diff --git a/AUTHORS b/AUTHORS
index a37220e8..2a5cc5e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -143,6 +143,7 @@
 Arunoday Sarkar <a.sarkar.arun@gmail.com>
 Arunprasad Rajkumar <ararunprasad@gmail.com>
 Arunprasad Rajkumar <arurajku@cisco.com>
+Arup Barua <arup.barua@samsung.com>
 Asami Doi <d0iasm.pub@gmail.com>
 Ashish Kumar Gupta <guptaag@amazon.com>
 Ashlin Joseph <ashlin.j@samsung.com>
diff --git a/DEPS b/DEPS
index ae9d463..67592e2 100644
--- a/DEPS
+++ b/DEPS
@@ -306,7 +306,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '02e2101a75f707c6a5e3f1133c3b8bf7012da5ab',
+  'skia_revision': 'cfb6de45f39b6d98b60748c7a1581065020cad9d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -385,7 +385,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': '7803e937d72d239e2e1e348f41005e179d3ab846',
+  'devtools_frontend_revision': '1aa5347ad5a44acc32633c154495d79f59c5f049',
   # 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.
@@ -421,7 +421,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': '01bd3aa73e60dd8b7d532580866f6e8b26b37b50',
+  'dawn_revision': 'acce83d10975dd9c6ef0137ba11198a22754034a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -445,7 +445,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling nearby
   # and whatever else without interference from each other.
-  'nearby_revision': '7a918e83105a1ed6b7acb5c0611518b4f3a701cf',
+  'nearby_revision': 'beb67fc02a5b9fbbd5ff550acb80277d8b52be92',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling securemessage
   # and whatever else without interference from each other.
@@ -816,7 +816,7 @@
 
   'src/clank': {
     'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' +
-    '7ab14e934be961308b768df110a3df4b0935a623',
+    '097dbd407dac07c04d49b2c2183ba57230e96f05',
     'condition': 'checkout_android and checkout_src_internal and not checkout_clank_via_src_internal',
   },
 
@@ -840,7 +840,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'f82ebee598c83d0e946669c15df5d17d07f353f4',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'c68dc7872c5ad24db9677759b71a22d8ea2d7ced',
       'condition': 'checkout_ios',
   },
 
@@ -1249,7 +1249,7 @@
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'ae30d7f9d66b229aca7f4fcef7fa875edeb1bbad',
+      'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '69a59b11fca4255301ea9f1af114ceeb8594bc84',
     'condition': 'checkout_src_internal',
   },
 
@@ -1664,7 +1664,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '3692281b7c39cb1184f1b21447374ff4d0c09335',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '5048c2cc764a27143f7ad026ef61cca567be0d18',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1796,7 +1796,7 @@
     Var('chromium_git') + '/external/github.com/GoogleChromeLabs/text-fragments-polyfill.git' + '@' + 'c036420683f672d685e27415de0a5f5e85bdc23f',
 
   'src/third_party/tflite/src':
-    Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '11eaf0880146cdd6af17b38fb1361dd031ee0f8c',
+    Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '1596f8978aa6e91bf0204b9e55ac4f99ea9374df',
 
   'src/third_party/turbine': {
       'packages': [
@@ -1846,7 +1846,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'd1b65aa5a88f6efd900604dfcda840154e9f16e2',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'd7e8d005dd88bbe5445ec42f30cdafca55982fae',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '8c74caae35d253e20d294ed1c3d035726282587b',
 
   'src/third_party/webrtc':
     Var('webrtc_git') + '/src.git' + '@' + '12046bf8c4159584ff78d8e15023cf4bac28b256',
@@ -1919,7 +1919,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@517446dbd8f0a8ebb4eb4030ad2b183d9e81d35f',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@6acb9e57b8b550ec065154c5e0ac6017e3e9e7ec',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 9637078..f1bf8cc 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1851,6 +1851,8 @@
     "system/unified/quick_settings_header.h",
     "system/unified/quick_settings_metrics_util.cc",
     "system/unified/quick_settings_metrics_util.h",
+    "system/unified/quick_settings_slider.cc",
+    "system/unified/quick_settings_slider.h",
     "system/unified/quick_settings_view.cc",
     "system/unified/quick_settings_view.h",
     "system/unified/quiet_mode_feature_pod_controller.cc",
@@ -3418,6 +3420,7 @@
     "shelf/login_shelf_view_pixeltest.cc",
     "shelf/scrollable_shelf_view_pixeltest.cc",
     "system/accessibility/accessibility_detailed_view_pixeltest.cc",
+    "system/bluetooth/bluetooth_detailed_view_legacy_pixeltest.cc",
     "test/pixel/demo_ash_pixel_diff_test.cc",
   ]
 
@@ -3429,6 +3432,7 @@
     "//ash/app_list:test_support",
     "//ash/public/cpp",
     "//base/test:test_support",
+    "//chromeos/ash/services/bluetooth_config:test_support",
     "//chromeos/dbus/power:power",
     "//chromeos/dbus/power:power_manager_proto",
     "//components/viz/test:test_support",
diff --git a/ash/capture_mode/capture_mode_feature_pod_controller.cc b/ash/capture_mode/capture_mode_feature_pod_controller.cc
index b59efe22..f9882aa 100644
--- a/ash/capture_mode/capture_mode_feature_pod_controller.cc
+++ b/ash/capture_mode/capture_mode_feature_pod_controller.cc
@@ -13,6 +13,7 @@
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/unified/feature_pod_button.h"
 #include "ash/system/unified/feature_pod_controller_base.h"
+#include "ash/system/unified/quick_settings_metrics_util.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -33,8 +34,13 @@
   button_->SetLabel(label_text);
   button_->icon_button()->SetTooltipText(label_text);
   button_->SetLabelTooltip(label_text);
-  button_->SetVisible(
-      !Shell::Get()->session_controller()->IsUserSessionBlocked());
+  const bool visible =
+      !Shell::Get()->session_controller()->IsUserSessionBlocked();
+  button_->SetVisible(visible);
+
+  if (visible)
+    TrackVisibilityUMA();
+
   button_->DisableLabelButtonFocus();
   return button_;
 }
diff --git a/ash/components/arc/session/arc_vm_client_adapter.cc b/ash/components/arc/session/arc_vm_client_adapter.cc
index 71a3e5f..873fb42e 100644
--- a/ash/components/arc/session/arc_vm_client_adapter.cc
+++ b/ash/components/arc/session/arc_vm_client_adapter.cc
@@ -86,14 +86,6 @@
 constexpr const char kArcVmBootNotificationServerSocketPath[] =
     "/run/arcvm_boot_notification_server/host.socket";
 
-constexpr base::TimeDelta kArcBugReportBackupTimeMetricMinTime =
-    base::Milliseconds(1);
-constexpr base::TimeDelta kArcBugReportBackupTimeMetricMaxTime =
-    base::Seconds(60);
-constexpr int kArcBugReportBackupTimeMetricBuckets = 50;
-constexpr const char kArcBugReportBackupTimeMetric[] =
-    "Login.ArcBugReportBackupTime";
-
 constexpr int kLogdConfigSizeSmall = 256;   // kBytes
 constexpr int kLogdConfigSizeMed = 512;     // kBytes
 constexpr int kLogdConfigSizeLarge = 1024;  // kBytes
@@ -866,7 +858,7 @@
       GetDebugDaemonClient()->BackupArcBugReport(
           cryptohome::CreateAccountIdentifierFromIdentification(cryptohome_id_),
           base::BindOnce(&ArcVmClientAdapter::OnArcBugReportBackedUp,
-                         weak_factory_.GetWeakPtr(), base::TimeTicks::Now()));
+                         weak_factory_.GetWeakPtr()));
     } else {
       StopArcInstanceInternal();
     }
@@ -947,16 +939,8 @@
   }
 
  private:
-  void OnArcBugReportBackedUp(base::TimeTicks arc_bug_report_backup_time,
-                              bool result) {
-    if (result) {
-      base::TimeDelta elapsed_time =
-          base::TimeTicks::Now() - arc_bug_report_backup_time;
-      base::UmaHistogramCustomTimes(kArcBugReportBackupTimeMetric, elapsed_time,
-                                    kArcBugReportBackupTimeMetricMinTime,
-                                    kArcBugReportBackupTimeMetricMaxTime,
-                                    kArcBugReportBackupTimeMetricBuckets);
-    } else {
+  void OnArcBugReportBackedUp(bool result) {
+    if (!result) {
       LOG(ERROR) << "Error contacting debugd to back up ARC bug report.";
     }
 
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 8718acc4b..f6d3ef5 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -77,6 +77,12 @@
              "ChromeOSAmbientMode",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
+// Allows Cryptohome to migrate existing VaultKeysets to AuthFactors and
+// UserSecretStash.
+BASE_FEATURE(kMigrateToUserSecretStash,
+             "MigrateToUserSecretStash",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 constexpr base::FeatureParam<bool> kAmbientModeCapturedOnPixelAlbumEnabled{
     &kAmbientModeFeature, "CapturedOnPixelAlbumEnabled", false};
 
@@ -582,7 +588,7 @@
 // Enables diacritics on longpress on the physical keyboard.
 BASE_FEATURE(kDiacriticsOnPhysicalKeyboardLongpress,
              "DiacriticsOnPhysicalKeyboardLongpress",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 // Disables the CryptAuth v1 DeviceSync flow. Note: During the first phase
 // of the v2 DeviceSync rollout, v1 and v2 DeviceSync run in parallel. This flag
@@ -2243,6 +2249,10 @@
   return base::FeatureList::IsEnabled(kEnable16Desks);
 }
 
+bool IsMigrateToUserSecretStashEnabled() {
+  return base::FeatureList::IsEnabled(kMigrateToUserSecretStash);
+}
+
 bool IsAdaptiveChargingEnabled() {
   return base::FeatureList::IsEnabled(kAdaptiveCharging);
 }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index ae00bbe..8848798 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -402,6 +402,8 @@
 BASE_DECLARE_FEATURE(kEducationEnrollmentOobeFlow);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kMicMuteNotifications);
 COMPONENT_EXPORT(ASH_CONSTANTS)
+BASE_DECLARE_FEATURE(kMigrateToUserSecretStash);
+COMPONENT_EXPORT(ASH_CONSTANTS)
 BASE_DECLARE_FEATURE(kDisableMessagesCrossDeviceIntegration);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kMinimumChromeVersion);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kMojoDBusRelay);
@@ -750,6 +752,7 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsMacAddressRandomizationEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsManagedTermsOfServiceEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsMicMuteNotificationsEnabled();
+COMPONENT_EXPORT(ASH_CONSTANTS) bool IsMigrateToUserSecretStashEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsMinimumChromeVersionEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsNearbyKeepAliveFixEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsNetworkingInDiagnosticsAppEnabled();
diff --git a/ash/ime/ime_controller_impl.cc b/ash/ime/ime_controller_impl.cc
index f092374..76e84e67 100644
--- a/ash/ime/ime_controller_impl.cc
+++ b/ash/ime/ime_controller_impl.cc
@@ -62,21 +62,7 @@
 }
 
 void ImeControllerImpl::SetClient(ImeControllerClient* client) {
-  if (client_) {
-    if (CastConfigController::Get())
-      CastConfigController::Get()->RemoveObserver(this);
-    Shell::Get()->display_manager()->RemoveObserver(this);
-    Shell::Get()->system_tray_notifier()->RemoveScreenCaptureObserver(this);
-  }
-
   client_ = client;
-
-  if (client_) {
-    if (CastConfigController::Get())
-      CastConfigController::Get()->AddObserver(this);
-    Shell::Get()->system_tray_notifier()->AddScreenCaptureObserver(this);
-    Shell::Get()->display_manager()->AddObserver(this);
-  }
 }
 
 bool ImeControllerImpl::CanSwitchIme() const {
@@ -218,28 +204,6 @@
   mi_view->ShowAndFadeOut();
 }
 
-void ImeControllerImpl::OnDisplayMetricsChanged(const display::Display& display,
-                                                uint32_t changed_metrics) {
-  if (changed_metrics & display::DisplayObserver::DISPLAY_METRIC_MIRROR_STATE) {
-    Shell* shell = Shell::Get();
-    client_->UpdateMirroringState(shell->display_manager()->IsInMirrorMode());
-  }
-}
-
-void ImeControllerImpl::OnDevicesUpdated(
-    const std::vector<SinkAndRoute>& devices) {
-  DCHECK(client_);
-
-  bool casting_desktop = false;
-  for (const auto& receiver : devices) {
-    if (receiver.route.content_source == ContentSource::kDesktop) {
-      casting_desktop = true;
-      break;
-    }
-  }
-  client_->UpdateCastingState(casting_desktop);
-}
-
 void ImeControllerImpl::SetCapsLockEnabled(bool caps_enabled) {
   is_caps_lock_enabled_ = caps_enabled;
 
@@ -300,15 +264,4 @@
   return candidate_ids;
 }
 
-void ImeControllerImpl::OnScreenCaptureStart(
-    base::OnceClosure stop_callback,
-    const base::RepeatingClosure& source_callback,
-    const std::u16string& screen_capture_status) {
-  client_->UpdateCastingState(true);
-}
-
-void ImeControllerImpl::OnScreenCaptureStop() {
-  client_->UpdateCastingState(false);
-}
-
 }  // namespace ash
diff --git a/ash/ime/ime_controller_impl.h b/ash/ime/ime_controller_impl.h
index 2f9c80e..e2cbd7c 100644
--- a/ash/ime/ime_controller_impl.h
+++ b/ash/ime/ime_controller_impl.h
@@ -9,18 +9,15 @@
 #include <vector>
 
 #include "ash/ash_export.h"
-#include "ash/public/cpp/cast_config_controller.h"
 #include "ash/public/cpp/ime_controller.h"
 #include "ash/public/cpp/ime_controller_client.h"
 #include "ash/public/cpp/ime_info.h"
-#include "ash/system/privacy/screen_capture_observer.h"
 #include "base/observer_list.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "ui/base/ime/ash/ime_keyset.h"
-#include "ui/display/display_observer.h"
 
 namespace ui {
 class Accelerator;
@@ -32,10 +29,7 @@
 
 // Connects ash IME users (e.g. the system tray) to the IME implementation,
 // which might live in Chrome browser or in a separate mojo service.
-class ASH_EXPORT ImeControllerImpl : public ImeController,
-                                     public display::DisplayObserver,
-                                     public CastConfigController::Observer,
-                                     public ScreenCaptureObserver {
+class ASH_EXPORT ImeControllerImpl : public ImeController {
  public:
   class Observer {
    public:
@@ -118,20 +112,6 @@
   void ShowModeIndicator(const gfx::Rect& anchor_bounds,
                          const std::u16string& ime_short_name) override;
 
-  // display::DisplayObserver:
-  void OnDisplayMetricsChanged(const display::Display& display,
-                               uint32_t changed_metrics) override;
-
-  // CastConfigController::Observer:
-  void OnDevicesUpdated(const std::vector<SinkAndRoute>& devices) override;
-
-  // ScreenCaptureObserver:
-  void OnScreenCaptureStart(
-      base::OnceClosure stop_callback,
-      const base::RepeatingClosure& source_callback,
-      const std::u16string& screen_capture_status) override;
-  void OnScreenCaptureStop() override;
-
   // Synchronously returns the cached caps lock state.
   bool IsCapsLockEnabled() const;
 
diff --git a/ash/ime/ime_controller_impl_unittest.cc b/ash/ime/ime_controller_impl_unittest.cc
index 78f3533d..71496fd 100644
--- a/ash/ime/ime_controller_impl_unittest.cc
+++ b/ash/ime/ime_controller_impl_unittest.cc
@@ -369,39 +369,5 @@
   EXPECT_LT(bounds3.bottom(), screen_bounds.bottom());
 }
 
-TEST_F(ImeControllerImplTest, MirroringChanged) {
-  UpdateDisplay("600x500,600x500");
-  // The controller is already an observer of the display_manager
-  ImeControllerImpl* controller = Shell::Get()->ime_controller();
-  TestImeControllerClient client;
-  controller->SetClient(&client);
-
-  display::DisplayManager* display_manager = Shell::Get()->display_manager();
-  display_manager->SetMultiDisplayMode(display::DisplayManager::MIRRORING);
-  display_manager->UpdateDisplays();
-  EXPECT_TRUE(client.is_mirroring_);
-
-  UpdateDisplay("600x500");
-  EXPECT_FALSE(client.is_mirroring_);
-
-  UpdateDisplay("600x500,600x500");
-  EXPECT_TRUE(client.is_mirroring_);
-}
-
-TEST_F(ImeControllerImplTest, MeetMirroringChanged) {
-  ImeControllerImpl* controller = Shell::Get()->ime_controller();
-  TestImeControllerClient client;
-  controller->SetClient(&client);
-
-  EXPECT_FALSE(client.is_casting_);
-
-  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStart(
-      base::DoNothing(), base::DoNothing(), u"");
-  EXPECT_TRUE(client.is_casting_);
-
-  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStop();
-  EXPECT_FALSE(client.is_casting_);
-}
-
 }  // namespace
 }  // namespace ash
diff --git a/ash/ime/test_ime_controller_client.cc b/ash/ime/test_ime_controller_client.cc
index 8d59e37b..552d32a 100644
--- a/ash/ime/test_ime_controller_client.cc
+++ b/ash/ime/test_ime_controller_client.cc
@@ -42,14 +42,6 @@
   std::move(callback).Run();
 }
 
-void TestImeControllerClient::UpdateMirroringState(bool enabled) {
-  is_mirroring_ = enabled;
-}
-
-void TestImeControllerClient::UpdateCastingState(bool enabled) {
-  is_casting_ = enabled;
-}
-
 void TestImeControllerClient::ShowModeIndicator() {
   ++show_mode_indicator_count_;
 }
diff --git a/ash/ime/test_ime_controller_client.h b/ash/ime/test_ime_controller_client.h
index 7e0cb32..9599db6 100644
--- a/ash/ime/test_ime_controller_client.h
+++ b/ash/ime/test_ime_controller_client.h
@@ -26,8 +26,6 @@
   void SetCapsLockEnabled(bool enabled) override;
   void OverrideKeyboardKeyset(input_method::ImeKeyset keyset,
                               OverrideKeyboardKeysetCallback callback) override;
-  void UpdateMirroringState(bool enabled) override;
-  void UpdateCastingState(bool enabled) override;
   void ShowModeIndicator() override;
 
   int next_ime_count_ = 0;
@@ -37,8 +35,6 @@
   std::string last_switch_ime_id_;
   bool last_show_message_ = false;
   input_method::ImeKeyset last_keyset_ = input_method::ImeKeyset::kNone;
-  bool is_mirroring_ = false;
-  bool is_casting_ = false;
   int show_mode_indicator_count_ = 0;
 };
 
diff --git a/ash/public/cpp/ime_controller_client.h b/ash/public/cpp/ime_controller_client.h
index 1e1ec0d..bc3ee72 100644
--- a/ash/public/cpp/ime_controller_client.h
+++ b/ash/public/cpp/ime_controller_client.h
@@ -44,14 +44,6 @@
   // caps lock.
   virtual void SetCapsLockEnabled(bool enabled) = 0;
 
-  // Notifies the mirroring state change to the client where IME lives (e.g.
-  // Chrome), so that the IME can behave according to the state.
-  virtual void UpdateMirroringState(bool enabled) = 0;
-
-  // Notifies the casting state change to the client where IME lives (e.g.
-  // Chrome), so that the IME can behave according to the state.
-  virtual void UpdateCastingState(bool enabled) = 0;
-
   // Overrides the keyboard keyset (emoji, handwriting or voice). If keyset is
   // 'kNone', we switch to the default keyset. Because this is asynchronous,
   // any code that needs the keyset to be updated first must use the callback.
diff --git a/ash/shelf/shelf_party_feature_pod_controller.cc b/ash/shelf/shelf_party_feature_pod_controller.cc
index 14ab46b..95ea99a3 100644
--- a/ash/shelf/shelf_party_feature_pod_controller.cc
+++ b/ash/shelf/shelf_party_feature_pod_controller.cc
@@ -12,6 +12,7 @@
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/unified/feature_pod_button.h"
+#include "ash/system/unified/quick_settings_metrics_util.h"
 #include "components/session_manager/session_manager_types.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -31,6 +32,10 @@
   button_->SetVectorIcon(kShelfPartyIcon);
   button_->SetLabel(
       l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SHELF_PARTY_LABEL));
+
+  // Init the button with invisible state. The `UpdateButton` method will update
+  // the visibility based on the current condition.
+  button_->SetVisible(false);
   UpdateButton();
   Shell::Get()->session_controller()->AddObserver(this);
   Shell::Get()->shelf_controller()->model()->AddObserver(this);
@@ -62,9 +67,16 @@
   DCHECK(button_);
   const SessionControllerImpl* session_controller =
       Shell::Get()->session_controller();
-  button_->SetVisible(session_controller->GetSessionState() ==
-                          session_manager::SessionState::ACTIVE &&
-                      !session_controller->IsEnterpriseManaged());
+
+  const bool visible = session_controller->GetSessionState() ==
+                           session_manager::SessionState::ACTIVE &&
+                       !session_controller->IsEnterpriseManaged();
+  // If the button's visibility changes from invisible to visible, log its
+  // visibility.
+  if (!button_->GetVisible() && visible)
+    TrackVisibilityUMA();
+  button_->SetVisible(visible);
+
   const bool toggled =
       Shell::Get()->shelf_controller()->model()->in_shelf_party();
   button_->SetToggled(toggled);
diff --git a/ash/system/accessibility/accessibility_feature_pod_controller.cc b/ash/system/accessibility/accessibility_feature_pod_controller.cc
index a110fb5..0d277ff2 100644
--- a/ash/system/accessibility/accessibility_feature_pod_controller.cc
+++ b/ash/system/accessibility/accessibility_feature_pod_controller.cc
@@ -12,6 +12,7 @@
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/unified/feature_pod_button.h"
+#include "ash/system/unified/quick_settings_metrics_util.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -37,9 +38,13 @@
 
   AccessibilityDelegate* delegate = Shell::Get()->accessibility_delegate();
   LoginStatus login_status = Shell::Get()->session_controller()->login_status();
-  button->SetVisible(login_status == LoginStatus::NOT_LOGGED_IN ||
-                     login_status == LoginStatus::LOCKED ||
-                     delegate->ShouldShowAccessibilityMenu());
+  const bool visible = login_status == LoginStatus::NOT_LOGGED_IN ||
+                       login_status == LoginStatus::LOCKED ||
+                       delegate->ShouldShowAccessibilityMenu();
+  button->SetVisible(visible);
+  if (visible)
+    TrackVisibilityUMA();
+
   return button;
 }
 
diff --git a/ash/system/bluetooth/bluetooth_detailed_view_legacy_pixeltest.cc b/ash/system/bluetooth/bluetooth_detailed_view_legacy_pixeltest.cc
new file mode 100644
index 0000000..33ca8d1
--- /dev/null
+++ b/ash/system/bluetooth/bluetooth_detailed_view_legacy_pixeltest.cc
@@ -0,0 +1,99 @@
+// 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 <string>
+
+#include "ash/constants/ash_features.h"
+#include "ash/system/unified/unified_system_tray.h"
+#include "ash/system/unified/unified_system_tray_bubble.h"
+#include "ash/system/unified/unified_system_tray_controller.h"
+#include "ash/system/unified/unified_system_tray_view.h"
+#include "ash/test/ash_test_base.h"
+#include "ash/test/ash_test_helper.h"
+#include "ash/test/pixel/ash_pixel_differ.h"
+#include "ash/test/pixel/ash_pixel_test_init_params.h"
+#include "base/test/scoped_feature_list.h"
+#include "chromeos/ash/services/bluetooth_config/fake_device_cache.h"
+#include "chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom.h"
+#include "chromeos/ash/services/bluetooth_config/scoped_bluetooth_config_test_helper.h"
+
+namespace ash {
+namespace {
+
+using bluetooth_config::ScopedBluetoothConfigTestHelper;
+using bluetooth_config::mojom::BluetoothDeviceProperties;
+using bluetooth_config::mojom::DeviceConnectionState;
+using bluetooth_config::mojom::PairedBluetoothDeviceProperties;
+using bluetooth_config::mojom::PairedBluetoothDevicePropertiesPtr;
+
+// Creates a paired Bluetooth device.
+PairedBluetoothDevicePropertiesPtr CreatePairedDevice(
+    DeviceConnectionState connection_state,
+    const std::u16string& public_name) {
+  PairedBluetoothDevicePropertiesPtr paired_properties =
+      PairedBluetoothDeviceProperties::New();
+  paired_properties->device_properties = BluetoothDeviceProperties::New();
+  paired_properties->device_properties->connection_state = connection_state;
+  paired_properties->device_properties->public_name = public_name;
+  return paired_properties;
+}
+
+}  // namespace
+
+// Pixel tests for the quick settings Bluetooth detailed view.
+class BluetoothDetailedViewLegacyPixelTest : public AshTestBase {
+ public:
+  BluetoothDetailedViewLegacyPixelTest() {
+    feature_list_.InitWithFeatures(
+        /*enabled_features=*/{},
+        /*disabled_features=*/{features::kQsRevamp, features::kQsRevampWip});
+  }
+
+  // AshTestBase:
+  absl::optional<pixel_test::InitParams> CreatePixelTestInitParams()
+      const override {
+    return pixel_test::InitParams();
+  }
+
+  // Sets the list of paired devices in the device cache.
+  void SetPairedDevices(
+      std::vector<PairedBluetoothDevicePropertiesPtr> paired_devices) {
+    ash_test_helper()
+        ->bluetooth_config_test_helper()
+        ->fake_device_cache()
+        ->SetPairedDevices(std::move(paired_devices));
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+TEST_F(BluetoothDetailedViewLegacyPixelTest, Basics) {
+  // Create test devices.
+  std::vector<PairedBluetoothDevicePropertiesPtr> paired_devices;
+  paired_devices.push_back(
+      CreatePairedDevice(DeviceConnectionState::kConnected, u"Keyboard"));
+  paired_devices.push_back(
+      CreatePairedDevice(DeviceConnectionState::kNotConnected, u"Mouse"));
+  SetPairedDevices(std::move(paired_devices));
+
+  // Show the system tray bubble.
+  UnifiedSystemTray* system_tray = GetPrimaryUnifiedSystemTray();
+  system_tray->ShowBubble();
+  ASSERT_TRUE(system_tray->bubble());
+
+  // Show the Bluetooth detailed view.
+  system_tray->bubble()
+      ->unified_system_tray_controller()
+      ->ShowBluetoothDetailedView();
+  views::View* detailed_view =
+      system_tray->bubble()->unified_view()->detailed_view();
+  ASSERT_TRUE(detailed_view);
+
+  // Compare pixels.
+  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
+      "bluetooth_detailed_view_legacy.rev_0", detailed_view));
+}
+
+}  // namespace ash
diff --git a/ash/system/bluetooth/bluetooth_feature_pod_controller.cc b/ash/system/bluetooth/bluetooth_feature_pod_controller.cc
index caae4680..48f0c15 100644
--- a/ash/system/bluetooth/bluetooth_feature_pod_controller.cc
+++ b/ash/system/bluetooth/bluetooth_feature_pod_controller.cc
@@ -9,6 +9,7 @@
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/unified/feature_pod_button.h"
+#include "ash/system/unified/quick_settings_metrics_util.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
 #include "base/check.h"
 #include "base/i18n/number_formatting.h"
@@ -40,6 +41,9 @@
   DCHECK(!button_);
   button_ = new FeaturePodButton(this);
   button_->ShowDetailedViewArrow();
+  // Init the button with invisible state. The `UpdateButtonStateIfExists`
+  // method will update the visibility based on the current condition.
+  button_->SetVisible(false);
   UpdateButtonStateIfExists();
   return button_;
 }
@@ -195,12 +199,16 @@
     return;
   }
 
+  // If the button's visibility changes from invisible to visible, log its
+  // visibility.
+  if (!button_->GetVisible())
+    TrackVisibilityUMA();
+
   button_->SetEnabled(modification_state_ ==
                       BluetoothModificationState::kCanModifyBluetooth);
   button_->SetToggled(
       bluetooth_config::IsBluetoothEnabledOrEnabling(system_state_));
   button_->SetVisible(true);
-
   button_->SetVectorIcon(ComputeButtonIcon());
   button_->SetLabel(ComputeButtonLabel());
   button_->SetSubLabel(ComputeButtonSubLabel());
diff --git a/ash/system/camera/autozoom_feature_pod_controller.cc b/ash/system/camera/autozoom_feature_pod_controller.cc
index 3e1a27a..8dc67d5c 100644
--- a/ash/system/camera/autozoom_feature_pod_controller.cc
+++ b/ash/system/camera/autozoom_feature_pod_controller.cc
@@ -11,6 +11,7 @@
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/camera/autozoom_controller_impl.h"
 #include "ash/system/unified/feature_pod_button.h"
+#include "ash/system/unified/quick_settings_metrics_util.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/accessibility/view_accessibility.h"
 
@@ -37,6 +38,9 @@
       description);
   button_->label_button()->GetViewAccessibility().OverrideDescription(
       description);
+  // Init the button with invisible state. The `UpdateButton` method will update
+  // the visibility based on the current condition.
+  button_->SetVisible(false);
   UpdateButton(Shell::Get()->autozoom_controller()->GetState());
   return button_;
 }
@@ -56,9 +60,14 @@
   if (!button_)
     return;
 
-  button_->SetVisible(
+  const bool visible =
       Shell::Get()->autozoom_controller()->IsAutozoomControlEnabled() &&
-      Shell::Get()->session_controller()->ShouldEnableSettings());
+      Shell::Get()->session_controller()->ShouldEnableSettings();
+
+  if (!button_->GetVisible() && visible)
+    TrackVisibilityUMA();
+
+  button_->SetVisible(visible);
 }
 
 void AutozoomFeaturePodController::OnAutozoomStateChanged(
diff --git a/ash/system/cast/cast_feature_pod_controller.cc b/ash/system/cast/cast_feature_pod_controller.cc
index 7429a01..b924bba 100644
--- a/ash/system/cast/cast_feature_pod_controller.cc
+++ b/ash/system/cast/cast_feature_pod_controller.cc
@@ -12,6 +12,7 @@
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/model/system_tray_model.h"
 #include "ash/system/unified/feature_pod_button.h"
+#include "ash/system/unified/quick_settings_metrics_util.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
 #include "components/access_code_cast/common/access_code_cast_metrics.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -41,7 +42,9 @@
     CastConfigController::Get()->AddObserver(this);
     CastConfigController::Get()->RequestDeviceRefresh();
   }
-
+  // Init the button with invisible state. The `Update` method will update the
+  // visibility based on the current condition.
+  button_->SetVisible(false);
   Update();
   return button_;
 }
@@ -84,11 +87,14 @@
   auto* cast_config = CastConfigController::Get();
   // The cast feature tile will always be shown on the QS bubble if the revamped
   // view is enabled.
-  button_->SetVisible(features::IsQsRevampEnabled() ||
-                      (cast_config &&
-                       (cast_config->HasSinksAndRoutes() ||
-                        cast_config->AccessCodeCastingEnabled()) &&
-                       !cast_config->HasActiveRoute()));
+  const bool visible = features::IsQsRevampEnabled() ||
+                       (cast_config &&
+                        (cast_config->HasSinksAndRoutes() ||
+                         cast_config->AccessCodeCastingEnabled()) &&
+                        !cast_config->HasActiveRoute());
+  if (!button_->GetVisible() && visible)
+    TrackVisibilityUMA();
+  button_->SetVisible(visible);
 }
 
 }  // namespace ash
diff --git a/ash/system/dark_mode/dark_mode_feature_pod_controller.cc b/ash/system/dark_mode/dark_mode_feature_pod_controller.cc
index b4f349f..840c5be 100644
--- a/ash/system/dark_mode/dark_mode_feature_pod_controller.cc
+++ b/ash/system/dark_mode/dark_mode_feature_pod_controller.cc
@@ -14,6 +14,7 @@
 #include "ash/system/model/system_tray_model.h"
 #include "ash/system/tray/tray_popup_utils.h"
 #include "ash/system/unified/feature_pod_button.h"
+#include "ash/system/unified/quick_settings_metrics_util.h"
 #include "base/metrics/histogram_functions.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -40,10 +41,13 @@
   // TODO(minch): Add the logic for login screen.
   // Disable dark mode feature pod in OOBE since only light mode should be
   // allowed there.
-  button_->SetVisible(
+  const bool visible =
       Shell::Get()->session_controller()->IsActiveUserSessionStarted() &&
       Shell::Get()->session_controller()->GetSessionState() !=
-          session_manager::SessionState::OOBE);
+          session_manager::SessionState::OOBE;
+  if (visible)
+    TrackVisibilityUMA();
+  button_->SetVisible(visible);
 
   UpdateButton(DarkLightModeControllerImpl::Get()->IsDarkModeEnabled());
   return button_;
diff --git a/ash/system/ime/ime_feature_pod_controller.cc b/ash/system/ime/ime_feature_pod_controller.cc
index 1519bb1..635b09b6 100644
--- a/ash/system/ime/ime_feature_pod_controller.cc
+++ b/ash/system/ime/ime_feature_pod_controller.cc
@@ -12,6 +12,7 @@
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/tray/system_tray_notifier.h"
 #include "ash/system/unified/feature_pod_button.h"
+#include "ash/system/unified/quick_settings_metrics_util.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -71,6 +72,9 @@
   button_->SetIconAndLabelTooltips(GetTooltipString());
   button_->ShowDetailedViewArrow();
   button_->DisableLabelButtonFocus();
+  // Init the button with invisible state. The `Update` method will update the
+  // visibility based on the current condition.
+  button_->SetVisible(false);
   Update();
   return button_;
 }
@@ -94,6 +98,10 @@
 
 void IMEFeaturePodController::Update() {
   button_->SetSubLabel(GetLabelString());
+  // If the button's visibility changes from invisible to visible, log its
+  // visibility.
+  if (!button_->GetVisible() && IsButtonVisible())
+    TrackVisibilityUMA();
   button_->SetVisible(IsButtonVisible());
 }
 
diff --git a/ash/system/locale/locale_feature_pod_controller.cc b/ash/system/locale/locale_feature_pod_controller.cc
index 1c5c7ffd..cd02aebc 100644
--- a/ash/system/locale/locale_feature_pod_controller.cc
+++ b/ash/system/locale/locale_feature_pod_controller.cc
@@ -11,6 +11,7 @@
 #include "ash/system/model/locale_model.h"
 #include "ash/system/model/system_tray_model.h"
 #include "ash/system/unified/feature_pod_button.h"
+#include "ash/system/unified/quick_settings_metrics_util.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
 #include "base/i18n/case_conversion.h"
 #include "base/strings/utf_string_conversions.h"
@@ -29,6 +30,9 @@
   const bool visible =
       !Shell::Get()->system_tray_model()->locale()->locale_list().empty();
   button->SetVisible(visible);
+  if (visible)
+    TrackVisibilityUMA();
+
   if (visible) {
     button->SetVectorIcon(kUnifiedMenuLocaleIcon);
     button->SetIconAndLabelTooltips(
diff --git a/ash/system/message_center/notification_grouping_controller_unittest.cc b/ash/system/message_center/notification_grouping_controller_unittest.cc
index a667832e..ffea459 100644
--- a/ash/system/message_center/notification_grouping_controller_unittest.cc
+++ b/ash/system/message_center/notification_grouping_controller_unittest.cc
@@ -461,4 +461,23 @@
   EXPECT_FALSE(message_center->FindNotificationById(id)->group_child());
 }
 
+TEST_F(NotificationGroupingControllerTest, ChildNotificationUpdate) {
+  auto* message_center = MessageCenter::Get();
+  std::string id0, id1, id2;
+  const GURL url(u"http://test-url.com/");
+  id0 = AddNotificationWithOriginUrl(url);
+  id1 = AddNotificationWithOriginUrl(url);
+
+  EXPECT_TRUE(message_center->FindNotificationById(id0)->group_child());
+
+  // Update the notification.
+  auto notification = MakeNotification(id2, url);
+  auto updated_notification =
+      std::make_unique<Notification>(id0, *notification.get());
+  message_center->UpdateNotification(id0, std::move(updated_notification));
+
+  // Make sure the updated notification is still a group child.
+  EXPECT_TRUE(message_center->FindNotificationById(id0)->group_child());
+}
+
 }  // namespace ash
diff --git a/ash/system/nearby_share/nearby_share_feature_pod_controller.cc b/ash/system/nearby_share/nearby_share_feature_pod_controller.cc
index 695222c..221122c4 100644
--- a/ash/system/nearby_share/nearby_share_feature_pod_controller.cc
+++ b/ash/system/nearby_share/nearby_share_feature_pod_controller.cc
@@ -12,6 +12,7 @@
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/model/system_tray_model.h"
 #include "ash/system/unified/feature_pod_button.h"
+#include "ash/system/unified/quick_settings_metrics_util.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
 #include "base/bind.h"
 #include "base/strings/string_number_conversions.h"
@@ -66,10 +67,14 @@
   button_ = new FeaturePodButton(this);
   SessionControllerImpl* session_controller =
       Shell::Get()->session_controller();
-  button_->SetVisible(nearby_share_delegate_->IsPodButtonVisible() &&
-                      session_controller->IsActiveUserSessionStarted() &&
-                      session_controller->IsUserPrimary() &&
-                      !session_controller->IsUserSessionBlocked());
+  const bool visible = nearby_share_delegate_->IsPodButtonVisible() &&
+                       session_controller->IsActiveUserSessionStarted() &&
+                       session_controller->IsUserPrimary() &&
+                       !session_controller->IsUserSessionBlocked();
+  button_->SetVisible(visible);
+  if (visible)
+    TrackVisibilityUMA();
+
   button_->SetLabel(
       l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NEARBY_SHARE_BUTTON_LABEL));
   button_->SetLabelTooltip(l10n_util::GetStringUTF16(
diff --git a/ash/system/network/network_feature_pod_controller.cc b/ash/system/network/network_feature_pod_controller.cc
index ace7ae4..df95630 100644
--- a/ash/system/network/network_feature_pod_controller.cc
+++ b/ash/system/network/network_feature_pod_controller.cc
@@ -179,6 +179,7 @@
   button_ = button.get();
   button_->ShowDetailedViewArrow();
   UpdateButtonStateIfExists();
+  TrackVisibilityUMA();
   return button.release();
 }
 
diff --git a/ash/system/network/network_feature_pod_controller_legacy.cc b/ash/system/network/network_feature_pod_controller_legacy.cc
index 4da4ffb..7152e8fe 100644
--- a/ash/system/network/network_feature_pod_controller_legacy.cc
+++ b/ash/system/network/network_feature_pod_controller_legacy.cc
@@ -63,6 +63,7 @@
   DCHECK(!button_);
   button_ = new NetworkFeaturePodButtonLegacy(this);
   UpdateButton();
+  TrackVisibilityUMA();
   return button_;
 }
 
diff --git a/ash/system/network/vpn_feature_pod_controller.cc b/ash/system/network/vpn_feature_pod_controller.cc
index 1cf81d4c..7ade1f4 100644
--- a/ash/system/network/vpn_feature_pod_controller.cc
+++ b/ash/system/network/vpn_feature_pod_controller.cc
@@ -15,6 +15,7 @@
 #include "ash/system/network/vpn_list.h"
 #include "ash/system/tray/tray_constants.h"
 #include "ash/system/unified/feature_pod_button.h"
+#include "ash/system/unified/quick_settings_metrics_util.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -62,6 +63,9 @@
       l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_VPN_TOOLTIP));
   button_->ShowDetailedViewArrow();
   button_->DisableLabelButtonFocus();
+  // Init the button with invisible state. The `Update` method will update the
+  // visibility based on the current condition.
+  button_->SetVisible(false);
   Update();
   return button_;
 }
@@ -80,6 +84,11 @@
 }
 
 void VPNFeaturePodController::Update() {
+  // If the button's visibility changes from invisible to visible, log its
+  // visibility.
+  if (!button_->GetVisible() && IsVPNVisibleInSystemTray())
+    TrackVisibilityUMA();
+
   button_->SetVisible(IsVPNVisibleInSystemTray());
   if (!button_->GetVisible())
     return;
diff --git a/ash/system/night_light/night_light_feature_pod_controller.cc b/ash/system/night_light/night_light_feature_pod_controller.cc
index 100b561..6de24b3 100644
--- a/ash/system/night_light/night_light_feature_pod_controller.cc
+++ b/ash/system/night_light/night_light_feature_pod_controller.cc
@@ -17,6 +17,7 @@
 #include "ash/system/night_light/night_light_controller_impl.h"
 #include "ash/system/tray/tray_popup_utils.h"
 #include "ash/system/unified/feature_pod_button.h"
+#include "ash/system/unified/quick_settings_metrics_util.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
 #include "base/i18n/time_formatting.h"
 #include "base/metrics/histogram_macros.h"
@@ -50,8 +51,12 @@
   DCHECK(!button_);
   button_ = new FeaturePodButton(this);
   button_->SetVectorIcon(kUnifiedMenuNightLightIcon);
-  button_->SetVisible(
-      Shell::Get()->session_controller()->ShouldEnableSettings());
+  const bool visible =
+      Shell::Get()->session_controller()->ShouldEnableSettings();
+  button_->SetVisible(visible);
+  if (visible)
+    TrackVisibilityUMA();
+
   button_->SetLabel(
       l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NIGHT_LIGHT_BUTTON_LABEL));
   button_->SetLabelTooltip(l10n_util::GetStringUTF16(
diff --git a/ash/system/privacy_screen/privacy_screen_feature_pod_controller.cc b/ash/system/privacy_screen/privacy_screen_feature_pod_controller.cc
index 3cafeb7..0c3fbb6 100644
--- a/ash/system/privacy_screen/privacy_screen_feature_pod_controller.cc
+++ b/ash/system/privacy_screen/privacy_screen_feature_pod_controller.cc
@@ -12,6 +12,7 @@
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/unified/feature_pod_button.h"
+#include "ash/system/unified/quick_settings_metrics_util.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/layout/box_layout.h"
 
@@ -28,6 +29,9 @@
 FeaturePodButton* PrivacyScreenFeaturePodController::CreateButton() {
   DCHECK(!button_);
   button_ = new FeaturePodButton(this);
+  // Init the button with invisible state. The `UpdateButton` method will update
+  // the visibility based on the current condition.
+  button_->SetVisible(false);
   UpdateButton();
   return button_;
 }
@@ -56,6 +60,11 @@
   auto* privacy_screen_controller = Shell::Get()->privacy_screen_controller();
 
   bool is_supported = privacy_screen_controller->IsSupported();
+  // If the button's visibility changes from invisible to visible, log its
+  // visibility.
+  if (!button_->GetVisible() && is_supported)
+    TrackVisibilityUMA();
+
   button_->SetVisible(is_supported);
   if (!is_supported)
     return;
diff --git a/ash/system/rotation/rotation_lock_feature_pod_controller.cc b/ash/system/rotation/rotation_lock_feature_pod_controller.cc
index 7b084aa..cf2cc56 100644
--- a/ash/system/rotation/rotation_lock_feature_pod_controller.cc
+++ b/ash/system/rotation/rotation_lock_feature_pod_controller.cc
@@ -9,6 +9,7 @@
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/unified/feature_pod_button.h"
+#include "ash/system/unified/quick_settings_metrics_util.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -31,6 +32,9 @@
   DCHECK(!button_);
   button_ = new FeaturePodButton(this);
   button_->DisableLabelButtonFocus();
+  // Init the button with invisible state. The `UpdateButton` method will update
+  // the visibility based on the current condition.
+  button_->SetVisible(false);
   UpdateButton();
   return button_;
 }
@@ -62,6 +66,10 @@
   // shown in the case.
   const bool is_auto_rotation_allowed =
       Shell::Get()->tablet_mode_controller()->is_in_tablet_physical_state();
+
+  if (!button_->GetVisible() && is_auto_rotation_allowed)
+    TrackVisibilityUMA();
+
   button_->SetVisible(is_auto_rotation_allowed);
 
   if (!is_auto_rotation_allowed)
diff --git a/ash/system/unified/feature_pod_controller_base.cc b/ash/system/unified/feature_pod_controller_base.cc
index 3c5ba25..5b42e78 100644
--- a/ash/system/unified/feature_pod_controller_base.cc
+++ b/ash/system/unified/feature_pod_controller_base.cc
@@ -21,4 +21,8 @@
   quick_settings_metrics_util::RecordQsFeatureDiveIn(GetCatalogName());
 }
 
+void FeaturePodControllerBase::TrackVisibilityUMA() {
+  quick_settings_metrics_util::RecordVisibleQsFeature(GetCatalogName());
+}
+
 }  // namespace ash
diff --git a/ash/system/unified/feature_pod_controller_base.h b/ash/system/unified/feature_pod_controller_base.h
index a7e95b6..6c12db08 100644
--- a/ash/system/unified/feature_pod_controller_base.h
+++ b/ash/system/unified/feature_pod_controller_base.h
@@ -50,6 +50,10 @@
   // Tracks the navigating to detailed page behavior, usually happens
   // `OnLabelPressed`, sometimes also happens `OnIconPressed`.
   void TrackDiveInUMA();
+
+  // Tracks the visibility of this feature pod. Call this method if the
+  // visibility is set from `false` to `true`.
+  void TrackVisibilityUMA();
 };
 
 }  // namespace ash
diff --git a/ash/system/unified/quick_settings_slider.cc b/ash/system/unified/quick_settings_slider.cc
new file mode 100644
index 0000000..6abe1a0
--- /dev/null
+++ b/ash/system/unified/quick_settings_slider.cc
@@ -0,0 +1,214 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/system/unified/quick_settings_slider.h"
+
+#include "ash/constants/ash_features.h"
+#include "ash/style/ash_color_provider.h"
+#include "ash/style/color_util.h"
+#include "base/notreached.h"
+#include "cc/paint/paint_flags.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/chromeos/styles/cros_tokens_color_mappings.h"
+#include "ui/color/color_id.h"
+#include "ui/color/color_provider.h"
+#include "ui/events/event.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/views/controls/slider.h"
+
+namespace ash {
+
+namespace {
+
+// The thickness of the empty slider.
+constexpr int kEmptySliderThickness = 4;
+
+// The thickness of the full slider.
+constexpr int kFullSliderThickness = 32;
+
+// The radius used to draw the rounded empty slider ends.
+constexpr float kEmptySliderRoundedRadius = 2.f;
+constexpr float kEmptySliderWidth = 2 * kEmptySliderRoundedRadius;
+
+// The radius used to draw the rounded full slider ends.
+constexpr float kFullSliderRoundedRadius = 16.f;
+constexpr float kFullSliderWidth = 2 * kFullSliderRoundedRadius;
+
+// The radius used to draw the rounded corner for active/inactive slider on the
+// audio subpage.
+constexpr float kActiveRadioSliderRoundedRadius = 16.f;
+// TODO(b/256705775): Replace the actual radius value once the spec is updated.
+constexpr float kInactiveRadioSliderRoundedRadius = 8.f;
+
+// TODO(b/256705775): Replace the value once the spec is updated.
+// The thickness of the focus ring border.
+constexpr int kLineThickness = 2;
+// The gap between the focus ring and the slider.
+constexpr int kFocusOffset = 2;
+
+float GetSliderRoundedCornerRadius(QuickSettingsSlider::Style slider_style) {
+  switch (slider_style) {
+    case QuickSettingsSlider::Style::kDefault:
+      return kFullSliderRoundedRadius;
+    case QuickSettingsSlider::Style::kRadioActive:
+      return kActiveRadioSliderRoundedRadius;
+    case QuickSettingsSlider::Style::kRadioInactive:
+      return kInactiveRadioSliderRoundedRadius;
+    default:
+      NOTREACHED();
+  }
+}
+
+}  // namespace
+
+QuickSettingsSlider::QuickSettingsSlider(views::SliderListener* listener,
+                                         Style slider_style)
+    : views::Slider(listener), slider_style_(slider_style) {
+  if (!features::IsQsRevampEnabled())
+    return;
+  SetValueIndicatorRadius(kFullSliderRoundedRadius);
+  SetFocusBehavior(FocusBehavior::ALWAYS);
+}
+
+QuickSettingsSlider::~QuickSettingsSlider() = default;
+
+void QuickSettingsSlider::SetSliderStyle(Style style) {
+  if (slider_style_ == style)
+    return;
+
+  slider_style_ = style;
+
+  if (slider_style_ == Style::kRadioInactive)
+    SetFocusBehavior(FocusBehavior::NEVER);
+
+  SchedulePaint();
+}
+
+SkColor QuickSettingsSlider::GetThumbColor() const {
+  // TODO(b/256705775): Updates the color when QsRevamp is disabled but Jelly is
+  // enabled.
+  if (!features::IsQsRevampEnabled()) {
+    using Type = AshColorProvider::ContentLayerType;
+    return AshColorProvider::Get()->GetContentLayerColor(
+        (style() == RenderingStyle::kMinimalStyle) ? Type::kSliderColorInactive
+                                                   : Type::kSliderColorActive);
+  }
+
+  switch (slider_style_) {
+    case Style::kDefault:
+    case Style::kRadioActive:
+      return GetColorProvider()->GetColor(static_cast<ui::ColorId>(
+          cros_tokens::kCrosSysSystemPrimaryContainer));
+    case Style::kRadioInactive:
+      return GetColorProvider()->GetColor(
+          static_cast<ui::ColorId>(cros_tokens::kCrosSysDisabled));
+    default:
+      NOTREACHED();
+  }
+}
+
+SkColor QuickSettingsSlider::GetTroughColor() const {
+  // TODO(b/256705775): Updates the color when QsRevamp is disabled but Jelly is
+  // enabled.
+  if (!features::IsQsRevampEnabled())
+    return ColorUtil::GetSecondToneColor(GetThumbColor());
+
+  switch (slider_style_) {
+    case Style::kDefault:
+      return GetColorProvider()->GetColor(
+          static_cast<ui::ColorId>(cros_tokens::kCrosSysSystemOnBase));
+    case Style::kRadioActive:
+      return GetColorProvider()->GetColor(
+          static_cast<ui::ColorId>(cros_tokens::kCrosSysHighlightShape));
+    case Style::kRadioInactive:
+      return GetColorProvider()->GetColor(
+          static_cast<ui::ColorId>(cros_tokens::kCrosSysDisabled));
+    default:
+      NOTREACHED();
+  }
+}
+
+void QuickSettingsSlider::OnPaint(gfx::Canvas* canvas) {
+  // Paints the `QuickSettingsSlider`. If the feature is not enabled, use
+  // `Slider::OnPaint()`.
+  if (!ash::features::IsQsRevampEnabled()) {
+    views::Slider::OnPaint(canvas);
+    return;
+  }
+
+  const gfx::Rect content = GetContentsBounds();
+  const int width = content.width() - kFullSliderWidth;
+  const int full_width = GetAnimatingValue() * width + kFullSliderWidth;
+  const int x = content.x();
+  const int y = content.height() / 2 - kFullSliderThickness / 2;
+
+  gfx::Rect empty_slider_rect;
+  float empty_slider_radius;
+  switch (slider_style_) {
+    case Style::kDefault: {
+      const int empty_width =
+          width + kFullSliderRoundedRadius - full_width + kEmptySliderWidth;
+      const int x_empty = x + full_width - kEmptySliderRoundedRadius;
+      const int y_empty = content.height() / 2 - kEmptySliderThickness / 2;
+
+      empty_slider_rect =
+          gfx::Rect(x_empty, y_empty, empty_width, kEmptySliderThickness);
+      empty_slider_radius = kEmptySliderRoundedRadius;
+      break;
+    }
+    case Style::kRadioActive:
+    case Style::kRadioInactive: {
+      empty_slider_rect =
+          gfx::Rect(x, y, content.width(), kFullSliderThickness);
+      empty_slider_radius = GetSliderRoundedCornerRadius(slider_style_);
+      break;
+    }
+    default:
+      NOTREACHED();
+  }
+
+  cc::PaintFlags slider_flags;
+  slider_flags.setAntiAlias(true);
+
+  slider_flags.setColor(GetTroughColor());
+  canvas->DrawRoundRect(empty_slider_rect, empty_slider_radius, slider_flags);
+
+  slider_flags.setColor(GetThumbColor());
+  canvas->DrawRoundRect(gfx::Rect(x, y, full_width, kFullSliderThickness),
+                        GetSliderRoundedCornerRadius(slider_style_),
+                        slider_flags);
+
+  // Paints the focusing ring for the slider. It should be painted last to be
+  // on the top.
+  if (HasFocus()) {
+    cc::PaintFlags highlight_border;
+    highlight_border.setColor(GetColorProvider()->GetColor(
+        static_cast<ui::ColorId>(cros_tokens::kCrosSysPrimary)));
+    highlight_border.setAntiAlias(true);
+    highlight_border.setStyle(cc::PaintFlags::kStroke_Style);
+    highlight_border.setStrokeWidth(kLineThickness);
+    canvas->DrawRoundRect(gfx::Rect(x - kFocusOffset, y - kFocusOffset,
+                                    full_width + 2 * kFocusOffset,
+                                    kFullSliderThickness + 2 * kFocusOffset),
+                          kFullSliderRoundedRadius, highlight_border);
+  }
+}
+
+ReadOnlySlider::ReadOnlySlider(Style slider_style)
+    : QuickSettingsSlider(/*listener=*/nullptr, slider_style) {}
+
+ReadOnlySlider::~ReadOnlySlider() = default;
+
+bool ReadOnlySlider::CanAcceptEvent(const ui::Event& event) {
+  return false;
+}
+
+BEGIN_METADATA(QuickSettingsSlider, views::View)
+END_METADATA
+
+BEGIN_METADATA(ReadOnlySlider, views::View)
+END_METADATA
+
+}  // namespace ash
diff --git a/ash/system/unified/quick_settings_slider.h b/ash/system/unified/quick_settings_slider.h
new file mode 100644
index 0000000..ce455f81
--- /dev/null
+++ b/ash/system/unified/quick_settings_slider.h
@@ -0,0 +1,94 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_SYSTEM_UNIFIED_QUICK_SETTINGS_SLIDER_H_
+#define ASH_SYSTEM_UNIFIED_QUICK_SETTINGS_SLIDER_H_
+
+#include "ash/ash_export.h"
+#include "ui/views/controls/slider.h"
+
+namespace gfx {
+class Canvas;
+}  // namespace gfx
+
+namespace views {
+class View;
+}  // namespace views
+
+namespace ui {
+class Event;
+}  // namespace ui
+
+namespace ash {
+
+// This slider view is used in quick settings in the status area. It will be
+// used in the `QuickSettingsView` and `TrayBubbleView`. This slider view
+// supports different styles. `kDefault` slider is used in `QuickSettingsView`
+// and in `TrayBubbleView`. `kRadioActive` slider will be used for the active
+// input/output device in `AudioDetailedView`. `kRadioInactive` slider will be
+// used for the inactive device in `AudioDetailedView`.
+class ASH_EXPORT QuickSettingsSlider : public views::Slider {
+ public:
+  METADATA_HEADER(QuickSettingsSlider);
+
+  // Represents the style of the slider.
+  enum class Style {
+    // Represents the slider where the full part is a rounded corner rectangle
+    // with a height of `kFullSliderThickness`, and the empty part is a rounded
+    // corner rectangle with a height of `kEmptySliderThickness`. These two
+    // parts are center-aligned horizontally. The ends of both parts have fully
+    // rounded corners.
+    kDefault,
+    // Represents the style where both the full part and the empty part of the
+    // slider have a height of `kFullSliderThickness`. The ends are fully
+    // rounded.
+    kRadioActive,
+    // Represents the style where the full part and the empty part also have the
+    // same height of `kFullSliderThickness`, except that the ends are not fully
+    // rounded but have a radius of `kInactiveRadioSliderRoundedRadius`.
+    kRadioInactive
+  };
+
+  QuickSettingsSlider(views::SliderListener* listener, Style slider_style);
+  QuickSettingsSlider(const QuickSettingsSlider&) = delete;
+  QuickSettingsSlider& operator=(const QuickSettingsSlider&) = delete;
+  ~QuickSettingsSlider() override;
+
+  // Setter and Getter of the slider style. Schedules paint after setting the
+  // style since styles and colors may change for the radio sliders because of
+  // the active status change. If the slider is the `kRadioInactive`, also
+  // disables the focus behavior for it.
+  void SetSliderStyle(Style style);
+  Style slider_style() const { return slider_style_; }
+
+ private:
+  // views::Slider:
+  SkColor GetThumbColor() const override;
+  SkColor GetTroughColor() const override;
+
+  // views::View:
+  void OnPaint(gfx::Canvas* canvas) override;
+
+  Style slider_style_;
+};
+
+// A slider that ignores inputs. This will be used in the
+// `UnifiedKeyboardBrightnessView` and `UnifiedKeyboardBacklightToggleView`.
+class ASH_EXPORT ReadOnlySlider : public QuickSettingsSlider {
+ public:
+  METADATA_HEADER(ReadOnlySlider);
+
+  explicit ReadOnlySlider(Style slider_style);
+  ReadOnlySlider(const ReadOnlySlider&) = delete;
+  ReadOnlySlider& operator=(const ReadOnlySlider&) = delete;
+  ~ReadOnlySlider() override;
+
+ private:
+  // views::View:
+  bool CanAcceptEvent(const ui::Event& event) override;
+};
+
+}  // namespace ash
+
+#endif  // ASH_SYSTEM_UNIFIED_QUICK_SETTINGS_SLIDER_H_
diff --git a/ash/system/unified/quiet_mode_feature_pod_controller.cc b/ash/system/unified/quiet_mode_feature_pod_controller.cc
index bd1c8e2..14b3534 100644
--- a/ash/system/unified/quiet_mode_feature_pod_controller.cc
+++ b/ash/system/unified/quiet_mode_feature_pod_controller.cc
@@ -13,6 +13,7 @@
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/machine_learning/user_settings_event_logger.h"
 #include "ash/system/unified/feature_pod_button.h"
+#include "ash/system/unified/quick_settings_metrics_util.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
@@ -48,9 +49,13 @@
   DCHECK(!button_);
   button_ = new FeaturePodButton(this);
   button_->SetVectorIcon(kUnifiedMenuDoNotDisturbIcon);
-  button_->SetVisible(
+  const bool visible =
       Shell::Get()->session_controller()->ShouldShowNotificationTray() &&
-      !Shell::Get()->session_controller()->IsScreenLocked());
+      !Shell::Get()->session_controller()->IsScreenLocked();
+  button_->SetVisible(visible);
+  if (visible)
+    TrackVisibilityUMA();
+
   button_->SetLabel(
       l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NOTIFICATIONS_LABEL));
   button_->SetIconTooltip(l10n_util::GetStringFUTF16(
diff --git a/ash/system/unified/unified_slider_view.cc b/ash/system/unified/unified_slider_view.cc
index 11e27698..ba43321 100644
--- a/ash/system/unified/unified_slider_view.cc
+++ b/ash/system/unified/unified_slider_view.cc
@@ -6,7 +6,6 @@
 
 #include "ash/constants/quick_settings_catalogs.h"
 #include "ash/style/ash_color_provider.h"
-#include "ash/style/color_util.h"
 #include "ash/system/tray/tray_popup_utils.h"
 #include "ash/system/unified/quick_settings_metrics_util.h"
 #include "base/check_op.h"
@@ -15,74 +14,14 @@
 #include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/label.h"
+#include "ui/views/controls/slider.h"
 #include "ui/views/layout/box_layout.h"
-#include "ui/views/view_class_properties.h"
 #include "ui/views/widget/widget.h"
 
 namespace ash {
 
 using ContentLayerType = AshColorProvider::ContentLayerType;
 
-namespace {
-
-// Custom the slider to use different colors.
-class SystemSlider : public views::Slider {
- public:
-  explicit SystemSlider(views::SliderListener* listener = nullptr)
-      : views::Slider(listener) {}
-  SystemSlider(const SystemSlider&) = delete;
-  SystemSlider& operator=(const SystemSlider&) = delete;
-  ~SystemSlider() override {}
-
- private:
-  // views::Slider:
-  SkColor GetThumbColor() const override {
-    using Type = AshColorProvider::ContentLayerType;
-    return AshColorProvider::Get()->GetContentLayerColor(
-        (style() == RenderingStyle::kMinimalStyle) ? Type::kSliderColorInactive
-                                                   : Type::kSliderColorActive);
-  }
-
-  // views::Slider:
-  SkColor GetTroughColor() const override {
-    return ColorUtil::GetSecondToneColor(GetThumbColor());
-  }
-
-  // views::View:
-  void OnThemeChanged() override {
-    views::Slider::OnThemeChanged();
-    SchedulePaint();
-  }
-};
-
-// A slider that ignores inputs.
-class ReadOnlySlider : public SystemSlider {
- public:
-  ReadOnlySlider() : SystemSlider() {}
-  ReadOnlySlider(const ReadOnlySlider&) = delete;
-  ReadOnlySlider& operator=(const ReadOnlySlider&) = delete;
-  ~ReadOnlySlider() override {}
-
- private:
-  // views::View:
-  bool OnMousePressed(const ui::MouseEvent& event) override { return false; }
-  bool OnMouseDragged(const ui::MouseEvent& event) override { return false; }
-  void OnMouseReleased(const ui::MouseEvent& event) override {}
-  bool OnKeyPressed(const ui::KeyEvent& event) override { return false; }
-  const char* GetClassName() const override { return "ReadOnlySlider"; }
-
-  // ui::EventHandler:
-  void OnGestureEvent(ui::GestureEvent* event) override {}
-};
-
-std::unique_ptr<views::Slider> CreateSlider(UnifiedSliderListener* listener,
-                                            bool readonly) {
-  return readonly ? std::make_unique<ReadOnlySlider>()
-                  : std::make_unique<SystemSlider>(listener);
-}
-
-}  // namespace
-
 void UnifiedSliderListener::TrackToggleUMA(bool target_toggle_state) {
   DCHECK_NE(GetCatalogName(), QsSliderCatalogName::kUnknown);
   quick_settings_metrics_util::RecordQsSliderToggle(
@@ -99,7 +38,7 @@
                                      UnifiedSliderListener* listener,
                                      const gfx::VectorIcon& icon,
                                      int accessible_name_id,
-                                     bool readonly)
+                                     bool read_only)
     : button_(
           AddChildView(std::make_unique<IconButton>(std::move(callback),
                                                     IconButton::Type::kSmall,
@@ -107,7 +46,10 @@
                                                     accessible_name_id,
                                                     /*is_togglable=*/true,
                                                     /*has_border=*/true))),
-      slider_(AddChildView(CreateSlider(listener, readonly))) {
+      slider_(
+          AddChildView(CreateSlider(listener,
+                                    read_only,
+                                    QuickSettingsSlider::Style::kDefault))) {
   auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::Orientation::kHorizontal, kUnifiedSliderRowPadding,
       kUnifiedSliderViewSpacing));
@@ -129,6 +71,15 @@
   layer()->SetFillsBoundsOpaquely(false);
 }
 
+std::unique_ptr<views::Slider> UnifiedSliderView::CreateSlider(
+    UnifiedSliderListener* listener,
+    bool read_only,
+    QuickSettingsSlider::Style slider_style) {
+  return read_only
+             ? std::make_unique<ReadOnlySlider>(slider_style)
+             : std::make_unique<QuickSettingsSlider>(listener, slider_style);
+}
+
 void UnifiedSliderView::SetSliderValue(float value, bool by_user) {
   // SetValue() calls |listener|, so we should ignore the call when the widget
   // is closed, because controllers are already deleted.
diff --git a/ash/system/unified/unified_slider_view.h b/ash/system/unified/unified_slider_view.h
index 07f957a..ca0c322a 100644
--- a/ash/system/unified/unified_slider_view.h
+++ b/ash/system/unified/unified_slider_view.h
@@ -7,8 +7,7 @@
 
 #include "ash/constants/quick_settings_catalogs.h"
 #include "ash/style/icon_button.h"
-#include "ui/views/controls/slider.h"
-#include "ui/views/view.h"
+#include "quick_settings_slider.h"
 
 namespace gfx {
 struct VectorIcon;
@@ -16,6 +15,8 @@
 
 namespace views {
 class Label;
+class Slider;
+class View;
 }  // namespace views
 
 namespace ash {
@@ -47,18 +48,23 @@
 // left side and a slider on the right side.
 class UnifiedSliderView : public views::View {
  public:
-  // If |readonly| is set, the slider will not accept any user events.
+  // If |read_only| is set, the slider will not accept any user events.
   UnifiedSliderView(views::Button::PressedCallback callback,
                     UnifiedSliderListener* listener,
                     const gfx::VectorIcon& icon,
                     int accessible_name_id,
-                    bool readonly = false);
+                    bool read_only = false);
 
   UnifiedSliderView(const UnifiedSliderView&) = delete;
   UnifiedSliderView& operator=(const UnifiedSliderView&) = delete;
 
   ~UnifiedSliderView() override;
 
+  std::unique_ptr<views::Slider> CreateSlider(
+      UnifiedSliderListener* listener,
+      bool read_only,
+      QuickSettingsSlider::Style slider_style);
+
   IconButton* button() { return button_; }
   views::Slider* slider() { return slider_; }
   views::Label* toast_label() { return toast_label_; }
diff --git a/ash/system/unified/unified_system_tray_controller.cc b/ash/system/unified/unified_system_tray_controller.cc
index 76e0385..8d1b122 100644
--- a/ash/system/unified/unified_system_tray_controller.cc
+++ b/ash/system/unified/unified_system_tray_controller.cc
@@ -8,6 +8,7 @@
 #include "ash/capture_mode/capture_mode_feature_pod_controller.h"
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_pref_names.h"
+#include "ash/constants/quick_settings_catalogs.h"
 #include "ash/public/cpp/metrics_util.h"
 #include "ash/public/cpp/pagination/pagination_controller.h"
 #include "ash/public/cpp/system_tray_client.h"
@@ -650,14 +651,7 @@
   FeaturePodButton* button = controller->CreateButton();
   button->SetExpandedAmount(IsExpanded() ? 1.0 : 0.0,
                             false /* fade_icon_button */);
-
-  // Records visible pods.
-  if (button->visible_preferred()) {
-    quick_settings_metrics_util::RecordVisibleQsFeature(
-        controller->GetCatalogName());
-  }
   unified_view_->AddFeaturePodButton(button);
-
   feature_pod_controllers_.push_back(std::move(controller));
 }
 
diff --git a/ash/webui/camera_app_ui/resources/js/views/camera.ts b/ash/webui/camera_app_ui/resources/js/views/camera.ts
index 6c15702..540cfeaf 100644
--- a/ash/webui/camera_app_ui/resources/js/views/camera.ts
+++ b/ash/webui/camera_app_ui/resources/js/views/camera.ts
@@ -996,7 +996,7 @@
   }
 
   override handlingKey(key: util.KeyboardShortcut): boolean {
-    if (key === 'Ctrl-R') {
+    if (key === 'Ctrl-Alt-R') {
       toast.showDebugMessage(
           this.cameraManager.getPreviewResolution().toString());
       return true;
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 2de52a9..d5745e8 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -4246,7 +4246,6 @@
       "android/java/src/org/chromium/base/Features.java",
       "android/java/src/org/chromium/base/FieldTrialList.java",
       "android/java/src/org/chromium/base/FileUtils.java",
-      "android/java/src/org/chromium/base/Function.java",
       "android/java/src/org/chromium/base/ImportantFileWriterAndroid.java",
       "android/java/src/org/chromium/base/IntStringCallback.java",
       "android/java/src/org/chromium/base/IntentUtils.java",
diff --git a/base/android/java/src/org/chromium/base/FileUtils.java b/base/android/java/src/org/chromium/base/FileUtils.java
index 4eecf49..4e962a6 100644
--- a/base/android/java/src/org/chromium/base/FileUtils.java
+++ b/base/android/java/src/org/chromium/base/FileUtils.java
@@ -25,6 +25,7 @@
 import java.io.OutputStream;
 import java.util.List;
 import java.util.Locale;
+import java.util.function.Function;
 
 /**
  * Helper methods for dealing with Files.
diff --git a/base/android/java/src/org/chromium/base/Function.java b/base/android/java/src/org/chromium/base/Function.java
deleted file mode 100644
index 93babd8..0000000
--- a/base/android/java/src/org/chromium/base/Function.java
+++ /dev/null
@@ -1,25 +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.base;
-
-/**
- * Based on Java 8's {@link java.util.function.Function}.
- *
- * <p>A function that takes a single argument and returns a value.
- *
- * @param <T> Function input type.
- * @param <RT> Function return type.
- */
-public interface Function<T, RT> {
-    // TODO(crbug.com/1034012): Remove once min Android API level reaches 24.
-
-    /**
-     * Returns the result of applying this function to {@code input}.
-     *
-     * @param input Function input argument.
-     * @return Function result.
-     */
-    RT apply(T input);
-}
diff --git a/base/android/java/src/org/chromium/base/Promise.java b/base/android/java/src/org/chromium/base/Promise.java
index 2806353f..9244202 100644
--- a/base/android/java/src/org/chromium/base/Promise.java
+++ b/base/android/java/src/org/chromium/base/Promise.java
@@ -12,6 +12,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.function.Function;
 
 /**
  * A Promise class to be used as a placeholder for a result that will be provided asynchronously.
diff --git a/base/android/junit/src/org/chromium/base/FileUtilsTest.java b/base/android/junit/src/org/chromium/base/FileUtilsTest.java
index bcf74a92..7609e112 100644
--- a/base/android/junit/src/org/chromium/base/FileUtilsTest.java
+++ b/base/android/junit/src/org/chromium/base/FileUtilsTest.java
@@ -50,6 +50,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.function.Function;
 
 /** Unit tests for {@link Log}. */
 @RunWith(BaseRobolectricTestRunner.class)
diff --git a/base/android/junit/src/org/chromium/base/PromiseTest.java b/base/android/junit/src/org/chromium/base/PromiseTest.java
index 8bb76a7..4d480cd 100644
--- a/base/android/junit/src/org/chromium/base/PromiseTest.java
+++ b/base/android/junit/src/org/chromium/base/PromiseTest.java
@@ -18,6 +18,8 @@
 import org.chromium.base.Promise.UnhandledRejectionException;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 
+import java.util.function.Function;
+
 /** Unit tests for {@link Promise}. */
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
diff --git a/base/message_loop/message_pump_epoll.cc b/base/message_loop/message_pump_epoll.cc
index 2df30fa4..e021f27 100644
--- a/base/message_loop/message_pump_epoll.cc
+++ b/base/message_loop/message_pump_epoll.cc
@@ -96,7 +96,7 @@
     }
 
     // Process any immediately ready IO event, but don't wait for more yet.
-    const bool processed_events = WaitForEpollEvent(TimeDelta());
+    const bool processed_events = WaitForEpollEvents(TimeDelta());
     if (run_state.should_quit) {
       break;
     }
@@ -119,7 +119,7 @@
       timeout = next_work_info.remaining_delay();
     }
     delegate->BeforeWait();
-    WaitForEpollEvent(timeout);
+    WaitForEpollEvents(timeout);
     if (run_state.should_quit) {
       break;
     }
@@ -195,7 +195,7 @@
   }
 }
 
-bool MessagePumpEpoll::WaitForEpollEvent(TimeDelta timeout) {
+bool MessagePumpEpoll::WaitForEpollEvents(TimeDelta timeout) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   // `timeout` has microsecond resolution, but timeouts accepted by epoll_wait()
@@ -204,9 +204,9 @@
   const int epoll_timeout =
       timeout.is_max() ? -1
                        : saturated_cast<int>(timeout.InMillisecondsRoundedUp());
-  epoll_event event;
+  epoll_event events[16];
   const int epoll_result =
-      epoll_wait(epoll_.get(), &event, /*maxevents=*/1, epoll_timeout);
+      epoll_wait(epoll_.get(), events, std::size(events), epoll_timeout);
   if (epoll_result < 0) {
     DPCHECK(errno == EINTR);
     return false;
@@ -216,27 +216,48 @@
     return false;
   }
 
-  DPCHECK(epoll_result == 1);
-  OnEpollEvent(event);
+  const base::span<epoll_event> ready_events(events,
+                                             static_cast<size_t>(epoll_result));
+  for (auto& e : ready_events) {
+    if (e.data.ptr == &wake_event_) {
+      // Wake-up events are always safe to handle immediately. Unlike other
+      // events used by MessagePumpEpoll they also don't point to an
+      // EpollEventEntry, so we handle them separately here.
+      HandleWakeUp();
+      e.data.ptr = nullptr;
+      continue;
+    }
+
+    // To guard against one of the ready events unregistering and thus
+    // invalidating one of the others here, first link each entry to the
+    // corresponding epoll_event returned by epoll_wait(). We do this before
+    // dispatching any events, and the second pass below will only dispatch an
+    // event if its epoll_event data is still valid.
+    auto& entry = EpollEventEntry::FromEpollEvent(e);
+    DCHECK(!entry.active_event);
+    EpollEventEntry::FromEpollEvent(e).active_event = &e;
+  }
+
+  for (auto& e : ready_events) {
+    if (e.data.ptr) {
+      auto& entry = EpollEventEntry::FromEpollEvent(e);
+      entry.active_event = nullptr;
+      OnEpollEvent(entry, e.events);
+    }
+  }
+
   return true;
 }
 
-void MessagePumpEpoll::OnEpollEvent(const epoll_event& e) {
+void MessagePumpEpoll::OnEpollEvent(EpollEventEntry& entry, uint32_t events) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  if (e.data.ptr == &wake_event_) {
-    HandleWakeUp();
-    return;
-  }
 
-  const bool readable = (e.events & EPOLLIN) != 0;
-  const bool writable = (e.events & EPOLLOUT) != 0;
+  const bool readable = (events & EPOLLIN) != 0;
+  const bool writable = (events & EPOLLOUT) != 0;
 
   // Under different circumstances, peer closure may raise both/either EPOLLHUP
   // and/or EPOLLERR. Treat them as equivalent.
-  const bool disconnected = (e.events & (EPOLLHUP | EPOLLERR)) != 0;
-
-  DCHECK(e.data.ptr);
-  auto& entry = *static_cast<EpollEventEntry*>(e.data.ptr);
+  const bool disconnected = (events & (EPOLLHUP | EPOLLERR)) != 0;
 
   // Copy the set of Interests, since interests may be added to or removed from
   // `entry` during the loop below. This copy is inexpensive in practice
@@ -333,7 +354,12 @@
 
 MessagePumpEpoll::EpollEventEntry::EpollEventEntry(int fd) : fd(fd) {}
 
-MessagePumpEpoll::EpollEventEntry::~EpollEventEntry() = default;
+MessagePumpEpoll::EpollEventEntry::~EpollEventEntry() {
+  if (active_event) {
+    DCHECK_EQ(this, active_event->data.ptr);
+    active_event->data.ptr = nullptr;
+  }
+}
 
 uint32_t MessagePumpEpoll::EpollEventEntry::ComputeActiveEvents() {
   uint32_t events = 0;
diff --git a/base/message_loop/message_pump_epoll.h b/base/message_loop/message_pump_epoll.h
index 10a182b..c615dd9 100644
--- a/base/message_loop/message_pump_epoll.h
+++ b/base/message_loop/message_pump_epoll.h
@@ -70,6 +70,10 @@
     EpollEventEntry& operator=(const EpollEventEntry&) = delete;
     ~EpollEventEntry();
 
+    static EpollEventEntry& FromEpollEvent(epoll_event& e) {
+      return *static_cast<EpollEventEntry*>(e.data.ptr);
+    }
+
     // Returns the combined set of epoll event flags which should be monitored
     // by the epoll instance for `fd`. This is based on a combination of the
     // parameters of all currently active elements in `interests`. Namely:
@@ -91,6 +95,12 @@
     // than two controllers (e.g. one reader and one writer) watch the same
     // descriptor on the same thread.
     StackVector<scoped_refptr<Interest>, 2> interests;
+
+    // Temporary pointer to an active epoll_event structure which refers to
+    // this entry. This is set immediately upon returning from epoll_wait() and
+    // cleared again immediately before dispatching to any registered interests,
+    // so long as this entry isn't destroyed in the interim.
+    epoll_event* active_event = nullptr;
   };
 
   // State which lives on the stack within Run(), to support nested run loops.
@@ -108,8 +118,8 @@
   void AddEpollEvent(EpollEventEntry& entry);
   void UpdateEpollEvent(EpollEventEntry& entry);
   void UnregisterInterest(const scoped_refptr<Interest>& interest);
-  bool WaitForEpollEvent(TimeDelta timeout);
-  void OnEpollEvent(const epoll_event& e);
+  bool WaitForEpollEvents(TimeDelta timeout);
+  void OnEpollEvent(EpollEventEntry& entry, uint32_t events);
   void HandleEvent(int fd,
                    bool can_read,
                    bool can_write,
diff --git a/base/power_monitor/battery_level_provider.cc b/base/power_monitor/battery_level_provider.cc
index 042e959..e0412a8 100644
--- a/base/power_monitor/battery_level_provider.cc
+++ b/base/power_monitor/battery_level_provider.cc
@@ -40,6 +40,12 @@
         absl::make_optional(battery_details.front().full_charged_capacity);
     state.charge_unit =
         absl::make_optional(battery_details.front().charge_unit);
+#if BUILDFLAG(IS_WIN)
+    state.battery_discharge_granularity =
+        battery_details.front().battery_discharge_granularity;
+    state.max_battery_discharge_granularity =
+        battery_details.front().max_battery_discharge_granularity;
+#endif  // BUILDFLAG(IS_WIN)
   }
   state.capture_time = base::TimeTicks::Now();
 
diff --git a/base/power_monitor/battery_level_provider.h b/base/power_monitor/battery_level_provider.h
index df8716b7..655d06f9 100644
--- a/base/power_monitor/battery_level_provider.h
+++ b/base/power_monitor/battery_level_provider.h
@@ -54,6 +54,20 @@
 
     // The time at which the battery state capture took place.
     base::TimeTicks capture_time;
+
+#if BUILDFLAG(IS_WIN)
+    // The granularity of the |current_capacity| value, in hundredths of a
+    // percent. Only available on Windows, and if a battery is present. This
+    // value is populated by the manufacturer and is not guaranteed to be
+    // available or accurate.
+    absl::optional<uint32_t> battery_discharge_granularity;
+
+    // The most coarse granularity among all the reporting scales of the
+    // battery, in hundredths of a percent. Only available on Windows, and if a
+    // battery is present. This value is populated by the manufacturer and is
+    // not guaranteed to be available or accurate.
+    absl::optional<uint32_t> max_battery_discharge_granularity;
+#endif  // BUILDFLAG(IS_WIN)
   };
 
   // Creates a platform specific BatteryLevelProvider able to retrieve battery
@@ -87,6 +101,20 @@
 
     // The battery's unit of charge.
     BatteryLevelUnit charge_unit;
+
+#if BUILDFLAG(IS_WIN)
+    // The granularity of the |current_capacity| value, in hundredths of a
+    // percent. Only available on Windows, and if a battery is present. This
+    // value is populated by the manufacturer and is not guaranteed to be
+    // available or accurate.
+    absl::optional<uint32_t> battery_discharge_granularity;
+
+    // The most coarse granularity among all the reporting scales of the
+    // battery, in hundredths of a percent. Only available on Windows, and if a
+    // battery is present. This value is populated by the manufacturer and is
+    // not guaranteed to be available or accurate.
+    absl::optional<uint32_t> max_battery_discharge_granularity;
+#endif  // BUILDFLAG(IS_WIN)
   };
 
   // Constructs a `BatteryState` from a list of `BatteryDetails`. The list can
diff --git a/base/power_monitor/battery_level_provider_win.cc b/base/power_monitor/battery_level_provider_win.cc
index 90dac87..889f829f 100644
--- a/base/power_monitor/battery_level_provider_win.cc
+++ b/base/power_monitor/battery_level_provider_win.cc
@@ -12,6 +12,7 @@
 #include <setupapi.h>
 #include <winioctl.h>
 
+#include <array>
 #include <vector>
 
 #include "base/memory/weak_ptr.h"
@@ -105,6 +106,60 @@
   return battery_information;
 }
 
+// Returns information about the granularity of the battery discharge rate. This
+// function returns 2 values: the granularity that correspond to the current
+// capacity; and the most coarse granularity, which can differ from the other
+// granularity if the battery has multiple scales and the current capacity is
+// not full.
+std::pair<absl::optional<uint32_t>, absl::optional<uint32_t>>
+GetBatteryGranularityInformation(HANDLE battery,
+                                 ULONG battery_tag,
+                                 ULONG current_capacity,
+                                 ULONG designed_capacity) {
+  BATTERY_QUERY_INFORMATION query_information = {};
+  query_information.BatteryTag = battery_tag;
+  query_information.InformationLevel = BatteryGranularityInformation;
+
+  // The battery discharge granularity can change as the level of the battery
+  // gets closer to zero. The documentation for `BatteryGranularityInformation`
+  // says that a maximum of 4 scales is possible. Each scale contains the
+  // granularity (in mWh) and the capacity (in mWh) at which the scale takes
+  // effect.
+  // https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-battery_reporting_scale
+  std::array<BATTERY_REPORTING_SCALE, 4> battery_reporting_scales;
+
+  DWORD bytes_returned = 0;
+  BOOL success = ::DeviceIoControl(
+      battery, IOCTL_BATTERY_QUERY_INFORMATION, &query_information,
+      sizeof(query_information), &battery_reporting_scales,
+      sizeof(battery_reporting_scales), &bytes_returned, nullptr);
+  if (!success)
+    return {absl::nullopt, absl::nullopt};
+
+  size_t nb_elements = bytes_returned / sizeof(BATTERY_REPORTING_SCALE);
+  if (!nb_elements)
+    return {absl::nullopt, absl::nullopt};
+
+  DWORD max_granularity = battery_reporting_scales[0].Granularity;
+  DWORD current_granularity = battery_reporting_scales[0].Granularity;
+  for (size_t i = 1; i < nb_elements; i++) {
+    // The granularities are ordered from the highest capacity to the lowest
+    // capacity, or from the most coarse granularity to the most precise
+    // granularity, according to the documentation.
+    if (current_capacity < battery_reporting_scales[i].Capacity)
+      current_granularity = battery_reporting_scales[i].Granularity;
+
+    // Just in case, the documentation is not trusted for |max_granularity|. All
+    // the values are still compared to find the most coarse granularity.
+    max_granularity =
+        std::max(max_granularity, battery_reporting_scales[i].Granularity);
+  }
+
+  // Returns the granularities in hundredths of a percent.
+  return {current_granularity * 10000.0 / designed_capacity,
+          max_granularity * 10000.0 / designed_capacity};
+}
+
 // Returns BATTERY_STATUS structure containing battery state, given battery
 // handle and tag, or nullopt if the request failed. Battery handle and tag are
 // obtained with GetBatteryHandle() and GetBatteryTag(), respectively.
@@ -226,6 +281,12 @@
       return absl::nullopt;
     }
 
+    const auto& [battery_discharge_granularity,
+                 max_battery_discharge_granularity] =
+        GetBatteryGranularityInformation(battery.Get(), *battery_tag,
+                                         battery_status->Capacity,
+                                         battery_information->DesignedCapacity);
+
     battery_details_list.push_back(BatteryDetails(
         {.is_external_power_connected =
              !!(battery_status->PowerState & BATTERY_POWER_ON_LINE),
@@ -234,7 +295,10 @@
          .charge_unit =
              ((battery_information->Capabilities & BATTERY_CAPACITY_RELATIVE)
                   ? BatteryLevelUnit::kRelative
-                  : BatteryLevelUnit::kMWh)}));
+                  : BatteryLevelUnit::kMWh),
+         .battery_discharge_granularity = battery_discharge_granularity,
+         .max_battery_discharge_granularity =
+             max_battery_discharge_granularity}));
   }
 
   return MakeBatteryState(battery_details_list);
diff --git a/build/config/chrome_build.gni b/build/config/chrome_build.gni
index 2207912..0e755fb 100644
--- a/build/config/chrome_build.gni
+++ b/build/config/chrome_build.gni
@@ -18,6 +18,12 @@
   # Design document: https://goo.gle/chrome-for-testing
   is_chrome_for_testing_branded = false
 
+  # Whether to use internal Chrome for Testing (CfT) icons.
+  # If set to true, use Google-internal icons, otherwise fall back to Chromium icons.
+  #
+  # This flag can only be set to true for CfT builds.
+  use_internal_chrome_for_testing_icons = false
+
   # Set to true to enable settings for high end Android devices, typically
   # enhancing speed at the expense of resources such as binary sizes and memory.
   is_high_end_android = false
@@ -27,13 +33,21 @@
     !is_chrome_for_testing_branded || !is_chrome_branded,
     "Chrome for Testing (`is_chrome_for_testing_branded`) requires Chromium flavor (`is_chrome_branded = False`)")
 
+assert(
+    is_chrome_for_testing_branded || !use_internal_chrome_for_testing_icons,
+    "Use of internal Chrome for Testing icons (`use_internal_chrome_for_testing_icons`) requires CfT flavor (`is_chrome_for_testing_branded = True`)")
+
 declare_args() {
   # Refers to the subdirectory for branding in various places including
   # chrome/app/theme.
   #
   # `branding_path_product` must not contain slashes.
   if (is_chrome_for_testing_branded) {
-    branding_path_component = "google_chrome/google_chrome_for_testing"
+    if (use_internal_chrome_for_testing_icons) {
+      branding_path_component = "google_chrome/google_chrome_for_testing"
+    } else {
+      branding_path_component = "chromium"
+    }
     branding_path_product = "chromium"
   } else if (is_chrome_branded) {
     branding_path_component = "google_chrome"
diff --git a/build/config/fuchsia/generate_runner_scripts.gni b/build/config/fuchsia/generate_runner_scripts.gni
index 4b67ddf..3d9ed5f6 100644
--- a/build/config/fuchsia/generate_runner_scripts.gni
+++ b/build/config/fuchsia/generate_runner_scripts.gni
@@ -35,9 +35,11 @@
   # targets.
   fuchsia_browser_type = "web_engine_shell"
 
-  # This variable controls which version of the testing scripts to use.
+  # This variable controls which default version of the testing scripts to use.
+  # Individual tests can override this via setting |legacy_script_required| to
+  # true.
   # TODO(crbug/1280705): remove when all tests are migrated to CFv2.
-  use_cfv2_script = false
+  use_v2_script_default = true
 }
 
 # Generates a wrapper script under root_build_dir/bin that performs an
@@ -69,12 +71,18 @@
 #   include_fuchsia_build_dir: If true, adds
 #                              |default_fuchsia_build_dir_for_installation|
 #                              to executable_args (when set in GN args).
+#   use_v2_script: Whether to use the the ssh based v1 or ffx based v2 scripts.
 template("fuchsia_run_script_with_packages") {
   if (defined(invoker.package_name)) {
     _pkg_shortname = invoker.package_name
   } else {
     _pkg_shortname = get_label_info(invoker.package, "name")
   }
+  if (!defined(invoker.use_v2_script)) {
+    use_v2_script = use_v2_script_default
+  } else {
+    use_v2_script = invoker.use_v2_script
+  }
 
   _generated_script_path =
       "$root_build_dir/bin/" +
@@ -118,7 +126,7 @@
     }
 
     # Compute the list of full paths to package files, including dependencies.
-    if (!use_cfv2_script) {
+    if (!use_v2_script) {
       _pkg_dir = "$root_out_dir/gen/" + get_label_info(invoker.package, "dir") +
                  "/" + _pkg_shortname
       package_paths =
@@ -129,7 +137,7 @@
         package_dep_target = package_dep[0]
         deps += [ package_dep_target ]
         data_deps += [ package_dep_target ]
-        if (!use_cfv2_script) {
+        if (!use_v2_script) {
           package_dep_name = package_dep[1]
           package_dep_path = rebase_path(
                   get_label_info(package_dep_target, "target_gen_dir") + "/" +
@@ -145,7 +153,7 @@
       executable_args = []
     }
 
-    if (!use_cfv2_script) {
+    if (!use_v2_script) {
       foreach(package_path, package_paths) {
         executable_args += [
           "--package",
@@ -209,6 +217,12 @@
   _run_target = "${target_name}__runner"
   _install_target = "${target_name}__installer"
 
+  if (!defined(invoker.use_v2_script)) {
+    use_v2_script = use_v2_script_default
+  } else {
+    use_v2_script = invoker.use_v2_script
+  }
+
   fuchsia_run_script_with_packages(_run_target) {
     forward_variables_from(invoker,
                            TESTONLY_AND_VISIBILITY + [
@@ -219,7 +233,7 @@
                                  "package_deps",
                                ])
 
-    if (use_cfv2_script) {
+    if (use_v2_script) {
       _test_runner_py = "//build/fuchsia/test/run_test.py"
     } else {
       _test_runner_py = "//build/fuchsia/test_runner.py"
@@ -239,7 +253,7 @@
       "@WrappedPath(.)",
     ]
 
-    if (use_cfv2_script) {
+    if (use_v2_script) {
       executable_args += [ package_name ]
     } else {
       executable_args += [
@@ -253,7 +267,7 @@
     }
 
     if (default_fuchsia_device_node_name != "") {
-      if (use_cfv2_script) {
+      if (use_v2_script) {
         executable_args += [
           "--target-id",
           default_fuchsia_device_node_name,
@@ -273,7 +287,7 @@
     }
     data += [ _test_runner_py ]
 
-    if (use_cfv2_script) {
+    if (use_v2_script) {
       data += [ "$root_gen_dir/package_metadata/${invoker.package_name}.meta" ]
     }
 
@@ -292,25 +306,3 @@
                                ])
   }
 }
-
-# Transitional target that aliases "fuchsia_package_runner" to an installer
-# target. Used for migrating out-of-tree users of fuchsia_package_runner.
-template("fuchsia_package_runner") {
-  if (defined(invoker.install_only) && invoker.install_only) {
-    fuchsia_package_installer(target_name) {
-      forward_variables_from(invoker, "*", [ "install_only" ])
-
-      if (defined(invoker.package_name_override)) {
-        package_name = invoker.package_name_override
-      }
-    }
-  } else {
-    fuchsia_test_runner(target_name) {
-      forward_variables_from(invoker, "*", [ "package_name_override" ])
-
-      if (defined(invoker.package_name_override)) {
-        package_name = invoker.package_name_override
-      }
-    }
-  }
-}
diff --git a/build/fuchsia/test/common.py b/build/fuchsia/test/common.py
index e9b57629..ebaefb76 100644
--- a/build/fuchsia/test/common.py
+++ b/build/fuchsia/test/common.py
@@ -119,6 +119,7 @@
                     target_id: Optional[str] = None,
                     check: bool = True,
                     suppress_repair: bool = False,
+                    configs: Optional[List[str]] = None,
                     **kwargs) -> subprocess.CompletedProcess:
     """Runs `ffx` with the given arguments, waiting for it to exit.
 
@@ -136,6 +137,7 @@
             exit code.
         suppress_repair: If True, do not attempt to find and run a repair
             command.
+        configs: A list of configs to be applied to the current command.
     Returns:
         A CompletedProcess instance
     Raises:
@@ -145,6 +147,9 @@
     ffx_cmd = [_FFX_TOOL]
     if target_id:
         ffx_cmd.extend(('--target', target_id))
+    if configs:
+        for config in configs:
+            ffx_cmd.extend(('--config', config))
     ffx_cmd.extend(cmd)
     env = os.environ
     if _FFX_ISOLATE_DIR:
diff --git a/build/fuchsia/test/compatible_utils.py b/build/fuchsia/test/compatible_utils.py
index 9703194..c86af343 100644
--- a/build/fuchsia/test/compatible_utils.py
+++ b/build/fuchsia/test/compatible_utils.py
@@ -14,12 +14,19 @@
 _BUILD_ARGS = "buildargs.gn"
 
 _FILTER_DIR = 'testing/buildbot/filters'
+_SSH_KEYS = os.path.expanduser('~/.ssh/fuchsia_authorized_keys')
 
 
 class VersionNotFoundError(Exception):
     """Thrown when version info cannot be retrieved from device."""
 
 
+def get_ssh_keys() -> str:
+    """Returns path of Fuchsia ssh keys."""
+
+    return _SSH_KEYS
+
+
 def running_unattended() -> bool:
     """Returns true if running non-interactively.
 
@@ -36,7 +43,7 @@
 
     pave_command = [
         os.path.join(image_dir, 'pave.sh'), '--authorized-keys',
-        os.path.expanduser('~/.ssh/fuchsia_authorized_keys'), '-1'
+        get_ssh_keys(), '-1'
     ]
     if target_id:
         pave_command.extend(['-n', target_id])
diff --git a/build/fuchsia/test/flash_device.py b/build/fuchsia/test/flash_device.py
index 6821084..db4b382 100755
--- a/build/fuchsia/test/flash_device.py
+++ b/build/fuchsia/test/flash_device.py
@@ -7,13 +7,15 @@
 import argparse
 import json
 import os
+import subprocess
 import sys
 import time
 
 from typing import Optional, Tuple
 
 from common import register_device_args, run_ffx_command
-from compatible_utils import get_sdk_hash
+from compatible_utils import get_sdk_hash, get_ssh_keys, pave, \
+    running_unattended
 from ffx_integration import ScopedFfxConfig
 
 
@@ -53,37 +55,84 @@
     return True
 
 
+def _run_flash_command(system_image_dir: str, target_id: Optional[str]):
+    """Helper function for running `ffx target flash`."""
+
+    # TODO(fxb/91843): Remove workaround when ffx has stable support for
+    # multiple hardware devices connected via USB.
+    if running_unattended():
+        flash_cmd = [
+            os.path.join(system_image_dir, 'flash.sh'),
+            '--ssh-key=%s' % get_ssh_keys(),
+        ]
+        if target_id:
+            flash_cmd.extend(('-s', target_id))
+        subprocess.run(flash_cmd, check=True, timeout=240)
+        return
+
+    manifest = os.path.join(system_image_dir, 'flash-manifest.manifest')
+    run_ffx_command(('target', 'flash', manifest, '--no-bootloader-reboot'),
+                    target_id=target_id,
+                    configs=[
+                        'fastboot.usb.disabled=true',
+                        'ffx.fastboot.inline_target=true'
+                    ])
+
+
 def flash(system_image_dir: str,
-          os_check: str,
           target: Optional[str],
           serial_num: Optional[str] = None) -> None:
     """Flash the device."""
+    with ScopedFfxConfig('fastboot.reboot.reconnect_timeout', '120'):
+        if serial_num:
+            with ScopedFfxConfig('discovery.zedboot.enabled', 'true'):
+                run_ffx_command(('target', 'reboot', '-b'),
+                                target,
+                                check=False)
+            for _ in range(10):
+                time.sleep(10)
+                if run_ffx_command(('target', 'list', serial_num),
+                                   check=False).returncode == 0:
+                    break
+            _run_flash_command(system_image_dir, serial_num)
+        else:
+            _run_flash_command(system_image_dir, target)
+    run_ffx_command(('target', 'wait'), target)
+
+
+def update(system_image_dir: str,
+           os_check: str,
+           target: Optional[str],
+           serial_num: Optional[str] = None,
+           should_pave: Optional[bool] = True) -> None:
+    """Conditionally updates target given.
+
+    Args:
+        system_image_dir: string, path to image directory.
+        os_check: <check|ignore|update>, which decides how to update the device.
+        target: Node-name string indicating device that should be updated.
+        serial_num: String of serial number of device that should be updated.
+        should_pave: Optional bool on whether or not to pave or flash.
+    """
 
     if update_required(os_check, system_image_dir, target):
-        manifest = os.path.join(system_image_dir, 'flash-manifest.manifest')
-        with ScopedFfxConfig('fastboot.reboot.reconnect_timeout', '120'):
-            if serial_num:
-                with ScopedFfxConfig('discovery.zedboot.enabled', 'true'):
-                    run_ffx_command(('target', 'reboot', '-b'),
-                                    target,
-                                    check=False)
-                for _ in range(10):
-                    time.sleep(10)
-                    if run_ffx_command(('target', 'list', serial_num),
-                                       check=False).returncode == 0:
-                        break
-                run_ffx_command(('target', 'flash', manifest), serial_num)
-            else:
-                run_ffx_command(('target', 'flash', manifest), target)
-        run_ffx_command(('target', 'wait'), target)
+        if should_pave:
+            if running_unattended():
+                assert target, ('Target ID must be specified on swarming when'
+                                ' paving.')
+            pave(system_image_dir, target)
+            time.sleep(120)
+        else:
+            flash(system_image_dir, target, serial_num)
 
 
-def register_flash_args(arg_parser: argparse.ArgumentParser,
-                        default_os_check: Optional[str] = 'check') -> None:
-    """Register common arguments for device flashing."""
+def register_update_args(arg_parser: argparse.ArgumentParser,
+                         default_os_check: Optional[str] = 'check',
+                         default_pave: Optional[bool] = True) -> None:
+    """Register common arguments for device updating."""
 
-    serve_args = arg_parser.add_argument_group('flash',
-                                               'device flashing arguments')
+    serve_args = arg_parser.add_argument_group('update',
+                                               'device updating arguments')
     serve_args.add_argument('--system-image-dir',
                             help='Specify the directory that contains the '
                             'Fuchsia image used to pave the device. Only '
@@ -103,16 +152,26 @@
                             '"update", then the target device will '
                             'be reflashed. If "ignore", then the OS version '
                             'will not be checked.')
+    serve_args.add_argument('--pave',
+                            action='store_true',
+                            help='Performs a pave instead of a flash. '
+                            'Device must already be in Zedboot')
+    serve_args.add_argument('--no-pave',
+                            action='store_false',
+                            dest='pave',
+                            help='Performs a flash instead of a pave '
+                            '(experimental).')
+    serve_args.set_defaults(pave=default_pave)
 
 
 def main():
     """Stand-alone function for flashing a device."""
     parser = argparse.ArgumentParser()
     register_device_args(parser)
-    register_flash_args(parser)
+    register_update_args(parser)
     args = parser.parse_args()
-    flash(args.system_image_dir, args.os_check, args.target_id,
-          args.serial_num)
+    update(args.system_image_dir, args.os_check, args.target_id,
+           args.serial_num, args.pave)
 
 
 if __name__ == '__main__':
diff --git a/build/fuchsia/test/flash_device_unittests.py b/build/fuchsia/test/flash_device_unittests.py
index 4410592..675bbcc 100755
--- a/build/fuchsia/test/flash_device_unittests.py
+++ b/build/fuchsia/test/flash_device_unittests.py
@@ -37,10 +37,10 @@
         self.addCleanup(self._ffx_mock.stop)
         self.addCleanup(self._sdk_hash_mock.stop)
 
-    def test_flash_ignore(self) -> None:
+    def test_update_ignore(self) -> None:
         """Test setting |os_check| to 'ignore'."""
 
-        flash_device.flash(_TEST_IMAGE_DIR, 'ignore', None)
+        flash_device.update(_TEST_IMAGE_DIR, 'ignore', None)
         self.assertEqual(self._ffx_mock.call_count, 0)
         self.assertEqual(self._sdk_hash_mock.call_count, 0)
 
@@ -48,48 +48,93 @@
         """Test ValueError raised when system_image_dir unspecified."""
 
         with self.assertRaises(ValueError):
-            flash_device.flash(None, 'check', None)
+            flash_device.update(None, 'check', None)
 
-    def test_flash_system_info_match(self) -> None:
-        """Test no flash when |os_check| is 'check' and system info matches."""
+    def test_update_system_info_match(self) -> None:
+        """Test no update when |os_check| is 'check' and system info matches."""
 
         self._ffx_mock.return_value.stdout = \
             '[{"title": "Build", "child": [{"value": "%s"}, ' \
             '{"value": "%s"}]}]' % (_TEST_VERSION, _TEST_PRODUCT)
-        flash_device.flash(_TEST_IMAGE_DIR, 'check', None)
+        flash_device.update(_TEST_IMAGE_DIR, 'check', None)
         self.assertEqual(self._ffx_mock.call_count, 1)
         self.assertEqual(self._sdk_hash_mock.call_count, 1)
 
-    def test_flash_system_info_mismatch(self) -> None:
-        """Test flash when |os_check| is 'check' and system info does not
+    def test_update_system_info_mismatch(self) -> None:
+        """Test update when |os_check| is 'check' and system info does not
         match."""
 
         self._ffx_mock.return_value.stdout = \
             '[{"title": "Build", "child": [{"value": "wrong.version"}, ' \
             '{"value": "wrong_product"}]}]'
-        flash_device.flash(_TEST_IMAGE_DIR, 'check', None)
+        flash_device.update(_TEST_IMAGE_DIR, 'check', None, should_pave=False)
         self.assertEqual(self._ffx_mock.call_count, 3)
 
     def test_incorrect_target_info(self) -> None:
-        """Test flash when |os_check| is 'check' and system info was not
+        """Test update when |os_check| is 'check' and system info was not
         retrieved."""
 
         self._ffx_mock.return_value.stdout = '[{"title": "badtitle"}]'
-        flash_device.flash(_TEST_IMAGE_DIR, 'check', None)
+        flash_device.update(_TEST_IMAGE_DIR, 'check', None, should_pave=False)
         self.assertEqual(self._ffx_mock.call_count, 3)
 
-    def test_flash_with_serial_num(self) -> None:
-        """Test flash when |serial_num| is specified."""
+    def test_update_with_serial_num(self) -> None:
+        """Test update when |serial_num| is specified."""
 
         with mock.patch('time.sleep'):
-            flash_device.flash(_TEST_IMAGE_DIR, 'update', None, 'test_serial')
+            flash_device.update(_TEST_IMAGE_DIR,
+                                'update',
+                                None,
+                                'test_serial',
+                                should_pave=False)
         self.assertEqual(self._ffx_mock.call_count, 4)
 
+    # pylint: disable=no-self-use
+    def test_update_calls_paving_if_specified(self) -> None:
+        """Test update calls pave if specified."""
+        with mock.patch('time.sleep'), \
+            mock.patch('flash_device.pave') as mock_pave:
+            flash_device.update(_TEST_IMAGE_DIR,
+                                'update',
+                                'some-target-id',
+                                should_pave=True)
+            mock_pave.assert_called_once_with(_TEST_IMAGE_DIR,
+                                              'some-target-id')
+
+    # pylint: enable=no-self-use
+
+    def test_update_raises_error_if_unattended_with_no_target(self) -> None:
+        """Test update calls pave if specified."""
+        with mock.patch('time.sleep'), \
+            mock.patch('flash_device.pave'), \
+            mock.patch('flash_device.running_unattended', return_value=True):
+            self.assertRaises(AssertionError,
+                              flash_device.update,
+                              _TEST_IMAGE_DIR,
+                              'update',
+                              None,
+                              should_pave=True)
+
+    def test_update_on_swarming(self) -> None:
+        """Test update on swarming bots."""
+
+        with mock.patch('time.sleep'), \
+             mock.patch('flash_device.running_unattended',
+                        return_value = True), \
+             mock.patch('subprocess.run'):
+            flash_device.update(_TEST_IMAGE_DIR,
+                                'update',
+                                None,
+                                'test_serial',
+                                should_pave=False)
+        self.assertEqual(self._ffx_mock.call_count, 3)
+
     def test_main(self) -> None:
         """Tests |main| function."""
 
-        with mock.patch('sys.argv',
-                        ['flash_device.py', '--os-check', 'ignore']):
+        with mock.patch(
+                'sys.argv',
+            ['flash_device.py', '--os-check', 'ignore', '--no-pave']):
             with mock.patch.dict(os.environ, {}):
                 flash_device.main()
         self.assertEqual(self._ffx_mock.call_count, 0)
diff --git a/build/fuchsia/test/run_executable_test.py b/build/fuchsia/test/run_executable_test.py
index 59980f8..c9531c74d 100755
--- a/build/fuchsia/test/run_executable_test.py
+++ b/build/fuchsia/test/run_executable_test.py
@@ -177,7 +177,7 @@
         if self._isolated_script_test_output:
             _copy_custom_output_file(
                 test_runner,
-                os.path.basename(self._test_launcher_summary_output),
+                os.path.basename(self._isolated_script_test_output),
                 self._isolated_script_test_output)
         if self._code_coverage_dir:
             _copy_coverage_files(test_runner,
diff --git a/build/fuchsia/test/run_test.py b/build/fuchsia/test/run_test.py
index b659425..b9e734c 100755
--- a/build/fuchsia/test/run_test.py
+++ b/build/fuchsia/test/run_test.py
@@ -7,7 +7,6 @@
 import argparse
 import sys
 import tempfile
-import time
 
 from contextlib import ExitStack
 from typing import List
@@ -15,9 +14,9 @@
 from common import register_common_args, register_device_args, \
                    register_log_args, resolve_packages, resolve_v1_packages, \
                    set_ffx_isolate_dir
-from compatible_utils import pave, running_unattended
+from compatible_utils import running_unattended
 from ffx_integration import ScopedFfxConfig, test_connection
-from flash_device import register_flash_args, update_required
+from flash_device import register_update_args, update
 from log_manager import LogManager, start_system_log
 from publish_package import publish_packages, register_package_args
 from run_blink_test import BlinkTestRunner
@@ -61,7 +60,7 @@
     register_device_args(parser)
     register_emulator_args(parser)
     register_executable_test_args(parser)
-    register_flash_args(parser, default_os_check='ignore')
+    register_update_args(parser, default_os_check='ignore', default_pave=True)
     register_log_args(parser)
     register_package_args(parser, allow_temp_repo=True)
     register_serve_args(parser)
@@ -83,14 +82,9 @@
             ScopedFfxConfig('repository.server.listen', '"[::]:0"'))
         log_manager = stack.enter_context(LogManager(runner_args.logs_dir))
         if runner_args.device:
-            if update_required(runner_args.os_check,
-                               runner_args.system_image_dir,
-                               runner_args.target_id):
-
-                # TODO(https://fxbug.dev/91843): Switch to flashing the device
-                # when the ffx command is more stable.
-                pave(runner_args.system_image_dir, runner_args.target_id)
-                time.sleep(120)
+            update(runner_args.system_image_dir, runner_args.os_check,
+                   runner_args.target_id, runner_args.serial_num,
+                   runner_args.pave)
         else:
             runner_args.target_id = stack.enter_context(
                 create_emulator_from_args(runner_args))
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 4cb340de..5188cc5 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -1079,7 +1079,7 @@
   "java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java",
   "java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java",
   "java/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessage.java",
-  "java/src/org/chromium/chrome/browser/sync/ui/SyncErrorPromptUtils.java",
+  "java/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageImpressionTracker.java",
   "java/src/org/chromium/chrome/browser/sync/ui/SyncTrustedVaultProxyActivity.java",
   "java/src/org/chromium/chrome/browser/tab/AccessibilityVisibilityHandler.java",
   "java/src/org/chromium/chrome/browser/tab/AutofillSessionLifetimeController.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni
index 88ba691..df75116 100644
--- a/chrome/android/chrome_junit_test_java_sources.gni
+++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -243,7 +243,7 @@
   "junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerFlowTest.java",
   "junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerTest.java",
   "junit/src/org/chromium/chrome/browser/survey/SurveyHttpClientBridgeUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/sync/ui/SyncErrorPromptUtilsTest.java",
+  "junit/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageImpressionTrackerTest.java",
   "junit/src/org/chromium/chrome/browser/tab/RequestDesktopUtilsUnitTest.java",
   "junit/src/org/chromium/chrome/browser/tab/TabAttributesTest.java",
   "junit/src/org/chromium/chrome/browser/tab/TabBrowserControlsConstraintsHelperTest.java",
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacadeTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacadeTest.java
index a7b2e26..f43b21c 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacadeTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacadeTest.java
@@ -15,7 +15,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import org.chromium.base.Function;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -24,6 +23,8 @@
 import org.chromium.components.autofill_assistant.AssistantFeatures;
 import org.chromium.components.external_intents.ExternalNavigationDelegate.IntentToAutofillAllowingAppResult;
 
+import java.util.function.Function;
+
 /**
  * Tests autofill assistant facade.
  */
diff --git a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
index e937bd948..39581be4 100644
--- a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
+++ b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
@@ -15,7 +15,6 @@
 import androidx.annotation.Nullable;
 
 import org.chromium.base.Callback;
-import org.chromium.base.Function;
 import org.chromium.base.Log;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.ActivityTabProvider;
@@ -32,6 +31,8 @@
 import org.chromium.components.external_intents.ExternalNavigationDelegate.IntentToAutofillAllowingAppResult;
 import org.chromium.content_public.browser.WebContents;
 
+import java.util.function.Function;
+
 /** Facade for starting Autofill Assistant on a tab. */
 public class AutofillAssistantFacade {
     /** Used for logging. */
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
index 9a9ffba..db0d89f3 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
@@ -4,11 +4,15 @@
 
 package org.chromium.chrome.features.start_surface;
 
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
 import android.app.Activity;
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
 import android.widget.FrameLayout;
 
 import androidx.annotation.NonNull;
@@ -18,6 +22,7 @@
 import com.google.android.material.appbar.AppBarLayout;
 
 import org.chromium.base.ActivityState;
+import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.Log;
 import org.chromium.base.MathUtils;
@@ -152,6 +157,7 @@
     private boolean mIsInitPending;
 
     private boolean mIsSecondaryTaskInitPending;
+    private boolean mHasPrimaryTasksSurfaceCreated;
 
     // Listeners used by the contained surfaces (e.g., Explore) to listen to the scroll changes on
     // the main scrollable container of the start surface.
@@ -292,25 +298,27 @@
             // createSwipeRefreshLayout has to be called before creating any surface.
             createSwipeRefreshLayout();
             createAndSetStartSurface(excludeQueryTiles);
+            mHasPrimaryTasksSurfaceCreated = true;
         }
 
         TabSwitcher.Controller controller =
                 mTabSwitcher != null ? mTabSwitcher.getController() : mTasksSurface.getController();
         Runnable initializeMVTilesRunnable =
-                mTasksSurface == null ? null : mTasksSurface::initializeMVTiles;
-        View logoContainerView = mTasksSurface == null
-                ? null
-                : mTasksSurface.getView().findViewById(R.id.logo_container);
+                mHasPrimaryTasksSurfaceCreated ? mTasksSurface::initializeMVTiles : null;
+        View logoContainerView = mHasPrimaryTasksSurfaceCreated
+                ? mTasksSurface.getView().findViewById(R.id.logo_container)
+                : null;
         ViewGroup feedPlaceholderParentView =
-                mTasksSurface == null ? null : mTasksSurface.getBodyViewContainer();
+                mHasPrimaryTasksSurfaceCreated ? mTasksSurface.getBodyViewContainer() : null;
         mStartSurfaceMediator = new StartSurfaceMediator(controller, containerView,
                 mTabModelSelector, mPropertyModel,
-                mIsStartSurfaceEnabled ? this::initializeSecondaryTasksSurface : null,
+                mHasPrimaryTasksSurfaceCreated ? this::initializeSecondaryTasksSurface : null,
                 mIsStartSurfaceEnabled, mActivity, mBrowserControlsManager,
                 this::isActivityFinishingOrDestroyed, excludeQueryTiles,
                 startSurfaceOneshotSupplier, hadWarmStart, jankTracker, initializeMVTilesRunnable,
                 mParentTabSupplier, logoContainerView, backPressManager, feedPlaceholderParentView);
 
+        mayUpdateLayoutParams(ApiCompatibilityUtils.isInMultiWindowMode(mActivity));
         startSurfaceOneshotSupplier.set(this);
     }
 
@@ -705,6 +713,9 @@
         mTasksSurface.getView().setId(R.id.primary_tasks_surface_view);
         initializeOffsetChangedListener();
         addHeaderOffsetChangeListener(mOffsetChangedListenerToGenerateScrollEvents);
+        mTasksSurface.initHeaderDragListener();
+        mMultiWindowModeStateDispatcher.addObserver(
+                isInMultiWindowMode -> mayUpdateLayoutParams(isInMultiWindowMode));
 
         mTasksSurfacePropertyModelChangeProcessor =
                 PropertyModelChangeProcessor.create(mPropertyModel,
@@ -713,6 +724,29 @@
                         TasksSurfaceViewBinder::bind);
     }
 
+    private void mayUpdateLayoutParams(boolean isInMultiWindowMode) {
+        // Set the height of Start surface homepage's tasks_surface_body as wrap_content. We only
+        // update the tasks_surface_body in mTasksSurface since it's Start surface homepage while we
+        // don't change mSecondaryTasksSurface (grid tab switcher).
+        // If Feed placeholder is shown and we set body's height wrap_content, feed articles aren't
+        // rendered on emulator. Thus we need to add the check of whether the place holder is
+        // showing. See https://crbug.com/1208486.
+        if (!mHasPrimaryTasksSurfaceCreated || mStartSurfaceMediator.hasFeedPlaceholderShown()) {
+            return;
+        }
+
+        FrameLayout bodyViewLayout = (FrameLayout) mTasksSurface.getBodyViewContainer();
+        LayoutParams params = bodyViewLayout.getLayoutParams();
+        // Keeps the height to be "match_parent" in multiple window mode. When Feeds is disabled, it
+        // prevents the tasks_surface_body from scrolling above the toolbar and can't be scrolling
+        // down.
+        int heightToSet = isInMultiWindowMode ? MATCH_PARENT : WRAP_CONTENT;
+        if (params.height == heightToSet) return;
+
+        params.height = heightToSet;
+        bodyViewLayout.setLayoutParams(params);
+    }
+
     private TabSwitcher.Controller initializeSecondaryTasksSurface() {
         assert mIsStartSurfaceEnabled;
         assert mSecondaryTasksSurface == null;
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
index 5f11c6f..038c85f 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -54,6 +54,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.back_press.BackPressManager;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
+import org.chromium.chrome.browser.feed.FeedFeatures;
 import org.chromium.chrome.browser.feed.FeedReliabilityLogger;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.lens.LensEntryPoint;
@@ -64,7 +65,9 @@
 import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.Pref;
+import org.chromium.chrome.browser.preferences.PrefChangeRegistrar;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabLaunchType;
 import org.chromium.chrome.browser.tab.TabSelectionType;
@@ -82,6 +85,7 @@
 import org.chromium.components.browser_ui.widget.gesture.BackPressHandler;
 import org.chromium.components.embedder_support.util.UrlUtilities;
 import org.chromium.components.prefs.PrefService;
+import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.util.ColorUtils;
@@ -452,6 +456,20 @@
                     if (mLogoCoordinator != null) mLogoCoordinator.initWithNative();
                 }
             }
+
+            // If feed is disabled from user toggling off the header, Start surface will be set not
+            // scrollable, so we reset the scroll position to make it visible in the entire screen
+            // again.
+            PrefChangeRegistrar prefChangeRegistrar = new PrefChangeRegistrar();
+            prefChangeRegistrar.addObserver(Pref.ARTICLES_LIST_VISIBLE, () -> {
+                boolean isFeedVisible = FeedFeatures.isFeedEnabled()
+                        && UserPrefs.get(Profile.getLastUsedRegularProfile())
+                                   .getBoolean(Pref.ARTICLES_LIST_VISIBLE);
+                if (!isFeedVisible) {
+                    mPropertyModel.set(RESET_TASK_SURFACE_HEADER_SCROLL_POSITION, true);
+                    maybeDestroyFeedPlaceholder();
+                }
+            });
         }
 
         mFeedVisibilityPrefOnStartUp = prefService.getBoolean(Pref.ARTICLES_LIST_VISIBLE);
@@ -1003,6 +1021,10 @@
                 && !mHasFeedPlaceholderShown;
     }
 
+    boolean hasFeedPlaceholderShown() {
+        return mHasFeedPlaceholderShown;
+    }
+
     void setSecondaryTasksSurfaceController(
             TabSwitcher.Controller secondaryTasksSurfaceController) {
         mSecondaryTasksSurfaceController = secondaryTasksSurfaceController;
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurface.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurface.java
index 94a9131..341a918 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurface.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurface.java
@@ -130,4 +130,9 @@
      */
     @Nullable
     TabSwitcherCustomViewManager getTabSwitcherCustomViewManager();
+
+    /**
+     * Initialize the listener to decide whether the tasks view can be draggable or scrollable.
+     */
+    void initHeaderDragListener();
 }
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java
index b1f35862..88a83ac 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java
@@ -335,6 +335,11 @@
         return (mTabSwitcher != null) ? mTabSwitcher.getTabSwitcherCustomViewManager() : null;
     }
 
+    @Override
+    public void initHeaderDragListener() {
+        mView.initHeaderDragListener();
+    }
+
     /** Suggestions UI Delegate for constructing the TileGroup. */
     private class MostVisitedSuggestionsUiDelegate extends SuggestionsUiDelegateImpl {
         public MostVisitedSuggestionsUiDelegate(SuggestionsNavigationDelegate navigationDelegate,
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceProperties.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceProperties.java
index 28a872e8..f92b2305 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceProperties.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceProperties.java
@@ -87,7 +87,7 @@
     public static final PropertyModel.WritableIntPropertyKey TOP_TOOLBAR_PLACEHOLDER_HEIGHT =
             new PropertyModel.WritableIntPropertyKey();
     public static final PropertyModel
-            .WritableObjectPropertyKey RESET_TASK_SURFACE_HEADER_SCROLL_POSITION =
+            .WritableObjectPropertyKey<Boolean> RESET_TASK_SURFACE_HEADER_SCROLL_POSITION =
             new PropertyModel.WritableObjectPropertyKey<>(true /* skipEquality */);
     public static final PropertyKey[] ALL_KEYS = new PropertyKey[] {IS_FAKE_SEARCH_BOX_VISIBLE,
             IS_INCOGNITO, IS_INCOGNITO_DESCRIPTION_INITIALIZED, IS_INCOGNITO_DESCRIPTION_VISIBLE,
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksView.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksView.java
index c95140a..11646a1 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksView.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksView.java
@@ -52,6 +52,7 @@
     private FrameLayout mCarouselTabSwitcherContainer;
     private AppBarLayout mHeaderView;
     private ViewGroup mMvTilesContainerLayout;
+    private ViewGroup mBodyViewContainer;
     private SearchBoxCoordinator mSearchBoxCoordinator;
     private IncognitoDescriptionView mIncognitoDescriptionView;
     private View.OnClickListener mIncognitoDescriptionLearnMoreListener;
@@ -61,7 +62,7 @@
             CookieControlsEnforcement.NO_ENFORCEMENT;
     private View.OnClickListener mIncognitoCookieControlsIconClickListener;
     private UiConfig mUiConfig;
-    private boolean mIsIncognito;
+    private int mContentHeight;
 
     /** Default constructor needed to inflate via XML. */
     public TasksView(Context context, AttributeSet attrs) {
@@ -87,8 +88,7 @@
         mSearchBoxCoordinator = new SearchBoxCoordinator(getContext(), this);
 
         mHeaderView = (AppBarLayout) findViewById(R.id.task_surface_header);
-
-        forceHeaderScrollable();
+        mBodyViewContainer = findViewById(R.id.tasks_surface_body);
 
         mUiConfig = new UiConfig(this);
         setHeaderPadding();
@@ -120,7 +120,7 @@
     }
 
     ViewGroup getBodyViewContainer() {
-        return findViewById(R.id.tasks_surface_body);
+        return mBodyViewContainer;
     }
 
     /**
@@ -128,7 +128,7 @@
      * @param isVisible Whether it's visible.
      */
     void setSurfaceBodyVisibility(boolean isVisible) {
-        getBodyViewContainer().setVisibility(isVisible ? View.VISIBLE : View.GONE);
+        mBodyViewContainer.setVisibility(isVisible ? View.VISIBLE : View.GONE);
     }
 
     /**
@@ -206,7 +206,6 @@
         int hintTextColor = mContext.getColor(isIncognito ? R.color.locationbar_light_hint_text
                                                           : R.color.locationbar_dark_hint_text);
         mSearchBoxCoordinator.setSearchBoxHintColor(hintTextColor);
-        mIsIncognito = isIncognito;
     }
 
     /**
@@ -320,7 +319,7 @@
      * @param topMargin The top margin to set.
      */
     void setTasksSurfaceBodyTopMargin(int topMargin) {
-        MarginLayoutParams params = (MarginLayoutParams) getBodyViewContainer().getLayoutParams();
+        MarginLayoutParams params = (MarginLayoutParams) mBodyViewContainer.getLayoutParams();
         params.topMargin = topMargin;
     }
 
@@ -426,15 +425,25 @@
         mSearchBoxCoordinator.setLensButtonLeftMargin(lensButtonLeftMargin);
     }
 
-    private void forceHeaderScrollable() {
-        // TODO(https://crbug.com/1251632): Find out why scrolling was broken after
-        // crrev.com/c/3025127. Force the header view to be draggable as a workaround.
+    void initHeaderDragListener() {
+        mHeaderView.addOnLayoutChangeListener(
+                (view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+                    mContentHeight = mHeaderView.getMeasuredHeight()
+                            + mBodyViewContainer.getMeasuredHeight();
+                });
+
         CoordinatorLayout.LayoutParams params =
                 (CoordinatorLayout.LayoutParams) mHeaderView.getLayoutParams();
         AppBarLayout.Behavior behavior = new AppBarLayout.Behavior();
         behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
             @Override
             public boolean canDrag(AppBarLayout appBarLayout) {
+                if (mContentHeight <= mContext.getResources().getDisplayMetrics().heightPixels) {
+                    // Needs to reset the offset of the Start surface to prevent it stay in the
+                    // middle of the screen but can't scroll any more.
+                    resetScrollPosition();
+                    return false;
+                }
                 return true;
             }
         });
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartFeedTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartFeedTest.java
index 55a9204..992557d9 100644
--- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartFeedTest.java
+++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartFeedTest.java
@@ -5,22 +5,16 @@
 package org.chromium.chrome.features.start_surface;
 
 import static androidx.test.espresso.Espresso.onView;
-import static androidx.test.espresso.action.ViewActions.click;
 import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
 import static androidx.test.espresso.assertion.ViewAssertions.matches;
 import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
 import static androidx.test.espresso.matcher.ViewMatchers.withId;
-import static androidx.test.espresso.matcher.ViewMatchers.withText;
-
-import static org.hamcrest.CoreMatchers.allOf;
-import static org.hamcrest.Matchers.instanceOf;
 
 import static org.chromium.chrome.features.start_surface.StartSurfaceTestUtils.INSTANT_START_TEST_BASE_PARAMS;
+import static org.chromium.chrome.features.start_surface.StartSurfaceTestUtils.toggleFeedHeader;
 
 import android.view.View;
 
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.test.espresso.contrib.RecyclerViewActions;
 import androidx.test.espresso.matcher.BoundedMatcher;
 import androidx.test.filters.LargeTest;
 import androidx.test.filters.SmallTest;
@@ -76,8 +70,6 @@
     UiRestriction.RESTRICTION_TYPE_PHONE})
 public class InstantStartFeedTest {
     // clang-format on
-    private static final int ARTICLE_SECTION_HEADER_POSITION = 0;
-
     @Rule
     public JniMocker mJniMocker = new JniMocker();
 
@@ -149,7 +141,7 @@
 
         // Hide articles and verify that FEED_ARTICLES_LIST_VISIBLE and ARTICLES_LIST_VISIBLE are
         // both false.
-        toggleHeader(false);
+        toggleFeedHeader(false);
         CriteriaHelper.pollUiThread(() -> !ReturnToChromeUtil.getFeedArticlesVisibility());
         TestThreadUtils.runOnUiThreadBlocking(
                 ()
@@ -159,7 +151,7 @@
 
         // Show articles and verify that FEED_ARTICLES_LIST_VISIBLE and ARTICLES_LIST_VISIBLE are
         // both true.
-        toggleHeader(true);
+        toggleFeedHeader(true);
         CriteriaHelper.pollUiThread(ReturnToChromeUtil::getFeedArticlesVisibility);
         TestThreadUtils.runOnUiThreadBlocking(
                 ()
@@ -198,26 +190,6 @@
                 .check(matches(isDisplayed()));
     }
 
-    /**
-     * Toggles the header and checks whether the header has the right status.
-     *
-     * @param expanded Whether the header should be expanded.
-     */
-    private void toggleHeader(boolean expanded) {
-        onView(allOf(instanceOf(RecyclerView.class),
-                       withId(org.chromium.chrome.test.R.id.feed_stream_recycler_view)))
-                .perform(RecyclerViewActions.scrollToPosition(ARTICLE_SECTION_HEADER_POSITION));
-        onView(withId(org.chromium.chrome.test.R.id.header_menu)).perform(click());
-
-        onView(withText(expanded ? org.chromium.chrome.test.R.string.ntp_turn_on_feed
-                                 : org.chromium.chrome.test.R.string.ntp_turn_off_feed))
-                .perform(click());
-
-        onView(withText(expanded ? org.chromium.chrome.test.R.string.ntp_discover_on
-                                 : org.chromium.chrome.test.R.string.ntp_discover_off))
-                .check(matches(isDisplayed()));
-    }
-
     private static Matcher<View> matchesBackgroundAlpha(final int expectedAlpha) {
         return new BoundedMatcher<View, View>(View.class) {
             String mMessage;
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartToolbarTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartToolbarTest.java
index 4bae834..4f94efed 100644
--- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartToolbarTest.java
+++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartToolbarTest.java
@@ -140,7 +140,7 @@
         StartSurfaceTestUtils.waitForTabModel(cta);
         TabUiTestHelper.verifyTabModelTabCount(cta, 0, 0);
 
-        StartSurfaceTestUtils.scrollToolbar(cta);
+        StartSurfaceTestUtils.scrollToolbarAndVerify(cta);
 
         View surface = cta.findViewById(org.chromium.chrome.test.R.id.control_container);
         ChromeRenderTestRule.sanitize(surface);
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTabSwitcherTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTabSwitcherTest.java
index 9372a310..d5a7cc1 100644
--- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTabSwitcherTest.java
+++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTabSwitcherTest.java
@@ -162,13 +162,19 @@
             TabUiTestHelper.enterTabSwitcher(mActivityTestRule.getActivity());
         }
 
+        ChromeTabbedActivity cta = mActivityTestRule.getActivity();
         onViewWaiting(withId(R.id.secondary_tasks_surface_view));
 
+        // Grid tab switcher surface's height shouldn't be wrap_content. See crbug.com/1368437.
+        ViewGroup gts_surface_view = cta.findViewById(R.id.secondary_tasks_surface_view);
+        int surfaceHeight = gts_surface_view.getMeasuredHeight();
+        int bodyHeight = gts_surface_view.findViewById(R.id.tasks_surface_body).getMeasuredHeight();
+        Assert.assertEquals(surfaceHeight, bodyHeight);
+
         onViewWaiting(
                 allOf(withParent(withId(R.id.tasks_surface_body)), withId(R.id.tab_list_view)))
                 .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
-        LayoutTestUtils.waitForLayout(
-                mActivityTestRule.getActivity().getLayoutManager(), LayoutType.BROWSING);
+        LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.BROWSING);
     }
 
     @Test
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
index d9827b1..69e7c05 100644
--- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
+++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
@@ -30,6 +30,8 @@
 import static org.chromium.chrome.features.start_surface.StartSurfaceTestUtils.START_SURFACE_TEST_BASE_PARAMS;
 import static org.chromium.chrome.features.start_surface.StartSurfaceTestUtils.START_SURFACE_TEST_SINGLE_ENABLED_PARAMS;
 import static org.chromium.chrome.features.start_surface.StartSurfaceTestUtils.sClassParamsForStartSurfaceTest;
+import static org.chromium.chrome.features.start_surface.StartSurfaceTestUtils.scrollToolbar;
+import static org.chromium.chrome.features.start_surface.StartSurfaceTestUtils.scrollToolbarAndVerify;
 import static org.chromium.ui.test.util.ViewUtils.onViewWaiting;
 import static org.chromium.ui.test.util.ViewUtils.waitForStableView;
 import static org.chromium.ui.test.util.ViewUtils.waitForView;
@@ -626,7 +628,7 @@
         TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
 
         // Scroll the toolbar.
-        StartSurfaceTestUtils.scrollToolbar(cta);
+        StartSurfaceTestUtils.scrollToolbarAndVerify(cta);
         AppBarLayout taskSurfaceHeader = cta.findViewById(R.id.task_surface_header);
         assertNotEquals(taskSurfaceHeader.getBottom(), taskSurfaceHeader.getHeight());
 
@@ -718,6 +720,54 @@
     @MediumTest
     @Feature({"StartSurface"})
     // clang-format off
+    @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS
+            + "open_ntp_instead_of_start/false/open_start_as_homepage/true"
+            + "/show_last_active_tab_only/true"})
+    public void  testNotScrollableWhenContentIsShorterThanScreen() {
+        // clang-format on
+        if (!mImmediateReturn) {
+            StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity());
+        }
+
+        ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        StartSurfaceTestUtils.waitForOverviewVisible(
+                mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta);
+        StartSurfaceTestUtils.waitForDeferredStartup(mActivityTestRule);
+        int screenHeight = cta.getResources().getDisplayMetrics().heightPixels;
+
+        // If the content is shorter than the screen, the view shouldn't be scrolled.
+        onViewWaiting(allOf(withId(R.id.task_surface_header), isDisplayed()));
+        AppBarLayout taskSurfaceHeader = cta.findViewById(R.id.task_surface_header);
+        int contentHeight = taskSurfaceHeader.getMeasuredHeight()
+                + cta.findViewById(R.id.tasks_surface_body).getMeasuredHeight();
+        if (contentHeight <= screenHeight) {
+            checkContentIsNotScrollable(cta, taskSurfaceHeader);
+            return;
+        }
+
+        //  If the content is larger than the screen, scroll the toolbar.
+        scrollToolbarAndVerify(cta);
+
+        // Turning off Feed should reset Start surface's scroll position.
+        StartSurfaceTestUtils.toggleFeedHeader(false);
+        CriteriaHelper.pollInstrumentationThread(
+                () -> taskSurfaceHeader.getBottom() == taskSurfaceHeader.getHeight());
+        // If the content is shorter than the screen now without Feed, the view shouldn't be
+        // scrolled.
+        contentHeight = taskSurfaceHeader.getMeasuredHeight()
+                + cta.findViewById(R.id.tasks_surface_body).getMeasuredHeight();
+        if (contentHeight <= screenHeight) checkContentIsNotScrollable(cta, taskSurfaceHeader);
+
+        // Turning on Feed makes the content larger than the screen, the view should be
+        // scrollable again.
+        StartSurfaceTestUtils.toggleFeedHeader(true);
+        scrollToolbarAndVerify(cta);
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"StartSurface"})
+    // clang-format off
     @CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS})
     public void test_DoNotLoadLastSelectedTabOnStartup() {
         // clang-format on
@@ -748,6 +798,15 @@
         Assert.assertEquals(1, RenderProcessHostUtils.getCurrentRenderProcessCount());
     }
 
+    private void checkContentIsNotScrollable(
+            ChromeTabbedActivity cta, AppBarLayout taskSurfaceHeader) {
+        scrollToolbar(cta);
+        CriteriaHelper.pollInstrumentationThread(
+                ()
+                        -> taskSurfaceHeader.getBottom() == taskSurfaceHeader.getHeight()
+                        && cta.findViewById(R.id.tab_switcher_toolbar).getTranslationY() == 0);
+    }
+
     /**
      * @return Whether both features {@link ChromeFeatureList#INSTANT_START} and
      * {@link ChromeFeatureList#TAB_SWITCHER_ON_RETURN} are enabled.
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java
index fce0971..9173ff3 100644
--- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java
+++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java
@@ -11,9 +11,11 @@
 import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
 import static androidx.test.espresso.matcher.ViewMatchers.withId;
 import static androidx.test.espresso.matcher.ViewMatchers.withParent;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
 import static org.hamcrest.CoreMatchers.allOf;
 import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.Matchers.instanceOf;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -32,13 +34,18 @@
 import android.view.ViewGroup;
 
 import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView;
 import androidx.test.espresso.UiController;
 import androidx.test.espresso.ViewAction;
 import androidx.test.espresso.contrib.RecyclerViewActions;
 import androidx.test.espresso.matcher.ViewMatchers;
+import androidx.test.espresso.matcher.ViewMatchers.Visibility;
 import androidx.test.uiautomator.UiDevice;
 
+import com.google.android.material.appbar.AppBarLayout;
+
 import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
 import org.junit.Assert;
 
 import org.chromium.base.CommandLine;
@@ -96,6 +103,7 @@
  * Utility methods and classes for testing Start Surface.
  */
 public class StartSurfaceTestUtils {
+    private static final int ARTICLE_SECTION_HEADER_POSITION = 0;
     public static final String INSTANT_START_TEST_BASE_PARAMS =
             "force-fieldtrial-params=Study.Group:"
             + ReturnToChromeUtil.TAB_SWITCHER_ON_RETURN_MS_PARAM + "/0";
@@ -307,7 +315,8 @@
     }
 
     /**
-     * Scroll the start surface to make toolbar scrolled off.
+     * Try to scroll the start surface to make toolbar scrolled off. Notice that if Start surface is
+     * not scrollable, nothing will happen.
      * @param cta The ChromeTabbedActivity under test.
      */
     public static void scrollToolbar(ChromeTabbedActivity cta) {
@@ -321,15 +330,28 @@
 
         // Drag the Feed header title to scroll the toolbar to the top.
         int toY = -cta.getResources().getDimensionPixelOffset(R.dimen.toolbar_height_no_shadow);
+        onViewWaiting(allOf(withId(R.id.header_title), isDisplayed()));
         TestTouchUtils.dragCompleteView(InstrumentationRegistry.getInstrumentation(),
-                cta.findViewById(R.id.header_title), 0, 0, 0, toY, 1);
+                cta.findViewById(R.id.header_title), 0, 0, 0, toY, 10);
+    }
 
-        // The start surface toolbar should be scrolled up and not be displayed.
+    /**
+     * Scroll the start surface to make toolbar scrolled off and verify the corresponding UI
+     * changes.
+     * @param cta The ChromeTabbedActivity under test.
+     */
+    public static void scrollToolbarAndVerify(ChromeTabbedActivity cta) {
+        scrollToolbar(cta);
+
+        int toY = -cta.getResources().getDimensionPixelOffset(R.dimen.toolbar_height_no_shadow);
+        AppBarLayout taskSurfaceHeader = cta.findViewById(R.id.task_surface_header);
+
+        // The start surface toolbar and tasks surface header should be scrolled up.
         CriteriaHelper.pollInstrumentationThread(
                 ()
-                        -> cta.findViewById(R.id.tab_switcher_toolbar).getTranslationY()
-                        <= (float) -cta.getResources().getDimensionPixelOffset(
-                                R.dimen.toolbar_height_no_shadow));
+                        -> taskSurfaceHeader.getBottom() != taskSurfaceHeader.getHeight()
+                        && cta.findViewById(R.id.tab_switcher_toolbar).getTranslationY()
+                                <= (float) toY);
 
         // Toolbar layout view should show.
         onViewWaiting(withId(R.id.toolbar));
@@ -502,6 +524,26 @@
     }
 
     /**
+     * Toggles the Feed header and checks whether the header has the right status.
+     * @param expanded Whether the header should be expanded.
+     */
+    public static void toggleFeedHeader(boolean expanded) {
+        onView(Matchers.allOf(
+                       instanceOf(RecyclerView.class), withId(R.id.feed_stream_recycler_view)))
+                .perform(RecyclerViewActions.scrollToPosition(ARTICLE_SECTION_HEADER_POSITION));
+        onView(withId(R.id.header_menu)).perform(click());
+
+        onView(withText(expanded ? R.string.ntp_turn_on_feed : R.string.ntp_turn_off_feed))
+                .perform(click());
+
+        // There must be one and only one view with "Discover on/off" text being displayed.
+        onView(Matchers.allOf(
+                       withText(expanded ? R.string.ntp_discover_on : R.string.ntp_discover_off),
+                       withEffectiveVisibility(Visibility.VISIBLE)))
+                .check(matches(isDisplayed()));
+    }
+
+    /**
      * Create a file so that a TabState can be restored later.
      * @param tabId the Tab ID
      * @param encrypted for Incognito mode
diff --git a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinatorUnitTest.java b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinatorUnitTest.java
index 7e58ef45..e8c37ab 100644
--- a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinatorUnitTest.java
+++ b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinatorUnitTest.java
@@ -4,7 +4,12 @@
 
 package org.chromium.chrome.features.start_surface;
 
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
 import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.FrameLayout;
 
 import androidx.test.filters.MediumTest;
 
@@ -26,6 +31,7 @@
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.tasks.ReturnToChromeUtil;
 import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 
 /** Tests for {@link StartSurfaceCoordinator}. */
@@ -302,6 +308,33 @@
                 View.GONE, mCoordinator.getFeedSwipeRefreshLayoutForTesting().getVisibility());
     }
 
+    @Test
+    @DisableFeatures(ChromeFeatureList.INSTANT_START)
+    public void testSurfaceBodyHeightWhenPlaceholderIsNotShown() {
+        mCoordinator.setStartSurfaceState(StartSurfaceState.SHOWING_HOMEPAGE);
+        mCoordinator.showOverview(false);
+
+        Assert.assertFalse(mCoordinator.getMediatorForTesting().hasFeedPlaceholderShown());
+
+        FrameLayout layout =
+                (FrameLayout) mCoordinator.getPrimaryTasksSurface().getBodyViewContainer();
+        LayoutParams params = layout.getLayoutParams();
+        Assert.assertEquals(WRAP_CONTENT, params.height);
+    }
+
+    @Test
+    public void testSurfaceBodyHeightWhenPlaceholderIsShown() {
+        mCoordinator.setStartSurfaceState(StartSurfaceState.SHOWING_HOMEPAGE);
+        mCoordinator.showOverview(false);
+
+        Assert.assertTrue(mCoordinator.getMediatorForTesting().hasFeedPlaceholderShown());
+
+        FrameLayout layout =
+                (FrameLayout) mCoordinator.getPrimaryTasksSurface().getBodyViewContainer();
+        LayoutParams params = layout.getLayoutParams();
+        Assert.assertEquals(MATCH_PARENT, params.height);
+    }
+
     /**
      * Check that the next decision time is within |numOfDays| from now.
      * @param numOfDays Number of days to check.
diff --git a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
index 7645609..65fe022 100644
--- a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
+++ b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
@@ -88,6 +88,8 @@
 import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener;
 import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.PrefChangeRegistrar;
+import org.chromium.chrome.browser.preferences.PrefChangeRegistrarJni;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
@@ -182,7 +184,9 @@
     @Mock
     private LogoView mLogoView;
     @Mock
-    LogoBridge.Natives mLogoBridge;
+    LogoBridge.Natives mLogoBridgeJni;
+    @Mock
+    private PrefChangeRegistrar.Natives mPrefChangeRegistrarJni;
     @Mock
     private Profile mProfile;
     @Mock
@@ -253,8 +257,10 @@
         doReturn(mFeedReliabilityLogger)
                 .when(mExploreSurfaceCoordinator)
                 .getFeedReliabilityLogger();
-        mJniMocker.mock(LogoBridgeJni.TEST_HOOKS, mLogoBridge);
+
+        mJniMocker.mock(LogoBridgeJni.TEST_HOOKS, mLogoBridgeJni);
         doReturn(mLogoView).when(mLogoContainerView).findViewById(R.id.search_provider_logo);
+        mJniMocker.mock(PrefChangeRegistrarJni.TEST_HOOKS, mPrefChangeRegistrarJni);
     }
 
     @After
@@ -1425,7 +1431,7 @@
         mediator.showOverview(true);
 
         verify(mLogoContainerView).setVisibility(View.VISIBLE);
-        verify(mLogoBridge).getCurrentLogo(anyLong(), any(), any());
+        verify(mLogoBridgeJni).getCurrentLogo(anyLong(), any(), any());
         Assert.assertTrue(mediator.isLogoVisible());
     }
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
index 09a846c..e2bccd7 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
@@ -25,6 +25,7 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tasks.tab_management.TabListRecyclerView.RecyclerViewPosition;
 import org.chromium.chrome.browser.tasks.tab_management.TabSelectionEditorCoordinator.TabSelectionEditorController;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.tab_ui.R;
@@ -80,8 +81,9 @@
                     new SnackbarManager(activity, mDialogView.getSnackBarContainer(), null);
 
             mMediator = new TabGridDialogMediator(activity, this, mModel, tabModelSelector,
-                    tabCreatorManager, resetHandler, animationSourceViewProvider,
-                    shareDelegateSupplier, snackbarManager, mComponentName);
+                    tabCreatorManager, resetHandler, this::getRecyclerViewPosition,
+                    animationSourceViewProvider, shareDelegateSupplier, snackbarManager,
+                    mComponentName);
 
             // TODO(crbug.com/1031349) : Remove the inline mode logic here, make the constructor to
             // take in a mode parameter instead.
@@ -131,6 +133,11 @@
         }
     }
 
+    @NonNull
+    RecyclerViewPosition getRecyclerViewPosition() {
+        return mTabListCoordinator.getRecyclerViewPosition();
+    }
+
     @Nullable
     private TabSelectionEditorController getTabSelectionEditorController() {
         if (!TabUiFeatureUtilities.isTabGroupsAndroidContinuationEnabled(mContext)
@@ -144,7 +151,9 @@
                                                  : TabListCoordinator.TabListMode.GRID;
             mTabSelectionEditorCoordinator = new TabSelectionEditorCoordinator(mContext,
                     mDialogView.findViewById(R.id.dialog_container_view), mTabModelSelector,
-                    mTabContentManager, mode, mRootView, /*displayGroups=*/false);
+                    mTabContentManager, mTabListCoordinator::setRecyclerViewPosition, mode,
+                    mRootView,
+                    /*displayGroups=*/false);
         }
 
         return mTabSelectionEditorCoordinator.getController();
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
index 003fe64..c77e9bb 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
@@ -37,6 +37,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
 import org.chromium.chrome.browser.tasks.ReturnToChromeUtil;
 import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter;
+import org.chromium.chrome.browser.tasks.tab_management.TabListRecyclerView.RecyclerViewPosition;
 import org.chromium.chrome.browser.tasks.tab_management.TabSelectionEditorAction.ButtonType;
 import org.chromium.chrome.browser.tasks.tab_management.TabSelectionEditorAction.IconPosition;
 import org.chromium.chrome.browser.tasks.tab_management.TabSelectionEditorAction.ShowMode;
@@ -124,6 +125,7 @@
     private final TabCreatorManager mTabCreatorManager;
     private final DialogController mDialogController;
     private final TabSwitcherMediator.ResetHandler mTabSwitcherResetHandler;
+    private final Supplier<RecyclerViewPosition> mRecyclerViewPositionSupplier;
     private final AnimationSourceViewProvider mAnimationSourceViewProvider;
     private final DialogHandler mTabGridDialogHandler;
     private final Supplier<ShareDelegate> mShareDelegateSupplier;
@@ -142,6 +144,7 @@
     TabGridDialogMediator(Context context, DialogController dialogController, PropertyModel model,
             TabModelSelector tabModelSelector, TabCreatorManager tabCreatorManager,
             TabSwitcherMediator.ResetHandler tabSwitcherResetHandler,
+            Supplier<RecyclerViewPosition> recyclerViewPositionSupplier,
             AnimationSourceViewProvider animationSourceViewProvider,
             Supplier<ShareDelegate> shareDelegateSupplier, SnackbarManager snackbarManager,
             String componentName) {
@@ -151,6 +154,7 @@
         mTabCreatorManager = tabCreatorManager;
         mDialogController = dialogController;
         mTabSwitcherResetHandler = tabSwitcherResetHandler;
+        mRecyclerViewPositionSupplier = recyclerViewPositionSupplier;
         mAnimationSourceViewProvider = animationSourceViewProvider;
         mTabGridDialogHandler = new DialogHandler();
         mShareDelegateSupplier = shareDelegateSupplier;
@@ -302,8 +306,12 @@
                 // Setup dialog selection editor.
                 setupDialogSelectionEditor();
                 if (mTabSelectionEditorControllerSupplier.get() != null) {
-                    mTabSelectionEditorControllerSupplier.get().show(tabs);
-                    if (TabUiFeatureUtilities.isTabSelectionEditorV2Enabled(mContext)) {
+                    boolean v2Enabled =
+                            TabUiFeatureUtilities.isTabSelectionEditorV2Enabled(mContext);
+                    mTabSelectionEditorControllerSupplier.get().show(tabs,
+                            /*preSelectedTabCount=*/0,
+                            v2Enabled ? mRecyclerViewPositionSupplier.get() : null);
+                    if (v2Enabled) {
                         RecordUserAction.record("TabMultiSelectV2.OpenFromDialog");
                     } else {
                         RecordUserAction.record("TabMultiSelect.OpenFromDialog");
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
index 69e5e3f..80ec2e1 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
@@ -263,7 +263,8 @@
             @Override
             public void tabClosureUndone(Tab tab) {
                 if (!mIsTabGroupUiVisible) {
-                    resetTabStripWithRelatedTabsForId(tab.getId());
+                    // Reset with the current tab as the undone tab may be in the background.
+                    resetTabStripWithRelatedTabsForId(mTabModelSelector.getCurrentTab().getId());
                 }
             }
         };
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 f40dff70..f08bc7e 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
@@ -37,6 +37,7 @@
 import org.chromium.chrome.browser.tasks.ReturnToChromeUtil;
 import org.chromium.chrome.browser.tasks.pseudotab.PseudoTab;
 import org.chromium.chrome.browser.tasks.tab_management.TabListModel.CardProperties.ModelType;
+import org.chromium.chrome.browser.tasks.tab_management.TabListRecyclerView.RecyclerViewPosition;
 import org.chromium.chrome.browser.tasks.tab_management.TabProperties.UiType;
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.ui.modelutil.MVCListAdapter;
@@ -298,6 +299,21 @@
         return recyclerViewRect;
     }
 
+    /**
+     * @return the position and offset of the first visible element in the list.
+     */
+    @NonNull
+    RecyclerViewPosition getRecyclerViewPosition() {
+        return mRecyclerView.getRecyclerViewPosition();
+    }
+
+    /**
+     * @param recyclerViewPosition the position and offset to scroll the recycler view to.
+     */
+    void setRecyclerViewPosition(@NonNull RecyclerViewPosition recyclerViewPosition) {
+        mRecyclerView.setRecyclerViewPosition(recyclerViewPosition);
+    }
+
     void initWithNative(DynamicResourceLoader dynamicResourceLoader) {
         if (mIsInitialized) return;
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java
index 9529d24..8e702a5 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java
@@ -29,6 +29,7 @@
 import android.widget.ImageView;
 import android.widget.RelativeLayout;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.recyclerview.widget.DefaultItemAnimator;
@@ -495,6 +496,63 @@
     }
 
     /**
+     * A structure for holding the a recycler view position and offset.
+     */
+    public static class RecyclerViewPosition {
+        private int mPosition;
+        private int mOffset;
+
+        /**
+         * @param position The position of the first visible item in the recyclerView.
+         * @param offset The scroll offset of the recyclerView;
+         */
+        public RecyclerViewPosition(int position, int offset) {
+            mPosition = position;
+            mOffset = offset;
+        }
+
+        /**
+         * @return the position of the first visible item in the RecyclerView.
+         */
+        public int getPosition() {
+            return mPosition;
+        }
+
+        /**
+         * @return the offset from the first item in the RecyclerView.
+         */
+        public int getOffset() {
+            return mOffset;
+        }
+    }
+
+    /**
+     * @return the position and offset of the first visible element in the list.
+     */
+    @NonNull
+    RecyclerViewPosition getRecyclerViewPosition() {
+        GridLayoutManager layoutManager = (GridLayoutManager) getLayoutManager();
+        int position = layoutManager.findFirstVisibleItemPosition();
+        int offset = 0;
+        if (position != RecyclerView.NO_POSITION) {
+            View firstVisibleView = layoutManager.findViewByPosition(position);
+            if (firstVisibleView != null) {
+                offset = firstVisibleView.getTop();
+            }
+        }
+        return new RecyclerViewPosition(position, offset);
+    }
+
+    /**
+     * @param recyclerViewPosition the position and offset to scroll the recycler view to.
+     */
+    void setRecyclerViewPosition(@NonNull RecyclerViewPosition recyclerViewPosition) {
+        ((GridLayoutManager) getLayoutManager())
+                .scrollToPositionWithOffset(
+                        recyclerViewPosition.getPosition(), recyclerViewPosition.getOffset());
+    }
+
+    /**
      * This method finds out the index of the hovered tab's viewHolder in {@code recyclerView}.
      * @param recyclerView   The recyclerview that owns the tabs' viewHolders.
      * @param view           The view of the selected tab.
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorAction.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorAction.java
index 3af8566..9d20979f 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorAction.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorAction.java
@@ -115,7 +115,12 @@
         /**
          * Hides the selection editor.
          */
-        void hide();
+        void hideByAction();
+
+        /**
+         * Sync position of the client {@link TabListCoordinator}'s RecyclerView with the editor's.
+         */
+        void syncRecyclerViewPosition();
     }
 
     private ObserverList<ActionObserver> mObsevers = new ObserverList<>();
@@ -241,11 +246,18 @@
                 obs.preProcessSelectedTabs(tabs);
             }
         }
+        // When hiding by action it is expected that syncRecyclerViewPosition() is called before the
+        // action occurs. This is because an action may remove tabs so it needs to sync position
+        // before the removal of items occurs to ensure the positions match correctly for
+        // animations.
+        if (shouldHideEditorAfterAction()) {
+            mActionDelegate.syncRecyclerViewPosition();
+        }
         if (!performAction(tabs)) {
             return false;
         };
         if (shouldHideEditorAfterAction()) {
-            mActionDelegate.hide();
+            mActionDelegate.hideByAction();
             RecordUserAction.record("TabMultiSelectV2.ClosedAutomatically");
         }
         return true;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCoordinator.java
index 2e91689..73b73d9 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCoordinator.java
@@ -16,6 +16,7 @@
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
+import org.chromium.base.Callback;
 import org.chromium.base.TraceEvent;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.metrics.RecordUserAction;
@@ -25,6 +26,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tasks.pseudotab.PseudoTab;
 import org.chromium.chrome.browser.tasks.tab_management.TabListCoordinator.TabListMode;
+import org.chromium.chrome.browser.tasks.tab_management.TabListRecyclerView.RecyclerViewPosition;
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.components.browser_ui.widget.gesture.BackPressHandler;
 import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate;
@@ -50,9 +52,16 @@
          * Handles the reset event.
          * @param tabs List of {@link Tab}s to reset.
          * @param preSelectedCount First {@code preSelectedCount} {@code tabs} are pre-selected.
+         * @param recyclerViewPosition The state to preserve scroll position of the recycler view.
          * @param quickMode whether to use quick mode.
          */
-        void resetWithListOfTabs(@Nullable List<Tab> tabs, int preSelectedCount, boolean quickMode);
+        void resetWithListOfTabs(@Nullable List<Tab> tabs, int preSelectedCount,
+                @Nullable RecyclerViewPosition recyclerViewPosition, boolean quickMode);
+
+        /**
+         * Handles syncing the position of the outer {@link TabListCoordinator}'s RecyclerView.
+         */
+        void syncRecyclerViewPosition();
 
         /**
          * Handles cleanup.
@@ -65,18 +74,14 @@
      */
     interface TabSelectionEditorController extends BackPressHandler {
         /**
-         * Shows the TabSelectionEditor with the given {@link Tab}s.
-         * @param tabs List of {@link Tab}s to show.
-         */
-        void show(List<Tab> tabs);
-
-        /**
          * Shows the TabSelectionEditor with the given {@Link Tab}s, and the first
          * {@code preSelectedTabCount} tabs being selected.
          * @param tabs List of {@link Tab}s to show.
          * @param preSelectedTabCount Number of selected {@link Tab}s.
+         * @param recyclerViewPosition The state to preserve scroll position of the recycler view.
          */
-        void show(List<Tab> tabs, int preSelectedTabCount);
+        void show(List<Tab> tabs, int preSelectedTabCount,
+                @Nullable RecyclerViewPosition recyclerViewPosition);
 
         /**
          * Hides the TabSelectionEditor.
@@ -159,15 +164,18 @@
     private final PropertyModel mModel;
     private final PropertyModelChangeProcessor mTabSelectionEditorLayoutChangeProcessor;
     private final TabSelectionEditorMediator mTabSelectionEditorMediator;
+    private final Callback<RecyclerViewPosition> mClientTabListRecyclerViewPositionSetter;
     private MultiThumbnailCardProvider mMultiThumbnailCardProvider;
 
     public TabSelectionEditorCoordinator(Context context, ViewGroup parentView,
             TabModelSelector tabModelSelector, TabContentManager tabContentManager,
+            Callback<RecyclerViewPosition> clientTabListRecyclerViewPositionSetter,
             @TabListMode int mode, ViewGroup rootView, boolean displayGroups) {
         try (TraceEvent e = TraceEvent.scoped("TabSelectionEditorCoordinator.constructor")) {
             mContext = context;
             mParentView = parentView;
             mTabModelSelector = tabModelSelector;
+            mClientTabListRecyclerViewPositionSetter = clientTabListRecyclerViewPositionSetter;
             assert mode == TabListCoordinator.TabListMode.GRID
                     || mode == TabListCoordinator.TabListMode.LIST;
             assert !displayGroups
@@ -236,10 +244,27 @@
 
             ResetHandler resetHandler = new ResetHandler() {
                 @Override
-                public void resetWithListOfTabs(
-                        @Nullable List<Tab> tabs, int preSelectedCount, boolean quickMode) {
+                public void resetWithListOfTabs(@Nullable List<Tab> tabs, int preSelectedCount,
+                        @Nullable RecyclerViewPosition recyclerViewPosition, boolean quickMode) {
                     TabSelectionEditorCoordinator.this.resetWithListOfTabs(
                             tabs, preSelectedCount, quickMode);
+                    if (!ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_SELECTION_EDITOR_V2)
+                            || recyclerViewPosition == null) {
+                        return;
+                    }
+
+                    mTabListCoordinator.setRecyclerViewPosition(recyclerViewPosition);
+                }
+
+                @Override
+                public void syncRecyclerViewPosition() {
+                    if (!ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_SELECTION_EDITOR_V2)
+                            || mClientTabListRecyclerViewPositionSetter == null) {
+                        return;
+                    }
+
+                    mClientTabListRecyclerViewPositionSetter.onResult(
+                            mTabListCoordinator.getRecyclerViewPosition());
                 }
 
                 @Override
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorMediator.java
index cd7b9ca8..17be223 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorMediator.java
@@ -24,6 +24,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
+import org.chromium.chrome.browser.tasks.tab_management.TabListRecyclerView.RecyclerViewPosition;
 import org.chromium.chrome.browser.tasks.tab_management.TabSelectionEditorCoordinator.TabSelectionEditorNavigationProvider;
 import org.chromium.components.browser_ui.styles.ChromeColors;
 import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate;
@@ -194,14 +195,9 @@
      * {@link TabSelectionEditorCoordinator.TabSelectionEditorController} implementation.
      */
     @Override
-    public void show(List<Tab> tabs) {
-        show(tabs, 0);
-    }
-
-    @Override
-    public void show(List<Tab> tabs, int preSelectedTabCount) {
+    public void show(List<Tab> tabs, int preSelectedTabCount,
+            @Nullable RecyclerViewPosition recyclerViewPosition) {
         recordTimeSinceLastShown();
-
         // We don't call TabListCoordinator#prepareTabSwitcherView, since not all the logic (e.g.
         // requiring one tab to be selected) is applicable here.
         mTabListCoordinator.prepareTabGridView();
@@ -221,7 +217,8 @@
             mSelectionDelegate.setSelectedItems(preSelectedTabIds);
         }
 
-        mResetHandler.resetWithListOfTabs(tabs, preSelectedTabCount, /*quickMode=*/false);
+        mResetHandler.resetWithListOfTabs(
+                tabs, preSelectedTabCount, recyclerViewPosition, /*quickMode=*/false);
 
         mModel.set(TabSelectionEditorProperties.IS_VISIBLE, true);
     }
@@ -298,20 +295,42 @@
     }
 
     @Override
+    public void syncRecyclerViewPosition() {
+        mResetHandler.syncRecyclerViewPosition();
+    }
+
+    @Override
     public ObservableSupplier<Boolean> getHandleBackPressChangedSupplier() {
         return mBackPressChangedSupplier;
     }
 
     @Override
     public void hide() {
+        hideInternal(/*hiddenByAction=*/false);
+    }
+
+    @Override
+    public void hideByAction() {
+        hideInternal(/*hiddenByAction=*/true);
+    }
+
+    private void hideInternal(boolean hiddenByAction) {
         if (!isEditorVisible()) return;
 
         if (TabUiFeatureUtilities.isTabSelectionEditorV2Enabled(mContext)) {
             RecordUserAction.record("TabMultiSelectV2.Closed");
         }
+
+        // When hiding by action it is expected that syncRecyclerViewPosition() is called before the
+        // action occurs. This is because an action may remove tabs so sync position must happen
+        // first so the recyclerViewStat is valid due to the same number of items.
+        if (!hiddenByAction) {
+            syncRecyclerViewPosition();
+        }
         mTabListCoordinator.cleanupTabGridView();
         mVisibleTabs.clear();
-        mResetHandler.resetWithListOfTabs(null, 0, /*quickMode=*/false);
+        mResetHandler.resetWithListOfTabs(
+                null, /*preSelectedCount=*/0, /*recyclerViewPosition=*/null, /*quickMode=*/false);
         mModel.set(TabSelectionEditorProperties.IS_VISIBLE, false);
         if (ChromeFeatureList.sDiscardOccludedBitmaps.isEnabled()) {
             mResetHandler.postHiding();
@@ -330,7 +349,8 @@
             selectedTabIds.add(tab.getId());
         }
         mSelectionDelegate.setSelectedItems(selectedTabIds);
-        mResetHandler.resetWithListOfTabs(mVisibleTabs, mVisibleTabs.size(), /*quickMode=*/true);
+        mResetHandler.resetWithListOfTabs(mVisibleTabs, mVisibleTabs.size(),
+                /*recyclerViewPosition=*/null, /*quickMode=*/true);
     }
 
     @Override
@@ -338,7 +358,8 @@
         Set<Integer> selectedTabIds = mSelectionDelegate.getSelectedItems();
         selectedTabIds.clear();
         mSelectionDelegate.setSelectedItems(selectedTabIds);
-        mResetHandler.resetWithListOfTabs(mVisibleTabs, 0, /*quickMode=*/true);
+        mResetHandler.resetWithListOfTabs(mVisibleTabs, /*preSelectedCount=*/0,
+                /*recyclerViewPosition=*/null, /*quickMode=*/true);
     }
 
     @Override
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 67ac9165..3c55a6f 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
@@ -114,8 +114,8 @@
                 getEnablingThreshold(tabSuggestion),
                 getNavigationProvider(tabSuggestion, feedbackCallback));
 
-        mTabSelectionEditorController.show(
-                getTabListFromSuggestion(tabSuggestion), tabSuggestion.getTabsInfo().size());
+        mTabSelectionEditorController.show(getTabListFromSuggestion(tabSuggestion),
+                tabSuggestion.getTabsInfo().size(), /*recyclerViewPosition=*/null);
     }
 
     private String getActionString(TabSuggestion tabSuggestion) {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java
index 7a238d65..a745229 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java
@@ -22,8 +22,6 @@
 import org.chromium.components.browser_ui.widget.gesture.BackPressHandler;
 import org.chromium.ui.resources.dynamics.ViewResourceAdapter;
 
-import java.util.List;
-
 /**
  * Interface for the Tab Switcher.
  */
@@ -152,12 +150,6 @@
         ObservableSupplier<Boolean> isDialogVisibleSupplier();
 
         /**
-         * Shows the TabSelectionEditor.
-         */
-        @VisibleForTesting
-        default void showTabSelectionEditor(List<Tab> tabs) {}
-
-        /**
          * Returns the tab switcher type.
          */
         @TabSwitcherType
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
index 59bd0ae..1d03626 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
@@ -327,7 +327,9 @@
                                     mTabSelectionEditorCoordinator.getController().show(
                                             mTabModelSelector.getTabModelFilterProvider()
                                                     .getCurrentTabModelFilter()
-                                                    .getTabsWithNoOtherRelatedTabs());
+                                                    .getTabsWithNoOtherRelatedTabs(),
+                                            /*preSelectedTabCount=*/0,
+                                            /*recyclerViewPosition=*/null);
                                     RecordUserAction.record("MobileMenuGroupTabs");
                                     return true;
                                 } else if (id == R.id.menu_select_tabs) {
@@ -477,9 +479,9 @@
         // For tab switcher in carousel mode, the selection editor should still follow grid
         // style.
         int selectionEditorMode = mMode == TabListMode.CAROUSEL ? TabListMode.GRID : mMode;
-        mTabSelectionEditorCoordinator =
-                new TabSelectionEditorCoordinator(context, mCoordinatorView, mTabModelSelector,
-                        tabContentManager, selectionEditorMode, mRootView, /*displayGroups=*/false);
+        mTabSelectionEditorCoordinator = new TabSelectionEditorCoordinator(context,
+                mCoordinatorView, mTabModelSelector, tabContentManager, null, selectionEditorMode,
+                mRootView, /*displayGroups=*/false);
     }
 
     private void showTabSelectionEditorV2() {
@@ -488,8 +490,9 @@
         if (mTabSelectionEditorCoordinator == null) {
             int selectionEditorMode = mMode == TabListMode.CAROUSEL ? TabListMode.GRID : mMode;
             mTabSelectionEditorCoordinator = new TabSelectionEditorCoordinator(mActivity,
-                    mCoordinatorView, mTabModelSelector, mTabContentManager, selectionEditorMode,
-                    mRootView, /*displayGroups=*/true);
+                    mCoordinatorView, mTabModelSelector, mTabContentManager,
+                    mTabListCoordinator::setRecyclerViewPosition, selectionEditorMode, mRootView,
+                    /*displayGroups=*/true);
             mMediator.setTabSelectionEditorController(
                     mTabSelectionEditorCoordinator.getController());
         }
@@ -519,7 +522,8 @@
         for (int i = 0; i < list.getCount(); i++) {
             tabs.add(list.getTabAt(i));
         }
-        mTabSelectionEditorCoordinator.getController().show(tabs);
+        mTabSelectionEditorCoordinator.getController().show(
+                tabs, /*preSelectedTabCount=*/0, mTabListCoordinator.getRecyclerViewPosition());
         RecordUserAction.record("TabMultiSelectV2.OpenFromGrid");
     }
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
index dd2b478c..a4b7f1d 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
@@ -923,14 +923,6 @@
     }
 
     @Override
-    public void showTabSelectionEditor(List<Tab> tabs) {
-        if (mTabSelectionEditorController == null) {
-            return;
-        }
-        mTabSelectionEditorController.show(tabs);
-    }
-
-    @Override
     public void enableRecordingFirstMeaningfulPaint(long activityCreateTimeMs) {
         mFirstMeaningfulPaintRecorder = new FirstMeaningfulPaintRecorder(activityCreateTimeMs);
     }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java
index 03b36db1..c8c0509 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java
@@ -21,6 +21,7 @@
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.components.browser_ui.styles.ChromeColors;
 import org.chromium.components.browser_ui.styles.SemanticColorUtils;
+import org.chromium.ui.util.ColorUtils;
 
 /**
  * Utility class that provides theme related attributes for Tab UI.
@@ -64,11 +65,10 @@
      */
     public static @ColorInt int getTabStripBackgroundColor(Context context, boolean isIncognito) {
         if (TabUiFeatureUtilities.isTabStripFolioEnabled()) {
-            if (isIncognito) {
+            // Use black color for incognito and night mode for folio.
+            if (isIncognito || ColorUtils.inNightMode(context)) {
                 return Color.BLACK;
             }
-            // @TODO(crbug.com/1373630): May change the color for night theme after finalizing the
-            // spec
             return ChromeColors.getSurfaceColor(
                     context, org.chromium.chrome.R.dimen.default_elevation_2);
         } else if (TabUiFeatureUtilities.isTabStripDetachedEnabled()) {
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
index 071e7ee..ea5b91d 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
@@ -32,6 +32,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
 
 import static org.chromium.chrome.browser.flags.ChromeFeatureList.DISCARD_OCCLUDED_BITMAPS;
 import static org.chromium.chrome.browser.flags.ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS;
@@ -87,6 +88,8 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 import org.chromium.base.test.params.ParameterAnnotations;
 import org.chromium.base.test.params.ParameterizedRunner;
@@ -101,6 +104,7 @@
 import org.chromium.chrome.browser.compositor.layouts.Layout;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.homepage.HomepagePolicyManager;
 import org.chromium.chrome.browser.layouts.LayoutType;
 import org.chromium.chrome.browser.night_mode.ChromeNightModeTestUtils;
 import org.chromium.chrome.browser.tasks.pseudotab.TabAttributeCache;
@@ -122,6 +126,7 @@
 import org.chromium.ui.test.util.NightModeTestUtils;
 import org.chromium.ui.test.util.UiDisableIf;
 import org.chromium.ui.util.ColorUtils;
+import org.chromium.url.GURL;
 
 import java.util.concurrent.ExecutionException;
 
@@ -156,6 +161,9 @@
                             ChromeRenderTestRule.Component.UI_BROWSER_MOBILE_TAB_SWITCHER_GRID)
                     .build();
 
+    @Mock
+    private HomepagePolicyManager mHomepagePolicyManager;
+
     @BeforeClass
     public static void setUpBeforeActivityLaunched() {
         ChromeNightModeTestUtils.setUpNightModeBeforeChromeActivityLaunched();
@@ -171,6 +179,7 @@
 
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
         Intents.init();
         TabUiFeatureUtilities.setTabManagementModuleSupportedForTesting(true);
         mActivityTestRule.startMainActivityOnBlankPage();
@@ -1125,7 +1134,7 @@
     @MediumTest
     @DisableIf.Device(type = UiDisableIf.TABLET)
     @Features.EnableFeatures({ChromeFeatureList.TAB_SELECTION_EDITOR_V2})
-    public void testStripDialog_TabSelectionEditorV2CloseAll() throws Exception {
+    public void testStripDialog_TabSelectionEditorV2CloseAll_NoCustomHomepage() throws Exception {
         ChromeTabbedActivity cta = mActivityTestRule.getActivity();
         // Create a tab group with 2 tabs.
         createTabs(cta, false, 2);
@@ -1157,7 +1166,55 @@
                 .clickToolbarMenuButton()
                 .clickToolbarMenuItem("Close tabs");
 
+        // Rather than destroying the activity the GTS should be showing.
+        verifyTabSwitcherCardCount(cta, 0);
+    }
+
+    @Test
+    @MediumTest
+    @DisableIf.Device(type = UiDisableIf.TABLET)
+    @Features.EnableFeatures({ChromeFeatureList.TAB_SELECTION_EDITOR_V2})
+    public void testStripDialog_TabSelectionEditorV2CloseAll_CustomHomepage() throws Exception {
+        GURL url = new GURL(mActivityTestRule.getEmbeddedTestServerRule().getServer().getURL(
+                "/chrome/test/data/android/google.html"));
+        when(mHomepagePolicyManager.isHomepageLocationPolicyEnabled()).thenReturn(true);
+        when(mHomepagePolicyManager.getHomepagePreference()).thenReturn(url);
+
+        HomepagePolicyManager.setInstanceForTests(mHomepagePolicyManager);
+        ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        // Create a tab group with 2 tabs.
+        createTabs(cta, false, 2);
+        enterTabSwitcher(cta);
+        verifyTabSwitcherCardCount(cta, 2);
+        mergeAllNormalTabsToAGroup(cta);
+        verifyTabSwitcherCardCount(cta, 1);
+
+        // Enter tab switcher and select first tab.
+        openDialogFromTabSwitcherAndVerify(cta, 2, null);
+        clickFirstTabInDialog(cta);
+        waitForDialogHidingAnimation(cta);
+
+        // Make sure tab strip is showing.
+        CriteriaHelper.pollUiThread(()
+                                            -> mActivityTestRule.getActivity()
+                                                       .getBrowserControlsManager()
+                                                       .getBottomControlOffset()
+                        == 0);
+        waitForView(allOf(withId(R.id.toolbar_left_button), isCompletelyDisplayed()));
+
+        // Test opening dialog from strip and from tab switcher.
+        openDialogFromStripAndVerify(cta, 2, null);
+        openSelectionEditorV2AndVerify(cta, 2);
+
+        // Close two tabs.
+        mSelectionEditorRobot.actionRobot.clickItemAtAdapterPosition(0)
+                .clickItemAtAdapterPosition(1)
+                .clickToolbarMenuButton()
+                .clickToolbarMenuItem("Close tabs");
+
+        // With a custom homepage exit the app.
         CriteriaHelper.pollUiThread(() -> cta.isDestroyed());
+        HomepagePolicyManager.setInstanceForTests(null);
     }
 
     @Test
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java
index 9c6c3a05..a14312e 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java
@@ -21,6 +21,11 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.isNotNull;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 
 import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_LOW_END_DEVICE;
 import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE;
@@ -49,9 +54,11 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
 import org.chromium.base.BaseSwitches;
+import org.chromium.base.Callback;
 import org.chromium.base.GarbageCollectionTestUtils;
 import org.chromium.base.SysUtils;
 import org.chromium.base.test.util.Batch;
@@ -72,6 +79,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter;
+import org.chromium.chrome.browser.tasks.tab_management.TabListRecyclerView.RecyclerViewPosition;
 import org.chromium.chrome.browser.tasks.tab_management.TabSelectionEditorAction.ButtonType;
 import org.chromium.chrome.browser.tasks.tab_management.TabSelectionEditorAction.IconPosition;
 import org.chromium.chrome.browser.tasks.tab_management.TabSelectionEditorAction.ShowMode;
@@ -132,6 +140,9 @@
                     .setDescription("TabSelectionEditorV2 UI Polish")
                     .build();
 
+    @Mock
+    private Callback<RecyclerViewPosition> mSetRecyclerViewPosition;
+
     private TabSelectionEditorTestingRobot mRobot = new TabSelectionEditorTestingRobot();
 
     private TabModelSelector mTabModelSelector;
@@ -153,7 +164,8 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             mTabSelectionEditorCoordinator = new TabSelectionEditorCoordinator(
                     sActivityTestRule.getActivity(), mParentView, mTabModelSelector,
-                    sActivityTestRule.getActivity().getTabContentManager(), getMode(),
+                    sActivityTestRule.getActivity().getTabContentManager(),
+                    mSetRecyclerViewPosition, getMode(),
                     sActivityTestRule.getActivity().getCompositorViewHolderForTesting(),
                     displayGroups);
 
@@ -242,7 +254,7 @@
         prepareBlankTab(2, false);
         List<Tab> tabs = getTabsInCurrentTabModel();
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> mTabSelectionEditorController.show(tabs));
+        showSelectionEditor(tabs);
 
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible()
                 .verifyToolbarActionButtonDisabled()
@@ -259,7 +271,7 @@
         prepareBlankTab(2, false);
         List<Tab> tabs = getTabsInCurrentTabModel();
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> mTabSelectionEditorController.show(tabs));
+        showSelectionEditor(tabs);
 
         mRobot.resultRobot.verifyItemNotSelectedAtAdapterPosition(0);
 
@@ -284,12 +296,36 @@
         prepareBlankTab(2, false);
         List<Tab> tabs = getTabsInCurrentTabModel();
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> mTabSelectionEditorController.show(tabs));
+        showSelectionEditor(tabs);
 
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
 
         mRobot.actionRobot.clickToolbarNavigationButton();
         mRobot.resultRobot.verifyTabSelectionEditorIsHidden();
+
+        verify(mSetRecyclerViewPosition, never()).onResult(any());
+    }
+
+    @Test
+    @MediumTest
+    // clang-format off
+    @Features.EnableFeatures({ChromeFeatureList.TAB_SELECTION_EDITOR_V2,
+        ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID + "<Study"})
+    @CommandLineFlags.Add({"force-fieldtrials=Study/Group",
+        "force-fieldtrial-params=Study.Group:enable_launch_polish/true"})
+    public void testToolbarNavigationButtonHideTabSelectionEditorV2() {
+        // clang-format on
+        prepareBlankTab(2, false);
+        List<Tab> tabs = getTabsInCurrentTabModel();
+
+        showSelectionEditor(tabs);
+
+        mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
+
+        mRobot.actionRobot.clickToolbarNavigationButton();
+        mRobot.resultRobot.verifyTabSelectionEditorIsHidden();
+
+        verify(mSetRecyclerViewPosition, times(1)).onResult(isNotNull());
     }
 
     @Test
@@ -298,7 +334,7 @@
         prepareBlankTab(2, false);
         List<Tab> tabs = getTabsInCurrentTabModel();
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> mTabSelectionEditorController.show(tabs));
+        showSelectionEditor(tabs);
 
         mRobot.resultRobot.verifyToolbarActionButtonDisabled()
                 .verifyToolbarActionButtonWithResourceId(R.string.tab_selection_editor_group);
@@ -320,7 +356,7 @@
         prepareBlankTab(2, false);
         List<Tab> tabs = getTabsInCurrentTabModel();
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> mTabSelectionEditorController.show(tabs));
+        showSelectionEditor(tabs);
 
         mRobot.resultRobot.verifyToolbarActionButtonWithResourceId(
                 R.string.tab_selection_editor_group);
@@ -331,6 +367,7 @@
 
         mRobot.resultRobot.verifyTabSelectionEditorIsHidden();
 
+        verify(mSetRecyclerViewPosition, never()).onResult(any());
         // TODO(1021803): verify the undo snack after the bug is resolved.
         // verifyUndoSnackbarWithTextIsShown(sActivityTestRule.getActivity().getString(
         //     R.string.undo_bar_group_tabs_message, 2));
@@ -345,7 +382,7 @@
         List<Tab> tabs = getTabsInCurrentTabModel();
         TabUiTestHelper.enterTabSwitcher(cta);
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> mTabSelectionEditorController.show(tabs));
+        showSelectionEditor(tabs);
 
         mRobot.resultRobot.verifyToolbarActionButtonWithResourceId(
                 R.string.tab_selection_editor_group);
@@ -372,8 +409,8 @@
             mTabSelectionEditorController.configureToolbar("Test",
                     R.plurals.accessibility_tab_selection_editor_group_button, null,
                     enableThreshold, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
 
         mRobot.resultRobot.verifyToolbarActionButtonDisabled().verifyToolbarActionButtonWithText(
                 "Test");
@@ -403,8 +440,8 @@
                     ShowMode.MENU_ONLY, ButtonType.TEXT, IconPosition.START));
 
             mTabSelectionEditorController.configureToolbarWithMenuItems(actions, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
 
         final int closeId = R.id.tab_selection_editor_close_menu_item;
         final int groupId = R.id.tab_selection_editor_group_menu_item;
@@ -446,14 +483,17 @@
                     ShowMode.IF_ROOM, ButtonType.TEXT, IconPosition.START));
 
             mTabSelectionEditorController.configureToolbarWithMenuItems(actions, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
 
         final int closeId = R.id.tab_selection_editor_close_menu_item;
         mRobot.resultRobot.verifyToolbarActionViewDisabled(closeId);
 
         mRobot.actionRobot.clickItemAtAdapterPosition(0).clickToolbarActionView(closeId);
 
+        mRobot.resultRobot.verifyTabSelectionEditorIsHidden();
+        verify(mSetRecyclerViewPosition, times(2)).onResult(isNotNull());
+
         assertEquals(1, getTabsInCurrentTabModel().size());
     }
 
@@ -473,8 +513,8 @@
                     ShowMode.IF_ROOM, ButtonType.TEXT, IconPosition.START));
 
             mTabSelectionEditorController.configureToolbarWithMenuItems(actions, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
 
         final int closeId = R.id.tab_selection_editor_close_menu_item;
         mRobot.resultRobot.verifyToolbarActionViewDisabled(closeId);
@@ -511,8 +551,8 @@
                     ShowMode.IF_ROOM, ButtonType.TEXT, IconPosition.START));
 
             mTabSelectionEditorController.configureToolbarWithMenuItems(actions, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
 
         final int groupId = R.id.tab_selection_editor_group_menu_item;
         mRobot.resultRobot.verifyToolbarActionViewDisabled(groupId);
@@ -558,8 +598,8 @@
                     ShowMode.IF_ROOM, ButtonType.TEXT, IconPosition.START));
 
             mTabSelectionEditorController.configureToolbarWithMenuItems(actions, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
 
         final int groupId = R.id.tab_selection_editor_group_menu_item;
         mRobot.resultRobot.verifyToolbarActionViewDisabled(groupId);
@@ -607,8 +647,9 @@
                     ShowMode.MENU_ONLY, ButtonType.TEXT, IconPosition.START));
 
             mTabSelectionEditorController.configureToolbarWithMenuItems(actions, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
+
         mRobot.actionRobot.clickToolbarMenuButton().clickToolbarMenuItem("Close tabs");
         Espresso.pressBack();
 
@@ -640,8 +681,8 @@
                     ShowMode.IF_ROOM, ButtonType.ICON_AND_TEXT, IconPosition.END));
 
             mTabSelectionEditorController.configureToolbarWithMenuItems(actions, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
 
         final int shareId = R.id.tab_selection_editor_share_menu_item;
         mRobot.resultRobot.verifyToolbarActionViewWithText(shareId, "Share tabs");
@@ -688,8 +729,8 @@
                     ShowMode.IF_ROOM, ButtonType.ICON_AND_TEXT, IconPosition.END));
 
             mTabSelectionEditorController.configureToolbarWithMenuItems(actions, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
 
         mRobot.actionRobot.clickItemAtAdapterPosition(0).clickItemAtAdapterPosition(2);
 
@@ -732,8 +773,8 @@
                     ShowMode.IF_ROOM, ButtonType.ICON_AND_TEXT, IconPosition.END));
 
             mTabSelectionEditorController.configureToolbarWithMenuItems(actions, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
 
         mRobot.actionRobot.clickItemAtAdapterPosition(1).clickItemAtAdapterPosition(2);
 
@@ -781,8 +822,8 @@
                     ShowMode.IF_ROOM, ButtonType.ICON_AND_TEXT, IconPosition.END));
 
             mTabSelectionEditorController.configureToolbarWithMenuItems(actions, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
 
         mRobot.actionRobot.clickItemAtAdapterPosition(0)
                 .clickItemAtAdapterPosition(1)
@@ -813,8 +854,8 @@
                     ShowMode.IF_ROOM, ButtonType.ICON_AND_TEXT, IconPosition.END));
 
             mTabSelectionEditorController.configureToolbarWithMenuItems(actions, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
 
         final int shareId = R.id.tab_selection_editor_share_menu_item;
         mRobot.actionRobot.clickItemAtAdapterPosition(0).clickItemAtAdapterPosition(1);
@@ -837,8 +878,8 @@
                     IconPosition.END, /*isIncognito=*/false));
 
             mTabSelectionEditorController.configureToolbarWithMenuItems(actions, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
 
         final int selectionId = R.id.tab_selection_editor_selection_menu_item;
         mRobot.resultRobot.verifyToolbarActionViewEnabled(selectionId)
@@ -867,7 +908,9 @@
         List<Tab> tabs = getTabsInCurrentTabModel();
         int preSelectedTabCount = 1;
         TestThreadUtils.runOnUiThreadBlocking(
-                () -> mTabSelectionEditorController.show(tabs, preSelectedTabCount));
+                ()
+                        -> mTabSelectionEditorController.show(
+                                tabs, preSelectedTabCount, /*recyclerViewPosition=*/null));
 
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible()
                 .verifyToolbarActionButtonDisabled()
@@ -888,7 +931,9 @@
         List<Tab> tabs = getTabsInCurrentTabModel();
 
         TestThreadUtils.runOnUiThreadBlocking(
-                () -> mTabSelectionEditorController.show(tabs, preSelectedTabCount));
+                ()
+                        -> mTabSelectionEditorController.show(
+                                tabs, preSelectedTabCount, /*recyclerViewPosition=*/null));
 
         mRobot.resultRobot.verifyToolbarSelectionText("6 selected")
                 .verifyHasItemViewTypeAtAdapterPosition(
@@ -903,7 +948,9 @@
         List<Tab> tabs = getTabsInCurrentTabModel();
         int preSelectedTabCount = 1;
         TestThreadUtils.runOnUiThreadBlocking(
-                () -> mTabSelectionEditorController.show(tabs, preSelectedTabCount));
+                ()
+                        -> mTabSelectionEditorController.show(
+                                tabs, preSelectedTabCount, /*recyclerViewPosition=*/null));
 
         mRobot.resultRobot.verifyDividerNotClickableNotFocusable();
     }
@@ -920,7 +967,7 @@
         TabUiTestHelper.enterTabSwitcher(sActivityTestRule.getActivity());
         TabUiTestHelper.verifyAllTabsHaveThumbnail(
                 sActivityTestRule.getActivity().getCurrentTabModel());
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mTabSelectionEditorController.show(tabs); });
+        showSelectionEditor(tabs);
 
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
 
@@ -940,7 +987,7 @@
         TabUiTestHelper.enterTabSwitcher(sActivityTestRule.getActivity());
         TabUiTestHelper.verifyAllTabsHaveThumbnail(
                 sActivityTestRule.getActivity().getCurrentTabModel());
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mTabSelectionEditorController.show(tabs); });
+        showSelectionEditor(tabs);
 
         mRobot.actionRobot.clickItemAtAdapterPosition(0);
 
@@ -963,8 +1010,10 @@
         TabUiTestHelper.enterTabSwitcher(sActivityTestRule.getActivity());
         TabUiTestHelper.verifyAllTabsHaveThumbnail(
                 sActivityTestRule.getActivity().getCurrentTabModel());
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { mTabSelectionEditorController.show(tabs, preSelectedTabCount); });
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mTabSelectionEditorController.show(
+                    tabs, preSelectedTabCount, /*recyclerViewPosition=*/null);
+        });
 
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
 
@@ -985,8 +1034,10 @@
         TabUiTestHelper.enterTabSwitcher(sActivityTestRule.getActivity());
         TabUiTestHelper.verifyAllTabsHaveThumbnail(
                 sActivityTestRule.getActivity().getCurrentTabModel());
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { mTabSelectionEditorController.show(tabs, preSelectedTabCount); });
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mTabSelectionEditorController.show(
+                    tabs, preSelectedTabCount, /*recyclerViewPosition=*/null);
+        });
 
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
 
@@ -1007,8 +1058,10 @@
         TabUiTestHelper.enterTabSwitcher(sActivityTestRule.getActivity());
         TabUiTestHelper.verifyAllTabsHaveThumbnail(
                 sActivityTestRule.getActivity().getCurrentTabModel());
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { mTabSelectionEditorController.show(tabs, preSelectedTabCount); });
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mTabSelectionEditorController.show(
+                    tabs, preSelectedTabCount, /*recyclerViewPosition=*/null);
+        });
 
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
 
@@ -1032,8 +1085,8 @@
                     IconPosition.END, /*isIncognito=*/false));
 
             mTabSelectionEditorController.configureToolbarWithMenuItems(actions, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
 
         final int selectionId = R.id.tab_selection_editor_selection_menu_item;
         mRobot.resultRobot.verifyToolbarActionViewEnabled(selectionId)
@@ -1072,7 +1125,7 @@
         prepareBlankTab(2, false);
         List<Tab> tabs = getTabsInCurrentTabModel();
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> mTabSelectionEditorController.show(tabs));
+        showSelectionEditor(tabs);
 
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
 
@@ -1090,7 +1143,7 @@
         prepareBlankTab(2, false);
         List<Tab> tabs = getTabsInCurrentTabModel();
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> mTabSelectionEditorController.show(tabs));
+        showSelectionEditor(tabs);
 
         mRobot.actionRobot.clickItemAtAdapterPosition(0);
 
@@ -1109,7 +1162,7 @@
         prepareBlankTab(2, false);
         List<Tab> tabs = getTabsInCurrentTabModel();
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> mTabSelectionEditorController.show(tabs));
+        showSelectionEditor(tabs);
 
         mRobot.actionRobot.clickItemAtAdapterPosition(0);
         mRobot.resultRobot.verifyToolbarActionButtonDisabled().verifyTabSelectionEditorIsVisible();
@@ -1141,7 +1194,7 @@
         List<Tab> tabs = getTabsInCurrentTabModel();
         String expectedAccessibilityString = "Select about:blank tab";
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> mTabSelectionEditorController.show(tabs));
+        showSelectionEditor(tabs);
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
 
         // Test deselected tab
@@ -1164,8 +1217,8 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             mTabSelectionEditorController.configureToolbar("Group",
                     R.plurals.accessibility_tab_selection_editor_group_button, null, 2, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
 
         Button actionButton =
@@ -1195,8 +1248,8 @@
                     ShowMode.MENU_ONLY, ButtonType.TEXT, IconPosition.START));
 
             mTabSelectionEditorController.configureToolbarWithMenuItems(actions, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
 
         mRobot.actionRobot.clickToolbarMenuButton();
@@ -1226,8 +1279,8 @@
                     ShowMode.MENU_ONLY, ButtonType.TEXT, IconPosition.START));
 
             mTabSelectionEditorController.configureToolbarWithMenuItems(actions, null);
-            mTabSelectionEditorController.show(tabs);
         });
+        showSelectionEditor(tabs);
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
 
         final int closeId = R.id.tab_selection_editor_close_menu_item;
@@ -1265,7 +1318,7 @@
         // clang-format on
         prepareBlankTab(2, false);
         List<Tab> tabs = getTabsInCurrentTabModel();
-        TestThreadUtils.runOnUiThreadBlocking(() -> mTabSelectionEditorController.show(tabs));
+        showSelectionEditor(tabs);
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
 
         assertEquals("Multi-select mode", mTabSelectionEditorLayout.getContentDescription());
@@ -1281,7 +1334,7 @@
         // clang-format on
         prepareBlankTab(2, false);
         List<Tab> tabs = getTabsInCurrentTabModel();
-        TestThreadUtils.runOnUiThreadBlocking(() -> mTabSelectionEditorController.show(tabs));
+        showSelectionEditor(tabs);
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
 
         assertEquals("Hide multi-select mode",
@@ -1298,13 +1351,13 @@
         // clang-format on
         prepareBlankTab(2, false);
         List<Tab> tabs = getTabsInCurrentTabModel();
-        TestThreadUtils.runOnUiThreadBlocking(() -> mTabSelectionEditorController.show(tabs));
+        showSelectionEditor(tabs);
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
 
         TestThreadUtils.runOnUiThreadBlockingNoException(
                 () -> mTabSelectionEditorController.handleBackPressed());
         mRobot.resultRobot.verifyTabSelectionEditorIsHidden();
-        TestThreadUtils.runOnUiThreadBlocking(() -> mTabSelectionEditorController.show(tabs));
+        showSelectionEditor(tabs);
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
     }
 
@@ -1321,7 +1374,7 @@
 
         Map<View, Integer> initialValues = getParentViewAccessibilityImportanceMap();
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mTabSelectionEditorController.show(tabs); });
+        showSelectionEditor(tabs);
         mRobot.resultRobot.verifyTabSelectionEditorIsVisible();
         ViewGroup parentView = (ViewGroup) mTabSelectionEditorLayout.getParent();
         verifyBackgroundViewAccessibilityImportance(parentView, true, initialValues);
@@ -1385,4 +1438,11 @@
 
         return tabs;
     }
+
+    private void showSelectionEditor(List<Tab> tabs) {
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mTabSelectionEditorController.show(
+                    tabs, /*preSelectedTabCount=*/0, /*recyclerViewPosition=*/null);
+        });
+    }
 }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
index 568b954..73b8ebeb 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
@@ -18,6 +18,7 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
@@ -43,6 +44,7 @@
 import org.chromium.base.Callback;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.share.ShareDelegate;
@@ -59,6 +61,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl;
 import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter;
+import org.chromium.chrome.browser.tasks.tab_management.TabListRecyclerView.RecyclerViewPosition;
 import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.tab_ui.R;
@@ -135,6 +138,8 @@
     ObservableSupplier<ShareDelegate> mShareDelegateSupplier;
     @Mock
     SnackbarManager mSnackbarManager;
+    @Mock
+    Supplier<RecyclerViewPosition> mRecyclerViewPositionSupplier;
     @Captor
     ArgumentCaptor<TabModelObserver> mTabModelObserverCaptor;
 
@@ -183,6 +188,7 @@
         doReturn(mTabCreator).when(mTabCreatorManager).getTabCreator(anyBoolean());
         doReturn(mEditable).when(mTitleTextView).getText();
         doReturn(CUSTOMIZED_DIALOG_TITLE).when(mEditable).toString();
+        doReturn(null).when(mRecyclerViewPositionSupplier).get();
 
         if (!TabUiFeatureUtilities.isTabGroupsAndroidContinuationEnabled(
                     ContextUtils.getApplicationContext())
@@ -192,9 +198,10 @@
         }
         mActivity = Robolectric.buildActivity(TestActivity.class).get();
         mModel = new PropertyModel(TabGridPanelProperties.ALL_KEYS);
-        mMediator = new TabGridDialogMediator(mActivity, mDialogController, mModel,
-                mTabModelSelector, mTabCreatorManager, mTabSwitcherResetHandler,
-                mAnimationSourceViewProvider, mShareDelegateSupplier, mSnackbarManager, "");
+        mMediator =
+                new TabGridDialogMediator(mActivity, mDialogController, mModel, mTabModelSelector,
+                        mTabCreatorManager, mTabSwitcherResetHandler, mRecyclerViewPositionSupplier,
+                        mAnimationSourceViewProvider, mShareDelegateSupplier, mSnackbarManager, "");
 
         // TabModelObserver is registered when native is ready.
         assertThat(mTabModelObserverCaptor.getAllValues().isEmpty(), equalTo(true));
@@ -234,7 +241,8 @@
         verify(mTabSelectionEditorController)
                 .configureToolbar(eq(REMOVE_BUTTON_STRING), anyInt(),
                         any(TabSelectionEditorActionProvider.class), eq(1), eq(null));
-        verify(mTabSelectionEditorController).show(any());
+        verify(mRecyclerViewPositionSupplier, never()).get();
+        verify(mTabSelectionEditorController).show(any(), eq(0), eq(null));
     }
 
     @Test
@@ -257,7 +265,8 @@
         mMediator.getToolbarMenuCallbackForTesting().onResult(R.id.select_tabs);
         verify(mTabSelectionEditorController)
                 .configureToolbarWithMenuItems(captor.capture(), eq(null));
-        verify(mTabSelectionEditorController).show(any());
+        verify(mRecyclerViewPositionSupplier, times(1)).get();
+        verify(mTabSelectionEditorController).show(any(), eq(0), eq(null));
         List<TabSelectionEditorAction> actions = captor.getValue();
         assertThat(actions.get(0), instanceOf(TabSelectionEditorSelectionAction.class));
         assertThat(actions.get(1), instanceOf(TabSelectionEditorCloseAction.class));
@@ -1063,8 +1072,8 @@
         // For strip we don't play zoom-in/zoom-out for show/hide dialog, and thus
         // the animationParamsProvider is null.
         mMediator = new TabGridDialogMediator(mActivity, mDialogController, mModel,
-                mTabModelSelector, mTabCreatorManager, mTabSwitcherResetHandler, null,
-                mShareDelegateSupplier, mSnackbarManager, "");
+                mTabModelSelector, mTabCreatorManager, mTabSwitcherResetHandler,
+                mRecyclerViewPositionSupplier, null, mShareDelegateSupplier, mSnackbarManager, "");
         mMediator.initWithNative(
                 () -> { return mTabSelectionEditorController; }, mTabGroupTitleEditor);
 
@@ -1097,8 +1106,8 @@
         // For strip we don't play zoom-in/zoom-out for show/hide dialog, and thus
         // the animationParamsProvider is null.
         mMediator = new TabGridDialogMediator(mActivity, mDialogController, mModel,
-                mTabModelSelector, mTabCreatorManager, mTabSwitcherResetHandler, null,
-                mShareDelegateSupplier, mSnackbarManager, "");
+                mTabModelSelector, mTabCreatorManager, mTabSwitcherResetHandler,
+                mRecyclerViewPositionSupplier, null, mShareDelegateSupplier, mSnackbarManager, "");
         mMediator.initWithNative(
                 () -> { return mTabSelectionEditorController; }, mTabGroupTitleEditor);
         // Mock that the dialog is hidden and animation source view, header title and scrim click
@@ -1132,8 +1141,8 @@
         // For strip we don't play zoom-in/zoom-out for show/hide dialog, and thus
         // the animationParamsProvider is null.
         mMediator = new TabGridDialogMediator(mActivity, mDialogController, mModel,
-                mTabModelSelector, mTabCreatorManager, mTabSwitcherResetHandler, null,
-                mShareDelegateSupplier, mSnackbarManager, "");
+                mTabModelSelector, mTabCreatorManager, mTabSwitcherResetHandler,
+                mRecyclerViewPositionSupplier, null, mShareDelegateSupplier, mSnackbarManager, "");
         mMediator.initWithNative(
                 () -> { return mTabSelectionEditorController; }, mTabGroupTitleEditor);
         // Mock that the dialog is hidden and animation source view is set to some mock view for
@@ -1167,7 +1176,30 @@
 
         assertThat(mModel.get(TabGridPanelProperties.IS_KEYBOARD_VISIBLE), equalTo(false));
         assertThat(mModel.get(TabGridPanelProperties.IS_TITLE_TEXT_FOCUSED), equalTo(false));
-        verify(mTabSelectionEditorController).show(eq(tabgroup));
+        verify(mRecyclerViewPositionSupplier, never()).get();
+        verify(mTabSelectionEditorController).show(eq(tabgroup), eq(0), eq(null));
+    }
+
+    @Test
+    @Features.EnableFeatures({ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID,
+            ChromeFeatureList.TAB_SELECTION_EDITOR_V2})
+    public void
+    testDialogToolbarMenu_SelectionModeV2() {
+        Callback<Integer> callback = mMediator.getToolbarMenuCallbackForTesting();
+        // Mock that currently the title text is focused and the keyboard is showing. The current
+        // tab is tab1 which is in a group of {tab1, tab2}.
+        mModel.set(TabGridPanelProperties.IS_KEYBOARD_VISIBLE, true);
+        mModel.set(TabGridPanelProperties.IS_TITLE_TEXT_FOCUSED, true);
+        mMediator.setCurrentTabIdForTesting(TAB1_ID);
+        List<Tab> tabgroup = new ArrayList<>(Arrays.asList(mTab1, mTab2));
+        createTabGroup(tabgroup, TAB1_ID);
+
+        callback.onResult(R.id.select_tabs);
+
+        assertThat(mModel.get(TabGridPanelProperties.IS_KEYBOARD_VISIBLE), equalTo(false));
+        assertThat(mModel.get(TabGridPanelProperties.IS_TITLE_TEXT_FOCUSED), equalTo(false));
+        verify(mRecyclerViewPositionSupplier, times(1)).get();
+        verify(mTabSelectionEditorController).show(eq(tabgroup), eq(0), eq(null));
     }
 
     @Test
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
index ed70b64..57e19aa 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
@@ -743,7 +743,34 @@
 
     @Test
     @Features.EnableFeatures(ChromeFeatureList.TAB_GROUPS_ANDROID)
-    public void tabClosureUndone_UiNotVisible_NotShowingOverviewMode() {
+    public void tabClosureUndone_UiNotVisible_NotShowingOverviewMode_TabNotInGroup() {
+        // Assume mTab1 is selected. Since mTab1 is now a single tab, the strip is invisible.
+        initAndAssertProperties(mTab1);
+        // OverviewMode is hiding by default.
+        assertThat(mTabGroupUiMediator.getIsShowingOverViewModeForTesting(), equalTo(false));
+
+        // Simulate mTab2 and mTab3 being undone from closure with mTab1 still selected.
+        doReturn(new ArrayList<>(Arrays.asList(mTab2, mTab3)))
+                .when(mTabGroupModelFilter)
+                .getRelatedTabList(TAB2_ID);
+        doReturn(new ArrayList<>(Arrays.asList(mTab2, mTab3)))
+                .when(mTabGroupModelFilter)
+                .getRelatedTabList(TAB3_ID);
+        doReturn(new ArrayList<>(Arrays.asList(mTab1)))
+                .when(mTabGroupModelFilter)
+                .getRelatedTabList(TAB1_ID);
+        doReturn(mTab1).when(mTabModelSelector).getCurrentTab();
+
+        mTabModelObserverArgumentCaptor.getValue().tabClosureUndone(mTab2);
+        mTabModelObserverArgumentCaptor.getValue().tabClosureUndone(mTab3);
+
+        // Strip should remain invisible.
+        assertThat(mTabGroupUiMediator.getIsShowingOverViewModeForTesting(), equalTo(false));
+    }
+
+    @Test
+    @Features.EnableFeatures(ChromeFeatureList.TAB_GROUPS_ANDROID)
+    public void tabClosureUndone_UiNotVisible_NotShowingOverviewMode_TabInGroup() {
         // Assume mTab1 is selected. Since mTab1 is now a single tab, the strip is invisible.
         initAndAssertProperties(mTab1);
         // OverviewMode is hiding by default.
@@ -754,7 +781,11 @@
         TabImpl newTab = prepareTab(TAB4_ID, TAB4_ID);
         doReturn(new ArrayList<>(Arrays.asList(mTab1, newTab)))
                 .when(mTabGroupModelFilter)
+                .getRelatedTabList(TAB1_ID);
+        doReturn(new ArrayList<>(Arrays.asList(mTab1, newTab)))
+                .when(mTabGroupModelFilter)
                 .getRelatedTabList(TAB4_ID);
+        doReturn(mTab1).when(mTabModelSelector).getCurrentTab();
 
         mTabModelObserverArgumentCaptor.getValue().tabClosureUndone(newTab);
 
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCloseActionUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCloseActionUnitTest.java
index b700ec53..79d45c4a 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCloseActionUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCloseActionUnitTest.java
@@ -130,7 +130,7 @@
 
         Assert.assertTrue(mAction.perform());
         verify(mTabModel).closeTab(tabs.get(1), false, false, true);
-        verify(mDelegate).hide();
+        verify(mDelegate).hideByAction();
     }
 
     @Test
@@ -165,14 +165,14 @@
 
         Assert.assertTrue(mAction.perform());
         verify(mTabModel).closeMultipleTabs(tabs, true);
-        verify(mDelegate).hide();
+        verify(mDelegate).hideByAction();
 
         helper.waitForFirst();
         mAction.removeActionObserver(observer);
 
         Assert.assertTrue(mAction.perform());
         verify(mTabModel, times(2)).closeMultipleTabs(tabs, true);
-        verify(mDelegate, times(2)).hide();
+        verify(mDelegate, times(2)).hideByAction();
         Assert.assertEquals(1, helper.getCallCount());
     }
 
@@ -209,7 +209,7 @@
         Assert.assertEquals(1, holder.getSelectedAndRelatedTabs().get(5).getId());
         Assert.assertTrue(mAction.perform());
         verify(mTabModel).closeMultipleTabs(holder.getSelectedAndRelatedTabs(), true);
-        verify(mDelegate).hide();
+        verify(mDelegate).hideByAction();
     }
 
     @Test
@@ -238,6 +238,6 @@
 
         Assert.assertTrue(mAction.perform());
         verify(mTabModel).closeMultipleTabs(holder.getSelectedTabs(), true);
-        verify(mDelegate).hide();
+        verify(mDelegate).hideByAction();
     }
 }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorGroupActionUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorGroupActionUnitTest.java
index fb825dc5d..d2271aa 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorGroupActionUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorGroupActionUnitTest.java
@@ -145,14 +145,14 @@
 
         Assert.assertTrue(mAction.perform());
         verify(mGroupFilter).mergeListOfTabsToGroup(tabs, tabs.get(2), true, true);
-        verify(mDelegate).hide();
+        verify(mDelegate).hideByAction();
 
         helper.waitForFirst();
         mAction.removeActionObserver(observer);
 
         Assert.assertTrue(mAction.perform());
         verify(mGroupFilter, times(2)).mergeListOfTabsToGroup(tabs, tabs.get(2), true, true);
-        verify(mDelegate, times(2)).hide();
+        verify(mDelegate, times(2)).hideByAction();
         Assert.assertEquals(1, helper.getCallCount());
     }
 
@@ -195,7 +195,7 @@
         expectedTabs.add(0, tab8);
         verify(mGroupFilter)
                 .mergeListOfTabsToGroup(expectedTabs, holder.getSelectedTabs().get(2), true, true);
-        verify(mDelegate).hide();
+        verify(mDelegate).hideByAction();
     }
 
     @Test
@@ -231,7 +231,7 @@
         List<Tab> expectedTabs = holder.getSelectedAndRelatedTabs();
         verify(mGroupFilter)
                 .mergeListOfTabsToGroup(expectedTabs, holder.getSelectedTabs().get(0), true, true);
-        verify(mDelegate).hide();
+        verify(mDelegate).hideByAction();
     }
 
     @Test
@@ -274,6 +274,6 @@
         List<Tab> expectedTabs = holder.getSelectedAndRelatedTabs();
         verify(mGroupFilter)
                 .mergeListOfTabsToGroup(expectedTabs, holder.getSelectedTabs().get(0), true, true);
-        verify(mDelegate).hide();
+        verify(mDelegate).hideByAction();
     }
 }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorUngroupActionUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorUngroupActionUnitTest.java
index da216be..8b8a818e 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorUngroupActionUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorUngroupActionUnitTest.java
@@ -132,7 +132,7 @@
         for (int id : tabIds) {
             verify(mGroupFilter).moveTabOutOfGroup(id);
         }
-        verify(mDelegate).hide();
+        verify(mDelegate).hideByAction();
 
         helper.waitForFirst();
         mAction.removeActionObserver(observer);
@@ -141,7 +141,7 @@
         for (int id : tabIds) {
             verify(mGroupFilter, times(2)).moveTabOutOfGroup(id);
         }
-        verify(mDelegate, times(2)).hide();
+        verify(mDelegate, times(2)).hideByAction();
         Assert.assertEquals(1, helper.getCallCount());
     }
 }
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 6432e76..46fea56 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
@@ -157,12 +157,14 @@
         verify(mTabSelectionEditorController)
                 .configureToolbar(eq(closeSuggestionActionButtonText), anyInt(), any(),
                         eq(expectedEnablingThreshold), any());
-        verify(mTabSelectionEditorController).show(eq(Arrays.asList(mTab1, mTab2, mTab3)), eq(2));
+        verify(mTabSelectionEditorController)
+                .show(eq(Arrays.asList(mTab1, mTab2, mTab3)), eq(2), eq(null));
 
         tabSuggestion = prepareTabSuggestion(
                 Arrays.asList(mTab1, mTab3), TabSuggestion.TabSuggestionAction.CLOSE);
         mMessageService.review(tabSuggestion, mTabSuggestionFeedbackCallback);
-        verify(mTabSelectionEditorController).show(eq(Arrays.asList(mTab1, mTab3, mTab2)), eq(2));
+        verify(mTabSelectionEditorController)
+                .show(eq(Arrays.asList(mTab1, mTab3, mTab2)), eq(2), eq(null));
     }
 
     @Test
@@ -228,12 +230,14 @@
         verify(mTabSelectionEditorController)
                 .configureToolbar(eq(groupSuggestionActionButtonText), anyInt(), any(),
                         eq(expectedEnablingThreshold), any());
-        verify(mTabSelectionEditorController).show(eq(Arrays.asList(mTab1, mTab2, mTab3)), eq(2));
+        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));
+        verify(mTabSelectionEditorController)
+                .show(eq(Arrays.asList(mTab1, mTab3, mTab2)), eq(2), eq(null));
     }
 
     @Test
diff --git a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java
index 2538c76..71fcf136 100644
--- a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java
+++ b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java
@@ -29,7 +29,6 @@
 import com.google.vr.ndk.base.AndroidCompat;
 import com.google.vr.ndk.base.GvrLayout;
 
-import org.chromium.base.Function;
 import org.chromium.base.Log;
 import org.chromium.base.StrictModeContext;
 import org.chromium.base.ThreadUtils;
@@ -81,6 +80,7 @@
 import org.chromium.ui.widget.UiWidgetFactory;
 
 import java.util.ArrayList;
+import java.util.function.Function;
 
 /**
  * This view extends from GvrLayout which wraps a GLSurfaceView that renders VR shell.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/sharing/TwaSharingController.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/sharing/TwaSharingController.java
index ed061f9..49eeca8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/sharing/TwaSharingController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/sharing/TwaSharingController.java
@@ -12,7 +12,6 @@
 import androidx.browser.trusted.sharing.ShareData;
 import androidx.browser.trusted.sharing.ShareTarget;
 
-import org.chromium.base.Function;
 import org.chromium.base.Promise;
 import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider;
 import org.chromium.chrome.browser.browserservices.intents.WebApkExtras;
@@ -28,6 +27,7 @@
 
 import java.util.ArrayList;
 import java.util.Locale;
+import java.util.function.Function;
 
 import javax.inject.Inject;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java
index 8d2314e5..11d14740 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java
@@ -244,6 +244,16 @@
         }
 
         @Override
+        public void multipleTabsPendingClosure(List<Tab> tabs, boolean isAllTabs) {
+            // Handled by willCloseAllTabs;
+            if (isAllTabs) return;
+
+            for (Tab tab : tabs) {
+                tabClosed(tab.getId(), tab.isIncognito(), false);
+            }
+        }
+
+        @Override
         public void tabClosureCommitted(Tab tab) {
             LayoutManagerImpl.this.tabClosureCommitted(tab.getId(), tab.isIncognito());
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
index 42c4fc5..f11dc88 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
@@ -15,7 +15,6 @@
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.Callback;
 import org.chromium.base.ContextUtils;
-import org.chromium.base.Function;
 import org.chromium.base.IntentUtils;
 import org.chromium.base.PackageManagerUtils;
 import org.chromium.base.supplier.Supplier;
@@ -37,6 +36,7 @@
 import org.chromium.url.GURL;
 
 import java.util.List;
+import java.util.function.Function;
 
 /**
  * The main implementation of the {@link ExternalNavigationDelegate}.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
index 831da57..0a4b3ca 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
@@ -17,7 +17,6 @@
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.recyclerview.widget.RecyclerView.ViewHolder;
 
-import org.chromium.base.Function;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.history.HistoryProvider.BrowsingHistoryObserver;
@@ -30,6 +29,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.Function;
 
 /**
  * Bridges the user's browsing history and the UI used to display it.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryContentManager.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryContentManager.java
index 59df52b3..359cf97 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryContentManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryContentManager.java
@@ -24,7 +24,6 @@
 import androidx.recyclerview.widget.RecyclerView.ViewHolder;
 
 import org.chromium.base.ContextUtils;
-import org.chromium.base.Function;
 import org.chromium.base.IntentUtils;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.Supplier;
@@ -54,6 +53,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.Function;
 
 /**
  * Displays and manages the content view / list UI for browsing history.
@@ -555,4 +555,4 @@
     public static void setScrollToLoadDisabledForTesting(boolean isScrollToLoadDisabled) {
         sIsScrollToLoadDisabledForTests = isScrollToLoadDisabled;
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
index be8c8a70..d32374a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
@@ -8,7 +8,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
-import android.os.SystemClock;
 import android.text.format.DateUtils;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
@@ -122,7 +121,6 @@
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
-import java.util.Locale;
 
 /**
  * Handles the initialization dependences of the browser process.  This is meant to handle the
@@ -491,14 +489,10 @@
              */
             private static final long LOGCAT_RELEVANCE_THRESHOLD_IN_HOURS = 12;
 
-            private long mAsyncTaskStartTime;
-
             @Override
             protected Void doInBackground() {
                 try {
                     TraceEvent.begin("ChromeBrowserInitializer.onDeferredStartup.doInBackground");
-                    mAsyncTaskStartTime = SystemClock.uptimeMillis();
-
                     initCrashReporting();
 
                     // Initialize the WebappRegistry if it's not already initialized. Must be in
@@ -527,10 +521,6 @@
             protected void onPostExecute(Void params) {
                 // Must be run on the UI thread after the WebappRegistry has been completely warmed.
                 WebappRegistry.getInstance().unregisterOldWebapps(System.currentTimeMillis());
-
-                RecordHistogram.recordLongTimesHistogram(
-                        "UMA.Debug.EnableCrashUpload.DeferredStartUpAsyncTaskDuration",
-                        SystemClock.uptimeMillis() - mAsyncTaskStartTime);
             }
 
             /**
@@ -699,13 +689,5 @@
             }
         }
         RecordHistogram.recordCount1MHistogram("InputMethod.ActiveCount", uniqueLanguages.size());
-
-        InputMethodSubtype currentSubtype = imm.getCurrentInputMethodSubtype();
-        Locale systemLocale = Locale.getDefault();
-        if (currentSubtype != null && currentSubtype.getLocale() != null && systemLocale != null) {
-            String keyboardLanguage = currentSubtype.getLocale().split("_")[0];
-            boolean match = systemLocale.getLanguage().equalsIgnoreCase(keyboardLanguage);
-            RecordHistogram.recordBooleanHistogram("InputMethod.MatchesSystemLanguage", match);
-        }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessage.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessage.java
index b9ba091..971f928 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessage.java
@@ -33,7 +33,6 @@
 import org.chromium.chrome.browser.sync.settings.ManageSyncSettings;
 import org.chromium.chrome.browser.sync.settings.SyncSettingsUtils;
 import org.chromium.chrome.browser.sync.settings.SyncSettingsUtils.SyncError;
-import org.chromium.chrome.browser.sync.ui.SyncErrorPromptUtils.SyncErrorPromptType;
 import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.messages.DismissReason;
 import org.chromium.components.messages.MessageBannerProperties;
@@ -59,6 +58,26 @@
  * only one instance in the whole application will exist at a time.
  */
 public class SyncErrorMessage implements SyncStateChangedListener, UnownedUserData {
+    @VisibleForTesting
+    @IntDef({MessageType.NOT_SHOWN, MessageType.AUTH_ERROR, MessageType.PASSPHRASE_REQUIRED,
+            MessageType.SYNC_SETUP_INCOMPLETE, MessageType.CLIENT_OUT_OF_DATE,
+            MessageType.TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING,
+            MessageType.TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS,
+            MessageType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING,
+            MessageType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface MessageType {
+        int NOT_SHOWN = -1;
+        int AUTH_ERROR = 0;
+        int PASSPHRASE_REQUIRED = 1;
+        int SYNC_SETUP_INCOMPLETE = 2;
+        int CLIENT_OUT_OF_DATE = 3;
+        int TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING = 4;
+        int TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS = 5;
+        int TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING = 6;
+        int TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS = 7;
+    }
+
     // These values are persisted to logs. Entries should not be renumbered and
     // numeric values should never be reused.
     @IntDef({Action.SHOWN, Action.DISMISSED, Action.BUTTON_CLICKED, Action.NUM_ENTRIES})
@@ -70,7 +89,7 @@
         int NUM_ENTRIES = 3;
     }
 
-    private final @SyncErrorPromptType int mType;
+    private final @MessageType int mType;
     private final Activity mActivity;
     private final MessageDispatcher mMessageDispatcher;
     private final PropertyModel mModel;
@@ -84,7 +103,7 @@
      * Creates a {@link SyncErrorMessage} in the window of |dispatcher|, or results in a no-op
      * if preconditions are not satisfied. The conditions are:
      * a) there is an ongoing sync error and it belongs to the subset defined by
-     *    {@link SyncErrorPromptType}.
+     *    {@link MessageType}.
      * b) a minimal time interval has passed since the UI was last shown.
      * c) there is no other instance of the UI being shown on this window.
      * d) there is a valid {@link MessageDispatcher} in this window.
@@ -93,21 +112,24 @@
      */
     public static void maybeShowMessageUi(WindowAndroid windowAndroid) {
         try (TraceEvent t = TraceEvent.scoped("SyncErrorMessage.maybeShowMessageUi")) {
-            if (!SyncErrorPromptUtils.shouldShowPrompt(SyncErrorPromptUtils.getSyncErrorUiType(
-                        SyncSettingsUtils.getSyncError()))) {
+            if (getMessageType(SyncSettingsUtils.getSyncError()) == MessageType.NOT_SHOWN) {
+                return;
+            }
+
+            if (!SyncErrorMessageImpressionTracker.canShowNow()) {
                 return;
             }
 
             MessageDispatcher dispatcher = MessageDispatcherProvider.from(windowAndroid);
             if (dispatcher == null) {
-                // Show prompt UI next time when there is a valid dispatcher attached to this
+                // Show message next time when there is a valid dispatcher attached to this
                 // window.
                 return;
             }
 
             UnownedUserDataHost host = windowAndroid.getUnownedUserDataHost();
             if (SYNC_ERROR_MESSAGE_KEY.retrieveDataFromHost(host) != null) {
-                // Show prompt UI next time when the previous message has disappeared.
+                // Show message next time when the previous message has disappeared.
                 return;
             }
             SYNC_ERROR_MESSAGE_KEY.attachToHost(
@@ -142,17 +164,17 @@
         mMessageDispatcher =
                 sMessageDispatcherForTesting == null ? dispatcher : sMessageDispatcherForTesting;
         mMessageDispatcher.enqueueWindowScopedMessage(mModel, false);
-        mType = SyncErrorPromptUtils.getSyncErrorUiType(error);
+        mType = getMessageType(error);
         mActivity = activity;
         SyncService.get().addSyncStateChangedListener(this);
-        SyncErrorPromptUtils.updateLastShownTime();
+        SyncErrorMessageImpressionTracker.updateLastShownTime();
         recordHistogram(Action.SHOWN);
     }
 
     @Override
     public void syncStateChanged() {
         // If the error disappeared or changed type in the meantime, dismiss the UI.
-        if (mType != SyncErrorPromptUtils.getSyncErrorUiType(SyncSettingsUtils.getSyncError())) {
+        if (mType != getMessageType(SyncSettingsUtils.getSyncError())) {
             mMessageDispatcher.dismissMessage(mModel, DismissReason.UNKNOWN);
             assert !SYNC_ERROR_MESSAGE_KEY.isAttachedToAnyHost(this)
                 : "Message UI should have been dismissed";
@@ -161,27 +183,27 @@
 
     private @PrimaryActionClickBehavior int onAccepted() {
         switch (mType) {
-            case SyncErrorPromptType.NOT_SHOWN:
+            case MessageType.NOT_SHOWN:
                 assert false;
                 break;
-            case SyncErrorPromptType.AUTH_ERROR:
+            case MessageType.AUTH_ERROR:
                 if (ChromeFeatureList.isEnabled(UNIFIED_PASSWORD_MANAGER_ERROR_MESSAGES)) {
                     startUpdateCredentialsFlow(mActivity);
                 } else {
                     openSyncSettings();
                 }
                 break;
-            case SyncErrorPromptType.PASSPHRASE_REQUIRED:
-            case SyncErrorPromptType.SYNC_SETUP_INCOMPLETE:
-            case SyncErrorPromptType.CLIENT_OUT_OF_DATE:
+            case MessageType.PASSPHRASE_REQUIRED:
+            case MessageType.SYNC_SETUP_INCOMPLETE:
+            case MessageType.CLIENT_OUT_OF_DATE:
                 openSyncSettings();
                 break;
-            case SyncErrorPromptType.TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING:
-            case SyncErrorPromptType.TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS:
+            case MessageType.TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING:
+            case MessageType.TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS:
                 openTrustedVaultKeyRetrievalActivity();
                 break;
-            case SyncErrorPromptType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING:
-            case SyncErrorPromptType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS:
+            case MessageType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING:
+            case MessageType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS:
                 openTrustedVaultRecoverabilityDegradedActivity();
                 break;
         }
@@ -197,7 +219,7 @@
             // wasn't reached either, resetLastShownTime() so the message can be shown again. This
             // includes the case where the user changes tabs while the message is showing
             // (TAB_SWITCHED).
-            SyncErrorPromptUtils.resetLastShownTime();
+            SyncErrorMessageImpressionTracker.resetLastShownTime();
         }
         SyncService.get().removeSyncStateChangedListener(this);
         SYNC_ERROR_MESSAGE_KEY.detachFromAllHosts(this);
@@ -209,31 +231,31 @@
     }
 
     private void recordHistogram(@Action int action) {
-        assert mType != SyncErrorPromptType.NOT_SHOWN;
+        assert mType != MessageType.NOT_SHOWN;
         String name = "Signin.SyncErrorMessage.";
         switch (mType) {
-            case SyncErrorPromptType.AUTH_ERROR:
+            case MessageType.AUTH_ERROR:
                 name += "AuthError";
                 break;
-            case SyncErrorPromptType.PASSPHRASE_REQUIRED:
+            case MessageType.PASSPHRASE_REQUIRED:
                 name += "PassphraseRequired";
                 break;
-            case SyncErrorPromptType.SYNC_SETUP_INCOMPLETE:
+            case MessageType.SYNC_SETUP_INCOMPLETE:
                 name += "SyncSetupIncomplete";
                 break;
-            case SyncErrorPromptType.CLIENT_OUT_OF_DATE:
+            case MessageType.CLIENT_OUT_OF_DATE:
                 name += "ClientOutOfDate";
                 break;
-            case SyncErrorPromptType.TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING:
+            case MessageType.TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING:
                 name += "TrustedVaultKeyRequiredForEverything";
                 break;
-            case SyncErrorPromptType.TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS:
+            case MessageType.TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS:
                 name += "TrustedVaultKeyRequiredForPasswords";
                 break;
-            case SyncErrorPromptType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING:
+            case MessageType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING:
                 name += "TrustedVaultRecoverabilityDegradedForEverything";
                 break;
-            case SyncErrorPromptType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS:
+            case MessageType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS:
                 name += "TrustedVaultRecoverabilityDegradedForPasswords";
                 break;
             default:
@@ -326,6 +348,31 @@
     }
 
     @VisibleForTesting
+    @MessageType
+    public static int getMessageType(@SyncError int error) {
+        switch (error) {
+            case SyncError.AUTH_ERROR:
+                return MessageType.AUTH_ERROR;
+            case SyncError.PASSPHRASE_REQUIRED:
+                return MessageType.PASSPHRASE_REQUIRED;
+            case SyncError.SYNC_SETUP_INCOMPLETE:
+                return MessageType.SYNC_SETUP_INCOMPLETE;
+            case SyncError.CLIENT_OUT_OF_DATE:
+                return MessageType.CLIENT_OUT_OF_DATE;
+            case SyncError.TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING:
+                return MessageType.TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING;
+            case SyncError.TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS:
+                return MessageType.TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS;
+            case SyncError.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING:
+                return MessageType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING;
+            case SyncError.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS:
+                return MessageType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS;
+            default:
+                return MessageType.NOT_SHOWN;
+        }
+    }
+
+    @VisibleForTesting
     public static void setMessageDispatcherForTesting(MessageDispatcher dispatcherForTesting) {
         sMessageDispatcherForTesting = dispatcherForTesting;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageImpressionTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageImpressionTracker.java
new file mode 100644
index 0000000..6919e79
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageImpressionTracker.java
@@ -0,0 +1,62 @@
+// 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.
+
+package org.chromium.chrome.browser.sync.ui;
+
+import static org.chromium.chrome.browser.flags.ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ERROR_MESSAGES;
+import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.SYNC_ERROR_MESSAGE_SHOWN_AT_TIME;
+
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.base.TimeUtils;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.preferences.Pref;
+import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.components.prefs.PrefService;
+import org.chromium.components.user_prefs.UserPrefs;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tracks the last time the sync error message was shown and decides whether that was long enough
+ * ago to show the message again.
+ */
+public class SyncErrorMessageImpressionTracker {
+    @VisibleForTesting
+    public static final long MINIMAL_DURATION_BETWEEN_UI_MS =
+            TimeUnit.MILLISECONDS.convert(24, TimeUnit.HOURS);
+
+    @VisibleForTesting
+    public static final long MINIMAL_DURATION_TO_PWM_ERROR_UI_MS =
+            TimeUnit.MILLISECONDS.convert(30, TimeUnit.MINUTES);
+
+    public static boolean canShowNow() {
+        long lastShownTime = SharedPreferencesManager.getInstance().readLong(
+                SYNC_ERROR_MESSAGE_SHOWN_AT_TIME, 0);
+
+        if (ChromeFeatureList.isEnabled(UNIFIED_PASSWORD_MANAGER_ERROR_MESSAGES)) {
+            // Since the password manager error and the sync error can be related,
+            // the sync error should be shown only if at least MINIMAL_DURATION_TO_PWM_ERROR_UI_MS
+            // have passed since the last password manager error. This condition is mirrored
+            // for the password manager error.
+            long currentTime = TimeUtils.currentTimeMillis();
+            PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile());
+            long upmErrorShownTime =
+                    Long.valueOf(prefService.getString(Pref.UPM_ERROR_UI_SHOWN_TIMESTAMP));
+            return currentTime - lastShownTime > MINIMAL_DURATION_BETWEEN_UI_MS
+                    && currentTime - upmErrorShownTime > MINIMAL_DURATION_TO_PWM_ERROR_UI_MS;
+        }
+        return TimeUtils.currentTimeMillis() - lastShownTime > MINIMAL_DURATION_BETWEEN_UI_MS;
+    }
+
+    public static void updateLastShownTime() {
+        SharedPreferencesManager.getInstance().writeLong(
+                SYNC_ERROR_MESSAGE_SHOWN_AT_TIME, TimeUtils.currentTimeMillis());
+    }
+
+    public static void resetLastShownTime() {
+        SharedPreferencesManager.getInstance().removeKey(SYNC_ERROR_MESSAGE_SHOWN_AT_TIME);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncErrorPromptUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncErrorPromptUtils.java
deleted file mode 100644
index eab8488..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncErrorPromptUtils.java
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.sync.ui;
-
-import static org.chromium.chrome.browser.flags.ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ERROR_MESSAGES;
-import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.SYNC_ERROR_PROMPT_SHOWN_AT_TIME;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.VisibleForTesting;
-
-import org.chromium.base.TimeUtils;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
-import org.chromium.chrome.browser.preferences.Pref;
-import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.sync.settings.SyncSettingsUtils.SyncError;
-import org.chromium.components.prefs.PrefService;
-import org.chromium.components.user_prefs.UserPrefs;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Shared code between the old {@link org.chromium.chrome.browser.infobar.SyncErrorInfobar}
- * and the new UI based on {@link SyncErrorMessage}.
- *
- * TODO(crbug.com/1355876): make private as methods of message ui controller once the migration to
- *                          the new UI is completed.
- */
-public class SyncErrorPromptUtils {
-    @VisibleForTesting
-    public static final long MINIMAL_DURATION_BETWEEN_UI_MS =
-            TimeUnit.MILLISECONDS.convert(24, TimeUnit.HOURS);
-
-    @VisibleForTesting
-    public static final long MINIMAL_DURATION_TO_PWM_ERROR_UI_MS =
-            TimeUnit.MILLISECONDS.convert(30, TimeUnit.MINUTES);
-
-    @IntDef({SyncErrorPromptType.NOT_SHOWN, SyncErrorPromptType.AUTH_ERROR,
-            SyncErrorPromptType.PASSPHRASE_REQUIRED, SyncErrorPromptType.SYNC_SETUP_INCOMPLETE,
-            SyncErrorPromptType.CLIENT_OUT_OF_DATE,
-            SyncErrorPromptType.TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING,
-            SyncErrorPromptType.TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS,
-            SyncErrorPromptType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING,
-            SyncErrorPromptType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface SyncErrorPromptType {
-        int NOT_SHOWN = -1;
-        int AUTH_ERROR = 0;
-        int PASSPHRASE_REQUIRED = 1;
-        int SYNC_SETUP_INCOMPLETE = 2;
-        int CLIENT_OUT_OF_DATE = 3;
-        int TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING = 4;
-        int TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS = 5;
-        int TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING = 6;
-        int TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS = 7;
-    }
-
-    @SyncErrorPromptType
-    public static int getSyncErrorUiType(@SyncError int error) {
-        switch (error) {
-            case SyncError.AUTH_ERROR:
-                return SyncErrorPromptType.AUTH_ERROR;
-            case SyncError.PASSPHRASE_REQUIRED:
-                return SyncErrorPromptType.PASSPHRASE_REQUIRED;
-            case SyncError.SYNC_SETUP_INCOMPLETE:
-                return SyncErrorPromptType.SYNC_SETUP_INCOMPLETE;
-            case SyncError.CLIENT_OUT_OF_DATE:
-                return SyncErrorPromptType.CLIENT_OUT_OF_DATE;
-            case SyncError.TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING:
-                return SyncErrorPromptType.TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING;
-            case SyncError.TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS:
-                return SyncErrorPromptType.TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS;
-            case SyncError.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING:
-                return SyncErrorPromptType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING;
-            case SyncError.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS:
-                return SyncErrorPromptType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS;
-            default:
-                return SyncErrorPromptType.NOT_SHOWN;
-        }
-    }
-
-    public static boolean shouldShowPrompt(@SyncErrorPromptType int type) {
-        if (type == SyncErrorPromptType.NOT_SHOWN) {
-            return false;
-        }
-        long lastShownTime =
-                SharedPreferencesManager.getInstance().readLong(SYNC_ERROR_PROMPT_SHOWN_AT_TIME, 0);
-
-        if (ChromeFeatureList.isEnabled(UNIFIED_PASSWORD_MANAGER_ERROR_MESSAGES)) {
-            // Since the password manager error and the sync error can be related,
-            // the sync error should be shown only if at least MINIMAL_DURATION_TO_PWM_ERROR_UI_MS
-            // have passed since the last password manager error. This condition is mirrored
-            // for the password manager error.
-            long currentTime = TimeUtils.currentTimeMillis();
-            PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile());
-            long upmErrorShownTime =
-                    Long.valueOf(prefService.getString(Pref.UPM_ERROR_UI_SHOWN_TIMESTAMP));
-            return currentTime - lastShownTime > MINIMAL_DURATION_BETWEEN_UI_MS
-                    && currentTime - upmErrorShownTime > MINIMAL_DURATION_TO_PWM_ERROR_UI_MS;
-        }
-        return TimeUtils.currentTimeMillis() - lastShownTime > MINIMAL_DURATION_BETWEEN_UI_MS;
-    }
-
-    public static void updateLastShownTime() {
-        SharedPreferencesManager.getInstance().writeLong(
-                SYNC_ERROR_PROMPT_SHOWN_AT_TIME, TimeUtils.currentTimeMillis());
-    }
-
-    public static void resetLastShownTime() {
-        SharedPreferencesManager.getInstance().removeKey(SYNC_ERROR_PROMPT_SHOWN_AT_TIME);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
index efcf4bc..d879cc5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
@@ -13,7 +13,6 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.CommandLine;
-import org.chromium.base.Function;
 import org.chromium.base.TraceEvent;
 import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.supplier.ObservableSupplier;
@@ -131,6 +130,7 @@
 import org.chromium.ui.modaldialog.ModalDialogManager;
 
 import java.util.function.BooleanSupplier;
+import java.util.function.Function;
 
 /**
  * A {@link RootUiCoordinator} variant that controls tabbed-mode specific UI.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
index 0506abfe..bc6e7c6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
@@ -25,7 +25,6 @@
 import org.chromium.base.StrictModeContext;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.TraceEvent;
-import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.task.AsyncTask;
@@ -1148,10 +1147,6 @@
 
         saveListToFile(getStateDirectory(), mPersistencePolicy.getStateFileName(), listData);
         mLastSavedMetadata = listData;
-        if (LibraryLoader.getInstance().isInitialized()) {
-            RecordHistogram.recordCount1MHistogram(
-                    "Android.TabPersistentStore.MetadataFileSize", listData.length);
-        }
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/EventTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/EventTracker.java
index 55b2656..4574588 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/EventTracker.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/EventTracker.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.usage_stats;
 
-import org.chromium.base.Function;
 import org.chromium.base.Promise;
 import org.chromium.chrome.browser.usage_stats.WebsiteEventProtos.Timestamp;
 
@@ -13,6 +12,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
 
 /**
  * In-memory store of {@link org.chromium.chrome.browser.usage_stats.WebsiteEvent} objects.
@@ -175,4 +175,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/SuspensionTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/SuspensionTracker.java
index 55f2154..379a0d5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/SuspensionTracker.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/SuspensionTracker.java
@@ -4,11 +4,11 @@
 
 package org.chromium.chrome.browser.usage_stats;
 
-import org.chromium.base.Function;
 import org.chromium.base.Promise;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.Function;
 
 /**
  * Class that tracks which sites are currently suspended.
@@ -88,4 +88,4 @@
 
         return false;
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/TokenTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/TokenTracker.java
index 82a5726..deb3492e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/TokenTracker.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/TokenTracker.java
@@ -4,13 +4,13 @@
 
 package org.chromium.chrome.browser.usage_stats;
 
-import org.chromium.base.Function;
 import org.chromium.base.Promise;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 
 /**
  * Class that tracks the mapping between tokens and fully-qualified domain names (FQDNs).
@@ -125,4 +125,4 @@
 
         return null;
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java
index 99d4e26e..58e099b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java
@@ -20,7 +20,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import org.chromium.base.Function;
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.IntentHandler;
@@ -37,6 +36,8 @@
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.url.GURL;
 
+import java.util.function.Function;
+
 /**
  * Instrumentation tests for {@link ExternalNavigationHandler}.
  */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/OWNERS
index cc92f624..2bd624cb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/OWNERS
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/OWNERS
@@ -1 +1 @@
-file://chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/OWNERS
+file://chrome/browser/partnercustomizations/OWNERS
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageTest.java
index aee203b..9600de1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageTest.java
@@ -39,7 +39,7 @@
 import org.chromium.chrome.browser.sync.SyncTestRule;
 import org.chromium.chrome.browser.sync.settings.SyncSettingsUtils;
 import org.chromium.chrome.browser.sync.settings.SyncSettingsUtils.SyncError;
-import org.chromium.chrome.browser.sync.ui.SyncErrorPromptUtils.SyncErrorPromptType;
+import org.chromium.chrome.browser.sync.ui.SyncErrorMessage.MessageType;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ChromeRenderTestRule;
 import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
@@ -85,7 +85,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        SyncErrorPromptUtils.resetLastShownTime();
+        SyncErrorMessageImpressionTracker.resetLastShownTime();
         mFakeSyncServiceImpl = (FakeSyncServiceImpl) mSyncTestRule.getSyncService();
         SyncErrorMessage.setMessageDispatcherForTesting(mMessageDispatcher);
         doAnswer((invocation) -> {
@@ -148,7 +148,7 @@
         verifyHasShownMessage();
 
         // Not possible to resolve this error from within chrome unlike the other
-        // SyncErrorPromptType-s.
+        // SyncErrorMessage-s.
     }
 
     @Test
@@ -195,8 +195,7 @@
             return SyncSettingsUtils.getSyncError();
         });
 
-        Assert.assertEquals(
-                SyncErrorPromptType.NOT_SHOWN, SyncErrorPromptUtils.getSyncErrorUiType(syncError));
+        Assert.assertEquals(MessageType.NOT_SHOWN, SyncErrorMessage.getMessageType(syncError));
 
         verifyHasNeverShownMessage();
     }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/sync/ui/SyncErrorPromptUtilsTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageImpressionTrackerTest.java
similarity index 60%
rename from chrome/android/junit/src/org/chromium/chrome/browser/sync/ui/SyncErrorPromptUtilsTest.java
rename to chrome/android/junit/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageImpressionTrackerTest.java
index 4cf18e5..35ec806c 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/sync/ui/SyncErrorPromptUtilsTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/sync/ui/SyncErrorMessageImpressionTrackerTest.java
@@ -30,17 +30,16 @@
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.sync.ui.SyncErrorPromptUtils.SyncErrorPromptType;
 import org.chromium.components.prefs.PrefService;
 import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.components.user_prefs.UserPrefsJni;
 
 /**
- * Unit tests for the sync prompt utils.
+ * Unit tests for SyncErrorMessageImpressionTracker.
  * */
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
-public class SyncErrorPromptUtilsTest {
+public class SyncErrorMessageImpressionTrackerTest {
     @Rule
     public JniMocker mJniMocker = new JniMocker();
 
@@ -72,83 +71,88 @@
 
     @After
     public void tearDown() {
-        mSharedPrefsManager.removeKey(ChromePreferenceKeys.SYNC_ERROR_PROMPT_SHOWN_AT_TIME);
+        mSharedPrefsManager.removeKey(ChromePreferenceKeys.SYNC_ERROR_MESSAGE_SHOWN_AT_TIME);
         mFakeTimeTestRule.resetTimes();
     }
 
     @Test
     @DisableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ERROR_MESSAGES)
     public void testNotEnoughTimeSinceLastSyncErrorUINoPwm() {
-        final long timeOfFirstSyncPrompt = TimeUtils.currentTimeMillis();
+        final long timeOfFirstSyncMessage = TimeUtils.currentTimeMillis();
         mSharedPrefsManager.writeLong(
-                ChromePreferenceKeys.SYNC_ERROR_PROMPT_SHOWN_AT_TIME, timeOfFirstSyncPrompt);
-        mFakeTimeTestRule.advanceMillis(SyncErrorPromptUtils.MINIMAL_DURATION_BETWEEN_UI_MS);
-        assertFalse(SyncErrorPromptUtils.shouldShowPrompt(SyncErrorPromptType.AUTH_ERROR));
+                ChromePreferenceKeys.SYNC_ERROR_MESSAGE_SHOWN_AT_TIME, timeOfFirstSyncMessage);
+        mFakeTimeTestRule.advanceMillis(
+                SyncErrorMessageImpressionTracker.MINIMAL_DURATION_BETWEEN_UI_MS);
+        assertFalse(SyncErrorMessageImpressionTracker.canShowNow());
     }
 
     @Test
     @DisableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ERROR_MESSAGES)
     public void testEnoughTimeSinceLastSyncErrorUINoPwm() {
-        final long timeOfFirstSyncPrompt = TimeUtils.currentTimeMillis();
+        final long timeOfFirstSyncMessage = TimeUtils.currentTimeMillis();
         mSharedPrefsManager.writeLong(
-                ChromePreferenceKeys.SYNC_ERROR_PROMPT_SHOWN_AT_TIME, timeOfFirstSyncPrompt);
-        mFakeTimeTestRule.advanceMillis(SyncErrorPromptUtils.MINIMAL_DURATION_BETWEEN_UI_MS + 1);
-        assertTrue(SyncErrorPromptUtils.shouldShowPrompt(SyncErrorPromptType.AUTH_ERROR));
+                ChromePreferenceKeys.SYNC_ERROR_MESSAGE_SHOWN_AT_TIME, timeOfFirstSyncMessage);
+        mFakeTimeTestRule.advanceMillis(
+                SyncErrorMessageImpressionTracker.MINIMAL_DURATION_BETWEEN_UI_MS + 1);
+        assertTrue(SyncErrorMessageImpressionTracker.canShowNow());
     }
 
     @Test
     @EnableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ERROR_MESSAGES)
     public void testNotEnoughTimeSinceLastSyncErrorUI() {
-        final long timeOfFirstSyncPrompt = TimeUtils.currentTimeMillis();
+        final long timeOfFirstSyncMessage = TimeUtils.currentTimeMillis();
         mSharedPrefsManager.writeLong(
-                ChromePreferenceKeys.SYNC_ERROR_PROMPT_SHOWN_AT_TIME, timeOfFirstSyncPrompt);
-        // Make sure not enough time passed since the time of the first sync error prompt.
-        mFakeTimeTestRule.advanceMillis(SyncErrorPromptUtils.MINIMAL_DURATION_BETWEEN_UI_MS);
+                ChromePreferenceKeys.SYNC_ERROR_MESSAGE_SHOWN_AT_TIME, timeOfFirstSyncMessage);
+        // Make sure not enough time passed since the time of the first sync error message.
+        mFakeTimeTestRule.advanceMillis(
+                SyncErrorMessageImpressionTracker.MINIMAL_DURATION_BETWEEN_UI_MS);
 
-        // Pretend enough time has passed since the last password manager prompt.
-        final long timeOfPwmPrompt = TimeUtils.currentTimeMillis()
-                - SyncErrorPromptUtils.MINIMAL_DURATION_TO_PWM_ERROR_UI_MS - 1;
+        // Pretend enough time has passed since the last password manager message.
+        final long timeOfPwmMessage = TimeUtils.currentTimeMillis()
+                - SyncErrorMessageImpressionTracker.MINIMAL_DURATION_TO_PWM_ERROR_UI_MS - 1;
         when(mPrefService.getString(Pref.UPM_ERROR_UI_SHOWN_TIMESTAMP))
-                .thenReturn(Long.toString(timeOfPwmPrompt));
+                .thenReturn(Long.toString(timeOfPwmMessage));
 
-        assertFalse(SyncErrorPromptUtils.shouldShowPrompt(SyncErrorPromptType.AUTH_ERROR));
+        assertFalse(SyncErrorMessageImpressionTracker.canShowNow());
     }
 
     @Test
     @EnableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ERROR_MESSAGES)
     public void testNotEnoughTimeSinceLastPwmUI() {
-        final long timeOfFirstSyncPrompt = TimeUtils.currentTimeMillis();
+        final long timeOfFirstSyncMessage = TimeUtils.currentTimeMillis();
         mSharedPrefsManager.writeLong(
-                ChromePreferenceKeys.SYNC_ERROR_PROMPT_SHOWN_AT_TIME, timeOfFirstSyncPrompt);
+                ChromePreferenceKeys.SYNC_ERROR_MESSAGE_SHOWN_AT_TIME, timeOfFirstSyncMessage);
         // Make sure enough time passed since the last sync error UI.
-        mFakeTimeTestRule.advanceMillis(SyncErrorPromptUtils.MINIMAL_DURATION_BETWEEN_UI_MS + 1);
+        mFakeTimeTestRule.advanceMillis(
+                SyncErrorMessageImpressionTracker.MINIMAL_DURATION_BETWEEN_UI_MS + 1);
 
         // Pretend not enough time passed since last password manager UI.
-        final long timeOfPwmPrompt = TimeUtils.currentTimeMillis()
-                - SyncErrorPromptUtils.MINIMAL_DURATION_TO_PWM_ERROR_UI_MS;
+        final long timeOfPwmMessage = TimeUtils.currentTimeMillis()
+                - SyncErrorMessageImpressionTracker.MINIMAL_DURATION_TO_PWM_ERROR_UI_MS;
         when(mPrefService.getString(Pref.UPM_ERROR_UI_SHOWN_TIMESTAMP))
-                .thenReturn(Long.toString(timeOfPwmPrompt));
+                .thenReturn(Long.toString(timeOfPwmMessage));
 
-        assertFalse(SyncErrorPromptUtils.shouldShowPrompt(SyncErrorPromptType.AUTH_ERROR));
+        assertFalse(SyncErrorMessageImpressionTracker.canShowNow());
     }
 
     @Test
     @EnableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ERROR_MESSAGES)
     public void testEnoughTimeSinceBothUis() {
-        final long timeOfFirstSyncPrompt = TimeUtils.currentTimeMillis();
+        final long timeOfFirstSyncMessage = TimeUtils.currentTimeMillis();
         mSharedPrefsManager.writeLong(
-                ChromePreferenceKeys.SYNC_ERROR_PROMPT_SHOWN_AT_TIME, timeOfFirstSyncPrompt);
+                ChromePreferenceKeys.SYNC_ERROR_MESSAGE_SHOWN_AT_TIME, timeOfFirstSyncMessage);
 
         // Make sure enough time passed since the last sync error UI.
-        mFakeTimeTestRule.advanceMillis(SyncErrorPromptUtils.MINIMAL_DURATION_BETWEEN_UI_MS + 1);
+        mFakeTimeTestRule.advanceMillis(
+                SyncErrorMessageImpressionTracker.MINIMAL_DURATION_BETWEEN_UI_MS + 1);
 
         // Pretend enough time passed since the last password manager error UI.
-        final long timeOfPwmPrompt = TimeUtils.currentTimeMillis()
-                - SyncErrorPromptUtils.MINIMAL_DURATION_TO_PWM_ERROR_UI_MS - 1;
+        final long timeOfPwmMessage = TimeUtils.currentTimeMillis()
+                - SyncErrorMessageImpressionTracker.MINIMAL_DURATION_TO_PWM_ERROR_UI_MS - 1;
 
         when(mPrefService.getString(Pref.UPM_ERROR_UI_SHOWN_TIMESTAMP))
-                .thenReturn(Long.toString(timeOfPwmPrompt));
+                .thenReturn(Long.toString(timeOfPwmMessage));
 
-        assertTrue(SyncErrorPromptUtils.shouldShowPrompt(SyncErrorPromptType.AUTH_ERROR));
+        assertTrue(SyncErrorMessageImpressionTracker.canShowNow());
     }
 }
diff --git a/chrome/android/native_java_unittests/src/org/chromium/chrome/browser/partnercustomizations/OWNERS b/chrome/android/native_java_unittests/src/org/chromium/chrome/browser/partnercustomizations/OWNERS
index cc92f624..2bd624cb 100644
--- a/chrome/android/native_java_unittests/src/org/chromium/chrome/browser/partnercustomizations/OWNERS
+++ b/chrome/android/native_java_unittests/src/org/chromium/chrome/browser/partnercustomizations/OWNERS
@@ -1 +1 @@
-file://chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/OWNERS
+file://chrome/browser/partnercustomizations/OWNERS
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index cda47242..7875c31d 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -1628,6 +1628,9 @@
   <message name="IDS_SETTINGS_ACCESSIBILITY_AUDIO_AND_CAPTIONS_LINK_DESCRIPTION" desc="In the settings tab, the description of a link that opens a screen allowing the user to change audio and captions accessibility features.">
     Mono audio, startup, Live Caption, and more
   </message>
+  <message name="IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_LINK_TITLE" desc="In the Accessibility settings page, the title of a link that opens a screen allowing the user to change options for the Select-to-speak accessibility feature.">
+    Select-to-speak settings
+  </message>
 
   <!-- Account Manager (OS settings) -->
   <message name="IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_DESCRIPTION_V2" desc="Description of the Account Manager Settings page for child users. Shown just below the title of the page.">
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_LINK_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_LINK_TITLE.png.sha1
new file mode 100644
index 0000000..866e231
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_LINK_TITLE.png.sha1
@@ -0,0 +1 @@
+05fc5364c13d304f264fd570e2de80149ada497c
\ No newline at end of file
diff --git a/chrome/app/theme/chrome_unscaled_resources.grd b/chrome/app/theme/chrome_unscaled_resources.grd
index 7290b72..f7cb4c7f 100644
--- a/chrome/app/theme/chrome_unscaled_resources.grd
+++ b/chrome/app/theme/chrome_unscaled_resources.grd
@@ -16,42 +16,21 @@
     <includes>
       <if expr="_google_chrome">
         <then>
-          <include name="IDR_ASSISTANT_LOGO_MONOCHROME" file="google_chrome/google_assistant.svg" type="BINDATA" />
-          <if expr="_google_chrome_for_testing">
+          <if expr="is_linux">
             <then>
-              <if expr="is_linux">
-                <then>
-                  <include name="IDR_PRODUCT_LOGO_64" file="google_chrome/google_chrome_for_testing/linux/product_logo_64.png" type="BINDATA" />
-                  <include name="IDR_PRODUCT_LOGO_128" file="google_chrome/google_chrome_for_testing/linux/product_logo_128.png" type="BINDATA" />
-                  <!-- Beta and Dev use the same logo as stable because channels are not a relevant concept for CfT. -->
-                  <include name="IDR_PRODUCT_LOGO_128_BETA" file="google_chrome/google_chrome_for_testing/linux/product_logo_128.png" type="BINDATA" />
-                  <include name="IDR_PRODUCT_LOGO_128_DEV" file="google_chrome/google_chrome_for_testing/linux/product_logo_128.png" type="BINDATA" />
-                  <include name="IDR_PRODUCT_LOGO_256" file="google_chrome/google_chrome_for_testing/linux/product_logo_256.png" type="BINDATA" />
-                </then>
-                <else>
-                  <include name="IDR_PRODUCT_LOGO_64" file="google_chrome/google_chrome_for_testing/product_logo_64.png" type="BINDATA" />
-                  <include name="IDR_PRODUCT_LOGO_128" file="google_chrome/google_chrome_for_testing/product_logo_128.png" type="BINDATA" />
-                  <include name="IDR_PRODUCT_LOGO_256" file="google_chrome/google_chrome_for_testing/product_logo_256.png" type="BINDATA" />
-                </else>
-              </if>
+              <include name="IDR_PRODUCT_LOGO_64" file="google_chrome/linux/product_logo_64.png" type="BINDATA" />
+              <include name="IDR_PRODUCT_LOGO_128" file="google_chrome/linux/product_logo_128.png" type="BINDATA" />
+              <include name="IDR_PRODUCT_LOGO_128_BETA" file="google_chrome/linux/product_logo_128_beta.png" type="BINDATA" />
+              <include name="IDR_PRODUCT_LOGO_128_DEV" file="google_chrome/linux/product_logo_128_dev.png" type="BINDATA" />
+              <include name="IDR_PRODUCT_LOGO_256" file="google_chrome/linux/product_logo_256.png" type="BINDATA" />
             </then>
-            <else>  <!-- not _google_chrome_for_testing -->
-              <if expr="is_linux">
-                <then>
-                  <include name="IDR_PRODUCT_LOGO_64" file="google_chrome/linux/product_logo_64.png" type="BINDATA" />
-                  <include name="IDR_PRODUCT_LOGO_128" file="google_chrome/linux/product_logo_128.png" type="BINDATA" />
-                  <include name="IDR_PRODUCT_LOGO_128_BETA" file="google_chrome/linux/product_logo_128_beta.png" type="BINDATA" />
-                  <include name="IDR_PRODUCT_LOGO_128_DEV" file="google_chrome/linux/product_logo_128_dev.png" type="BINDATA" />
-                  <include name="IDR_PRODUCT_LOGO_256" file="google_chrome/linux/product_logo_256.png" type="BINDATA" />
-                </then>
-                <else>
-                  <include name="IDR_PRODUCT_LOGO_64" file="google_chrome/product_logo_64.png" type="BINDATA" />
-                  <include name="IDR_PRODUCT_LOGO_128" file="google_chrome/product_logo_128.png" type="BINDATA" />
-                  <include name="IDR_PRODUCT_LOGO_256" file="google_chrome/product_logo_256.png" type="BINDATA" />
-                </else>
-              </if>
+            <else>
+              <include name="IDR_PRODUCT_LOGO_64" file="google_chrome/product_logo_64.png" type="BINDATA" />
+              <include name="IDR_PRODUCT_LOGO_128" file="google_chrome/product_logo_128.png" type="BINDATA" />
+              <include name="IDR_PRODUCT_LOGO_256" file="google_chrome/product_logo_256.png" type="BINDATA" />
             </else>
           </if>
+          <include name="IDR_ASSISTANT_LOGO_MONOCHROME" file="google_chrome/google_assistant.svg" type="BINDATA" />
           <include name="IDR_PRODUCT_LOGO_24PX_1X" file="google_chrome/chrome_24px_1x.svg" type="BINDATA" />
           <include name="IDR_PRODUCT_LOGO_128PX_SVG" file="google_chrome/chrome_128px.svg" type="BINDATA" />
           <if expr="chromeos_ash">
@@ -78,16 +57,34 @@
           </if>
         </then>
         <else> <!-- not _google_chrome -->
-          <if expr="is_linux">
+          <if expr="_google_chrome_for_testing and _use_internal_chrome_for_testing_icons">
             <then>
-              <include name="IDR_PRODUCT_LOGO_64" file="chromium/linux/product_logo_64.png" type="BINDATA" />
-              <include name="IDR_PRODUCT_LOGO_128" file="chromium/linux/product_logo_128.png" type="BINDATA" />
-              <include name="IDR_PRODUCT_LOGO_256" file="chromium/linux/product_logo_256.png" type="BINDATA" />
+              <if expr="is_linux">
+                <then>
+                  <include name="IDR_PRODUCT_LOGO_64" file="google_chrome/google_chrome_for_testing/linux/product_logo_64.png" type="BINDATA" />
+                  <include name="IDR_PRODUCT_LOGO_128" file="google_chrome/google_chrome_for_testing/linux/product_logo_128.png" type="BINDATA" />
+                  <include name="IDR_PRODUCT_LOGO_256" file="google_chrome/google_chrome_for_testing/linux/product_logo_256.png" type="BINDATA" />
+                </then>
+                <else>
+                  <include name="IDR_PRODUCT_LOGO_64" file="google_chrome/google_chrome_for_testing/product_logo_64.png" type="BINDATA" />
+                  <include name="IDR_PRODUCT_LOGO_128" file="google_chrome/google_chrome_for_testing/product_logo_128.png" type="BINDATA" />
+                  <include name="IDR_PRODUCT_LOGO_256" file="google_chrome/google_chrome_for_testing/product_logo_256.png" type="BINDATA" />
+                </else>
+              </if>
             </then>
-            <else>
-              <include name="IDR_PRODUCT_LOGO_64" file="chromium/product_logo_64.png" type="BINDATA" />
-              <include name="IDR_PRODUCT_LOGO_128" file="chromium/product_logo_128.png" type="BINDATA" />
-              <include name="IDR_PRODUCT_LOGO_256" file="chromium/product_logo_256.png" type="BINDATA" />
+            <else>  <!-- not (_google_chrome_for_testing and _use_internal_chrome_for_testing_icons) -->
+              <if expr="is_linux">
+                <then>
+                  <include name="IDR_PRODUCT_LOGO_64" file="chromium/linux/product_logo_64.png" type="BINDATA" />
+                  <include name="IDR_PRODUCT_LOGO_128" file="chromium/linux/product_logo_128.png" type="BINDATA" />
+                  <include name="IDR_PRODUCT_LOGO_256" file="chromium/linux/product_logo_256.png" type="BINDATA" />
+                </then>
+                <else>
+                  <include name="IDR_PRODUCT_LOGO_64" file="chromium/product_logo_64.png" type="BINDATA" />
+                  <include name="IDR_PRODUCT_LOGO_128" file="chromium/product_logo_128.png" type="BINDATA" />
+                  <include name="IDR_PRODUCT_LOGO_256" file="chromium/product_logo_256.png" type="BINDATA" />
+                </else>
+              </if>
             </else>
           </if>
           <!-- NOTE: product_logo_*.* files beyond what's listed above are
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index eb12891a..db0ecde 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -137,44 +137,18 @@
         <then>
           <if expr="is_linux">
             <then>
-              <if expr="_google_chrome_for_testing">
-                <then>
-                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_16" file="google_chrome/google_chrome_for_testing/linux/product_logo_16.png" />
-                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32" file="google_chrome/google_chrome_for_testing/linux/product_logo_32.png" />
-                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32_BETA" file="google_chrome/google_chrome_for_testing/linux/product_logo_32.png" />
-                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32_DEV" file="google_chrome/google_chrome_for_testing/linux/product_logo_32.png" />
-                </then>
-                <else>
-                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_16" file="google_chrome/linux/product_logo_16.png" />
-                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32" file="google_chrome/linux/product_logo_32.png" />
-                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32_BETA" file="google_chrome/linux/product_logo_32_beta.png" />
-                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32_DEV" file="google_chrome/linux/product_logo_32_dev.png" />
-                </else>
-              </if> <!-- _google_chrome_for_testing -->
+              <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_16" file="google_chrome/linux/product_logo_16.png" />
+              <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32" file="google_chrome/linux/product_logo_32.png" />
+              <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32_BETA" file="google_chrome/linux/product_logo_32_beta.png" />
+              <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32_DEV" file="google_chrome/linux/product_logo_32_dev.png" />
             </then>
             <else> <!-- not is_linux -->
               <if expr="not is_android">
-                <if expr="_google_chrome_for_testing">
-                  <then>
-                    <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_16" file="google_chrome/google_chrome_for_testing/product_logo_16.png" />
-                    <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32" file="google_chrome/google_chrome_for_testing/product_logo_32.png" />
-                  </then>
-                  <else>
-                    <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_16" file="google_chrome/product_logo_16.png" />
-                    <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32" file="google_chrome/product_logo_32.png" />
-                  </else>
-                </if> <!-- _google_chrome_for_testing -->
+                <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_16" file="google_chrome/product_logo_16.png" />
+                <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32" file="google_chrome/product_logo_32.png" />
               </if> <!-- not is_android -->
-              <if expr="_google_chrome_for_testing">
-                <then>
-                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32_BETA" file="google_chrome/google_chrome_for_testing/product_logo_32.png" />
-                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32_DEV" file="google_chrome/google_chrome_for_testing/product_logo_32.png" />
-                </then>
-                <else>
-                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32_BETA" file="google_chrome/product_logo_32_beta.png" />
-                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32_DEV" file="google_chrome/product_logo_32_dev.png" />
-                </else>
-              </if> <!-- _google_chrome_for_testing -->
+              <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32_BETA" file="google_chrome/product_logo_32_beta.png" />
+              <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32_DEV" file="google_chrome/product_logo_32_dev.png" />
             </else>
           </if> <!-- is_linux -->
           <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32_CANARY" file="google_chrome/product_logo_32_canary.png" />
@@ -186,16 +160,32 @@
           <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_ENTERPRISE_WHITE" file="google_chrome/product_logo_enterprise_white.png" />
         </then>
         <else> <!-- not _google_chrome -->
-          <if expr="is_linux">
+          <if expr="_google_chrome_for_testing and _use_internal_chrome_for_testing_icons">
             <then>
-              <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_16" file="chromium/linux/product_logo_16.png" />
-              <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32" file="chromium/linux/product_logo_32.png" />
+              <if expr="is_linux">
+                <then>
+                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_16" file="google_chrome/google_chrome_for_testing/linux/product_logo_16.png" />
+                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32" file="google_chrome/google_chrome_for_testing/linux/product_logo_32.png" />
+                </then>
+                <else>
+                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_16" file="google_chrome/google_chrome_for_testing/product_logo_16.png" />
+                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32" file="google_chrome/google_chrome_for_testing/product_logo_32.png" />
+                </else>
+              </if> <!-- is_linux -->
             </then>
-            <else>
-              <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_16" file="chromium/product_logo_16.png" />
-              <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32" file="chromium/product_logo_32.png" />
+            <else> <!-- not (_google_chrome_for_testing and _use_internal_chrome_for_testing_icons) -->
+              <if expr="is_linux">
+                <then>
+                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_16" file="chromium/linux/product_logo_16.png" />
+                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32" file="chromium/linux/product_logo_32.png" />
+                </then>
+                <else>
+                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_16" file="chromium/product_logo_16.png" />
+                  <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32" file="chromium/product_logo_32.png" />
+                </else>
+              </if> <!-- is_linux -->
             </else>
-          </if> <!-- is_linux -->
+          </if> <!-- _google_chrome_for_testing and _use_internal_chrome_for_testing_icons -->
           <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_NAME_22" file="chromium/product_logo_name_22.png" />
           <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_NAME_22_WHITE" file="chromium/product_logo_name_22_white.png" />
         </else>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index b4e640d6..acfe9c64 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1344,14 +1344,6 @@
      std::size(kJourneysVisitDedupingUseHostParams), nullptr},
 };
 
-const FeatureEntry::FeatureParam kTabGroupsSaveWithSyncIntegration[] = {
-    {"sync_integration", "true"},
-};
-const FeatureEntry::FeatureVariation kTabGroupsSaveVariations[] = {
-    {" with sync integration", kTabGroupsSaveWithSyncIntegration,
-     std::size(kTabGroupsSaveWithSyncIntegration), nullptr},
-};
-
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC) || \
     BUILDFLAG(IS_WIN) || BUILDFLAG(IS_FUCHSIA)
 const FeatureEntry::FeatureParam kOmniboxDocumentProviderServerScoring[] = {
@@ -6010,9 +6002,7 @@
 
     {"tab-groups-save", flag_descriptions::kTabGroupsSaveName,
      flag_descriptions::kTabGroupsSaveDescription, kOsDesktop,
-     FEATURE_WITH_PARAMS_VALUE_TYPE(features::kTabGroupsSave,
-                                    kTabGroupsSaveVariations,
-                                    "TabGroupsSave")},
+     FEATURE_VALUE_TYPE(features::kTabGroupsSave)},
 
     {flag_descriptions::kScrollableTabStripFlagId,
      flag_descriptions::kScrollableTabStripName,
@@ -9139,13 +9129,6 @@
                                     "MerchantWidePromotion")},
 #endif
 
-    {"autofill-enable-unmask-card-request-set-instrument-id",
-     flag_descriptions::kAutofillEnableUnmaskCardRequestSetInstrumentIdName,
-     flag_descriptions::
-         kAutofillEnableUnmaskCardRequestSetInstrumentIdDescription,
-     kOsAll,
-     FEATURE_VALUE_TYPE(
-         autofill::features::kAutofillEnableUnmaskCardRequestSetInstrumentId)},
     {"durable-client-hints-cache",
      flag_descriptions::kDurableClientHintsCacheName,
      flag_descriptions::kDurableClientHintsCacheDescription, kOsAll,
diff --git a/chrome/browser/android/examples/partner_browser_customizations_provider/OWNERS b/chrome/browser/android/examples/partner_browser_customizations_provider/OWNERS
index cc92f624..2bd624cb 100644
--- a/chrome/browser/android/examples/partner_browser_customizations_provider/OWNERS
+++ b/chrome/browser/android/examples/partner_browser_customizations_provider/OWNERS
@@ -1 +1 @@
-file://chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/OWNERS
+file://chrome/browser/partnercustomizations/OWNERS
diff --git a/chrome/browser/apps/app_preload_service/OWNERS b/chrome/browser/apps/app_preload_service/OWNERS
index 9caceea..929b116 100644
--- a/chrome/browser/apps/app_preload_service/OWNERS
+++ b/chrome/browser/apps/app_preload_service/OWNERS
@@ -1,2 +1,3 @@
 jshikaram@chromium.org
 melzhang@chromium.org
+tsergeant@chromium.org
diff --git a/chrome/browser/apps/app_service/app_service_proxy_base.cc b/chrome/browser/apps/app_service/app_service_proxy_base.cc
index 384d7c4a..eaa6ef1 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_base.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_base.cc
@@ -301,33 +301,6 @@
       });
 }
 
-void AppServiceProxyBase::Launch(const std::string& app_id,
-                                 int32_t event_flags,
-                                 apps::mojom::LaunchSource mojom_launch_source,
-                                 apps::mojom::WindowInfoPtr window_info) {
-  if (app_service_.is_connected()) {
-    app_registry_cache_.ForOneApp(
-        app_id, [this, event_flags, mojom_launch_source,
-                 &window_info](const apps::AppUpdate& update) {
-          if (MaybeShowLaunchPreventionDialog(update)) {
-            return;
-          }
-
-          apps::LaunchSource launch_source =
-              ConvertMojomLaunchSourceToLaunchSource(mojom_launch_source);
-          RecordAppLaunch(update.AppId(), launch_source);
-          RecordAppPlatformMetrics(profile_, update, launch_source,
-                                   apps::LaunchContainer::kLaunchContainerNone);
-
-          app_service_->Launch(ConvertAppTypeToMojomAppType(update.AppType()),
-                               update.AppId(), event_flags, mojom_launch_source,
-                               std::move(window_info));
-
-          PerformPostLaunchTasks(launch_source);
-        });
-  }
-}
-
 void AppServiceProxyBase::LaunchAppWithFiles(
     const std::string& app_id,
     int32_t event_flags,
diff --git a/chrome/browser/apps/app_service/app_service_proxy_base.h b/chrome/browser/apps/app_service/app_service_proxy_base.h
index 2ff93c0..b86b8c2 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_base.h
+++ b/chrome/browser/apps/app_service/app_service_proxy_base.h
@@ -143,12 +143,6 @@
               int32_t event_flags,
               apps::LaunchSource launch_source,
               apps::WindowInfoPtr window_info = nullptr);
-  // TODO(crbug.com/1253250): Will be removed soon. Please use the non mojom
-  // interface.
-  void Launch(const std::string& app_id,
-              int32_t event_flags,
-              apps::mojom::LaunchSource launch_source,
-              apps::mojom::WindowInfoPtr window_info = nullptr);
 
   // Launches the app for the given |app_id| with files from |file_paths|.
   // DEPRECATED. Prefer passing the files in an Intent through
diff --git a/chrome/browser/apps/app_service/app_service_proxy_desktop.cc b/chrome/browser/apps/app_service/app_service_proxy_desktop.cc
index 3f50e53..4e1b6d1c 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_desktop.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_desktop.cc
@@ -5,8 +5,7 @@
 #include "chrome/browser/apps/app_service/app_service_proxy_desktop.h"
 
 #include "chrome/browser/web_applications/app_service/web_app_publisher_helper.h"
-#include "chrome/browser/web_applications/commands/run_on_os_login_command.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"
 #include "components/services/app_service/app_service_mojom_impl.h"
 #include "components/services/app_service/public/cpp/app_types.h"
@@ -52,12 +51,10 @@
   if (app_type == apps::AppType::kWeb) {
     web_app::WebAppProvider* provider =
         web_app::WebAppProvider::GetForWebApps(profile_);
-    provider->command_manager().ScheduleCommand(
-        web_app::RunOnOsLoginCommand::CreateForSetLoginMode(
-            &provider->registrar(), &provider->os_integration_manager(),
-            &provider->sync_bridge(), app_id,
-            web_app::ConvertOsLoginModeToWebAppConstants(run_on_os_login_mode),
-            base::DoNothing()));
+    provider->scheduler().SetRunOnOsLoginMode(
+        app_id,
+        web_app::ConvertOsLoginModeToWebAppConstants(run_on_os_login_mode),
+        base::DoNothing());
   }
 }
 
diff --git a/chrome/browser/apps/app_service/app_service_proxy_lacros.cc b/chrome/browser/apps/app_service/app_service_proxy_lacros.cc
index a89a33e..400b405 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_lacros.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_lacros.cc
@@ -143,15 +143,6 @@
       this, app_id, event_flags, launch_source, display::kInvalidDisplayId));
 }
 
-void AppServiceProxyLacros::Launch(const std::string& app_id,
-                                   int32_t event_flags,
-                                   apps::mojom::LaunchSource launch_source,
-                                   apps::mojom::WindowInfoPtr window_info) {
-  Launch(app_id, event_flags,
-         ConvertMojomLaunchSourceToLaunchSource(launch_source),
-         ConvertMojomWindowInfoToWindowInfo(window_info));
-}
-
 void AppServiceProxyLacros::LaunchAppWithFiles(
     const std::string& app_id,
     int32_t event_flags,
diff --git a/chrome/browser/apps/app_service/app_service_proxy_lacros.h b/chrome/browser/apps/app_service/app_service_proxy_lacros.h
index f3cc0fa..0f234bf 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_lacros.h
+++ b/chrome/browser/apps/app_service/app_service_proxy_lacros.h
@@ -120,12 +120,6 @@
               int32_t event_flags,
               apps::LaunchSource launch_source,
               apps::WindowInfoPtr window_info = nullptr);
-  // TODO(crbug.com/1253250): Will be removed soon. Please use the non mojom
-  // interface.
-  void Launch(const std::string& app_id,
-              int32_t event_flags,
-              apps::mojom::LaunchSource launch_source,
-              apps::mojom::WindowInfoPtr window_info = nullptr);
 
   // Launches the app for the given |app_id| with files from |file_paths|.
   // DEPRECATED. Prefer passing the files in an Intent through
diff --git a/chrome/browser/apps/app_service/publishers/arc_apps.cc b/chrome/browser/apps/app_service/publishers/arc_apps.cc
index 5ed1c29c..fee93ee0 100644
--- a/chrome/browser/apps/app_service/publishers/arc_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/arc_apps.cc
@@ -965,14 +965,8 @@
                         std::make_unique<WindowInfo>(params.display_id),
                         base::DoNothing());
   } else {
-    if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-      Launch(params.app_id, event_flags, params.launch_source,
-             std::make_unique<WindowInfo>(params.display_id));
-    } else {
-      Launch(params.app_id, event_flags,
-             ConvertLaunchSourceToMojomLaunchSource(params.launch_source),
-             apps::MakeWindowInfo(params.display_id));
-    }
+    Launch(params.app_id, event_flags, params.launch_source,
+           std::make_unique<WindowInfo>(params.display_id));
   }
   // TODO(crbug.com/1244506): Add launch return value.
   std::move(callback).Run(LaunchResult());
diff --git a/chrome/browser/apps/app_service/publishers/borealis_apps.cc b/chrome/browser/apps/app_service/publishers/borealis_apps.cc
index d11741d0..27cd23c8 100644
--- a/chrome/browser/apps/app_service/publishers/borealis_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/borealis_apps.cc
@@ -381,12 +381,8 @@
 
 void BorealisApps::LaunchAppWithParams(AppLaunchParams&& params,
                                        LaunchCallback callback) {
-  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-    Launch(params.app_id, ui::EF_NONE, LaunchSource::kUnknown, nullptr);
-  } else {
-    Launch(params.app_id, ui::EF_NONE, apps::mojom::LaunchSource::kUnknown,
-           nullptr);
-  }
+  Launch(params.app_id, ui::EF_NONE, LaunchSource::kUnknown, nullptr);
+
   // TODO(crbug.com/1244506): Add launch return value.
   std::move(callback).Run(LaunchResult());
 }
diff --git a/chrome/browser/apps/app_service/publishers/built_in_chromeos_apps.cc b/chrome/browser/apps/app_service/publishers/built_in_chromeos_apps.cc
index 1d87be5..0a88885 100644
--- a/chrome/browser/apps/app_service/publishers/built_in_chromeos_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/built_in_chromeos_apps.cc
@@ -156,8 +156,8 @@
 
 void BuiltInChromeOsApps::LaunchAppWithParams(AppLaunchParams&& params,
                                               LaunchCallback callback) {
-  Launch(params.app_id, ui::EF_NONE, apps::mojom::LaunchSource::kUnknown,
-         nullptr);
+  Launch(params.app_id, ui::EF_NONE, LaunchSource::kUnknown, nullptr);
+
   // TODO(crbug.com/1244506): Add launch return value.
   std::move(callback).Run(LaunchResult());
 }
diff --git a/chrome/browser/apps/app_service/publishers/crostini_apps.cc b/chrome/browser/apps/app_service/publishers/crostini_apps.cc
index a26b61e..300889f 100644
--- a/chrome/browser/apps/app_service/publishers/crostini_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/crostini_apps.cc
@@ -219,14 +219,8 @@
                         std::make_unique<WindowInfo>(params.display_id),
                         base::DoNothing());
   } else {
-    if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-      Launch(params.app_id, event_flags, params.launch_source,
-             std::make_unique<WindowInfo>(params.display_id));
-    } else {
-      Launch(params.app_id, event_flags,
-             ConvertLaunchSourceToMojomLaunchSource(params.launch_source),
-             std::move(window_info));
-    }
+    Launch(params.app_id, event_flags, params.launch_source,
+           std::make_unique<WindowInfo>(params.display_id));
   }
   // TODO(crbug.com/1244506): Add launch return value.
   std::move(callback).Run(LaunchResult());
diff --git a/chrome/browser/apps/app_service/publishers/plugin_vm_apps.cc b/chrome/browser/apps/app_service/publishers/plugin_vm_apps.cc
index 6dcfcad..63584c01 100644
--- a/chrome/browser/apps/app_service/publishers/plugin_vm_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/plugin_vm_apps.cc
@@ -339,12 +339,8 @@
 
 void PluginVmApps::LaunchAppWithParams(AppLaunchParams&& params,
                                        LaunchCallback callback) {
-  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-    Launch(params.app_id, ui::EF_NONE, LaunchSource::kUnknown, nullptr);
-  } else {
-    Launch(params.app_id, ui::EF_NONE, apps::mojom::LaunchSource::kUnknown,
-           nullptr);
-  }
+  Launch(params.app_id, ui::EF_NONE, LaunchSource::kUnknown, nullptr);
+
   // TODO(crbug.com/1244506): Add launch return value.
   std::move(callback).Run(LaunchResult());
 }
diff --git a/chrome/browser/apps/app_service/publishers/remote_apps.cc b/chrome/browser/apps/app_service/publishers/remote_apps.cc
index 44785a6..985c6bf 100644
--- a/chrome/browser/apps/app_service/publishers/remote_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/remote_apps.cc
@@ -140,12 +140,8 @@
 
 void RemoteApps::LaunchAppWithParams(AppLaunchParams&& params,
                                      LaunchCallback callback) {
-  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-    Launch(params.app_id, ui::EF_NONE, LaunchSource::kUnknown, nullptr);
-  } else {
-    Launch(params.app_id, ui::EF_NONE, apps::mojom::LaunchSource::kUnknown,
-           nullptr);
-  }
+  Launch(params.app_id, ui::EF_NONE, LaunchSource::kUnknown, nullptr);
+
   // TODO(crbug.com/1244506): Add launch return value.
   std::move(callback).Run(LaunchResult());
 }
diff --git a/chrome/browser/apps/app_service/publishers/standalone_browser_apps.cc b/chrome/browser/apps/app_service/publishers/standalone_browser_apps.cc
index 219cffff..19b51c9 100644
--- a/chrome/browser/apps/app_service/publishers/standalone_browser_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/standalone_browser_apps.cc
@@ -168,12 +168,8 @@
 
 void StandaloneBrowserApps::LaunchAppWithParams(AppLaunchParams&& params,
                                                 LaunchCallback callback) {
-  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-    Launch(params.app_id, ui::EF_NONE, LaunchSource::kUnknown, nullptr);
-  } else {
-    Launch(params.app_id, ui::EF_NONE, apps::mojom::LaunchSource::kUnknown,
-           nullptr);
-  }
+  Launch(params.app_id, ui::EF_NONE, LaunchSource::kUnknown, nullptr);
+
   // TODO(crbug.com/1244506): Add launch return value.
   std::move(callback).Run(LaunchResult());
 }
diff --git a/chrome/browser/apps/platform_apps/app_browsertest.cc b/chrome/browser/apps/platform_apps/app_browsertest.cc
index 52962cb..7b7d246 100644
--- a/chrome/browser/apps/platform_apps/app_browsertest.cc
+++ b/chrome/browser/apps/platform_apps/app_browsertest.cc
@@ -1333,7 +1333,7 @@
       ->Launch(file_manager->id(),
                apps::GetEventFlags(WindowOpenDisposition::NEW_FOREGROUND_TAB,
                                    true /* prefer_container */),
-               apps::mojom::LaunchSource::kFromTest);
+               apps::LaunchSource::kFromTest);
 
   while (!base::Contains(opener_app_ids_, file_manager->id())) {
     content::RunAllPendingInMessageLoop();
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index f0eb82d..e4405ea 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -1336,6 +1336,8 @@
     "input_method/native_input_method_engine_observer.h",
     "input_method/personal_info_suggester.cc",
     "input_method/personal_info_suggester.h",
+    "input_method/screen_projection_change_monitor.cc",
+    "input_method/screen_projection_change_monitor.h",
     "input_method/suggester.h",
     "input_method/suggestion_enums.h",
     "input_method/suggestion_handler_interface.h",
@@ -4540,6 +4542,7 @@
     "input_method/native_input_method_engine_observer_unittest.cc",
     "input_method/native_input_method_engine_unittest.cc",
     "input_method/personal_info_suggester_unittest.cc",
+    "input_method/screen_projection_change_monitor_unittest.cc",
     "input_method/suggestions_collector_unittest.cc",
     "input_method/suggestions_service_client_unittest.cc",
     "input_method/text_utils_unittest.cc",
diff --git a/chrome/browser/ash/android_sms/android_sms_app_manager_impl.cc b/chrome/browser/ash/android_sms/android_sms_app_manager_impl.cc
index 476c2ab6..a79130f3 100644
--- a/chrome/browser/ash/android_sms/android_sms_app_manager_impl.cc
+++ b/chrome/browser/ash/android_sms/android_sms_app_manager_impl.cc
@@ -21,7 +21,6 @@
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
-#include "components/services/app_service/public/cpp/features.h"
 
 namespace ash {
 namespace android_sms {
@@ -47,19 +46,11 @@
 
 void AndroidSmsAppManagerImpl::PwaDelegate::OpenApp(Profile* profile,
                                                     const std::string& app_id) {
-  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-    apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
-        app_id,
-        apps::GetEventFlags(WindowOpenDisposition::NEW_WINDOW,
-                            false /* preferred_containner */),
-        apps::LaunchSource::kFromChromeInternal);
-  } else {
-    apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
-        app_id,
-        apps::GetEventFlags(WindowOpenDisposition::NEW_WINDOW,
-                            false /* preferred_containner */),
-        apps::mojom::LaunchSource::kFromChromeInternal);
-  }
+  apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
+      app_id,
+      apps::GetEventFlags(WindowOpenDisposition::NEW_WINDOW,
+                          false /* preferred_containner */),
+      apps::LaunchSource::kFromChromeInternal);
 }
 
 bool AndroidSmsAppManagerImpl::PwaDelegate::TransferItemAttributes(
diff --git a/chrome/browser/ash/app_restore/arc_app_queue_restore_handler.cc b/chrome/browser/ash/app_restore/arc_app_queue_restore_handler.cc
index 958b5ee..1dc7c25 100644
--- a/chrome/browser/ash/app_restore/arc_app_queue_restore_handler.cc
+++ b/chrome/browser/ash/app_restore/arc_app_queue_restore_handler.cc
@@ -47,10 +47,8 @@
 #include "components/exo/wm_helper.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/app_types.h"
-#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/types_util.h"
-#include "components/services/app_service/public/mojom/types.mojom.h"
 #include "ui/display/display.h"
 #include "ui/wm/public/activation_client.h"
 
@@ -663,15 +661,8 @@
                                apps::LaunchSource::kFromFullRestore,
                                std::move(window_info), base::DoNothing());
   } else {
-    if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-      proxy->Launch(app_id, app_restore_data->event_flag.value(),
-                    apps::LaunchSource::kFromFullRestore,
-                    std::move(window_info));
-    } else {
-      proxy->Launch(app_id, app_restore_data->event_flag.value(),
-                    apps::mojom::LaunchSource::kFromFullRestore,
-                    ConvertWindowInfoToMojomWindowInfo(window_info));
-    }
+    proxy->Launch(app_id, app_restore_data->event_flag.value(),
+                  apps::LaunchSource::kFromFullRestore, std::move(window_info));
   }
 
   if (!HasRestoreData())
diff --git a/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper.cc b/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper.cc
index d411cb84..5714f4926 100644
--- a/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper.cc
+++ b/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper.cc
@@ -20,11 +20,9 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/app_update.h"
-#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/cpp/icon_types.h"
 #include "components/services/app_service/public/cpp/instance_update.h"
 #include "components/services/app_service/public/cpp/types_util.h"
-#include "components/services/app_service/public/mojom/types.mojom.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
@@ -100,15 +98,9 @@
 }
 
 void AppServiceWrapper::LaunchApp(const std::string& app_service_id) {
-  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-    GetAppProxy()->Launch(
-        app_service_id, ui::EF_NONE, apps::LaunchSource::kFromParentalControls,
-        std::make_unique<apps::WindowInfo>(display::kDefaultDisplayId));
-  } else {
-    GetAppProxy()->Launch(app_service_id, ui::EF_NONE,
-                          apps::mojom::LaunchSource::kFromParentalControls,
-                          apps::MakeWindowInfo(display::kDefaultDisplayId));
-  }
+  GetAppProxy()->Launch(
+      app_service_id, ui::EF_NONE, apps::LaunchSource::kFromParentalControls,
+      std::make_unique<apps::WindowInfo>(display::kDefaultDisplayId));
 }
 
 std::vector<AppId> AppServiceWrapper::GetInstalledApps() const {
diff --git a/chrome/browser/ash/enhanced_network_tts/DIR_METADATA b/chrome/browser/ash/enhanced_network_tts/DIR_METADATA
new file mode 100644
index 0000000..6cacb6d
--- /dev/null
+++ b/chrome/browser/ash/enhanced_network_tts/DIR_METADATA
@@ -0,0 +1 @@
+mixins: "//chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/COMMON_METADATA"
diff --git a/chrome/browser/ash/extensions/speech/DIR_METADATA b/chrome/browser/ash/extensions/speech/DIR_METADATA
new file mode 100644
index 0000000..43ecd79
--- /dev/null
+++ b/chrome/browser/ash/extensions/speech/DIR_METADATA
@@ -0,0 +1 @@
+mixins: "//extensions/renderer/api/automation/COMMON_METADATA"
diff --git a/chrome/browser/ash/file_manager/volume_manager_unittest.cc b/chrome/browser/ash/file_manager/volume_manager_unittest.cc
index e8cc9d6..2d0382ea 100644
--- a/chrome/browser/ash/file_manager/volume_manager_unittest.cc
+++ b/chrome/browser/ash/file_manager/volume_manager_unittest.cc
@@ -22,12 +22,14 @@
 #include "base/memory/weak_ptr.h"
 #include "base/notreached.h"
 #include "base/ranges/algorithm.h"
+#include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_running_on_chromeos.h"
 #include "chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.h"
 #include "chrome/browser/ash/arc/fileapi/arc_media_view_util.h"
 #include "chrome/browser/ash/drive/file_system_util.h"
 #include "chrome/browser/ash/file_manager/fake_disk_mount_manager.h"
+#include "chrome/browser/ash/file_manager/path_util.h"
 #include "chrome/browser/ash/file_manager/volume_manager_observer.h"
 #include "chrome/browser/ash/file_system_provider/fake_extension_provider.h"
 #include "chrome/browser/ash/file_system_provider/service.h"
@@ -1219,31 +1221,41 @@
       FILE_PATH_LITERAL("/dummy/device/location2"), u"label2", u"vendor2",
       u"model2", 12345 /* size */);
 
-  // Attach.
-  //
-  // There should be two events: one each for the Fusebox and non-Fusebox MTP
-  // volumes.
+  // Attach: expect mount events for the MTP and fusebox MTP volumes.
   volume_manager()->OnRemovableStorageAttached(info);
   ASSERT_EQ(2u, observer.events().size());
   EXPECT_EQ(LoggingObserver::Event::VOLUME_MOUNTED, observer.events()[0].type);
+  EXPECT_EQ(LoggingObserver::Event::VOLUME_MOUNTED, observer.events()[1].type);
 
+  // The MTP volume should be mounted.
   base::WeakPtr<Volume> volume = volume_manager()->FindVolumeById("mtp:model");
   ASSERT_TRUE(volume);
+  EXPECT_EQ("", volume->file_system_type());
   EXPECT_EQ(VOLUME_TYPE_MTP, volume->type());
 
-  // Non MTP events from storage monitor are ignored.
+  // The fusebox MTP volume should be mounted.
+  const auto fusebox_volume_id = base::StrCat({util::kFuseBox, "mtp:model"});
+  base::WeakPtr<Volume> fusebox_volume =
+      volume_manager()->FindVolumeById(fusebox_volume_id);
+  ASSERT_TRUE(fusebox_volume);
+  EXPECT_EQ(util::kFuseBox, fusebox_volume->file_system_type());
+  EXPECT_EQ(VOLUME_TYPE_MTP, fusebox_volume->type());
+
+  // Non MTP attach events from storage monitor are ignored.
   volume_manager()->OnRemovableStorageAttached(non_mtp_info);
   EXPECT_EQ(2u, observer.events().size());
 
-  // Detach.
-  //
-  // There should be two more events, bringing the total to four.
+  // Detach: there should be two more events, bringing the total to four.
   volume_manager()->OnRemovableStorageDetached(info);
   ASSERT_EQ(4u, observer.events().size());
   EXPECT_EQ(LoggingObserver::Event::VOLUME_UNMOUNTED,
             observer.events()[2].type);
+  EXPECT_EQ(LoggingObserver::Event::VOLUME_UNMOUNTED,
+            observer.events()[3].type);
 
+  // The unmount events should remove the MTP and fusebox MTP volumes.
   EXPECT_FALSE(volume);
+  EXPECT_FALSE(fusebox_volume);
 
   volume_manager()->RemoveObserver(&observer);
 }
diff --git a/chrome/browser/ash/input_method/assistive_suggester_unittest.cc b/chrome/browser/ash/input_method/assistive_suggester_unittest.cc
index 7d76883..85d6793 100644
--- a/chrome/browser/ash/input_method/assistive_suggester_unittest.cc
+++ b/chrome/browser/ash/input_method/assistive_suggester_unittest.cc
@@ -304,7 +304,9 @@
 
 TEST_F(AssistiveSuggesterTest,
        AssistiveDiacriticsLongpressFlagDisabled_AssistiveFeatureDisabled) {
-  // Feature flag not enabled by default.
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(
+      features::kDiacriticsOnPhysicalKeyboardLongpress);
   SetInputMethodOptions(*profile_, /*predictive_writing_enabled=*/false,
                         /*diacritics_on_longpress_enabled=*/true);
   assistive_suggester_->OnActivate(kUsEnglishEngineId);
diff --git a/chrome/browser/ash/input_method/input_method_engine.cc b/chrome/browser/ash/input_method/input_method_engine.cc
index b6f05ae..0ab720f 100644
--- a/chrome/browser/ash/input_method/input_method_engine.cc
+++ b/chrome/browser/ash/input_method/input_method_engine.cc
@@ -94,7 +94,12 @@
       profile_(nullptr),
       composition_changed_(false),
       commit_text_changed_(false),
-      pref_change_registrar_(nullptr) {}
+      pref_change_registrar_(nullptr),
+      // This is safe because the callback does not outlive
+      // screen_projection_change_monitor_, which is a member of this class.
+      screen_projection_change_monitor_(
+          base::BindRepeating(&InputMethodEngine::OnScreenProjectionChanged,
+                              base::Unretained(this))) {}
 
 InputMethodEngine::~InputMethodEngine() = default;
 
@@ -235,7 +240,7 @@
     properties[ui::kPropertyFromVK] =
         std::vector<uint8_t>(ui::kPropertyFromVKSize);
     properties[ui::kPropertyFromVK][ui::kPropertyFromVKIsMirroringIndex] =
-        (uint8_t)is_mirroring_;
+        static_cast<uint8_t>(screen_projection_change_monitor_.is_mirroring());
     event_copy.SetProperties(properties);
 
     ui::TextInputTarget* input_context =
@@ -691,20 +696,6 @@
   observer_->OnAssistiveWindowChanged(window);
 }
 
-void InputMethodEngine::SetMirroringEnabled(bool mirroring_enabled) {
-  if (mirroring_enabled != is_mirroring_) {
-    is_mirroring_ = mirroring_enabled;
-    observer_->OnScreenProjectionChanged(is_mirroring_ || is_casting_);
-  }
-}
-
-void InputMethodEngine::SetCastingEnabled(bool casting_enabled) {
-  if (casting_enabled != is_casting_) {
-    is_casting_ = casting_enabled;
-    observer_->OnScreenProjectionChanged(is_mirroring_ || is_casting_);
-  }
-}
-
 ui::VirtualKeyboardController* InputMethodEngine::GetVirtualKeyboardController()
     const {
   // Callers expect a nullptr when the keyboard is disabled. See
@@ -1115,6 +1106,12 @@
   // TODO(nona): Support item.children.
 }
 
+void InputMethodEngine::OnScreenProjectionChanged(bool is_projected) {
+  if (observer_) {
+    observer_->OnScreenProjectionChanged(is_projected);
+  }
+}
+
 void InputMethodEngine::NotifyInputMethodExtensionReadyForTesting() {
   is_ready_for_testing_ = true;
 }
diff --git a/chrome/browser/ash/input_method/input_method_engine.h b/chrome/browser/ash/input_method/input_method_engine.h
index 7f06d4c6..a8d0db7 100644
--- a/chrome/browser/ash/input_method/input_method_engine.h
+++ b/chrome/browser/ash/input_method/input_method_engine.h
@@ -18,6 +18,7 @@
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/ash/input_method/assistive_window_properties.h"
 #include "chrome/browser/ash/input_method/input_method_engine_observer.h"
+#include "chrome/browser/ash/input_method/screen_projection_change_monitor.h"
 #include "chrome/browser/ash/input_method/suggestion_handler_interface.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_observer.h"
@@ -244,8 +245,6 @@
   void AssistiveWindowButtonClicked(
       const ui::ime::AssistiveWindowButton& button) override;
   void AssistiveWindowChanged(const ash::ime::AssistiveWindow& window) override;
-  void SetMirroringEnabled(bool mirroring_enabled) override;
-  void SetCastingEnabled(bool casting_enabled) override;
   ui::VirtualKeyboardController* GetVirtualKeyboardController() const override;
   bool IsReadyForTesting() override;
 
@@ -341,6 +340,8 @@
   void MenuItemToProperty(const InputMethodManager::MenuItem& item,
                           ui::ime::InputMethodMenuItem* property);
 
+  void OnScreenProjectionChanged(bool is_projected);
+
   // The current candidate window.
   ui::CandidateWindow candidate_window_;
 
@@ -356,12 +357,6 @@
   // Mapping of candidate id to index.
   std::map<int, int> candidate_indexes_;
 
-  // Whether the screen is in mirroring mode.
-  bool is_mirroring_ = false;
-
-  // Whether the desktop is being casted.
-  bool is_casting_ = false;
-
   ui::TextInputType current_input_type_;
 
   // ID that is used for the current input context.  False if there is no focus.
@@ -400,6 +395,8 @@
 
   base::Value::Dict input_method_settings_snapshot_;
 
+  ScreenProjectionChangeMonitor screen_projection_change_monitor_;
+
   bool is_ready_for_testing_ = false;
 
   base::ScopedObservation<Profile, ProfileObserver> profile_observation_{this};
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 e7a1d50a..d0931f20 100644
--- a/chrome/browser/ash/input_method/mock_input_method_engine.h
+++ b/chrome/browser/ash/input_method/mock_input_method_engine.h
@@ -50,8 +50,8 @@
   void PropertyActivate(const std::string& property_name) override;
   void CandidateClicked(uint32_t index) override;
   void AssistiveWindowChanged(const ash::ime::AssistiveWindow& window) override;
-  void SetMirroringEnabled(bool mirroring_enabled) override;
-  void SetCastingEnabled(bool casting_enabled) override;
+  void SetMirroringEnabled(bool mirroring_enabled);
+  void SetCastingEnabled(bool casting_enabled);
   bool IsReadyForTesting() override;
 
   const std::string& GetActiveComponentId() const;
diff --git a/chrome/browser/ash/input_method/screen_projection_change_monitor.cc b/chrome/browser/ash/input_method/screen_projection_change_monitor.cc
new file mode 100644
index 0000000..1553262
--- /dev/null
+++ b/chrome/browser/ash/input_method/screen_projection_change_monitor.cc
@@ -0,0 +1,93 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/input_method/screen_projection_change_monitor.h"
+
+#include "ash/public/cpp/cast_config_controller.h"
+#include "ash/shell.h"
+#include "ash/system/tray/system_tray_notifier.h"
+#include "ui/display/manager/display_manager.h"
+
+namespace ash::input_method {
+
+ScreenProjectionChangeMonitor::ScreenProjectionChangeMonitor(
+    OnScreenProjectionChangedCallback callback)
+    : callback_(std::move(callback)) {
+  // Unfortunately, the lifetimes of the observees are tricky so we cannot use a
+  // ScopedObservation here. Manually manage the observer lifetimes.
+  // Shell::Get() and CastConfigController::Get() might be null in tests.
+  if (Shell::HasInstance()) {
+    Shell::Get()->display_manager()->AddObserver(this);
+    Shell::Get()->system_tray_notifier()->AddScreenCaptureObserver(this);
+  }
+
+  if (CastConfigController::Get()) {
+    CastConfigController::Get()->AddObserver(this);
+  }
+}
+
+ScreenProjectionChangeMonitor::~ScreenProjectionChangeMonitor() {
+  if (CastConfigController::Get()) {
+    CastConfigController::Get()->RemoveObserver(this);
+  }
+
+  if (Shell::HasInstance()) {
+    Shell::Get()->system_tray_notifier()->RemoveScreenCaptureObserver(this);
+    Shell::Get()->display_manager()->RemoveObserver(this);
+  }
+}
+
+bool ScreenProjectionChangeMonitor::is_mirroring() const {
+  return is_mirroring_;
+}
+
+void ScreenProjectionChangeMonitor::OnDisplayMetricsChanged(
+    const display::Display& display,
+    uint32_t changed_metrics) {
+  if (changed_metrics & display::DisplayObserver::DISPLAY_METRIC_MIRROR_STATE) {
+    UpdateCastingAndMirroringState(
+        is_casting_, Shell::Get()->display_manager()->IsInMirrorMode());
+  }
+}
+
+void ScreenProjectionChangeMonitor::OnDevicesUpdated(
+    const std::vector<SinkAndRoute>& devices) {
+  bool casting_desktop = false;
+  for (const auto& receiver : devices) {
+    if (receiver.route.content_source == ContentSource::kDesktop) {
+      casting_desktop = true;
+      break;
+    }
+  }
+  UpdateCastingAndMirroringState(casting_desktop, is_mirroring_);
+}
+
+void ScreenProjectionChangeMonitor::OnScreenCaptureStart(
+    base::OnceClosure stop_callback,
+    const base::RepeatingClosure& source_callback,
+    const std::u16string& screen_capture_status) {
+  UpdateCastingAndMirroringState(true, is_mirroring_);
+}
+
+void ScreenProjectionChangeMonitor::OnScreenCaptureStop() {
+  UpdateCastingAndMirroringState(false, is_mirroring_);
+}
+
+bool ScreenProjectionChangeMonitor::IsProjecting() const {
+  return is_casting_ || is_mirroring_;
+}
+
+void ScreenProjectionChangeMonitor::UpdateCastingAndMirroringState(
+    bool is_casting,
+    bool is_mirroring) {
+  bool was_projecting = IsProjecting();
+  is_casting_ = is_casting;
+  is_mirroring_ = is_mirroring;
+  bool is_projecting = IsProjecting();
+  if (was_projecting != is_projecting) {
+    callback_.Run(is_projecting);
+  }
+}
+
+}  // namespace ash::input_method
diff --git a/chrome/browser/ash/input_method/screen_projection_change_monitor.h b/chrome/browser/ash/input_method/screen_projection_change_monitor.h
new file mode 100644
index 0000000..bd1692c
--- /dev/null
+++ b/chrome/browser/ash/input_method/screen_projection_change_monitor.h
@@ -0,0 +1,58 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_INPUT_METHOD_SCREEN_PROJECTION_CHANGE_MONITOR_H_
+#define CHROME_BROWSER_ASH_INPUT_METHOD_SCREEN_PROJECTION_CHANGE_MONITOR_H_
+
+#include "ash/ash_export.h"
+#include "ash/public/cpp/cast_config_controller.h"
+#include "ash/system/privacy/screen_capture_observer.h"
+#include "ui/display/display_observer.h"
+
+namespace ash::input_method {
+
+// Monitors changes to the screen projection (casting or mirroring) status.
+// Assumes the default state is no casting nor mirroring.
+class ASH_EXPORT ScreenProjectionChangeMonitor
+    : public display::DisplayObserver,
+      public CastConfigController::Observer,
+      public ScreenCaptureObserver {
+ public:
+  using OnScreenProjectionChangedCallback =
+      base::RepeatingCallback<void(bool is_projected)>;
+
+  explicit ScreenProjectionChangeMonitor(
+      OnScreenProjectionChangedCallback callback);
+  ~ScreenProjectionChangeMonitor() override;
+
+  bool is_mirroring() const;
+
+ private:
+  // display::DisplayObserver:
+  void OnDisplayMetricsChanged(const display::Display& display,
+                               uint32_t changed_metrics) override;
+
+  // CastConfigController::Observer:
+  void OnDevicesUpdated(const std::vector<SinkAndRoute>& devices) override;
+
+  // ScreenCaptureObserver:
+  void OnScreenCaptureStart(
+      base::OnceClosure stop_callback,
+      const base::RepeatingClosure& source_callback,
+      const std::u16string& screen_capture_status) override;
+  void OnScreenCaptureStop() override;
+
+  bool IsProjecting() const;
+
+  void UpdateCastingAndMirroringState(bool is_casting, bool is_mirroring);
+
+  OnScreenProjectionChangedCallback callback_;
+
+  bool is_casting_ = false;
+  bool is_mirroring_ = false;
+};
+
+}  // namespace ash::input_method
+
+#endif  // CHROME_BROWSER_ASH_INPUT_METHOD_SCREEN_PROJECTION_CHANGE_MONITOR_H_
diff --git a/chrome/browser/ash/input_method/screen_projection_change_monitor_unittest.cc b/chrome/browser/ash/input_method/screen_projection_change_monitor_unittest.cc
new file mode 100644
index 0000000..274ca4a
--- /dev/null
+++ b/chrome/browser/ash/input_method/screen_projection_change_monitor_unittest.cc
@@ -0,0 +1,71 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/input_method/screen_projection_change_monitor.h"
+
+#include "ash/shell.h"
+#include "ash/system/tray/system_tray_notifier.h"
+#include "ash/test/ash_test_base.h"
+#include "base/test/repeating_test_future.h"
+#include "chrome/browser/ui/ash/cast_config_controller_media_router.h"
+#include "ui/display/manager/display_manager.h"
+
+namespace ash::input_method {
+
+namespace {
+
+using base::test::RepeatingTestFuture;
+using ScreenProjectionChangeMonitorTest = AshTestBase;
+
+TEST_F(ScreenProjectionChangeMonitorTest, MirroringChangeTriggersCallback) {
+  CastConfigControllerMediaRouter cast_config;
+  RepeatingTestFuture<bool> monitor_future;
+  ScreenProjectionChangeMonitor monitor(monitor_future.GetCallback());
+
+  // Turn on mirroring.
+  UpdateDisplay("600x500,600x500");
+  display::DisplayManager* display_manager = Shell::Get()->display_manager();
+  display_manager->SetMultiDisplayMode(display::DisplayManager::MIRRORING);
+  display_manager->UpdateDisplays();
+  // Turn off mirroring.
+  UpdateDisplay("600x500");
+
+  EXPECT_TRUE(monitor_future.Take());
+  EXPECT_FALSE(monitor_future.Take());
+}
+
+TEST_F(ScreenProjectionChangeMonitorTest, ScreenSharingChangeTriggersCallback) {
+  CastConfigControllerMediaRouter cast_config;
+  RepeatingTestFuture<bool> monitor_future;
+  ScreenProjectionChangeMonitor monitor(monitor_future.GetCallback());
+
+  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStart(
+      base::DoNothing(), base::DoNothing(), u"");
+  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStop();
+
+  EXPECT_TRUE(monitor_future.Take());
+  EXPECT_FALSE(monitor_future.Take());
+}
+
+TEST_F(ScreenProjectionChangeMonitorTest, NoChangeDoesNotTriggerCallback) {
+  CastConfigControllerMediaRouter cast_config;
+  RepeatingTestFuture<bool> monitor_future;
+  ScreenProjectionChangeMonitor monitor(monitor_future.GetCallback());
+
+  UpdateDisplay("600x500,600x500");
+  display::DisplayManager* display_manager = Shell::Get()->display_manager();
+  display_manager->SetMultiDisplayMode(display::DisplayManager::MIRRORING);
+  display_manager->UpdateDisplays();
+  // Turning on screen capture will not change the screen projection state
+  // because we are already mirroring.
+  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStart(
+      base::DoNothing(), base::DoNothing(), u"");
+
+  EXPECT_TRUE(monitor_future.Take());
+  EXPECT_TRUE(monitor_future.IsEmpty());
+}
+
+}  // namespace
+
+}  // namespace ash::input_method
diff --git a/chrome/browser/ash/note_taking_helper.cc b/chrome/browser/ash/note_taking_helper.cc
index c9b2bb4..96e28423 100644
--- a/chrome/browser/ash/note_taking_helper.cc
+++ b/chrome/browser/ash/note_taking_helper.cc
@@ -53,12 +53,10 @@
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/app_update.h"
-#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/intent_filter.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "components/services/app_service/public/cpp/types_util.h"
-#include "components/services/app_service/public/mojom/types.mojom-shared.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/api/app_runtime.h"
@@ -219,13 +217,8 @@
         app_id, ui::EF_NONE, apps_util::CreateCreateNoteIntent(),
         apps::LaunchSource::kFromShelf, nullptr, base::DoNothing());
   } else {
-    if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-      apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
-          app_id, ui::EF_NONE, apps::LaunchSource::kFromShelf);
-    } else {
-      apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
-          app_id, ui::EF_NONE, apps::mojom::LaunchSource::kFromShelf);
-    }
+    apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
+        app_id, ui::EF_NONE, apps::LaunchSource::kFromShelf);
   }
 
   return NoteTakingHelper::LaunchResult::WEB_APP_SUCCESS;
diff --git a/chrome/browser/ash/notifications/deprecation_notification_controller.cc b/chrome/browser/ash/notifications/deprecation_notification_controller.cc
index 5229d51..be8673c8 100644
--- a/chrome/browser/ash/notifications/deprecation_notification_controller.cc
+++ b/chrome/browser/ash/notifications/deprecation_notification_controller.cc
@@ -6,6 +6,7 @@
 
 #include <string>
 
+#include "ash/accelerators/accelerator_controller_impl.h"
 #include "ash/constants/notifier_catalogs.h"
 #include "ash/public/cpp/notification_utils.h"
 #include "ash/resources/vector_icons/vector_icons.h"
@@ -115,7 +116,13 @@
 
 bool DeprecationNotificationController::
     ShouldShowSixPackKeyDeprecationNotification(ui::KeyboardCode key_code) {
-  return !shown_key_notifications_.contains(key_code);
+  const auto* accelerator_controller = Shell::Get()->accelerator_controller();
+  DCHECK(accelerator_controller);
+
+  // Six pack key notification should not show if accelerators are being blocked
+  // as the user does not expect these keys to be interpreted as a six pack key.
+  return !accelerator_controller->ShouldPreventProcessingAccelerators() &&
+         !shown_key_notifications_.contains(key_code);
 }
 
 void DeprecationNotificationController::
diff --git a/chrome/browser/ash/notifications/deprecation_notification_controller_unittest.cc b/chrome/browser/ash/notifications/deprecation_notification_controller_unittest.cc
index 5270293..754eff5 100644
--- a/chrome/browser/ash/notifications/deprecation_notification_controller_unittest.cc
+++ b/chrome/browser/ash/notifications/deprecation_notification_controller_unittest.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/ash/notifications/deprecation_notification_controller.h"
 
+#include "ash/accelerators/accelerator_controller_impl.h"
+#include "ash/shell.h"
+#include "ash/test/ash_test_base.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/message_center/fake_message_center.h"
 
@@ -11,7 +14,7 @@
 
 namespace {
 
-class DeprecationNotificationControllerTest : public testing::Test {
+class DeprecationNotificationControllerTest : public AshTestBase {
  protected:
   DeprecationNotificationControllerTest() : controller_(&message_center_) {}
   DeprecationNotificationControllerTest(
@@ -62,4 +65,50 @@
   EXPECT_EQ(message_center_.NotificationCount(), 0u);
 }
 
+// Test that six pack notifications are not displayed when accelerators are
+// blocked.
+TEST_F(DeprecationNotificationControllerTest,
+       SixPackNotificationsBlockedWithShortcuts) {
+  // Block shortcuts and attempt to create notifications. Since shortcuts are
+  // blocked, no notifications should be created.
+  Shell::Get()->accelerator_controller()->SetPreventProcessingAccelerators(
+      /*prevent_processing_accelerators=*/true);
+
+  controller_.NotifyDeprecatedSixPackKeyRewrite(ui::VKEY_DELETE);
+  EXPECT_EQ(message_center_.NotificationCount(), 0u);
+  controller_.NotifyDeprecatedSixPackKeyRewrite(ui::VKEY_INSERT);
+  EXPECT_EQ(message_center_.NotificationCount(), 0u);
+  controller_.NotifyDeprecatedSixPackKeyRewrite(ui::VKEY_HOME);
+  EXPECT_EQ(message_center_.NotificationCount(), 0u);
+  controller_.NotifyDeprecatedSixPackKeyRewrite(ui::VKEY_END);
+  EXPECT_EQ(message_center_.NotificationCount(), 0u);
+  controller_.NotifyDeprecatedSixPackKeyRewrite(ui::VKEY_PRIOR);
+  EXPECT_EQ(message_center_.NotificationCount(), 0u);
+  controller_.NotifyDeprecatedSixPackKeyRewrite(ui::VKEY_NEXT);
+  EXPECT_EQ(message_center_.NotificationCount(), 0u);
+
+  // Clear the messages from the message center.
+  message_center_.RemoveAllNotifications(
+      /*by_user=*/false, message_center::FakeMessageCenter::RemoveType::ALL);
+
+  // Unblock shortcuts and then publish notifications, notifications should now
+  // publish as expected.
+  Shell::Get()->accelerator_controller()->SetPreventProcessingAccelerators(
+      /*prevent_processing_accelerators=*/false);
+
+  size_t expected_notification_count = 1;
+  controller_.NotifyDeprecatedSixPackKeyRewrite(ui::VKEY_DELETE);
+  EXPECT_EQ(message_center_.NotificationCount(), expected_notification_count++);
+  controller_.NotifyDeprecatedSixPackKeyRewrite(ui::VKEY_INSERT);
+  EXPECT_EQ(message_center_.NotificationCount(), expected_notification_count++);
+  controller_.NotifyDeprecatedSixPackKeyRewrite(ui::VKEY_HOME);
+  EXPECT_EQ(message_center_.NotificationCount(), expected_notification_count++);
+  controller_.NotifyDeprecatedSixPackKeyRewrite(ui::VKEY_END);
+  EXPECT_EQ(message_center_.NotificationCount(), expected_notification_count++);
+  controller_.NotifyDeprecatedSixPackKeyRewrite(ui::VKEY_PRIOR);
+  EXPECT_EQ(message_center_.NotificationCount(), expected_notification_count++);
+  controller_.NotifyDeprecatedSixPackKeyRewrite(ui::VKEY_NEXT);
+  EXPECT_EQ(message_center_.NotificationCount(), expected_notification_count++);
+}
+
 }  // namespace ash
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.cc
index 4728186..58dc41a 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.cc
@@ -50,7 +50,6 @@
     Profile* profile,
     std::unique_ptr<AppEventsObserver::Delegate> delegate)
     : profile_(profile), delegate_(std::move(delegate)) {
-  DCHECK(profile_);
   if (!delegate_->IsAppServiceAvailableForProfile(profile)) {
     // Profile cannot run apps, so we just return.
     return;
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.cc
index 7aa0bea..b400aca 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.cc
@@ -11,9 +11,11 @@
 
 #include "base/check.h"
 #include "base/containers/contains.h"
+#include "base/feature_list.h"
 #include "base/location.h"
 #include "base/strings/string_piece.h"
 #include "base/values.h"
+#include "chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.h"
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/audio/audio_events_observer.h"
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.h"
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/network/https_latency_event_detector.h"
@@ -52,6 +54,11 @@
 
 }  // namespace
 
+// static
+BASE_FEATURE(kEnableAppMetricsReporting,
+             "EnableAppMetricsReporting",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 bool MetricReportingManager::Delegate::IsAffiliated(Profile* profile) const {
   const user_manager::User* const user =
       ::ash::ProfileHelper::Get()->GetUserByProfile(profile);
@@ -113,7 +120,7 @@
       delegate_->CreateMetricReportQueue(
           EventType::kUser, Destination::PERIPHERAL_EVENTS, Priority::SECURITY);
 
-  InitOnAffiliatedLogin();
+  InitOnAffiliatedLogin(profile);
   delayed_init_on_login_timer_.Start(
       FROM_HERE, delegate_->GetInitDelay(),
       base::BindOnce(&MetricReportingManager::DelayedInitOnAffiliatedLogin,
@@ -238,7 +245,7 @@
                               this, &MetricReportingManager::UploadTelemetry);
 }
 
-void MetricReportingManager::InitOnAffiliatedLogin() {
+void MetricReportingManager::InitOnAffiliatedLogin(Profile* profile) {
   if (delegate_->IsDeprovisioned()) {
     return;
   }
@@ -255,6 +262,15 @@
       /*enable_setting_path=*/::ash::kReportDeviceNetworkStatus,
       metrics::kReportDeviceNetworkStatusDefaultValue);
   InitPeripheralsCollectors();
+
+  // Start observing app events only if the feature flag is set.
+  if (base::FeatureList::IsEnabled(kEnableAppMetricsReporting)) {
+    auto app_events_observer = AppEventsObserver::CreateForProfile(profile);
+    InitEventObserverManager(
+        std::move(app_events_observer), user_event_report_queue_.get(),
+        /*enable_setting_path=*/::ash::kReportDeviceAppInfo,
+        metrics::kReportDeviceAppInfoDefaultValue);
+  }
 }
 
 void MetricReportingManager::InitTelemetrySamplersOnAffiliatedLogin() {
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.h b/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.h
index 1cfe3c5..9fca4c18 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.h
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.h
@@ -9,6 +9,7 @@
 #include <string>
 #include <vector>
 
+#include "base/feature_list.h"
 #include "base/scoped_observation.h"
 #include "base/sequence_checker.h"
 #include "base/strings/string_piece_forward.h"
@@ -33,6 +34,9 @@
 class CollectorBase;
 class Sampler;
 
+// Feature flag that can be set to facilitate app metrics reporting.
+BASE_DECLARE_FEATURE(kEnableAppMetricsReporting);
+
 // Class to initialize and start info, event, and telemetry collection and
 // reporting.
 class MetricReportingManager : public policy::ManagedSessionService::Observer,
@@ -94,7 +98,7 @@
 
   // Init samplers, collectors and event observers that need to start after an
   // affiliated user login with no delay, should only be called once on login.
-  void InitOnAffiliatedLogin();
+  void InitOnAffiliatedLogin(Profile* profile);
 
   // Init telemetry samplers that can only be used in affiliated users sessions.
   void InitTelemetrySamplersOnAffiliatedLogin();
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager_unittest.cc
index 2817d0c..53dd8907 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager_unittest.cc
@@ -193,6 +193,8 @@
 const MetricReportingSettingData displays_telemetry_settings = {
     ::ash::kReportDeviceGraphicsStatus, false, ::ash::kReportUploadFrequency,
     1};
+const MetricReportingSettingData app_event_settings = {
+    ::ash::kReportDeviceAppInfo, false, "", 1};
 
 struct MetricReportingManagerTestCase {
   std::string test_name;
@@ -446,35 +448,64 @@
 INSTANTIATE_TEST_SUITE_P(
     MetricReportingManagerEventTests,
     MetricReportingManagerEventTest,
-    ::testing::ValuesIn<MetricReportingManagerTestCase>(
-        {{"NetworkEvent_Unaffiliated",
-          /*enabled_features=*/{},
-          /*disabled_features=*/{},
-          /*is_affiliated=*/false, network_event_settings,
-          /*expected_count_before_login=*/0,
-          /*expected_count_after_login=*/0,
-          /*expected_count_after_login_delay=*/0},
-         {"NetworkEvent_Default",
-          /*enabled_features=*/{},
-          /*disabled_features=*/{},
-          /*is_affiliated=*/true, network_event_settings,
-          /*expected_count_before_login=*/0,
-          /*expected_count_after_login=*/1,
-          /*expected_count_after_login_delay=*/2},
-         {"AudioEvent_Unaffiliated",
-          /*enabled_features=*/{},
-          /*disabled_features=*/{},
-          /*is_affiliated=*/false, audio_metric_settings,
-          /*expected_count_before_login=*/0,
-          /*expected_count_after_login=*/0,
-          /*expected_count_after_login_delay=*/0},
-         {"AudioEvent_Default",
-          /*enabled_features=*/{},
-          /*disabled_features=*/{},
-          /*is_affiliated=*/true, audio_metric_settings,
-          /*expected_count_before_login=*/0,
-          /*expected_count_after_login=*/1,
-          /*expected_count_after_login_delay=*/1}}),
+    ::testing::ValuesIn<MetricReportingManagerTestCase>({
+        {"NetworkEvent_Unaffiliated",
+         /*enabled_features=*/{},
+         /*disabled_features=*/{},
+         /*is_affiliated=*/false, network_event_settings,
+         /*expected_count_before_login=*/0,
+         /*expected_count_after_login=*/0,
+         /*expected_count_after_login_delay=*/0},
+        {"NetworkEvent_Default",
+         /*enabled_features=*/{},
+         /*disabled_features=*/{},
+         /*is_affiliated=*/true, network_event_settings,
+         /*expected_count_before_login=*/0,
+         /*expected_count_after_login=*/1,
+         /*expected_count_after_login_delay=*/2},
+        {"AudioEvent_Unaffiliated",
+         /*enabled_features=*/{},
+         /*disabled_features=*/{},
+         /*is_affiliated=*/false, audio_metric_settings,
+         /*expected_count_before_login=*/0,
+         /*expected_count_after_login=*/0,
+         /*expected_count_after_login_delay=*/0},
+        {"AudioEvent_Default",
+         /*enabled_features=*/{},
+         /*disabled_features=*/{},
+         /*is_affiliated=*/true, audio_metric_settings,
+         /*expected_count_before_login=*/0,
+         /*expected_count_after_login=*/1,
+         /*expected_count_after_login_delay=*/1},
+        {"AppEvents_Unaffiliated",
+         /*enabled_features=*/{},
+         /*disabled_features=*/{},
+         /*is_affiliated=*/false, app_event_settings,
+         /*expected_count_before_login=*/0,
+         /*expected_count_after_login=*/0,
+         /*expected_count_after_login_delay=*/0},
+        {"AppEvents_Default",
+         /*enabled_features=*/{},
+         /*disabled_features=*/{},
+         /*is_affiliated=*/true, app_event_settings,
+         /*expected_count_before_login=*/0,
+         /*expected_count_after_login=*/0,
+         /*expected_count_after_login_delay=*/0},
+        {"AppEvents_FeatureFlagEnabled",
+         /*enabled_features=*/{kEnableAppMetricsReporting},
+         /*disabled_features=*/{},
+         /*is_affiliated=*/true, app_event_settings,
+         /*expected_count_before_login=*/0,
+         /*expected_count_after_login=*/1,
+         /*expected_count_after_login_delay=*/1},
+        {"AppEvents_FeatureFlagDisabled",
+         /*enabled_features=*/{},
+         /*disabled_features=*/{kEnableAppMetricsReporting},
+         /*is_affiliated=*/true, app_event_settings,
+         /*expected_count_before_login=*/0,
+         /*expected_count_after_login=*/0,
+         /*expected_count_after_login_delay=*/0},
+    }),
     [](const testing::TestParamInfo<MetricReportingManagerInfoTest::ParamType>&
            info) { return info.param.test_name; });
 
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 278487b..f108d86c 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -35,7 +35,7 @@
       </if>
       <if expr="not is_android">
         <include name="IDR_ABOUT_SYS_HTML" file="resources\about_sys\about_sys.html" type="BINDATA" />
-        <include name="IDR_ABOUT_SYS_CSS" file="resources\about_sys\about_sys.css" flattenhtml="true" type="BINDATA" />
+        <include name="IDR_ABOUT_SYS_CSS" file="resources\about_sys\about_sys.css" type="BINDATA" />
         <include name="IDR_ABOUT_SYS_JS" file="resources\about_sys\about_sys.js" preprocess="true" type="BINDATA" />
       </if>
       <include name="IDR_AD_NETWORK_HASHES" file="resources\ad_networks.dat" type="BINDATA" />
diff --git a/chrome/browser/chromeos/reporting/metric_default_utils.h b/chrome/browser/chromeos/reporting/metric_default_utils.h
index a83e1b3..9f52a1c2 100644
--- a/chrome/browser/chromeos/reporting/metric_default_utils.h
+++ b/chrome/browser/chromeos/reporting/metric_default_utils.h
@@ -54,6 +54,9 @@
 // Default value for reporting device graphics status.
 constexpr bool kReportDeviceGraphicsStatusDefaultValue = false;
 
+// Default value for reporting device app info and usage.
+constexpr bool kReportDeviceAppInfoDefaultValue = false;
+
 // Returns the default report upload frequency for the current environment.
 const base::TimeDelta GetDefaultReportUploadFrequency();
 
diff --git a/chrome/browser/extensions/extension_csp_bypass_browsertest.cc b/chrome/browser/extensions/extension_csp_bypass_browsertest.cc
index 602b5a9..5ddca9a8 100644
--- a/chrome/browser/extensions/extension_csp_bypass_browsertest.cc
+++ b/chrome/browser/extensions/extension_csp_bypass_browsertest.cc
@@ -133,8 +133,11 @@
   EXPECT_TRUE(CanLoadScript(ext_without_permission));
 
   // chrome-extension:-URLs can never bypass CSP in WebUI.
+  // TODO(crbug.com/1098690): Find a way to make this test work for pages that
+  // do use TrustedTypes. In the meantime, just use a WebUI that has not
+  // enabled TrustedTypes yet.
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(),
-                                           GURL(chrome::kChromeUISettingsURL)));
+                                           GURL(chrome::kChromeUIWelcomeURL)));
 
   EXPECT_FALSE(CanLoadScript(component_ext_with_permission));
   EXPECT_FALSE(CanLoadScript(component_ext_without_permission));
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedStream.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedStream.java
index 96d3ece..627d07f 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedStream.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedStream.java
@@ -22,7 +22,6 @@
 import androidx.recyclerview.widget.RecyclerView.LayoutManager;
 
 import org.chromium.base.Callback;
-import org.chromium.base.Function;
 import org.chromium.base.Log;
 import org.chromium.base.ObserverList;
 import org.chromium.base.ThreadUtils;
@@ -78,6 +77,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 
 /**
  * A implementation of a Feed {@link Stream} that is just able to render a vertical stream of
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 4e8702e2..e5a81d8 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -506,11 +506,6 @@
     "expiry_milestone": 112
   },
   {
-    "name": "autofill-enable-unmask-card-request-set-instrument-id",
-    "owners": [ "jsaul@google.com", "payments-autofill-team@google.com" ],
-    "expiry_milestone": 109
-  },
-  {
     "name": "autofill-enable-update-virtual-card-enrollment",
     "owners": [ "siyua", "jsaul@google.com" ],
     "expiry_milestone": 112
@@ -5309,7 +5304,7 @@
   {
     "name": "oobe-hid-detection-revamp",
     "owners": [ "gordonseto", "cros-connectivity@google.com"],
-    "expiry_milestone": 110
+    "expiry_milestone": 117
   },
   {
     "name": "oobe-material-next",
@@ -5926,6 +5921,11 @@
     "expiry_milestone": 114
   },
   {
+    "name": "remove-crash-infobar",
+    "owners": [ "justincohen", "bling-flags@google.com"],
+    "expiry_milestone": 115
+  },
+  {
     "name": "request-desktop-site-additions",
     "owners": [ "shuyng@google.com", "twellington", "clank-app-team@google.com" ],
     "expiry_milestone": 112
@@ -6350,7 +6350,7 @@
   {
     "name": "smart-sorting-new-overflow-menu",
     "owners": [ "bwwilliams@google.com", "bling-flags@google.com" ],
-    "expiry_milestone": 110
+    "expiry_milestone": 111
   },
   {
     "name": "smart-suggestion-for-large-downloads",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 99d87811..9e783e1 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -423,12 +423,6 @@
     "When enabled, if the user interacts with the manual fallback bottom "
     "sheet, it'll remain sticky until the user dismisses it.";
 
-const char kAutofillEnableUnmaskCardRequestSetInstrumentIdName[] =
-    "When enabled, sets non-legacy instrument ID in UnmaskCardRequest";
-const char kAutofillEnableUnmaskCardRequestSetInstrumentIdDescription[] =
-    "When enabled, UnmaskCardRequest will set the card's non-legacy ID when "
-    "available.";
-
 const char kAutofillEnableUpdateVirtualCardEnrollmentName[] =
     "Enable Update Virtual Card Enrollment";
 const char kAutofillEnableUpdateVirtualCardEnrollmentDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 83d74a5..573b417 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -239,9 +239,6 @@
 extern const char kAutofillEnableStickyManualFallbackForCardsName[];
 extern const char kAutofillEnableStickyManualFallbackForCardsDescription[];
 
-extern const char kAutofillEnableUnmaskCardRequestSetInstrumentIdName[];
-extern const char kAutofillEnableUnmaskCardRequestSetInstrumentIdDescription[];
-
 extern const char kAutofillEnableUpdateVirtualCardEnrollmentName[];
 extern const char kAutofillEnableUpdateVirtualCardEnrollmentDescription[];
 
diff --git a/chrome/browser/metrics/power/power_metrics_reporter.cc b/chrome/browser/metrics/power/power_metrics_reporter.cc
index e59edc8..b3e430d 100644
--- a/chrome/browser/metrics/power/power_metrics_reporter.cc
+++ b/chrome/browser/metrics/power/power_metrics_reporter.cc
@@ -240,19 +240,36 @@
       previous_battery_state, new_battery_state, interval_duration);
 
 #if BUILDFLAG(IS_WIN)
-  // Report battery max capacity. We suspect that the max capacity is 100 for a
-  // significant portion of clients on Windows, which doesn't provide sufficient
-  // granularity (the battery typically discharges by less than 1% per 2
-  // minutes). This histogram will allow us to validate the hypothesis.
-  if (new_battery_state.has_value()) {
-    CHECK_EQ(new_battery_state->full_charged_capacity.has_value(),
-             new_battery_state->charge_unit.has_value());
-    if (new_battery_state->full_charged_capacity.has_value() &&
-        new_battery_state->charge_unit.value() ==
-            base::BatteryLevelProvider::BatteryLevelUnit::kMWh) {
-      base::UmaHistogramCounts10000(
-          "Power.BatteryMaxCapacity",
-          new_battery_state->full_charged_capacity.value());
+  if (new_battery_state.has_value() &&
+      new_battery_state->charge_unit.has_value() &&
+      new_battery_state->charge_unit.value() ==
+          base::BatteryLevelProvider::BatteryLevelUnit::kMWh) {
+    CHECK(new_battery_state->full_charged_capacity.has_value());
+    // Report battery max capacity. We suspect that the max capacity is 100 for
+    // a significant portion of clients on Windows, which doesn't provide
+    // sufficient granularity (the battery typically discharges by less than 1%
+    // per 2 minutes). This histogram will allow us to validate the hypothesis.
+    base::UmaHistogramCounts10000(
+        "Power.BatteryMaxCapacity",
+        new_battery_state->full_charged_capacity.value());
+
+    base::UmaHistogramBoolean(
+        "Power. BatteryDischargeGranularityAvailable",
+        new_battery_state->battery_discharge_granularity.has_value());
+
+    DCHECK_EQ(new_battery_state->battery_discharge_granularity.has_value(),
+              new_battery_state->max_battery_discharge_granularity.has_value());
+    if (new_battery_state->battery_discharge_granularity.has_value()) {
+      base::UmaHistogramCustomCounts(
+          "Power.BatteryDischargeGranularity",
+          new_battery_state->battery_discharge_granularity.value(),
+          /*min=*/0, /*exclusive_max=*/20000,
+          /*buckets=*/50);
+      base::UmaHistogramCustomCounts(
+          "Power.MaxBatteryDischargeGranularity",
+          new_battery_state->max_battery_discharge_granularity.value(),
+          /*min=*/0, /*exclusive_max=*/20000,
+          /*buckets=*/50);
     }
   }
 #endif
diff --git a/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc b/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc
index 5af7f86..b239e87 100644
--- a/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc
+++ b/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc
@@ -37,7 +37,7 @@
 constexpr double kTolerableTimeElapsedRatio = 0.10;
 constexpr double kTolerablePositiveDrift = 1 + kTolerableTimeElapsedRatio;
 
-base::BatteryLevelProvider::BatteryState MakeBatteryDischarginState(
+base::BatteryLevelProvider::BatteryState MakeBatteryDischargingState(
     int battery_percent) {
   return base::BatteryLevelProvider::BatteryState{
       .battery_count = 1,
@@ -225,7 +225,7 @@
   std::unique_ptr<base::BatteryLevelProvider> CreateBatteryLevelProvider()
       override {
     // Start with a half-full battery
-    battery_states_.push(MakeBatteryDischarginState(50));
+    battery_states_.push(MakeBatteryDischargingState(50));
     auto battery_provider =
         std::make_unique<FakeBatteryLevelProvider>(&battery_states_);
     return std::move(battery_provider);
@@ -273,7 +273,7 @@
 
 TEST_F(PowerMetricsReporterUnitTest, LongIntervalHistograms) {
   process_monitor_.SetMetricsToReturn(GetFakeProcessMetrics());
-  battery_states_.push(MakeBatteryDischarginState(30));
+  battery_states_.push(MakeBatteryDischargingState(30));
 
   UsageScenarioDataStore::IntervalData interval_data;
   interval_data.max_tab_count = 1;
@@ -296,7 +296,7 @@
 #if BUILDFLAG(IS_MAC)
 TEST_F(PowerMetricsReporterUnitTest, ResourceCoalitionHistograms_EndToEnd) {
   process_monitor_.SetMetricsToReturn({});
-  battery_states_.push(MakeBatteryDischarginState(30));
+  battery_states_.push(MakeBatteryDischargingState(30));
 
   UsageScenarioDataStore::IntervalData interval_data;
   interval_data.max_tab_count = 1;
@@ -332,7 +332,7 @@
   process_monitor_.SetMetricsToReturn(aggregated_process_metrics);
 
   // Pretend that the battery has dropped by 2%.
-  battery_states_.push(MakeBatteryDischarginState(48));
+  battery_states_.push(MakeBatteryDischargingState(48));
 
   const base::TimeDelta kTooLate =
       kLongPowerMetricsIntervalDuration * kTolerablePositiveDrift +
@@ -351,7 +351,7 @@
   process_monitor_.SetMetricsToReturn(aggregated_process_metrics);
 
   // Pretend that the battery has dropped by 2%.
-  battery_states_.push(MakeBatteryDischarginState(48));
+  battery_states_.push(MakeBatteryDischargingState(48));
 
   const base::TimeDelta kLate =
       kLongPowerMetricsIntervalDuration * kTolerablePositiveDrift -
@@ -378,7 +378,7 @@
 
   // Pretend that the battery has dropped by 20% in 2 minutes, for a rate of
   // 10% per minute.
-  battery_states_.push(MakeBatteryDischarginState(30));
+  battery_states_.push(MakeBatteryDischargingState(30));
 
   UsageScenarioDataStore::IntervalData fake_interval_data;
   fake_interval_data.uptime_at_interval_end = base::Hours(++fake_value);
@@ -506,7 +506,7 @@
   fake_metrics.energy_impact = 44;
 #endif
   process_monitor_.SetMetricsToReturn(fake_metrics);
-  battery_states_.push(MakeBatteryDischarginState(50));
+  battery_states_.push(MakeBatteryDischargingState(50));
 
   const ukm::SourceId kTestSourceId =
       ukm::ConvertToSourceId(42, ukm::SourceIdType::NAVIGATION_ID);
@@ -678,7 +678,7 @@
   power_metrics_reporter_->battery_state_for_testing()->current_capacity = 100;
 
   process_monitor_.SetMetricsToReturn({});
-  battery_states_.push(MakeBatteryDischarginState(100));
+  battery_states_.push(MakeBatteryDischargingState(100));
 
   UsageScenarioDataStore::IntervalData fake_interval_data;
   fake_interval_data.source_id_for_longest_visible_origin =
@@ -707,7 +707,7 @@
   process_monitor_.SetMetricsToReturn({});
 
   // Set the new battery state at 75%.
-  battery_states_.push(MakeBatteryDischarginState(75));
+  battery_states_.push(MakeBatteryDischargingState(75));
 
   UsageScenarioDataStore::IntervalData fake_interval_data;
   fake_interval_data.source_id_for_longest_visible_origin =
@@ -734,7 +734,7 @@
 
 TEST_F(PowerMetricsReporterUnitTest, UKMsNoTab) {
   process_monitor_.SetMetricsToReturn(GetFakeProcessMetrics());
-  battery_states_.push(MakeBatteryDischarginState(50));
+  battery_states_.push(MakeBatteryDischargingState(50));
 
   UsageScenarioDataStore::IntervalData fake_interval_data;
   fake_interval_data.max_tab_count = 0;
@@ -758,7 +758,7 @@
 
 TEST_F(PowerMetricsReporterUnitTest, DurationsLongerThanIntervalAreCapped) {
   process_monitor_.SetMetricsToReturn(GetFakeProcessMetrics());
-  battery_states_.push(MakeBatteryDischarginState(50));
+  battery_states_.push(MakeBatteryDischargingState(50));
 
   UsageScenarioDataStore::IntervalData fake_interval_data;
   fake_interval_data.time_playing_video_full_screen_single_monitor =
@@ -782,7 +782,7 @@
 
 TEST_F(PowerMetricsReporterUnitTest, UKMsWithSleepEvent) {
   process_monitor_.SetMetricsToReturn({});
-  battery_states_.push(MakeBatteryDischarginState(50));
+  battery_states_.push(MakeBatteryDischargingState(50));
 
   UsageScenarioDataStore::IntervalData fake_interval_data = {};
   fake_interval_data.sleep_events = 1;
@@ -803,7 +803,7 @@
 // advances and resource coalition data is available.
 TEST_F(PowerMetricsReporterUnitTest, ShortIntervalHistograms_EndToEnd) {
   process_monitor_.SetMetricsToReturn({});
-  battery_states_.push(MakeBatteryDischarginState(30));
+  battery_states_.push(MakeBatteryDischargingState(30));
 
   UsageScenarioDataStore::IntervalData interval_data;
   interval_data.max_tab_count = 1;
@@ -828,3 +828,22 @@
       "PerformanceMonitor.ResourceCoalition.CPUTime2_10sec", 6000, 1);
 }
 #endif  // BUILDFLAG(IS_MAC)
+
+#if BUILDFLAG(IS_WIN)
+TEST_F(PowerMetricsReporterUnitTest, BatteryDischargeGranularity) {
+  const uint32_t kGranularity = 20;
+  const uint32_t kMaxGranularity = 30;
+
+  battery_states_.push(base::BatteryLevelProvider::BatteryState{
+      .full_charged_capacity = 100,
+      .charge_unit = base::BatteryLevelProvider::BatteryLevelUnit::kMWh,
+      .battery_discharge_granularity = kGranularity,
+      .max_battery_discharge_granularity = kMaxGranularity});
+  task_environment_.FastForwardBy(kLongPowerMetricsIntervalDuration);
+
+  histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeGranularity",
+                                       kGranularity, 1);
+  histogram_tester_.ExpectUniqueSample("Power.MaxBatteryDischargeGranularity",
+                                       kMaxGranularity, 1);
+}
+#endif  // BUILDFLAG(IS_WIN)
diff --git a/chrome/browser/notifications/notification_ui_manager_browsertest.cc b/chrome/browser/notifications/notification_ui_manager_browsertest.cc
index d73f1cfc..5d534cc8 100644
--- a/chrome/browser/notifications/notification_ui_manager_browsertest.cc
+++ b/chrome/browser/notifications/notification_ui_manager_browsertest.cc
@@ -83,11 +83,13 @@
       new_delegate->AddRef();
     }
 
-    return Notification(message_center::NOTIFICATION_TYPE_SIMPLE, id, u"title",
-                        u"message", ui::ImageModel(), u"chrome-test://testing/",
-                        GURL("chrome-test://testing/"),
-                        message_center::NotifierId(),
-                        message_center::RichNotificationData(), new_delegate);
+    return Notification(
+        message_center::NOTIFICATION_TYPE_SIMPLE, id, u"title", u"message",
+        ui::ImageModel(), u"chrome-test://testing/",
+        GURL("chrome-test://testing/"),
+        message_center::NotifierId(message_center::NotifierType::APPLICATION,
+                                   "extension_id"),
+        message_center::RichNotificationData(), new_delegate);
   }
 
   Notification CreateRichTestNotification(const std::string& id,
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerErrorMessageHelperBridge.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerErrorMessageHelperBridge.java
index d23d61f5..6e3f871 100644
--- a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerErrorMessageHelperBridge.java
+++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerErrorMessageHelperBridge.java
@@ -68,7 +68,7 @@
         long lastShownTimestamp =
                 Long.valueOf(prefService.getString(Pref.UPM_ERROR_UI_SHOWN_TIMESTAMP));
         long lastShownSyncErrorTimestamp = SharedPreferencesManager.getInstance().readLong(
-                ChromePreferenceKeys.SYNC_ERROR_PROMPT_SHOWN_AT_TIME, 0);
+                ChromePreferenceKeys.SYNC_ERROR_MESSAGE_SHOWN_AT_TIME, 0);
         long currentTime = TimeUtils.currentTimeMillis();
         return (currentTime - lastShownTimestamp > MINIMAL_INTERVAL_BETWEEN_PROMPTS_MS)
                 && (currentTime - lastShownSyncErrorTimestamp) > MINIMAL_INTERVAL_TO_SYNC_ERROR_MS;
diff --git a/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/PasswordManagerErrorMessageHelperBridgeTest.java b/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/PasswordManagerErrorMessageHelperBridgeTest.java
index d6e6e9e3..9a14fd1 100644
--- a/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/PasswordManagerErrorMessageHelperBridgeTest.java
+++ b/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/PasswordManagerErrorMessageHelperBridgeTest.java
@@ -116,7 +116,7 @@
 
     @After
     public void tearDown() {
-        mSharedPrefsManager.removeKey(ChromePreferenceKeys.SYNC_ERROR_PROMPT_SHOWN_AT_TIME);
+        mSharedPrefsManager.removeKey(ChromePreferenceKeys.SYNC_ERROR_MESSAGE_SHOWN_AT_TIME);
         mFakeTimeTestRule.resetTimes();
     }
 
@@ -128,7 +128,7 @@
         when(mPrefService.getString(Pref.UPM_ERROR_UI_SHOWN_TIMESTAMP))
                 .thenReturn(Long.toString(timeOfFirstUpmPrompt));
         mSharedPrefsManager.writeLong(
-                ChromePreferenceKeys.SYNC_ERROR_PROMPT_SHOWN_AT_TIME, timeOfSyncPrompt);
+                ChromePreferenceKeys.SYNC_ERROR_MESSAGE_SHOWN_AT_TIME, timeOfSyncPrompt);
         mFakeTimeTestRule.advanceMillis(
                 PasswordManagerErrorMessageHelperBridge.MINIMAL_INTERVAL_BETWEEN_PROMPTS_MS);
         assertFalse(PasswordManagerErrorMessageHelperBridge.shouldShowErrorUi());
@@ -144,7 +144,7 @@
         when(mPrefService.getString(Pref.UPM_ERROR_UI_SHOWN_TIMESTAMP))
                 .thenReturn(Long.toString(timeOfFirstUpmPrompt));
         mSharedPrefsManager.writeLong(
-                ChromePreferenceKeys.SYNC_ERROR_PROMPT_SHOWN_AT_TIME, timeOfSyncPrompt);
+                ChromePreferenceKeys.SYNC_ERROR_MESSAGE_SHOWN_AT_TIME, timeOfSyncPrompt);
         assertFalse(PasswordManagerErrorMessageHelperBridge.shouldShowErrorUi());
     }
 
@@ -157,7 +157,7 @@
         when(mPrefService.getString(Pref.UPM_ERROR_UI_SHOWN_TIMESTAMP))
                 .thenReturn(Long.toString(timeOfFirstUpmPrompt));
         mSharedPrefsManager.writeLong(
-                ChromePreferenceKeys.SYNC_ERROR_PROMPT_SHOWN_AT_TIME, timeOfSyncPrompt);
+                ChromePreferenceKeys.SYNC_ERROR_MESSAGE_SHOWN_AT_TIME, timeOfSyncPrompt);
         mFakeTimeTestRule.advanceMillis(
                 PasswordManagerErrorMessageHelperBridge.MINIMAL_INTERVAL_BETWEEN_PROMPTS_MS + 1);
         assertTrue(PasswordManagerErrorMessageHelperBridge.shouldShowErrorUi());
diff --git a/chrome/browser/policy/messaging_layer/public/report_client.cc b/chrome/browser/policy/messaging_layer/public/report_client.cc
index ce183f1..9e679ec 100644
--- a/chrome/browser/policy/messaging_layer/public/report_client.cc
+++ b/chrome/browser/policy/messaging_layer/public/report_client.cc
@@ -258,7 +258,7 @@
                     base::BindRepeating(&ReportingClient::AsyncStartUploader),
                     std::move(storage_created_cb));
               }),
-          base::ThreadTaskRunnerHandle::Get()) {
+          base::SequencedTaskRunner::GetCurrentDefault()) {
 }
 
 ReportingClient::~ReportingClient() = default;
diff --git a/chrome/browser/policy/messaging_layer/upload/upload_provider.h b/chrome/browser/policy/messaging_layer/upload/upload_provider.h
index 12953a2..4ce4a29 100644
--- a/chrome/browser/policy/messaging_layer/upload/upload_provider.h
+++ b/chrome/browser/policy/messaging_layer/upload/upload_provider.h
@@ -12,7 +12,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/threading/platform_thread.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/policy/messaging_layer/upload/upload_client.h"
 #include "components/reporting/proto/synced/record.pb.h"
 #include "components/reporting/resources/resource_interface.h"
diff --git a/chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event.cc b/chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event.cc
index 25fc9aa4..2fcec9b 100644
--- a/chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event.cc
+++ b/chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event.cc
@@ -49,7 +49,8 @@
       /*priority=*/FAST_BATCH, base::BindOnce([](Status status) {
         LOG(WARNING) << "Heartbeat Event completed with status: " << status;
       }),
-      base::ThreadPool::CreateSequencedTaskRunner(base::TaskTraits()));
+      base::ThreadPool::CreateSequencedTaskRunner(
+          {base::TaskPriority::BEST_EFFORT, base::MayBlock()}));
 }
 
 }  // namespace reporting
diff --git a/chrome/browser/policy/messaging_layer/util/report_queue_manual_test_context_unittest.cc b/chrome/browser/policy/messaging_layer/util/report_queue_manual_test_context_unittest.cc
index 8a14ab3b..054153c 100644
--- a/chrome/browser/policy/messaging_layer/util/report_queue_manual_test_context_unittest.cc
+++ b/chrome/browser/policy/messaging_layer/util/report_queue_manual_test_context_unittest.cc
@@ -73,15 +73,8 @@
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 };
 
-// TODO(crbug.com/1383860) Disabled due to flake on Mac.
-#if BUILDFLAG(IS_MAC)
-TEST_F(
-    ReportQueueManualTestContextTest,
-    DISABLED_BuildsReportQueueManualTestContextAndUploadsDeviceEventMessages) {
-#else
 TEST_F(ReportQueueManualTestContextTest,
        BuildsReportQueueManualTestContextAndUploadsDeviceEventMessages) {
-#endif
   EXPECT_CALL(*mock_report_queue_, AddRecord(_, _, _))
       .Times(kNumberOfMessagesToEnqueue)
       .WillRepeatedly(
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
index 824a098..6644238 100644
--- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
@@ -922,7 +922,7 @@
     public static final String SURVEY_DATE_LAST_ROLLED = "last_rolled_for_chrome_survey_key";
 
     // The UI used to be an infobar in the past.
-    public static final String SYNC_ERROR_PROMPT_SHOWN_AT_TIME =
+    public static final String SYNC_ERROR_MESSAGE_SHOWN_AT_TIME =
             "sync_error_infobar_shown_shown_at_time";
 
     public static final String TABBED_ACTIVITY_LAST_BACKGROUNDED_TIME_MS_PREF =
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/LegacyChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/LegacyChromePreferenceKeys.java
index 94c52d2..8c1a201 100644
--- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/LegacyChromePreferenceKeys.java
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/LegacyChromePreferenceKeys.java
@@ -129,7 +129,7 @@
                 ChromePreferenceKeys.SIGNIN_LEGACY_SYNC_ACCOUNT_EMAIL,
                 ChromePreferenceKeys.SNAPSHOT_DATABASE_REMOVED,
                 ChromePreferenceKeys.SURVEY_DATE_LAST_ROLLED,
-                ChromePreferenceKeys.SYNC_ERROR_PROMPT_SHOWN_AT_TIME,
+                ChromePreferenceKeys.SYNC_ERROR_MESSAGE_SHOWN_AT_TIME,
                 ChromePreferenceKeys.TABBED_ACTIVITY_LAST_BACKGROUNDED_TIME_MS_PREF,
                 ChromePreferenceKeys.TABMODEL_ACTIVE_TAB_ID,
                 ChromePreferenceKeys.TABMODEL_HAS_COMPUTED_MAX_ID,
diff --git a/chrome/browser/printing/print_backend_service_test_impl.cc b/chrome/browser/printing/print_backend_service_test_impl.cc
index e58c80b5..f9cbb1e8 100644
--- a/chrome/browser/printing/print_backend_service_test_impl.cc
+++ b/chrome/browser/printing/print_backend_service_test_impl.cc
@@ -14,6 +14,19 @@
 #include "chrome/browser/printing/print_backend_service_manager.h"
 #include "printing/backend/test_print_backend.h"
 
+#if BUILDFLAG(IS_WIN)
+#include <memory>
+
+#include "base/run_loop.h"
+#include "base/test/bind.h"
+#include "base/threading/thread_restrictions.h"
+#include "chrome/browser/printing/printer_xml_parser_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "printing/printing_features.h"
+#endif  // BUILDFLAG(IS_WIN)
+
 namespace printing {
 
 #if BUILDFLAG(IS_WIN)
@@ -115,6 +128,12 @@
     return;
   }
 
+#if BUILDFLAG(IS_WIN)
+  // Fetching capabilities with XPS uses synchronous mojo calls, which requires
+  // base sync primitives for testing with multiple threads.
+  base::ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
+#endif  // BUILDFLAG(IS_WIN)
+
   PrintBackendServiceImpl::FetchCapabilities(printer_name, std::move(callback));
 }
 
@@ -213,4 +232,58 @@
   return service;
 }
 
+#if BUILDFLAG(IS_WIN)
+// static
+std::unique_ptr<PrintBackendServiceTestImpl>
+PrintBackendServiceTestImpl::LaunchForTestingWithServiceThread(
+    mojo::Remote<mojom::PrintBackendService>& remote,
+    scoped_refptr<TestPrintBackend> backend,
+    bool sandboxed,
+    mojo::PendingRemote<mojom::PrinterXmlParser> xml_parser_remote,
+    scoped_refptr<base::SingleThreadTaskRunner> service_task_runner) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  std::unique_ptr<PrintBackendServiceTestImpl> service;
+
+  base::RunLoop run_loop;
+  service_task_runner->PostTaskAndReplyWithResult(
+      FROM_HERE,
+      base::BindOnce(&PrintBackendServiceTestImpl::CreateServiceOnServiceThread,
+                     remote.BindNewPipeAndPassReceiver(), backend,
+                     std::move(xml_parser_remote)),
+      base::BindLambdaForTesting(
+          [&](std::unique_ptr<PrintBackendServiceTestImpl> result_service) {
+            service = std::move(result_service);
+            run_loop.Quit();
+          }));
+  run_loop.Run();
+
+  // Register this test version of print backend service to be used instead of
+  // launching instances out-of-process on-demand.
+  if (sandboxed) {
+    PrintBackendServiceManager::GetInstance().SetServiceForTesting(&remote);
+  } else {
+    PrintBackendServiceManager::GetInstance().SetServiceForFallbackTesting(
+        &remote);
+  }
+
+  return service;
+}
+
+// static
+std::unique_ptr<PrintBackendServiceTestImpl>
+PrintBackendServiceTestImpl::CreateServiceOnServiceThread(
+    mojo::PendingReceiver<mojom::PrintBackendService> receiver,
+    scoped_refptr<TestPrintBackend> backend,
+    mojo::PendingRemote<mojom::PrinterXmlParser> xml_parser_remote) {
+  // Private ctor.
+  auto service = base::WrapUnique(
+      new PrintBackendServiceTestImpl(std::move(receiver), std::move(backend)));
+  service->Init(/*locale=*/std::string(), std::move(xml_parser_remote));
+
+  return service;
+}
+
+#endif  // BUILDFLAG(IS_WIN)
+
 }  // namespace printing
diff --git a/chrome/browser/printing/print_backend_service_test_impl.h b/chrome/browser/printing/print_backend_service_test_impl.h
index 50dd74e..411f4ce0 100644
--- a/chrome/browser/printing/print_backend_service_test_impl.h
+++ b/chrome/browser/printing/print_backend_service_test_impl.h
@@ -20,6 +20,10 @@
 #if BUILDFLAG(IS_WIN)
 #include "base/containers/queue.h"
 #include "base/memory/read_only_shared_memory_region.h"
+#include "base/memory/scoped_refptr.h"
+#include "chrome/services/printing/public/mojom/printer_xml_parser.mojom-forward.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 #include "printing/mojom/print.mojom.h"
 #endif
 
@@ -49,6 +53,20 @@
       scoped_refptr<TestPrintBackend> backend,
       bool sandboxed);
 
+#if BUILDFLAG(IS_WIN)
+  // Launch the service in-process for testing using the provided backend.
+  // `sandboxed` identifies if this service is potentially subject to
+  // experiencing access-denied errors on some commands. Launches the service on
+  // the thread associated with `service_task_runner`.
+  static std::unique_ptr<PrintBackendServiceTestImpl>
+  LaunchForTestingWithServiceThread(
+      mojo::Remote<mojom::PrintBackendService>& remote,
+      scoped_refptr<TestPrintBackend> backend,
+      bool sandboxed,
+      mojo::PendingRemote<mojom::PrinterXmlParser> xml_parser_remote,
+      scoped_refptr<base::SingleThreadTaskRunner> service_task_runner);
+#endif  // BUILDFLAG(IS_WIN)
+
   PrintBackendServiceTestImpl(const PrintBackendServiceTestImpl&) = delete;
   PrintBackendServiceTestImpl& operator=(const PrintBackendServiceTestImpl&) =
       delete;
@@ -108,7 +126,7 @@
 #endif
 
  private:
-  // Use LaunchForTesting().
+  // Use LaunchForTesting() or LaunchForTestingWithServiceThread().
   PrintBackendServiceTestImpl(
       mojo::PendingReceiver<mojom::PrintBackendService> receiver,
       scoped_refptr<TestPrintBackend> backend);
@@ -119,6 +137,16 @@
 
   void TerminateConnection();
 
+#if BUILDFLAG(IS_WIN)
+  // Launches and returns a test Print Backend service run on a service thread.
+  // This runs on the service thread.
+  static std::unique_ptr<PrintBackendServiceTestImpl>
+  CreateServiceOnServiceThread(
+      mojo::PendingReceiver<mojom::PrintBackendService> receiver,
+      scoped_refptr<TestPrintBackend> backend,
+      mojo::PendingRemote<mojom::PrinterXmlParser> xml_parser_remote);
+#endif  // BUILDFLAG(IS_WIN)
+
   // When pretending to be sandboxed, have the possibility of getting access
   // denied errors.
   bool is_sandboxed_ = false;
diff --git a/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc b/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc
index 185ece11..48d8aa77 100644
--- a/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc
+++ b/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc
@@ -287,8 +287,14 @@
 
 }  // namespace
 
+// TODO(crbug.com/1385142): Flaky on macos12 builds.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_TaskManagementTest DISABLED_TaskManagementTest
+#else
+#define MAYBE_TaskManagementTest TaskManagementTest
+#endif
 IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
-                       TaskManagementTest) {
+                       MAYBE_TaskManagementTest) {
   // This test starts with two tabs open.
   EXPECT_EQ(2U, GetTrackedTags().size());
 
diff --git a/chrome/browser/resources/about_sys/about_sys.css b/chrome/browser/resources/about_sys/about_sys.css
index 57e4b889..6b6fb478 100644
--- a/chrome/browser/resources/about_sys/about_sys.css
+++ b/chrome/browser/resources/about_sys/about_sys.css
@@ -57,9 +57,7 @@
 }
 
 div#header h1::before {
-  /* grit doesn't flatten -webkit-mask, so define the properties separately
-  * for now. */
-  -webkit-mask-image: url(../../../../ui/webui/resources/images/settings.svg);
+  -webkit-mask-image: url(chrome://resources/images/icon_settings.svg);
   -webkit-mask-position: center;
   -webkit-mask-repeat: no-repeat;
   -webkit-mask-size: 24px;
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/COMMON_METADATA b/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/COMMON_METADATA
index 64b49c6..11df69f 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/COMMON_METADATA
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/COMMON_METADATA
@@ -1,7 +1,7 @@
 team_email: "chromium-accessibility@chromium.org"
 buganizer {
-  component_id: 1272677
+  component_id: 1279067
 }
 buganizer_public {
-  component_id: 1272681
+  component_id: 1279213
 }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js
index 8e233a1a..7a9c4ac 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js
@@ -680,28 +680,6 @@
   }
 
   /** @override */
-  formatState_(data, token) {
-    const buff = data.outputBuffer;
-    const node = data.node;
-    const formatLog = data.outputFormatLogger;
-
-    if (node.state) {
-      Object.getOwnPropertyNames(node.state).forEach(state => {
-        const stateInfo = outputTypes.OUTPUT_STATE_INFO[state];
-        if (stateInfo && !stateInfo.isRoleSpecific && stateInfo.on) {
-          formatLog.writeToken(token);
-          this.format_({
-            node,
-            outputFormat: '$' + state,
-            outputBuffer: buff,
-            outputFormatLogger: formatLog,
-          });
-        }
-      });
-    }
-  }
-
-  /** @override */
   formatFind_(data, token, tree) {
     const buff = data.outputBuffer;
     const formatLog = data.outputFormatLogger;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_formatter.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_formatter.js
index ea32712..7eab2f0 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_formatter.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_formatter.js
@@ -66,7 +66,7 @@
     } else if (token === 'pressed') {
       this.formatPressed_(this.params_, token);
     } else if (token === 'state') {
-      this.output_.formatState_(this.params_, token);
+      this.formatState_(this.params_, token);
     } else if (token === 'find') {
       this.output_.formatFind_(this.params_, token, tree);
     } else if (token === 'descendants') {
@@ -379,6 +379,32 @@
   /**
    * @param {!outputTypes.OutputFormattingData} data
    * @param {string} token
+   * @private
+   */
+  formatState_(data, token) {
+    const buff = data.outputBuffer;
+    const node = data.node;
+    const formatLog = data.outputFormatLogger;
+
+    if (node.state) {
+      Object.getOwnPropertyNames(node.state).forEach(state => {
+        const stateInfo = outputTypes.OUTPUT_STATE_INFO[state];
+        if (stateInfo && !stateInfo.isRoleSpecific && stateInfo.on) {
+          formatLog.writeToken(token);
+          this.output_.format_({
+            node,
+            outputFormat: '$' + state,
+            outputBuffer: buff,
+            outputFormatLogger: formatLog,
+          });
+        }
+      });
+    }
+  }
+
+  /**
+   * @param {!outputTypes.OutputFormattingData} data
+   * @param {string} token
    * @param {!{annotation: Array<*>, isUnique: (boolean|undefined)}} options
    */
   formatUrlFilename_(data, token, options) {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_interface.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_interface.js
index dcacdfb88..832a54b2 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_interface.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_interface.js
@@ -142,12 +142,6 @@
   /**
    * @param {!OutputFormattingData} data
    * @param {string} token
-   */
-  formatState_(data, token) {}
-
-  /**
-   * @param {!OutputFormattingData} data
-   * @param {string} token
    * @param {!{annotation: Array<*>, isUnique: (boolean|undefined)}} options
    */
   formatTableCellIndex_(data, token, options) {}
diff --git a/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/COMMON_METADATA b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/COMMON_METADATA
new file mode 100644
index 0000000..8a7f713
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/COMMON_METADATA
@@ -0,0 +1,10 @@
+monorail {
+  component: "OS>Accessibility"
+}
+team_email: "chromium-accessibility@chromium.org"
+buganizer {
+  component_id: 1279168
+}
+buganizer_public {
+  component_id: 1279189
+}
diff --git a/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/DIR_METADATA b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/DIR_METADATA
new file mode 100644
index 0000000..6cacb6d
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/DIR_METADATA
@@ -0,0 +1 @@
+mixins: "//chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/COMMON_METADATA"
diff --git a/chrome/browser/resources/new_tab_page/lens_upload_dialog.html b/chrome/browser/resources/new_tab_page/lens_upload_dialog.html
index e80f01c..422ed15 100644
--- a/chrome/browser/resources/new_tab_page/lens_upload_dialog.html
+++ b/chrome/browser/resources/new_tab_page/lens_upload_dialog.html
@@ -19,7 +19,7 @@
     --upload-dialog-shadow: var( --cr-elevation-3);
     --upload-dialog-title-color: var(--google-grey-800);
     font-family: inherit;
-    width: calc(100% + 8px);
+    width: 100%;
   }
 
   :host([is-dragging_]),
diff --git a/chrome/browser/resources/settings/chromeos/lazy_load.js b/chrome/browser/resources/settings/chromeos/lazy_load.js
index 041316c..42d3d24 100644
--- a/chrome/browser/resources/settings/chromeos/lazy_load.js
+++ b/chrome/browser/resources/settings/chromeos/lazy_load.js
@@ -30,6 +30,7 @@
 import './os_a11y_page/keyboard_and_text_input_page.js';
 import './os_a11y_page/cursor_and_touchpad_page.js';
 import './os_a11y_page/audio_and_captions_page.js';
+import './os_a11y_page/select_to_speak_subpage.js';
 import './os_a11y_page/switch_access_action_assignment_dialog.js';
 import './os_a11y_page/switch_access_action_assignment_pane.js';
 import './os_a11y_page/switch_access_setup_guide_dialog.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.html b/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.html
index a42b979..e97a7d8d 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.html
@@ -89,6 +89,15 @@
       </settings-text-to-speech-page>
     </settings-subpage>
   </template>
+  <template is="dom-if"
+      if="[[isAccessibilitySelectToSpeakPageMigrationEnabled_]]">
+    <template is="dom-if" route-path="/textToSpeech/selectToSpeak">
+      <settings-subpage page-title="$i18n{selectToSpeakLinkTitle}">
+        <settings-select-to-speak-subpage prefs="{{prefs}}">
+        </settings-select-to-speak-subpage>
+      </settings-subpage>
+    </template>
+  </template>
   <template is="dom-if" route-path="/displayAndMagnification">
     <settings-subpage page-title="$i18n{displayAndMagnificationLinkTitle}">
       <settings-display-and-magnification-page prefs="{{prefs}}">
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.ts b/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.ts
index de828f8..7bfcf3c8 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.ts
@@ -19,6 +19,7 @@
 import './keyboard_and_text_input_page.js';
 import './cursor_and_touchpad_page.js';
 import './audio_and_captions_page.js';
+import './select_to_speak_subpage.js';
 import './switch_access_subpage.js';
 import './tts_subpage.js';
 
@@ -94,6 +95,17 @@
       },
 
       /**
+       * Whether Select-to-speak page migration is enabled.
+       */
+      isAccessibilitySelectToSpeakPageMigrationEnabled_: {
+        type: Boolean,
+        value() {
+          return loadTimeData.getBoolean(
+              'isAccessibilitySelectToSpeakPageMigrationEnabled');
+        },
+      },
+
+      /**
        * Whether the user is in kiosk mode.
        */
       isKioskModeActive_: {
@@ -171,6 +183,10 @@
       this.addFocusConfig(
           routes.A11Y_AUDIO_AND_CAPTIONS, '#audio-and-captions-page-trigger');
     }
+    if (routes.A11Y_SELECT_TO_SPEAK) {
+      this.addFocusConfig(
+          routes.A11Y_SELECT_TO_SPEAK, '#select-to-speak-subpage-trigger');
+    }
 
     this.addWebUIListener(
         'screen-reader-state-changed',
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/select_to_speak_subpage.html b/chrome/browser/resources/settings/chromeos/os_a11y_page/select_to_speak_subpage.html
new file mode 100644
index 0000000..e518c16
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/select_to_speak_subpage.html
@@ -0,0 +1,19 @@
+<!--
+Copyright 2022 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<style include="settings-shared">
+  :host {
+    --cr-section-indent-width: 60px;
+  }
+
+  .sub-item {
+    padding-inline-start: var(--cr-section-indent-width);
+  }
+
+  .settings-box {
+    padding-inline-start: 0;
+  }
+</style>
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/select_to_speak_subpage.ts b/chrome/browser/resources/settings/chromeos/os_a11y_page/select_to_speak_subpage.ts
new file mode 100644
index 0000000..a1a94e08
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/select_to_speak_subpage.ts
@@ -0,0 +1,90 @@
+// 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.
+
+/**
+ * @fileoverview
+ * 'settings-select-to-speak-subpage' is the accessibility settings subpage for
+ * Select-to-speak settings.
+ */
+
+import 'chrome://resources/cr_elements/cr_shared_vars.css.js';
+import '../../settings_shared.css.js';
+import 'chrome://resources/cr_components/localized_link/localized_link.js';
+
+import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js';
+import {WebUiListenerMixin, WebUiListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {Route} from '../../router.js';
+import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js';
+import {routes} from '../os_route.js';
+import {RouteOriginBehavior, RouteOriginBehaviorInterface} from '../route_origin_behavior.js';
+
+import {getTemplate} from './select_to_speak_subpage.html.js';
+
+const SettingsSelectToSpeakSubpageElementBase =
+    mixinBehaviors(
+        [
+          DeepLinkingBehavior,
+          RouteOriginBehavior,
+        ],
+        WebUiListenerMixin(I18nMixin(PolymerElement))) as {
+      new (): PolymerElement & I18nMixinInterface &
+          WebUiListenerMixinInterface & DeepLinkingBehaviorInterface &
+          RouteOriginBehaviorInterface,
+    };
+
+class SettingsSelectToSpeakSubpageElement extends
+    SettingsSelectToSpeakSubpageElementBase {
+  static get is() {
+    return 'settings-select-to-speak-subpage';
+  }
+
+  static get template() {
+    return getTemplate();
+  }
+
+  static get properties() {
+    return {
+      prefs: {
+        type: Object,
+        notify: true,
+      },
+    };
+  }
+
+  prefs: {[key: string]: any};
+  private route_: Route;
+
+  constructor() {
+    super();
+
+    /** RouteOriginBehavior override */
+    this.route_ = routes.A11Y_SELECT_TO_SPEAK;
+  }
+
+  /**
+   * Note: Overrides RouteOriginBehavior implementation.
+   */
+  override currentRouteChanged(newRoute: Route, prevRoute?: Route) {
+    super.currentRouteChanged(newRoute, prevRoute);
+
+    // Does not apply to this page.
+    if (newRoute !== routes.A11Y_SELECT_TO_SPEAK) {
+      return;
+    }
+
+    this.attemptDeepLink();
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'settings-select-to-speak-subpage': SettingsSelectToSpeakSubpageElement;
+  }
+}
+
+customElements.define(
+    SettingsSelectToSpeakSubpageElement.is,
+    SettingsSelectToSpeakSubpageElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html
index fe07093..949f5e0 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html
@@ -49,10 +49,21 @@
 </settings-toggle-button>
 <iron-collapse opened="[[prefs.settings.a11y.select_to_speak.value]]">
   <div class="sub-item">
-    <cr-link-row id="selectToSpeakSubpageButton"
-        class="settings-box" on-click="onSelectToSpeakSettingsTap_"
-        label="$i18n{selectToSpeakOptionsLabel}" external>
-    </cr-link-row>
+    <template is="dom-if"
+        if="[[isAccessibilitySelectToSpeakPageMigrationEnabled_]]">
+      <cr-link-row id="select-to-speak-subpage-trigger"
+          class="settings-box" on-click="onSelectToSpeakTap_"
+          label="$i18n{selectToSpeakLinkTitle}"
+          role-description="$i18n{subpageArrowRoleDescription}">
+      </cr-link-row>
+    </template>
+    <template is="dom-if"
+        if="[[!isAccessibilitySelectToSpeakPageMigrationEnabled_]]">
+      <cr-link-row id="selectToSpeakSubpageButton"
+          class="settings-box" on-click="onSelectToSpeakSettingsTap_"
+          label="$i18n{selectToSpeakOptionsLabel}" external>
+      </cr-link-row>
+    </template>
   </div>
 </iron-collapse>
 
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts
index dc5a8ca2..ba94bc5 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts
@@ -14,6 +14,7 @@
 
 import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js';
 import {WebUiListenerMixin, WebUiListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
@@ -64,6 +65,14 @@
        */
       hasKeyboard_: Boolean,
 
+      isAccessibilitySelectToSpeakPageMigrationEnabled_: {
+        type: Boolean,
+        value() {
+          return loadTimeData.getBoolean(
+              'isAccessibilitySelectToSpeakPageMigrationEnabled');
+        },
+      },
+
       /**
        * Used by DeepLinkingBehavior to focus this page's deep links.
        */
@@ -163,6 +172,10 @@
   private onSelectToSpeakSettingsTap_(): void {
     this.textToSpeechBrowserProxy_.showSelectToSpeakSettings();
   }
+
+  private onSelectToSpeakTap_(): void {
+    Router.getInstance().navigateTo(routes.A11Y_SELECT_TO_SPEAK);
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/settings/chromeos/os_route.js b/chrome/browser/resources/settings/chromeos/os_route.js
index e3fe9ea..c737560076 100644
--- a/chrome/browser/resources/settings/chromeos/os_route.js
+++ b/chrome/browser/resources/settings/chromeos/os_route.js
@@ -226,6 +226,14 @@
     r.A11Y_AUDIO_AND_CAPTIONS = createSubpage(
         r.OS_ACCESSIBILITY, routesMojomWebui.AUDIO_AND_CAPTIONS_SUBPAGE_PATH,
         Subpage.kAudioAndCaptions);
+    if (loadTimeData.valueExists(
+            'isAccessibilitySelectToSpeakPageMigrationEnabled') &&
+        loadTimeData.getBoolean(
+            'isAccessibilitySelectToSpeakPageMigrationEnabled')) {
+      r.A11Y_SELECT_TO_SPEAK = createSubpage(
+          r.A11Y_TEXT_TO_SPEECH, routesMojomWebui.SELECT_TO_SPEAK_SUBPAGE_PATH,
+          Subpage.kSelectToSpeak);
+    }
     r.MANAGE_TTS_SETTINGS = createSubpage(
         loadTimeData.getBoolean('isKioskModeActive') ? r.MANAGE_ACCESSIBILITY :
                                                        r.A11Y_TEXT_TO_SPEECH,
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni
index f21f62f9..0c5537c 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.gni
+++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -65,6 +65,7 @@
   "chromeos/os_a11y_page/display_and_magnification_page.ts",
   "chromeos/os_a11y_page/keyboard_and_text_input_page.ts",
   "chromeos/os_a11y_page/os_a11y_page.ts",
+  "chromeos/os_a11y_page/select_to_speak_subpage.ts",
   "chromeos/os_a11y_page/switch_access_action_assignment_dialog.ts",
   "chromeos/os_a11y_page/switch_access_action_assignment_pane.ts",
   "chromeos/os_a11y_page/switch_access_setup_guide_dialog.ts",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_routes.js b/chrome/browser/resources/settings/chromeos/os_settings_routes.js
index 8d1333b..7800b0b 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_routes.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings_routes.js
@@ -13,6 +13,7 @@
  *   A11Y_DISPLAY_AND_MAGNIFICATION: !Route,
  *   A11Y_KEYBOARD_AND_TEXT_INPUT: !Route,
  *   A11Y_TEXT_TO_SPEECH: !Route,
+ *   A11Y_SELECT_TO_SPEAK: !Route,
  *   ABOUT: !Route,
  *   ABOUT_ABOUT: !Route,
  *   ACCOUNTS: !Route,
diff --git a/chrome/browser/resources/settings/controls/settings_checkbox.html b/chrome/browser/resources/settings/controls/settings_checkbox.html
index 74f8601..649d4c8 100644
--- a/chrome/browser/resources/settings/controls/settings_checkbox.html
+++ b/chrome/browser/resources/settings/controls/settings_checkbox.html
@@ -28,7 +28,7 @@
       aria-label="[[label]]">
     <div id="label" class="label">[[label]] <slot></slot></div>
     <div id="subLabel" class="secondary label">
-      <div inner-h-t-m-l="[[subLabelHtml]]"></div>
+      <div inner-h-t-m-l="[[sanitizeInnerHtml_(subLabelHtml)]]"></div>
       [[subLabel]]
     </div>
   </cr-checkbox>
diff --git a/chrome/browser/resources/settings/controls/settings_checkbox.ts b/chrome/browser/resources/settings/controls/settings_checkbox.ts
index 6b86c7b..7e605284 100644
--- a/chrome/browser/resources/settings/controls/settings_checkbox.ts
+++ b/chrome/browser/resources/settings/controls/settings_checkbox.ts
@@ -11,6 +11,7 @@
 import '../settings_shared.css.js';
 
 import {CrCheckboxElement} from 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js';
+import {sanitizeInnerHtml} from 'chrome://resources/js/parse_html_subset.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {SettingsBooleanControlMixin} from './settings_boolean_control_mixin.js';
@@ -75,6 +76,10 @@
   private hasSubLabel_(subLabel: string, subLabelHtml: string): boolean {
     return !!subLabel || !!subLabelHtml;
   }
+
+  private sanitizeInnerHtml_(rawString: string): TrustedHTML {
+    return sanitizeInnerHtml(rawString);
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/settings/ensure_lazy_loaded.ts b/chrome/browser/resources/settings/ensure_lazy_loaded.ts
index b44d2aa6..a4b3fdc2 100644
--- a/chrome/browser/resources/settings/ensure_lazy_loaded.ts
+++ b/chrome/browser/resources/settings/ensure_lazy_loaded.ts
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {getTrustedScriptURL} from 'chrome://resources/js/static_types.js';
+
 let lazyLoadPromise: Promise<void>|null = null;
 
 /** @return Resolves when the lazy load module is imported. */
@@ -9,7 +11,7 @@
   if (lazyLoadPromise === null) {
     const script = document.createElement('script');
     script.type = 'module';
-    script.src = './lazy_load.js';
+    script.src = getTrustedScriptURL`./lazy_load.js`;
     document.body.appendChild(script);
 
     lazyLoadPromise =
diff --git a/chrome/browser/resources/settings/people_page/signout_dialog.ts b/chrome/browser/resources/settings/people_page/signout_dialog.ts
index cee7ad1..7bc56c17 100644
--- a/chrome/browser/resources/settings/people_page/signout_dialog.ts
+++ b/chrome/browser/resources/settings/people_page/signout_dialog.ts
@@ -18,6 +18,7 @@
 
 import {CrDialogElement} from '//resources/cr_elements/cr_dialog/cr_dialog.js';
 import {WebUiListenerMixin} from '//resources/cr_elements/web_ui_listener_mixin.js';
+import {sanitizeInnerHtml} from '//resources/js/parse_html_subset.js';
 import {microTask, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {loadTimeData} from '../i18n_setup.js';
@@ -126,19 +127,20 @@
   }
 
   // <if expr="not chromeos_ash">
-  private getDisconnectExplanationHtml_(domain: string): string {
+  private getDisconnectExplanationHtml_(domain: string): TrustedHTML {
     if (domain) {
-      return loadTimeData.getStringF(
-          'syncDisconnectManagedProfileExplanation',
-          '<span id="managed-by-domain-name">' + domain + '</span>');
+      return sanitizeInnerHtml(loadTimeData.getStringF(
+          'syncDisconnectManagedProfileExplanation', `<span>${domain}</span>`));
     }
-    return loadTimeData.getString('syncDisconnectExplanation');
+    return sanitizeInnerHtml(
+        loadTimeData.getString('syncDisconnectExplanation'));
   }
   // </if>
 
   // <if expr="chromeos_ash">
-  private getDisconnectExplanationHtml_(_domain: string): string {
-    return loadTimeData.getString('syncDisconnectExplanation');
+  private getDisconnectExplanationHtml_(_domain: string): TrustedHTML {
+    return sanitizeInnerHtml(
+        loadTimeData.getString('syncDisconnectExplanation'));
   }
   // </if>
 
diff --git a/chrome/browser/resources/settings/people_page/sync_page.ts b/chrome/browser/resources/settings/people_page/sync_page.ts
index 4e6a8aa..39b10aa 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.ts
+++ b/chrome/browser/resources/settings/people_page/sync_page.ts
@@ -236,7 +236,7 @@
   // </if>
 
   private enterPassphraseLabel_: TrustedHTML;
-  private existingPassphraseLabel_: string;
+  private existingPassphraseLabel_: TrustedHTML;
 
   private browserProxy_: SyncBrowserProxy = SyncBrowserProxyImpl.getInstance();
   private collapsibleSectionsInitialized_: boolean;
@@ -566,18 +566,18 @@
     });
   }
 
-  private computeExistingPassphraseLabel_(): string {
+  private computeExistingPassphraseLabel_(): TrustedHTML {
     if (!this.syncPrefs || !this.syncPrefs.encryptAllData) {
-      return '';
+      return window.trustedTypes!.emptyHTML;
     }
 
     if (!this.syncPrefs.explicitPassphraseTime) {
-      return this.i18n('existingPassphraseLabel');
+      return this.i18nAdvanced('existingPassphraseLabel');
     }
 
-    return this.i18n(
-        'existingPassphraseLabelWithDate',
-        this.syncPrefs.explicitPassphraseTime);
+    return this.i18nAdvanced('existingPassphraseLabelWithDate', {
+      substitutions: [this.syncPrefs.explicitPassphraseTime],
+    });
   }
 
   /**
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_description_item.html b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_description_item.html
index ce0fbea..099fd43 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_description_item.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_description_item.html
@@ -25,7 +25,7 @@
 <div id="descriptionItemWrapper">
   <iron-icon icon="[[icon]]" aria-hidden="true"></iron-icon>
   <div class="secondary">
-    <div inner-h-t-m-l="[[labelHtml]]"></div>
+    <div inner-h-t-m-l="[[sanitizeInnerHtml_(labelHtml)]]"></div>
     [[label]]
   </div>
 </div>
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_description_item.ts b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_description_item.ts
index c4153bb..d61b535 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_description_item.ts
+++ b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_description_item.ts
@@ -11,6 +11,7 @@
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import '../../settings_shared.css.js';
 
+import {sanitizeInnerHtml} from 'chrome://resources/js/parse_html_subset.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {getTemplate} from './privacy_guide_description_item.html.js';
@@ -42,6 +43,10 @@
       },
     };
   }
+
+  private sanitizeInnerHtml_(rawString: string): TrustedHTML {
+    return sanitizeInnerHtml(rawString);
+  }
 }
 
 customElements.define(
diff --git a/chrome/browser/resources/settings/privacy_page/secure_dns.ts b/chrome/browser/resources/settings/privacy_page/secure_dns.ts
index e6c5dab5..4b3de5aa 100644
--- a/chrome/browser/resources/settings/privacy_page/secure_dns.ts
+++ b/chrome/browser/resources/settings/privacy_page/secure_dns.ts
@@ -23,8 +23,9 @@
 import './secure_dns_input.js';
 
 import {CrRadioGroupElement} from 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js';
-import {assertNotReached} from 'chrome://resources/js/assert_ts.js';
 import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
+import {assertNotReached} from 'chrome://resources/js/assert_ts.js';
+import {sanitizeInnerHtml} from 'chrome://resources/js/parse_html_subset.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {SettingsToggleButtonElement} from '../controls/settings_toggle_button.js';
@@ -139,7 +140,7 @@
   private secureDnsRadio_: SecureDnsMode;
   private resolverOptions_: ResolverOption[];
   private lastResolverOption_: string;
-  private privacyPolicyString_: string;
+  private privacyPolicyString_: TrustedHTML;
   private secureDnsInputValue_: string;
   private browserProxy_: PrivacyPageBrowserProxy =
       PrivacyPageBrowserProxyImpl.getInstance();
@@ -393,9 +394,9 @@
       return;
     }
 
-    this.privacyPolicyString_ = loadTimeData.substituteString(
+    this.privacyPolicyString_ = sanitizeInnerHtml(loadTimeData.substituteString(
         loadTimeData.getString('secureDnsSecureDropdownModePrivacyPolicy'),
-        resolver.policy);
+        resolver.policy));
   }
 
   /**
diff --git a/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html b/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html
index fdc696d..703e648e 100644
--- a/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html
+++ b/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html
@@ -14,8 +14,8 @@
         [[getPageTitle_(isTriggered_, triggeredResetToolName_)]]
       </div>
       <div id="dialog-body" slot="body">
-        <span inner-h-t-m-l="
-          [[getExplanationText_(isTriggered_, triggeredResetToolName_)]]">
+        <span inner-h-t-m-l="[[getExplanationText_(
+              isTriggered_, triggeredResetToolName_)]]">
         </span>
         <span>
           <a href="$i18nRaw{resetPageLearnMoreUrl}" target="_blank">
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_child.html b/chrome/browser/resources/settings/safety_check_page/safety_check_child.html
index dd01a48..3b40ac8 100644
--- a/chrome/browser/resources/settings/safety_check_page/safety_check_child.html
+++ b/chrome/browser/resources/settings/safety_check_page/safety_check_child.html
@@ -43,8 +43,9 @@
     aria-label="[[getStatusIconAriaLabel_(iconStatus)]]">
 </iron-icon>
 <div class="flex cr-padded-text">
-  <div id="label" inner-h-t-m-l="[[label]]"></div>
-  <div id="subLabel" class="secondary" no-search inner-h-t-m-l="[[subLabel]]">
+  <div id="label" inner-h-t-m-l="[[sanitizeInnerHtml_(label)]]"></div>
+  <div id="subLabel" class="secondary" no-search
+      inner-h-t-m-l="[[sanitizeInnerHtml_(subLabel)]]">
   </div>
 </div>
 <template is="dom-if" if="[[showButton_(buttonLabel)]]" restamp>
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_child.ts b/chrome/browser/resources/settings/safety_check_page/safety_check_child.ts
index 670529570..ab2fe857 100644
--- a/chrome/browser/resources/settings/safety_check_page/safety_check_child.ts
+++ b/chrome/browser/resources/settings/safety_check_page/safety_check_child.ts
@@ -16,8 +16,9 @@
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import '../settings_shared.css.js';
 
-import {assertNotReached} from 'chrome://resources/js/assert_ts.js';
 import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
+import {assertNotReached} from 'chrome://resources/js/assert_ts.js';
+import {sanitizeInnerHtml} from 'chrome://resources/js/parse_html_subset.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {getTemplate} from './safety_check_child.html.js';
@@ -197,6 +198,10 @@
     // For cr-actionable-row-style.
     this.toggleAttribute('effectively-disabled_', !this.rowClickable);
   }
+
+  private sanitizeInnerHtml_(rawString: string): TrustedHTML {
+    return sanitizeInnerHtml(rawString);
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/settings/settings.ts b/chrome/browser/resources/settings/settings.ts
index acd9c8e..db35018 100644
--- a/chrome/browser/resources/settings/settings.ts
+++ b/chrome/browser/resources/settings/settings.ts
@@ -14,6 +14,7 @@
 export {CrToolbarElement} from 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar.js';
 export {CrToolbarSearchFieldElement} from 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js';
 export {PluralStringProxyImpl as SettingsPluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js';
+export {getTrustedHTML} from 'chrome://resources/js/static_types.js';
 export {SettingsAboutPageElement} from './about_page/about_page.js';
 export {AboutPageBrowserProxy, AboutPageBrowserProxyImpl, UpdateStatus} from './about_page/about_page_browser_proxy.js';
 // <if expr="_google_chrome and is_macosx">
diff --git a/chrome/browser/resources/settings/site_settings/site_details_permission.ts b/chrome/browser/resources/settings/site_settings/site_details_permission.ts
index 8f57381a..a77ae8a 100644
--- a/chrome/browser/resources/settings/site_settings/site_details_permission.ts
+++ b/chrome/browser/resources/settings/site_settings/site_details_permission.ts
@@ -13,9 +13,10 @@
 import '../settings_vars.css.js';
 import '../i18n_setup.js';
 
-import {assert, assertNotReached} from 'chrome://resources/js/assert_ts.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, assertNotReached} from 'chrome://resources/js/assert_ts.js';
+import {sanitizeInnerHtml} from 'chrome://resources/js/parse_html_subset.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {ContentSetting, ContentSettingsTypes, SiteSettingSource} from './constants.js';
@@ -232,7 +233,7 @@
       setting: ContentSetting): boolean {
     // This method assumes that an empty string will be returned for categories
     // that have no permission info string.
-    return this.permissionInfoString_(
+    return String(this.permissionInfoString_(
                source, category, setting,
                // Set all permission info string arguments as null. This is OK
                // because there is no need to know what the information string
@@ -241,7 +242,7 @@
                // <if expr="is_win and _google_chrome">
                null,
                // </if>
-               null, null, null, null, null, null) !== '';
+               null, null, null, null, null, null)) !== '';
   }
 
   /**
@@ -343,16 +344,16 @@
    * @param setting The permission setting.
    * @param  allowlistString The string to show if the permission is
    *     allowlisted.
-   * @param adsBlacklistString The string to show if the site is
-   *     blacklisted for showing bad ads.
+   * @param adsBlocklistString The string to show if the site is
+   *     blocklisted for showing bad ads.
    * @param adsBlockString The string to show if ads are blocked, but
-   *     the site is not blacklisted.
+   *     the site is not blocklisted.
    * @return The permission information string to display in the HTML.
    */
   private permissionInfoString_(
       source: SiteSettingSource, category: ContentSettingsTypes,
       setting: ContentSetting, allowlistString: string|null,
-      adsBlacklistString: string|null, adsBlockString: string|null,
+      adsBlocklistString: string|null, adsBlockString: string|null,
       embargoString: string|null, insecureOriginString: string|null,
       killSwitchString: string|null,
       // <if expr="is_win and _google_chrome">
@@ -361,10 +362,10 @@
       extensionAllowString: string|null, extensionBlockString: string|null,
       extensionAskString: string|null, policyAllowString: string|null,
       policyBlockString: string|null,
-      policyAskString: string|null): (string|null) {
+      policyAskString: string|null): (TrustedHTML|null) {
     if (source === undefined || category === undefined ||
         setting === undefined) {
-      return null;
+      return window.trustedTypes!.emptyHTML;
     }
 
     const extensionStrings: {[key: string]: string|null} = {};
@@ -377,46 +378,50 @@
     policyStrings[ContentSetting.BLOCK] = policyBlockString;
     policyStrings[ContentSetting.ASK] = policyAskString;
 
+    function htmlOrNull(str: string|null): TrustedHTML|null {
+      return str === null ? null : sanitizeInnerHtml(str);
+    }
+
     if (source === SiteSettingSource.ALLOWLIST) {
-      return allowlistString;
+      return htmlOrNull(allowlistString);
     } else if (source === SiteSettingSource.ADS_FILTER_BLACKLIST) {
       assert(
           ContentSettingsTypes.ADS === category,
-          'The ads filter blacklist only applies to Ads.');
-      return adsBlacklistString;
+          'The ads filter blocklist only applies to Ads.');
+      return htmlOrNull(adsBlocklistString);
     } else if (
         category === ContentSettingsTypes.ADS &&
         setting === ContentSetting.BLOCK) {
-      return adsBlockString;
+      return htmlOrNull(adsBlockString);
     } else if (source === SiteSettingSource.EMBARGO) {
       assert(
           ContentSetting.BLOCK === setting,
           'Embargo is only used to block permissions.');
-      return embargoString;
+      return htmlOrNull(embargoString);
     } else if (source === SiteSettingSource.EXTENSION) {
-      return extensionStrings[setting];
+      return htmlOrNull(extensionStrings[setting]);
     } else if (source === SiteSettingSource.INSECURE_ORIGIN) {
       assert(
           ContentSetting.BLOCK === setting,
           'Permissions can only be blocked due to insecure origins.');
-      return insecureOriginString;
+      return htmlOrNull(insecureOriginString);
     } else if (source === SiteSettingSource.KILL_SWITCH) {
       assert(
           ContentSetting.BLOCK === setting,
           'The permissions kill switch can only be used to block permissions.');
-      return killSwitchString;
+      return htmlOrNull(killSwitchString);
     } else if (source === SiteSettingSource.POLICY) {
-      return policyStrings[setting];
+      return htmlOrNull(policyStrings[setting]);
       // <if expr="is_win and _google_chrome">
     } else if (
         category === ContentSettingsTypes.PROTECTED_CONTENT &&
         setting === ContentSetting.ALLOW) {
-      return protectedContentIdentifierAllowedString;
+      return htmlOrNull(protectedContentIdentifierAllowedString);
       // </if>
     } else if (
         source === SiteSettingSource.DEFAULT ||
         source === SiteSettingSource.PREFERENCE) {
-      return '';
+      return window.trustedTypes!.emptyHTML;
     }
     assertNotReached(`No string for ${category} setting source '${source}'`);
   }
diff --git a/chrome/browser/speech/extension_api/DIR_METADATA b/chrome/browser/speech/extension_api/DIR_METADATA
index e81b58c5..e77aa423 100644
--- a/chrome/browser/speech/extension_api/DIR_METADATA
+++ b/chrome/browser/speech/extension_api/DIR_METADATA
@@ -1,3 +1 @@
-monorail: {
-  component: "Internals>SpeechSynthesis"
-}
+mixins: "//chromeos/services/tts/COMMON_METADATA"
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManager.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManager.java
index 125c995..24038423 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManager.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManager.java
@@ -25,7 +25,6 @@
 
 import com.google.protobuf.InvalidProtocolBufferException;
 
-import org.chromium.base.Function;
 import org.chromium.chrome.browser.omnibox.MatchClassificationStyle;
 import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
@@ -41,6 +40,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Function;
 
 /**
  * CachedZeroSuggestionsManager manages caching and restoring zero suggestions.
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarSnapshotState.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarSnapshotState.java
index 91eef17..0193a16 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarSnapshotState.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarSnapshotState.java
@@ -25,6 +25,8 @@
  * if a new bitmap capture is warranted.
  */
 public class ToolbarSnapshotState {
+    static boolean sSkipVisibleHintAssertion;
+
     /**
      * Reasons that two snapshots are different. Treat this list as append only and keep it in sync
      * with ToolbarSnapshotDifference in enums.xml, as well as the proto in
@@ -81,7 +83,14 @@
         mOptionalButtonData = optionalButtonData;
         mVisualState = visualState;
         mUrlText = urlText;
-        mVisibleTextPrefixHint = visibleTextPrefixHint;
+        boolean isVisibleTextPrefixHintValid = urlText != null && visibleTextPrefixHint != null
+                && TextUtils.indexOf(urlText, visibleTextPrefixHint) >= 0;
+        mVisibleTextPrefixHint = isVisibleTextPrefixHintValid ? visibleTextPrefixHint : null;
+        if (!sSkipVisibleHintAssertion && visibleTextPrefixHint != null) {
+            assert isVisibleTextPrefixHintValid : "The visible hint, " + visibleTextPrefixHint
+                                                  + ", should always be part of the URL text, "
+                                                  + urlText;
+        }
         mSecurityIcon = securityIcon;
         mColorStateList = colorStateList;
         mIsShowingUpdateBadgeDuringLastCapture = isShowingUpdateBadgeDuringLastCapture;
@@ -128,10 +137,7 @@
     private boolean isVisibleUrlTextSame(ToolbarSnapshotState that) {
         if (mVisibleTextPrefixHint != null
                 && TextUtils.equals(mVisibleTextPrefixHint, that.mVisibleTextPrefixHint)) {
-            if (TextUtils.indexOf(mUrlText, mVisibleTextPrefixHint) >= 0) return true;
-            assert false : "The visible hint, " + mVisibleTextPrefixHint
-                           + ", should always be part of the URL text, "
-                           + mUrlText;
+            return true;
         }
         return TextUtils.equals(mUrlText, that.mUrlText);
     }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarSnapshotStateTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarSnapshotStateTest.java
index e6e0df9..b8af293 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarSnapshotStateTest.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarSnapshotStateTest.java
@@ -11,6 +11,7 @@
 import androidx.annotation.DrawableRes;
 import androidx.annotation.Nullable;
 
+import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -53,6 +54,11 @@
         mDefaultToolbarSnapshotState = new ToolbarSnapshotStateBuilder().build();
     }
 
+    @After
+    public void after() {
+        ToolbarSnapshotState.sSkipVisibleHintAssertion = false;
+    }
+
     @Test
     public void testSameSnapshots() {
         ToolbarSnapshotState otherToolbarSnapshotState = new ToolbarSnapshotStateBuilder().build();
@@ -117,11 +123,13 @@
 
     @Test
     public void testSameUrlText_DifferentHintText() {
+        ToolbarSnapshotState.sSkipVisibleHintAssertion = true;
         ToolbarSnapshotState initialToolbarSnapshotState =
                 new ToolbarSnapshotStateBuilder().setVisibleTextPrefixHint("foo").build();
         ToolbarSnapshotState otherToolbarSnapshotState = new ToolbarSnapshotStateBuilder().build();
         Assert.assertEquals(ToolbarSnapshotDifference.NONE,
                 initialToolbarSnapshotState.getAnyDifference(otherToolbarSnapshotState));
+        ToolbarSnapshotState.sSkipVisibleHintAssertion = false;
     }
 
     @Test
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_item.cc b/chrome/browser/ui/app_list/app_service/app_service_app_item.cc
index cc139c2a..e42f4d9 100644
--- a/chrome/browser/ui/app_list/app_service/app_service_app_item.cc
+++ b/chrome/browser/ui/app_list/app_service/app_service_app_item.cc
@@ -29,8 +29,6 @@
 #include "chrome/browser/ui/app_list/app_service/app_service_context_menu.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
 #include "components/services/app_service/public/cpp/app_types.h"
-#include "components/services/app_service/public/cpp/features.h"
-#include "components/services/app_service/public/mojom/types.mojom-shared.h"
 
 namespace {
 
@@ -256,17 +254,10 @@
 void AppServiceAppItem::Launch(int event_flags,
                                apps::LaunchSource launch_source) {
   ResetIsNewInstall();
-  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-    apps::AppServiceProxyFactory::GetForProfile(profile())->Launch(
-        id(), event_flags, launch_source,
-        std::make_unique<apps::WindowInfo>(
-            GetController()->GetAppListDisplayId()));
-  } else {
-    apps::AppServiceProxyFactory::GetForProfile(profile())->Launch(
-        id(), event_flags,
-        apps::ConvertLaunchSourceToMojomLaunchSource(launch_source),
-        apps::MakeWindowInfo(GetController()->GetAppListDisplayId()));
-  }
+  apps::AppServiceProxyFactory::GetForProfile(profile())->Launch(
+      id(), event_flags, launch_source,
+      std::make_unique<apps::WindowInfo>(
+          GetController()->GetAppListDisplayId()));
 }
 
 void AppServiceAppItem::CallLoadIcon(bool allow_placeholder_icon) {
diff --git a/chrome/browser/ui/app_list/arc/arc_app_launcher.cc b/chrome/browser/ui/app_list/arc/arc_app_launcher.cc
index 3284c4d..7855432 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_launcher.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_launcher.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/apps/app_service/launch_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
-#include "components/services/app_service/public/cpp/features.h"
 #include "ui/events/event_constants.h"
 
 ArcAppLauncher::ArcAppLauncher(content::BrowserContext* context,
@@ -125,15 +124,8 @@
         app_id_, ui::EF_NONE, std::move(launch_intent_), launch_source_,
         std::make_unique<apps::WindowInfo>(display_id_), base::DoNothing());
   } else {
-    if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-      proxy->Launch(app_id_, ui::EF_NONE, launch_source_,
-                    std::make_unique<apps::WindowInfo>(display_id_));
-    } else {
-      proxy->Launch(
-          app_id_, ui::EF_NONE,
-          apps::ConvertLaunchSourceToMojomLaunchSource(launch_source_),
-          apps::MakeWindowInfo(display_id_));
-    }
+    proxy->Launch(app_id_, ui::EF_NONE, launch_source_,
+                  std::make_unique<apps::WindowInfo>(display_id_));
   }
 
   app_launched_ = true;
diff --git a/chrome/browser/ui/app_list/search/app_service_app_result.cc b/chrome/browser/ui/app_list/search/app_service_app_result.cc
index cd451dc7..f8fe5b8 100644
--- a/chrome/browser/ui/app_list/search/app_service_app_result.cc
+++ b/chrome/browser/ui/app_list/search/app_service_app_result.cc
@@ -24,7 +24,6 @@
 #include "components/favicon/core/large_icon_service.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/app_update.h"
-#include "components/services/app_service/public/cpp/features.h"
 #include "extensions/common/extension.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/window_open_disposition_utils.h"
@@ -202,15 +201,9 @@
     }
   }
 
-  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-    proxy->Launch(app_id(), event_flags, launch_source,
-                  std::make_unique<apps::WindowInfo>(
-                      controller()->GetAppListDisplayId()));
-  } else {
-    proxy->Launch(app_id(), event_flags,
-                  apps::ConvertLaunchSourceToMojomLaunchSource(launch_source),
-                  apps::MakeWindowInfo(controller()->GetAppListDisplayId()));
-  }
+  proxy->Launch(
+      app_id(), event_flags, launch_source,
+      std::make_unique<apps::WindowInfo>(controller()->GetAppListDisplayId()));
 }
 
 void AppServiceAppResult::CallLoadIcon(bool chip, bool allow_placeholder_icon) {
diff --git a/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc b/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc
index 0b8229c..c4f1dcd 100644
--- a/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc
+++ b/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc
@@ -23,7 +23,6 @@
 #include "chromeos/ash/components/string_matching/tokenized_string_match.h"
 #include "chromeos/ui/vector_icons/vector_icons.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
-#include "components/services/app_service/public/cpp/features.h"
 #include "ui/events/keycodes/keyboard_codes_posix.h"
 #include "ui/gfx/paint_vector_icon.h"
 
@@ -267,13 +266,8 @@
 void KeyboardShortcutResult::Open(int event_flags) {
   apps::AppServiceProxy* proxy =
       apps::AppServiceProxyFactory::GetForProfile(profile_);
-  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-    proxy->Launch(ash::kInternalAppIdKeyboardShortcutViewer, event_flags,
-                  apps::LaunchSource::kFromAppListQuery, nullptr);
-  } else {
-    proxy->Launch(ash::kInternalAppIdKeyboardShortcutViewer, event_flags,
-                  apps::mojom::LaunchSource::kFromAppListQuery, nullptr);
-  }
+  proxy->Launch(ash::kInternalAppIdKeyboardShortcutViewer, event_flags,
+                apps::LaunchSource::kFromAppListQuery, nullptr);
 }
 
 double KeyboardShortcutResult::CalculateRelevance(
diff --git a/chrome/browser/ui/ash/chrome_new_window_client.cc b/chrome/browser/ui/ash/chrome_new_window_client.cc
index 60f4a7b..758af44 100644
--- a/chrome/browser/ui/ash/chrome_new_window_client.cc
+++ b/chrome/browser/ui/ash/chrome_new_window_client.cc
@@ -69,10 +69,8 @@
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/app_types.h"
-#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "components/services/app_service/public/cpp/types_util.h"
-#include "components/services/app_service/public/mojom/types.mojom.h"
 #include "components/sessions/core/tab_restore_service.h"
 #include "components/sessions/core/tab_restore_service_observer.h"
 #include "components/url_formatter/url_fixer.h"
@@ -382,13 +380,8 @@
   apps::AppServiceProxy* proxy =
       apps::AppServiceProxyFactory::GetForProfile(profile);
   DCHECK(proxy);
-  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-    proxy->Launch(ash::calculator_app::GetInstalledCalculatorAppId(profile),
-                  ui::EF_NONE, apps::LaunchSource::kFromKeyboard);
-  } else {
-    proxy->Launch(ash::calculator_app::GetInstalledCalculatorAppId(profile),
-                  ui::EF_NONE, apps::mojom::LaunchSource::kFromKeyboard);
-  }
+  proxy->Launch(ash::calculator_app::GetInstalledCalculatorAppId(profile),
+                ui::EF_NONE, apps::LaunchSource::kFromKeyboard);
 }
 
 void ChromeNewWindowClient::OpenFileManager() {
@@ -409,19 +402,10 @@
       return;
     }
 
-    if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-      proxy->Launch(
-          update.AppId(),
-          apps::GetEventFlags(WindowOpenDisposition::NEW_FOREGROUND_TAB,
-                              /*prefer_container=*/true),
-          apps::LaunchSource::kFromKeyboard);
-    } else {
-      proxy->Launch(
-          update.AppId(),
-          apps::GetEventFlags(WindowOpenDisposition::NEW_FOREGROUND_TAB,
-                              /*prefer_container=*/true),
-          apps::mojom::LaunchSource::kFromKeyboard);
-    }
+    proxy->Launch(update.AppId(),
+                  apps::GetEventFlags(WindowOpenDisposition::NEW_FOREGROUND_TAB,
+                                      /*prefer_container=*/true),
+                  apps::LaunchSource::kFromKeyboard);
   };
 
   bool result = proxy->AppRegistryCache().ForOneApp(
diff --git a/chrome/browser/ui/ash/ime_controller_client_impl.cc b/chrome/browser/ui/ash/ime_controller_client_impl.cc
index 141f53e4..d52bf7e 100644
--- a/chrome/browser/ui/ash/ime_controller_client_impl.cc
+++ b/chrome/browser/ui/ash/ime_controller_client_impl.cc
@@ -104,20 +104,6 @@
     keyboard->SetCapsLockEnabled(caps_enabled);
 }
 
-void ImeControllerClientImpl::UpdateMirroringState(bool mirroring_enabled) {
-  ui::TextInputMethod* ime_engine =
-      ui::IMEBridge::Get()->GetCurrentEngineHandler();
-  if (ime_engine)
-    ime_engine->SetMirroringEnabled(mirroring_enabled);
-}
-
-void ImeControllerClientImpl::UpdateCastingState(bool casting_enabled) {
-  ui::TextInputMethod* ime_engine =
-      ui::IMEBridge::Get()->GetCurrentEngineHandler();
-  if (ime_engine)
-    ime_engine->SetCastingEnabled(casting_enabled);
-}
-
 void ImeControllerClientImpl::OverrideKeyboardKeyset(
     ash::input_method::ImeKeyset keyset,
     OverrideKeyboardKeysetCallback callback) {
diff --git a/chrome/browser/ui/ash/ime_controller_client_impl.h b/chrome/browser/ui/ash/ime_controller_client_impl.h
index 88409b4..3cdec785 100644
--- a/chrome/browser/ui/ash/ime_controller_client_impl.h
+++ b/chrome/browser/ui/ash/ime_controller_client_impl.h
@@ -42,8 +42,6 @@
   void SwitchImeById(const std::string& id, bool show_message) override;
   void ActivateImeMenuItem(const std::string& key) override;
   void SetCapsLockEnabled(bool caps_enabled) override;
-  void UpdateMirroringState(bool mirroring_enabled) override;
-  void UpdateCastingState(bool casting_enabled) override;
   void OverrideKeyboardKeyset(ash::input_method::ImeKeyset keyset,
                               OverrideKeyboardKeysetCallback callback) override;
   void ShowModeIndicator() override;
diff --git a/chrome/browser/ui/ash/shelf/shelf_controller_helper.cc b/chrome/browser/ui/ash/shelf/shelf_controller_helper.cc
index 6b57eb6..680d997 100644
--- a/chrome/browser/ui/ash/shelf/shelf_controller_helper.cc
+++ b/chrome/browser/ui/ash/shelf/shelf_controller_helper.cc
@@ -35,7 +35,6 @@
 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/app_types.h"
-#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/cpp/types_util.h"
 #include "content/public/browser/navigation_entry.h"
 #include "net/base/url_util.h"
@@ -165,16 +164,9 @@
 
   // Launch apps with AppServiceProxy.Launch.
   if (proxy->AppRegistryCache().GetAppType(app_id) != apps::AppType::kUnknown) {
-    if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-      proxy->Launch(app_id, event_flags,
-                    ShelfLaunchSourceToAppsLaunchSource(source),
-                    std::make_unique<apps::WindowInfo>(display_id));
-    } else {
-      proxy->Launch(app_id, event_flags,
-                    apps::ConvertLaunchSourceToMojomLaunchSource(
-                        ShelfLaunchSourceToAppsLaunchSource(source)),
-                    apps::MakeWindowInfo(display_id));
-    }
+    proxy->Launch(app_id, event_flags,
+                  ShelfLaunchSourceToAppsLaunchSource(source),
+                  std::make_unique<apps::WindowInfo>(display_id));
     return;
   }
 
diff --git a/chrome/browser/ui/ash/shelf/standalone_browser_extension_app_shelf_item_controller.cc b/chrome/browser/ui/ash/shelf/standalone_browser_extension_app_shelf_item_controller.cc
index bc1b4c72..c3270b5 100644
--- a/chrome/browser/ui/ash/shelf/standalone_browser_extension_app_shelf_item_controller.cc
+++ b/chrome/browser/ui/ash/shelf/standalone_browser_extension_app_shelf_item_controller.cc
@@ -24,7 +24,6 @@
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller_util.h"
 #include "chrome/browser/ui/ash/shelf/standalone_browser_extension_app_context_menu.h"
 #include "components/services/app_service/public/cpp/app_types.h"
-#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/cpp/instance_registry.h"
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/views/widget/widget.h"
@@ -104,16 +103,9 @@
   if (filtered_windows.size() == 0) {
     apps::AppServiceProxy* proxy = apps::AppServiceProxyFactory::GetForProfile(
         ProfileManager::GetPrimaryUserProfile());
-    if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-      proxy->Launch(app_id(), event->flags(),
-                    ShelfLaunchSourceToAppsLaunchSource(source),
-                    /*window_info=*/nullptr);
-    } else {
-      proxy->Launch(app_id(), event->flags(),
-                    apps::ConvertLaunchSourceToMojomLaunchSource(
-                        ShelfLaunchSourceToAppsLaunchSource(source)),
-                    /*window_info=*/nullptr);
-    }
+    proxy->Launch(app_id(), event->flags(),
+                  ShelfLaunchSourceToAppsLaunchSource(source),
+                  /*window_info=*/nullptr);
 
     std::move(callback).Run(ash::SHELF_ACTION_NEW_WINDOW_CREATED, {});
     return;
diff --git a/chrome/browser/ui/ash/system_tray_client_impl.cc b/chrome/browser/ui/ash/system_tray_client_impl.cc
index 8823abc..e7dc8b2 100644
--- a/chrome/browser/ui/ash/system_tray_client_impl.cc
+++ b/chrome/browser/ui/ash/system_tray_client_impl.cc
@@ -70,7 +70,6 @@
 #include "chromeos/ash/components/network/tether_constants.h"
 #include "components/prefs/pref_service.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
-#include "components/services/app_service/public/cpp/features.h"
 #include "components/session_manager/core/session_manager.h"
 #include "components/session_manager/core/session_manager_observer.h"
 #include "components/user_manager/user_manager.h"
@@ -628,13 +627,8 @@
     return;
   }
 
-  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-    apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
-        app_id, ui::EF_NONE, apps::LaunchSource::kFromParentalControls);
-  } else {
-    apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
-        app_id, ui::EF_NONE, apps::mojom::LaunchSource::kFromParentalControls);
-  }
+  apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
+      app_id, ui::EF_NONE, apps::LaunchSource::kFromParentalControls);
 }
 
 void SystemTrayClientImpl::ShowSettingsSimUnlock() {
diff --git a/chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.cc b/chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.cc
index 4b3fb932..2677aef 100644
--- a/chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.cc
+++ b/chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.cc
@@ -34,7 +34,6 @@
 #include "chrome/browser/web_applications/web_app_utils.h"
 #include "chrome/common/webui_url_constants.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
-#include "components/services/app_service/public/cpp/features.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/display/scoped_display_for_new_windows.h"
@@ -175,15 +174,8 @@
     return;
   }
 
-  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-    app_service->Launch(*app_id, event_flags, params.launch_source,
-                        std::move(window_info));
-  } else {
-    app_service->Launch(
-        *app_id, event_flags,
-        apps::ConvertLaunchSourceToMojomLaunchSource(params.launch_source),
-        apps::ConvertWindowInfoToMojomWindowInfo(window_info));
-  }
+  app_service->Launch(*app_id, event_flags, params.launch_source,
+                      std::move(window_info));
 }
 
 Browser* LaunchSystemWebAppImpl(Profile* profile,
diff --git a/chrome/browser/ui/quick_answers/ui/quick_answers_pre_target_handler.cc b/chrome/browser/ui/quick_answers/ui/quick_answers_pre_target_handler.cc
index 03a6cf7..e0f00dd4 100644
--- a/chrome/browser/ui/quick_answers/ui/quick_answers_pre_target_handler.cc
+++ b/chrome/browser/ui/quick_answers/ui/quick_answers_pre_target_handler.cc
@@ -58,6 +58,10 @@
   if (!event->IsLocatedEvent())
     return;
 
+  // Filter scroll event due to potential timing issue (b/258750397).
+  if (event->IsScrollEvent() || event->type() == ui::ET_MOUSEWHEEL)
+    return;
+
   // Clone event to forward down the view-hierarchy.
   auto clone = event->Clone();
   ui::Event::DispatcherApi(clone.get()).set_target(event->target());
diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc
index ea8530a..bf0ab714 100644
--- a/chrome/browser/ui/ui_features.cc
+++ b/chrome/browser/ui/ui_features.cc
@@ -199,6 +199,8 @@
 BASE_FEATURE(kTabGroupsSave,
              "TabGroupsSave",
              base::FEATURE_DISABLED_BY_DEFAULT);
+const base::FeatureParam<bool> kTabGroupsSaveSyncIntegration{
+    &kTabGroupsSave, "TabGroupsSaveSyncIntegration", false};
 
 // Enables preview images in tab-hover cards.
 // https://crbug.com/928954
diff --git a/chrome/browser/ui/ui_features.h b/chrome/browser/ui/ui_features.h
index 1e03b7c..c27bf440 100644
--- a/chrome/browser/ui/ui_features.h
+++ b/chrome/browser/ui/ui_features.h
@@ -94,6 +94,7 @@
 BASE_DECLARE_FEATURE(kTabGroupsNewBadgePromo);
 
 BASE_DECLARE_FEATURE(kTabGroupsSave);
+extern const base::FeatureParam<bool> kTabGroupsSaveSyncIntegration;
 
 BASE_DECLARE_FEATURE(kTabHoverCardImages);
 
diff --git a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.cc b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.cc
index 5f0966bf..9bcfa64 100644
--- a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.cc
+++ b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.cc
@@ -211,7 +211,7 @@
                    const GURL& validated_url,
                    int error_code) override {
     if (render_frame_host->IsActive() &&
-        (render_frame_host == web_contents()->GetPrimaryMainFrame())) {
+        render_frame_host->IsInPrimaryMainFrame()) {
       UpdateBrowserControlsStateShown(/*animate=*/true);
     }
   }
diff --git a/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc
index 4ac6e0b8..4dc7eab 100644
--- a/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc
@@ -577,35 +577,16 @@
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
   EXPECT_TRUE(registrar().IsTabbedWindowModeEnabled(app_id));
-  content::WebContents* web_contents = tab_strip->GetActiveWebContents();
-
-  // Navigate home tab to different URL via a server redirect so that it doesn't
-  // open in a new tab.
-  GURL target_url =
-      embedded_test_server()->GetURL("/web_apps/get_manifest.html");
-  GURL redirect_url =
-      embedded_test_server()->GetURL("/server-redirect?" + target_url.spec());
-
-  // NavigateToURL() returns `false` because the final redirected URL does not
-  // match `redirect_url`. Separately ensure the navigation succeeded using a
-  // navigation observer.
-  content::TestNavigationObserver nav_observer(web_contents, 1);
-  EXPECT_FALSE(content::NavigateToURL(web_contents, redirect_url));
-  nav_observer.Wait();
-  EXPECT_TRUE(nav_observer.last_navigation_succeeded());
-
-  // Check no new tab was opened.
-  EXPECT_EQ(tab_strip->count(), 1);
 
   // Reload.
-  content::TestNavigationObserver reload_nav_observer(web_contents, 1);
+  content::TestNavigationObserver reload_nav_observer(
+      tab_strip->GetActiveWebContents(), 1);
   chrome::Reload(app_browser, WindowOpenDisposition::CURRENT_TAB);
   reload_nav_observer.Wait();
 
   // Expect the reload did not cause a new tab to open.
-  EXPECT_EQ(target_url, reload_nav_observer.last_navigation_url());
   EXPECT_EQ(tab_strip->count(), 1);
-  EXPECT_EQ(tab_strip->GetWebContentsAt(0)->GetVisibleURL(), target_url);
+  EXPECT_EQ(tab_strip->GetWebContentsAt(0)->GetVisibleURL(), start_url);
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, QueryParamsInStartUrl) {
@@ -632,4 +613,32 @@
             embedded_test_server()->GetURL("/web_apps/get_manifest.html"));
 }
 
+IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest,
+                       OutOfScopeNavigationFromHomeTab) {
+  GURL start_url =
+      embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
+  AppId app_id = InstallWebAppFromPage(browser(), start_url);
+  Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
+  TabStripModel* tab_strip = app_browser->tab_strip_model();
+
+  EXPECT_TRUE(registrar().IsTabbedWindowModeEnabled(app_id));
+
+  // Expect app opened with pinned home tab.
+  EXPECT_EQ(tab_strip->count(), 1);
+  EXPECT_TRUE(tab_strip->IsTabPinned(0));
+  EXPECT_EQ(tab_strip->GetWebContentsAt(0)->GetVisibleURL(), start_url);
+  EXPECT_EQ(tab_strip->active_index(), 0);
+
+  // Navigate to an out of scope URL.
+  OpenUrlAndWait(app_browser, GURL("https://www.example.com"));
+
+  // Expect URL to have opened in a new browser tab.
+  EXPECT_EQ(tab_strip->count(), 1);
+  EXPECT_EQ(tab_strip->active_index(), 0);
+  EXPECT_EQ(tab_strip->GetWebContentsAt(0)->GetVisibleURL(), start_url);
+  EXPECT_EQ(
+      browser()->tab_strip_model()->GetActiveWebContents()->GetVisibleURL(),
+      GURL("https://www.example.com"));
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/ui/web_applications/tabbed_web_app_navigation_throttle.cc b/chrome/browser/ui/web_applications/tabbed_web_app_navigation_throttle.cc
index f6c4978..c58ac46 100644
--- a/chrome/browser/ui/web_applications/tabbed_web_app_navigation_throttle.cc
+++ b/chrome/browser/ui/web_applications/tabbed_web_app_navigation_throttle.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/web_applications/app_browser_controller.h"
 #include "chrome/browser/ui/web_applications/web_app_tabbed_utils.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
@@ -44,24 +45,24 @@
 
   content::WebContents* web_contents = handle->GetWebContents();
 
+  Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
+  if (!browser || !browser->app_controller())
+    return nullptr;
+
   WebAppProvider* provider = WebAppProvider::GetForWebContents(web_contents);
   if (!provider)
     return nullptr;
 
-  absl::optional<web_app::AppId> app_id =
-      provider->registrar().FindInstalledAppWithUrlInScope(
-          handle->GetURL(), /*window_only=*/true);
-  if (!app_id)
-    return nullptr;
+  const AppId& app_id = browser->app_controller()->app_id();
 
   absl::optional<GURL> home_tab_url =
-      provider->registrar().GetAppPinnedHomeTabUrl(*app_id);
+      provider->registrar().GetAppPinnedHomeTabUrl(app_id);
 
   auto* tab_helper = WebAppTabHelper::FromWebContents(web_contents);
 
   // Only create the throttle for tabbed web apps that have a home tab.
   if (tab_helper && tab_helper->acting_as_app() &&
-      provider->registrar().IsTabbedWindowModeEnabled(*app_id) &&
+      provider->registrar().IsTabbedWindowModeEnabled(app_id) &&
       home_tab_url.has_value()) {
     return std::make_unique<TabbedWebAppNavigationThrottle>(handle);
   }
@@ -76,20 +77,22 @@
   WebAppProvider* provider = WebAppProvider::GetForWebContents(web_contents);
   DCHECK(provider);
 
-  absl::optional<web_app::AppId> app_id =
-      provider->registrar().FindInstalledAppWithUrlInScope(
-          navigation_handle()->GetURL(), /*window_only=*/true);
-  DCHECK(app_id);
+  Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
+  DCHECK(browser);
+  web_app::AppBrowserController* app_controller = browser->app_controller();
+  DCHECK(app_controller);
+
+  const AppId& app_id = app_controller->app_id();
 
   absl::optional<GURL> home_tab_url =
-      provider->registrar().GetAppPinnedHomeTabUrl(*app_id);
+      provider->registrar().GetAppPinnedHomeTabUrl(app_id);
   DCHECK(home_tab_url.has_value());
 
   auto* tab_helper = WebAppTabHelper::FromWebContents(web_contents);
   DCHECK(tab_helper);
   bool navigating_from_home_tab = tab_helper->is_pinned_home_tab();
   bool navigation_url_is_home_url = IsPinnedHomeTabUrl(
-      provider->registrar(), *app_id, navigation_handle()->GetURL());
+      provider->registrar(), app_id, navigation_handle()->GetURL());
 
   // Navigations from the home tab to another URL should open in a new tab.
   if (navigating_from_home_tab && !navigation_url_is_home_url) {
diff --git a/chrome/browser/ui/webui/app_settings/web_app_settings_ui.cc b/chrome/browser/ui/webui/app_settings/web_app_settings_ui.cc
index baf0fff4..6252efc 100644
--- a/chrome/browser/ui/webui/app_settings/web_app_settings_ui.cc
+++ b/chrome/browser/ui/webui/app_settings/web_app_settings_ui.cc
@@ -89,6 +89,7 @@
       html_source,
       base::make_span(kAppSettingsResources, kAppSettingsResourcesSize),
       IDR_APP_SETTINGS_WEB_APP_SETTINGS_HTML);
+  webui::EnableTrustedTypesCSP(html_source);
 
   Profile* profile = Profile::FromWebUI(web_ui);
   content::WebUIDataSource::Add(profile, html_source);
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index 12fbda1d..57a5651 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -54,12 +54,12 @@
 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
 #include "chrome/browser/web_applications/commands/install_from_info_command.h"
-#include "chrome/browser/web_applications/commands/run_on_os_login_command.h"
 #include "chrome/browser/web_applications/extension_status_utils.h"
 #include "chrome/browser/web_applications/extensions/bookmark_app_util.h"
 #include "chrome/browser/web_applications/user_display_mode.h"
 #include "chrome/browser/web_applications/web_app.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_icon_manager.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
@@ -1261,11 +1261,8 @@
     return;
   }
 
-  web_app_provider_->command_manager().ScheduleCommand(
-      web_app::RunOnOsLoginCommand::CreateForSetLoginMode(
-          &web_app_provider_->registrar(),
-          &web_app_provider_->os_integration_manager(),
-          &web_app_provider_->sync_bridge(), app_id, mode, base::DoNothing()));
+  web_app_provider_->scheduler().SetRunOnOsLoginMode(app_id, mode,
+                                                     base::DoNothing());
 }
 
 void AppLauncherHandler::HandleLaunchDeprecatedAppDialog(
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_default_unittest.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_default_unittest.cc
index 66e3e754..14acaa95 100644
--- a/chrome/browser/ui/webui/print_preview/local_printer_handler_default_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_default_unittest.cc
@@ -31,10 +31,78 @@
 #include "base/notreached.h"
 #endif
 
+#if BUILDFLAG(IS_WIN) && BUILDFLAG(ENABLE_OOP_PRINTING)
+#include <vector>
+
+#include "base/task/thread_pool.h"
+#include "base/test/bind.h"
+#include "base/test/values_test_util.h"
+#include "chrome/browser/printing/printer_xml_parser_impl.h"
+#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
+#endif  // BUILDFLAG(IS_WIN) && BUILDFLAG(ENABLE_OOP_PRINTING)
+
 namespace printing {
 
 namespace {
 
+#if BUILDFLAG(IS_WIN) && BUILDFLAG(ENABLE_OOP_PRINTING)
+constexpr char kVendorCapabilities[] = "vendor_capability";
+
+// XML with feature not of interest.
+constexpr char kXmlTestFeature[] =
+    R"(<?xml version="1.0" encoding="UTF-8"?>
+    <psf:PrintCapabilities>
+      <psf:Feature name="TestFeature">
+        <psf:Property name="psf:SelectionType">
+          <psf:Value xsi:type="xsd:QName">psk:PickOne</psf:Value>
+        </psf:Property>
+        <psf:Option constrained="psk:None">
+          <psf:ScoredProperty name="TestTimeStamp">
+            <psf:Value xsi:type="xsd:integer">0</psf:Value>
+          </psf:ScoredProperty>
+        </psf:Option>
+      </psf:Feature>
+    </psf:PrintCapabilities>)";
+
+constexpr char kXmlPageOutputQuality[] =
+    R"(<?xml version="1.0" encoding="UTF-8"?>
+    <psf:PrintCapabilities>
+      <psf:Feature name="psk:PageOutputQuality">
+        <psf:Property name="psf:SelectionType">
+          <psf:Value xsi:type="xsd:QName">psk:PickOne</psf:Value>
+        </psf:Property>
+        <psf:Property name="psk:DisplayName">
+          <psf:Value xsi:type="xsd:string">Quality</psf:Value>
+        </psf:Property>
+        <psf:Option name="ns0000:Draft" constrained="psk:None">
+          <psf:Property name="psk:DisplayName">
+            <psf:Value xsi:type="xsd:string">Draft</psf:Value>
+          </psf:Property>
+        </psf:Option>
+        <psf:Option name="ns0000:Standard" constrained="psk:None">
+          <psf:Property name="psk:DisplayName">
+            <psf:Value xsi:type="xsd:string">Standard</psf:Value>
+          </psf:Property>
+        </psf:Option>
+      </psf:Feature>
+    </psf:PrintCapabilities>)";
+
+constexpr char kJsonPageOutputQuality[] = R"({
+  "display_name": "Page output quality",
+  "id": "page_output_quality",
+  "select_cap": {
+    "option": [ {
+        "display_name": "Draft",
+        "value": "ns0000:Draft"
+      }, {
+        "display_name": "Standard",
+        "value": "ns0000:Standard"
+      } ]
+  },
+  "type": "SELECT"
+})";
+#endif  // BUILDFLAG(IS_WIN) && BUILDFLAG(ENABLE_OOP_PRINTING)
+
 // Used as a callback to `GetDefaultPrinter()` in tests.
 // Records value returned by `GetDefaultPrinter()`.
 void RecordGetDefaultPrinter(std::string& default_printer_out,
@@ -118,16 +186,33 @@
   // Indicate if fallback support for access-denied errors should be included
   // when using a service for print backend calls.
   virtual bool SupportFallback() = 0;
-#endif
+
+#if BUILDFLAG(IS_WIN)
+  // Indicate if print backend service should be able to fetch XPS capabilities
+  // when fetching printer capabilities.
+  virtual bool EnableXpsCapabilities() = 0;
+#endif  // BUILDFLAG(IS_WIN)
+#endif  // BUILDFLAG(ENABLE_OOP_PRINTING)
 
   void SetUp() override {
 #if BUILDFLAG(ENABLE_OOP_PRINTING)
     // Choose between running with local test runner or via a service.
     if (UseService()) {
-      feature_list_.InitAndEnableFeatureWithParameters(
-          features::kEnableOopPrintDrivers,
-          {{ features::kEnableOopPrintDriversSandbox.name,
-             "true" }});
+      std::vector<base::test::FeatureRefAndParams> features_and_params(
+          {{ features::kEnableOopPrintDrivers,
+             {
+               { features::kEnableOopPrintDriversSandbox.name,
+                 "true" }
+             } }});
+
+#if BUILDFLAG(IS_WIN)
+      if (EnableXpsCapabilities()) {
+        features_and_params.push_back(
+            {features::kReadPrinterCapabilitiesWithXps, {}});
+      }
+#endif  // BUILDFLAG(IS_WIN)
+
+      feature_list_.InitWithFeaturesAndParameters(features_and_params, {});
     } else {
       feature_list_.InitWithFeatureState(features::kEnableOopPrintDrivers,
                                          false);
@@ -145,18 +230,30 @@
     if (UseService()) {
 #if BUILDFLAG(ENABLE_OOP_PRINTING)
       sandboxed_print_backend_ = base::MakeRefCounted<TestPrintBackend>();
+      if (SupportFallback())
+        unsandboxed_print_backend_ = base::MakeRefCounted<TestPrintBackend>();
+
+#if BUILDFLAG(IS_WIN)
+      // To test OOP for Windows, the Print Backend service and Data Decoder
+      // service are launched on separate threads. This setup is required to
+      // unblock Mojo calls.
+      if (EnableXpsCapabilities()) {
+        xml_parser_ = std::make_unique<PrinterXmlParserImpl>();
+        SetUpDataDecoder();
+      }
+      SetUpServiceThread();
+#else
       sandboxed_print_backend_service_ =
           PrintBackendServiceTestImpl::LaunchForTesting(
               sandboxed_print_backend_remote_, sandboxed_print_backend_,
               /*sandboxed=*/true);
       if (SupportFallback()) {
-        unsandboxed_print_backend_ = base::MakeRefCounted<TestPrintBackend>();
-
         unsandboxed_print_backend_service_ =
             PrintBackendServiceTestImpl::LaunchForTesting(
                 unsandboxed_print_backend_remote_, unsandboxed_print_backend_,
                 /*sandboxed=*/false);
       }
+#endif  // BUILDFLAG(IS_WIN)
 #else
       NOTREACHED();
 #endif  // BUILDFLAG(ENABLE_OOP_PRINTING)
@@ -169,8 +266,26 @@
   }
 
 #if BUILDFLAG(ENABLE_OOP_PRINTING)
-  void TearDown() override { PrintBackendServiceManager::ResetForTesting(); }
-#endif
+
+  void TearDown() override {
+#if BUILDFLAG(IS_WIN)
+    if (UseService()) {
+      service_task_runner_->DeleteSoon(
+          FROM_HERE, std::move(sandboxed_print_backend_service_));
+      if (SupportFallback()) {
+        service_task_runner_->DeleteSoon(
+            FROM_HERE, std::move(unsandboxed_print_backend_service_));
+      }
+      if (EnableXpsCapabilities()) {
+        data_decoder_task_runner_->DeleteSoon(FROM_HERE,
+                                              std::move(data_decoder_));
+      }
+    }
+#endif  // BUILDFLAG(IS_WIN)
+
+    PrintBackendServiceManager::ResetForTesting();
+  }
+#endif  // BUILDFLAG(ENABLE_OOP_PRINTING)
 
   void AddPrinter(const std::string& id,
                   const std::string& display_name,
@@ -210,6 +325,19 @@
   }
 
 #if BUILDFLAG(ENABLE_OOP_PRINTING)
+#if BUILDFLAG(IS_WIN)
+  void SetPrinterXml(const std::string& id,
+                     const std::string& capabilities_xml) {
+    if (SupportFallback()) {
+      unsandboxed_print_backend()->SetXmlCapabilitiesForPrinter(
+          id, capabilities_xml);
+    }
+
+    sandboxed_print_backend()->SetXmlCapabilitiesForPrinter(id,
+                                                            capabilities_xml);
+  }
+#endif  // BUILDFLAG(IS_WIN)
+
   void SetTerminateServiceOnNextInteraction() {
     if (SupportFallback()) {
       unsandboxed_print_backend_service_
@@ -227,6 +355,48 @@
   }
 
  private:
+#if BUILDFLAG(IS_WIN) && BUILDFLAG(ENABLE_OOP_PRINTING)
+  void SetUpDataDecoder() {
+    data_decoder_task_runner_ = base::ThreadPool::CreateSingleThreadTaskRunner(
+        {}, base::SingleThreadTaskRunnerThreadMode::DEDICATED);
+
+    base::RunLoop run_loop;
+    data_decoder_task_runner_->PostTaskAndReply(
+        FROM_HERE, base::BindLambdaForTesting([&]() {
+          data_decoder_ =
+              std::make_unique<data_decoder::test::InProcessDataDecoder>();
+        }),
+        run_loop.QuitClosure());
+    run_loop.Run();
+  }
+
+  void SetUpServiceThread() {
+    mojo::PendingRemote<mojom::PrinterXmlParser> sandboxed_xml_parser_remote;
+    mojo::PendingRemote<mojom::PrinterXmlParser> unsandboxed_xml_parser_remote;
+    if (EnableXpsCapabilities()) {
+      sandboxed_xml_parser_remote = xml_parser_->GetRemote();
+      unsandboxed_xml_parser_remote = xml_parser_->GetRemote();
+    }
+
+    service_task_runner_ = base::ThreadPool::CreateSingleThreadTaskRunner(
+        {}, base::SingleThreadTaskRunnerThreadMode::DEDICATED);
+
+    sandboxed_print_backend_service_ =
+        PrintBackendServiceTestImpl::LaunchForTestingWithServiceThread(
+            sandboxed_print_backend_remote_, sandboxed_print_backend_,
+            /*sandboxed=*/true, std::move(sandboxed_xml_parser_remote),
+            service_task_runner_);
+
+    if (SupportFallback()) {
+      unsandboxed_print_backend_service_ =
+          PrintBackendServiceTestImpl::LaunchForTestingWithServiceThread(
+              unsandboxed_print_backend_remote_, unsandboxed_print_backend_,
+              /*sandboxed=*/false, std::move(unsandboxed_xml_parser_remote),
+              service_task_runner_);
+    }
+  }
+#endif  // BUILDFLAG(IS_WIN) && BUILDFLAG(ENABLE_OOP_PRINTING)
+
   // Must outlive `profile_`.
   content::BrowserTaskEnvironment task_environment_;
   std::unique_ptr<TestingProfile> profile_;
@@ -243,6 +413,14 @@
   std::unique_ptr<PrintBackendServiceTestImpl> sandboxed_print_backend_service_;
   std::unique_ptr<PrintBackendServiceTestImpl>
       unsandboxed_print_backend_service_;
+
+#if BUILDFLAG(IS_WIN)
+  scoped_refptr<base::SingleThreadTaskRunner> service_task_runner_;
+  scoped_refptr<base::SingleThreadTaskRunner> data_decoder_task_runner_;
+  std::unique_ptr<data_decoder::test::InProcessDataDecoder> data_decoder_;
+  std::unique_ptr<PrinterXmlParserImpl> xml_parser_;
+#endif  // BUILDFLAG(IS_WIN)
+
 #else
   scoped_refptr<TestPrintBackend> default_print_backend_;
 #endif  // BUILDFLAG(ENABLE_OOP_PRINTING)
@@ -266,7 +444,11 @@
   bool UseService() override { return GetParam(); }
 #if BUILDFLAG(ENABLE_OOP_PRINTING)
   bool SupportFallback() override { return false; }
-#endif
+
+#if BUILDFLAG(IS_WIN)
+  bool EnableXpsCapabilities() override { return false; }
+#endif  // BUILDFLAG(IS_WIN)
+#endif  // BUILDFLAG(ENABLE_OOP_PRINTING)
 };
 
 #if BUILDFLAG(ENABLE_OOP_PRINTING)
@@ -293,8 +475,19 @@
 
   bool UseService() override { return true; }
   bool SupportFallback() override { return true; }
+#if BUILDFLAG(IS_WIN)
+  bool EnableXpsCapabilities() override { return false; }
+#endif  // BUILDFLAG(IS_WIN)
 };
 
+#if BUILDFLAG(IS_WIN)
+class LocalPrinterHandlerDefaultWithServiceEnableXpsTest
+    : public LocalPrinterHandlerDefaultWithServiceTest {
+ public:
+  bool EnableXpsCapabilities() override { return true; }
+};
+#endif  // BUILDFLAG(IS_WIN)
+
 INSTANTIATE_TEST_SUITE_P(All, LocalPrinterHandlerDefaultTest, testing::Bool());
 
 #else
@@ -591,6 +784,89 @@
   EXPECT_TRUE(fetched_caps.empty());
 }
 
-#endif  // #if BUILDFLAG(ENABLE_OOP_PRINTING)
+#if BUILDFLAG(IS_WIN)
+
+// Tests that fetching XPS capabilities succeeds if the XML string is valid,
+// even when there are no XPS capabilities of interest.
+TEST_F(LocalPrinterHandlerDefaultWithServiceEnableXpsTest,
+       FetchXpsPrinterCapabilitiesValidXps) {
+  AddPrinter("printer1", "default1", "description1", /*is_default=*/true,
+             /*requires_elevated_permissions=*/false);
+  SetPrinterXml("printer1", kXmlTestFeature);
+
+  base::Value::Dict fetched_caps;
+  local_printer_handler()->StartGetCapability(
+      /*destination_id=*/"printer1",
+      base::BindOnce(&RecordGetCapability, std::ref(fetched_caps)));
+  RunUntilIdle();
+
+  // Fetching capabilities should still succeed.
+  const base::Value::Dict* capabilities =
+      fetched_caps.FindDict(kSettingCapabilities);
+  ASSERT_TRUE(capabilities);
+  EXPECT_TRUE(fetched_caps.FindDict(kPrinter));
+
+  // None of the capabilities of interest exist in the XML, so no XML
+  // capabilities should be added.
+  const base::Value::Dict* printer = capabilities->FindDict(kPrinter);
+  ASSERT_TRUE(printer);
+  ASSERT_FALSE(printer->FindList(kVendorCapabilities));
+}
+
+// Tests that XPS capabilities are included when fetching capabilities of
+// interest.
+TEST_F(LocalPrinterHandlerDefaultWithServiceEnableXpsTest,
+       FetchXpsPrinterCapabilitiesValidXpsCapabilityWithInterest) {
+  AddPrinter("printer1", "default1", "description1", /*is_default=*/true,
+             /*requires_elevated_permissions=*/false);
+  SetPrinterXml("printer1", kXmlPageOutputQuality);
+
+  base::Value::Dict fetched_caps;
+  local_printer_handler()->StartGetCapability(
+      /*destination_id=*/"printer1",
+      base::BindOnce(&RecordGetCapability, std::ref(fetched_caps)));
+
+  RunUntilIdle();
+
+  const base::Value::Dict* capabilities =
+      fetched_caps.FindDict(kSettingCapabilities);
+  ASSERT_TRUE(capabilities);
+  EXPECT_TRUE(fetched_caps.FindDict(kPrinter));
+
+  // Check for XPS capabilities added.
+  const base::Value::Dict* printer = capabilities->FindDict(kPrinter);
+  ASSERT_TRUE(printer);
+
+  const base::Value::List* vendor_capabilities =
+      printer->FindList(kVendorCapabilities);
+  ASSERT_TRUE(vendor_capabilities);
+  ASSERT_EQ(vendor_capabilities->size(), 1u);
+  EXPECT_EQ(vendor_capabilities->front(),
+            base::test::ParseJson(kJsonPageOutputQuality));
+}
+
+// Tests that fetching capabilities fails when the XPS string is invalid and
+// cannot be processed.
+TEST_F(LocalPrinterHandlerDefaultWithServiceEnableXpsTest,
+       FetchXpsPrinterCapabilitiesInvalidXps) {
+  AddPrinter("printer1", "default1", "description1", /*is_default=*/true,
+             /*requires_elevated_permissions=*/false);
+  SetPrinterXml("printer1", "");
+
+  base::Value::Dict fetched_caps;
+  local_printer_handler()->StartGetCapability(
+      /*destination_id=*/"printer1",
+      base::BindOnce(&RecordGetCapability, std::ref(fetched_caps)));
+
+  RunUntilIdle();
+
+  const base::Value::Dict* capabilities =
+      fetched_caps.FindDict(kSettingCapabilities);
+  ASSERT_FALSE(capabilities);
+}
+
+#endif  // BUILDFLAG(IS_WIN)
+
+#endif  // BUILDFLAG(ENABLE_OOP_PRINTING)
 
 }  // namespace printing
diff --git a/chrome/browser/ui/webui/settings/ash/accessibility_section.cc b/chrome/browser/ui/webui/settings/ash/accessibility_section.cc
index 73861d6..eb4231b 100644
--- a/chrome/browser/ui/webui/settings/ash/accessibility_section.cc
+++ b/chrome/browser/ui/webui/settings/ash/accessibility_section.cc
@@ -53,6 +53,7 @@
 using ::chromeos::settings::mojom::kDisplayAndMagnificationSubpagePath;
 using ::chromeos::settings::mojom::kKeyboardAndTextInputSubpagePath;
 using ::chromeos::settings::mojom::kManageAccessibilitySubpagePath;
+using ::chromeos::settings::mojom::kSelectToSpeakSubpagePath;
 using ::chromeos::settings::mojom::kSwitchAccessOptionsSubpagePath;
 using ::chromeos::settings::mojom::kTextToSpeechPagePath;
 using ::chromeos::settings::mojom::kTextToSpeechSubpagePath;
@@ -468,6 +469,10 @@
   return ::features::IsAccessibilityOSSettingsVisibilityEnabled();
 }
 
+bool IsAccessibilitySelectToSpeakPageMigrationEnabled() {
+  return ::features::IsAccessibilitySelectToSpeakPageMigrationEnabled();
+}
+
 bool AreExperimentalAccessibilityColorEnhancementSettingsEnabled() {
   return ::features::
       AreExperimentalAccessibilityColorEnhancementSettingsEnabled();
@@ -758,6 +763,8 @@
        IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_DESCRIPTION_WITHOUT_KEYBOARD},
       {"selectToSpeakDisabledDescription",
        IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_DISABLED_DESCRIPTION},
+      {"selectToSpeakLinkTitle",
+       IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_LINK_TITLE},
       {"selectToSpeakOptionsLabel",
        IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_OPTIONS_LABEL},
       {"selectToSpeakTitle", IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_TITLE},
@@ -941,6 +948,9 @@
   html_source->AddBoolean("isAccessibilityOSSettingsVisibilityEnabled",
                           IsAccessibilityOSSettingsVisibilityEnabled());
 
+  html_source->AddBoolean("isAccessibilitySelectToSpeakPageMigrationEnabled",
+                          IsAccessibilitySelectToSpeakPageMigrationEnabled());
+
   html_source->AddBoolean(
       "areExperimentalAccessibilityColorEnhancementSettingsEnabled",
       AreExperimentalAccessibilityColorEnhancementSettingsEnabled());
@@ -1017,6 +1027,14 @@
         IDS_SETTINGS_ACCESSIBILITY_TEXT_TO_SPEECH_LINK_TITLE,
         mojom::Subpage::kTextToSpeechPage, mojom::SearchResultIcon::kA11y,
         mojom::SearchResultDefaultRank::kMedium, mojom::kTextToSpeechPagePath);
+    // Select to speak options page.
+    if (IsAccessibilitySelectToSpeakPageMigrationEnabled()) {
+      generator->RegisterTopLevelSubpage(
+          IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_LINK_TITLE,
+          mojom::Subpage::kSelectToSpeak, mojom::SearchResultIcon::kA11y,
+          mojom::SearchResultDefaultRank::kMedium,
+          mojom::kSelectToSpeakSubpagePath);
+    }
     // Display and magnification page.
     generator->RegisterTopLevelSubpage(
         IDS_SETTINGS_ACCESSIBILITY_DISPLAY_AND_MAGNIFICATION_LINK_TITLE,
@@ -1081,6 +1099,7 @@
   RegisterNestedSettingBulk(mojom::Subpage::kTextToSpeech,
                             kTextToSpeechSettings, generator);
 
+  // TODO(crbug.com/1383613): Change some of these to RegisterNestedSubpages.
   // Switch access.
   generator->RegisterTopLevelSubpage(IDS_SETTINGS_MANAGE_SWITCH_ACCESS_SETTINGS,
                                      mojom::Subpage::kSwitchAccessOptions,
diff --git a/chrome/browser/ui/webui/settings/ash/accessibility_section.h b/chrome/browser/ui/webui/settings/ash/accessibility_section.h
index 524f96c..7b0e7b4 100644
--- a/chrome/browser/ui/webui/settings/ash/accessibility_section.h
+++ b/chrome/browser/ui/webui/settings/ash/accessibility_section.h
@@ -54,6 +54,7 @@
                            const extensions::Extension* extension,
                            extensions::UnloadedExtensionReason reason) override;
 
+  void AddSelectToSpeakStrings(content::WebUIDataSource* html_source);
   void UpdateSearchTags();
   void UpdateTextToSpeechVoiceSearchTags();
   void UpdateTextToSpeechEnginesSearchTags();
diff --git a/chrome/browser/ui/webui/settings/ash/android_apps_handler.cc b/chrome/browser/ui/webui/settings/ash/android_apps_handler.cc
index 61d6a2a2..baa74d0 100644
--- a/chrome/browser/ui/webui/settings/ash/android_apps_handler.cc
+++ b/chrome/browser/ui/webui/settings/ash/android_apps_handler.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"  // kSettingsAppId
 #include "components/services/app_service/public/cpp/app_launch_util.h"
-#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/display/display.h"
@@ -108,16 +107,9 @@
     activated_from_keyboard = args[0].GetBool();
   int flags = activated_from_keyboard ? ui::EF_NONE : ui::EF_LEFT_MOUSE_BUTTON;
 
-  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-    app_service_proxy_->Launch(
-        arc::kSettingsAppId, flags, apps::LaunchSource::kFromParentalControls,
-        std::make_unique<apps::WindowInfo>(GetDisplayIdForCurrentProfile()));
-  } else {
-    app_service_proxy_->Launch(
-        arc::kSettingsAppId, flags,
-        apps::mojom::LaunchSource::kFromParentalControls,
-        apps::MakeWindowInfo(GetDisplayIdForCurrentProfile()));
-  }
+  app_service_proxy_->Launch(
+      arc::kSettingsAppId, flags, apps::LaunchSource::kFromParentalControls,
+      std::make_unique<apps::WindowInfo>(GetDisplayIdForCurrentProfile()));
 }
 
 int64_t AndroidAppsHandler::GetDisplayIdForCurrentProfile() {
diff --git a/chrome/browser/ui/webui/settings/ash/internet_handler.cc b/chrome/browser/ui/webui/settings/ash/internet_handler.cc
index 4e0d180..2bb07d9 100644
--- a/chrome/browser/ui/webui/settings/ash/internet_handler.cc
+++ b/chrome/browser/ui/webui/settings/ash/internet_handler.cc
@@ -27,7 +27,6 @@
 #include "chromeos/ash/components/network/network_state_handler.h"
 #include "components/onc/onc_constants.h"
 #include "components/prefs/pref_service.h"
-#include "components/services/app_service/public/cpp/features.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
@@ -138,14 +137,8 @@
   if (arc_app_list_prefs && arc_app_list_prefs->GetApp(app_id)) {
     DCHECK(apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(
         profile_));
-    if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-      apps::AppServiceProxyFactory::GetForProfile(profile_)->Launch(
-          app_id, ui::EF_NONE, apps::LaunchSource::kFromParentalControls);
-    } else {
-      apps::AppServiceProxyFactory::GetForProfile(profile_)->Launch(
-          app_id, ui::EF_NONE,
-          apps::mojom::LaunchSource::kFromParentalControls);
-    }
+    apps::AppServiceProxyFactory::GetForProfile(profile_)->Launch(
+        app_id, ui::EF_NONE, apps::LaunchSource::kFromParentalControls);
     return;
   }
 
diff --git a/chrome/browser/ui/webui/settings/ash/os_settings_manager_unittest.cc b/chrome/browser/ui/webui/settings/ash/os_settings_manager_unittest.cc
index e668369..66a9715 100644
--- a/chrome/browser/ui/webui/settings/ash/os_settings_manager_unittest.cc
+++ b/chrome/browser/ui/webui/settings/ash/os_settings_manager_unittest.cc
@@ -51,7 +51,9 @@
   // testing::Test:
   void SetUp() override {
     scoped_feature_list_.InitWithFeatures(
-      {features::kAccessibilityOSSettingsVisibility}, {});
+        {features::kAccessibilityOSSettingsVisibility,
+         features::kAccessibilitySelectToSpeakPageMigration},
+        {});
 
     ASSERT_TRUE(profile_manager_.SetUp());
     TestingProfile* profile =
diff --git a/chrome/browser/ui/webui/settings/ash/parental_controls_handler.cc b/chrome/browser/ui/webui/settings/ash/parental_controls_handler.cc
index 2a85d7322..94f3879 100644
--- a/chrome/browser/ui/webui/settings/ash/parental_controls_handler.cc
+++ b/chrome/browser/ui/webui/settings/ash/parental_controls_handler.cc
@@ -19,8 +19,6 @@
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/app_update.h"
-#include "components/services/app_service/public/cpp/features.h"
-#include "components/services/app_service/public/mojom/types.mojom.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/display/types/display_constants.h"
@@ -71,15 +69,9 @@
       ChildUserService::kFamilyLinkHelperAppPackageName, profile_);
   if (registry.GetAppType(app_id) != apps::AppType::kUnknown) {
     // Launch FLH app since it is available.
-    if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-      proxy->Launch(
-          app_id, ui::EF_NONE, apps::LaunchSource::kFromParentalControls,
-          std::make_unique<apps::WindowInfo>(display::kDefaultDisplayId));
-    } else {
-      proxy->Launch(app_id, ui::EF_NONE,
-                    apps::mojom::LaunchSource::kFromParentalControls,
-                    apps::MakeWindowInfo(display::kDefaultDisplayId));
-    }
+    proxy->Launch(
+        app_id, ui::EF_NONE, apps::LaunchSource::kFromParentalControls,
+        std::make_unique<apps::WindowInfo>(display::kDefaultDisplayId));
     return;
   }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom b/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom
index af8e538..67887a8b 100644
--- a/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom
+++ b/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom
@@ -152,6 +152,7 @@
   kKeyboardAndTextInput = 1507,
   kCursorAndTouchpad = 1508,
   kAudioAndCaptions = 1509,
+  kSelectToSpeak = 1510,
 
   // Note: Reset section has no subpages.
 
@@ -277,6 +278,7 @@
 const string kDisplayAndMagnificationSubpagePath = "displayAndMagnification";
 const string kKeyboardAndTextInputSubpagePath = "keyboardAndTextInput";
 const string kCursorAndTouchpadSubpagePath = "cursorAndTouchpad";
+const string kSelectToSpeakSubpagePath = "textToSpeech/selectToSpeak";
 const string kAudioAndCaptionsSubpagePath = "audioAndCaptions";
 const string kTextToSpeechSubpagePath = "manageAccessibility/tts";
 const string kSwitchAccessOptionsSubpagePath =
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc
index 1936ca7..0f7b23b 100644
--- a/chrome/browser/ui/webui/settings/settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -413,6 +413,7 @@
   webui::SetupWebUIDataSource(
       html_source, base::make_span(kSettingsResources, kSettingsResourcesSize),
       IDR_SETTINGS_SETTINGS_HTML);
+  webui::EnableTrustedTypesCSP(html_source);
 
   AddLocalizedStrings(html_source, profile, web_ui->GetWebContents());
 
diff --git a/chrome/browser/ui/webui/webui_util.cc b/chrome/browser/ui/webui/webui_util.cc
index d5196a2..0e87f4c 100644
--- a/chrome/browser/ui/webui/webui_util.cc
+++ b/chrome/browser/ui/webui/webui_util.cc
@@ -69,7 +69,8 @@
   source->OverrideContentSecurityPolicy(
       network::mojom::CSPDirectiveName::TrustedTypes,
       "trusted-types parse-html-subset sanitize-inner-html static-types "
-      "webui-test-script "
+      // Add TrustedTypes policies used during tests.
+      "webui-test-script webui-test-html "
       // Add TrustedTypes policies necessary for using Polymer.
       "polymer-html-literal polymer-template-event-attribute-policy;");
 }
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
index af550bf3..edb12e3 100644
--- a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
+++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
@@ -51,14 +51,12 @@
 #include "chrome/browser/ui/web_applications/web_app_dialog_manager.h"
 #include "chrome/browser/ui/web_applications/web_app_launch_manager.h"
 #include "chrome/browser/ui/web_applications/web_app_ui_manager_impl.h"
-#include "chrome/browser/web_applications/commands/run_on_os_login_command.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/os_integration/web_app_file_handler_manager.h"
 #include "chrome/browser/web_applications/policy/web_app_policy_manager.h"
 #include "chrome/browser/web_applications/user_display_mode.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_chromeos_data.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_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
@@ -1280,12 +1278,9 @@
 void WebAppPublisherHelper::SetRunOnOsLoginMode(
     const std::string& app_id,
     apps::RunOnOsLoginMode run_on_os_login_mode) {
-  provider_->command_manager().ScheduleCommand(
-      RunOnOsLoginCommand::CreateForSetLoginMode(
-          &provider_->registrar(), &provider_->os_integration_manager(),
-          &provider_->sync_bridge(), app_id,
-          ConvertOsLoginModeToWebAppConstants(run_on_os_login_mode),
-          base::DoNothing()));
+  provider_->scheduler().SetRunOnOsLoginMode(
+      app_id, ConvertOsLoginModeToWebAppConstants(run_on_os_login_mode),
+      base::DoNothing());
 }
 
 apps::WindowMode WebAppPublisherHelper::ConvertDisplayModeToWindowMode(
diff --git a/chrome/browser/web_applications/commands/install_from_sync_command.cc b/chrome/browser/web_applications/commands/install_from_sync_command.cc
index 1864ff44..e79bfb4 100644
--- a/chrome/browser/web_applications/commands/install_from_sync_command.cc
+++ b/chrome/browser/web_applications/commands/install_from_sync_command.cc
@@ -74,8 +74,6 @@
 InstallFromSyncCommand::InstallFromSyncCommand(
     WebAppUrlLoader* url_loader,
     Profile* profile,
-    WebAppInstallFinalizer* finalizer,
-    WebAppRegistrar* registrar,
     std::unique_ptr<WebAppDataRetriever> data_retriever,
     const Params& params,
     OnceInstallCallback install_callback)
@@ -84,8 +82,6 @@
                            base::flat_set<AppId>>({params.app_id})),
       url_loader_(url_loader),
       profile_(profile),
-      finalizer_(finalizer),
-      registrar_(registrar),
       data_retriever_(std::move(data_retriever)),
       params_(params),
       install_callback_(std::move(install_callback)),
@@ -133,9 +129,12 @@
   return *lock_description_;
 }
 
-void InstallFromSyncCommand::Start() {
+void InstallFromSyncCommand::StartWithLock(
+    std::unique_ptr<SharedWebContentsWithAppLock> lock) {
+  lock_ = std::move(lock);
+
   url_loader_->LoadUrl(
-      params_.start_url, shared_web_contents(),
+      params_.start_url, &lock_->shared_web_contents(),
       WebAppUrlLoader::UrlComparison::kIgnoreQueryParamsAndRef,
       base::BindOnce(
           &InstallFromSyncCommand::OnWebAppUrlLoadedGetWebAppInstallInfo,
@@ -174,7 +173,7 @@
   }
 
   data_retriever_->GetWebAppInstallInfo(
-      shared_web_contents(),
+      &lock_->shared_web_contents(),
       base::BindOnce(&InstallFromSyncCommand::OnGetWebAppInstallInfo,
                      weak_ptr_factory_.GetWeakPtr()));
 }
@@ -198,7 +197,7 @@
   fallback_install_info_->mobile_capable = install_info_->mobile_capable;
 
   data_retriever_->CheckInstallabilityAndRetrieveManifest(
-      shared_web_contents(), /*bypass_service_worker_check=*/true,
+      &lock_->shared_web_contents(), /*bypass_service_worker_check=*/true,
       base::BindOnce(&InstallFromSyncCommand::OnDidPerformInstallableCheck,
                      weak_ptr_factory_.GetWeakPtr()));
 }
@@ -238,7 +237,7 @@
 
   base::flat_set<GURL> icon_urls = GetValidIconUrlsToDownload(*install_info_);
   data_retriever_->GetIcons(
-      shared_web_contents(), std::move(icon_urls),
+      &lock_->shared_web_contents(), std::move(icon_urls),
       /*skip_page_favicons=*/manifest_has_icons,
       base::BindOnce(&InstallFromSyncCommand::OnIconsRetrievedFinalizeInstall,
                      weak_ptr_factory_.GetWeakPtr(),
@@ -264,7 +263,7 @@
   install_error_log_entry_.LogDownloadedIconsErrors(
       *current_info, result, icons_map, icons_http_results);
 
-  finalizer_->FinalizeInstall(
+  lock_->install_finalizer().FinalizeInstall(
       *current_info, GetFinalizerOptionForSyncInstall(),
       base::BindOnce(&InstallFromSyncCommand::OnInstallFinalized,
                      weak_ptr_factory_.GetWeakPtr(), mode));
@@ -299,7 +298,7 @@
   // list.
   // TODO(dmurph): Also use favicons. https://crbug.com/1328977.
   data_retriever_->GetIcons(
-      shared_web_contents(), std::move(icon_urls),
+      &lock_->shared_web_contents(), std::move(icon_urls),
       /*skip_page_favicons=*/true,
       base::BindOnce(&InstallFromSyncCommand::OnIconsRetrievedFinalizeInstall,
                      weak_ptr_factory_.GetWeakPtr(),
diff --git a/chrome/browser/web_applications/commands/install_from_sync_command.h b/chrome/browser/web_applications/commands/install_from_sync_command.h
index 70c5e71..58566c51 100644
--- a/chrome/browser/web_applications/commands/install_from_sync_command.h
+++ b/chrome/browser/web_applications/commands/install_from_sync_command.h
@@ -27,13 +27,13 @@
 namespace web_app {
 
 class LockDescription;
+class SharedWebContentsWithAppLock;
 class SharedWebContentsWithAppLockDescription;
-class WebAppInstallFinalizer;
 class WebAppDataRetriever;
-class WebAppRegistrar;
 enum class WebAppUrlLoaderResult;
 
-class InstallFromSyncCommand : public WebAppCommand {
+class InstallFromSyncCommand
+    : public WebAppCommandTemplate<SharedWebContentsWithAppLock> {
  public:
   struct Params {
     Params() = delete;
@@ -62,8 +62,6 @@
   InstallFromSyncCommand(
       WebAppUrlLoader* url_loader,
       Profile* profile,
-      WebAppInstallFinalizer* finalizer,
-      WebAppRegistrar* registrar,
       std::unique_ptr<WebAppDataRetriever> web_app_data_retriever,
       const Params& params,
       OnceInstallCallback install_callback);
@@ -77,7 +75,8 @@
 
   void OnShutdown() override;
 
-  void Start() override;
+  void StartWithLock(
+      std::unique_ptr<SharedWebContentsWithAppLock> lock) override;
 
   void SetFallbackTriggeredForTesting(
       base::OnceCallback<void(webapps::InstallResultCode code)> callback);
@@ -111,10 +110,10 @@
                               webapps::InstallResultCode code);
 
   std::unique_ptr<SharedWebContentsWithAppLockDescription> lock_description_;
+  std::unique_ptr<SharedWebContentsWithAppLock> lock_;
+
   const base::raw_ptr<WebAppUrlLoader> url_loader_;
   const base::raw_ptr<Profile> profile_;
-  const base::raw_ptr<WebAppInstallFinalizer> finalizer_;
-  const base::raw_ptr<WebAppRegistrar> registrar_;
   const std::unique_ptr<WebAppDataRetriever> data_retriever_;
   const Params params_;
   OnceInstallCallback install_callback_;
diff --git a/chrome/browser/web_applications/commands/install_from_sync_command_browsertest.cc b/chrome/browser/web_applications/commands/install_from_sync_command_browsertest.cc
index 1b7da22..6097964 100644
--- a/chrome/browser/web_applications/commands/install_from_sync_command_browsertest.cc
+++ b/chrome/browser/web_applications/commands/install_from_sync_command_browsertest.cc
@@ -47,8 +47,7 @@
                       96)});
   provider->command_manager().ScheduleCommand(
       std::make_unique<InstallFromSyncCommand>(
-          url_loader.get(), profile(), &provider->install_finalizer(),
-          &provider->registrar(), std::make_unique<WebAppDataRetriever>(),
+          url_loader.get(), profile(), std::make_unique<WebAppDataRetriever>(),
           params,
           base::BindLambdaForTesting(
               [&](const AppId& app_id, webapps::InstallResultCode code) {
@@ -88,9 +87,8 @@
                         96)});
     provider->command_manager().ScheduleCommand(
         std::make_unique<InstallFromSyncCommand>(
-            url_loader.get(), profile(), &provider->install_finalizer(),
-            &provider->registrar(), std::make_unique<WebAppDataRetriever>(),
-            params,
+            url_loader.get(), profile(),
+            std::make_unique<WebAppDataRetriever>(), params,
             base::BindLambdaForTesting([&](const AppId& app_id,
                                            webapps::InstallResultCode code) {
               EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
@@ -106,9 +104,8 @@
                         96)});
     provider->command_manager().ScheduleCommand(
         std::make_unique<InstallFromSyncCommand>(
-            url_loader.get(), profile(), &provider->install_finalizer(),
-            &provider->registrar(), std::make_unique<WebAppDataRetriever>(),
-            params,
+            url_loader.get(), profile(),
+            std::make_unique<WebAppDataRetriever>(), params,
             base::BindLambdaForTesting([&](const AppId& app_id,
                                            webapps::InstallResultCode code) {
               EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
diff --git a/chrome/browser/web_applications/commands/install_from_sync_command_unittest.cc b/chrome/browser/web_applications/commands/install_from_sync_command_unittest.cc
index d0163e5..3233cef4 100644
--- a/chrome/browser/web_applications/commands/install_from_sync_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/install_from_sync_command_unittest.cc
@@ -123,8 +123,7 @@
       InstallFromSyncCommand::Params params,
       OnceInstallCallback install_callback) {
     return std::make_unique<InstallFromSyncCommand>(
-        &url_loader(), profile(), &provider()->install_finalizer(),
-        &provider()->registrar(), std::move(data_retriever), params,
+        &url_loader(), profile(), std::move(data_retriever), params,
         std::move(install_callback));
   }
 
diff --git a/chrome/browser/web_applications/commands/install_isolated_web_app_command.cc b/chrome/browser/web_applications/commands/install_isolated_web_app_command.cc
index 229b682..754def5 100644
--- a/chrome/browser/web_applications/commands/install_isolated_web_app_command.cc
+++ b/chrome/browser/web_applications/commands/install_isolated_web_app_command.cc
@@ -70,7 +70,6 @@
     std::unique_ptr<content::WebContents> web_contents,
     std::unique_ptr<WebAppUrlLoader> url_loader,
     content::BrowserContext& browser_context,
-    WebAppInstallFinalizer& install_finalizer,
     base::OnceCallback<void(base::expected<InstallIsolatedWebAppCommandSuccess,
                                            InstallIsolatedWebAppCommandError>)>
         callback)
@@ -81,7 +80,6 @@
       web_contents_(std::move(web_contents)),
       url_loader_(std::move(url_loader)),
       browser_context_(browser_context),
-      install_finalizer_(install_finalizer),
       data_retriever_(std::make_unique<WebAppDataRetriever>()) {
   DETACH_FROM_SEQUENCE(sequence_checker_);
 
@@ -109,8 +107,11 @@
   return *lock_description_;
 }
 
-void InstallIsolatedWebAppCommand::Start() {
+void InstallIsolatedWebAppCommand::StartWithLock(
+    std::unique_ptr<AppLock> lock) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  lock_ = std::move(lock);
+
   CreateStoragePartition();
   LoadUrl();
 }
@@ -257,7 +258,7 @@
       webapps::WebappInstallSource::ISOLATED_APP_DEV_INSTALL);
   options.isolation_data = isolation_data_;
 
-  install_finalizer_->FinalizeInstall(
+  lock_->install_finalizer().FinalizeInstall(
       info, options,
       base::BindOnce(&InstallIsolatedWebAppCommand::OnFinalizeInstall,
                      weak_factory_.GetWeakPtr()));
diff --git a/chrome/browser/web_applications/commands/install_isolated_web_app_command.h b/chrome/browser/web_applications/commands/install_isolated_web_app_command.h
index e83e4311c..c22f409a 100644
--- a/chrome/browser/web_applications/commands/install_isolated_web_app_command.h
+++ b/chrome/browser/web_applications/commands/install_isolated_web_app_command.h
@@ -33,10 +33,10 @@
 
 namespace web_app {
 
+class AppLock;
 class AppLockDescription;
 class LockDescription;
 class WebAppDataRetriever;
-class WebAppInstallFinalizer;
 class WebAppUrlLoader;
 
 enum class WebAppUrlLoaderResult;
@@ -59,7 +59,7 @@
 //
 // |content::IsolatedWebAppThrottle| enforces that. The requirements prevent
 // re-using web contents.
-class InstallIsolatedWebAppCommand : public WebAppCommand {
+class InstallIsolatedWebAppCommand : public WebAppCommandTemplate<AppLock> {
  public:
   //
   // |isolation_info| holds the origin information of the app. It is
@@ -78,7 +78,6 @@
       std::unique_ptr<content::WebContents> web_contents,
       std::unique_ptr<WebAppUrlLoader> url_loader,
       content::BrowserContext& browser_context,
-      WebAppInstallFinalizer& install_finalizer,
       base::OnceCallback<
           void(base::expected<InstallIsolatedWebAppCommandSuccess,
                               InstallIsolatedWebAppCommandError>)> callback);
@@ -97,7 +96,7 @@
 
   base::Value ToDebugValue() const override;
 
-  void Start() override;
+  void StartWithLock(std::unique_ptr<AppLock> lock) override;
   void OnSyncSourceRemoved() override;
   void OnShutdown() override;
 
@@ -136,6 +135,7 @@
   SEQUENCE_CHECKER(sequence_checker_);
 
   std::unique_ptr<AppLockDescription> lock_description_;
+  std::unique_ptr<AppLock> lock_;
 
   IsolatedWebAppUrlInfo isolation_info_;
   IsolationData isolation_data_;
@@ -146,8 +146,6 @@
 
   base::raw_ref<content::BrowserContext> browser_context_;
 
-  const raw_ref<WebAppInstallFinalizer> install_finalizer_;
-
   std::unique_ptr<WebAppDataRetriever> data_retriever_;
 
   base::OnceCallback<void(base::expected<InstallIsolatedWebAppCommandSuccess,
diff --git a/chrome/browser/web_applications/commands/install_isolated_web_app_command_unittest.cc b/chrome/browser/web_applications/commands/install_isolated_web_app_command_unittest.cc
index da4e5ba..93f63d5 100644
--- a/chrome/browser/web_applications/commands/install_isolated_web_app_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/install_isolated_web_app_command_unittest.cc
@@ -30,7 +30,6 @@
 #include "chrome/browser/web_applications/isolated_web_apps/pending_install_info.h"
 #include "chrome/browser/web_applications/isolation_data.h"
 #include "chrome/browser/web_applications/locks/lock.h"
-#include "chrome/browser/web_applications/test/fake_install_finalizer.h"
 #include "chrome/browser/web_applications/test/fake_web_app_provider.h"
 #include "chrome/browser/web_applications/test/mock_data_retriever.h"
 #include "chrome/browser/web_applications/test/test_web_app_url_loader.h"
@@ -38,7 +37,6 @@
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_data_retriever.h"
-#include "chrome/browser/web_applications/web_app_helpers.h"
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
@@ -47,7 +45,6 @@
 #include "chrome/browser/web_applications/web_app_url_loader.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
-#include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_task_environment.h"
@@ -233,13 +230,9 @@
       url_loader = std::move(test_url_loader);
     }
 
-    auto command =
-        CreateCommand(parameters.url_info, std::move(web_contents),
-                      parameters.isolation_data, std::move(url_loader),
-                      parameters.install_finalizer != nullptr
-                          ? *parameters.install_finalizer
-                          : web_app_provider().install_finalizer(),
-                      test_future.GetCallback());
+    auto command = CreateCommand(
+        parameters.url_info, std::move(web_contents), parameters.isolation_data,
+        std::move(url_loader), test_future.GetCallback());
 
     command->SetDataRetrieverForTesting(
         data_retriever != nullptr ? std::move(data_retriever)
@@ -254,7 +247,6 @@
       std::unique_ptr<content::WebContents> web_contents,
       absl::optional<IsolationData> isolation_data,
       std::unique_ptr<WebAppUrlLoader> url_loader,
-      WebAppInstallFinalizer& install_finalizer,
       base::OnceCallback<
           void(base::expected<InstallIsolatedWebAppCommandSuccess,
                               InstallIsolatedWebAppCommandError>)> callback) {
@@ -264,8 +256,7 @@
 
     return std::make_unique<InstallIsolatedWebAppCommand>(
         url_info, isolation_data.value(), std::move(web_contents),
-        std::move(url_loader), *profile(), install_finalizer,
-        std::move(callback));
+        std::move(url_loader), *profile(), std::move(callback));
   }
 
   base::expected<InstallIsolatedWebAppCommandSuccess,
@@ -452,38 +443,6 @@
 }
 
 TEST_F(InstallIsolatedWebAppCommandTest,
-       InstallationFailsWhenFinalizerReturnNotInstallableError) {
-  IsolatedWebAppUrlInfo url_info = CreateRandomIsolatedWebAppUrlInfo();
-
-  auto install_finalizer = std::make_unique<FakeInstallFinalizer>();
-  install_finalizer->SetNextFinalizeInstallResult(
-      url_info.app_id(), webapps::InstallResultCode::kNotInstallable);
-
-  EXPECT_THAT(ExecuteCommand(Parameters{
-                  .url_info = url_info,
-                  .install_finalizer = install_finalizer.get(),
-              }),
-              IsInstallationError(
-                  HasSubstr("Error during finalization: kNotInstallable")));
-}
-
-TEST_F(InstallIsolatedWebAppCommandTest,
-       InstallationFailsWhenFinalizerReturnInstallURLLoadTimeOut) {
-  IsolatedWebAppUrlInfo url_info = CreateRandomIsolatedWebAppUrlInfo();
-
-  auto install_finalizer = std::make_unique<FakeInstallFinalizer>();
-  install_finalizer->SetNextFinalizeInstallResult(
-      url_info.app_id(), webapps::InstallResultCode::kInstallURLLoadTimeOut);
-
-  EXPECT_THAT(ExecuteCommand(Parameters{
-                  .url_info = url_info,
-                  .install_finalizer = install_finalizer.get(),
-              }),
-              IsInstallationError(HasSubstr(
-                  "Error during finalization: kInstallURLLoadTimeOut")));
-}
-
-TEST_F(InstallIsolatedWebAppCommandTest,
        InstallationSucceedesWhenFinalizerReturnSuccessNewInstall) {
   IsolatedWebAppUrlInfo url_info = CreateRandomIsolatedWebAppUrlInfo();
 
@@ -550,7 +509,7 @@
       content::WebContents::Create(
           content::WebContents::CreateParams(profile())),
       CreateIsolationDataDevProxy(), std::make_unique<TestWebAppUrlLoader>(),
-      web_app_provider().install_finalizer(), test_future.GetCallback());
+      test_future.GetCallback());
   EXPECT_THAT(
       command->lock_description(),
       AllOf(Property(&LockDescription::type, Eq(LockDescription::Type::kApp)),
diff --git a/chrome/browser/web_applications/commands/manifest_update_data_fetch_command.cc b/chrome/browser/web_applications/commands/manifest_update_data_fetch_command.cc
index 1d132638..f3f56015 100644
--- a/chrome/browser/web_applications/commands/manifest_update_data_fetch_command.cc
+++ b/chrome/browser/web_applications/commands/manifest_update_data_fetch_command.cc
@@ -184,10 +184,6 @@
     const AppId& app_id,
     base::WeakPtr<content::WebContents> web_contents,
     ManifestFetchCallback fetch_callback,
-    WebAppRegistrar* registrar,
-    WebAppIconManager* icon_manager,
-    WebAppUiManager* ui_manager,
-    OsIntegrationManager* os_integration_manager,
     std::unique_ptr<WebAppDataRetriever> data_retriever)
     : lock_description_(
           std::make_unique<AppLockDescription, base::flat_set<AppId>>(
@@ -196,10 +192,6 @@
       app_id_(app_id),
       web_contents_(web_contents),
       fetch_callback_(std::move(fetch_callback)),
-      registrar_(registrar),
-      icon_manager_(icon_manager),
-      ui_manager_(ui_manager),
-      os_integration_manager_(os_integration_manager),
       data_retriever_(std::move(data_retriever)) {}
 
 ManifestUpdateDataFetchCommand::~ManifestUpdateDataFetchCommand() = default;
@@ -221,7 +213,10 @@
   return base::Value(std::move(data));
 }
 
-void ManifestUpdateDataFetchCommand::Start() {
+void ManifestUpdateDataFetchCommand::StartWithLock(
+    std::unique_ptr<AppLock> lock) {
+  lock_ = std::move(lock);
+
   if (IsWebContentsDestroyed()) {
     CompleteCommand(ManifestUpdateResult::kWebContentsDestroyed);
     return;
@@ -323,7 +318,7 @@
       "WebApp.Icon.HttpStatusCodeClassOnUpdate", result, icons_http_results);
 
   stage_ = ManifestUpdateStage::kPendingIconReadFromDisk;
-  icon_manager_->ReadAllIcons(
+  lock_->icon_manager().ReadAllIcons(
       app_id_, base::BindOnce(&ManifestUpdateDataFetchCommand::OnAllIconsRead,
                               AsWeakPtr(), std::move(icons_map)));
 }
@@ -354,7 +349,7 @@
 
   IconDiff icon_diff = IsUpdateNeededForIconContents(disk_icon_bitmaps);
   std::u16string old_title =
-      base::UTF8ToUTF16(registrar_->GetAppShortName(app_id_));
+      base::UTF8ToUTF16(lock_->registrar().GetAppShortName(app_id_));
   std::u16string new_title = install_info_->title;
 
   bool title_change = old_title != new_title;
@@ -376,7 +371,7 @@
   // - All icon changes when the kWebAppManifestIconUpdating override is set.
   // - ... and apps that simply aren't requesting any app identity changes.
   if (!NeedsAppIdentityUpdateDialog(title_change, icon_change, app_id_,
-                                    *registrar_)) {
+                                    lock_->registrar())) {
     UMA_HISTOGRAM_ENUMERATION("Webapp.AppIdentityDialog.AlreadyApproved",
                               app_id_changes);
     OnPostAppIdentityUpdateCheck(AppIdentityUpdate::kSkipped);
@@ -406,7 +401,7 @@
   // special exemption), they should bail out now (with the icon set reset) so
   // as to avoid showing the app identity dialog and allow other non-app
   // identity changes to occur.
-  const WebApp* web_app = registrar_->GetAppById(app_id_);
+  const WebApp* web_app = lock_->registrar().GetAppById(app_id_);
   if (web_app->IsPreinstalledApp() || web_app->IsPolicyInstalledApp()) {
     UMA_HISTOGRAM_ENUMERATION("Webapp.AppIdentityDialog.NotShowing",
                               app_id_changes);
@@ -463,7 +458,7 @@
   }
 
   UMA_HISTOGRAM_ENUMERATION("Webapp.AppIdentityDialog.Showing", app_id_changes);
-  ui_manager_->ShowWebAppIdentityUpdateDialog(
+  lock_->ui_manager().ShowWebAppIdentityUpdateDialog(
       app_id_, title_change, icon_change, old_title, new_title, *before_icon,
       *after_icon, web_contents_.get(),
       base::BindOnce(
@@ -487,12 +482,13 @@
   }
 
   DCHECK(install_info_.has_value());
-  if (IsUpdateNeededForManifest(app_id_, install_info_.value(), *registrar_)) {
+  if (IsUpdateNeededForManifest(app_id_, install_info_.value(),
+                                lock_->registrar())) {
     CompleteCommand(absl::nullopt);
     return;
   }
 
-  icon_manager_->ReadAllShortcutsMenuIcons(
+  lock_->icon_manager().ReadAllShortcutsMenuIcons(
       app_id_, base::BindOnce(
                    &ManifestUpdateDataFetchCommand::OnAllShortcutsMenuIconsRead,
                    AsWeakPtr()));
@@ -501,7 +497,7 @@
 IconDiff ManifestUpdateDataFetchCommand::IsUpdateNeededForIconContents(
     const IconBitmaps& disk_icon_bitmaps) const {
   DCHECK(install_info_.has_value());
-  const WebApp* app = registrar_->GetAppById(app_id_);
+  const WebApp* app = lock_->registrar().GetAppById(app_id_);
   DCHECK(app);
 
   return HaveIconBitmapsChanged(disk_icon_bitmaps, install_info_->icon_bitmaps,
@@ -541,7 +537,7 @@
     return true;
   }
 
-  const WebApp* app = registrar_->GetAppById(app_id_);
+  const WebApp* app = lock_->registrar().GetAppById(app_id_);
   DCHECK(app);
   for (size_t i = 0; i < downloaded_shortcuts_menu_icon_bitmaps.size(); ++i) {
     const IconBitmaps& downloaded_icon_bitmaps =
@@ -580,7 +576,7 @@
     return;
   }
 
-  os_integration_manager_->UpdateUrlHandlers(
+  lock_->os_integration_manager().UpdateUrlHandlers(
       app_id_,
       base::BindOnce(
           &ManifestUpdateDataFetchCommand::OnWebAppOriginAssociationsUpdated,
diff --git a/chrome/browser/web_applications/commands/manifest_update_data_fetch_command.h b/chrome/browser/web_applications/commands/manifest_update_data_fetch_command.h
index 7ee5214..71d3ccc 100644
--- a/chrome/browser/web_applications/commands/manifest_update_data_fetch_command.h
+++ b/chrome/browser/web_applications/commands/manifest_update_data_fetch_command.h
@@ -32,12 +32,9 @@
 
 namespace web_app {
 
+class AppLock;
 class AppLockDescription;
 class LockDescription;
-class OsIntegrationManager;
-class WebAppIconManager;
-class WebAppRegistrar;
-class WebAppUiManager;
 class WebAppDataRetriever;
 
 enum class AppIdentityUpdate;
@@ -133,7 +130,7 @@
 //    locally. Abort if no differences.
 //  - Check if the app ID has changed, abort if so.
 //  - Require user confirmation for changes to the app name.
-class ManifestUpdateDataFetchCommand : public WebAppCommand {
+class ManifestUpdateDataFetchCommand : public WebAppCommandTemplate<AppLock> {
  public:
   using ManifestFetchCallback =
       base::OnceCallback<void(absl::optional<ManifestUpdateResult> result,
@@ -145,10 +142,6 @@
       const AppId& app_id,
       base::WeakPtr<content::WebContents> web_contents,
       ManifestFetchCallback fetch_callback,
-      WebAppRegistrar* registrar,
-      WebAppIconManager* icon_manager,
-      WebAppUiManager* ui_manager,
-      OsIntegrationManager* os_integration_manager,
       std::unique_ptr<WebAppDataRetriever> data_retriever);
 
   ~ManifestUpdateDataFetchCommand() override;
@@ -157,7 +150,7 @@
   void OnSyncSourceRemoved() override {}
   void OnShutdown() override;
   base::Value ToDebugValue() const override;
-  void Start() override;
+  void StartWithLock(std::unique_ptr<AppLock> lock) override;
 
   base::WeakPtr<ManifestUpdateDataFetchCommand> AsWeakPtr() {
     return weak_factory_.GetWeakPtr();
@@ -197,14 +190,12 @@
   void CompleteCommand(absl::optional<ManifestUpdateResult> result);
 
   std::unique_ptr<AppLockDescription> lock_description_;
+  std::unique_ptr<AppLock> lock_;
+
   const GURL url_;
   const AppId app_id_;
   base::WeakPtr<content::WebContents> web_contents_;
   ManifestFetchCallback fetch_callback_;
-  raw_ptr<WebAppRegistrar> registrar_;
-  raw_ptr<WebAppIconManager> icon_manager_;
-  raw_ptr<WebAppUiManager> ui_manager_;
-  raw_ptr<OsIntegrationManager> os_integration_manager_;
   std::unique_ptr<WebAppDataRetriever> data_retriever_;
 
   ManifestUpdateStage stage_ = ManifestUpdateStage::kPendingInstallableData;
diff --git a/chrome/browser/web_applications/commands/manifest_update_data_fetch_command_unittest.cc b/chrome/browser/web_applications/commands/manifest_update_data_fetch_command_unittest.cc
index 26b3e84..f14bdf0 100644
--- a/chrome/browser/web_applications/commands/manifest_update_data_fetch_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/manifest_update_data_fetch_command_unittest.cc
@@ -415,8 +415,6 @@
                       app_identity_allowed;
                   loop.Quit();
                 }),
-            &provider().registrar(), &provider().icon_manager(),
-            &provider().ui_manager(), &provider().os_integration_manager(),
             std::move(data_retriever)));
     loop.Run();
     return output_result;
diff --git a/chrome/browser/web_applications/commands/manifest_update_finalize_command.cc b/chrome/browser/web_applications/commands/manifest_update_finalize_command.cc
index e704e7c..ea2864d 100644
--- a/chrome/browser/web_applications/commands/manifest_update_finalize_command.cc
+++ b/chrome/browser/web_applications/commands/manifest_update_finalize_command.cc
@@ -34,11 +34,7 @@
     bool app_identity_update_allowed,
     ManifestWriteCallback write_callback,
     std::unique_ptr<ScopedKeepAlive> keep_alive,
-    std::unique_ptr<ScopedProfileKeepAlive> profile_keep_alive,
-    WebAppRegistrar* registrar,
-    WebAppInstallFinalizer* install_finalizer,
-    OsIntegrationManager* os_integration_manager,
-    WebAppSyncBridge* sync_bridge)
+    std::unique_ptr<ScopedProfileKeepAlive> profile_keep_alive)
     : lock_description_(
           std::make_unique<AppLockDescription, base::flat_set<AppId>>(
               {app_id})),
@@ -48,11 +44,7 @@
       app_identity_update_allowed_(app_identity_update_allowed),
       write_callback_(std::move(write_callback)),
       keep_alive_(std::move(keep_alive)),
-      profile_keep_alive_(std::move(profile_keep_alive)),
-      registrar_(registrar),
-      install_finalizer_(install_finalizer),
-      os_integration_manager_(os_integration_manager),
-      sync_bridge_(sync_bridge) {}
+      profile_keep_alive_(std::move(profile_keep_alive)) {}
 
 ManifestUpdateFinalizeCommand::~ManifestUpdateFinalizeCommand() = default;
 
@@ -74,21 +66,25 @@
   return base::Value(std::move(data));
 }
 
-void ManifestUpdateFinalizeCommand::Start() {
+void ManifestUpdateFinalizeCommand::StartWithLock(
+    std::unique_ptr<AppLock> lock) {
   DCHECK_EQ(stage_, ManifestUpdateStage::kAppWindowsClosed);
 
-  if (!AllowUnpromptedNameUpdate(app_id_, *registrar_) &&
+  lock_ = std::move(lock);
+
+  if (!AllowUnpromptedNameUpdate(app_id_, lock_->registrar()) &&
       !app_identity_update_allowed_) {
     // The app's name must not change due to an automatic update, except for
     // default installed apps (that have been vetted).
     install_info_.title =
-        base::UTF8ToUTF16(registrar_->GetAppShortName(app_id_));
+        base::UTF8ToUTF16(lock_->registrar().GetAppShortName(app_id_));
   }
 
   // Preserve the user's choice of form factor to open the app with.
-  install_info_.user_display_mode = registrar_->GetAppUserDisplayMode(app_id_);
+  install_info_.user_display_mode =
+      lock_->registrar().GetAppUserDisplayMode(app_id_);
   stage_ = ManifestUpdateStage::kPendingFinalizerUpdate;
-  install_finalizer_->FinalizeUpdate(
+  lock_->install_finalizer().FinalizeUpdate(
       install_info_,
       base::BindOnce(&ManifestUpdateFinalizeCommand::OnInstallationComplete,
                      AsWeakPtr()));
@@ -106,10 +102,11 @@
   }
 
   DCHECK_EQ(app_id_, app_id);
-  DCHECK(!IsUpdateNeededForManifest(app_id_, install_info_, *registrar_));
+  DCHECK(
+      !IsUpdateNeededForManifest(app_id_, install_info_, lock_->registrar()));
   DCHECK_EQ(code, webapps::InstallResultCode::kSuccessAlreadyInstalled);
 
-  sync_bridge_->SetAppManifestUpdateTime(app_id, base::Time::Now());
+  lock_->sync_bridge().SetAppManifestUpdateTime(app_id, base::Time::Now());
   CompleteCommand(code, ManifestUpdateResult::kAppUpdated);
 }
 
diff --git a/chrome/browser/web_applications/commands/manifest_update_finalize_command.h b/chrome/browser/web_applications/commands/manifest_update_finalize_command.h
index 42f33eb..365505e8 100644
--- a/chrome/browser/web_applications/commands/manifest_update_finalize_command.h
+++ b/chrome/browser/web_applications/commands/manifest_update_finalize_command.h
@@ -24,16 +24,13 @@
 
 namespace web_app {
 
+class AppLock;
 class AppLockDescription;
 class LockDescription;
-class OsIntegrationManager;
-class WebAppInstallFinalizer;
-class WebAppRegistrar;
-class WebAppSyncBridge;
 
 // After all app windows have closed, this command runs to perform the last few
 // steps of writing the data to the DB.
-class ManifestUpdateFinalizeCommand : public WebAppCommand {
+class ManifestUpdateFinalizeCommand : public WebAppCommandTemplate<AppLock> {
  public:
   using ManifestWriteCallback = base::OnceCallback<
       void(const GURL& url, const AppId& app_id, ManifestUpdateResult result)>;
@@ -45,11 +42,7 @@
       bool app_identity_update_allowed,
       ManifestWriteCallback write_callback,
       std::unique_ptr<ScopedKeepAlive> keep_alive,
-      std::unique_ptr<ScopedProfileKeepAlive> profile_keep_alive,
-      WebAppRegistrar* registrar,
-      WebAppInstallFinalizer* install_finalizer,
-      OsIntegrationManager* os_integration_manager,
-      WebAppSyncBridge* sync_bridge);
+      std::unique_ptr<ScopedProfileKeepAlive> profile_keep_alive);
 
   ~ManifestUpdateFinalizeCommand() override;
 
@@ -57,7 +50,7 @@
   void OnSyncSourceRemoved() override {}
   void OnShutdown() override;
   base::Value ToDebugValue() const override;
-  void Start() override;
+  void StartWithLock(std::unique_ptr<AppLock> lock) override;
 
   base::WeakPtr<ManifestUpdateFinalizeCommand> AsWeakPtr() {
     return weak_factory_.GetWeakPtr();
@@ -71,6 +64,8 @@
                        ManifestUpdateResult result);
 
   std::unique_ptr<AppLockDescription> lock_description_;
+  std::unique_ptr<AppLock> lock_;
+
   const GURL url_;
   const AppId app_id_;
   WebAppInstallInfo install_info_;
@@ -81,11 +76,6 @@
   std::unique_ptr<ScopedKeepAlive> keep_alive_;
   std::unique_ptr<ScopedProfileKeepAlive> profile_keep_alive_;
 
-  raw_ptr<WebAppRegistrar> registrar_;
-  raw_ptr<WebAppInstallFinalizer> install_finalizer_;
-  raw_ptr<OsIntegrationManager> os_integration_manager_;
-  raw_ptr<WebAppSyncBridge> sync_bridge_;
-
   ManifestUpdateStage stage_ = ManifestUpdateStage::kAppWindowsClosed;
   base::Value::Dict debug_log_;
 
diff --git a/chrome/browser/web_applications/commands/manifest_update_finalize_command_unittest.cc b/chrome/browser/web_applications/commands/manifest_update_finalize_command_unittest.cc
index 3ff78f9..aa1bbf5 100644
--- a/chrome/browser/web_applications/commands/manifest_update_finalize_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/manifest_update_finalize_command_unittest.cc
@@ -53,9 +53,7 @@
     return std::make_unique<ManifestUpdateFinalizeCommand>(
         url, app_id, std::move(install_info), app_identity_update_allowed,
         std::move(callback), std::move(keep_alive),
-        std::move(profile_keep_alive), &provider().registrar(),
-        &provider().install_finalizer(), &provider().os_integration_manager(),
-        &provider().sync_bridge());
+        std::move(profile_keep_alive));
   }
 
   ManifestUpdateResult RunCommandAndGetResult(
diff --git a/chrome/browser/web_applications/commands/run_on_os_login_command.cc b/chrome/browser/web_applications/commands/run_on_os_login_command.cc
index 192465ab..3b990ba 100644
--- a/chrome/browser/web_applications/commands/run_on_os_login_command.cc
+++ b/chrome/browser/web_applications/commands/run_on_os_login_command.cc
@@ -23,42 +23,26 @@
 
 // static
 std::unique_ptr<RunOnOsLoginCommand> RunOnOsLoginCommand::CreateForSetLoginMode(
-    WebAppRegistrar* registrar,
-    OsIntegrationManager* os_integration_manager,
-    WebAppSyncBridge* sync_bridge,
     const AppId& app_id,
     RunOnOsLoginMode login_mode,
     base::OnceClosure callback) {
-  DCHECK(registrar);
-  DCHECK(os_integration_manager);
-  DCHECK(sync_bridge);
-
   return base::WrapUnique(new RunOnOsLoginCommand(
-      app_id, registrar, os_integration_manager, sync_bridge, login_mode,
-      RunOnOsLoginAction::kSetModeInDBAndOS, std::move(callback)));
+      app_id, login_mode, RunOnOsLoginAction::kSetModeInDBAndOS,
+      std::move(callback)));
 }
 
 // static
 std::unique_ptr<RunOnOsLoginCommand>
-RunOnOsLoginCommand::CreateForSyncLoginMode(
-    WebAppRegistrar* registrar,
-    OsIntegrationManager* os_integration_manager,
-    const AppId& app_id,
-    base::OnceClosure callback) {
-  DCHECK(registrar);
-  DCHECK(os_integration_manager);
-
+RunOnOsLoginCommand::CreateForSyncLoginMode(const AppId& app_id,
+                                            base::OnceClosure callback) {
   return base::WrapUnique(new RunOnOsLoginCommand(
-      app_id, registrar, os_integration_manager, /*sync_bridge=*/nullptr,
+      app_id,
       /*login_mode=*/absl::nullopt, RunOnOsLoginAction::kSyncModeFromDBToOS,
       std::move(callback)));
 }
 
 RunOnOsLoginCommand::RunOnOsLoginCommand(
     AppId app_id,
-    WebAppRegistrar* registrar,
-    OsIntegrationManager* os_integration_manager,
-    WebAppSyncBridge* sync_bridge,
     absl::optional<RunOnOsLoginMode> login_mode,
     RunOnOsLoginAction set_or_sync_mode,
     base::OnceClosure callback)
@@ -66,9 +50,6 @@
           std::make_unique<AppLockDescription, base::flat_set<AppId>>(
               {app_id})),
       app_id_(app_id),
-      registrar_(registrar),
-      os_integration_manager_(os_integration_manager),
-      sync_bridge_(sync_bridge),
       login_mode_(login_mode),
       set_or_sync_mode_(set_or_sync_mode),
       callback_(std::move(callback)) {}
@@ -79,7 +60,9 @@
   return *lock_description_;
 }
 
-void RunOnOsLoginCommand::Start() {
+void RunOnOsLoginCommand::StartWithLock(std::unique_ptr<AppLock> lock) {
+  lock_ = std::move(lock);
+
   switch (set_or_sync_mode_) {
     case RunOnOsLoginAction::kSetModeInDBAndOS:
       SetRunOnOsLoginMode();
@@ -144,12 +127,12 @@
 }
 
 void RunOnOsLoginCommand::SetRunOnOsLoginMode() {
-  if (!registrar_->IsLocallyInstalled(app_id_)) {
+  if (!lock_->registrar().IsLocallyInstalled(app_id_)) {
     Abort(RunOnOsLoginCommandCompletionState::kAppNotLocallyInstalled);
     return;
   }
 
-  const auto current_mode = registrar_->GetAppRunOnOsLoginMode(app_id_);
+  const auto current_mode = lock_->registrar().GetAppRunOnOsLoginMode(app_id_);
 
   // Early return if policy does not allow the user to change value, or if the
   // new value is the same as the old value.
@@ -167,25 +150,26 @@
   }
 
   {
-    ScopedRegistryUpdate update(sync_bridge_);
+    ScopedRegistryUpdate update(&lock_->sync_bridge());
     update->UpdateApp(app_id_)->SetRunOnOsLoginMode(login_mode_.value());
   }
-  registrar_->NotifyWebAppRunOnOsLoginModeChanged(app_id_, login_mode_.value());
+  lock_->registrar().NotifyWebAppRunOnOsLoginModeChanged(app_id_,
+                                                         login_mode_.value());
   UpdateRunOnOsLoginModeWithOsIntegration();
 }
 
 void RunOnOsLoginCommand::SyncRunOnOsLoginMode() {
-  if (!registrar_->IsLocallyInstalled(app_id_)) {
+  if (!lock_->registrar().IsLocallyInstalled(app_id_)) {
     Abort(RunOnOsLoginCommandCompletionState::kAppNotLocallyInstalled);
     return;
   }
-  login_mode_ = registrar_->GetAppRunOnOsLoginMode(app_id_).value;
+  login_mode_ = lock_->registrar().GetAppRunOnOsLoginMode(app_id_).value;
   UpdateRunOnOsLoginModeWithOsIntegration();
 }
 
 void RunOnOsLoginCommand::UpdateRunOnOsLoginModeWithOsIntegration() {
   absl::optional<RunOnOsLoginMode> os_integration_state =
-      registrar_->GetExpectedRunOnOsLoginOsIntegrationState(app_id_);
+      lock_->registrar().GetExpectedRunOnOsLoginOsIntegrationState(app_id_);
 
   if (os_integration_state && login_mode_.value() == *os_integration_state) {
     RecordCompletionState(
@@ -198,7 +182,7 @@
   if (login_mode_.value() == RunOnOsLoginMode::kNotRun) {
     web_app::OsHooksOptions os_hooks;
     os_hooks[web_app::OsHookType::kRunOnOsLogin] = true;
-    os_integration_manager_->UninstallOsHooks(
+    lock_->os_integration_manager().UninstallOsHooks(
         app_id_, os_hooks,
         base::BindOnce(&RunOnOsLoginCommand::OnOsHooksSet,
                        weak_factory_.GetWeakPtr()));
@@ -206,7 +190,7 @@
     web_app::InstallOsHooksOptions install_options;
     install_options.os_hooks[web_app::OsHookType::kRunOnOsLogin] = true;
     install_options.reason = SHORTCUT_CREATION_AUTOMATED;
-    os_integration_manager_->InstallOsHooks(
+    lock_->os_integration_manager().InstallOsHooks(
         app_id_,
         base::BindOnce(&RunOnOsLoginCommand::OnOsHooksSet,
                        weak_factory_.GetWeakPtr()),
diff --git a/chrome/browser/web_applications/commands/run_on_os_login_command.h b/chrome/browser/web_applications/commands/run_on_os_login_command.h
index 88c4604..e1d118d 100644
--- a/chrome/browser/web_applications/commands/run_on_os_login_command.h
+++ b/chrome/browser/web_applications/commands/run_on_os_login_command.h
@@ -16,11 +16,9 @@
 
 namespace web_app {
 
+class AppLock;
 class AppLockDescription;
 class LockDescription;
-class WebAppRegistrar;
-class OsIntegrationManager;
-class WebAppSyncBridge;
 
 enum class RunOnOsLoginAction {
   kSetModeInDBAndOS = 0,
@@ -41,34 +39,26 @@
 // This command persists run on os login data to the web_app DB
 // and/or syncs the run on os login data with the OS integration hooks
 // asynchronously.
-class RunOnOsLoginCommand : public WebAppCommand {
+class RunOnOsLoginCommand : public WebAppCommandTemplate<AppLock> {
  public:
   static std::unique_ptr<RunOnOsLoginCommand> CreateForSetLoginMode(
-      WebAppRegistrar* registrar,
-      OsIntegrationManager* os_integration_manager,
-      WebAppSyncBridge* sync_bridge,
       const AppId& app_id,
       RunOnOsLoginMode login_mode,
       base::OnceClosure callback);
   static std::unique_ptr<RunOnOsLoginCommand> CreateForSyncLoginMode(
-      WebAppRegistrar* registrar,
-      OsIntegrationManager* os_integration_manager,
       const AppId& app_id,
       base::OnceClosure callback);
   ~RunOnOsLoginCommand() override;
 
   LockDescription& lock_description() const override;
 
-  void Start() override;
+  void StartWithLock(std::unique_ptr<AppLock> lock) override;
   void OnSyncSourceRemoved() override {}
   void OnShutdown() override;
   base::Value ToDebugValue() const override;
 
  private:
   RunOnOsLoginCommand(AppId app_id,
-                      WebAppRegistrar* registrar,
-                      OsIntegrationManager* os_integration_manager,
-                      WebAppSyncBridge* sync_bridge,
                       absl::optional<RunOnOsLoginMode> login_mode,
                       RunOnOsLoginAction set_or_sync_mode,
                       base::OnceClosure callback_);
@@ -88,10 +78,9 @@
       RunOnOsLoginCommandCompletionState completion_state);
 
   std::unique_ptr<AppLockDescription> lock_description_;
+  std::unique_ptr<AppLock> lock_;
+
   AppId app_id_;
-  base::raw_ptr<WebAppRegistrar> registrar_;
-  base::raw_ptr<OsIntegrationManager> os_integration_manager_;
-  base::raw_ptr<WebAppSyncBridge> sync_bridge_;
   absl::optional<RunOnOsLoginMode> login_mode_;
   RunOnOsLoginAction set_or_sync_mode_;
   std::string stop_reason_;
diff --git a/chrome/browser/web_applications/commands/run_on_os_login_command_unittest.cc b/chrome/browser/web_applications/commands/run_on_os_login_command_unittest.cc
index 28a6552b..ff0331d 100644
--- a/chrome/browser/web_applications/commands/run_on_os_login_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/run_on_os_login_command_unittest.cc
@@ -133,8 +133,7 @@
   base::RunLoop loop;
   provider()->command_manager().ScheduleCommand(
       RunOnOsLoginCommand::CreateForSetLoginMode(
-          &registrar(), os_integration_manager(), &sync_bridge(), app_id,
-          RunOnOsLoginMode::kWindowed, loop.QuitClosure()));
+          app_id, RunOnOsLoginMode::kWindowed, loop.QuitClosure()));
   loop.Run();
   tester.ExpectBucketCount(
       "WebApp.RunOnOsLogin.CommandCompletionState",
@@ -152,8 +151,7 @@
   base::RunLoop loop1;
   provider()->command_manager().ScheduleCommand(
       RunOnOsLoginCommand::CreateForSetLoginMode(
-          &registrar(), os_integration_manager(), &sync_bridge(), app_id,
-          RunOnOsLoginMode::kMinimized, loop1.QuitClosure()));
+          app_id, RunOnOsLoginMode::kMinimized, loop1.QuitClosure()));
   loop1.Run();
   tester.ExpectBucketCount(
       "WebApp.RunOnOsLogin.CommandCompletionState",
@@ -188,8 +186,7 @@
     base::RunLoop loop;
     provider()->command_manager().ScheduleCommand(
         RunOnOsLoginCommand::CreateForSetLoginMode(
-            &registrar(), os_integration_manager(), &sync_bridge(), app_id,
-            RunOnOsLoginMode::kWindowed, loop.QuitClosure()));
+            app_id, RunOnOsLoginMode::kWindowed, loop.QuitClosure()));
     loop.Run();
   }
 
@@ -290,16 +287,14 @@
   base::RunLoop loop1;
   provider()->command_manager().ScheduleCommand(
       RunOnOsLoginCommand::CreateForSetLoginMode(
-          &registrar(), os_integration_manager(), &sync_bridge(), app_id,
-          RunOnOsLoginMode::kWindowed, loop1.QuitClosure()));
+          app_id, RunOnOsLoginMode::kWindowed, loop1.QuitClosure()));
   loop1.Run();
   EXPECT_EQ(1u, os_integration_manager()->num_register_run_on_os_login_calls());
 
   base::RunLoop loop2;
   provider()->command_manager().ScheduleCommand(
       RunOnOsLoginCommand::CreateForSetLoginMode(
-          &registrar(), os_integration_manager(), &sync_bridge(), app_id,
-          RunOnOsLoginMode::kWindowed, loop2.QuitClosure()));
+          app_id, RunOnOsLoginMode::kWindowed, loop2.QuitClosure()));
   loop2.Run();
   // Count should still be 1 because repeated calls cause command to end early
   // as success.
@@ -314,8 +309,7 @@
   base::RunLoop loop;
   provider()->command_manager().ScheduleCommand(
       RunOnOsLoginCommand::CreateForSetLoginMode(
-          &registrar(), os_integration_manager(), &sync_bridge(), app_id,
-          RunOnOsLoginMode::kNotRun, loop.QuitClosure()));
+          app_id, RunOnOsLoginMode::kNotRun, loop.QuitClosure()));
   loop.Run();
 
   // OS registration should not be attempted if the default state of Run On OS
@@ -337,8 +331,7 @@
 
   base::RunLoop loop;
   provider()->command_manager().ScheduleCommand(
-      RunOnOsLoginCommand::CreateForSyncLoginMode(
-          &registrar(), os_integration_manager(), app_id, loop.QuitClosure()));
+      RunOnOsLoginCommand::CreateForSyncLoginMode(app_id, loop.QuitClosure()));
   loop.Run();
 
   // Syncing on a web_app with a Run on OS Login mode of kNotRun will
@@ -357,8 +350,7 @@
 
   base::RunLoop loop;
   provider()->command_manager().ScheduleCommand(
-      RunOnOsLoginCommand::CreateForSyncLoginMode(
-          &registrar(), os_integration_manager(), "abc", loop.QuitClosure()));
+      RunOnOsLoginCommand::CreateForSyncLoginMode("abc", loop.QuitClosure()));
   loop.Run();
 
   tester.ExpectBucketCount(
@@ -381,8 +373,7 @@
   base::RunLoop loop;
   provider()->command_manager().ScheduleCommand(
       RunOnOsLoginCommand::CreateForSetLoginMode(
-          &registrar(), os_integration_manager(), &sync_bridge(), app_id,
-          RunOnOsLoginMode::kWindowed, loop.QuitClosure()));
+          app_id, RunOnOsLoginMode::kWindowed, loop.QuitClosure()));
   loop.Run();
 
   tester.ExpectBucketCount(
@@ -397,8 +388,7 @@
   base::RunLoop loop1;
   provider()->command_manager().ScheduleCommand(
       RunOnOsLoginCommand::CreateForSetLoginMode(
-          &registrar(), os_integration_manager(), &sync_bridge(), app_id,
-          RunOnOsLoginMode::kWindowed, loop1.QuitClosure()));
+          app_id, RunOnOsLoginMode::kWindowed, loop1.QuitClosure()));
   loop1.Run();
 
   tester.ExpectBucketCount(
@@ -431,8 +421,7 @@
   base::RunLoop loop;
   provider()->command_manager().ScheduleCommand(
       RunOnOsLoginCommand::CreateForSetLoginMode(
-          &registrar(), os_integration_manager(), &sync_bridge(), app_id,
-          RunOnOsLoginMode::kWindowed, loop.QuitClosure()));
+          app_id, RunOnOsLoginMode::kWindowed, loop.QuitClosure()));
   loop.Run();
 
   tester.ExpectBucketCount(
@@ -452,8 +441,7 @@
   base::RunLoop loop1;
   provider()->command_manager().ScheduleCommand(
       RunOnOsLoginCommand::CreateForSetLoginMode(
-          &registrar(), os_integration_manager(), &sync_bridge(), app_id,
-          RunOnOsLoginMode::kNotRun, loop1.QuitClosure()));
+          app_id, RunOnOsLoginMode::kNotRun, loop1.QuitClosure()));
   loop1.Run();
 
   // kNotRun should not invoke any calls.
@@ -464,8 +452,7 @@
   base::RunLoop loop2;
   provider()->command_manager().ScheduleCommand(
       RunOnOsLoginCommand::CreateForSetLoginMode(
-          &registrar(), os_integration_manager(), &sync_bridge(), app_id,
-          RunOnOsLoginMode::kWindowed, loop2.QuitClosure()));
+          app_id, RunOnOsLoginMode::kWindowed, loop2.QuitClosure()));
   loop2.Run();
 
   // kWindowed should invoke 1 register call.
@@ -496,8 +483,7 @@
 
   base::RunLoop loop;
   provider()->command_manager().ScheduleCommand(
-      RunOnOsLoginCommand::CreateForSyncLoginMode(
-          &registrar(), os_integration_manager(), app_id, loop.QuitClosure()));
+      RunOnOsLoginCommand::CreateForSyncLoginMode(app_id, loop.QuitClosure()));
   loop.Run();
 
   EXPECT_EQ(0u, os_integration_manager()->num_register_run_on_os_login_calls());
diff --git a/chrome/browser/web_applications/locks/app_lock.cc b/chrome/browser/web_applications/locks/app_lock.cc
index a1abbe4d..98244b5 100644
--- a/chrome/browser/web_applications/locks/app_lock.cc
+++ b/chrome/browser/web_applications/locks/app_lock.cc
@@ -18,14 +18,16 @@
                  OsIntegrationManager& os_integration_manager,
                  WebAppInstallManager& install_manager,
                  WebAppIconManager& icon_manager,
-                 WebAppTranslationManager& translation_manager)
+                 WebAppTranslationManager& translation_manager,
+                 WebAppUiManager& ui_manager)
     : registrar_(registrar),
       sync_bridge_(sync_bridge),
       install_finalizer_(install_finalizer),
       os_integration_manager_(os_integration_manager),
       install_manager_(install_manager),
       icon_manager_(icon_manager),
-      translation_manager_(translation_manager) {}
+      translation_manager_(translation_manager),
+      ui_manager_(ui_manager) {}
 AppLock::~AppLock() = default;
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/locks/app_lock.h b/chrome/browser/web_applications/locks/app_lock.h
index 0c003b9..13c3ef2c 100644
--- a/chrome/browser/web_applications/locks/app_lock.h
+++ b/chrome/browser/web_applications/locks/app_lock.h
@@ -19,6 +19,7 @@
 class WebAppRegistrar;
 class WebAppSyncBridge;
 class WebAppTranslationManager;
+class WebAppUiManager;
 
 // This locks the given app ids in the WebAppProvider system.
 //
@@ -40,7 +41,8 @@
           OsIntegrationManager& os_integration_manager,
           WebAppInstallManager& install_manager,
           WebAppIconManager& icon_manager,
-          WebAppTranslationManager& translation_manager);
+          WebAppTranslationManager& translation_manager,
+          WebAppUiManager& ui_manager);
   ~AppLock();
 
   WebAppRegistrar& registrar() { return *registrar_; }
@@ -54,6 +56,7 @@
   WebAppTranslationManager& translation_manager() {
     return *translation_manager_;
   }
+  WebAppUiManager& ui_manager() { return *ui_manager_; }
 
  private:
   raw_ref<WebAppRegistrar> registrar_;
@@ -63,6 +66,7 @@
   raw_ref<WebAppInstallManager> install_manager_;
   raw_ref<WebAppIconManager> icon_manager_;
   raw_ref<WebAppTranslationManager> translation_manager_;
+  raw_ref<WebAppUiManager> ui_manager_;
 };
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/locks/full_system_lock.cc b/chrome/browser/web_applications/locks/full_system_lock.cc
index 5b7558a19..0c471639 100644
--- a/chrome/browser/web_applications/locks/full_system_lock.cc
+++ b/chrome/browser/web_applications/locks/full_system_lock.cc
@@ -19,13 +19,15 @@
                                OsIntegrationManager& os_integration_manager,
                                WebAppInstallManager& install_manager,
                                WebAppIconManager& icon_manager,
-                               WebAppTranslationManager& translation_manager)
+                               WebAppTranslationManager& translation_manager,
+                               WebAppUiManager& ui_manager)
     : AppLock(registrar,
               sync_bridge,
               install_finalizer,
               os_integration_manager,
               install_manager,
               icon_manager,
-              translation_manager) {}
+              translation_manager,
+              ui_manager) {}
 FullSystemLock::~FullSystemLock() = default;
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/locks/full_system_lock.h b/chrome/browser/web_applications/locks/full_system_lock.h
index caea779..30eca5b 100644
--- a/chrome/browser/web_applications/locks/full_system_lock.h
+++ b/chrome/browser/web_applications/locks/full_system_lock.h
@@ -17,6 +17,7 @@
 class WebAppRegistrar;
 class WebAppSyncBridge;
 class WebAppTranslationManager;
+class WebAppUiManager;
 
 // This locks the whole system. No other locks can be held when this lock is
 // acquired.
@@ -39,7 +40,8 @@
                  OsIntegrationManager& os_integration_manager,
                  WebAppInstallManager& install_manager,
                  WebAppIconManager& icon_manager,
-                 WebAppTranslationManager& translation_manager);
+                 WebAppTranslationManager& translation_manager,
+                 WebAppUiManager& ui_manager);
   ~FullSystemLock();
 };
 
diff --git a/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.cc b/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.cc
index cac1f3b1..bfaed07 100644
--- a/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.cc
+++ b/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.cc
@@ -25,7 +25,8 @@
     OsIntegrationManager& os_integration_manager,
     WebAppInstallManager& install_manager,
     WebAppIconManager& icon_manager,
-    WebAppTranslationManager& translation_manager)
+    WebAppTranslationManager& translation_manager,
+    WebAppUiManager& ui_manager)
     : SharedWebContentsLock(shared_web_contents),
       AppLock(registrar,
               sync_bridge,
@@ -33,7 +34,8 @@
               os_integration_manager,
               install_manager,
               icon_manager,
-              translation_manager) {}
+              translation_manager,
+              ui_manager) {}
 
 SharedWebContentsWithAppLock::~SharedWebContentsWithAppLock() = default;
 
diff --git a/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.h b/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.h
index 5779cc3..5d90f8ab 100644
--- a/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.h
+++ b/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.h
@@ -23,6 +23,7 @@
 class WebAppRegistrar;
 class WebAppSyncBridge;
 class WebAppTranslationManager;
+class WebAppUiManager;
 
 // This locks both the background shared web contents AND the given app ids. The
 // background web contents is used by the WebAppProvider system to do operations
@@ -50,7 +51,8 @@
                                OsIntegrationManager& os_integration_manager,
                                WebAppInstallManager& install_manager,
                                WebAppIconManager& icon_manager,
-                               WebAppTranslationManager& translation_manager);
+                               WebAppTranslationManager& translation_manager,
+                               WebAppUiManager& ui_manager);
   ~SharedWebContentsWithAppLock();
 };
 
diff --git a/chrome/browser/web_applications/locks/web_app_lock_manager.cc b/chrome/browser/web_applications/locks/web_app_lock_manager.cc
index e89ba3a..43b2bc6 100644
--- a/chrome/browser/web_applications/locks/web_app_lock_manager.cc
+++ b/chrome/browser/web_applications/locks/web_app_lock_manager.cc
@@ -161,7 +161,7 @@
       provider_->registrar(), provider_->sync_bridge(),
       provider_->install_finalizer(), provider_->os_integration_manager(),
       provider_->install_manager(), provider_->icon_manager(),
-      provider_->translation_manager());
+      provider_->translation_manager(), provider_->ui_manager());
 
   AcquireLock(lock_description,
               base::BindOnce(std::move(on_lock_acquired), std::move(lock)));
@@ -179,7 +179,7 @@
       provider_->registrar(), provider_->sync_bridge(),
       provider_->install_finalizer(), provider_->os_integration_manager(),
       provider_->install_manager(), provider_->icon_manager(),
-      provider_->translation_manager());
+      provider_->translation_manager(), provider_->ui_manager());
 
   AcquireLock(lock_description,
               base::BindOnce(std::move(on_lock_acquired), std::move(lock)));
@@ -196,7 +196,7 @@
       provider_->registrar(), provider_->sync_bridge(),
       provider_->install_finalizer(), provider_->os_integration_manager(),
       provider_->install_manager(), provider_->icon_manager(),
-      provider_->translation_manager());
+      provider_->translation_manager(), provider_->ui_manager());
 
   AcquireLock(lock_description,
               base::BindOnce(std::move(on_lock_acquired), std::move(lock)));
@@ -236,7 +236,7 @@
       provider_->registrar(), provider_->sync_bridge(),
       provider_->install_finalizer(), provider_->os_integration_manager(),
       provider_->install_manager(), provider_->icon_manager(),
-      provider_->translation_manager());
+      provider_->translation_manager(), provider_->ui_manager());
   // TODO(dmurph): Create option for lock acquisition callbacks to always be
   // posted async. https://crbug.com/1354312
   auto posted_callback = base::BindOnce(
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager.cc b/chrome/browser/web_applications/policy/web_app_policy_manager.cc
index a4bd81f8..5d35916 100644
--- a/chrome/browser/web_applications/policy/web_app_policy_manager.cc
+++ b/chrome/browser/web_applications/policy/web_app_policy_manager.cc
@@ -22,13 +22,12 @@
 #include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/web_applications/commands/run_on_os_login_command.h"
 #include "chrome/browser/web_applications/external_install_options.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/policy/pre_redirection_url_observer.h"
 #include "chrome/browser/web_applications/policy/web_app_policy_constants.h"
 #include "chrome/browser/web_applications/user_display_mode.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_helpers.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
@@ -364,10 +363,8 @@
                      weak_ptr_factory_.GetWeakPtr()));
   WebAppProvider* provider = WebAppProvider::GetForLocalAppsUnchecked(profile_);
   for (const AppId& app_id : app_ids_to_sync) {
-    provider->command_manager().ScheduleCommand(
-        RunOnOsLoginCommand::CreateForSyncLoginMode(
-            app_registrar_, os_integration_manager_, app_id,
-            base::BindOnce(callback_for_sync_commands, app_id)));
+    provider->scheduler().SyncRunOnOsLoginMode(
+        app_id, base::BindOnce(callback_for_sync_commands, app_id));
   }
 }
 
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.cc b/chrome/browser/web_applications/web_app_command_scheduler.cc
index 6cbd757..fa9080c 100644
--- a/chrome/browser/web_applications/web_app_command_scheduler.cc
+++ b/chrome/browser/web_applications/web_app_command_scheduler.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/web_applications/commands/fetch_manifest_and_install_command.h"
 #include "chrome/browser/web_applications/commands/manifest_update_data_fetch_command.h"
 #include "chrome/browser/web_applications/commands/manifest_update_finalize_command.h"
+#include "chrome/browser/web_applications/commands/run_on_os_login_command.h"
 #include "chrome/browser/web_applications/commands/update_file_handler_command.h"
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h"
 #include "chrome/browser/web_applications/isolation_data.h"
@@ -131,9 +132,7 @@
 
   provider_->command_manager().ScheduleCommand(
       std::make_unique<ManifestUpdateDataFetchCommand>(
-          url, app_id, contents, std::move(callback), &provider_->registrar(),
-          &provider_->icon_manager(), &provider_->ui_manager(),
-          &provider_->os_integration_manager(),
+          url, app_id, contents, std::move(callback),
           std::make_unique<WebAppDataRetriever>()));
 }
 
@@ -163,9 +162,7 @@
       std::make_unique<ManifestUpdateFinalizeCommand>(
           url, app_id, std::move(install_info), app_identity_update_allowed,
           std::move(callback), std::move(keep_alive),
-          std::move(profile_keep_alive), &provider_->registrar(),
-          &provider_->install_finalizer(), &provider_->os_integration_manager(),
-          &provider_->sync_bridge()));
+          std::move(profile_keep_alive)));
 }
 
 void WebAppCommandScheduler::FetchInstallabilityForChromeManagement(
@@ -211,8 +208,43 @@
   provider_->command_manager().ScheduleCommand(
       std::make_unique<InstallIsolatedWebAppCommand>(
           url_info, isolation_data, CreateIsolatedWebAppWebContents(*profile_),
-          std::make_unique<WebAppUrlLoader>(), *profile_,
-          provider_->install_finalizer(), std::move(callback)));
+          std::make_unique<WebAppUrlLoader>(), *profile_, std::move(callback)));
+}
+
+void WebAppCommandScheduler::SetRunOnOsLoginMode(const AppId& app_id,
+                                                 RunOnOsLoginMode login_mode,
+                                                 base::OnceClosure callback) {
+  if (is_in_shutdown_)
+    return;
+
+  if (!provider_->is_registry_ready()) {
+    provider_->on_registry_ready().Post(
+        FROM_HERE, base::BindOnce(&WebAppCommandScheduler::SetRunOnOsLoginMode,
+                                  weak_ptr_factory_.GetWeakPtr(), app_id,
+                                  std::move(login_mode), std::move(callback)));
+    return;
+  }
+
+  provider_->command_manager().ScheduleCommand(
+      RunOnOsLoginCommand::CreateForSetLoginMode(app_id, std::move(login_mode),
+                                                 std::move(callback)));
+}
+
+void WebAppCommandScheduler::SyncRunOnOsLoginMode(const AppId& app_id,
+                                                  base::OnceClosure callback) {
+  if (is_in_shutdown_)
+    return;
+
+  if (!provider_->is_registry_ready()) {
+    provider_->on_registry_ready().Post(
+        FROM_HERE, base::BindOnce(&WebAppCommandScheduler::SyncRunOnOsLoginMode,
+                                  weak_ptr_factory_.GetWeakPtr(), app_id,
+                                  std::move(callback)));
+    return;
+  }
+
+  provider_->command_manager().ScheduleCommand(
+      RunOnOsLoginCommand::CreateForSyncLoginMode(app_id, std::move(callback)));
 }
 
 void WebAppCommandScheduler::Shutdown() {
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.h b/chrome/browser/web_applications/web_app_command_scheduler.h
index 3ba0d89..6474e91d 100644
--- a/chrome/browser/web_applications/web_app_command_scheduler.h
+++ b/chrome/browser/web_applications/web_app_command_scheduler.h
@@ -97,6 +97,16 @@
                              const IsolationData& isolation_data,
                              InstallIsolatedWebAppCallback callback);
 
+  // Schedules a command that updates run on os login to provided `login_mode`
+  // for a web app.
+  void SetRunOnOsLoginMode(const AppId& app_id,
+                           RunOnOsLoginMode login_mode,
+                           base::OnceClosure callback);
+
+  // Schedules a command that syncs the run on os login mode from web app DB to
+  // OS.
+  void SyncRunOnOsLoginMode(const AppId& app_id, base::OnceClosure callback);
+
   // TODO(https://crbug.com/1298130): expose all commands for web app
   // operations.
 
diff --git a/chrome/browser/web_applications/web_app_install_manager.cc b/chrome/browser/web_applications/web_app_install_manager.cc
index 2f37dcfe..449d1ff 100644
--- a/chrome/browser/web_applications/web_app_install_manager.cc
+++ b/chrome/browser/web_applications/web_app_install_manager.cc
@@ -165,8 +165,8 @@
           web_app->sync_fallback_data().icon_infos);
       command_manager_->ScheduleCommand(
           std::make_unique<InstallFromSyncCommand>(
-              url_loader_.get(), profile_, finalizer_.get(), registrar_.get(),
-              data_retriever_factory_.Run(), params, callback));
+              url_loader_.get(), profile_, data_retriever_factory_.Run(),
+              params, callback));
     }
   }
 }
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 947ac8d..c648c55 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1668513567-1c16039fa079b360fb6caf1a4126f5bbeff41fda.profdata
+chrome-linux-main-1668535201-75fc85a3c125992778d1e47c2a35a51122294f08.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index e31c824..6b0617d 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1668513567-e8b632c66128ba4eb8b632266c9ef90bfe07a5cd.profdata
+chrome-mac-arm-main-1668535201-6eeea5262f1db72d753fdff0925f67623ab7a0f4.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 9b0765f..984801dd 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1668513567-51c4263e2db9fdeb3c5c1e23efc638cdd1fcead0.profdata
+chrome-win32-main-1668524267-8b306ad9a5d9f070ac469c16f8df79896d38e3e8.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 5a10111..204b596 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1668524267-a9168568dbbecca1a6da96404935a7d5d70a0129.profdata
+chrome-win64-main-1668535201-29eac2f149149a9645e9194655e00d0639794e61.profdata
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index eb0597b..741fd60a8 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2378,6 +2378,7 @@
       "data/webui/ntp4_browsertest.h",
       "gpu/webgl_infobar_browsertest.cc",
       "interaction/interaction_test_util_browser_browsertest.cc",
+      "interaction/interactive_browser_test_browsertest.cc",
       "interaction/webcontents_interaction_test_util_browsertest.cc",
       "v8/wasm_trap_handler_browsertest.cc",
     ]
diff --git a/chrome/test/data/BUILD.gn b/chrome/test/data/BUILD.gn
index 3335544..ad32a3b 100644
--- a/chrome/test/data/BUILD.gn
+++ b/chrome/test/data/BUILD.gn
@@ -59,7 +59,7 @@
     "extensions/api_test/file_system_provider/service_worker:closure_compile",
   ]
 
-  if (!is_android) {
+  if (is_chromeos_ash) {
     deps += [ "webui:closure_compile" ]
   }
 }
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index e2cc5fe0..acb388e 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -13,7 +13,6 @@
 import("//extensions/buildflags/buildflags.gni")
 import("//pdf/features.gni")
 import("//printing/buildflags/buildflags.gni")
-import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/grit/grit_rule.gni")
 import("//tools/grit/preprocess_if_expr.gni")
 import("//tools/typescript/ts_definitions.gni")
@@ -298,10 +297,9 @@
   }
 }
 
-group("closure_compile") {
-  deps = [ ":closure_compile_local" ]
-  if (is_chromeos_ash) {
-    deps += [
+if (is_chromeos_ash) {
+  group("closure_compile") {
+    deps = [
       "chromeos:closure_compile",
       "cr_components/chromeos:closure_compile",
       "nearby_share:closure_compile",
@@ -311,22 +309,6 @@
   }
 }
 
-js_type_check("closure_compile_local") {
-  is_polymer3 = true
-  deps = [
-    ":chai_assert",
-    ":test_browser_proxy",
-  ]
-}
-
-js_library("chai_assert") {
-  externs_list = [ "//third_party/chaijs/externs/chai-3.5.js" ]
-}
-
-js_library("test_browser_proxy") {
-  deps = [ "//ui/webui/resources/js:promise_resolver" ]
-}
-
 grit("resources") {
   testonly = true
   defines = chrome_grit_defines
@@ -371,19 +353,17 @@
 }
 
 # TypeScript related targets
+if (is_chromeos_ash) {
+  checked_in_dts_files = [ "chromeos/chai_assert.d.ts" ]
 
-checked_in_dts_files = [
-  "chai_assert.d.ts",
-  "test_browser_proxy.d.ts",
-]
-
-# Copies checked-in .d.ts files to the preprocess folder so that they are
-# discovered by TSC the same way generated .d.ts files are.
-preprocess_if_expr("copy_checked_in_dts_files") {
-  in_folder = "./"
-  in_files = checked_in_dts_files
-  out_folder = "$target_gen_dir/tsc"
-  visibility = [ ":build_ts" ]
+  # Copies checked-in .d.ts files to the preprocess folder so that they are
+  # discovered by TSC the same way generated .d.ts files are.
+  preprocess_if_expr("copy_checked_in_dts_files") {
+    in_folder = "./"
+    in_files = checked_in_dts_files
+    out_folder = "$target_gen_dir/tsc"
+    visibility = [ ":build_ts" ]
+  }
 }
 
 generate_definitions_js_files = [ "mojo_webui_test_support.js" ]
@@ -408,10 +388,8 @@
   out_dir = "$target_gen_dir/tsc"
   composite = true
   tsconfig_base = "tsconfig_base.json"
-  path_mappings = [ "chrome://webui-test/*|" +
-                    rebase_path("$root_gen_dir/chrome/test/data/webui/tsc/*",
-                                target_gen_dir) ]
   in_files = [
+    "chai_assert.ts",
     "chrome_timeticks_test.ts",
     "color_provider_css_colors_test.ts",
     "color_provider_css_colors_test_chromeos.ts",
@@ -423,6 +401,7 @@
     "mock_timer_test.ts",
     "polymer_test_util.ts",
     "text_defaults_test.ts",
+    "test_browser_proxy.ts",
     "test_plural_string_proxy.ts",
     "test_store_ts.ts",
     "test_util.ts",
@@ -433,12 +412,12 @@
   }
 
   deps = [ "//ui/webui/resources:library" ]
-  extra_deps = [
-    ":copy_checked_in_dts_files",
-    ":generate_definitions",
-  ]
+  extra_deps = [ ":generate_definitions" ]
   if (is_chromeos_ash) {
-    extra_deps += [ "//ash/webui/common/resources:generate_definitions" ]
+    extra_deps += [
+      ":copy_checked_in_dts_files",
+      "//ash/webui/common/resources:generate_definitions",
+    ]
   }
   definitions = [
     "//tools/typescript/definitions/chrome_send.d.ts",
@@ -447,8 +426,10 @@
   ]
 
   # Checked-in .d.ts files.
-  foreach(_file, checked_in_dts_files) {
-    definitions += [ "$target_gen_dir/tsc/$_file" ]
+  if (is_chromeos_ash) {
+    foreach(_file, checked_in_dts_files) {
+      definitions += [ "$target_gen_dir/tsc/$_file" ]
+    }
   }
 
   # Auto-generated .d.ts files.
@@ -466,10 +447,8 @@
 
   input_files_base_dir = rebase_path(".", "//")
   input_files = [
-    "chai_assert.js",
     "mocha_adapter.js",
     "mojo_webui_test_support.js",
-    "test_browser_proxy.js",
     "usb_internals_test.js",
 
     "invalidations/invalidations_test.js",
@@ -477,11 +456,16 @@
 
   if (is_chromeos_ash) {
     input_files += [
+      "chromeos/chai_assert.js",
       "chromeos/mock_controller.js",
+      "chromeos/mock_controller.m.js",
+      "chromeos/test_browser_proxy.js",
       "chromeos/test_store.js",
+      "chromeos/test_util.js",
       "chromeos/arc_account_picker/test_util.js",
       "chromeos/ash_common/i18n_behavior_test.js",
       "chromeos/fake_network_config_mojom.js",
+      "set_time_dialog_test.js",
     ]
   }
 
diff --git a/chrome/test/data/webui/bluetooth_internals/test_utils.js b/chrome/test/data/webui/bluetooth_internals/test_utils.js
index d93d6ff..c1f45bd6 100644
--- a/chrome/test/data/webui/bluetooth_internals/test_utils.js
+++ b/chrome/test/data/webui/bluetooth_internals/test_utils.js
@@ -7,7 +7,7 @@
 import {DeviceCallbackRouter} from 'chrome://bluetooth-internals/device.mojom-webui.js';
 import {assert} from 'chrome://resources/js/assert.js';
 
-import {TestBrowserProxy} from '../test_browser_proxy.js';
+import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
 
 /**
  * A BluetoothInternalsHandler for the chrome://bluetooth-internals
diff --git a/chrome/test/data/webui/chai_assert.ts b/chrome/test/data/webui/chai_assert.ts
new file mode 100644
index 0000000..7fbac26
--- /dev/null
+++ b/chrome/test/data/webui/chai_assert.ts
@@ -0,0 +1,137 @@
+// Copyright 2020 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/** @fileoverview Assertion helper functions wrapping the chaijs API. */
+
+import './chai.js';
+
+/**
+ * value The value to check.
+ * message Additional error message.
+ */
+export function assertTrue(
+    value: boolean, message?: string): asserts value {
+  chai.assert.isTrue(value, message);
+}
+
+/**
+ * value The value to check.
+ * message Additional error message.
+ */
+export function assertFalse(value: boolean, message?: string) {
+  chai.assert.isFalse(value, message);
+}
+
+/**
+ * value1 The first operand.
+ * value2 The second operand.
+ * message Additional error message.
+ */
+export function assertGE(
+    value1: number, value2: number, message?: string) {
+  chai.expect(value1).to.be.at.least(value2, message);
+}
+
+/**
+ * @param value1 The first operand.
+ * @param value2 The second operand.
+ * @param message Additional error message.
+ */
+export function assertGT(value1: number, value2: number,
+                         message?: string) {
+  chai.assert.isAbove(value1, value2, message);
+}
+
+/**
+ * @param expected The expected value.
+ * @param actual The actual value.
+ * @param message Additional error message.
+ */
+export function assertEquals(
+    expected: any, actual: any, message?: string) {
+  chai.assert.strictEqual(actual, expected, message);
+}
+
+export function assertDeepEquals(expected: any, actual: any,
+                                 message?: string) {
+  chai.assert.deepEqual(actual, expected, message);
+}
+
+/**
+ * @param value1 The first operand.
+ * @param value2 The second operand.
+ * @param message Additional error message.
+ */
+export function assertLE(value1: number, value2: number,
+                         message?: string) {
+  chai.expect(value1).to.be.at.most(value2, message);
+}
+
+/**
+ * @param value1 The first operand.
+ * @param value2 The second operand.
+ * @param message Additional error message.
+ */
+export function assertLT(value1: number, value2: number,
+                         message?: string) {
+  chai.assert.isBelow(value1, value2, message);
+}
+
+/**
+ * @param expected The expected value.
+ * @param actual The actual value.
+ * @param message Additional error message.
+ */
+export function assertNotEquals(expected: any, actual: any,
+                                message?: string) {
+  chai.assert.notStrictEqual(actual, expected, message);
+}
+
+/**
+ * @param message Additional error message.
+ */
+export function assertNotReached(message?: string): never {
+  chai.assert.fail(null, null, message);
+}
+
+/**
+ * @param expectedOrConstructor The expected Error constructor, partial or
+ *     complete error message string, or RegExp to test the error message.
+ * @param message Additional error message.
+ */
+export function assertThrows(
+    testFunction: () => void,
+    expectedOrConstructor?: (ErrorConstructor|string|RegExp),
+    message?: string) {
+  // The implementation of assert.throws goes like:
+  //  function (fn, errt, errs, msg) {
+  //    if ('string' === typeof errt || errt instanceof RegExp) {
+  //      errs = errt;
+  //      errt = null;
+  //    }
+  //    ...
+  // That is, if the second argument is string or RegExp, the type of the
+  // exception is not checked: only the error message. This is achieved by
+  // partially "shifting" parameters (the "additional error message" is not
+  // shifted and will be lost). "Shifting" isn't a thing TS compiler understands, so
+  // just cast to string.
+  // TODO(crbug/1000989): Refactor this into something that makes sense when
+  // tests are actually compiled and we can do that safely.
+  if ('string' === typeof expectedOrConstructor) {
+    chai.assert.throws(
+        testFunction, expectedOrConstructor as string);
+  } else {
+    chai.assert.throws(
+        testFunction, expectedOrConstructor as ErrorConstructor, message);
+  }
+}
+
+/**
+ * Verifies that the contents of the expected and observed arrays match.
+ * expected The expected result.
+ * actual The actual result.
+ */
+export function assertArrayEquals(expected: any[], actual: any[]) {
+  assertDeepEquals(expected, actual);
+}
diff --git a/chrome/test/data/webui/chrome_timeticks_test.ts b/chrome/test/data/webui/chrome_timeticks_test.ts
index afb62ff..5d3468a 100644
--- a/chrome/test/data/webui/chrome_timeticks_test.ts
+++ b/chrome/test/data/webui/chrome_timeticks_test.ts
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from './chai_assert.js';
 
 suite('ChromeTimeTicksTest', () => {
   test('NowIsBigInt', () => {
     const now = chrome.timeTicks.nowInMicroseconds();
     assertEquals(typeof now, 'bigint');
   });
-});
\ No newline at end of file
+});
diff --git a/chrome/test/data/webui/chromeos/BUILD.gn b/chrome/test/data/webui/chromeos/BUILD.gn
index 978ecf8..e4febf3 100644
--- a/chrome/test/data/webui/chromeos/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/BUILD.gn
@@ -15,12 +15,18 @@
                     "js_module_root=./gen/chrome/test/data/webui/",
                   ]
   deps = [
+    ":chai_assert",
     ":fake_network_config_mojom",
     ":mock_controller.m",
+    ":test_browser_proxy",
     ":test_util",
   ]
 }
 
+js_library("chai_assert") {
+  externs_list = [ "//third_party/chaijs/externs/chai-3.5.js" ]
+}
+
 js_library("fake_network_config_mojom") {
   deps = [
     "//ash/webui/common/resources/network:onc_mojo",
@@ -32,6 +38,10 @@
 js_library("mock_controller.m") {
 }
 
+js_library("test_browser_proxy") {
+  deps = [ "//ui/webui/resources/js:promise_resolver" ]
+}
+
 js_library("test_util") {
   deps = [ "//ui/webui/resources/js/cr:event_target" ]
 }
diff --git a/chrome/test/data/webui/chromeos/account_manager/BUILD.gn b/chrome/test/data/webui/chromeos/account_manager/BUILD.gn
index 3365047..07aa601 100644
--- a/chrome/test/data/webui/chromeos/account_manager/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/account_manager/BUILD.gn
@@ -10,6 +10,9 @@
                     "browser_resolver_prefix_replacements=\"chrome://account-migration-welcome/=" + rebase_path(
                             "//chrome/browser/resources/chromeos/account_manager/",
                             root_build_dir) + "\"",
+                    "browser_resolver_prefix_replacements=\"chrome://webui-test/chromeos/=" + rebase_path(
+                            "//chrome/test/data/webui/chromeos/",
+                            root_build_dir) + "\"",
                     "js_module_root=" + rebase_path("//chrome/test/data/webui/",
                                                     root_build_dir),
                     "js_module_root=./gen/chrome/test/data/webui/",
@@ -23,7 +26,7 @@
 js_library("account_migration_welcome_test") {
   deps = [
     ":test_account_manager_browser_proxy",
-    "../..:chai_assert",
+    "..:chai_assert",
     "//chrome/browser/resources/chromeos/account_manager:account_migration_welcome_app",
     "//ui/webui/resources/js:assert",
   ]
@@ -32,7 +35,7 @@
 
 js_library("test_account_manager_browser_proxy") {
   deps = [
-    "../..:test_browser_proxy",
+    "..:test_browser_proxy",
     "//chrome/browser/resources/chromeos/account_manager:account_manager_browser_proxy",
   ]
 }
diff --git a/chrome/test/data/webui/chromeos/account_manager/account_migration_welcome_test.js b/chrome/test/data/webui/chromeos/account_manager/account_migration_welcome_test.js
index 678ae364..baeb165 100644
--- a/chrome/test/data/webui/chromeos/account_manager/account_migration_welcome_test.js
+++ b/chrome/test/data/webui/chromeos/account_manager/account_migration_welcome_test.js
@@ -8,7 +8,7 @@
 import {assert} from 'chrome://resources/js/assert.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertEquals} from '../../chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {TestAccountManagerBrowserProxy} from './test_account_manager_browser_proxy.js';
 
 window.account_migration_welcome_test = {};
diff --git a/chrome/test/data/webui/chromeos/account_manager/test_account_manager_browser_proxy.js b/chrome/test/data/webui/chromeos/account_manager/test_account_manager_browser_proxy.js
index 4537b86..a66c97c 100644
--- a/chrome/test/data/webui/chromeos/account_manager/test_account_manager_browser_proxy.js
+++ b/chrome/test/data/webui/chromeos/account_manager/test_account_manager_browser_proxy.js
@@ -4,7 +4,7 @@
 
 import {AccountManagerBrowserProxy} from 'chrome://account-migration-welcome/account_manager_browser_proxy.js';
 
-import {TestBrowserProxy} from '../../test_browser_proxy.js';
+import {TestBrowserProxy} from 'chrome://webui-test/chromeos/test_browser_proxy.js';
 
 /** @implements {AccountManagerBrowserProxy} */
 export class TestAccountManagerBrowserProxy extends TestBrowserProxy {
diff --git a/chrome/test/data/webui/chromeos/arc_account_picker/BUILD.gn b/chrome/test/data/webui/chromeos/arc_account_picker/BUILD.gn
index 5c62f061..546941b9 100644
--- a/chrome/test/data/webui/chromeos/arc_account_picker/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/arc_account_picker/BUILD.gn
@@ -10,6 +10,9 @@
                     "browser_resolver_prefix_replacements=\"chrome://chrome-signin/arc_account_picker/=" + rebase_path(
                             "//chrome/browser/resources/chromeos/arc_account_picker/",
                             root_build_dir) + "\"",
+                    "browser_resolver_prefix_replacements=\"chrome://webui-test/chromeos/=" + rebase_path(
+                            "//chrome/test/data/webui/chromeos/",
+                            root_build_dir) + "\"",
                     "js_module_root=" + rebase_path("//chrome/test/data/webui/",
                                                     root_build_dir),
                     "js_module_root=./gen/chrome/test/data/webui/",
@@ -22,7 +25,7 @@
 
 js_library("arc_account_picker_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//chrome/browser/resources/chromeos/arc_account_picker:arc_account_picker_app",
     "//chrome/browser/resources/chromeos/arc_account_picker:arc_account_picker_browser_proxy",
     "//ui/webui/resources/js:assert",
@@ -33,7 +36,7 @@
 
 js_library("test_util") {
   deps = [
-    "../..:test_browser_proxy",
+    "..:test_browser_proxy",
     "//chrome/browser/resources/chromeos/arc_account_picker:arc_account_picker_browser_proxy",
   ]
 }
diff --git a/chrome/test/data/webui/chromeos/arc_account_picker/arc_account_picker_test.js b/chrome/test/data/webui/chromeos/arc_account_picker/arc_account_picker_test.js
index 730db67c..738dd21c 100644
--- a/chrome/test/data/webui/chromeos/arc_account_picker/arc_account_picker_test.js
+++ b/chrome/test/data/webui/chromeos/arc_account_picker/arc_account_picker_test.js
@@ -7,7 +7,7 @@
 import {assert} from 'chrome://resources/js/assert.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {getFakeAccountsNotAvailableInArcList, TestArcAccountPickerBrowserProxy} from './test_util.js';
 
diff --git a/chrome/test/data/webui/chromeos/arc_account_picker/test_util.js b/chrome/test/data/webui/chromeos/arc_account_picker/test_util.js
index 1587aa4..afb83b1 100644
--- a/chrome/test/data/webui/chromeos/arc_account_picker/test_util.js
+++ b/chrome/test/data/webui/chromeos/arc_account_picker/test_util.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {Account, ArcAccountPickerBrowserProxy, ArcAccountPickerBrowserProxyImpl} from 'chrome://chrome-signin/arc_account_picker/arc_account_picker_browser_proxy.js';
-import {TestBrowserProxy} from '../../test_browser_proxy.js';
+import {TestBrowserProxy} from 'chrome://webui-test/chromeos/test_browser_proxy.js';
 
 /**
  * @param {!TestArcAccountPickerBrowserProxy} testBrowserProxy
diff --git a/chrome/test/data/webui/chromeos/ash_common/BUILD.gn b/chrome/test/data/webui/chromeos/ash_common/BUILD.gn
index 29660f5..65cc7bd 100644
--- a/chrome/test/data/webui/chromeos/ash_common/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/ash_common/BUILD.gn
@@ -44,6 +44,9 @@
                     "browser_resolver_prefix_replacements=\"chrome://resources/ash/common/=" + rebase_path(
                             "//ash/webui/common/resources/",
                             root_build_dir) + "\"",
+                    "browser_resolver_prefix_replacements=\"chrome://webui-test/chromeos/=" + rebase_path(
+                            "//chrome/test/data/webui/chromeos/",
+                            root_build_dir) + "\"",
                     "browser_resolver_prefix_replacements=\"chrome://webui-test/=./gen/chrome/test/data/webui/tsc\"",
                     "js_module_root=" + rebase_path("//chrome/test/data/webui/",
                                                     root_build_dir),
@@ -66,28 +69,28 @@
 
 js_library("fake_observables_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/common/resources:fake_observables",
   ]
 }
 
 js_library("fake_method_resolver_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/common/resources:fake_method_resolver",
   ]
 }
 
 js_library("keyboard_diagram_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/common/resources:keyboard_diagram",
   ]
 }
 
 js_library("navigation_selector_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/common/resources:navigation_selector",
     "//third_party/polymer/v3_0/components-chromium/iron-collapse:iron-collapse",
   ]
@@ -95,7 +98,7 @@
 
 js_library("navigation_view_panel_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/common/resources:navigation_selector",
     "//ash/webui/common/resources:navigation_view_panel",
   ]
@@ -105,8 +108,8 @@
 
 js_library("page_toolbar_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/common/resources:page_toolbar",
   ]
 }
diff --git a/chrome/test/data/webui/chromeos/ash_common/fake_method_resolver_test.js b/chrome/test/data/webui/chromeos/ash_common/fake_method_resolver_test.js
index a98eea29..d0a6b20 100644
--- a/chrome/test/data/webui/chromeos/ash_common/fake_method_resolver_test.js
+++ b/chrome/test/data/webui/chromeos/ash_common/fake_method_resolver_test.js
@@ -4,7 +4,7 @@
 
 import {FakeMethodResolver} from 'chrome://resources/ash/common/fake_method_resolver.js';
 
-import {assertEquals} from '../../chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function fakeMethodResolverTestSuite() {
   let resolver = null;
diff --git a/chrome/test/data/webui/chromeos/ash_common/fake_observables_test.js b/chrome/test/data/webui/chromeos/ash_common/fake_observables_test.js
index 2dc08a20..0ae96a2 100644
--- a/chrome/test/data/webui/chromeos/ash_common/fake_observables_test.js
+++ b/chrome/test/data/webui/chromeos/ash_common/fake_observables_test.js
@@ -5,7 +5,7 @@
 import {FakeObservables} from 'chrome://resources/ash/common/fake_observables.js';
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
 
-import {assertEquals} from '../../chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function fakeObservablesTestSuite() {
   let observables = null;
diff --git a/chrome/test/data/webui/chromeos/ash_common/keyboard_diagram_test.js b/chrome/test/data/webui/chromeos/ash_common/keyboard_diagram_test.js
index 3e541d4..313327b 100644
--- a/chrome/test/data/webui/chromeos/ash_common/keyboard_diagram_test.js
+++ b/chrome/test/data/webui/chromeos/ash_common/keyboard_diagram_test.js
@@ -7,7 +7,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertNotEquals, assertThrows, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertNotEquals, assertThrows, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function keyboardDiagramTestSuite() {
   /** @type {?KeyboardDiagramElement} */
diff --git a/chrome/test/data/webui/chromeos/ash_common/navigation_selector_test.js b/chrome/test/data/webui/chromeos/ash_common/navigation_selector_test.js
index 284b6b5..ef065a9 100644
--- a/chrome/test/data/webui/chromeos/ash_common/navigation_selector_test.js
+++ b/chrome/test/data/webui/chromeos/ash_common/navigation_selector_test.js
@@ -5,7 +5,7 @@
 import {NavigationSelectorElement, SelectorItem} from 'chrome://resources/ash/common/navigation_selector.js';
 import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from 'chrome://webui-test/test_util.js';
 
 export function navigationSelectorTestSuite() {
diff --git a/chrome/test/data/webui/chromeos/ash_common/navigation_view_panel_test.js b/chrome/test/data/webui/chromeos/ash_common/navigation_view_panel_test.js
index b623ccd..407af2b 100644
--- a/chrome/test/data/webui/chromeos/ash_common/navigation_view_panel_test.js
+++ b/chrome/test/data/webui/chromeos/ash_common/navigation_view_panel_test.js
@@ -7,7 +7,7 @@
 import {assert} from 'chrome://resources/js/assert.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertThrows, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertThrows, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {eventToPromise} from 'chrome://webui-test/test_util.js';
 
 export function navigationViewPanelTestSuite() {
diff --git a/chrome/test/data/webui/chromeos/ash_common/page_toolbar_test.js b/chrome/test/data/webui/chromeos/ash_common/page_toolbar_test.js
index c88742b..33164ba 100644
--- a/chrome/test/data/webui/chromeos/ash_common/page_toolbar_test.js
+++ b/chrome/test/data/webui/chromeos/ash_common/page_toolbar_test.js
@@ -5,7 +5,7 @@
 import {PageToolbarElement} from 'chrome://resources/ash/common/page_toolbar.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 export function pageToolbarTestSuite() {
diff --git a/chrome/test/data/webui/chai_assert.d.ts b/chrome/test/data/webui/chromeos/chai_assert.d.ts
similarity index 100%
rename from chrome/test/data/webui/chai_assert.d.ts
rename to chrome/test/data/webui/chromeos/chai_assert.d.ts
diff --git a/chrome/test/data/webui/chai_assert.js b/chrome/test/data/webui/chromeos/chai_assert.js
similarity index 99%
rename from chrome/test/data/webui/chai_assert.js
rename to chrome/test/data/webui/chromeos/chai_assert.js
index 660d01e..5ff40b0 100644
--- a/chrome/test/data/webui/chai_assert.js
+++ b/chrome/test/data/webui/chromeos/chai_assert.js
@@ -4,7 +4,7 @@
 
 /** @fileoverview Assertion helper functions wrapping the chaijs API. */
 
-import './chai.js';
+import '../chai.js';
 
 /**
  * @param {boolean} value The value to check.
diff --git a/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn b/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn
index ac4ae89..b7cdf18 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn
@@ -6,15 +6,17 @@
 
 js_type_check("closure_compile") {
   is_polymer3 = true
-  closure_flags =
-      default_closure_args + mojom_js_args + [
-        "browser_resolver_prefix_replacements=\"chrome://diagnostics/=" +
-            rebase_path("//ash/webui/diagnostics_ui/resources/",
-                        root_build_dir) + "\"",
-        "js_module_root=" +
-            rebase_path("//chrome/test/data/webui/", root_build_dir),
-        "js_module_root=./gen/chrome/test/data/webui/",
-      ]
+  closure_flags = default_closure_args + mojom_js_args + [
+                    "browser_resolver_prefix_replacements=\"chrome://diagnostics/=" + rebase_path(
+                            "//ash/webui/diagnostics_ui/resources/",
+                            root_build_dir) + "\"",
+                    "browser_resolver_prefix_replacements=\"chrome://webui-test/chromeos/=" + rebase_path(
+                            "//chrome/test/data/webui/chromeos/",
+                            root_build_dir) + "\"",
+                    "js_module_root=" + rebase_path("//chrome/test/data/webui/",
+                                                    root_build_dir),
+                    "js_module_root=./gen/chrome/test/data/webui/",
+                  ]
   deps = [
     ":battery_status_card_test",
     ":connectivity_card_test",
@@ -55,8 +57,8 @@
 
 js_library("battery_status_card_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:battery_status_card",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
@@ -70,8 +72,8 @@
 
 js_library("cellular_info_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:cellular_info",
     "//ash/webui/diagnostics_ui/resources:diagnostics_utils",
@@ -80,8 +82,8 @@
 
 js_library("connectivity_card_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:connectivity_card",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
@@ -93,8 +95,8 @@
 
 js_library("cpu_card_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:cpu_card",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
@@ -106,8 +108,8 @@
 
 js_library("data_point_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/resources:data_point",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -116,8 +118,8 @@
 js_library("diagnostics_app_test") {
   deps = [
     ":test_diagnostics_browser_proxy",
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_app",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
@@ -129,8 +131,8 @@
 
 js_library("diagnostics_network_icon_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_network_icon",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
@@ -141,8 +143,8 @@
 
 js_library("diagnostics_sticky_banner_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/resources:diagnostics_sticky_banner",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -150,8 +152,8 @@
 
 js_library("diagnostics_test_utils") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:battery_status_card",
     "//ash/webui/diagnostics_ui/resources:cpu_card",
@@ -172,7 +174,7 @@
 
 js_library("diagnostics_utils_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_utils",
   ]
@@ -180,8 +182,8 @@
 
 js_library("drawing_provider_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:drawing_provider",
   ]
@@ -189,8 +191,8 @@
 
 js_library("drawing_provider_utils_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:drawing_provider_utils",
   ]
@@ -198,8 +200,8 @@
 
 js_library("ethernet_info_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:ethernet_info",
   ]
@@ -207,7 +209,7 @@
 
 js_library("fake_network_health_provider_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_data",
@@ -217,7 +219,7 @@
 
 js_library("fake_system_data_provider_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_data",
@@ -227,7 +229,7 @@
 
 js_library("fake_system_routine_controller_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_system_routine_controller",
@@ -236,7 +238,7 @@
 
 js_library("frequency_channel_utils_test") {
   deps = [
-    "../../:chai_assert",
+    "..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:frequency_channel_utils",
   ]
@@ -244,8 +246,8 @@
 
 js_library("input_card_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:fake_data",
     "//ash/webui/diagnostics_ui/resources:input_card",
@@ -255,8 +257,8 @@
 
 js_library("input_list_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:fake_data",
     "//ash/webui/diagnostics_ui/resources:input_list",
@@ -267,8 +269,8 @@
 js_library("ip_config_info_drawer_test") {
   deps = [
     ":test_diagnostics_browser_proxy",
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:ip_config_info_drawer",
@@ -278,9 +280,9 @@
 
 js_library("keyboard_tester_test") {
   deps = [
+    "..:chai_assert",
     "..:mock_controller.m",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:keyboard_tester",
   ]
@@ -289,8 +291,8 @@
 
 js_library("memory_card_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:diagnostics_utils",
@@ -304,7 +306,7 @@
 
 js_library("mojo_interface_provider_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_network_health_provider",
@@ -315,8 +317,8 @@
 
 js_library("network_card_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:network_card",
   ]
@@ -325,8 +327,8 @@
 
 js_library("network_info_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:network_info",
   ]
@@ -336,8 +338,8 @@
 js_library("network_list_test") {
   deps = [
     ":test_diagnostics_browser_proxy",
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_data",
@@ -350,8 +352,8 @@
 
 js_library("network_troubleshooting_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:network_troubleshooting",
   ]
@@ -360,8 +362,8 @@
 
 js_library("overview_card_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_data",
@@ -373,8 +375,8 @@
 js_library("percent_bar_chart_test") {
   deps = [
     ":diagnostics_test_utils",
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:percent_bar_chart",
   ]
@@ -383,15 +385,15 @@
 js_library("realtime_cpu_chart_test") {
   deps = [
     ":diagnostics_test_utils",
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/resources:realtime_cpu_chart",
   ]
 }
 
 js_library("routine_group_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:diagnostics_utils",
@@ -402,8 +404,8 @@
 
 js_library("routine_list_executor_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_system_routine_controller",
@@ -413,8 +415,8 @@
 
 js_library("routine_result_entry_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_system_routine_controller",
@@ -427,8 +429,8 @@
 js_library("routine_result_list_test") {
   deps = [
     ":diagnostics_test_utils",
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_system_routine_controller",
@@ -442,8 +444,8 @@
 js_library("routine_section_test") {
   deps = [
     ":diagnostics_test_utils",
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:diagnostics_utils",
@@ -463,8 +465,8 @@
 js_library("system_page_test") {
   deps = [
     ":test_diagnostics_browser_proxy",
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_data",
@@ -477,7 +479,7 @@
 
 js_library("test_diagnostics_browser_proxy") {
   deps = [
-    "../..:test_browser_proxy",
+    "..:test_browser_proxy",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:diagnostics_browser_proxy",
   ]
@@ -485,8 +487,8 @@
 
 js_library("text_badge_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:text_badge",
   ]
@@ -494,8 +496,8 @@
 
 js_library("touchscreen_tester_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:touchscreen_tester",
   ]
@@ -503,8 +505,8 @@
 
 js_library("touchpad_tester_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:touchpad_tester",
   ]
@@ -513,8 +515,8 @@
 
 js_library("wifi_info_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/diagnostics_ui/mojom:mojom_webui_js",
     "//ash/webui/diagnostics_ui/resources:wifi_info",
   ]
diff --git a/chrome/test/data/webui/chromeos/diagnostics/battery_status_card_test.js b/chrome/test/data/webui/chromeos/diagnostics/battery_status_card_test.js
index 2292503..7160739c 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/battery_status_card_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/battery_status_card_test.js
@@ -19,7 +19,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isChildVisible, isVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/cellular_info_test.js b/chrome/test/data/webui/chromeos/diagnostics/cellular_info_test.js
index 32de74fd..6af995e7 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/cellular_info_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/cellular_info_test.js
@@ -9,7 +9,7 @@
 import {fakeCellularNetwork} from 'chrome://diagnostics/fake_data.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {assertDataPointHasExpectedHeaderAndValue} from './diagnostics_test_utils.js';
 
diff --git a/chrome/test/data/webui/chromeos/diagnostics/connectivity_card_test.js b/chrome/test/data/webui/chromeos/diagnostics/connectivity_card_test.js
index 963d9cc..ec2fa3d 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/connectivity_card_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/connectivity_card_test.js
@@ -17,7 +17,7 @@
 import {RoutineType, StandardRoutineResult} from 'chrome://diagnostics/system_routine_controller.mojom-webui.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/cpu_card_test.js b/chrome/test/data/webui/chromeos/diagnostics/cpu_card_test.js
index 2d064e9..2c8d93c9 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/cpu_card_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/cpu_card_test.js
@@ -15,7 +15,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isChildVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/data_point_test.js b/chrome/test/data/webui/chromeos/diagnostics/data_point_test.js
index 8a21011..994892b 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/data_point_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/data_point_test.js
@@ -8,7 +8,7 @@
 import {DataPointElement} from 'chrome://diagnostics/data_point.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_input_hiding_test.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_input_hiding_test.js
index 20ad2bb..4eee85f 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_input_hiding_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_input_hiding_test.js
@@ -16,7 +16,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {TestDiagnosticsBrowserProxy} from './test_diagnostics_browser_proxy.js';
 
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_test.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_test.js
index 80acca70..ac91d125 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_test.js
@@ -16,7 +16,7 @@
 import {BatteryChargeStatus, BatteryHealth, BatteryInfo, CpuUsage, MemoryUsage, SystemInfo} from 'chrome://diagnostics/system_data_provider.mojom-webui.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_network_icon_test.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_network_icon_test.js
index 371d390..15f5571 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_network_icon_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_network_icon_test.js
@@ -8,7 +8,7 @@
 import {fakeCellularDisabledNetwork, fakeCellularNetwork, fakeConnectingEthernetNetwork, fakeDisconnectedEthernetNetwork, fakeEthernetNetwork, fakePortalWifiNetwork, fakeWifiNetwork, fakeWifiNetworkDisabled} from 'chrome://diagnostics/fake_data.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 import {assertTextContains} from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_sticky_banner_test.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_sticky_banner_test.js
index ae3f3359..78bf682 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_sticky_banner_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_sticky_banner_test.js
@@ -7,7 +7,7 @@
 import {DiagnosticsStickyBannerElement} from 'chrome://diagnostics/diagnostics_sticky_banner.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertNotEquals, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_test_utils.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_test_utils.js
index 2e61f15b..c1e391e9 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_test_utils.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_test_utils.js
@@ -16,7 +16,7 @@
 import {RoutineSectionElement} from 'chrome://diagnostics/routine_section.js';
 import {WifiInfoElement} from 'chrome://diagnostics/wifi_info.js';
 
-import {assertEquals, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 /**
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_utils_test.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_utils_test.js
index 379ec31..22b1e715 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_utils_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_utils_test.js
@@ -11,7 +11,7 @@
 import {RoutineType} from 'chrome://diagnostics/system_routine_controller.mojom-webui.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
-import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 suite('diagnosticsUtilsTestSuite', function() {
   test('ProperlyConvertsKibToGib', () => {
diff --git a/chrome/test/data/webui/chromeos/diagnostics/drawing_provider_test.js b/chrome/test/data/webui/chromeos/diagnostics/drawing_provider_test.js
index a972951..ade5c9a 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/drawing_provider_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/drawing_provider_test.js
@@ -8,7 +8,7 @@
 import {CanvasDrawingProvider} from 'chrome://diagnostics/drawing_provider.js';
 import {constructRgba, DESTINATION_OVER, LINE_CAP, LINE_WIDTH, lookupCssVariableValue, MARK_COLOR, MARK_OPACITY, MARK_RADIUS, TRAIL_COLOR, TRAIL_MAX_OPACITY} from 'chrome://diagnostics/drawing_provider_utils.js';
 
-import {assertDeepEquals, assertEquals} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {MockController} from '../mock_controller.m.js';
 
 /**
diff --git a/chrome/test/data/webui/chromeos/diagnostics/drawing_provider_utils_test.js b/chrome/test/data/webui/chromeos/diagnostics/drawing_provider_utils_test.js
index 698664b..6639e26 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/drawing_provider_utils_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/drawing_provider_utils_test.js
@@ -7,7 +7,7 @@
 
 import {constructRgba, getTrailOpacityFromPressure, lookupCssVariableValue, MARK_COLOR, MARK_OPACITY, TRAIL_COLOR, TRAIL_MAX_OPACITY} from 'chrome://diagnostics/drawing_provider_utils.js';
 
-import {assertEquals} from '../../chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {MockController} from '../mock_controller.m.js';
 
 // A helper function to mock getPropertyValue function.
diff --git a/chrome/test/data/webui/chromeos/diagnostics/ethernet_info_test.js b/chrome/test/data/webui/chromeos/diagnostics/ethernet_info_test.js
index 710a0c00..e806afe2 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/ethernet_info_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/ethernet_info_test.js
@@ -9,7 +9,7 @@
 import {AuthenticationType, EthernetStateProperties, Network} from 'chrome://diagnostics/network_health_provider.mojom-webui.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {assertDataPointHasExpectedHeaderAndValue, assertTextContains, getDataPointValue} from './diagnostics_test_utils.js';
 
diff --git a/chrome/test/data/webui/chromeos/diagnostics/fake_network_health_provider_test.js b/chrome/test/data/webui/chromeos/diagnostics/fake_network_health_provider_test.js
index 230119f..c026f1a 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/fake_network_health_provider_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/fake_network_health_provider_test.js
@@ -9,7 +9,7 @@
 import {NetworkListObserverRemote, NetworkStateObserverRemote} from 'chrome://diagnostics/network_health_provider.mojom-webui.js';
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
 
-import {assertDeepEquals, assertEquals, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 suite('fakeNetworkHealthProviderTestSuite', function() {
   /** @type {?FakeNetworkHealthProvider} */
diff --git a/chrome/test/data/webui/chromeos/diagnostics/fake_system_data_provider_test.js b/chrome/test/data/webui/chromeos/diagnostics/fake_system_data_provider_test.js
index e764e1e..84d8a67f 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/fake_system_data_provider_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/fake_system_data_provider_test.js
@@ -9,7 +9,7 @@
 import {BatteryChargeStatusObserverRemote, BatteryHealthObserverRemote, CpuUsageObserverRemote, DeviceCapabilities, MemoryUsageObserverRemote, SystemInfo, VersionInfo} from 'chrome://diagnostics/system_data_provider.mojom-webui.js';
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 suite('fakeSystemDataProviderTestSuite', function() {
   /** @type {?FakeSystemDataProvider} */
diff --git a/chrome/test/data/webui/chromeos/diagnostics/fake_system_routine_controller_test.js b/chrome/test/data/webui/chromeos/diagnostics/fake_system_routine_controller_test.js
index eb95f39..d3333de 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/fake_system_routine_controller_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/fake_system_routine_controller_test.js
@@ -8,7 +8,7 @@
 import {RoutineRunnerRemote, RoutineType, StandardRoutineResult} from 'chrome://diagnostics/system_routine_controller.mojom-webui.js';
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 suite('fakeSystemRoutineContollerTestSuite', function() {
   /** @type {?FakeSystemRoutineController} */
diff --git a/chrome/test/data/webui/chromeos/diagnostics/frequency_channel_utils_test.js b/chrome/test/data/webui/chromeos/diagnostics/frequency_channel_utils_test.js
index 77e6e94..9b7c3c5 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/frequency_channel_utils_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/frequency_channel_utils_test.js
@@ -7,7 +7,7 @@
 import {ChannelBand} from 'chrome://diagnostics/diagnostics_types.js';
 import {convertFrequencyToChannel, getFrequencyChannelBand} from 'chrome://diagnostics/frequency_channel_utils.js';
 
-import {assertEquals} from '../../chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 suite('frequencyChannelUtilsTestSuite', function() {
   test('ConvertFrequencyToChannel', () => {
diff --git a/chrome/test/data/webui/chromeos/diagnostics/input_card_test.js b/chrome/test/data/webui/chromeos/diagnostics/input_card_test.js
index 70d6d344..6521f0d1 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/input_card_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/input_card_test.js
@@ -10,7 +10,7 @@
 import {ConnectionType, KeyboardInfo, MechanicalLayout, NumberPadPresence, PhysicalLayout, TopRightKey, TopRowKey} from 'chrome://diagnostics/input_data_provider.mojom-webui.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 /** @type {!Array<!KeyboardInfo>} */
 const keyboards = [
diff --git a/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js b/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js
index 9673520..a1e68d1 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js
@@ -19,7 +19,7 @@
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 import {eventToPromise} from 'chrome://webui-test/test_util.js';
 
-import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 import {TestDiagnosticsBrowserProxy} from './test_diagnostics_browser_proxy.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/ip_config_info_drawer_test.js b/chrome/test/data/webui/chromeos/diagnostics/ip_config_info_drawer_test.js
index 54be354f..7d5f3fef 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/ip_config_info_drawer_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/ip_config_info_drawer_test.js
@@ -11,7 +11,7 @@
 import {Network} from 'chrome://diagnostics/network_health_provider.mojom-webui.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/keyboard_tester_test.js b/chrome/test/data/webui/chromeos/diagnostics/keyboard_tester_test.js
index 857540a..c7e1b19 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/keyboard_tester_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/keyboard_tester_test.js
@@ -10,7 +10,7 @@
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 import {eventToPromise} from 'chrome://webui-test/test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {MockController} from '../mock_controller.m.js';
 
 suite('keyboardTesterTestSuite', function() {
diff --git a/chrome/test/data/webui/chromeos/diagnostics/memory_card_test.js b/chrome/test/data/webui/chromeos/diagnostics/memory_card_test.js
index 26b71e1..6c17560b 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/memory_card_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/memory_card_test.js
@@ -16,7 +16,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isChildVisible, isVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/mojo_interface_provider_test.js b/chrome/test/data/webui/chromeos/diagnostics/mojo_interface_provider_test.js
index f685cd8..a7617f48 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/mojo_interface_provider_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/mojo_interface_provider_test.js
@@ -9,7 +9,7 @@
 import {FakeSystemRoutineController} from 'chrome://diagnostics/fake_system_routine_controller.js';
 import {getNetworkHealthProvider, getSystemDataProvider, getSystemRoutineController, setNetworkHealthProviderForTesting, setSystemDataProviderForTesting, setSystemRoutineControllerForTesting} from 'chrome://diagnostics/mojo_interface_provider.js';
 
-import {assertEquals} from '../../chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 suite('fakeMojoProviderTestSuite', function() {
   test('SettingGettingTestProvider', () => {
diff --git a/chrome/test/data/webui/chromeos/diagnostics/network_card_test.js b/chrome/test/data/webui/chromeos/diagnostics/network_card_test.js
index 2a85c813..7f70f22 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/network_card_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/network_card_test.js
@@ -14,7 +14,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/network_info_test.js b/chrome/test/data/webui/chromeos/diagnostics/network_info_test.js
index 9fd6d85d..104604e 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/network_info_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/network_info_test.js
@@ -10,7 +10,7 @@
 import {NetworkInfoElement} from 'chrome://diagnostics/network_info.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/network_list_test.js b/chrome/test/data/webui/chromeos/diagnostics/network_list_test.js
index 977b1fcb..ca557ed 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/network_list_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/network_list_test.js
@@ -15,7 +15,7 @@
 import {NetworkListElement} from 'chrome://diagnostics/network_list.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/network_troubleshooting_test.js b/chrome/test/data/webui/chromeos/diagnostics/network_troubleshooting_test.js
index 13c985f..f71bb63b 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/network_troubleshooting_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/network_troubleshooting_test.js
@@ -8,7 +8,7 @@
 import {NetworkTroubleshootingElement} from 'chrome://diagnostics/network_troubleshooting.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/overview_card_test.js b/chrome/test/data/webui/chromeos/diagnostics/overview_card_test.js
index c4e0e7e..530988f 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/overview_card_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/overview_card_test.js
@@ -13,7 +13,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/percent_bar_chart_test.js b/chrome/test/data/webui/chromeos/diagnostics/percent_bar_chart_test.js
index fcbcc63..139e2fc 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/percent_bar_chart_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/percent_bar_chart_test.js
@@ -8,7 +8,7 @@
 import {PercentBarChartElement} from 'chrome://diagnostics/percent_bar_chart.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
 
diff --git a/chrome/test/data/webui/chromeos/diagnostics/realtime_cpu_chart_test.js b/chrome/test/data/webui/chromeos/diagnostics/realtime_cpu_chart_test.js
index 73862cea..d03dc70 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/realtime_cpu_chart_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/realtime_cpu_chart_test.js
@@ -8,7 +8,7 @@
 import {RealtimeCpuChartElement} from 'chrome://diagnostics/realtime_cpu_chart.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertGT, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertGT, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import * as diagnostics_test_utils from './diagnostics_test_utils.js';
 
diff --git a/chrome/test/data/webui/chromeos/diagnostics/routine_group_test.js b/chrome/test/data/webui/chromeos/diagnostics/routine_group_test.js
index 2244f087..a9168d7 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/routine_group_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/routine_group_test.js
@@ -9,7 +9,7 @@
 import {ExecutionProgress, ResultStatusItem} from 'chrome://diagnostics/routine_list_executor.js';
 import {RoutineResult, RoutineType, StandardRoutineResult} from 'chrome://diagnostics/system_routine_controller.mojom-webui.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 /**
  * @param {!RoutineType} routineType
diff --git a/chrome/test/data/webui/chromeos/diagnostics/routine_list_executor_test.js b/chrome/test/data/webui/chromeos/diagnostics/routine_list_executor_test.js
index 65239adb..870b2d4 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/routine_list_executor_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/routine_list_executor_test.js
@@ -8,7 +8,7 @@
 import {ExecutionProgress, ResultStatusItem, RoutineListExecutor} from 'chrome://diagnostics/routine_list_executor.js';
 import {PowerRoutineResult, RoutineResultInfo, RoutineType, StandardRoutineResult} from 'chrome://diagnostics/system_routine_controller.mojom-webui.js';
 
-import {assertEquals, assertFalse, assertNotEquals, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 suite('fakeRoutineListExecutorTestSuite', function() {
   /** @type {?FakeSystemRoutineController} */
diff --git a/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js b/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
index 30d4772..7f578e39 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
@@ -13,7 +13,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/routine_result_list_test.js b/chrome/test/data/webui/chromeos/diagnostics/routine_result_list_test.js
index f22b71d..5ef68cb6 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/routine_result_list_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/routine_result_list_test.js
@@ -11,7 +11,7 @@
 import {RoutineResult, RoutineType, StandardRoutineResult} from 'chrome://diagnostics/system_routine_controller.mojom-webui.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
 
diff --git a/chrome/test/data/webui/chromeos/diagnostics/routine_section_test.js b/chrome/test/data/webui/chromeos/diagnostics/routine_section_test.js
index 52ec9d68..47d06252 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/routine_section_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/routine_section_test.js
@@ -19,7 +19,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/system_page_test.js b/chrome/test/data/webui/chromeos/diagnostics/system_page_test.js
index cd55df7..b385a60 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/system_page_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/system_page_test.js
@@ -22,7 +22,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/test_diagnostics_browser_proxy.js b/chrome/test/data/webui/chromeos/diagnostics/test_diagnostics_browser_proxy.js
index 18e74f8..e731d3c 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/test_diagnostics_browser_proxy.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/test_diagnostics_browser_proxy.js
@@ -5,8 +5,8 @@
 import {NavigationView} from 'chrome://diagnostics/diagnostics_types.js';
 import {getNavigationViewForPageId} from 'chrome://diagnostics/diagnostics_utils.js';
 
-import {assertEquals} from '../../chai_assert.js';
-import {TestBrowserProxy} from '../../test_browser_proxy.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
+import {TestBrowserProxy} from 'chrome://webui-test/chromeos/test_browser_proxy.js';
 
 /** Test version of DiagnosticsBrowserProxy. */
 export class TestDiagnosticsBrowserProxy extends TestBrowserProxy {
diff --git a/chrome/test/data/webui/chromeos/diagnostics/text_badge_test.js b/chrome/test/data/webui/chromeos/diagnostics/text_badge_test.js
index 518e8cb..fc42fb3 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/text_badge_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/text_badge_test.js
@@ -8,7 +8,7 @@
 import {BadgeType, TextBadgeElement} from 'chrome://diagnostics/text_badge.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
 
diff --git a/chrome/test/data/webui/chromeos/diagnostics/touchpad_tester_test.js b/chrome/test/data/webui/chromeos/diagnostics/touchpad_tester_test.js
index fb338e5e..e3d3169 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/touchpad_tester_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/touchpad_tester_test.js
@@ -10,7 +10,7 @@
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {MockController} from '../mock_controller.m.js';
 import {isChildVisible, isVisible} from '../test_util.js';
 
diff --git a/chrome/test/data/webui/chromeos/diagnostics/touchscreen_tester_test.js b/chrome/test/data/webui/chromeos/diagnostics/touchscreen_tester_test.js
index 62b1e2a..23c1d241 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/touchscreen_tester_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/touchscreen_tester_test.js
@@ -7,7 +7,7 @@
 import {DialogType, SCREEN_MAX_LENGTH, TouchEventType} from 'chrome://diagnostics/touchscreen_tester.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {MockController} from '../mock_controller.m.js';
 import {eventToPromise} from '../test_util.js';
 
diff --git a/chrome/test/data/webui/chromeos/diagnostics/wifi_info_test.js b/chrome/test/data/webui/chromeos/diagnostics/wifi_info_test.js
index f9ce88b..3fd1504 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/wifi_info_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/wifi_info_test.js
@@ -11,7 +11,7 @@
 import {WifiInfoElement} from 'chrome://diagnostics/wifi_info.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {assertDataPointHasExpectedHeaderAndValue, assertTextContains, getDataPointValue} from './diagnostics_test_utils.js';
 
diff --git a/chrome/test/data/webui/chromeos/edu_coexistence/edu_coexistence_test_util.js b/chrome/test/data/webui/chromeos/edu_coexistence/edu_coexistence_test_util.js
index 79dfef6..b113506 100644
--- a/chrome/test/data/webui/chromeos/edu_coexistence/edu_coexistence_test_util.js
+++ b/chrome/test/data/webui/chromeos/edu_coexistence/edu_coexistence_test_util.js
@@ -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 {TestBrowserProxy} from '../../test_browser_proxy.js';
+import {TestBrowserProxy} from 'chrome://webui-test/chromeos/test_browser_proxy.js';
 
 /** @return {!Array<string>} */
 export function getFakeAccountsList() {
diff --git a/chrome/test/data/webui/chromeos/emoji_picker/BUILD.gn b/chrome/test/data/webui/chromeos/emoji_picker/BUILD.gn
index 429b71a..611bd7b 100644
--- a/chrome/test/data/webui/chromeos/emoji_picker/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/emoji_picker/BUILD.gn
@@ -6,21 +6,23 @@
 
 js_type_check("closure_compile") {
   is_polymer3 = true
-  closure_flags =
-      default_closure_args + mojom_js_args + [
-        "browser_resolver_prefix_replacements=\"chrome://emoji-picker/=" +
-            rebase_path("//chrome/browser/resources/chromeos/emoji_picker/",
-                        root_build_dir) + "\"",
-        "js_module_root=" +
-            rebase_path("//chrome/test/data/webui/", root_build_dir),
-        "js_module_root=./gen/chrome/test/data/webui/",
-        "js_module_root=" +
-            rebase_path("//chrome/browser/resources/chromeos/emoji_picker/",
-                        root_build_dir),
-        "js_module_root=" + rebase_path(
-                "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/ash/emoji",
-                root_build_dir),
-      ]
+  closure_flags = default_closure_args + mojom_js_args + [
+                    "browser_resolver_prefix_replacements=\"chrome://emoji-picker/=" + rebase_path(
+                            "//chrome/browser/resources/chromeos/emoji_picker/",
+                            root_build_dir) + "\"",
+                    "browser_resolver_prefix_replacements=\"chrome://webui-test/chromeos/=" + rebase_path(
+                            "//chrome/test/data/webui/chromeos/",
+                            root_build_dir) + "\"",
+                    "js_module_root=" + rebase_path("//chrome/test/data/webui/",
+                                                    root_build_dir),
+                    "js_module_root=./gen/chrome/test/data/webui/",
+                    "js_module_root=" + rebase_path(
+                            "//chrome/browser/resources/chromeos/emoji_picker/",
+                            root_build_dir),
+                    "js_module_root=" + rebase_path(
+                            "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/ash/emoji",
+                            root_build_dir),
+                  ]
   deps = [
     ":emoji_picker_extension_emoji_test",
     ":emoji_picker_extension_emoticon_test",
@@ -47,7 +49,7 @@
 js_library("emoji_picker_store_test") {
   deps = [
     "//chrome/browser/resources/chromeos/emoji_picker:store",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/webui/resources/js:assert",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -88,7 +90,7 @@
 js_library("emoji_picker_prefix_search_test") {
   deps = [
     "//chrome/browser/resources/chromeos/emoji_picker:prefix_search",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/webui/resources/js:assert",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -97,7 +99,7 @@
 js_library("emoji_picker_search_test") {
   deps = [
     "//chrome/browser/resources/chromeos/emoji_picker:emoji_picker",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/webui/resources/js:assert",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -105,7 +107,7 @@
 
 js_library("emoji_picker_trie_test") {
   deps = [
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/webui/resources/js:assert",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
diff --git a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_extension_categories.js b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_extension_categories.js
index c6cf82b..5193920 100644
--- a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_extension_categories.js
+++ b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_extension_categories.js
@@ -8,7 +8,7 @@
 import {assert} from 'chrome://resources/js/assert.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertEquals, assertFalse, assertGT, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertGT, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {deepQuerySelector, waitForCondition, waitWithTimeout} from './emoji_picker_test_util.js';
 
diff --git a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_extension_test.js b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_extension_test.js
index e5aa758..cb19d59 100644
--- a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_extension_test.js
+++ b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_extension_test.js
@@ -8,7 +8,7 @@
 import {assert} from 'chrome://resources/js/assert.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertEquals, assertFalse} from '../../chai_assert.js';
+import {assertEquals, assertFalse} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {completePendingMicrotasks, deepQuerySelector, isGroupButtonActive, timeout, waitForCondition} from './emoji_picker_test_util.js';
 
diff --git a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_prefix_search_test.js b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_prefix_search_test.js
index f270b9f..bcee73f 100644
--- a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_prefix_search_test.js
+++ b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_prefix_search_test.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {EmojiPrefixSearch} from 'chrome://emoji-picker/prefix_search.js';
-import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {assertCloseTo} from './emoji_picker_test_util.js';
 
 const mockCollection1 = [
@@ -130,4 +130,4 @@
         assertArrayEquals(
             prefixSearch.search('Smi With'), prefixSearch.search('sMI WITh'));
       });
-});
\ No newline at end of file
+});
diff --git a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_search_test.js b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_search_test.js
index 0bfca6c9..0edd9598 100644
--- a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_search_test.js
+++ b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_search_test.js
@@ -7,7 +7,7 @@
 import {assert} from 'chrome://resources/js/assert.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertEquals, assertGT} from '../../chai_assert.js';
+import {assertEquals, assertGT} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {deepQuerySelector, waitForCondition, waitWithTimeout} from './emoji_picker_test_util.js';
 
diff --git a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_store_test.js b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_store_test.js
index e003a82..ca19915 100644
--- a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_store_test.js
+++ b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_store_test.js
@@ -5,7 +5,7 @@
 import {RecentlyUsedStore} from 'chrome://emoji-picker/store.js';
 import {assert} from 'chrome://resources/js/assert.js';
 
-import {assertDeepEquals} from '../../chai_assert.js';
+import {assertDeepEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 const TEST_EMOJI = {
   waving: {string: '👋', codepoints: [128075]},
diff --git a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_test.js b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_test.js
index 36c61a8b..f9bccc2 100644
--- a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_test.js
+++ b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_test.js
@@ -11,7 +11,7 @@
 import {assert} from 'chrome://resources/js/assert.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertEquals, assertFalse, assertGT, assertLT, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertGT, assertLT, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {assertCloseTo, deepQuerySelector, dispatchMouseEvent, isGroupButtonActive, timeout, waitForCondition, waitForEvent, waitWithTimeout} from './emoji_picker_test_util.js';
 
diff --git a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_test_util.js b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_test_util.js
index 18c81a72..9887d92f 100644
--- a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_test_util.js
+++ b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_test_util.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {assert} from 'chrome://resources/js/assert.js';
-import {assertTrue} from '../../chai_assert.js';
+import {assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function assertCloseTo(actual, expected) {
   assertTrue(
diff --git a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_trie_test.js b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_trie_test.js
index 0ae76fd..17c329b 100644
--- a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_trie_test.js
+++ b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_trie_test.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {Trie} from 'chrome://emoji-picker/structs/trie.js';
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 suite('TrieUnitTest', () => {
   let trie;
diff --git a/chrome/test/data/webui/chromeos/firmware_update/BUILD.gn b/chrome/test/data/webui/chromeos/firmware_update/BUILD.gn
index 1f0d050..a46924f 100644
--- a/chrome/test/data/webui/chromeos/firmware_update/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/firmware_update/BUILD.gn
@@ -6,17 +6,18 @@
 
 js_type_check("closure_compile") {
   is_polymer3 = true
-  closure_flags =
-      default_closure_args + [
-        "browser_resolver_prefix_replacements=\"chrome://accessory-update/=" +
-            rebase_path("//ash/webui/firmware_update_ui/resources/",
-                        root_build_dir) + "\"",
-        "browser_resolver_prefix_replacements=\"chrome://webui-test/=" +
-            "./gen/chrome/test/data/webui/tsc\"",
-        "js_module_root=" +
-            rebase_path("//chrome/test/data/webui/", root_build_dir),
-        "js_module_root=./gen/chrome/test/data/webui/",
-      ]
+  closure_flags = default_closure_args + [
+                    "browser_resolver_prefix_replacements=\"chrome://accessory-update/=" + rebase_path(
+                            "//ash/webui/firmware_update_ui/resources/",
+                            root_build_dir) + "\"",
+                    "browser_resolver_prefix_replacements=\"chrome://webui-test/chromeos/=" + rebase_path(
+                            "//chrome/test/data/webui/chromeos/",
+                            root_build_dir) + "\"",
+                    "browser_resolver_prefix_replacements=\"chrome://webui-test/=" + "./gen/chrome/test/data/webui/tsc\"",
+                    "js_module_root=" + rebase_path("//chrome/test/data/webui/",
+                                                    root_build_dir),
+                    "js_module_root=./gen/chrome/test/data/webui/",
+                  ]
   deps = [
     ":fake_update_controller_test",
     ":fake_update_provider_test",
@@ -30,7 +31,7 @@
 
 js_library("fake_update_controller_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/firmware_update_ui/resources:fake_data",
     "//ash/webui/firmware_update_ui/resources:fake_update_controller",
     "//ash/webui/firmware_update_ui/resources:firmware_update_types",
@@ -40,7 +41,7 @@
 
 js_library("fake_update_provider_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/firmware_update_ui/resources:fake_data",
     "//ash/webui/firmware_update_ui/resources:fake_update_provider",
     "//ash/webui/firmware_update_ui/resources:firmware_update_types",
@@ -50,8 +51,8 @@
 
 js_library("firmware_update_dialog_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/firmware_update_ui/resources:fake_data",
     "//ash/webui/firmware_update_ui/resources:firmware_update_dialog",
     "//ash/webui/firmware_update_ui/resources:firmware_update_types",
@@ -66,8 +67,8 @@
 
 js_library("firmware_update_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/firmware_update_ui/resources:fake_data",
     "//ash/webui/firmware_update_ui/resources:fake_update_controller",
     "//ash/webui/firmware_update_ui/resources:fake_update_provider",
@@ -88,8 +89,8 @@
 
 js_library("peripheral_updates_list_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/firmware_update_ui/resources:fake_data",
     "//ash/webui/firmware_update_ui/resources:fake_update_provider",
     "//ash/webui/firmware_update_ui/resources:firmware_update_types",
@@ -103,8 +104,8 @@
 
 js_library("update_card_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/firmware_update_ui/resources:fake_data",
     "//ash/webui/firmware_update_ui/resources:firmware_update_types",
     "//ash/webui/firmware_update_ui/resources:mojo_utils",
diff --git a/chrome/test/data/webui/chromeos/firmware_update/fake_update_controller_test.js b/chrome/test/data/webui/chromeos/firmware_update/fake_update_controller_test.js
index 1b50110b..905f6c6 100644
--- a/chrome/test/data/webui/chromeos/firmware_update/fake_update_controller_test.js
+++ b/chrome/test/data/webui/chromeos/firmware_update/fake_update_controller_test.js
@@ -7,7 +7,7 @@
 import {UpdateProgressObserverRemote} from 'chrome://accessory-update/firmware_update_types.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function fakeUpdateControllerTest() {
   /** @type {?FakeUpdateController} */
diff --git a/chrome/test/data/webui/chromeos/firmware_update/fake_update_provider_test.js b/chrome/test/data/webui/chromeos/firmware_update/fake_update_provider_test.js
index 13a8599..225ab58 100644
--- a/chrome/test/data/webui/chromeos/firmware_update/fake_update_provider_test.js
+++ b/chrome/test/data/webui/chromeos/firmware_update/fake_update_provider_test.js
@@ -6,7 +6,7 @@
 import {FakeUpdateProvider} from 'chrome://accessory-update/fake_update_provider.js';
 import {UpdateObserverRemote} from 'chrome://accessory-update/firmware_update_types.js';
 
-import {assertDeepEquals} from '../../chai_assert.js';
+import {assertDeepEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function fakeUpdateProviderTest() {
   /** @type {?FakeUpdateProvider} */
diff --git a/chrome/test/data/webui/chromeos/firmware_update/firmware_update_dialog_test.js b/chrome/test/data/webui/chromeos/firmware_update/firmware_update_dialog_test.js
index 56d5464..08cbd36 100644
--- a/chrome/test/data/webui/chromeos/firmware_update/firmware_update_dialog_test.js
+++ b/chrome/test/data/webui/chromeos/firmware_update/firmware_update_dialog_test.js
@@ -10,7 +10,7 @@
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 export function firmwareUpdateDialogTest() {
diff --git a/chrome/test/data/webui/chromeos/firmware_update/firmware_update_test.js b/chrome/test/data/webui/chromeos/firmware_update/firmware_update_test.js
index f49e5c7..5dfbe56 100644
--- a/chrome/test/data/webui/chromeos/firmware_update/firmware_update_test.js
+++ b/chrome/test/data/webui/chromeos/firmware_update/firmware_update_test.js
@@ -16,7 +16,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {eventToPromise} from '../test_util.js';
 
 export function firmwareUpdateAppTest() {
diff --git a/chrome/test/data/webui/chromeos/firmware_update/peripheral_updates_list_test.js b/chrome/test/data/webui/chromeos/firmware_update/peripheral_updates_list_test.js
index d4a1fc67..7e188e1 100644
--- a/chrome/test/data/webui/chromeos/firmware_update/peripheral_updates_list_test.js
+++ b/chrome/test/data/webui/chromeos/firmware_update/peripheral_updates_list_test.js
@@ -11,7 +11,7 @@
 import {UpdateCardElement} from 'chrome://accessory-update/update_card.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 export function peripheralUpdatesListTest() {
diff --git a/chrome/test/data/webui/chromeos/firmware_update/update_card_test.js b/chrome/test/data/webui/chromeos/firmware_update/update_card_test.js
index 8d90c83b..f20e742 100644
--- a/chrome/test/data/webui/chromeos/firmware_update/update_card_test.js
+++ b/chrome/test/data/webui/chromeos/firmware_update/update_card_test.js
@@ -8,7 +8,7 @@
 import {UpdateCardElement} from 'chrome://accessory-update/update_card.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 export function updateCardTest() {
diff --git a/chrome/test/data/webui/chromeos/gaia_action_buttons/BUILD.gn b/chrome/test/data/webui/chromeos/gaia_action_buttons/BUILD.gn
index 177d858..e01617b 100644
--- a/chrome/test/data/webui/chromeos/gaia_action_buttons/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/gaia_action_buttons/BUILD.gn
@@ -30,7 +30,7 @@
 
 js_library("gaia_action_buttons_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//chrome/browser/resources/chromeos/gaia_action_buttons:gaia_action_buttons",
     "//ui/webui/resources/js:assert",
     "//ui/webui/resources/js/cr:event_target",
diff --git a/chrome/test/data/webui/chromeos/gaia_action_buttons/gaia_action_buttons_test.js b/chrome/test/data/webui/chromeos/gaia_action_buttons/gaia_action_buttons_test.js
index 578bae5..a2b2f2b 100644
--- a/chrome/test/data/webui/chromeos/gaia_action_buttons/gaia_action_buttons_test.js
+++ b/chrome/test/data/webui/chromeos/gaia_action_buttons/gaia_action_buttons_test.js
@@ -8,7 +8,7 @@
 import {assert} from 'chrome://resources/js/assert.js';
 import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chromeos/chai_assert.js';
 
 window.gaia_action_buttons_test = {};
 const gaia_action_buttons_test = window.gaia_action_buttons_test;
diff --git a/chrome/test/data/webui/chromeos/mock_controller.m.js b/chrome/test/data/webui/chromeos/mock_controller.m.js
index a7d2bad..7a0a7f49 100644
--- a/chrome/test/data/webui/chromeos/mock_controller.m.js
+++ b/chrome/test/data/webui/chromeos/mock_controller.m.js
@@ -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 {assertDeepEquals, assertEquals} from '../chai_assert.js';
+import {assertDeepEquals, assertEquals} from './chai_assert.js';
 
 /**
  * Create a mock function that records function calls and validates against
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/BUILD.gn b/chrome/test/data/webui/chromeos/os_feedback_ui/BUILD.gn
index 90a3b66..c8f86de 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/BUILD.gn
@@ -10,6 +10,9 @@
                     "browser_resolver_prefix_replacements=\"chrome://os-feedback/=" + rebase_path(
                             "//ash/webui/os_feedback_ui/resources/",
                             root_build_dir) + "\"",
+                    "browser_resolver_prefix_replacements=\"chrome://webui-test/chromeos/=" + rebase_path(
+                            "//chrome/test/data/webui/chromeos/",
+                            root_build_dir) + "\"",
                     "browser_resolver_prefix_replacements=\"chrome://webui-test/=./gen/chrome/test/data/webui/tsc\"",
                     "js_module_root=" + rebase_path("//chrome/test/data/webui/",
                                                     root_build_dir),
@@ -30,7 +33,7 @@
 
 js_library("confirmation_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/os_feedback_ui/resources:confirmation_page",
     "//ash/webui/os_feedback_ui/resources:feedback_types",
   ]
@@ -39,7 +42,7 @@
 
 js_library("fake_help_content_provider_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/common/resources:mojo_utils",
     "//ash/webui/os_feedback_ui/resources:fake_data",
     "//ash/webui/os_feedback_ui/resources:fake_help_content_provider",
@@ -50,7 +53,7 @@
 
 js_library("feedback_flow_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/os_feedback_ui/resources:confirmation_page",
     "//ash/webui/os_feedback_ui/resources:feedback_flow",
     "//ash/webui/os_feedback_ui/resources:feedback_types",
@@ -61,7 +64,7 @@
 
 js_library("file_attachment_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/common/resources:mojo_utils",
     "//ash/webui/os_feedback_ui/resources:file_attachment",
   ]
@@ -70,7 +73,7 @@
 
 js_library("help_content_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/os_feedback_ui/resources:fake_data",
     "//ash/webui/os_feedback_ui/resources:feedback_types",
     "//ash/webui/os_feedback_ui/resources:help_content",
@@ -80,7 +83,7 @@
 
 js_library("mojo_interface_provider_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/os_feedback_ui/resources:fake_feedback_service_provider",
     "//ash/webui/os_feedback_ui/resources:fake_help_content_provider",
     "//ash/webui/os_feedback_ui/resources:feedback_types",
@@ -96,8 +99,8 @@
 
 js_library("search_page_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/os_feedback_ui/resources:fake_data",
     "//ash/webui/os_feedback_ui/resources:feedback_flow",
     "//ash/webui/os_feedback_ui/resources:feedback_types",
@@ -109,8 +112,8 @@
 
 js_library("share_data_page_test") {
   deps = [
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/os_feedback_ui/resources:fake_data",
     "//ash/webui/os_feedback_ui/resources:share_data_page",
   ]
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js
index 5f3a146..275ca51 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js
@@ -10,7 +10,7 @@
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {eventToPromise, isVisible} from '../test_util.js';
 
 /** @type {string} */
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/fake_help_content_provider_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/fake_help_content_provider_test.js
index 9400b1c8..78cb87ee 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/fake_help_content_provider_test.js
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/fake_help_content_provider_test.js
@@ -7,7 +7,7 @@
 import {HelpContentList, SearchResponse} from 'chrome://os-feedback/feedback_types.js';
 import {mojoString16ToString} from 'chrome://resources/ash/common/mojo_utils.js';
 
-import {assertDeepEquals, assertEquals} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function fakeHelpContentProviderTestSuite() {
   /** @type {?FakeHelpContentProvider} */
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/feedback_flow_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/feedback_flow_test.js
index 3e106b2..74ff2a1 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/feedback_flow_test.js
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/feedback_flow_test.js
@@ -13,7 +13,7 @@
 import {getDeepActiveElement} from 'chrome://resources/js/util.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {eventToPromise, isVisible} from '../test_util.js';
 
 export function FeedbackFlowTestSuite() {
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/file_attachment_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/file_attachment_test.js
index 5bee4b4..30b1965d 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/file_attachment_test.js
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/file_attachment_test.js
@@ -13,7 +13,7 @@
 import {getDeepActiveElement} from 'chrome://resources/js/util.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {eventToPromise, isVisible} from '../test_util.js';
 
 /** @type {string} */
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/help_content_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/help_content_test.js
index 7bd9b7741..f87298c 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/help_content_test.js
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/help_content_test.js
@@ -7,7 +7,7 @@
 import {HelpContentElement} from 'chrome://os-feedback/help_content.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../test_util.js';
 
 export function helpContentTestSuite() {
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/mojo_interface_provider_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/mojo_interface_provider_test.js
index 0979f7aa..b2690524 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/mojo_interface_provider_test.js
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/mojo_interface_provider_test.js
@@ -7,7 +7,7 @@
 import {FeedbackServiceProviderInterface, HelpContentProviderInterface} from 'chrome://os-feedback/feedback_types.js';
 import {getFeedbackServiceProvider, getHelpContentProvider, setFeedbackServiceProviderForTesting, setHelpContentProviderForTesting} from 'chrome://os-feedback/mojo_interface_provider.js';
 
-import {assertEquals, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function fakeMojoProviderTestSuite() {
   test('SettingGettingTestHelpContentProvider', () => {
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/search_page_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/search_page_test.js
index 3c46743..1e3fd9b 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/search_page_test.js
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/search_page_test.js
@@ -11,7 +11,7 @@
 import {getDeepActiveElement} from 'chrome://resources/js/util.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertNotEquals, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {eventToPromise} from '../test_util.js';
 
 export function searchPageTestSuite() {
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js
index dd517d2..90985ab 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js
@@ -16,7 +16,7 @@
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertArrayEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from '../../chai_assert.js';
+import {assertArrayEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {eventToPromise, isVisible} from '../test_util.js';
 
 /** @type {string} */
diff --git a/chrome/test/data/webui/chromeos/parent_access/parent_access_app_test.js b/chrome/test/data/webui/chromeos/parent_access/parent_access_app_test.js
index 06ed3438..4adef56 100644
--- a/chrome/test/data/webui/chromeos/parent_access/parent_access_app_test.js
+++ b/chrome/test/data/webui/chromeos/parent_access/parent_access_app_test.js
@@ -10,7 +10,7 @@
 import {setParentAccessUIHandlerForTest} from 'chrome://parent-access/parent_access_ui_handler.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertNotEquals} from '../../chai_assert.js';
+import {assertEquals, assertNotEquals} from 'chrome://webui-test/chai_assert.js';
 
 import {buildWebApprovalsParams} from './parent_access_test_utils.js';
 import {TestParentAccessUIHandler} from './test_parent_access_ui_handler.js';
diff --git a/chrome/test/data/webui/chromeos/parent_access/parent_access_ui_test.js b/chrome/test/data/webui/chromeos/parent_access/parent_access_ui_test.js
index 898beb79..606340a 100644
--- a/chrome/test/data/webui/chromeos/parent_access/parent_access_ui_test.js
+++ b/chrome/test/data/webui/chromeos/parent_access/parent_access_ui_test.js
@@ -11,7 +11,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 
 import {TestParentAccessUIHandler} from './test_parent_access_ui_handler.js';
 
diff --git a/chrome/test/data/webui/chromeos/personalization_app/avatar_camera_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/avatar_camera_element_test.ts
index 0791ada..eeaebe47e 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/avatar_camera_element_test.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/avatar_camera_element_test.ts
@@ -40,7 +40,6 @@
 
   convertFramesToPng(_: HTMLCanvasElement[]): string {
     assertNotReached('This function should never be called');
-    return '';
   }
 
   async captureFrames(
@@ -56,8 +55,8 @@
   }
 }
 
-class MockGetUserMediaProxy extends
-    TestBrowserProxy<GetUserMediaProxy> implements GetUserMediaProxy {
+class MockGetUserMediaProxy extends TestBrowserProxy implements
+    GetUserMediaProxy {
   mediaStream = new MediaStream();
 
   constructor() {
diff --git a/chrome/test/data/webui/chromeos/personalization_app/test_keyboard_backlight_interface_provider.ts b/chrome/test/data/webui/chromeos/personalization_app/test_keyboard_backlight_interface_provider.ts
index d418528..99dda4c 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/test_keyboard_backlight_interface_provider.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/test_keyboard_backlight_interface_provider.ts
@@ -6,9 +6,8 @@
 import {SkColor} from 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-webui.js';
 import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
 
-export class TestKeyboardBacklightProvider extends
-    TestBrowserProxy<KeyboardBacklightProviderInterface> implements
-        KeyboardBacklightProviderInterface {
+export class TestKeyboardBacklightProvider extends TestBrowserProxy implements
+    KeyboardBacklightProviderInterface {
   public backlightColor: BacklightColor = BacklightColor.kBlue;
 
   constructor() {
diff --git a/chrome/test/data/webui/chromeos/personalization_app/test_theme_interface_provider.ts b/chrome/test/data/webui/chromeos/personalization_app/test_theme_interface_provider.ts
index 1ffa5cac..161ef1c 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/test_theme_interface_provider.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/test_theme_interface_provider.ts
@@ -5,8 +5,8 @@
 import {ThemeObserverInterface, ThemeObserverRemote, ThemeProviderInterface} from 'chrome://personalization/js/personalization_app.js';
 import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
 
-export class TestThemeProvider extends
-    TestBrowserProxy<ThemeProviderInterface> implements ThemeProviderInterface {
+export class TestThemeProvider extends TestBrowserProxy implements
+    ThemeProviderInterface {
   constructor() {
     super([
       'setThemeObserver',
diff --git a/chrome/test/data/webui/chromeos/personalization_app/test_user_interface_provider.ts b/chrome/test/data/webui/chromeos/personalization_app/test_user_interface_provider.ts
index d5d2dbe5..e7cbd6b 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/test_user_interface_provider.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/test_user_interface_provider.ts
@@ -7,8 +7,8 @@
 import {Url} from 'chrome://resources/mojo/url/mojom/url.mojom-webui.js';
 import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
 
-export class TestUserProvider extends
-    TestBrowserProxy<UserProviderInterface> implements UserProviderInterface {
+export class TestUserProvider extends TestBrowserProxy implements
+    UserProviderInterface {
   public defaultUserImages: DefaultUserImage[] = [
     {
       index: 8,
diff --git a/chrome/test/data/webui/chromeos/personalization_app/test_wallpaper_interface_provider.ts b/chrome/test/data/webui/chromeos/personalization_app/test_wallpaper_interface_provider.ts
index dbcc124..73fd723a 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/test_wallpaper_interface_provider.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/test_wallpaper_interface_provider.ts
@@ -9,9 +9,8 @@
 import {assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
 
-export class TestWallpaperProvider extends
-    TestBrowserProxy<WallpaperProviderInterface> implements
-        WallpaperProviderInterface {
+export class TestWallpaperProvider extends TestBrowserProxy implements
+    WallpaperProviderInterface {
   constructor() {
     super([
       'makeTransparent',
diff --git a/chrome/test/data/webui/chromeos/scanning/BUILD.gn b/chrome/test/data/webui/chromeos/scanning/BUILD.gn
index 1eb2c83..8985403 100644
--- a/chrome/test/data/webui/chromeos/scanning/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/scanning/BUILD.gn
@@ -6,17 +6,20 @@
 
 js_type_check("closure_compile") {
   is_polymer3 = true
-  closure_flags =
-      default_closure_args + [
-        "browser_resolver_prefix_replacements=\"chrome://scanning/=" +
-            rebase_path("//ash/webui/scanning/resources/", root_build_dir) +
-            "\"",
-        "browser_resolver_prefix_replacements=\"chrome://webui-test/=" +
-            "./gen/chrome/test/data/webui/tsc\"",
-        "js_module_root=" +
-            rebase_path("//chrome/test/data/webui/", root_build_dir),
-        "js_module_root=./gen/chrome/test/data/webui/",
-      ]
+  closure_flags = default_closure_args + [
+                    "browser_resolver_prefix_replacements=\"chrome://scanning/=" + rebase_path(
+                            "//ash/webui/scanning/resources/",
+                            root_build_dir) + "\"",
+                    "browser_resolver_prefix_replacements=\"chrome://webui-test/chromeos/=" + rebase_path(
+                            "//chrome/test/data/webui/chromeos/",
+                            root_build_dir) + "\"",
+                    "js_module_root=" + rebase_path("//chrome/test/data/webui/",
+                                                    root_build_dir),
+                    "browser_resolver_prefix_replacements=\"chrome://webui-test/=" + "./gen/chrome/test/data/webui/tsc\"",
+                    "js_module_root=" + rebase_path("//chrome/test/data/webui/",
+                                                    root_build_dir),
+                    "js_module_root=./gen/chrome/test/data/webui/",
+                  ]
   deps = [
     ":action_toolbar_test",
     ":color_mode_select_test",
@@ -40,7 +43,7 @@
 
 js_library("action_toolbar_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/scanning/resources:action_toolbar",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -49,7 +52,7 @@
 js_library("color_mode_select_test") {
   deps = [
     ":scanning_app_test_utils",
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/scanning/resources:color_mode_select",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -57,7 +60,7 @@
 
 js_library("file_type_select_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/scanning/resources:file_type_select",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -65,7 +68,7 @@
 
 js_library("loading_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/scanning/resources:loading_page",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -73,7 +76,7 @@
 
 js_library("multi_page_scan_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/scanning/resources:multi_page_scan",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -81,7 +84,7 @@
 
 js_library("multi_page_checkbox_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/scanning/resources:multi_page_checkbox",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -89,7 +92,7 @@
 
 js_library("page_size_select_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/scanning/resources:page_size_select",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -97,7 +100,7 @@
 
 js_library("resolution_select_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/scanning/resources:resolution_select",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -105,7 +108,7 @@
 
 js_library("scan_done_section_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/scanning/resources:scan_done_section",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -113,7 +116,7 @@
 
 js_library("scan_preview_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/scanning/resources:scan_preview",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -122,7 +125,7 @@
 js_library("scan_to_select_test") {
   deps = [
     ":test_scanning_browser_proxy",
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/scanning/resources:scan_to_select",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -131,7 +134,7 @@
 js_library("scanner_select_test") {
   deps = [
     ":scanning_app_test_utils",
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/scanning/resources:scanner_select",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -140,8 +143,8 @@
 js_library("scanning_app_test") {
   deps = [
     ":scanning_app_test_utils",
+    "..:chai_assert",
     "..:test_util",
-    "../..:chai_assert",
     "//ash/webui/scanning/resources:scanning_app",
     "//third_party/polymer/v3_0/components-chromium/iron-collapse:iron-collapse",
   ]
@@ -152,7 +155,7 @@
 }
 
 js_library("scanning_app_test_utils") {
-  deps = [ "../..:chai_assert" ]
+  deps = [ "..:chai_assert" ]
 }
 
 js_library("scanning_app_unified_test") {
@@ -168,8 +171,8 @@
 
 js_library("test_scanning_browser_proxy") {
   deps = [
-    "../..:chai_assert",
-    "../..:test_browser_proxy",
+    "..:chai_assert",
+    "..:test_browser_proxy",
     "//ash/webui/scanning/resources:scanning_browser_proxy",
   ]
 }
diff --git a/chrome/test/data/webui/chromeos/scanning/action_toolbar_test.js b/chrome/test/data/webui/chromeos/scanning/action_toolbar_test.js
index 8d72bed..9eef3aa 100644
--- a/chrome/test/data/webui/chromeos/scanning/action_toolbar_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/action_toolbar_test.js
@@ -6,7 +6,7 @@
 
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function actionToolbarTest() {
   /** @type {?ActionToolbarElement} */
diff --git a/chrome/test/data/webui/chromeos/scanning/color_mode_select_test.js b/chrome/test/data/webui/chromeos/scanning/color_mode_select_test.js
index 5723fa9..e12dd94 100644
--- a/chrome/test/data/webui/chromeos/scanning/color_mode_select_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/color_mode_select_test.js
@@ -7,7 +7,7 @@
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {getColorModeString} from 'chrome://scanning/scanning_app_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {assertOrderedAlphabetically, changeSelect} from './scanning_app_test_utils.js';
 
diff --git a/chrome/test/data/webui/chromeos/scanning/file_type_select_test.js b/chrome/test/data/webui/chromeos/scanning/file_type_select_test.js
index 7e19c25e..58e0709 100644
--- a/chrome/test/data/webui/chromeos/scanning/file_type_select_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/file_type_select_test.js
@@ -4,7 +4,7 @@
 
 import 'chrome://scanning/file_type_select.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {changeSelect} from './scanning_app_test_utils.js';
 
diff --git a/chrome/test/data/webui/chromeos/scanning/loading_page_test.js b/chrome/test/data/webui/chromeos/scanning/loading_page_test.js
index 3fb2957..518f56ae 100644
--- a/chrome/test/data/webui/chromeos/scanning/loading_page_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/loading_page_test.js
@@ -7,9 +7,9 @@
 import {AppState} from 'chrome://scanning/scanning_app_types.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
-import {MockController} from '../mock_controller.m.js';
-import {isVisible} from '../test_util.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
+import {MockController} from 'chrome://webui-test/chromeos/mock_controller.m.js';
+import {isVisible} from 'chrome://webui-test/chromeos/test_util.js';
 
 import {FakeMediaQueryList} from './scanning_app_test_utils.js';
 
diff --git a/chrome/test/data/webui/chromeos/scanning/multi_page_checkbox_test.js b/chrome/test/data/webui/chromeos/scanning/multi_page_checkbox_test.js
index 51dcf62..a9a13cb 100644
--- a/chrome/test/data/webui/chromeos/scanning/multi_page_checkbox_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/multi_page_checkbox_test.js
@@ -6,7 +6,7 @@
 
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function multiPageCheckboxTest() {
   /** @type {?MultiPageCheckboxElement} */
diff --git a/chrome/test/data/webui/chromeos/scanning/multi_page_scan_test.js b/chrome/test/data/webui/chromeos/scanning/multi_page_scan_test.js
index 6d5e102..bcad02f 100644
--- a/chrome/test/data/webui/chromeos/scanning/multi_page_scan_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/multi_page_scan_test.js
@@ -9,8 +9,8 @@
 import {ScanningBrowserProxyImpl} from 'chrome://scanning/scanning_browser_proxy.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
-import {isVisible} from '../test_util.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
+import {isVisible} from 'chrome://webui-test/chromeos/test_util.js';
 
 import {TestScanningBrowserProxy} from './test_scanning_browser_proxy.js';
 
diff --git a/chrome/test/data/webui/chromeos/scanning/page_size_select_test.js b/chrome/test/data/webui/chromeos/scanning/page_size_select_test.js
index 3f7e62a..de21fb0 100644
--- a/chrome/test/data/webui/chromeos/scanning/page_size_select_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/page_size_select_test.js
@@ -7,7 +7,7 @@
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {getPageSizeString} from 'chrome://scanning/scanning_app_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {assertOrderedAlphabetically, changeSelect} from './scanning_app_test_utils.js';
 
diff --git a/chrome/test/data/webui/chromeos/scanning/resolution_select_test.js b/chrome/test/data/webui/chromeos/scanning/resolution_select_test.js
index ba0cfeb..3a0bcf7 100644
--- a/chrome/test/data/webui/chromeos/scanning/resolution_select_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/resolution_select_test.js
@@ -6,7 +6,7 @@
 
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {changeSelect} from './scanning_app_test_utils.js';
 
diff --git a/chrome/test/data/webui/chromeos/scanning/scan_done_section_test.js b/chrome/test/data/webui/chromeos/scanning/scan_done_section_test.js
index 0188137..70094993 100644
--- a/chrome/test/data/webui/chromeos/scanning/scan_done_section_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/scan_done_section_test.js
@@ -7,8 +7,8 @@
 import {ScanningBrowserProxyImpl} from 'chrome://scanning/scanning_browser_proxy.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
-import {isVisible} from '../test_util.js';
+import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
+import {isVisible} from 'chrome://webui-test/chromeos/test_util.js';
 
 import {TestScanningBrowserProxy} from './test_scanning_browser_proxy.js';
 
diff --git a/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js b/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js
index e1d12ba..347a4ff 100644
--- a/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js
@@ -11,9 +11,9 @@
 import {ScanningBrowserProxyImpl} from 'chrome://scanning/scanning_browser_proxy.js';
 import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertNotEquals, assertTrue} from '../../chai_assert.js';
-import {MockController} from '../mock_controller.m.js';
-import {isVisible} from '../test_util.js';
+import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
+import {MockController} from 'chrome://webui-test/chromeos/mock_controller.m.js';
+import {isVisible} from 'chrome://webui-test/chromeos/test_util.js';
 
 import {FakeMediaQueryList} from './scanning_app_test_utils.js';
 import {TestScanningBrowserProxy} from './test_scanning_browser_proxy.js';
diff --git a/chrome/test/data/webui/chromeos/scanning/scan_to_select_test.js b/chrome/test/data/webui/chromeos/scanning/scan_to_select_test.js
index 093a06a..274aa586 100644
--- a/chrome/test/data/webui/chromeos/scanning/scan_to_select_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/scan_to_select_test.js
@@ -6,7 +6,7 @@
 
 import {ScanningBrowserProxyImpl} from 'chrome://scanning/scanning_browser_proxy.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {changeSelect} from './scanning_app_test_utils.js';
 import {TestScanningBrowserProxy} from './test_scanning_browser_proxy.js';
diff --git a/chrome/test/data/webui/chromeos/scanning/scanner_select_test.js b/chrome/test/data/webui/chromeos/scanning/scanner_select_test.js
index 3c1ac61..1f1fd34d 100644
--- a/chrome/test/data/webui/chromeos/scanning/scanner_select_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/scanner_select_test.js
@@ -10,7 +10,7 @@
 import {getScannerDisplayName, tokenToString} from 'chrome://scanning/scanning_app_util.js';
 import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {assertOrderedAlphabetically, createScanner} from './scanning_app_test_utils.js';
 
diff --git a/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js b/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js
index 72bc96aa..cc2541d 100644
--- a/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js
@@ -13,8 +13,8 @@
 import {ScanningBrowserProxyImpl} from 'chrome://scanning/scanning_browser_proxy.js';
 import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertArrayEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from '../../chai_assert.js';
-import {isVisible} from '../test_util.js';
+import {assertArrayEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
+import {isVisible} from 'chrome://webui-test/chromeos/test_util.js';
 
 import {changeSelect, createScanner, createScannerSource} from './scanning_app_test_utils.js';
 import {TestScanningBrowserProxy} from './test_scanning_browser_proxy.js';
diff --git a/chrome/test/data/webui/chromeos/scanning/scanning_app_test_utils.js b/chrome/test/data/webui/chromeos/scanning/scanning_app_test_utils.js
index 0a3ce99b..8344f2469 100644
--- a/chrome/test/data/webui/chromeos/scanning/scanning_app_test_utils.js
+++ b/chrome/test/data/webui/chromeos/scanning/scanning_app_test_utils.js
@@ -4,7 +4,7 @@
 import {alphabeticalCompare} from 'chrome://scanning/scanning_app_util.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 /**
  * @param {!Array} arr
diff --git a/chrome/test/data/webui/chromeos/scanning/source_select_test.js b/chrome/test/data/webui/chromeos/scanning/source_select_test.js
index 90edef7..123f78e 100644
--- a/chrome/test/data/webui/chromeos/scanning/source_select_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/source_select_test.js
@@ -7,7 +7,7 @@
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {getSourceTypeString} from 'chrome://scanning/scanning_app_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {assertOrderedAlphabetically, createScannerSource} from './scanning_app_test_utils.js';
 
diff --git a/chrome/test/data/webui/chromeos/scanning/test_scanning_browser_proxy.js b/chrome/test/data/webui/chromeos/scanning/test_scanning_browser_proxy.js
index 54eef1c..64451b5 100644
--- a/chrome/test/data/webui/chromeos/scanning/test_scanning_browser_proxy.js
+++ b/chrome/test/data/webui/chromeos/scanning/test_scanning_browser_proxy.js
@@ -4,8 +4,8 @@
 
 import {ScanningBrowserProxy, SelectedPath} from 'chrome://scanning/scanning_browser_proxy.js';
 
-import {assertEquals} from '../../chai_assert.js';
-import {TestBrowserProxy} from '../../test_browser_proxy.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
+import {TestBrowserProxy} from 'chrome://webui-test/chromeos/test_browser_proxy.js';
 
 const EMPTY_SELECTED_PATH = {
   baseName: '',
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/BUILD.gn b/chrome/test/data/webui/chromeos/shimless_rma/BUILD.gn
index 507d5aa..347b1513 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/shimless_rma/BUILD.gn
@@ -6,17 +6,18 @@
 
 js_type_check("closure_compile") {
   is_polymer3 = true
-  closure_flags =
-      default_closure_args + mojom_js_args + [
-        "browser_resolver_prefix_replacements=\"chrome://shimless-rma/=" +
-            rebase_path("//ash/webui/shimless_rma/resources/", root_build_dir) +
-            "\"",
-        "browser_resolver_prefix_replacements=\"chrome://webui-test/=" +
-            "./gen/chrome/test/data/webui/tsc\"",
-        "js_module_root=" +
-            rebase_path("//chrome/test/data/webui/", root_build_dir),
-        "js_module_root=./gen/chrome/test/data/webui/",
-      ]
+  closure_flags = default_closure_args + mojom_js_args + [
+                    "browser_resolver_prefix_replacements=\"chrome://shimless-rma/=" + rebase_path(
+                            "//ash/webui/shimless_rma/resources/",
+                            root_build_dir) + "\"",
+                    "browser_resolver_prefix_replacements=\"chrome://webui-test/chromeos/=" + rebase_path(
+                            "//chrome/test/data/webui/chromeos/",
+                            root_build_dir) + "\"",
+                    "browser_resolver_prefix_replacements=\"chrome://webui-test/=" + "./gen/chrome/test/data/webui/tsc\"",
+                    "js_module_root=" + rebase_path("//chrome/test/data/webui/",
+                                                    root_build_dir),
+                    "js_module_root=./gen/chrome/test/data/webui/",
+                  ]
   deps = [
     ":all_inputs_disabled_test",
     ":critical_error_page_test",
@@ -62,7 +63,7 @@
 
 js_library("critical_error_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:critical_error_page",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
@@ -72,7 +73,7 @@
 
 js_library("all_inputs_disabled_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:shimless_rma_types",
@@ -82,7 +83,7 @@
 
 js_library("fake_shimless_rma_service_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:shimless_rma_types",
   ]
@@ -91,7 +92,7 @@
 
 js_library("hardware_error_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:hardware_error_page",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
@@ -101,7 +102,7 @@
 
 js_library("shimless_rma_app_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/mojom:mojom_js_library_for_compile",
     "//ash/webui/shimless_rma/resources:fake_data",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
@@ -115,7 +116,7 @@
 
 js_library("onboarding_choose_destination_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:onboarding_choose_destination_page",
@@ -127,7 +128,7 @@
 
 js_library("onboarding_choose_wipe_device_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:onboarding_choose_wipe_device_page",
     "//ui/webui/resources/js:assert",
   ]
@@ -136,7 +137,7 @@
 
 js_library("onboarding_choose_wp_disable_method_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:onboarding_choose_wp_disable_method_page",
@@ -146,7 +147,7 @@
 
 js_library("onboarding_enter_rsu_wp_disable_code_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:onboarding_enter_rsu_wp_disable_code_page",
@@ -157,7 +158,7 @@
 
 js_library("onboarding_landing_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:onboarding_landing_page",
@@ -167,7 +168,7 @@
 
 js_library("onboarding_select_components_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:onboarding_select_components_page",
@@ -181,7 +182,7 @@
 
 js_library("onboarding_update_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:onboarding_update_page",
@@ -191,8 +192,8 @@
 
 js_library("onboarding_network_page_test") {
   deps = [
+    "..:chai_assert",
     "..:fake_network_config_mojom",
-    "../..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_data",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
@@ -203,7 +204,7 @@
 
 js_library("onboarding_wait_for_manual_wp_disable_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:onboarding_wait_for_manual_wp_disable_page",
@@ -214,7 +215,7 @@
 
 js_library("onboarding_wp_disable_complete_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:onboarding_wp_disable_complete_page",
@@ -225,7 +226,7 @@
 
 js_library("reboot_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:reboot_page",
@@ -235,7 +236,7 @@
 
 js_library("reimaging_firmware_update_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:reimaging_firmware_update_page",
@@ -245,7 +246,7 @@
 
 js_library("reimaging_device_information_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/mojom:mojom_js_library_for_compile",
     "//ash/webui/shimless_rma/resources:fake_data",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
@@ -257,7 +258,7 @@
 
 js_library("reimaging_calibration_failed_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:reimaging_calibration_failed_page",
@@ -268,7 +269,7 @@
 
 js_library("reimaging_calibration_run_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:reimaging_calibration_run_page",
@@ -279,7 +280,7 @@
 
 js_library("reimaging_calibration_setup_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:reimaging_calibration_setup_page",
@@ -289,7 +290,7 @@
 
 js_library("reimaging_provisioning_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:reimaging_provisioning_page",
@@ -299,7 +300,7 @@
 
 js_library("repair_component_chip_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:repair_component_chip",
   ]
   externs_list = [
@@ -315,7 +316,7 @@
 
 js_library("wrapup_finalize_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:wrapup_finalize_page",
   ]
   externs_list = [
@@ -326,7 +327,7 @@
 
 js_library("wrapup_repair_complete_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:fake_shimless_rma_service",
     "//ash/webui/shimless_rma/resources:mojo_interface_provider",
     "//ash/webui/shimless_rma/resources:wrapup_repair_complete_page",
@@ -340,7 +341,7 @@
 
 js_library("wrapup_restock_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:shimless_rma",
     "//ash/webui/shimless_rma/resources:wrapup_restock_page",
   ]
@@ -352,7 +353,7 @@
 
 js_library("wrapup_wait_for_manual_wp_enable_page_test") {
   deps = [
-    "../..:chai_assert",
+    "..:chai_assert",
     "//ash/webui/shimless_rma/resources:wrapup_wait_for_manual_wp_enable_page",
   ]
   externs_list = [
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/all_inputs_disabled_test.js b/chrome/test/data/webui/chromeos/shimless_rma/all_inputs_disabled_test.js
index 2f5f7c5..5e04f95fe 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/all_inputs_disabled_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/all_inputs_disabled_test.js
@@ -27,7 +27,7 @@
 import {WrapupRestockPage} from 'chrome://shimless-rma/wrapup_restock_page.js';
 import {WrapupWaitForManualWpEnablePage} from 'chrome://shimless-rma/wrapup_wait_for_manual_wp_enable_page.js';
 
-import {assertTrue} from '../../chai_assert.js';
+import {assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function allInputsDisabledTest() {
   const INPUT_TYPES =
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/critical_error_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/critical_error_page_test.js
index 0aa14425..79c03460 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/critical_error_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/critical_error_page_test.js
@@ -9,7 +9,7 @@
 import {ShimlessRma} from 'chrome://shimless-rma/shimless_rma.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function criticalErrorPageTest() {
   /**
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js b/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js
index a0b25f1..a3062c3 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js
@@ -6,7 +6,7 @@
 import {FakeShimlessRmaService} from 'chrome://shimless-rma/fake_shimless_rma_service.js';
 import {CalibrationComponentStatus, CalibrationObserverRemote, CalibrationOverallStatus, CalibrationSetupInstruction, CalibrationStatus, ComponentRepairStatus, ComponentType, ErrorObserverRemote, FinalizationError, FinalizationObserverRemote, FinalizationStatus, HardwareVerificationStatusObserverRemote, HardwareWriteProtectionStateObserverRemote, OsUpdateObserverRemote, OsUpdateOperation, PowerCableStateObserverRemote, ProvisioningError, ProvisioningObserverRemote, ProvisioningStatus, RmadErrorCode, ShutdownMethod, State, UpdateErrorCode, UpdateRoFirmwareObserverRemote, UpdateRoFirmwareStatus, WriteProtectDisableCompleteAction} from 'chrome://shimless-rma/shimless_rma_types.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function fakeShimlessRmaServiceTestSuite() {
   /** @type {?FakeShimlessRmaService} */
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/hardware_error_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/hardware_error_page_test.js
index e14de0d..152574b 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/hardware_error_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/hardware_error_page_test.js
@@ -11,7 +11,7 @@
 import {ShutdownMethod} from 'chrome://shimless-rma/shimless_rma_types.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 /** @type {number} */
 const ERROR_CODE = 1004;
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_choose_destination_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_choose_destination_page_test.js
index c3cb8a6..81e6736 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_choose_destination_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_choose_destination_page_test.js
@@ -8,7 +8,7 @@
 import {OnboardingChooseDestinationPageElement} from 'chrome://shimless-rma/onboarding_choose_destination_page.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function onboardingChooseDestinationPageTest() {
   /** @type {?OnboardingChooseDestinationPageElement} */
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_choose_wipe_device_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_choose_wipe_device_page_test.js
index 7464ce3..69867bf 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_choose_wipe_device_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_choose_wipe_device_page_test.js
@@ -9,7 +9,7 @@
 import {ShimlessRma} from 'chrome://shimless-rma/shimless_rma.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function onboardingChooseWipeDevicePageTest() {
   /** @type {?OnboardingChooseWipeDevicePage} */
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_choose_wp_disable_method_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_choose_wp_disable_method_page_test.js
index dc83408f..dfee3f30 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_choose_wp_disable_method_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_choose_wp_disable_method_page_test.js
@@ -8,7 +8,7 @@
 import {OnboardingChooseWpDisableMethodPage} from 'chrome://shimless-rma/onboarding_choose_wp_disable_method_page.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function onboardingChooseWpDisableMethodPageTest() {
   /** @type {?OnboardingChooseWpDisableMethodPage} */
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_enter_rsu_wp_disable_code_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_enter_rsu_wp_disable_code_page_test.js
index 6e495be..a9cf766 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_enter_rsu_wp_disable_code_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_enter_rsu_wp_disable_code_page_test.js
@@ -9,7 +9,7 @@
 import {OnboardingEnterRsuWpDisableCodePage} from 'chrome://shimless-rma/onboarding_enter_rsu_wp_disable_code_page.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertNotReached, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertNotReached, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 
 /**
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_landing_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_landing_page_test.js
index 28604b57..a0552941 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_landing_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_landing_page_test.js
@@ -10,7 +10,7 @@
 import {State} from 'chrome://shimless-rma/shimless_rma_types.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../../test_util.js';
 
 
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_network_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_network_page_test.js
index 85143283..3273887 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_network_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_network_page_test.js
@@ -10,7 +10,7 @@
 import {OnboardingNetworkPage} from 'chrome://shimless-rma/onboarding_network_page.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {FakeNetworkConfig} from '../fake_network_config_mojom.js';
 
 export function onboardingNetworkPageTest() {
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_select_components_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_select_components_page_test.js
index 2036b67..352c4c9c 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_select_components_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_select_components_page_test.js
@@ -12,7 +12,7 @@
 import {Component, ComponentRepairStatus} from 'chrome://shimless-rma/shimless_rma_types.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function onboardingSelectComponentsPageTest() {
   /**
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_update_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_update_page_test.js
index f09bcd4..fca325d3 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_update_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_update_page_test.js
@@ -10,7 +10,7 @@
 import {OsUpdateOperation, UpdateErrorCode} from 'chrome://shimless-rma/shimless_rma_types.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../../test_util.js';
 
 export function onboardingUpdatePageTest() {
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_wait_for_manual_wp_disable_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_wait_for_manual_wp_disable_page_test.js
index 485c874..3784e359 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_wait_for_manual_wp_disable_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_wait_for_manual_wp_disable_page_test.js
@@ -9,7 +9,7 @@
 import {OnboardingWaitForManualWpDisablePage} from 'chrome://shimless-rma/onboarding_wait_for_manual_wp_disable_page.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 /**
  * It is not possible to suppress visibility inline so this helper
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_wp_disable_complete_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_wp_disable_complete_page_test.js
index f784c15..8108189 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_wp_disable_complete_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_wp_disable_complete_page_test.js
@@ -10,7 +10,7 @@
 import {WriteProtectDisableCompleteAction} from 'chrome://shimless-rma/shimless_rma_types.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 
 export function onboardingWpDisableCompletePageTest() {
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/reboot_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/reboot_page_test.js
index 174e3e3..bec6f47 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/reboot_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/reboot_page_test.js
@@ -8,7 +8,7 @@
 import {RebootPage} from 'chrome://shimless-rma/reboot_page.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function rebootPageTest() {
   /** @type {?RebootPage} */
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_failed_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_failed_page_test.js
index ac674496..4d124d5 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_failed_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_failed_page_test.js
@@ -12,7 +12,7 @@
 import {CalibrationComponentStatus, CalibrationStatus, ComponentType} from 'chrome://shimless-rma/shimless_rma_types.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertNotEquals, assertNotReached, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertNotEquals, assertNotReached, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function reimagingCalibrationFailedPageTest() {
   /**
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_run_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_run_page_test.js
index ea09653..7950db4 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_run_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_run_page_test.js
@@ -11,7 +11,7 @@
 import {CalibrationOverallStatus, CalibrationStatus, ComponentType} from 'chrome://shimless-rma/shimless_rma_types.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function reimagingCalibrationRunPageTest() {
   /**
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_setup_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_setup_page_test.js
index e0d2da3..882a921 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_setup_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_setup_page_test.js
@@ -10,7 +10,7 @@
 import {CalibrationComponentStatus, CalibrationSetupInstruction, CalibrationStatus, ComponentType} from 'chrome://shimless-rma/shimless_rma_types.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function reimagingCalibrationSetupPageTest() {
   /** @type {?ReimagingCalibrationSetupPage} */
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_device_information_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_device_information_page_test.js
index bc57ec16..8854f87 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_device_information_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_device_information_page_test.js
@@ -9,7 +9,7 @@
 import {ReimagingDeviceInformationPage} from 'chrome://shimless-rma/reimaging_device_information_page.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 const fakeSerialNumber = 'serial# 0001';
 const fakeDramPartNumber = 'dram# 0123';
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_firmware_update_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_firmware_update_page_test.js
index 41d2e71..89e6990 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_firmware_update_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_firmware_update_page_test.js
@@ -11,7 +11,7 @@
 import {UpdateRoFirmwareStatus} from 'chrome://shimless-rma/shimless_rma_types.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function reimagingFirmwareUpdatePageTest() {
   /**
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_provisioning_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_provisioning_page_test.js
index a3388e5f..e42a8423 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_provisioning_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_provisioning_page_test.js
@@ -10,7 +10,7 @@
 import {ProvisioningError, ProvisioningStatus, RmadErrorCode} from 'chrome://shimless-rma/shimless_rma_types.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function reimagingProvisioningPageTest() {
   /**
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/repair_component_chip_test.js b/chrome/test/data/webui/chromeos/shimless_rma/repair_component_chip_test.js
index 54c06a8..37f49c6 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/repair_component_chip_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/repair_component_chip_test.js
@@ -5,7 +5,7 @@
 import {RepairComponentChip} from 'chrome://shimless-rma/repair_component_chip.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../../test_util.js';
 
 export function repairComponentChipTest() {
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_app_test.js b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_app_test.js
index bca5396..3120ddb 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_app_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_app_test.js
@@ -12,7 +12,7 @@
 import {disableAllButtons, enableAllButtons} from 'chrome://shimless-rma/shimless_rma_util.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {eventToPromise, isVisible} from '../../test_util.js';
 
 export function shimlessRMAAppTest() {
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_finalize_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_finalize_page_test.js
index 842e7a6..ed3d809 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_finalize_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_finalize_page_test.js
@@ -10,7 +10,7 @@
 import {FINALIZATION_ERROR_CODE_PREFIX, WrapupFinalizePage} from 'chrome://shimless-rma/wrapup_finalize_page.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function wrapupFinalizePageTest() {
   /**
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_repair_complete_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_repair_complete_page_test.js
index 7547adf..b4b45e60 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_repair_complete_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_repair_complete_page_test.js
@@ -11,7 +11,7 @@
 import {WrapupRepairCompletePage} from 'chrome://shimless-rma/wrapup_repair_complete_page.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {isVisible} from '../../test_util.js';
 
 export function wrapupRepairCompletePageTest() {
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_restock_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_restock_page_test.js
index 8d00787..b8e364d 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_restock_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_restock_page_test.js
@@ -9,7 +9,7 @@
 import {WrapupRestockPage} from 'chrome://shimless-rma/wrapup_restock_page.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function wrapupRestockPageTest() {
   /**
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_wait_for_manual_wp_enable_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_wait_for_manual_wp_enable_page_test.js
index 8b61b7e55..d5eb1e2 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_wait_for_manual_wp_enable_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_wait_for_manual_wp_enable_page_test.js
@@ -9,7 +9,7 @@
 import {WrapupWaitForManualWpEnablePage} from 'chrome://shimless-rma/wrapup_wait_for_manual_wp_enable_page.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function wrapupWaitForManualWpEnablePageTest() {
   /**
diff --git a/chrome/test/data/webui/test_browser_proxy.js b/chrome/test/data/webui/chromeos/test_browser_proxy.js
similarity index 100%
rename from chrome/test/data/webui/test_browser_proxy.js
rename to chrome/test/data/webui/chromeos/test_browser_proxy.js
diff --git a/chrome/test/data/webui/color_provider_css_colors_test.ts b/chrome/test/data/webui/color_provider_css_colors_test.ts
index 4ac7d77..20a609e 100644
--- a/chrome/test/data/webui/color_provider_css_colors_test.ts
+++ b/chrome/test/data/webui/color_provider_css_colors_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 {assertEquals, assertNotEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertNotEquals} from './chai_assert.js';
 
 suite('ColorProviderCSSColorsTest', function() {
   let link: HTMLLinkElement;
diff --git a/chrome/test/data/webui/color_provider_css_colors_test_chromeos.ts b/chrome/test/data/webui/color_provider_css_colors_test_chromeos.ts
index b65c45a..f8c5347 100644
--- a/chrome/test/data/webui/color_provider_css_colors_test_chromeos.ts
+++ b/chrome/test/data/webui/color_provider_css_colors_test_chromeos.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 {assertNotEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertNotEquals} from './chai_assert.js';
 
 suite('ColorProviderCSSColorsTest', function() {
   let link: HTMLLinkElement;
diff --git a/chrome/test/data/webui/commander/commander_app_test.ts b/chrome/test/data/webui/commander/commander_app_test.ts
index cc3414f..c25d010 100644
--- a/chrome/test/data/webui/commander/commander_app_test.ts
+++ b/chrome/test/data/webui/commander/commander_app_test.ts
@@ -11,7 +11,7 @@
 import {keyDownOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertDeepEquals, assertEquals, assertGT, assertNotEquals, assertTrue} from '../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertGT, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
 
 import {TestCommanderBrowserProxy} from './test_commander_browser_proxy.js';
 
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/BUILD.gn b/chrome/test/data/webui/cr_components/chromeos/bluetooth/BUILD.gn
index 66ea10c..4a6afcc4 100644
--- a/chrome/test/data/webui/cr_components/chromeos/bluetooth/BUILD.gn
+++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/BUILD.gn
@@ -39,7 +39,7 @@
 js_library("bluetooth_pairing_ui_test") {
   deps = [
     ":fake_bluetooth_config",
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//ash/webui/common/resources/bluetooth:bluetooth_pairing_ui",
     "//chromeos/ash/services/bluetooth_config/public/mojom:mojom_webui_js",
   ]
@@ -48,7 +48,7 @@
 
 js_library("bluetooth_icon_test") {
   deps = [
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//ash/webui/common/resources/bluetooth:bluetooth_icon",
     "//chromeos/ash/services/bluetooth_config/public/mojom:mojom_webui_js",
   ]
@@ -57,7 +57,7 @@
 
 js_library("bluetooth_base_page_test") {
   deps = [
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//ash/webui/common/resources/bluetooth:bluetooth_base_page",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -65,7 +65,7 @@
 
 js_library("bluetooth_battery_icon_percentage_tests") {
   deps = [
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//ash/webui/common/resources/bluetooth:bluetooth_battery_icon_percentage",
     "//chromeos/ash/services/bluetooth_config/public/mojom:mojom_webui_js",
   ]
@@ -74,7 +74,7 @@
 
 js_library("bluetooth_device_battery_info_tests") {
   deps = [
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//ash/webui/common/resources/bluetooth:bluetooth_device_battery_info",
     "//chromeos/ash/services/bluetooth_config/public/mojom:mojom_webui_js",
   ]
@@ -83,7 +83,7 @@
 
 js_library("bluetooth_pairing_device_item_test") {
   deps = [
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//ash/webui/common/resources/bluetooth:bluetooth_pairing_device_item",
     "//ash/webui/common/resources/bluetooth:bluetooth_types",
   ]
@@ -95,7 +95,7 @@
 
 js_library("bluetooth_pairing_device_selection_page_test") {
   deps = [
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//ash/webui/common/resources/bluetooth:bluetooth_pairing_device_selection_page",
     "//ash/webui/common/resources/bluetooth:bluetooth_types",
     "//chromeos/ash/services/bluetooth_config/public/mojom:mojom_webui_js",
@@ -105,7 +105,7 @@
 
 js_library("bluetooth_pairing_request_code_page_test") {
   deps = [
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//ash/webui/common/resources/bluetooth:bluetooth_pairing_request_code_page",
     "//ash/webui/common/resources/bluetooth:bluetooth_types",
     "//chromeos/ash/services/bluetooth_config/public/mojom:mojom_webui_js",
@@ -119,7 +119,7 @@
 js_library("bluetooth_pairing_enter_code_page_test") {
   deps = [
     ":fake_bluetooth_config",
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//ash/webui/common/resources/bluetooth:bluetooth_pairing_enter_code_page",
     "//chromeos/ash/services/bluetooth_config/public/mojom:mojom_webui_js",
   ]
@@ -128,7 +128,7 @@
 
 js_library("bluetooth_pairing_confirm_code_page_test") {
   deps = [
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//ash/webui/common/resources/bluetooth:bluetooth_pairing_confirm_code_page",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -136,7 +136,7 @@
 
 js_library("bluetooth_spinner_page_test") {
   deps = [
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//ash/webui/common/resources/bluetooth:bluetooth_spinner_page",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -144,7 +144,7 @@
 
 js_library("fake_bluetooth_config") {
   deps = [
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//chromeos/ash/services/bluetooth_config/public/mojom:mojom_webui_js",
   ]
 }
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_base_page_test.js b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_base_page_test.js
index 4d07b52..108201a3 100644
--- a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_base_page_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_base_page_test.js
@@ -10,7 +10,7 @@
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from '../../../chromeos/chai_assert.js';
 import {eventToPromise} from '../../../chromeos/test_util.js';
 
 suite('CrComponentsBluetoothBasePageTest', function() {
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_battery_icon_percentage_tests.js b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_battery_icon_percentage_tests.js
index 485715a..5f337a5 100644
--- a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_battery_icon_percentage_tests.js
+++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_battery_icon_percentage_tests.js
@@ -9,7 +9,7 @@
 import {BluetoothDeviceProperties, DeviceConnectionState} from 'chrome://resources/mojo/chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-webui.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertEquals, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertTrue} from '../../../chromeos/chai_assert.js';
 
 import {createDefaultBluetoothDevice} from './fake_bluetooth_config.js';
 
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_device_battery_info_tests.js b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_device_battery_info_tests.js
index ef6197f..c8740e1 100644
--- a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_device_battery_info_tests.js
+++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_device_battery_info_tests.js
@@ -8,7 +8,7 @@
 import {BluetoothDeviceProperties, DeviceConnectionState} from 'chrome://resources/mojo/chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-webui.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertFalse, assertTrue} from '../../../chai_assert.js';
+import {assertFalse, assertTrue} from '../../../chromeos/chai_assert.js';
 
 import {createDefaultBluetoothDevice} from './fake_bluetooth_config.js';
 
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_icon_test.js b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_icon_test.js
index 3bc5193..1acff92 100644
--- a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_icon_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_icon_test.js
@@ -6,7 +6,7 @@
 import {AudioOutputCapability, BluetoothDeviceProperties, DeviceConnectionState, DeviceType} from 'chrome://resources/mojo/chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-webui.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from '../../../chromeos/chai_assert.js';
 
 import {createDefaultBluetoothDevice} from './fake_bluetooth_config.js';
 
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_confirm_code_page_test.js b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_confirm_code_page_test.js
index cb8bec4c..cd1692d 100644
--- a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_confirm_code_page_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_confirm_code_page_test.js
@@ -7,7 +7,7 @@
 
 import {SettingsBluetoothPairingConfirmCodePageElement} from 'chrome://resources/ash/common/bluetooth/bluetooth_pairing_confirm_code_page.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {assertEquals, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertTrue} from '../../../chromeos/chai_assert.js';
 import {eventToPromise} from '../../../chromeos/test_util.js';
 
 suite('CrComponentsBluetoothPairingConfirmCodePageTest', function() {
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_device_item_test.js b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_device_item_test.js
index b8a6fb19..64d1fba 100644
--- a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_device_item_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_device_item_test.js
@@ -9,7 +9,7 @@
 import {AudioOutputCapability, DeviceConnectionState, DeviceType} from 'chrome://resources/mojo/chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-webui.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertEquals, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertTrue} from '../../../chromeos/chai_assert.js';
 import {eventToPromise} from '../../../chromeos/test_util.js';
 
 import {createDefaultBluetoothDevice} from './fake_bluetooth_config.js';
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_device_selection_page_test.js b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_device_selection_page_test.js
index 187f2c99..7cb8d1c 100644
--- a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_device_selection_page_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_device_selection_page_test.js
@@ -11,7 +11,7 @@
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from '../../../chromeos/chai_assert.js';
 
 import {createDefaultBluetoothDevice, FakeBluetoothConfig} from './fake_bluetooth_config.js';
 import {FakeBluetoothDiscoveryDelegate} from './fake_bluetooth_discovery_delegate.js';
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_enter_code_page_test.js b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_enter_code_page_test.js
index 90c26a2..558db22b0 100644
--- a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_enter_code_page_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_enter_code_page_test.js
@@ -7,7 +7,7 @@
 import {SettingsBluetoothPairingEnterCodeElement} from 'chrome://resources/ash/common/bluetooth/bluetooth_pairing_enter_code_page.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertEquals, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertTrue} from '../../../chromeos/chai_assert.js';
 
 suite('CrComponentsBluetoothPairingEnterCodePageTest', function() {
   /** @type {?SettingsBluetoothPairingEnterCodeElement} */
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_request_code_page_test.js b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_request_code_page_test.js
index a0de038..57c2311 100644
--- a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_request_code_page_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_request_code_page_test.js
@@ -11,7 +11,7 @@
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertTrue} from '../../../chromeos/chai_assert.js';
 import {eventToPromise} from '../../../chromeos/test_util.js';
 
 import {createDefaultBluetoothDevice} from './fake_bluetooth_config.js';
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_ui_test.js b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_ui_test.js
index 9b47011..9ac7713 100644
--- a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_ui_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_ui_test.js
@@ -15,7 +15,7 @@
 import {AudioOutputCapability, BluetoothDeviceProperties, BluetoothSystemState, DeviceConnectionState, DeviceType} from 'chrome://resources/mojo/chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-webui.js';
 import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from '../../../chromeos/chai_assert.js';
 import {eventToPromise} from '../../../chromeos/test_util.js';
 
 import {createDefaultBluetoothDevice, FakeBluetoothConfig} from './fake_bluetooth_config.js';
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_spinner_page_test.js b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_spinner_page_test.js
index 9b2551b..acc9b39 100644
--- a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_spinner_page_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_spinner_page_test.js
@@ -6,7 +6,7 @@
 
 import {SettingsBluetoothSpinnerPageElement} from 'chrome://resources/ash/common/bluetooth/bluetooth_spinner_page.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {assertTrue} from '../../../chai_assert.js';
+import {assertTrue} from '../../../chromeos/chai_assert.js';
 
 suite('CrComponentsBluetoothSpinnerPageTest', function() {
   /** @type {?SettingsBluetoothSpinnerPageElement} */
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/fake_bluetooth_config.js b/chrome/test/data/webui/cr_components/chromeos/bluetooth/fake_bluetooth_config.js
index 7bd6d6ae..077db22 100644
--- a/chrome/test/data/webui/cr_components/chromeos/bluetooth/fake_bluetooth_config.js
+++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/fake_bluetooth_config.js
@@ -5,7 +5,7 @@
 import {stringToMojoString16} from 'chrome://resources/ash/common/bluetooth/bluetooth_utils.js';
 import {AudioOutputCapability, BluetoothDeviceProperties, BluetoothDeviceStatusObserverInterface, BluetoothDiscoveryDelegateInterface, BluetoothModificationState, BluetoothSystemProperties, BluetoothSystemState, CrosBluetoothConfigInterface, DeviceConnectionState, DevicePairingHandlerReceiver, DeviceType, DiscoverySessionStatusObserverInterface, PairedBluetoothDeviceProperties, SystemPropertiesObserverInterface} from 'chrome://resources/mojo/chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-webui.js';
 
-import {assertFalse, assertNotReached, assertTrue} from '../../../chai_assert.js';
+import {assertFalse, assertNotReached, assertTrue} from '../../../chromeos/chai_assert.js';
 
 import {FakeDevicePairingHandler} from './fake_device_pairing_handler.js';
 
diff --git a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/activation_code_page_test.js b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/activation_code_page_test.js
index bff5f1dc..8422f17 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/activation_code_page_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/activation_code_page_test.js
@@ -9,7 +9,7 @@
 import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 import {eventToPromise} from 'chrome://webui-test/test_util.js';
 
-import {assertTrue} from '../../../chai_assert.js';
+import {assertTrue} from '../../../chromeos/chai_assert.js';
 
 import {FakeBarcodeDetector, FakeImageCapture} from './fake_barcode_detector.js';
 import {FakeMediaDevices} from './fake_media_devices.js';
diff --git a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/button_bar_test.js b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/button_bar_test.js
index 3d5c47fb..a50e88d 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/button_bar_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/button_bar_test.js
@@ -8,7 +8,7 @@
 import {ButtonBarState, ButtonState} from 'chrome://resources/ash/common/cellular_setup/cellular_types.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertEquals, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertTrue} from '../../../chromeos/chai_assert.js';
 
 suite('CellularSetupButtonBarTest', function() {
   /** @type {!ButtonBarElement} */
diff --git a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/cellular_eid_dialog_test.js b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/cellular_eid_dialog_test.js
index b81df8595..b880416 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/cellular_eid_dialog_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/cellular_eid_dialog_test.js
@@ -8,7 +8,7 @@
 import {setESimManagerRemoteForTesting} from 'chrome://resources/ash/common/cellular_setup/mojo_interface_provider.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertDeepEquals, assertEquals, assertTrue} from '../../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertTrue} from '../../../chromeos/chai_assert.js';
 
 import {FakeCanvasContext} from './fake_canvas_context.js';
 import {FakeESimManagerRemote} from './fake_esim_manager_remote.js';
diff --git a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/cellular_setup_test.js b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/cellular_setup_test.js
index 56c9dea..e58e845 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/cellular_setup_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/cellular_setup_test.js
@@ -14,7 +14,7 @@
 import {FakeNetworkConfig} from 'chrome://test/chromeos/fake_network_config_mojom.js';
 import {FakeESimManagerRemote} from 'chrome://test/cr_components/chromeos/cellular_setup/fake_esim_manager_remote.js';
 
-import {assertFalse, assertTrue} from '../../../chai_assert.js';
+import {assertFalse, assertTrue} from '../../../chromeos/chai_assert.js';
 
 import {FakeCellularSetupDelegate} from './fake_cellular_setup_delegate.js';
 
diff --git a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/confirmation_code_page_test.js b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/confirmation_code_page_test.js
index 1dc7483..5f2dfb8 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/confirmation_code_page_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/confirmation_code_page_test.js
@@ -7,7 +7,7 @@
 
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertTrue} from '../../../chai_assert.js';
+import {assertTrue} from '../../../chromeos/chai_assert.js';
 
 suite('CrComponentsConfirmationCodePageTest', function() {
   let confirmationCodePage;
diff --git a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/esim_flow_ui_test.js b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/esim_flow_ui_test.js
index 6705cadb..fef5b38 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/esim_flow_ui_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/esim_flow_ui_test.js
@@ -15,7 +15,7 @@
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {FakeNetworkConfig} from 'chrome://test/chromeos/fake_network_config_mojom.js';
 
-import {assertEquals, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertTrue} from '../../../chromeos/chai_assert.js';
 
 import {FakeBarcodeDetector, FakeImageCapture} from './fake_barcode_detector.js';
 import {FakeCellularSetupDelegate} from './fake_cellular_setup_delegate.js';
diff --git a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/final_page_test.js b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/final_page_test.js
index 4845048..aaeb9af7 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/final_page_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/final_page_test.js
@@ -6,7 +6,7 @@
 
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertTrue} from '../../../chai_assert.js';
+import {assertTrue} from '../../../chromeos/chai_assert.js';
 
 import {FakeCellularSetupDelegate} from './fake_cellular_setup_delegate.js';
 
diff --git a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/provisioning_page_test.js b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/provisioning_page_test.js
index 5ddd0a6f..a64850f 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/provisioning_page_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/provisioning_page_test.js
@@ -7,7 +7,7 @@
 
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertTrue} from '../../../chai_assert.js';
+import {assertTrue} from '../../../chromeos/chai_assert.js';
 
 import {FakeCellularSetupDelegate} from './fake_cellular_setup_delegate.js';
 
diff --git a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/psim_flow_ui_test.js b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/psim_flow_ui_test.js
index fb30fa3..4f98d6d 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/psim_flow_ui_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/psim_flow_ui_test.js
@@ -12,7 +12,7 @@
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {eventToPromise} from 'chrome://webui-test/test_util.js';
 
-import {assertTrue} from '../../../chai_assert.js';
+import {assertTrue} from '../../../chromeos/chai_assert.js';
 
 import {FakeCellularSetupDelegate} from './fake_cellular_setup_delegate.js';
 import {FakeCarrierPortalHandlerRemote, FakeCellularSetupRemote} from './fake_cellular_setup_remote.js';
diff --git a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/setup_loading_page_test.js b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/setup_loading_page_test.js
index 66956f0..f7f5f2e 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/setup_loading_page_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/setup_loading_page_test.js
@@ -7,7 +7,7 @@
 
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertFalse, assertTrue} from '../../../chai_assert.js';
+import {assertFalse, assertTrue} from '../../../chromeos/chai_assert.js';
 
 suite('CrComponentsSetupLoadingPageTest', function() {
   let setupLoadingPage;
diff --git a/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/setup_succeeded_page_test.js b/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/setup_succeeded_page_test.js
index 292667f5..308a16b 100644
--- a/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/setup_succeeded_page_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/setup_succeeded_page_test.js
@@ -12,7 +12,7 @@
 
 import {BrowserProxyImpl} from 'chrome://resources/ash/common/multidevice_setup/multidevice_setup_browser_proxy.js';
 
-import {TestBrowserProxy} from '../../../test_browser_proxy.js';
+import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
 
 /**
  * @implements {BrowserProxy}
diff --git a/chrome/test/data/webui/cr_components/chromeos/network/apn_list_item_test.js b/chrome/test/data/webui/cr_components/chromeos/network/apn_list_item_test.js
index 99800e1..4c23d8a 100644
--- a/chrome/test/data/webui/cr_components/chromeos/network/apn_list_item_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/network/apn_list_item_test.js
@@ -9,7 +9,7 @@
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
 
 suite('ApnListTest', function() {
   /** @type {ApnListItemElement} */
diff --git a/chrome/test/data/webui/cr_components/chromeos/network/apn_list_test.js b/chrome/test/data/webui/cr_components/chromeos/network/apn_list_test.js
index b914312e..6ded077 100644
--- a/chrome/test/data/webui/cr_components/chromeos/network/apn_list_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/network/apn_list_test.js
@@ -8,7 +8,7 @@
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 
 suite('ApnListTest', function() {
   /** @type {ApnListElement} */
diff --git a/chrome/test/data/webui/cr_components/chromeos/network_health/BUILD.gn b/chrome/test/data/webui/cr_components/chromeos/network_health/BUILD.gn
index 91ebeaa..9b21efac 100644
--- a/chrome/test/data/webui/cr_components/chromeos/network_health/BUILD.gn
+++ b/chrome/test/data/webui/cr_components/chromeos/network_health/BUILD.gn
@@ -24,7 +24,7 @@
   deps = [
     ":fake_network_diagnostics_routines",
     ":network_health_test_utils",
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//ash/webui/common/resources/network_health:mojo_interface_provider",
     "//ash/webui/common/resources/network_health:network_diagnostics",
     "//chromeos/services/network_health/public/mojom:mojom_webui_js",
@@ -36,7 +36,7 @@
 js_library("routine_group_test") {
   deps = [
     ":network_health_test_utils",
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//ash/webui/common/resources/network_health:network_diagnostics",
     "//chromeos/services/network_health/public/mojom:mojom_webui_js",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
@@ -54,8 +54,9 @@
 js_library("fake_network_diagnostics_routines") {
   deps = [
     ":network_health_test_utils",
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//ash/webui/common/resources/network_health:network_diagnostics",
     "//chromeos/services/network_health/public/mojom:mojom_webui_js",
+    "//ui/webui/resources/js:assert",
   ]
 }
diff --git a/chrome/test/data/webui/cr_components/chromeos/network_health/fake_network_diagnostics_routines.js b/chrome/test/data/webui/cr_components/chromeos/network_health/fake_network_diagnostics_routines.js
index a129950..e97abd35 100644
--- a/chrome/test/data/webui/cr_components/chromeos/network_health/fake_network_diagnostics_routines.js
+++ b/chrome/test/data/webui/cr_components/chromeos/network_health/fake_network_diagnostics_routines.js
@@ -4,7 +4,7 @@
 
 import {NetworkDiagnosticsRoutinesInterface, RoutineResult, RoutineVerdict} from 'chrome://resources/mojo/chromeos/services/network_health/public/mojom/network_diagnostics.mojom-webui.js';
 
-import {assertNotReached} from '../../../chai_assert.js';
+import {assertNotReached} from '../../../chromeos/chai_assert.js';
 
 import {createResult} from './network_health_test_utils.js';
 
diff --git a/chrome/test/data/webui/cr_components/chromeos/network_health/network_diagnostics_test.js b/chrome/test/data/webui/cr_components/chromeos/network_health/network_diagnostics_test.js
index 2ccbf92d..e1655d54 100644
--- a/chrome/test/data/webui/cr_components/chromeos/network_health/network_diagnostics_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/network_health/network_diagnostics_test.js
@@ -10,7 +10,7 @@
 import {RoutineVerdict} from 'chrome://resources/mojo/chromeos/services/network_health/public/mojom/network_diagnostics.mojom-webui.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertGT, assertNotReached, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertFalse, assertGT, assertNotReached, assertTrue} from '../../../chromeos/chai_assert.js';
 import {isVisible} from '../../../chromeos/test_util.js';
 
 import {FakeNetworkDiagnostics} from './fake_network_diagnostics_routines.js';
diff --git a/chrome/test/data/webui/cr_components/chromeos/network_health/routine_group_test.js b/chrome/test/data/webui/cr_components/chromeos/network_health/routine_group_test.js
index b074d0cf..c680f5f5 100644
--- a/chrome/test/data/webui/cr_components/chromeos/network_health/routine_group_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/network_health/routine_group_test.js
@@ -9,7 +9,7 @@
 import {RoutineVerdict} from 'chrome://resources/mojo/chromeos/services/network_health/public/mojom/network_diagnostics.mojom-webui.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from '../../../chromeos/chai_assert.js';
 
 import {createResult, getIconFromSrc} from './network_health_test_utils.js';
 
diff --git a/chrome/test/data/webui/cr_components/chromeos/traffic_counters/BUILD.gn b/chrome/test/data/webui/cr_components/chromeos/traffic_counters/BUILD.gn
index d36a6894..8751b4c 100644
--- a/chrome/test/data/webui/cr_components/chromeos/traffic_counters/BUILD.gn
+++ b/chrome/test/data/webui/cr_components/chromeos/traffic_counters/BUILD.gn
@@ -20,7 +20,7 @@
 
 js_library("traffic_counters_test") {
   deps = [
-    "../../..:chai_assert",
+    "../../../chromeos:chai_assert",
     "//ash/webui/common/resources:i18n_behavior",
     "//ash/webui/common/resources/network:mojo_interface_provider",
     "//ash/webui/common/resources/network:onc_mojo",
diff --git a/chrome/test/data/webui/cr_components/chromeos/traffic_counters/traffic_counters_test.js b/chrome/test/data/webui/cr_components/chromeos/traffic_counters/traffic_counters_test.js
index 459e168..43450b6 100644
--- a/chrome/test/data/webui/cr_components/chromeos/traffic_counters/traffic_counters_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/traffic_counters/traffic_counters_test.js
@@ -11,7 +11,7 @@
 import {Time} from 'chrome://resources/mojo/mojo/public/mojom/base/time.mojom-webui.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertEquals, assertTrue} from '../../../chai_assert.js';
+import {assertEquals, assertTrue} from '../../../chromeos/chai_assert.js';
 import {FakeNetworkConfig} from '../../../chromeos/fake_network_config_mojom.js';
 
 suite('TrafficCountersTest', function() {
diff --git a/chrome/test/data/webui/cr_components/help_bubble_mixin_test.ts b/chrome/test/data/webui/cr_components/help_bubble_mixin_test.ts
index f197c731..fd1da38 100644
--- a/chrome/test/data/webui/cr_components/help_bubble_mixin_test.ts
+++ b/chrome/test/data/webui/cr_components/help_bubble_mixin_test.ts
@@ -8,6 +8,7 @@
 import {IronIconElement} from '//resources/polymer/v3_0/iron-icon/iron-icon.js';
 import {HelpBubbleElement} from 'chrome://resources/cr_components/help_bubble/help_bubble.js';
 import {HelpBubbleArrowPosition, HelpBubbleClientCallbackRouter, HelpBubbleClientRemote, HelpBubbleClosedReason, HelpBubbleHandlerInterface, HelpBubbleParams} from 'chrome://resources/cr_components/help_bubble/help_bubble.mojom-webui.js';
+import {HelpBubbleController} from 'chrome://resources/cr_components/help_bubble/help_bubble_controller.js';
 import {HelpBubbleMixin, HelpBubbleMixinInterface} from 'chrome://resources/cr_components/help_bubble/help_bubble_mixin.js';
 import {HelpBubbleProxy, HelpBubbleProxyImpl} from 'chrome://resources/cr_components/help_bubble/help_bubble_proxy.js';
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
@@ -38,6 +39,10 @@
   };
 }
 
+let titleBubble: HelpBubbleController;
+let p1Bubble: HelpBubbleController;
+let bulletListBubble: HelpBubbleController;
+
 export class HelpBubbleMixinTestElement extends HelpBubbleMixinTestElementBase {
   static get is() {
     return 'help-bubble-mixin-test-element';
@@ -57,15 +62,10 @@
 
   override connectedCallback() {
     super.connectedCallback();
-    this.registerHelpBubbleIdentifier(TITLE_NATIVE_ID, 'title');
-    this.registerHelpBubbleIdentifier(PARAGRAPH_NATIVE_ID, 'p1');
-    this.registerHelpBubbleIdentifier(LIST_NATIVE_ID, 'bulletList');
-  }
-
-
-  getHelpBubbleFor(anchorId: string): HelpBubbleElement|null {
-    return this.shadowRoot!.querySelector(
-        `help-bubble[anchor-id='${anchorId}']`);
+    titleBubble = this.registerHelpBubbleIdentifier(TITLE_NATIVE_ID, 'title');
+    p1Bubble = this.registerHelpBubbleIdentifier(PARAGRAPH_NATIVE_ID, 'p1');
+    bulletListBubble =
+        this.registerHelpBubbleIdentifier(LIST_NATIVE_ID, 'bulletList');
   }
 }
 
@@ -235,50 +235,54 @@
 
   test('help bubble mixin shows bubble when called directly', () => {
     assertFalse(container.isHelpBubbleShowing());
-    assertFalse(container.isHelpBubbleShowingFor('p1'));
-    container.showHelpBubble('p1', defaultParams);
+    assertFalse(container.isHelpBubbleShowingForTesting('p1'));
+    container.showHelpBubble(p1Bubble, defaultParams);
     assertTrue(container.isHelpBubbleShowing());
-    assertTrue(container.isHelpBubbleShowingFor('p1'));
+    assertTrue(container.isHelpBubbleShowingForTesting('p1'));
   });
 
   test('help bubble mixin reports not open for other elements', () => {
     // Valid but not open.
-    assertFalse(container.isHelpBubbleShowingFor('title'));
+    assertFalse(container.isHelpBubbleShowingForTesting('title'));
     // Not valid (and not open).
-    assertFalse(container.isHelpBubbleShowingFor('foo'));
+    assertFalse(container.isHelpBubbleShowingForTesting('foo'));
   });
 
   test('help bubble mixin hides bubble when called directly', () => {
-    container.showHelpBubble('p1', defaultParams);
-    assertTrue(container.hideHelpBubble('p1'));
+    container.showHelpBubble(p1Bubble, defaultParams);
+    // @ts-ignore - accessing private member for test
+    assertTrue(container.hideHelpBubble(p1Bubble.nativeId_));
     assertFalse(container.isHelpBubbleShowing());
   });
 
   test('help bubble mixin called directly doesn\'t hide wrong bubble', () => {
-    container.showHelpBubble('p1', defaultParams);
-    assertFalse(container.hideHelpBubble('title'));
+    container.showHelpBubble(p1Bubble, defaultParams);
+    // @ts-ignore - accessing private member for test
+    assertFalse(container.hideHelpBubble(titleBubble.nativeId_));
     assertTrue(container.isHelpBubbleShowing());
   });
 
   test('help bubble mixin show and hide multiple bubbles directly', () => {
-    container.showHelpBubble('p1', defaultParams);
-    assertTrue(container.isHelpBubbleShowingFor('p1'));
-    assertFalse(container.isHelpBubbleShowingFor('title'));
+    container.showHelpBubble(p1Bubble, defaultParams);
+    assertTrue(container.isHelpBubbleShowingForTesting('p1'));
+    assertFalse(container.isHelpBubbleShowingForTesting('title'));
     assertTrue(container.isHelpBubbleShowing());
 
-    container.showHelpBubble('title', defaultParams);
-    assertTrue(container.isHelpBubbleShowingFor('p1'));
-    assertTrue(container.isHelpBubbleShowingFor('title'));
+    container.showHelpBubble(titleBubble, defaultParams);
+    assertTrue(container.isHelpBubbleShowingForTesting('p1'));
+    assertTrue(container.isHelpBubbleShowingForTesting('title'));
     assertTrue(container.isHelpBubbleShowing());
 
-    container.hideHelpBubble('p1');
-    assertFalse(container.isHelpBubbleShowingFor('p1'));
-    assertTrue(container.isHelpBubbleShowingFor('title'));
+    // @ts-ignore - accessing private member for test
+    container.hideHelpBubble(p1Bubble.nativeId_);
+    assertFalse(container.isHelpBubbleShowingForTesting('p1'));
+    assertTrue(container.isHelpBubbleShowingForTesting('title'));
     assertTrue(container.isHelpBubbleShowing());
 
-    container.hideHelpBubble('title');
-    assertFalse(container.isHelpBubbleShowingFor('p1'));
-    assertFalse(container.isHelpBubbleShowingFor('title'));
+    // @ts-ignore - accessing private member for test
+    container.hideHelpBubble(titleBubble.nativeId_);
+    assertFalse(container.isHelpBubbleShowingForTesting('p1'));
+    assertFalse(container.isHelpBubbleShowingForTesting('title'));
     assertFalse(container.isHelpBubbleShowing());
   });
 
@@ -286,18 +290,18 @@
       'help bubble mixin shows help bubble when called via proxy', async () => {
         testProxy.getCallbackRouterRemote().showHelpBubble(defaultParams);
         await waitAfterNextRender(container);
-        assertTrue(container.isHelpBubbleShowing());
-        const bubble = container.getHelpBubbleFor('p1');
-        assertTrue(!!bubble);
-        assertEquals(container.$.p1, bubble.getAnchorElement());
-        assertTrue(isVisible(bubble));
+        assertTrue(container.isHelpBubbleShowing(), 'here');
+        const bubble = container.getHelpBubbleForTesting('p1');
+        assertTrue(!!bubble, 'now here');
+        assertEquals(container.$.p1, bubble.getAnchorElement(), 'f');
+        assertTrue(isVisible(bubble), 'now f');
       });
 
   test('help bubble mixin uses close button alt text', async () => {
     testProxy.getCallbackRouterRemote().showHelpBubble(defaultParams);
     await waitAfterNextRender(container);
     assertTrue(container.isHelpBubbleShowing());
-    const bubble = container.getHelpBubbleFor('p1')!;
+    const bubble = container.getHelpBubbleForTesting('p1')!;
     const closeButton = bubble.shadowRoot!.querySelector<HTMLElement>('#close');
     assertTrue(!!closeButton);
     assertEquals(CLOSE_BUTTON_ALT_TEXT, closeButton.getAttribute('aria-label'));
@@ -307,7 +311,7 @@
     testProxy.getCallbackRouterRemote().showHelpBubble(defaultParams);
     await waitAfterNextRender(container);
     assertTrue(container.isHelpBubbleShowing());
-    const bubble = container.getHelpBubbleFor('p1')!;
+    const bubble = container.getHelpBubbleForTesting('p1')!;
     assertEquals(bubble.bodyIconName, defaultParams.bodyIconName);
     const bodyIcon = bubble.shadowRoot!.querySelector<HTMLElement>('#bodyIcon');
     assertTrue(!!bodyIcon);
@@ -322,7 +326,7 @@
         testProxy.getCallbackRouterRemote().showHelpBubble(noIconParams);
         await waitAfterNextRender(container);
         assertTrue(container.isHelpBubbleShowing());
-        const bubble = container.getHelpBubbleFor('p1')!;
+        const bubble = container.getHelpBubbleForTesting('p1')!;
         assertEquals(bubble.bodyIconName, null);
         const bodyIcon =
             bubble.shadowRoot!.querySelector<HTMLElement>('#bodyIcon');
@@ -422,9 +426,13 @@
   });
 
   test('help bubble mixin sends event on element activated', async () => {
+    container.showHelpBubble(titleBubble, defaultParams);
+    container.showHelpBubble(bulletListBubble, defaultParams);
     await waitAfterNextRender(container);
-    container.notifyHelpBubbleAnchorActivated('bulletList');
-    container.notifyHelpBubbleAnchorActivated('title');
+    // @ts-ignore - accessing private member for test
+    container.notifyHelpBubbleAnchorActivated(bulletListBubble.nativeId_);
+    // @ts-ignore - accessing private member for test
+    container.notifyHelpBubbleAnchorActivated(titleBubble.nativeId_);
     assertEquals(
         2, testProxy.getHandler().getCallCount('helpBubbleAnchorActivated'));
     assertDeepEquals(
@@ -433,9 +441,15 @@
   });
 
   test('help bubble mixin sends custom events', async () => {
+    container.showHelpBubble(p1Bubble, defaultParams);
+    container.showHelpBubble(titleBubble, defaultParams);
     await waitAfterNextRender(container);
-    container.notifyHelpBubbleAnchorCustomEvent('p1', EVENT1_NAME);
-    container.notifyHelpBubbleAnchorCustomEvent('title', EVENT2_NAME);
+    container.notifyHelpBubbleAnchorCustomEvent(
+        // @ts-ignore - accessing private member for test
+        p1Bubble.nativeId_, EVENT1_NAME);
+    container.notifyHelpBubbleAnchorCustomEvent(
+        // @ts-ignore - accessing private member for test
+        titleBubble.nativeId_, EVENT2_NAME);
     assertEquals(
         2, testProxy.getHandler().getCallCount('helpBubbleAnchorCustomEvent'));
     assertDeepEquals(
@@ -449,7 +463,7 @@
   test(
       'help bubble mixin sends event on closed due to anchor losing visibility',
       async () => {
-        container.showHelpBubble('p1', defaultParams);
+        container.showHelpBubble(p1Bubble, defaultParams);
 
         // Hiding the container will cause the bubble to be closed.
         container.$.p1.style.display = 'none';
@@ -466,7 +480,7 @@
   test(
       'help bubble mixin does not send event when non-anchor loses visibility',
       async () => {
-        container.showHelpBubble('p1', defaultParams);
+        container.showHelpBubble(p1Bubble, defaultParams);
 
         // This is not the current bubble anchor, so should not send an event.
         container.$.title.style.display = 'none';
@@ -477,7 +491,7 @@
       });
 
   test('help bubble mixin does not timeout by default', async () => {
-    container.showHelpBubble('p1', defaultParams);
+    container.showHelpBubble(p1Bubble, defaultParams);
 
     // This is not the current bubble anchor, so should not send an event.
     container.$.title.style.display = 'none';
@@ -500,7 +514,7 @@
     testProxy.getCallbackRouterRemote().showHelpBubble(defaultParams);
     await waitAfterNextRender(container);
     assertTrue(container.isHelpBubbleShowing());
-    const bubble = container.getHelpBubbleFor('p1');
+    const bubble = container.getHelpBubbleForTesting('p1');
     assertTrue(!!bubble);
     assertEquals(container.$.p1, bubble.getAnchorElement());
     assertTrue(isVisible(bubble));
@@ -521,8 +535,8 @@
     testProxy.getCallbackRouterRemote().showHelpBubble(paramsWithTitle);
     await waitAfterNextRender(container);
     assertTrue(container.isHelpBubbleShowing());
-    const bubble1 = container.getHelpBubbleFor('title');
-    const bubble2 = container.getHelpBubbleFor('p1');
+    const bubble1 = container.getHelpBubbleForTesting('title');
+    const bubble2 = container.getHelpBubbleForTesting('p1');
     assertTrue(!!bubble1);
     assertTrue(!!bubble2);
     assertEquals(container.$.title, bubble1!.getAnchorElement());
@@ -537,8 +551,8 @@
     testProxy.getCallbackRouterRemote().showHelpBubble(paramsWithTitle);
     await waitAfterNextRender(container);
     assertTrue(container.isHelpBubbleShowing());
-    const titleBubble = container.getHelpBubbleFor('title')!;
-    const paragraphBubble = container.getHelpBubbleFor('p1')!;
+    const titleBubble = container.getHelpBubbleForTesting('title')!;
+    const paragraphBubble = container.getHelpBubbleForTesting('p1')!;
     // Testing that setting `titleText` will cause the title to display
     // correctly is present in help_bubble_test.ts, so it is sufficient to
     // verify that the property is set correctly.
@@ -562,8 +576,8 @@
         testProxy.getCallbackRouterRemote().showHelpBubble(paramsWithProgress);
         await waitAfterNextRender(container);
         assertTrue(container.isHelpBubbleShowing());
-        const paragraphBubble = container.getHelpBubbleFor('p1')!;
-        const progressBubble = container.getHelpBubbleFor('bulletList')!;
+        const paragraphBubble = container.getHelpBubbleForTesting('p1')!;
+        const progressBubble = container.getHelpBubbleForTesting('bulletList')!;
         // Testing that setting `progress` will cause the progress to display
         // correctly is present in help_bubble_test.ts, so it is sufficient to
         // verify that the property is set correctly.
@@ -583,19 +597,19 @@
     assertTrue(container.isHelpBubbleShowing());
     assertEquals(
         container.$.title,
-        container.getHelpBubbleFor('title')?.getAnchorElement());
-    assertEquals(null, container.getHelpBubbleFor('p1'));
+        container.getHelpBubbleForTesting('title')?.getAnchorElement());
+    assertEquals(null, container.getHelpBubbleForTesting('p1'));
 
     testProxy.getCallbackRouterRemote().hideHelpBubble(
         paramsWithTitle.nativeIdentifier);
     await waitAfterNextRender(container);
     assertFalse(container.isHelpBubbleShowing());
-    assertEquals(null, container.getHelpBubbleFor('title'));
-    assertEquals(null, container.getHelpBubbleFor('p1'));
+    assertEquals(null, container.getHelpBubbleForTesting('title'));
+    assertEquals(null, container.getHelpBubbleForTesting('p1'));
   });
 
   test('help bubble mixin sends event on closed via button', async () => {
-    container.showHelpBubble('p1', defaultParams);
+    container.showHelpBubble(p1Bubble, defaultParams);
 
     // Click the close button.
     container.shadowRoot!.querySelector('help-bubble')!.$.close.click();
@@ -626,7 +640,7 @@
   ];
 
   test('help bubble mixin sends action button clicked event', async () => {
-    container.showHelpBubble('p1', buttonParams);
+    container.showHelpBubble(p1Bubble, buttonParams);
     await waitAfterNextRender(container);
 
     // Click one of the action buttons.
@@ -668,7 +682,7 @@
       },
     };
 
-    container.showHelpBubble('p1', longTimeoutParams);
+    container.showHelpBubble(p1Bubble, longTimeoutParams);
     await waitAfterNextRender(container);
     assertEquals(
         0, testProxy.getHandler().getCallCount('helpBubbleClosed'),
@@ -687,7 +701,7 @@
       },
     };
 
-    container.showHelpBubble('p1', shortTimeoutParams);
+    container.showHelpBubble(p1Bubble, shortTimeoutParams);
     await waitAfterNextRender(container);
     await waitForSuccess({
       retryIntervalMs: 50,
@@ -698,7 +712,7 @@
     }) as number;
     assertDeepEquals(
         [[PARAGRAPH_NATIVE_ID, HelpBubbleClosedReason.kTimedOut]],
-        testProxy.getHandler().getArgs('helpBubbleClosed'));
-    assertFalse(container.isHelpBubbleShowing());
+        testProxy.getHandler().getArgs('helpBubbleClosed'), 'im here');
+    assertFalse(container.isHelpBubbleShowing(), 'or here');
   });
 });
diff --git a/chrome/test/data/webui/cr_components/help_bubble_test.ts b/chrome/test/data/webui/cr_components/help_bubble_test.ts
index d1e7875..f383acc 100644
--- a/chrome/test/data/webui/cr_components/help_bubble_test.ts
+++ b/chrome/test/data/webui/cr_components/help_bubble_test.ts
@@ -19,6 +19,11 @@
   assertionFn: () => void;
 }
 
+let counter = 0;
+function getMockId() {
+  return ++counter;
+}
+
 suite('CrComponentsHelpBubbleTest', () => {
   let helpBubble: HelpBubbleElement;
 
@@ -164,10 +169,10 @@
   const HELP_BUBBLE_TITLE = 'help bubble title';
 
   test('help bubble shows and anchors correctly', () => {
-    helpBubble.anchorId = 'p1';
+    const el = document.getElementById('p1')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
-    helpBubble.show();
+    helpBubble.show(el);
 
     assertEquals(
         document.querySelector<HTMLElement>('#p1'),
@@ -181,11 +186,11 @@
   });
 
   test('help bubble titles shows', () => {
-    helpBubble.anchorId = 'p1';
+    const el = document.getElementById('p1')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
     helpBubble.titleText = HELP_BUBBLE_TITLE;
-    helpBubble.show();
+    helpBubble.show(el);
 
     assertTrue(isVisible(helpBubble), 'help bubble should be visible');
     const titleElement = helpBubble.$.title;
@@ -198,10 +203,10 @@
   });
 
   test('help bubble titles hides when no title set', () => {
-    helpBubble.anchorId = 'p1';
+    const el = document.getElementById('p1')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
-    helpBubble.show();
+    helpBubble.show(el);
 
     assertTrue(isVisible(helpBubble), 'help bubble should be visible');
     const titleElement = helpBubble.$.title;
@@ -210,12 +215,12 @@
   });
 
   test('help bubble body icon shows when set', () => {
-    helpBubble.anchorId = 'p1';
+    const el = document.getElementById('p1')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
     helpBubble.bodyIconName = 'icon_name';
     helpBubble.bodyIconAltText = '';
-    helpBubble.show();
+    helpBubble.show(el);
 
     assertTrue(isVisible(helpBubble), 'help bubble should be visible');
     const bodyIcon = helpBubble.$.bodyIcon;
@@ -229,12 +234,12 @@
   });
 
   test('help bubble body icon is hidden when null', () => {
-    helpBubble.anchorId = 'p1';
+    const el = document.getElementById('p1')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
     helpBubble.bodyIconName = null;
     helpBubble.bodyIconAltText = '';
-    helpBubble.show();
+    helpBubble.show(el);
 
     assertTrue(isVisible(helpBubble), 'help bubble should be visible');
     const bodyIcon = helpBubble.$.bodyIcon;
@@ -244,10 +249,10 @@
   });
 
   test('help bubble closes', () => {
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
-    helpBubble.show();
+    helpBubble.show(el);
 
     assertEquals(
         document.querySelector<HTMLElement>('#title'),
@@ -262,12 +267,12 @@
   });
 
   test('help bubble open close open', () => {
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
-    helpBubble.show();
+    helpBubble.show(el);
     helpBubble.hide();
-    helpBubble.show();
+    helpBubble.show(el);
     assertEquals(
         document.querySelector<HTMLElement>('#title'),
         helpBubble.getAnchorElement(),
@@ -282,10 +287,10 @@
   test('help bubble close button has correct alt text', () => {
     const CLOSE_TEXT: string = 'Close button text.';
     const ICON_TEXT: string = 'Body icon text.';
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
     helpBubble.closeButtonAltText = CLOSE_TEXT;
     helpBubble.bodyIconAltText = ICON_TEXT;
-    helpBubble.show();
+    helpBubble.show(el);
 
     assertEquals(
         CLOSE_TEXT, helpBubble.$.close.getAttribute('aria-label'),
@@ -300,19 +305,21 @@
 
   test('help bubble click close button generates event', async () => {
     let clicked: number = 0;
+    const nativeId = getMockId();
     const callback = (e: HelpBubbleDismissedEvent) => {
       assertEquals(
-          'title', e.detail.anchorId, 'dismiss event anchorId should match');
+          nativeId, e.detail.nativeId, 'dismiss event anchorId should match');
       assertFalse(
           e.detail.fromActionButton,
           'dismiss event should not be from action button');
       ++clicked;
     };
     helpBubble.addEventListener(HELP_BUBBLE_DISMISSED_EVENT, callback);
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
+    helpBubble.nativeId = nativeId;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
     const closeButton = helpBubble.$.close;
     assertEquals(0, clicked, 'close button should not be clicked');
@@ -322,17 +329,19 @@
 
   test('help bubble with timeout does not immediately emit event', async () => {
     let timedOut: number = 0;
+    const nativeId = getMockId();
     const callback = (e: HelpBubbleTimedOutEvent) => {
       assertEquals(
-          'title', e.detail.anchorId, 'timeout event anchorId should match');
+          nativeId, e.detail.nativeId, 'timeout event anchorId should match');
       ++timedOut;
     };
     helpBubble.addEventListener(HELP_BUBBLE_TIMED_OUT_EVENT, callback);
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
+    helpBubble.nativeId = nativeId;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
     helpBubble.timeoutMs = 10 * 1000;  // 10s
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
     assertEquals(0, timedOut, 'timeout should not be triggered');
   });
@@ -340,17 +349,19 @@
   test('help bubble with timeout generates event', async () => {
     const timeoutMs: number = 100;
     let timedOut: number = 0;
+    const nativeId = getMockId();
     const callback = (e: HelpBubbleTimedOutEvent) => {
       assertEquals(
-          'title', e.detail.anchorId, 'timeout event anchorId should match');
+          nativeId, e.detail.nativeId, 'timeout event anchorId should match');
       ++timedOut;
     };
     helpBubble.addEventListener(HELP_BUBBLE_TIMED_OUT_EVENT, callback);
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
+    helpBubble.nativeId = nativeId;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
     helpBubble.timeoutMs = timeoutMs;  // 100ms
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
     await waitForSuccess({
       retryIntervalMs: 50,
@@ -361,16 +372,18 @@
 
   test('help bubble without timeout does not generate event', async () => {
     let timedOut: number = 0;
+    const nativeId = getMockId();
     const callback = (e: HelpBubbleTimedOutEvent) => {
       assertEquals(
-          'title', e.detail.anchorId, 'timeout event anchorId should match');
+          nativeId, e.detail.nativeId, 'timeout event anchorId should match');
       ++timedOut;
     };
     helpBubble.addEventListener(HELP_BUBBLE_TIMED_OUT_EVENT, callback);
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
+    helpBubble.nativeId = nativeId;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
-    helpBubble.show();
+    helpBubble.show(el);
     assertEquals(0, timedOut, 'timeout should not be triggered');
     await waitAfterNextRender(helpBubble);
     await sleep(100);  // 100ms
@@ -378,11 +391,11 @@
   });
 
   test('help bubble adds one button', async () => {
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
     helpBubble.buttons = [{text: 'button1', isDefault: false}];
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
     assertEquals(1, getNumButtons(), 'there should be one button');
     const button = helpBubble.getButtonForTesting(0);
@@ -396,7 +409,7 @@
   });
 
   test('help bubble adds several buttons', async () => {
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
     helpBubble.buttons = [
@@ -404,7 +417,7 @@
       {text: 'button2', isDefault: false},
       {text: 'button3', isDefault: false},
     ];
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
     assertEquals(3, getNumButtons(), 'there should be three buttons');
     for (let i: number = 0; i < 3; ++i) {
@@ -420,11 +433,11 @@
   });
 
   test('help bubble adds default button', async () => {
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
     helpBubble.buttons = [{text: 'button1', isDefault: true}];
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
     const button = helpBubble.getButtonForTesting(0);
     assertTrue(!!button, 'button should exist');
@@ -440,12 +453,12 @@
   ];
 
   test('help bubble adds default button among several', async () => {
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
     helpBubble.buttons = THREE_BUTTONS_MIDDLE_DEFAULT;
     helpBubble.forceCloseButton = true;
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
     assertEquals(3, getNumButtons(), 'there should be three buttons');
 
@@ -499,15 +512,17 @@
   test('help bubble click action button generates event', async () => {
     let clicked: boolean;
     let buttonIndex: number;
+    const nativeId = getMockId();
     const callback = (e: HelpBubbleDismissedEvent) => {
-      assertEquals('title', e.detail.anchorId, 'Check anchor.');
+      assertEquals(nativeId, e.detail.nativeId, 'Check anchor.');
       assertTrue(e.detail.fromActionButton, 'Check fromActionButton.');
       assertTrue(e.detail.buttonIndex !== undefined, 'Check buttonIndex.');
       clicked = true;
       buttonIndex = e.detail.buttonIndex;
     };
     helpBubble.addEventListener(HELP_BUBBLE_DISMISSED_EVENT, callback);
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
+    helpBubble.nativeId = nativeId;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
     helpBubble.buttons = THREE_BUTTONS_MIDDLE_DEFAULT;
@@ -515,7 +530,7 @@
     for (let i: number = 0; i < 3; ++i) {
       clicked = false;
       buttonIndex = -1;
-      helpBubble.show();
+      helpBubble.show(el);
       await waitAfterNextRender(helpBubble);
       const button = helpBubble.getButtonForTesting(i);
       assertTrue(!!button, 'button should exist');
@@ -527,12 +542,12 @@
   });
 
   test('help bubble with no progress doesn\'t show progress', async () => {
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
     helpBubble.buttons = THREE_BUTTONS_MIDDLE_DEFAULT;
 
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
 
     assertEquals(
@@ -544,13 +559,13 @@
   test(
       'help bubble with no progress and title doesn\'t show progress',
       async () => {
-        helpBubble.anchorId = 'title';
+        const el = document.getElementById('title')!;
         helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
         helpBubble.bodyText = HELP_BUBBLE_BODY;
         helpBubble.titleText = HELP_BUBBLE_TITLE;
         helpBubble.buttons = THREE_BUTTONS_MIDDLE_DEFAULT;
 
-        helpBubble.show();
+        helpBubble.show(el);
         await waitAfterNextRender(helpBubble);
 
         assertEquals(
@@ -563,13 +578,13 @@
       });
 
   test('help bubble with progress shows progress', async () => {
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
     helpBubble.progress = {current: 1, total: 3};
     helpBubble.buttons = THREE_BUTTONS_MIDDLE_DEFAULT;
 
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
 
     const elements = getProgressIndicators();
@@ -597,14 +612,14 @@
   });
 
   test('help bubble with progress and title shows progress', async () => {
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
     helpBubble.titleText = HELP_BUBBLE_TITLE;
     helpBubble.progress = {current: 1, total: 2};
     helpBubble.buttons = THREE_BUTTONS_MIDDLE_DEFAULT;
 
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
 
     const elements = getProgressIndicators();
@@ -623,12 +638,12 @@
   });
 
   test('help bubble with full progress', async () => {
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
     helpBubble.progress = {current: 2, total: 2};
 
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
 
     const elements = getProgressIndicators();
@@ -642,12 +657,12 @@
   });
 
   test('help bubble with empty progress', async () => {
-    helpBubble.anchorId = 'title';
+    const el = document.getElementById('title')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_CENTER;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
     helpBubble.progress = {current: 0, total: 2};
 
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
 
     const elements = getProgressIndicators();
@@ -661,11 +676,11 @@
   });
 
   test('help bubble does not left-align with small anchor', async () => {
-    helpBubble.anchorId = 'short-button';
+    const el = document.getElementById('short-button')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_LEFT;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
 
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
 
     const anchorRect = helpBubble.getAnchorElement()!.getBoundingClientRect();
@@ -690,11 +705,11 @@
   });
 
   test('help bubble left-aligns with large anchor', async () => {
-    helpBubble.anchorId = 'long-button';
+    const el = document.getElementById('long-button')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_LEFT;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
 
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
 
     const anchorRect = helpBubble.getAnchorElement()!.getBoundingClientRect();
@@ -718,11 +733,11 @@
   });
 
   test('help bubble does not right-align with small anchor', async () => {
-    helpBubble.anchorId = 'short-button';
+    const el = document.getElementById('short-button')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_RIGHT;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
 
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
 
     const anchorRect = helpBubble.getAnchorElement()!.getBoundingClientRect();
@@ -747,11 +762,11 @@
   });
 
   test('help bubble right-aligns with large anchor', async () => {
-    helpBubble.anchorId = 'long-button';
+    const el = document.getElementById('long-button')!;
     helpBubble.position = HelpBubbleArrowPosition.TOP_RIGHT;
     helpBubble.bodyText = HELP_BUBBLE_BODY;
 
-    helpBubble.show();
+    helpBubble.show(el);
     await waitAfterNextRender(helpBubble);
 
     const anchorRect = helpBubble.getAnchorElement()!.getBoundingClientRect();
diff --git a/chrome/test/data/webui/cr_focus_row_behavior_test.ts b/chrome/test/data/webui/cr_focus_row_behavior_test.ts
index f00f9f5..77faa64 100644
--- a/chrome/test/data/webui/cr_focus_row_behavior_test.ts
+++ b/chrome/test/data/webui/cr_focus_row_behavior_test.ts
@@ -8,7 +8,7 @@
 import {down, pressAndReleaseKeyOn, up} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
 import {html, PolymerElement, mixinBehaviors} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {eventToPromise} from './test_util.js';
-import {assertFalse, assertTrue, assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertFalse, assertTrue, assertEquals} from './chai_assert.js';
 
 import {waitAfterNextRender} from './polymer_test_util.js';
 
diff --git a/chrome/test/data/webui/cr_focus_row_mixin_test.ts b/chrome/test/data/webui/cr_focus_row_mixin_test.ts
index 6201a04..cbbb4d5b 100644
--- a/chrome/test/data/webui/cr_focus_row_mixin_test.ts
+++ b/chrome/test/data/webui/cr_focus_row_mixin_test.ts
@@ -11,7 +11,7 @@
 
 import {waitAfterNextRender} from './polymer_test_util.js';
 
-import {assertFalse, assertTrue, assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertFalse, assertTrue, assertEquals} from './chai_assert.js';
 
 // clang-format on
 
diff --git a/chrome/test/data/webui/fake_chrome_event.ts b/chrome/test/data/webui/fake_chrome_event.ts
index bb80ec05..f8f7021 100644
--- a/chrome/test/data/webui/fake_chrome_event.ts
+++ b/chrome/test/data/webui/fake_chrome_event.ts
@@ -6,7 +6,7 @@
  * @fileoverview Fake implementations of ChromeEvent.
  */
 
-import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertFalse, assertTrue} from './chai_assert.js';
 
 export class FakeChromeEvent {
   private listeners_: Set<Function> = new Set();
diff --git a/chrome/test/data/webui/invalidations/invalidations_test.js b/chrome/test/data/webui/invalidations/invalidations_test.js
index 3b2b075..be49504 100644
--- a/chrome/test/data/webui/invalidations/invalidations_test.js
+++ b/chrome/test/data/webui/invalidations/invalidations_test.js
@@ -4,7 +4,7 @@
 
 import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js';
 import {$} from 'chrome://resources/js/util.js';
-import {assertEquals, assertNotEquals, assertTrue} from '../chai_assert.js';
+import {assertEquals, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
 
 window.invalidations_test = {};
 invalidations_test = window.invalidations_test;
diff --git a/chrome/test/data/webui/js/static_types_test.ts b/chrome/test/data/webui/js/static_types_test.ts
index be031e8..a8c43a95 100644
--- a/chrome/test/data/webui/js/static_types_test.ts
+++ b/chrome/test/data/webui/js/static_types_test.ts
@@ -4,7 +4,7 @@
 
 import {getTrustedHTML, getTrustedScript, getTrustedScriptURL} from 'chrome://resources/js/static_types.js';
 
-import {assertEquals, assertNotReached, assertThrows} from '../chai_assert.js';
+import {assertEquals, assertNotReached, assertThrows} from 'chrome://webui-test/chai_assert.js';
 
 suite('StaticTypesTest', function() {
   test('compatible with Trusted Types', () => {
diff --git a/chrome/test/data/webui/mock_controller.ts b/chrome/test/data/webui/mock_controller.ts
index 077eae5..c58c677 100644
--- a/chrome/test/data/webui/mock_controller.ts
+++ b/chrome/test/data/webui/mock_controller.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {assertDeepEquals, assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertDeepEquals, assertEquals} from './chai_assert.js';
 
 /**
  * Create a mock function that records function calls and validates against
diff --git a/chrome/test/data/webui/mock_timer_test.ts b/chrome/test/data/webui/mock_timer_test.ts
index ffb6719..a3e6157 100644
--- a/chrome/test/data/webui/mock_timer_test.ts
+++ b/chrome/test/data/webui/mock_timer_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 {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from './chai_assert.js';
 
 import {MockTimer} from './mock_timer.js';
 
diff --git a/chrome/test/data/webui/nearby_share/BUILD.gn b/chrome/test/data/webui/nearby_share/BUILD.gn
index 271e1e01e..1f22f99 100644
--- a/chrome/test/data/webui/nearby_share/BUILD.gn
+++ b/chrome/test/data/webui/nearby_share/BUILD.gn
@@ -48,7 +48,7 @@
 
 js_library("fake_mojo_interfaces") {
   deps = [
-    "..:test_browser_proxy",
+    "../chromeos:test_browser_proxy",
     "//chrome/browser/ui/webui/nearby_share:mojom_js_library_for_compile",
   ]
 }
@@ -56,7 +56,7 @@
 js_library("nearby_confirmation_page_test") {
   deps = [
     ":fake_mojo_interfaces",
-    "..:chai_assert",
+    "../chromeos:chai_assert",
     "//chrome/browser/resources/nearby_share:nearby_confirmation_page",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -65,7 +65,7 @@
 js_library("nearby_discovery_page_test") {
   deps = [
     ":fake_mojo_interfaces",
-    "..:chai_assert",
+    "../chromeos:chai_assert",
     "//chrome/browser/resources/nearby_share:nearby_discovery_page",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -73,7 +73,7 @@
 
 js_library("nearby_share_app_test") {
   deps = [
-    "..:chai_assert",
+    "../chromeos:chai_assert",
     "../chromeos:test_util",
     "shared:fake_nearby_contact_manager",
     "shared:fake_nearby_share_settings",
diff --git a/chrome/test/data/webui/nearby_share/fake_mojo_interfaces.js b/chrome/test/data/webui/nearby_share/fake_mojo_interfaces.js
index 6b683620..bd424957 100644
--- a/chrome/test/data/webui/nearby_share/fake_mojo_interfaces.js
+++ b/chrome/test/data/webui/nearby_share/fake_mojo_interfaces.js
@@ -4,7 +4,7 @@
 
 /** @fileoverview Contains fake implementations of mojo interfaces. */
 
-import {TestBrowserProxy} from '../test_browser_proxy.js';
+import {TestBrowserProxy} from '../chromeos/test_browser_proxy.js';
 
 /**
  * @implements {nearbyShare.mojom.ConfirmationManagerInterface}
diff --git a/chrome/test/data/webui/nearby_share/nearby_confirmation_page_test.js b/chrome/test/data/webui/nearby_share/nearby_confirmation_page_test.js
index 5fa08c9..ffe18e48 100644
--- a/chrome/test/data/webui/nearby_share/nearby_confirmation_page_test.js
+++ b/chrome/test/data/webui/nearby_share/nearby_confirmation_page_test.js
@@ -8,7 +8,7 @@
 
 import {NearbyConfirmationPageElement} from 'chrome://nearby/nearby_confirmation_page.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from '../chromeos/chai_assert.js';
 
 import {FakeConfirmationManagerRemote, FakeTransferUpdateListenerPendingReceiver} from './fake_mojo_interfaces.js';
 
diff --git a/chrome/test/data/webui/nearby_share/nearby_discovery_page_test.js b/chrome/test/data/webui/nearby_share/nearby_discovery_page_test.js
index a853566..1461194 100644
--- a/chrome/test/data/webui/nearby_share/nearby_discovery_page_test.js
+++ b/chrome/test/data/webui/nearby_share/nearby_discovery_page_test.js
@@ -12,7 +12,7 @@
 import {keyEventOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from '../chromeos/chai_assert.js';
 import {isVisible} from '../chromeos/test_util.js';
 
 import {FakeConfirmationManagerRemote, FakeDiscoveryManagerRemote} from './fake_mojo_interfaces.js';
diff --git a/chrome/test/data/webui/nearby_share/nearby_share_app_test.js b/chrome/test/data/webui/nearby_share/nearby_share_app_test.js
index c557e26a..8309a9d 100644
--- a/chrome/test/data/webui/nearby_share/nearby_share_app_test.js
+++ b/chrome/test/data/webui/nearby_share/nearby_share_app_test.js
@@ -12,7 +12,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from '../chromeos/chai_assert.js';
 
 import {FakeContactManager} from './shared/fake_nearby_contact_manager.js';
 import {FakeNearbyShareSettings} from './shared/fake_nearby_share_settings.js';
diff --git a/chrome/test/data/webui/nearby_share/shared/BUILD.gn b/chrome/test/data/webui/nearby_share/shared/BUILD.gn
index 91e1b2c49..9a86e00 100644
--- a/chrome/test/data/webui/nearby_share/shared/BUILD.gn
+++ b/chrome/test/data/webui/nearby_share/shared/BUILD.gn
@@ -42,7 +42,7 @@
   deps = [
     ":fake_nearby_contact_manager",
     ":fake_nearby_share_settings",
-    "../..:chai_assert",
+    "../../chromeos:chai_assert",
     "../../chromeos:test_util",
     "//chrome/browser/resources/nearby_share/shared:nearby_contact_visibility",
   ]
@@ -51,7 +51,7 @@
 
 js_library("nearby_device_icon_test") {
   deps = [
-    "../..:chai_assert",
+    "../../chromeos:chai_assert",
     "//chrome/browser/resources/nearby_share/shared:nearby_device_icon",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -59,7 +59,7 @@
 
 js_library("nearby_device_test") {
   deps = [
-    "../..:chai_assert",
+    "../../chromeos:chai_assert",
     "//chrome/browser/resources/nearby_share/shared:nearby_device",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -68,7 +68,7 @@
 js_library("nearby_onboarding_one_page_test") {
   deps = [
     ":fake_nearby_share_settings",
-    "../..:chai_assert",
+    "../../chromeos:chai_assert",
     "../../chromeos:test_util",
     "//chrome/browser/resources/nearby_share/shared:nearby_onboarding_one_page",
   ]
@@ -81,7 +81,7 @@
 js_library("nearby_onboarding_page_test") {
   deps = [
     ":fake_nearby_share_settings",
-    "../..:chai_assert",
+    "../../chromeos:chai_assert",
     "../../chromeos:test_util",
     "//chrome/browser/resources/nearby_share/shared:nearby_onboarding_page",
   ]
@@ -93,7 +93,7 @@
 
 js_library("nearby_page_template_test") {
   deps = [
-    "../..:chai_assert",
+    "../../chromeos:chai_assert",
     "../../chromeos:test_util",
     "//chrome/browser/resources/nearby_share/shared:nearby_page_template",
   ]
@@ -102,7 +102,7 @@
 
 js_library("nearby_preview_test") {
   deps = [
-    "../..:chai_assert",
+    "../../chromeos:chai_assert",
     "//chrome/browser/resources/nearby_share/shared:nearby_preview",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -110,7 +110,7 @@
 
 js_library("nearby_progress_test") {
   deps = [
-    "../..:chai_assert",
+    "../../chromeos:chai_assert",
     "//chrome/browser/resources/nearby_share/shared:nearby_progress",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
@@ -125,7 +125,7 @@
 js_library("nearby_visibility_page_test") {
   deps = [
     ":fake_nearby_share_settings",
-    "../..:chai_assert",
+    "../../chromeos:chai_assert",
     "//chrome/browser/resources/nearby_share/shared:nearby_visibility_page",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
diff --git a/chrome/test/data/webui/nearby_share/shared/nearby_contact_visibility_test.js b/chrome/test/data/webui/nearby_share/shared/nearby_contact_visibility_test.js
index cdae77cd..a3baca0 100644
--- a/chrome/test/data/webui/nearby_share/shared/nearby_contact_visibility_test.js
+++ b/chrome/test/data/webui/nearby_share/shared/nearby_contact_visibility_test.js
@@ -9,7 +9,7 @@
 import {setNearbyShareSettingsForTesting} from 'chrome://nearby/shared/nearby_share_settings.js';
 import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from '../../chromeos/chai_assert.js';
 import {isChildVisible} from '../../chromeos/test_util.js';
 
 import {FakeContactManager} from './fake_nearby_contact_manager.js';
diff --git a/chrome/test/data/webui/nearby_share/shared/nearby_device_icon_test.js b/chrome/test/data/webui/nearby_share/shared/nearby_device_icon_test.js
index 4b0c1f6..883a995 100644
--- a/chrome/test/data/webui/nearby_share/shared/nearby_device_icon_test.js
+++ b/chrome/test/data/webui/nearby_share/shared/nearby_device_icon_test.js
@@ -12,7 +12,7 @@
 
 import {NearbyDeviceIconElement} from 'chrome://nearby/shared/nearby_device_icon.js';
 
-import {assertEquals} from '../../chai_assert.js';
+import {assertEquals} from '../../chromeos/chai_assert.js';
 
 suite('DeviceIconTest', function() {
   /** @type {!NearbyDeviceIconElement} */
diff --git a/chrome/test/data/webui/nearby_share/shared/nearby_device_test.js b/chrome/test/data/webui/nearby_share/shared/nearby_device_test.js
index 42d2dc2..74f2a675 100644
--- a/chrome/test/data/webui/nearby_share/shared/nearby_device_test.js
+++ b/chrome/test/data/webui/nearby_share/shared/nearby_device_test.js
@@ -12,7 +12,7 @@
 
 import {NearbyDeviceElement} from 'chrome://nearby/shared/nearby_device.js';
 
-import {assertEquals} from '../../chai_assert.js';
+import {assertEquals} from '../../chromeos/chai_assert.js';
 
 suite('DeviceTest', function() {
   /** @type {!NearbyDeviceElement} */
diff --git a/chrome/test/data/webui/nearby_share/shared/nearby_onboarding_one_page_test.js b/chrome/test/data/webui/nearby_share/shared/nearby_onboarding_one_page_test.js
index bf83fb2..f6c7001 100644
--- a/chrome/test/data/webui/nearby_share/shared/nearby_onboarding_one_page_test.js
+++ b/chrome/test/data/webui/nearby_share/shared/nearby_onboarding_one_page_test.js
@@ -10,7 +10,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from '../../chromeos/chai_assert.js';
 
 import {FakeNearbyShareSettings} from './fake_nearby_share_settings.js';
 
diff --git a/chrome/test/data/webui/nearby_share/shared/nearby_onboarding_page_test.js b/chrome/test/data/webui/nearby_share/shared/nearby_onboarding_page_test.js
index 1b17e2e..08359f3 100644
--- a/chrome/test/data/webui/nearby_share/shared/nearby_onboarding_page_test.js
+++ b/chrome/test/data/webui/nearby_share/shared/nearby_onboarding_page_test.js
@@ -9,7 +9,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from '../../chromeos/chai_assert.js';
 
 import {FakeNearbyShareSettings} from './fake_nearby_share_settings.js';
 
diff --git a/chrome/test/data/webui/nearby_share/shared/nearby_page_template_test.js b/chrome/test/data/webui/nearby_share/shared/nearby_page_template_test.js
index b22c00d8..5c75b4c 100644
--- a/chrome/test/data/webui/nearby_share/shared/nearby_page_template_test.js
+++ b/chrome/test/data/webui/nearby_share/shared/nearby_page_template_test.js
@@ -7,7 +7,7 @@
 import {NearbyPageTemplateElement} from 'chrome://nearby/shared/nearby_page_template.js';
 import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from '../../chromeos/chai_assert.js';
 import {isChildVisible} from '../../chromeos/test_util.js';
 
 suite('nearby-page-template', function() {
diff --git a/chrome/test/data/webui/nearby_share/shared/nearby_preview_test.js b/chrome/test/data/webui/nearby_share/shared/nearby_preview_test.js
index 7542ab5..8f91fe5 100644
--- a/chrome/test/data/webui/nearby_share/shared/nearby_preview_test.js
+++ b/chrome/test/data/webui/nearby_share/shared/nearby_preview_test.js
@@ -12,7 +12,7 @@
 
 import {NearbyPreviewElement} from 'chrome://nearby/shared/nearby_preview.js';
 
-import {assertEquals} from '../../chai_assert.js';
+import {assertEquals} from '../../chromeos/chai_assert.js';
 
 suite('PreviewTest', function() {
   /** @type {!NearbyPreviewElement} */
diff --git a/chrome/test/data/webui/nearby_share/shared/nearby_progress_test.js b/chrome/test/data/webui/nearby_share/shared/nearby_progress_test.js
index ff8b8e0..4259b17 100644
--- a/chrome/test/data/webui/nearby_share/shared/nearby_progress_test.js
+++ b/chrome/test/data/webui/nearby_share/shared/nearby_progress_test.js
@@ -12,7 +12,7 @@
 
 import {NearbyProgressElement} from 'chrome://nearby/shared/nearby_progress.js';
 
-import {assertEquals} from '../../chai_assert.js';
+import {assertEquals} from '../../chromeos/chai_assert.js';
 
 suite('ProgressTest', function() {
   /** @type {!NearbyProgressElement} */
diff --git a/chrome/test/data/webui/nearby_share/shared/nearby_visibility_page_test.js b/chrome/test/data/webui/nearby_share/shared/nearby_visibility_page_test.js
index 9b1912f..22019e7a 100644
--- a/chrome/test/data/webui/nearby_share/shared/nearby_visibility_page_test.js
+++ b/chrome/test/data/webui/nearby_share/shared/nearby_visibility_page_test.js
@@ -8,7 +8,7 @@
 import {NearbyVisibilityPageElement} from 'chrome://nearby/shared/nearby_visibility_page.js';
 import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from '../../chromeos/chai_assert.js';
 import {isChildVisible} from '../../chromeos/test_util.js';
 
 import {FakeNearbyShareSettings} from './fake_nearby_share_settings.js';
diff --git a/chrome/test/data/webui/net_internals/dns_view_test.js b/chrome/test/data/webui/net_internals/dns_view_test.js
index 40c59ac18..a73685e 100644
--- a/chrome/test/data/webui/net_internals/dns_view_test.js
+++ b/chrome/test/data/webui/net_internals/dns_view_test.js
@@ -5,7 +5,7 @@
 import {DnsView} from 'chrome://net-internals/dns_view.js';
 import {$} from 'chrome://resources/js/util.js';
 
-import {assertEquals} from '../chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chai_assert.js';
 
 import {Task, TaskQueue} from './task_queue.js';
 import {switchToView} from './test_util.js';
diff --git a/chrome/test/data/webui/net_internals/domain_security_policy_view_test.js b/chrome/test/data/webui/net_internals/domain_security_policy_view_test.js
index 889df4c6..654d57b 100644
--- a/chrome/test/data/webui/net_internals/domain_security_policy_view_test.js
+++ b/chrome/test/data/webui/net_internals/domain_security_policy_view_test.js
@@ -5,7 +5,7 @@
 import {DomainSecurityPolicyView} from 'chrome://net-internals/domain_security_policy_view.js';
 import {$} from 'chrome://resources/js/util.js';
 
-import {assertEquals, assertLE, assertNotEquals} from '../chai_assert.js';
+import {assertEquals, assertLE, assertNotEquals} from 'chrome://webui-test/chai_assert.js';
 
 import {Task, TaskQueue} from './task_queue.js';
 import {switchToView} from './test_util.js';
diff --git a/chrome/test/data/webui/net_internals/task_queue.js b/chrome/test/data/webui/net_internals/task_queue.js
index e5fd104e..c534bbb 100644
--- a/chrome/test/data/webui/net_internals/task_queue.js
+++ b/chrome/test/data/webui/net_internals/task_queue.js
@@ -4,7 +4,7 @@
 
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
 
-import {assertEquals, assertFalse, assertNotReached, assertTrue} from '../chai_assert.js';
+import {assertEquals, assertFalse, assertNotReached, assertTrue} from 'chrome://webui-test/chai_assert.js';
 
 /**
  * This class allows multiple Tasks to be queued up to be run sequentially.
diff --git a/chrome/test/data/webui/net_internals/test_util.js b/chrome/test/data/webui/net_internals/test_util.js
index c57e203..2096c5e8 100644
--- a/chrome/test/data/webui/net_internals/test_util.js
+++ b/chrome/test/data/webui/net_internals/test_util.js
@@ -12,7 +12,7 @@
 import {ProxyView} from 'chrome://net-internals/proxy_view.js';
 import {SocketsView} from 'chrome://net-internals/sockets_view.js';
 
-import {assertEquals, assertNotEquals, assertTrue} from '../chai_assert.js';
+import {assertEquals, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
 
 /**
  * Returns the view and menu item node for the tab with given id.
diff --git a/chrome/test/data/webui/new_tab_page/test_support.ts b/chrome/test/data/webui/new_tab_page/test_support.ts
index 06a1349..bb0e874d 100644
--- a/chrome/test/data/webui/new_tab_page/test_support.ts
+++ b/chrome/test/data/webui/new_tab_page/test_support.ts
@@ -7,8 +7,8 @@
 import {getDeepActiveElement} from 'chrome://resources/js/util.js';
 import {keyDownOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
 
-import {assertEquals, assertNotEquals} from '../chai_assert.js';
-import {TestBrowserProxy} from '../test_browser_proxy.js';
+import {assertEquals, assertNotEquals} from 'chrome://webui-test/chai_assert.js';
+import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
 
 export const NONE_ANIMATION: string = 'none 0s ease 0s 1 normal none running';
 
diff --git a/chrome/test/data/webui/new_tab_page/voice_search_overlay_test.ts b/chrome/test/data/webui/new_tab_page/voice_search_overlay_test.ts
index dc616b89..83b0bb1 100644
--- a/chrome/test/data/webui/new_tab_page/voice_search_overlay_test.ts
+++ b/chrome/test/data/webui/new_tab_page/voice_search_overlay_test.ts
@@ -13,7 +13,7 @@
 import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
 import {isVisible} from 'chrome://webui-test/test_util.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 
 import {fakeMetricsPrivate, MetricsTracker} from './../metrics_test_support.js';
 import {assertNotStyle, assertStyle, installMock, keydown} from './test_support.js';
diff --git a/chrome/test/data/webui/set_time_dialog_browsertest.js b/chrome/test/data/webui/set_time_dialog_browsertest.js
index c9b22ce..0767e75f 100644
--- a/chrome/test/data/webui/set_time_dialog_browsertest.js
+++ b/chrome/test/data/webui/set_time_dialog_browsertest.js
@@ -10,7 +10,7 @@
 var SetTimeDialogBrowserTest = class extends PolymerTest {
   /** @override */
   get browsePreload() {
-    return 'chrome://set-time/test_loader.html?module=set_time_dialog_test.js&host=test';
+    return 'chrome://set-time/test_loader.html?module=set_time_dialog_test.js';
   }
 };
 
diff --git a/chrome/test/data/webui/set_time_dialog_test.js b/chrome/test/data/webui/set_time_dialog_test.js
index e68dcb77..a0d7475 100644
--- a/chrome/test/data/webui/set_time_dialog_test.js
+++ b/chrome/test/data/webui/set_time_dialog_test.js
@@ -8,7 +8,7 @@
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {SetTimeBrowserProxyImpl} from 'chrome://set-time/set_time_browser_proxy.js';
 
-import {TestBrowserProxy} from './test_browser_proxy.js';
+import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
 
 suite('SetTimeDialog', function() {
   let setTimeElement = null;
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn
index b02a47b..f3510a3 100644
--- a/chrome/test/data/webui/settings/BUILD.gn
+++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -143,6 +143,7 @@
   "test_search_engines_browser_proxy.ts",
   "test_site_settings_prefs_browser_proxy.ts",
   "test_util.ts",
+  "trusted_html.ts",
   "zoom_levels_tests.ts",
 ]
 
diff --git a/chrome/test/data/webui/settings/idle_load_tests.ts b/chrome/test/data/webui/settings/idle_load_tests.ts
index 6c9aef2b..36bcf4d3 100644
--- a/chrome/test/data/webui/settings/idle_load_tests.ts
+++ b/chrome/test/data/webui/settings/idle_load_tests.ts
@@ -4,6 +4,8 @@
 
 // #clang-format off
 import 'chrome://settings/settings.js';
+
+import {getTrustedHTML} from 'chrome://settings/settings.js';
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 // #clang-format on
 
@@ -16,7 +18,7 @@
 
 suite('Settings idle load tests', function() {
   setup(function() {
-    document.body.innerHTML = `
+    document.body.innerHTML = getTrustedHTML`
       <settings-idle-load>
         <template>
           <div></div>
diff --git a/chrome/test/data/webui/settings/privacy_page_test.ts b/chrome/test/data/webui/settings/privacy_page_test.ts
index 781eea4..7609ae07 100644
--- a/chrome/test/data/webui/settings/privacy_page_test.ts
+++ b/chrome/test/data/webui/settings/privacy_page_test.ts
@@ -518,7 +518,7 @@
     Router.getInstance().navigateTo(routes.SITE_SETTINGS_NOTIFICATIONS);
     siteSettingsBrowserProxy = new TestSiteSettingsPrefsBrowserProxy();
     SiteSettingsPrefsBrowserProxyImpl.setInstance(siteSettingsBrowserProxy);
-    document.body.innerHTML = '';
+    document.body.innerHTML = window.trustedTypes!.emptyHTML;
   });
 
   teardown(function() {
diff --git a/chrome/test/data/webui/settings/search_settings_test.ts b/chrome/test/data/webui/settings/search_settings_test.ts
index 61ebd7d5..33e0397 100644
--- a/chrome/test/data/webui/settings/search_settings_test.ts
+++ b/chrome/test/data/webui/settings/search_settings_test.ts
@@ -4,9 +4,11 @@
 
 // clang-format off
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {BaseMixin, getSearchManager, SearchManager} from 'chrome://settings/settings.js';
+import {BaseMixin, getSearchManager, SearchManager, getTrustedHTML as getTrustedStaticHtml} from 'chrome://settings/settings.js';
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 
+import {getTrustedHtml} from './trusted_html.js';
+
 // clang-format on
 
 suite('SearchSettingsTest', function() {
@@ -24,9 +26,10 @@
   test('normal highlighting', function() {
     const optionText = 'FooSettingsFoo';
 
-    document.body.innerHTML = `<settings-section hidden-by-search>
+    document.body.innerHTML =
+        getTrustedHtml(`<settings-section hidden-by-search>
            <div id="mydiv">${optionText}</div>
-         </settings-section>`;
+         </settings-section>`);
 
     const section = document.querySelector('settings-section')!;
     const div = document.querySelector('#mydiv')!;
@@ -66,7 +69,8 @@
    * bubble.
    */
   test('<select> highlighting', function() {
-    document.body.innerHTML = `<settings-section hidden-by-search>
+    document.body.innerHTML =
+        getTrustedStaticHtml`<settings-section hidden-by-search>
            <select>
              <option>Foo</option>
              <option>Settings</option>
@@ -99,7 +103,8 @@
 
   test('ignored elements are ignored', function() {
     const text = 'hello';
-    document.body.innerHTML = `<settings-section hidden-by-search>
+    document.body.innerHTML =
+        getTrustedHtml(`<settings-section hidden-by-search>
            <cr-action-menu>${text}</cr-action-menu>
            <cr-dialog>${text}</cr-dialog>
            <cr-icon-button>${text}</cr-icon-button>
@@ -113,7 +118,7 @@
            <content>${text}</content>
            <style>${text}</style>
            <template>${text}</template>
-         </settings-section>`;
+         </settings-section>`);
 
     const section = document.querySelector('settings-section')!;
     assertTrue(section.hiddenBySearch);
@@ -166,7 +171,8 @@
 
     const text = 'hello';
 
-    document.body.innerHTML = `<dummy-test-element></dummy-test-element>`;
+    document.body.innerHTML =
+        getTrustedStaticHtml`<dummy-test-element></dummy-test-element>`;
 
     const element =
         document.body.querySelector<DummyTestElement>('dummy-test-element')!;
@@ -197,7 +203,8 @@
   // Test that multiple requests for the same text correctly highlight their
   // corresponding part of the tree without affecting other parts of the tree.
   test('multiple simultaneous requests for the same text', function() {
-    document.body.innerHTML = `<settings-section hidden-by-search>
+    document.body.innerHTML =
+        getTrustedStaticHtml`<settings-section hidden-by-search>
            <div><span>Hello there</span></div>
          </settings-section>
          <settings-section hidden-by-search>
@@ -224,9 +231,10 @@
   test('highlight removed when text is changed', function() {
     const originalText = 'FooSettingsFoo';
 
-    document.body.innerHTML = `<settings-section hidden-by-search>
+    document.body.innerHTML =
+        getTrustedHtml(`<settings-section hidden-by-search>
           <div id="mydiv">${originalText}</div>
-        </settings-section>`;
+        </settings-section>`);
 
     const section = document.querySelector('settings-section')!;
     const div = document.querySelector('#mydiv')!;
@@ -253,7 +261,7 @@
   });
 
   test('match text outside of a settings section', async function() {
-    document.body.innerHTML = `
+    document.body.innerHTML = getTrustedStaticHtml`
         <div id="mydiv">Match</div>
         <settings-section></settings-section>`;
 
@@ -272,7 +280,7 @@
   });
 
   test('associated control causes search highlight bubble', async () => {
-    document.body.innerHTML = `
+    document.body.innerHTML = getTrustedStaticHtml`
         <settings-section>
           <button></button>
           <settings-subpage>
@@ -288,7 +296,7 @@
   });
 
   test('bubble result count', async () => {
-    document.body.innerHTML = `
+    document.body.innerHTML = getTrustedStaticHtml`
         <settings-section>
           <select>
             <option>nohello</option>
@@ -315,7 +323,7 @@
   });
 
   test('diacritics', async () => {
-    document.body.innerHTML = `
+    document.body.innerHTML = getTrustedStaticHtml`
         <settings-section>
           <select>
             <option>año de oro</option>
diff --git a/chrome/test/data/webui/settings/settings_animated_pages_test.ts b/chrome/test/data/webui/settings/settings_animated_pages_test.ts
index b4416fb..53b4c01b 100644
--- a/chrome/test/data/webui/settings/settings_animated_pages_test.ts
+++ b/chrome/test/data/webui/settings/settings_animated_pages_test.ts
@@ -8,6 +8,7 @@
 import {eventToPromise} from 'chrome://webui-test/test_util.js';
 
 import {setupPopstateListener} from './test_util.js';
+import {getTrustedHtml} from './trusted_html.js';
 
 // clang-format on
 
@@ -46,13 +47,13 @@
   // Test simple case where the |focusConfig| key captures only the previous
   // route.
   test('FocusSubpageTrigger_SimpleKey', async function() {
-    document.body.innerHTML = `
+    document.body.innerHTML = getTrustedHtml(`
       <settings-animated-pages section="${testRoutes.SEARCH_ENGINES.section}">
         <div route-path="default">
           <button id="subpage-trigger"></button>
         </div>
         <div route-path="${testRoutes.SEARCH_ENGINES.path}"></div>
-      </settings-animated-pages>`;
+      </settings-animated-pages>`);
 
     const animatedPages =
         document.body.querySelector('settings-animated-pages')!;
@@ -75,7 +76,7 @@
   // route, to differentiate cases where a subpage can have multiple entry
   // points.
   test('FocusSubpageTrigger_FromToKey', async function() {
-    document.body.innerHTML = `
+    document.body.innerHTML = getTrustedHtml(`
       <settings-animated-pages section="${testRoutes.PRIVACY.section}">
         <div route-path="default">
           <button id="subpage-trigger1"></button>
@@ -84,7 +85,7 @@
           <button id="subpage-trigger2"></button>
         </div>
         <div route-path="${testRoutes.SITE_SETTINGS_COOKIES.path}"></div>
-      </settings-animated-pages>`;
+      </settings-animated-pages>`);
 
     const animatedPages =
         document.body.querySelector('settings-animated-pages')!;
@@ -121,13 +122,13 @@
   });
 
   test('IgnoresBubblingIronSelect', async function() {
-    document.body.innerHTML = `
+    document.body.innerHTML = getTrustedHtml(`
       <settings-animated-pages section="${testRoutes.PRIVACY.section}">
         <div route-path="default"></div>
         <settings-subpage route-path="${testRoutes.SITE_SETTINGS.path}">
           <div></div>
         </settings-subpage>
-      </settings-animated-pages>`;
+      </settings-animated-pages>`);
 
     const subpage = document.body.querySelector('settings-subpage')!;
     let counter = 0;
diff --git a/chrome/test/data/webui/settings/settings_performance_menu_test.ts b/chrome/test/data/webui/settings/settings_performance_menu_test.ts
index 233bcb1..60f625c7 100644
--- a/chrome/test/data/webui/settings/settings_performance_menu_test.ts
+++ b/chrome/test/data/webui/settings/settings_performance_menu_test.ts
@@ -16,7 +16,7 @@
   }
 
   setup(function() {
-    document.body.innerHTML = '';
+    document.body.innerHTML = window.trustedTypes!.emptyHTML;
     Router.getInstance().navigateTo(routes.PERFORMANCE, undefined);
     settingsMenu = document.createElement('settings-menu');
     settingsMenu.pageVisibility = pageVisibility;
@@ -54,4 +54,4 @@
         getPerformanceMenuItem()!.hidden,
         'performance menu item should be hidden when pageVisibility is false');
   });
-});
\ No newline at end of file
+});
diff --git a/chrome/test/data/webui/settings/trusted_html.ts b/chrome/test/data/webui/settings/trusted_html.ts
new file mode 100644
index 0000000..98d861a
--- /dev/null
+++ b/chrome/test/data/webui/settings/trusted_html.ts
@@ -0,0 +1,25 @@
+// 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.
+
+/**
+ * @fileoverview Provides a way to create TrustedHTML for HTML code that is
+ * injected during tests and can't leverage
+ * ui/webui/resources/js/static_types.ts because the HTML is not fully static.
+ */
+
+let policy: TrustedTypePolicy|null = null;
+
+export function getTrustedHtml(html: string): TrustedHTML {
+  if (policy === null) {
+    policy = window.trustedTypes!.createPolicy('webui-test-html', {
+      // Policy only used in test code, no need for any sanitization. DO NOT use
+      // in prod code.
+      createHTML: html => html,
+      createScriptURL: () => '',
+      createScript: () => '',
+    });
+  }
+
+  return policy.createHTML(html);
+}
diff --git a/chrome/test/data/webui/test_browser_proxy.d.ts b/chrome/test/data/webui/test_browser_proxy.d.ts
deleted file mode 100644
index 3da734a..0000000
--- a/chrome/test/data/webui/test_browser_proxy.d.ts
+++ /dev/null
@@ -1,16 +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.
-
-export class TestBrowserProxy<T = any> {
-  static fromClass<T>(clazz: {new(): T}): T&TestBrowserProxy<T>;
-  constructor(methodNames?: Array<keyof T>);
-  methodCalled(methodName: keyof T, ...args: any[]): any;
-  whenCalled(methodName: keyof T): Promise<any>;
-  resetResolver(methodName: keyof T): void;
-  reset(): void;
-  getCallCount(methodName: keyof T): number;
-  getArgs(methodName: keyof T): any[];
-  setResultMapperFor(methodName: keyof T, resultMapper: Function): void;
-  setResultFor(methodName: keyof T, value: any): void;
-}
diff --git a/chrome/test/data/webui/test_browser_proxy.ts b/chrome/test/data/webui/test_browser_proxy.ts
new file mode 100644
index 0000000..1305dd8
--- /dev/null
+++ b/chrome/test/data/webui/test_browser_proxy.ts
@@ -0,0 +1,175 @@
+// Copyright 2016 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {assert} from 'chrome://resources/js/assert_ts.js';
+import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
+
+type Constructor<T> = new (...args: any[]) => T;
+
+interface MethodData {
+  resolver: PromiseResolver<any>;
+  args: any[];
+  resultMapper?: Function;
+}
+
+/**
+ * A base class for all test browser proxies to inherit from. Provides helper
+ * methods for allowing tests to track when a method was called.
+ *
+ * Subclasses are responsible for calling |methodCalled|, when a method is
+ * called, which will trigger callers of |whenCalled| to get notified.
+ * For example:
+ * --------------------------------------------------------------------------
+ * class MyTestBrowserProxy extends TestBrowserProxy {
+ *   constructor() {
+ *     super(['myMethod']);
+ *   }
+ *
+ *   myMethod(someId) {
+ *     this.methodCalled('myMethod', someId);
+ *   }
+ * };
+ *
+ * // Test code sample
+ *
+ * var testBrowserProxy = new MyTestBrowserProxy();
+ * // ...Replacing real proxy with test proxy....
+ * simulateClickFooButton();
+ * testBrowserProxy.whenCalled('fooMethod').then(function(id) {
+ *   assertEquals(EXPECTED_ID, id);
+ * });
+ * --------------------------------------------------------------------------
+ */
+export class TestBrowserProxy {
+  private resolverMap_: Map<string, MethodData>;
+
+  /**
+   * @param methodNames Names of all methods whose calls need to be tracked.
+   */
+  constructor(methodNames: string[] = []) {
+    this.resolverMap_ = new Map();
+    methodNames.forEach(methodName => {
+      this.createMethodData_(methodName);
+    });
+  }
+
+  /**
+   * Creates a |TestBrowserProxy|, which has mock functions for all functions of
+   * class |clazz|.
+   */
+  static fromClass<T>(clazz: Constructor<T>): (T&TestBrowserProxy) {
+    const methodNames = Object.getOwnPropertyNames(clazz.prototype)
+                            .filter(methodName => methodName !== 'constructor');
+    const proxy = new TestBrowserProxy(methodNames);
+    proxy.mockMethods_(methodNames);
+    return proxy as unknown as (T&TestBrowserProxy);
+  }
+
+  /**
+   * Creates a mock implementation for each method name. These mocks allow tests
+   * to either set a result when the mock is called using
+   * |setResultFor(methodName)|, or set a result mapper function that will be
+   * invoked when a method is called using |setResultMapperFor(methodName)|.
+   */
+  private mockMethods_(methodNames: string[]) {
+    methodNames.forEach(methodName => {
+      (this as unknown as {[key: string]: Function})[methodName] =
+          (...args: any[]) => this.methodCalled(methodName, ...args);
+    });
+  }
+
+  /**
+   * Called by subclasses when a tracked method is called from the code that
+   * is being tested.
+   * @param args Arguments to be forwarded to the testing code, useful for
+   *     checking whether the proxy method was called with the expected
+   *     arguments.
+   * @return If set the result registered via |setResult[Mapper]For|.
+   */
+  methodCalled(methodName: string, ...args: any[]): any {
+    const methodData = this.resolverMap_.get(methodName);
+    assert(methodData);
+    const storedArgs = args.length === 1 ? args[0] : args;
+    methodData.args.push(storedArgs);
+    this.resolverMap_.set(methodName, methodData);
+    methodData.resolver.resolve(storedArgs);
+    if (methodData.resultMapper) {
+      return methodData.resultMapper(...args);
+    }
+  }
+
+  /**
+   * @return A promise that is resolved when the given method is called.
+   */
+  whenCalled(methodName: string): Promise<any> {
+    return this.getMethodData_(methodName).resolver.promise;
+  }
+
+  /**
+   * Resets the PromiseResolver associated with the given method.
+   */
+  resetResolver(methodName: string) {
+    this.getMethodData_(methodName);
+    this.createMethodData_(methodName);
+  }
+
+  /**
+   * Resets all PromiseResolvers.
+   */
+  reset() {
+    this.resolverMap_.forEach((_value, methodName) => {
+      this.createMethodData_(methodName);
+    });
+  }
+
+  /**
+   * Get number of times method is called.
+   */
+  getCallCount(methodName: string): number {
+    return this.getMethodData_(methodName).args.length;
+  }
+
+  /**
+   * Returns the arguments of calls made to |method|.
+   */
+  getArgs(methodName: string): any[] {
+    return this.getMethodData_(methodName).args;
+  }
+
+  /**
+   * Sets a function |resultMapper| that is called with the original arguments
+   * passed to method named |methodName|. This allows a test to return a unique
+   * object each method invovation or have the returned value be different based
+   * on the arguments.
+   */
+  setResultMapperFor(methodName: string, resultMapper: Function) {
+    this.getMethodData_(methodName).resultMapper = resultMapper;
+  }
+
+  /**
+   * Sets the return value of a method.
+   */
+  setResultFor(methodName: string, value: any) {
+    this.getMethodData_(methodName).resultMapper = () => value;
+  }
+
+  /**
+   * Try to give programmers help with mistyped methodNames.
+   */
+  private getMethodData_(methodName: string): MethodData {
+    // Tip: check that the |methodName| is being passed to |this.constructor|.
+    const methodData = this.resolverMap_.get(methodName);
+    assert(
+        methodData, `Method '${methodName}' not found in TestBrowserProxy.`);
+    return methodData;
+  }
+
+  /**
+   * Creates a new |MethodData| for |methodName|.
+   */
+  private createMethodData_(methodName: string) {
+    this.resolverMap_.set(
+        methodName, {resolver: new PromiseResolver(), args: []});
+  }
+}
diff --git a/chrome/test/data/webui/test_plural_string_proxy.ts b/chrome/test/data/webui/test_plural_string_proxy.ts
index 0d0f7e1a..ab1c683 100644
--- a/chrome/test/data/webui/test_plural_string_proxy.ts
+++ b/chrome/test/data/webui/test_plural_string_proxy.ts
@@ -7,7 +7,7 @@
 // clang-format off
 import {PluralStringProxy} from 'chrome://resources/js/plural_string_proxy.js';
 
-import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
+import {TestBrowserProxy} from './test_browser_proxy.js';
 // clang-format on
 
 /**
diff --git a/chrome/test/data/webui/test_store_ts.ts b/chrome/test/data/webui/test_store_ts.ts
index 1a16d49..f1ac8b9 100644
--- a/chrome/test/data/webui/test_store_ts.ts
+++ b/chrome/test/data/webui/test_store_ts.ts
@@ -4,7 +4,7 @@
 
 import {Action, Store} from 'chrome://resources/js/store_ts.js';
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
-import {assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertTrue} from './chai_assert.js';
 
 /**
  * This is a generic test store, designed to replace a real Store instance
diff --git a/chrome/test/data/webui/text_defaults_test.ts b/chrome/test/data/webui/text_defaults_test.ts
index 6076c5c..9b9cde90 100644
--- a/chrome/test/data/webui/text_defaults_test.ts
+++ b/chrome/test/data/webui/text_defaults_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 {assertEquals, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertNotEquals, assertTrue} from './chai_assert.js';
 
 /**
  * @param html Text, possibly with HTML &entities; in it.
diff --git a/chrome/test/data/webui/tsconfig_base.json b/chrome/test/data/webui/tsconfig_base.json
index fd3b64d6..e652212e 100644
--- a/chrome/test/data/webui/tsconfig_base.json
+++ b/chrome/test/data/webui/tsconfig_base.json
@@ -4,6 +4,6 @@
     "typeRoots": [
         "./../../../../third_party/node/node_modules/@types"
     ],
-    "types": ["mocha", "trusted-types"]
+    "types": ["chai", "mocha", "trusted-types"]
   }
 }
diff --git a/chrome/test/interaction/README.md b/chrome/test/interaction/README.md
index 60c0edb..06977d2 100644
--- a/chrome/test/interaction/README.md
+++ b/chrome/test/interaction/README.md
@@ -81,8 +81,8 @@
     - `CheckViewProperty()` [Views]
     - `Screenshot` [Browser] - compares the target against Skia Gold in pixel
       tests
-- **WaitFor** verbs ensure that the given UI event happens before proceeding.
-  Examples:
+- **WaitFor** verbs ensure that the given UI event happens or condition becomes
+  true before proceeding. Examples:
     - `WaitForShow()`
     - `WaitForHide()`
     - `WaitForActivated()`
@@ -102,7 +102,9 @@
   Unlike the above verbs, it will not wait; the element must exist when the step
   triggers or the test will fail.
 - **EnsureNotPresent** is the opposite of `WithElement`; if the element exists
-  when the step is triggered, the test fails.
+  when the step is triggered, the test fails. There is also a version that looks
+  for a DOM element in an
+  [instrumented WebContents](#webcontents-instrumentation) [Browser].
 - **Action** verbs simulate input to specific UI elements. You may specify the
   type of input you want to simulate (keyboard, mouse, etc.) but you don't have
   to. Examples:
@@ -125,6 +127,17 @@
     - `NameChildView()` [Views]
     - `NameDescendantView()` [Views]
     - `NameViewRelative()` [Views]
+- **Javascript** verbs execute javascript in an
+  [instrumented WebContents](#webcontents-instrumentation), or verify a result
+  from calling a javascript function. The `*At()` methods take a
+  [DeepQuery](#specifying-dom-elements) and operate on a specific DOM element
+  (possibly in a Shadow DOM), while the non-at methods operate at global scope.
+  If you are not sure if the target element exists or the condition is true yet,
+  use `WaitForStateChange()` instead. Examples:
+   - `ExecuteJs()` [Browser]
+   - `ExecuteJsAt()` [Browser]
+   - `CheckJsResult()` [Browser]
+   - `CheckJsResultAt()` [Browser]
 
 Example with mouse input:
 ```cpp
@@ -154,7 +167,7 @@
 
 A modifier wraps around a step and changes its behavior. Currently there is only one modifier:
 - **InAnyContext** allows the modified verb to find an element by its identifier
-  outside the test's default `ElementContext`. It has no effect on
+  outside the test's default `ElementContext`. It has no effect on some versions of
   `EnsureNotPresent()`, and is not compatible with named elements or with some
   specific verbs. Use sparingly.
 
@@ -166,7 +179,7 @@
     InAnyContext(CheckView(kMyButton, ensure_pressed)));
 ```
 
-### Instrumentation
+### WebContents Instrumentation
 
 A feature of `InteractiveBrowserTestApi` that it borrows from
 [WebContentsInteractoinTestUtil](/chrome/test/interaction/webcontents_interaction_test_util.h)
@@ -186,6 +199,25 @@
   that uses a `WebView` and is not a tab (e.g. the tablet tabstrip or Tab Search
   dialog).
 
+#### Specifying DOM Elements
+
+Certain verbs that operate on instrumented WebContents take a `DeepQuery`, which
+provides a path to a DOM element in the WebContents. A `DeepQuery` is a sequence
+of one or more element selectors, as taken by the JavaScript `querySelector()`
+method. A `DeepQuery` works as follows:
+
+```js
+let cur = document;
+for (let selector of deepQuery) {
+  if (cur.shadowRoot)
+    cur = cur.shadowRoot;
+  cur = cur.querySelector(selector);
+}  
+```
+
+If at any point the selector fails, the target DOM element is determined not to
+exist. Often, this fails the test, but might not in all cases. 
+
 ### Automatic Conversion
 
 The following convenience methods are provided to convert a `TrackedElement*` to
diff --git a/chrome/test/interaction/interactive_browser_test.cc b/chrome/test/interaction/interactive_browser_test.cc
index e52a48036..751e9e8 100644
--- a/chrome/test/interaction/interactive_browser_test.cc
+++ b/chrome/test/interaction/interactive_browser_test.cc
@@ -7,6 +7,7 @@
 
 #include "base/auto_reset.h"
 #include "base/check.h"
+#include "base/strings/string_util.h"
 #include "base/test/bind.h"
 #include "base/test/rectify_callback.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -16,6 +17,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/interaction/interaction_test_util_browser.h"
 #include "chrome/test/interaction/tracked_element_webcontents.h"
+#include "chrome/test/interaction/webcontents_interaction_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
 #include "ui/base/interaction/element_identifier.h"
@@ -215,6 +217,97 @@
   return steps;
 }
 
+// static
+ui::InteractionSequence::StepBuilder
+InteractiveBrowserTestApi::EnsureNotPresent(
+    ui::ElementIdentifier webcontents_id,
+    DeepQuery where) {
+  StepBuilder builder;
+  builder.SetElementID(webcontents_id);
+  builder.SetStartCallback(base::BindOnce(
+      [](DeepQuery where, ui::InteractionSequence* seq,
+         ui::TrackedElement* el) {
+        if (AsInstrumentedWebContents(el)->Exists(where)) {
+          LOG(ERROR) << "Expected DOM element not to be present: \""
+                     << base::JoinString(where, "\", \"") << "\"";
+          seq->FailForTesting();
+        }
+      },
+      where));
+  return builder;
+}
+
+// static
+ui::InteractionSequence::StepBuilder InteractiveBrowserTestApi::ExecuteJs(
+    ui::ElementIdentifier webcontents_id,
+    const std::string& function) {
+  StepBuilder builder;
+  builder.SetElementID(webcontents_id);
+  builder.SetStartCallback(base::BindOnce(
+      [](std::string function, ui::TrackedElement* el) {
+        AsInstrumentedWebContents(el)->Execute(function);
+      },
+      function));
+  return builder;
+}
+
+// static
+ui::InteractionSequence::StepBuilder InteractiveBrowserTestApi::ExecuteJsAt(
+    ui::ElementIdentifier webcontents_id,
+    DeepQuery where,
+    const std::string& function) {
+  StepBuilder builder;
+  builder.SetElementID(webcontents_id);
+  builder.SetStartCallback(base::BindOnce(
+      [](DeepQuery where, std::string function, ui::TrackedElement* el) {
+        AsInstrumentedWebContents(el)->ExecuteAt(where, function);
+      },
+      std::move(where), function));
+  return builder;
+}
+
+// static
+ui::InteractionSequence::StepBuilder InteractiveBrowserTestApi::CheckJsResult(
+    ui::ElementIdentifier webcontents_id,
+    const std::string& function) {
+  StepBuilder builder;
+  builder.SetElementID(webcontents_id);
+  builder.SetStartCallback(base::BindOnce(
+      [](std::string function, ui::InteractionSequence* seq,
+         ui::TrackedElement* el) {
+        const auto result = AsInstrumentedWebContents(el)->Evaluate(function);
+        if (!WebContentsInteractionTestUtil::IsTruthy(result)) {
+          LOG(ERROR) << "CheckJsResult(): result of function is falsy: "
+                     << result;
+          seq->FailForTesting();
+        }
+      },
+      function));
+  return builder;
+}
+
+// static
+ui::InteractionSequence::StepBuilder InteractiveBrowserTestApi::CheckJsResultAt(
+    ui::ElementIdentifier webcontents_id,
+    DeepQuery where,
+    const std::string& function) {
+  StepBuilder builder;
+  builder.SetElementID(webcontents_id);
+  builder.SetStartCallback(base::BindOnce(
+      [](DeepQuery where, std::string function, ui::InteractionSequence* seq,
+         ui::TrackedElement* el) {
+        const auto result =
+            AsInstrumentedWebContents(el)->EvaluateAt(where, function);
+        if (!WebContentsInteractionTestUtil::IsTruthy(result)) {
+          LOG(ERROR) << "CheckJsResultAt(): result of function is falsy: "
+                     << result;
+          seq->FailForTesting();
+        }
+      },
+      where, function));
+  return builder;
+}
+
 InteractiveBrowserTestApi::MultiStep InteractiveBrowserTestApi::MoveMouseTo(
     ElementSpecifier web_contents,
     DeepQuery where) {
diff --git a/chrome/test/interaction/interactive_browser_test.h b/chrome/test/interaction/interactive_browser_test.h
index 0a928b0..181f95782 100644
--- a/chrome/test/interaction/interactive_browser_test.h
+++ b/chrome/test/interaction/interactive_browser_test.h
@@ -128,6 +128,77 @@
       StateChange state_change,
       bool expect_timeout = false);
 
+  // Required to keep from hiding inherited versions of this method.
+  using InteractiveViewsTestApi::EnsureNotPresent;
+
+  // Ensures that there is no element at path `where` in `webcontents_id`.
+  // Unlike InteractiveTestApi::EnsureNotPresent, you can use `InAnyContext`()`
+  // with this method; it will only be used to locate `webcontents_id`.
+  [[nodiscard]] static StepBuilder EnsureNotPresent(
+      ui::ElementIdentifier webcontents_id,
+      DeepQuery where);
+
+  // Execute javascript `function`, which should take no arguments, in
+  // WebContents `webcontents_id`.
+  [[nodiscard]] static StepBuilder ExecuteJs(
+      ui::ElementIdentifier webcontents_id,
+      const std::string& function);
+
+  // Execute javascript `function`, which should take a single DOM element as an
+  // argument, with the element at `where`, in WebContents `webcontents_id`.
+  [[nodiscard]] static StepBuilder ExecuteJsAt(
+      ui::ElementIdentifier webcontents_id,
+      DeepQuery where,
+      const std::string& function);
+
+  // Executes javascript `function`, which should take no arguments and return a
+  // value, in WebContents `webcontents_id`, and fails if the result is not
+  // truthy.
+  [[nodiscard]] static StepBuilder CheckJsResult(
+      ui::ElementIdentifier webcontents_id,
+      const std::string& function);
+
+  // Executes javascript `function`, which should take no arguments and return a
+  // value, in WebContents `webcontents_id`, and fails if the result does not
+  // match `matcher`, which can be a literal or a testing::Matcher.
+  //
+  // Note that only the following types are supported:
+  //  - string (for literals, you may pass a const char*)
+  //  - bool
+  //  - int
+  //  - double (will also match integer return values)
+  //  - base::Value (required if you want to match a list or dictionary)
+  //
+  // You must pass a literal or Matcher that matches the type returned by the
+  // javascript function. If your function could return either an integer or a
+  // floating-point value, you *must* use a double.
+  template <typename T>
+  [[nodiscard]] static StepBuilder CheckJsResult(
+      ui::ElementIdentifier webcontents_id,
+      const std::string& function,
+      T&& matcher);
+
+  // Executes javascript `function`, which should take a single DOM element as
+  // an argument and returns a value, in WebContents `webcontents_id` on the
+  // element specified by `where`, and fails if the result is not truthy.
+  [[nodiscard]] static StepBuilder CheckJsResultAt(
+      ui::ElementIdentifier webcontents_id,
+      DeepQuery where,
+      const std::string& function);
+
+  // Executes javascript `function`, which should take a single DOM element as
+  // an argument and returns a value, in WebContents `webcontents_id` on the
+  // element specified by `where`, and fails if the result does not match
+  // `matcher`, which can be a literal or a testing::Matcher.
+  //
+  // See notes on CheckJsResult() for what values and Matchers are supported.
+  template <typename T>
+  [[nodiscard]] static StepBuilder CheckJsResultAt(
+      ui::ElementIdentifier webcontents_id,
+      DeepQuery where,
+      const std::string& function,
+      T&& matcher);
+
   // These are required so the following overloads don't hide the base class
   // variations.
   using InteractiveViewsTestApi::DragMouseTo;
@@ -185,4 +256,27 @@
   void TearDownOnMainThread() override;
 };
 
+// Template definitions:
+
+// static
+template <typename T>
+ui::InteractionSequence::StepBuilder InteractiveBrowserTestApi::CheckJsResult(
+    ui::ElementIdentifier webcontents_id,
+    const std::string& function,
+    T&& matcher) {
+  return internal::JsResultChecker<T>::CheckJsResult(webcontents_id, function,
+                                                     std::move(matcher));
+}
+
+// static
+template <typename T>
+ui::InteractionSequence::StepBuilder InteractiveBrowserTestApi::CheckJsResultAt(
+    ui::ElementIdentifier webcontents_id,
+    DeepQuery where,
+    const std::string& function,
+    T&& matcher) {
+  return internal::JsResultChecker<T>::CheckJsResultAt(
+      webcontents_id, where, function, std::move(matcher));
+}
+
 #endif  // CHROME_TEST_INTERACTION_INTERACTIVE_BROWSER_TEST_H_
diff --git a/chrome/test/interaction/interactive_browser_test_browsertest.cc b/chrome/test/interaction/interactive_browser_test_browsertest.cc
new file mode 100644
index 0000000..39ce067b
--- /dev/null
+++ b/chrome/test/interaction/interactive_browser_test_browsertest.cc
@@ -0,0 +1,190 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/test/bind.h"
+#include "chrome/test/interaction/interactive_browser_test.h"
+
+#include "base/bind.h"
+#include "content/public/test/browser_test.h"
+#include "ui/base/interaction/element_identifier.h"
+#include "ui/base/interaction/expect_call_in_scope.h"
+#include "ui/base/interaction/interaction_sequence.h"
+#include "url/gurl.h"
+
+namespace {
+DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kWebContentsId);
+constexpr char kDocumentWithNamedElement[] = "/select.html";
+}  // namespace
+
+class InteractiveBrowserTestBrowsertest : public InteractiveBrowserTest {
+ public:
+  InteractiveBrowserTestBrowsertest() = default;
+  ~InteractiveBrowserTestBrowsertest() override = default;
+
+  void SetUp() override {
+    set_open_about_blank_on_browser_launch(true);
+    ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
+    InteractiveBrowserTest::SetUp();
+  }
+
+  void SetUpOnMainThread() override {
+    InteractiveBrowserTest::SetUpOnMainThread();
+    embedded_test_server()->StartAcceptingConnections();
+  }
+
+  void TearDownOnMainThread() override {
+    EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
+    InteractiveBrowserTest::TearDownOnMainThread();
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(InteractiveBrowserTestBrowsertest, EnsureNotPresent) {
+  InstrumentTab(browser(), kWebContentsId);
+
+  const GURL url = embedded_test_server()->GetURL(kDocumentWithNamedElement);
+  RunTestSequence(NavigateWebContents(kWebContentsId, url),
+                  EnsureNotPresent(kWebContentsId, DeepQuery{"#doesNotExist"}));
+}
+
+IN_PROC_BROWSER_TEST_F(InteractiveBrowserTestBrowsertest,
+                       EnsureNotPresent_Fails) {
+  UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
+  private_test_impl().set_aborted_callback_for_testing(aborted.Get());
+
+  InstrumentTab(browser(), kWebContentsId);
+  const GURL url = embedded_test_server()->GetURL(kDocumentWithNamedElement);
+  EXPECT_CALL_IN_SCOPE(
+      aborted, Run,
+      RunTestSequence(NavigateWebContents(kWebContentsId, url),
+                      EnsureNotPresent(kWebContentsId, DeepQuery{"#select"})));
+}
+
+IN_PROC_BROWSER_TEST_F(InteractiveBrowserTestBrowsertest, ExecuteJs) {
+  InstrumentTab(browser(), kWebContentsId);
+
+  const GURL url = embedded_test_server()->GetURL(kDocumentWithNamedElement);
+  RunTestSequence(
+      NavigateWebContents(kWebContentsId, url),
+      ExecuteJs(kWebContentsId, "() => { window.value = 1; }"),
+      WithElement(kWebContentsId, base::BindOnce([](ui::TrackedElement* el) {
+                    const auto result = AsInstrumentedWebContents(el)->Evaluate(
+                        "() => window.value");
+                    EXPECT_EQ(1, result.GetInt());
+                  })));
+}
+
+IN_PROC_BROWSER_TEST_F(InteractiveBrowserTestBrowsertest, CheckJsResult) {
+  InstrumentTab(browser(), kWebContentsId);
+
+  const GURL url = embedded_test_server()->GetURL(kDocumentWithNamedElement);
+  const std::string str("a string");
+  RunTestSequence(
+      NavigateWebContents(kWebContentsId, url),
+      ExecuteJs(kWebContentsId,
+                R"(() => {
+            window.intValue = 1;
+            window.boolValue = true;
+            window.doubleValue = 2.0;
+            window.stringValue = 'a string';
+          })"),
+      CheckJsResult(kWebContentsId, "() => window.intValue"),
+      CheckJsResult(kWebContentsId, "() => window.intValue", 1),
+      CheckJsResult(kWebContentsId, "() => window.intValue", testing::Lt(2)),
+      CheckJsResult(kWebContentsId, "() => window.boolValue"),
+      CheckJsResult(kWebContentsId, "() => window.boolValue", true),
+      CheckJsResult(kWebContentsId, "() => window.boolValue",
+                    testing::Ne(false)),
+      CheckJsResult(kWebContentsId, "() => window.doubleValue"),
+      CheckJsResult(kWebContentsId, "() => window.doubleValue", 2.0),
+      CheckJsResult(kWebContentsId, "() => window.doubleValue",
+                    testing::Gt(1.5)),
+      CheckJsResult(kWebContentsId, "() => window.stringValue"),
+      CheckJsResult(kWebContentsId, "() => window.stringValue", "a string"),
+      CheckJsResult(kWebContentsId, "() => window.stringValue", str),
+      CheckJsResult(kWebContentsId, "() => window.stringValue",
+                    std::string("a string")),
+      CheckJsResult(kWebContentsId, "() => window.stringValue",
+                    testing::Ne(std::string("another string"))));
+}
+
+IN_PROC_BROWSER_TEST_F(InteractiveBrowserTestBrowsertest, CheckJsResult_Fails) {
+  UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
+  private_test_impl().set_aborted_callback_for_testing(aborted.Get());
+
+  InstrumentTab(browser(), kWebContentsId);
+  const GURL url = embedded_test_server()->GetURL(kDocumentWithNamedElement);
+  EXPECT_CALL_IN_SCOPE(
+      aborted, Run,
+      RunTestSequence(NavigateWebContents(kWebContentsId, url),
+                      ExecuteJs(kWebContentsId, "() => { window.value = 1; }"),
+                      CheckJsResult(kWebContentsId, "() => window.value", 2)));
+}
+
+IN_PROC_BROWSER_TEST_F(InteractiveBrowserTestBrowsertest, ExecuteJsAt) {
+  InstrumentTab(browser(), kWebContentsId);
+  const DeepQuery kWhere{"#select"};
+  const GURL url = embedded_test_server()->GetURL(kDocumentWithNamedElement);
+  RunTestSequence(
+      NavigateWebContents(kWebContentsId, url),
+      ExecuteJsAt(kWebContentsId, kWhere, "(el) => { el.intValue = 1; }"),
+      WithElement(kWebContentsId,
+                  base::BindLambdaForTesting([&kWhere](ui::TrackedElement* el) {
+                    const auto result =
+                        AsInstrumentedWebContents(el)->EvaluateAt(
+                            kWhere, "(el) => el.intValue");
+                    EXPECT_EQ(1, result.GetInt());
+                  })));
+}
+
+IN_PROC_BROWSER_TEST_F(InteractiveBrowserTestBrowsertest, CheckJsResultAt) {
+  InstrumentTab(browser(), kWebContentsId);
+  const DeepQuery kWhere{"#select"};
+  const GURL url = embedded_test_server()->GetURL(kDocumentWithNamedElement);
+  const std::string str("a string");
+  RunTestSequence(
+      NavigateWebContents(kWebContentsId, url),
+      ExecuteJsAt(kWebContentsId, kWhere,
+                  R"((el) => {
+            el.intValue = 1;
+            el.boolValue = true;
+            el.doubleValue = 2.0;
+            el.stringValue = 'a string';
+          })"),
+      CheckJsResultAt(kWebContentsId, kWhere, "(el) => el.intValue"),
+      CheckJsResultAt(kWebContentsId, kWhere, "(el) => el.intValue", 1),
+      CheckJsResultAt(kWebContentsId, kWhere, "(el) => el.intValue",
+                      testing::Lt(2)),
+      CheckJsResultAt(kWebContentsId, kWhere, "(el) => el.boolValue"),
+      CheckJsResultAt(kWebContentsId, kWhere, "(el) => el.boolValue", true),
+      CheckJsResultAt(kWebContentsId, kWhere, "(el) => el.boolValue",
+                      testing::Ne(false)),
+      CheckJsResultAt(kWebContentsId, kWhere, "(el) => el.doubleValue"),
+      CheckJsResultAt(kWebContentsId, kWhere, "(el) => el.doubleValue", 2.0),
+      CheckJsResultAt(kWebContentsId, kWhere, "(el) => el.doubleValue",
+                      testing::Gt(1.5)),
+      CheckJsResultAt(kWebContentsId, kWhere, "(el) => el.stringValue"),
+      CheckJsResultAt(kWebContentsId, kWhere, "(el) => el.stringValue",
+                      "a string"),
+      CheckJsResultAt(kWebContentsId, kWhere, "(el) => el.stringValue", str),
+      CheckJsResultAt(kWebContentsId, kWhere, "(el) => el.stringValue",
+                      std::string("a string")),
+      CheckJsResultAt(kWebContentsId, kWhere, "(el) => el.stringValue",
+                      testing::Ne(std::string("another string"))));
+}
+
+IN_PROC_BROWSER_TEST_F(InteractiveBrowserTestBrowsertest,
+                       CheckJsResultAt_Fails) {
+  UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
+  private_test_impl().set_aborted_callback_for_testing(aborted.Get());
+
+  InstrumentTab(browser(), kWebContentsId);
+  const DeepQuery kWhere{"#select"};
+  const GURL url = embedded_test_server()->GetURL(kDocumentWithNamedElement);
+  EXPECT_CALL_IN_SCOPE(
+      aborted, Run,
+      RunTestSequence(
+          NavigateWebContents(kWebContentsId, url),
+          ExecuteJsAt(kWebContentsId, kWhere, "(el) => { el.intValue = 1; }"),
+          CheckJsResultAt(kWebContentsId, kWhere, "(el) => el.intValue", 2)));
+}
diff --git a/chrome/test/interaction/interactive_browser_test_internal.h b/chrome/test/interaction/interactive_browser_test_internal.h
index f4b663ed..c8e5d63 100644
--- a/chrome/test/interaction/interactive_browser_test_internal.h
+++ b/chrome/test/interaction/interactive_browser_test_internal.h
@@ -7,10 +7,16 @@
 
 #include <map>
 #include <memory>
+#include <utility>
 
+#include "base/strings/string_piece_forward.h"
+#include "base/template_util.h"
+#include "base/values.h"
 #include "chrome/test/interaction/interaction_test_util_browser.h"
+#include "chrome/test/interaction/tracked_element_webcontents.h"
 #include "chrome/test/interaction/webcontents_interaction_test_util.h"
 #include "ui/base/interaction/element_identifier.h"
+#include "ui/base/interaction/interaction_sequence.h"
 #include "ui/views/interaction/interactive_views_test_internal.h"
 
 class InteractiveBrowserTestApi;
@@ -38,6 +44,149 @@
       instrumented_web_contents_;
 };
 
+// Provides a template-specialized method for converting base::Value objects to
+// an expected type for a testing::Matcher<T>.
+template <typename T>
+struct JsValueExtractor {};
+
+template <>
+struct JsValueExtractor<base::Value> {
+  static base::Value Extract(base::Value v) { return v; }
+};
+
+template <>
+struct JsValueExtractor<int> {
+  static int Extract(base::Value v) {
+    if (v.is_double()) {
+      LOG(ERROR) << "Result of Js function is a double; if there is any chance "
+                    "your function will return a floating-point result, please "
+                    "use a double value or matcher.";
+    }
+    return v.GetInt();
+  }
+};
+
+template <>
+struct JsValueExtractor<double> {
+  static double Extract(base::Value v) { return v.GetDouble(); }
+};
+
+template <>
+struct JsValueExtractor<bool> {
+  static bool Extract(base::Value v) { return v.GetBool(); }
+};
+
+template <>
+struct JsValueExtractor<std::string> {
+  static std::string Extract(base::Value v) { return v.GetString(); }
+};
+
+// Provides implementations for CheckJsResult[At]().
+//
+// The default implementation assumes an arbitrary value or and builds an
+// equality testing::Matcher<T> to use for the check; e.g.:
+//
+//   const std::string kExpectedHtmlContents = "...";
+//   ...
+//   CheckJsResult(id, "() => document.innerHtml", kExpectedHtmlContents)
+//   CheckJsResult(id, "() => getFooCount()", 3)
+//
+template <typename T>
+struct JsResultChecker {
+  using V = base::remove_cvref_t<T>;
+  using M = testing::Matcher<V>;
+  static ui::InteractionSequence::StepBuilder CheckJsResult(
+      ui::ElementIdentifier webcontents_id,
+      const std::string& function,
+      T&& value) {
+    return JsResultChecker<M>::CheckJsResult(webcontents_id, function,
+                                             M(std::move(value)));
+  }
+
+  static ui::InteractionSequence::StepBuilder CheckJsResultAt(
+      ui::ElementIdentifier webcontents_id,
+      WebContentsInteractionTestUtil::DeepQuery where,
+      const std::string& function,
+      T&& value) {
+    return JsResultChecker<M>::CheckJsResultAt(webcontents_id, where, function,
+                                               M(std::move(value)));
+  }
+};
+
+// This implementation allows for a javascript string to be matched against am
+// inline string literal, e.g.:
+//
+//   CheckJsResultAt(id, {"#id"}, "el => el.innerText", "The Quick Brown Fox")
+//
+template <int N>
+struct JsResultChecker<const char (&)[N]>
+    : public JsResultChecker<std::string> {};
+
+// This implementation allows for a javascript string ot be matched against a
+// constant C-style string, e.g.:
+//
+//   const char* const kExpectedString = "The Quick Brown Fox";
+//   ...
+//   CheckJsResultAt(id, {#id}m "el => el.innerText", kExpectedString)
+//
+template <>
+struct JsResultChecker<const char*> : public JsResultChecker<std::string> {};
+
+// This implementation allows for a testing::Matcher of any kind to be passed
+// in directly; e.g.:
+//
+//   CheckJsResult(id,
+//                 "() => document.documentElement.clientWidth",
+//                 testing::Gt(500))
+//
+template <template <typename...> typename M, typename T>
+struct JsResultChecker<M<T>> {
+  using E = JsValueExtractor<base::remove_cvref_t<T>>;
+
+  static ui::InteractionSequence::StepBuilder CheckJsResult(
+      ui::ElementIdentifier webcontents_id,
+      const std::string& function,
+      M<T> matcher) {
+    ui::InteractionSequence::StepBuilder builder;
+    builder.SetElementID(webcontents_id);
+    builder.SetStartCallback(base::BindOnce(
+        [](std::string function, testing::Matcher<T> matcher,
+           ui::InteractionSequence* seq, ui::TrackedElement* el) {
+          base::Value result =
+              el->AsA<TrackedElementWebContents>()->owner()->Evaluate(function);
+          if (!ui::test::internal::MatchAndExplain(
+                  "CheckJsResult()", matcher, E::Extract(std::move(result)))) {
+            seq->FailForTesting();
+          }
+        },
+        function, testing::Matcher<T>(std::move(matcher))));
+    return builder;
+  }
+
+  static ui::InteractionSequence::StepBuilder CheckJsResultAt(
+      ui::ElementIdentifier webcontents_id,
+      WebContentsInteractionTestUtil::DeepQuery where,
+      const std::string& function,
+      M<T> matcher) {
+    ui::InteractionSequence::StepBuilder builder;
+    builder.SetElementID(webcontents_id);
+    builder.SetStartCallback(base::BindOnce(
+        [](WebContentsInteractionTestUtil::DeepQuery where,
+           std::string function, testing::Matcher<T> matcher,
+           ui::InteractionSequence* seq, ui::TrackedElement* el) {
+          base::Value result =
+              el->AsA<TrackedElementWebContents>()->owner()->EvaluateAt(
+                  where, function);
+          if (!ui::test::internal::MatchAndExplain(
+                  "CheckJsResult()", matcher, E::Extract(std::move(result)))) {
+            seq->FailForTesting();
+          }
+        },
+        where, function, testing::Matcher<T>(std::move(matcher))));
+    return builder;
+  }
+};
+
 }  // namespace internal
 
 #endif  // CHROME_TEST_INTERACTION_INTERACTIVE_BROWSER_TEST_INTERNAL_H_
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn
index 55579400..31b51cf 100644
--- a/chrome/updater/BUILD.gn
+++ b/chrome/updater/BUILD.gn
@@ -169,12 +169,16 @@
     ]
 
     if (is_posix) {
-      sources += [ "remove_uninstalled_apps_task_posix.cc" ]
+      sources += [
+        "activity_impl_posix.cc",
+        "activity_impl_util_posix.h",
+        "remove_uninstalled_apps_task_posix.cc",
+      ]
     }
 
     if (is_mac) {
       sources += [
-        "activity_impl_mac.cc",
+        "activity_impl_util_mac.cc",
         "app/app_install_mac.mm",
         "app/server/mac/app_server.h",
         "app/server/mac/server.h",
@@ -183,6 +187,8 @@
         "app/server/mac/service_delegate.mm",
         "device_management/dm_storage_mac.mm",
         "installer_mac.cc",
+        "ipc/update_service_internal_proxy_mac.h",
+        "ipc/update_service_internal_proxy_mac.mm",
         "launchd_util.cc",
         "launchd_util.h",
         "mac/install_from_archive.h",
@@ -190,8 +196,6 @@
         "mac/setup/keystone.h",
         "mac/setup/keystone.mm",
         "mac/setup/setup.mm",
-        "mac/update_service_internal_proxy.h",
-        "mac/update_service_internal_proxy.mm",
         "net/network_fetcher_mac.mm",
         "policy/mac/managed_preference_policy_manager.h",
         "policy/mac/managed_preference_policy_manager.mm",
@@ -233,6 +237,8 @@
         "app/server/win/updater_legacy_idl.h",
         "app/server/win/wrl_classes.cc",
         "device_management/dm_storage_win.cc",
+        "ipc/update_service_internal_proxy_win.cc",
+        "ipc/update_service_internal_proxy_win.h",
         "net/network_fetcher_win.cc",
         "policy/win/group_policy_manager.cc",
         "policy/win/group_policy_manager.h",
@@ -284,8 +290,6 @@
         "win/ui/ui_util.h",
         "win/ui/yes_no_dialog.cc",
         "win/ui/yes_no_dialog.h",
-        "win/update_service_internal_proxy.cc",
-        "win/update_service_internal_proxy.h",
       ]
       deps += [
         "//build:branding_buildflags",
@@ -319,17 +323,17 @@
 
     if (is_linux) {
       sources += [
-        "activity_impl_linux.cc",
+        "activity_impl_util_linux.cc",
         "app/server/linux/server.cc",
         "app/server/linux/server.h",
         "app/server/linux/update_service_stub.cc",
         "app/server/linux/update_service_stub.h",
         "device_management/dm_storage_linux.cc",
+        "ipc/update_service_internal_proxy_linux.cc",
+        "ipc/update_service_internal_proxy_linux.h",
         "linux/ipc_support.cc",
         "linux/ipc_support.h",
         "linux/setup/setup.cc",
-        "linux/update_service_internal_proxy.cc",
-        "linux/update_service_internal_proxy.h",
         "net/network_fetcher_linux.cc",
         "prefs_linux.cc",
         "setup_linux.cc",
@@ -520,11 +524,11 @@
 
     if (is_win) {
       sources += [
+        "ipc/proxy_impl_base_win.h",
         "ipc/update_service_proxy_win.cc",
         "ipc/update_service_proxy_win.h",
         "util/win_util.cc",
         "util/win_util.h",
-        "win/proxy_impl_base.h",
         "win/scoped_handle.h",
         "win/user_info.cc",
         "win/user_info.h",
diff --git a/chrome/updater/activity_impl_linux.cc b/chrome/updater/activity_impl_linux.cc
deleted file mode 100644
index 0524481..0000000
--- a/chrome/updater/activity_impl_linux.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/updater/activity.h"
-
-#include <string>
-
-#include "base/notreached.h"
-#include "chrome/updater/updater_scope.h"
-
-namespace updater {
-
-// TODO(crbug.com/1276080) : needs implementations for actives API.
-
-bool GetActiveBit(UpdaterScope /*scope*/, const std::string& /*id*/) {
-  NOTIMPLEMENTED();
-  return true;
-}
-
-void ClearActiveBit(UpdaterScope /*scope*/, const std::string& /*id*/) {
-  NOTIMPLEMENTED();
-}
-
-}  // namespace updater
diff --git a/chrome/updater/activity_impl_mac.cc b/chrome/updater/activity_impl_mac.cc
deleted file mode 100644
index 8765087f..0000000
--- a/chrome/updater/activity_impl_mac.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/updater/activity_impl.h"
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <string>
-#include <vector>
-
-#include "base/files/file_enumerator.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/logging.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/ranges/algorithm.h"
-#include "chrome/updater/updater_branding.h"
-#include "chrome/updater/updater_scope.h"
-#include "chrome/updater/util/mac_util.h"
-
-namespace updater {
-namespace {
-
-std::vector<base::FilePath> GetHomeDirPaths(UpdaterScope scope) {
-  switch (scope) {
-    case UpdaterScope::kUser: {
-      const base::FilePath path = base::GetHomeDir();
-      if (path.empty())
-        return {};
-      return {path};
-    }
-    case UpdaterScope::kSystem: {
-      base::FileEnumerator enumerator(
-          base::FilePath(FILE_PATH_LITERAL("/Users")), /*recursive=*/false,
-          base::FileEnumerator::DIRECTORIES);
-      std::vector<base::FilePath> home_dir_paths;
-      for (base::FilePath name = enumerator.Next(); !name.empty();
-           name = enumerator.Next()) {
-        if (base::PathIsWritable(name)) {
-          home_dir_paths.push_back(name);
-        }
-      }
-      return home_dir_paths;
-    }
-  }
-}
-
-base::FilePath GetActiveFile(const base::FilePath& home_dir,
-                             const std::string& id) {
-  return home_dir.AppendASCII("Library")
-      .AppendASCII(COMPANY_SHORTNAME_STRING)
-      .AppendASCII(COMPANY_SHORTNAME_STRING "SoftwareUpdate")
-      .AppendASCII("Actives")
-      .AppendASCII(id);
-}
-
-void ClearActiveBit(const base::FilePath& home_dir, const std::string& id) {
-  struct stat home_buffer = {0};
-  if (stat(home_dir.value().c_str(), &home_buffer)) {
-    VPLOG(2) << "Failed to stat " << home_dir;
-    return;
-  }
-
-  const base::FilePath active_file_path = GetActiveFile(home_dir, id);
-  const base::ScopedFD dir_fd(
-      HANDLE_EINTR(open(active_file_path.DirName().value().c_str(), O_RDONLY)));
-  if (!dir_fd.is_valid()) {
-    return;
-  }
-  struct stat active_file_buffer = {0};
-  if (fstatat(dir_fd.get(), active_file_path.BaseName().value().c_str(),
-              &active_file_buffer, AT_SYMLINK_NOFOLLOW)) {
-    return;
-  }
-  if (active_file_buffer.st_uid != home_buffer.st_uid) {
-    return;
-  }
-  unlinkat(dir_fd.get(), active_file_path.BaseName().value().c_str(), 0);
-}
-
-}  // namespace
-
-bool GetActiveBit(UpdaterScope scope, const std::string& id) {
-  return base::ranges::any_of(
-      GetHomeDirPaths(scope), [&id](const base::FilePath& path) {
-        const base::FilePath& active_file = GetActiveFile(path, id);
-        return base::PathExists(active_file) &&
-               base::PathIsWritable(active_file);
-      });
-}
-
-void ClearActiveBit(UpdaterScope scope, const std::string& id) {
-  for (const base::FilePath& home_dir : GetHomeDirPaths(scope)) {
-    ClearActiveBit(home_dir, id);
-  }
-}
-
-}  // namespace updater
diff --git a/chrome/updater/activity_impl_posix.cc b/chrome/updater/activity_impl_posix.cc
new file mode 100644
index 0000000..12baf0f1
--- /dev/null
+++ b/chrome/updater/activity_impl_posix.cc
@@ -0,0 +1,64 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/updater/activity_impl.h"
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include "base/files/file.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_file.h"
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/ranges/algorithm.h"
+#include "chrome/updater/activity_impl_util_posix.h"
+
+namespace updater {
+enum class UpdaterScope;
+
+void ClearActiveBit(const base::FilePath& home_dir, const std::string& id) {
+  struct stat home_buffer = {0};
+  if (stat(home_dir.value().c_str(), &home_buffer)) {
+    VPLOG(2) << "Failed to stat " << home_dir;
+    return;
+  }
+
+  const base::FilePath active_file_path = GetActiveFile(home_dir, id);
+  const base::ScopedFD dir_fd(
+      HANDLE_EINTR(open(active_file_path.DirName().value().c_str(), O_RDONLY)));
+  if (!dir_fd.is_valid()) {
+    return;
+  }
+  struct stat active_file_buffer = {0};
+  if (fstatat(dir_fd.get(), active_file_path.BaseName().value().c_str(),
+              &active_file_buffer, AT_SYMLINK_NOFOLLOW)) {
+    return;
+  }
+  if (active_file_buffer.st_uid != home_buffer.st_uid) {
+    return;
+  }
+  unlinkat(dir_fd.get(), active_file_path.BaseName().value().c_str(), 0);
+}
+
+bool GetActiveBit(UpdaterScope scope, const std::string& id) {
+  return base::ranges::any_of(
+      GetHomeDirPaths(scope), [&id](const base::FilePath& path) {
+        const base::FilePath& active_file = GetActiveFile(path, id);
+        return base::PathExists(active_file) &&
+               base::PathIsWritable(active_file);
+      });
+}
+
+void ClearActiveBit(UpdaterScope scope, const std::string& id) {
+  for (const base::FilePath& home_dir : GetHomeDirPaths(scope)) {
+    ClearActiveBit(home_dir, id);
+  }
+}
+
+}  // namespace updater
diff --git a/chrome/updater/activity_impl_util_linux.cc b/chrome/updater/activity_impl_util_linux.cc
new file mode 100644
index 0000000..7089dc4
--- /dev/null
+++ b/chrome/updater/activity_impl_util_linux.cc
@@ -0,0 +1,26 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/updater/activity_impl_util_posix.h"
+
+#include <string>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/notreached.h"
+#include "chrome/updater/updater_scope.h"
+
+namespace updater {
+std::vector<base::FilePath> GetHomeDirPaths(UpdaterScope scope) {
+  NOTREACHED();
+  return {};
+}
+
+base::FilePath GetActiveFile(const base::FilePath& home_dir,
+                             const std::string& id) {
+  NOTREACHED();
+  return base::FilePath();
+}
+
+}  // namespace updater
diff --git a/chrome/updater/activity_impl_util_mac.cc b/chrome/updater/activity_impl_util_mac.cc
new file mode 100644
index 0000000..e9c0d5b
--- /dev/null
+++ b/chrome/updater/activity_impl_util_mac.cc
@@ -0,0 +1,51 @@
+// Copyright 2020 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/updater/activity_impl_util_posix.h"
+
+#include <string>
+#include <vector>
+
+#include "base/files/file_enumerator.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "chrome/updater/updater_branding.h"
+#include "chrome/updater/updater_scope.h"
+
+namespace updater {
+
+std::vector<base::FilePath> GetHomeDirPaths(UpdaterScope scope) {
+  switch (scope) {
+    case UpdaterScope::kUser: {
+      const base::FilePath path = base::GetHomeDir();
+      if (path.empty())
+        return {};
+      return {path};
+    }
+    case UpdaterScope::kSystem: {
+      base::FileEnumerator enumerator(
+          base::FilePath(FILE_PATH_LITERAL("/Users")), /*recursive=*/false,
+          base::FileEnumerator::DIRECTORIES);
+      std::vector<base::FilePath> home_dir_paths;
+      for (base::FilePath name = enumerator.Next(); !name.empty();
+           name = enumerator.Next()) {
+        if (base::PathIsWritable(name)) {
+          home_dir_paths.push_back(name);
+        }
+      }
+      return home_dir_paths;
+    }
+  }
+}
+
+base::FilePath GetActiveFile(const base::FilePath& home_dir,
+                             const std::string& id) {
+  return home_dir.AppendASCII("Library")
+      .AppendASCII(COMPANY_SHORTNAME_STRING)
+      .AppendASCII(COMPANY_SHORTNAME_STRING "SoftwareUpdate")
+      .AppendASCII("Actives")
+      .AppendASCII(id);
+}
+
+}  // namespace updater
diff --git a/chrome/updater/activity_impl_util_posix.h b/chrome/updater/activity_impl_util_posix.h
new file mode 100644
index 0000000..bc7c469
--- /dev/null
+++ b/chrome/updater/activity_impl_util_posix.h
@@ -0,0 +1,25 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_UPDATER_ACTIVITY_IMPL_UTIL_POSIX_H_
+#define CHROME_UPDATER_ACTIVITY_IMPL_UTIL_POSIX_H_
+
+#include <string>
+#include <vector>
+
+namespace base {
+class FilePath;
+}
+
+namespace updater {
+enum class UpdaterScope;
+
+std::vector<base::FilePath> GetHomeDirPaths(UpdaterScope scope);
+
+base::FilePath GetActiveFile(const base::FilePath& home_dir,
+                             const std::string& id);
+
+}  // namespace updater
+
+#endif  // CHROME_UPDATER_ACTIVITY_ACTIVITY_IMPL_UTIL_POSIX_H_
diff --git a/chrome/updater/app/server/linux/rpc_unittests.cc b/chrome/updater/app/server/linux/rpc_unittests.cc
index 09d09d9..985c9f4 100644
--- a/chrome/updater/app/server/linux/rpc_unittests.cc
+++ b/chrome/updater/app/server/linux/rpc_unittests.cc
@@ -18,9 +18,9 @@
 #include "base/version.h"
 #include "chrome/updater/app/server/linux/mojom/updater_service.mojom.h"
 #include "chrome/updater/app/server/linux/update_service_stub.h"
+#include "chrome/updater/ipc/update_service_internal_proxy_linux.h"
 #include "chrome/updater/ipc/update_service_proxy_linux.h"
 #include "chrome/updater/linux/ipc_support.h"
-#include "chrome/updater/linux/update_service_internal_proxy.h"
 #include "chrome/updater/registration_data.h"
 #include "chrome/updater/service_proxy_factory.h"
 #include "chrome/updater/update_service.h"
diff --git a/chrome/updater/win/proxy_impl_base.h b/chrome/updater/ipc/proxy_impl_base_win.h
similarity index 95%
rename from chrome/updater/win/proxy_impl_base.h
rename to chrome/updater/ipc/proxy_impl_base_win.h
index 6818cdf..81bd3158 100644
--- a/chrome/updater/win/proxy_impl_base.h
+++ b/chrome/updater/ipc/proxy_impl_base_win.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_UPDATER_WIN_PROXY_IMPL_BASE_H_
-#define CHROME_UPDATER_WIN_PROXY_IMPL_BASE_H_
+#ifndef CHROME_UPDATER_IPC_PROXY_IMPL_BASE_WIN_H_
+#define CHROME_UPDATER_IPC_PROXY_IMPL_BASE_WIN_H_
 
 #include <wrl/client.h>
 
@@ -118,4 +118,4 @@
 
 }  // namespace updater
 
-#endif  // CHROME_UPDATER_WIN_PROXY_IMPL_BASE_H_
+#endif  // CHROME_UPDATER_IPC_PROXY_IMPL_BASE_WIN_H_
diff --git a/chrome/updater/linux/update_service_internal_proxy.cc b/chrome/updater/ipc/update_service_internal_proxy_linux.cc
similarity index 98%
rename from chrome/updater/linux/update_service_internal_proxy.cc
rename to chrome/updater/ipc/update_service_internal_proxy_linux.cc
index ea9c21f..ef3bda0 100644
--- a/chrome/updater/linux/update_service_internal_proxy.cc
+++ b/chrome/updater/ipc/update_service_internal_proxy_linux.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/updater/linux/update_service_internal_proxy.h"
+#include "chrome/updater/ipc/update_service_internal_proxy_linux.h"
 
 #include <memory>
 
diff --git a/chrome/updater/linux/update_service_internal_proxy.h b/chrome/updater/ipc/update_service_internal_proxy_linux.h
similarity index 89%
rename from chrome/updater/linux/update_service_internal_proxy.h
rename to chrome/updater/ipc/update_service_internal_proxy_linux.h
index 9d013b8..f7be040 100644
--- a/chrome/updater/linux/update_service_internal_proxy.h
+++ b/chrome/updater/ipc/update_service_internal_proxy_linux.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_UPDATER_LINUX_UPDATE_SERVICE_INTERNAL_PROXY_H_
-#define CHROME_UPDATER_LINUX_UPDATE_SERVICE_INTERNAL_PROXY_H_
+#ifndef CHROME_UPDATER_IPC_UPDATE_SERVICE_INTERNAL_PROXY_LINUX_H_
+#define CHROME_UPDATER_IPC_UPDATE_SERVICE_INTERNAL_PROXY_LINUX_H_
 
 #include "chrome/updater/app/server/linux/mojom/updater_service_internal.mojom-forward.h"
 #include "chrome/updater/update_service_internal.h"
@@ -53,4 +53,4 @@
 
 }  // namespace updater
 
-#endif  // CHROME_UPDATER_LINUX_UPDATE_SERVICE_INTERNAL_PROXY_H_
+#endif  // CHROME_UPDATER_UPDATE_SERVICE_INTERNAL_PROXY_LINUX_H_
diff --git a/chrome/updater/mac/update_service_internal_proxy.h b/chrome/updater/ipc/update_service_internal_proxy_mac.h
similarity index 84%
rename from chrome/updater/mac/update_service_internal_proxy.h
rename to chrome/updater/ipc/update_service_internal_proxy_mac.h
index f67751e..60d83a1 100644
--- a/chrome/updater/mac/update_service_internal_proxy.h
+++ b/chrome/updater/ipc/update_service_internal_proxy_mac.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_UPDATER_MAC_UPDATE_SERVICE_INTERNAL_PROXY_H_
-#define CHROME_UPDATER_MAC_UPDATE_SERVICE_INTERNAL_PROXY_H_
+#ifndef CHROME_UPDATER_IPC_UPDATE_SERVICE_INTERNAL_PROXY_MAC_H_
+#define CHROME_UPDATER_IPC_UPDATE_SERVICE_INTERNAL_PROXY_MAC_H_
 
 #import <Foundation/Foundation.h>
 
@@ -42,4 +42,4 @@
 
 }  // namespace updater
 
-#endif  // CHROME_UPDATER_MAC_UPDATE_SERVICE_INTERNAL_PROXY_H_
+#endif  // CHROME_UPDATER_IPC_UPDATE_SERVICE_INTERNAL_PROXY_MAC_H_
diff --git a/chrome/updater/mac/update_service_internal_proxy.mm b/chrome/updater/ipc/update_service_internal_proxy_mac.mm
similarity index 97%
rename from chrome/updater/mac/update_service_internal_proxy.mm
rename to chrome/updater/ipc/update_service_internal_proxy_mac.mm
index 6cc3cbcd..dbc7f8e 100644
--- a/chrome/updater/mac/update_service_internal_proxy.mm
+++ b/chrome/updater/ipc/update_service_internal_proxy_mac.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/updater/mac/update_service_internal_proxy.h"
+#include "chrome/updater/ipc/update_service_internal_proxy_mac.h"
 
 #import <Foundation/Foundation.h>
 
diff --git a/chrome/updater/win/update_service_internal_proxy.cc b/chrome/updater/ipc/update_service_internal_proxy_win.cc
similarity index 97%
rename from chrome/updater/win/update_service_internal_proxy.cc
rename to chrome/updater/ipc/update_service_internal_proxy_win.cc
index 2e50b09e..2f36aaa 100644
--- a/chrome/updater/win/update_service_internal_proxy.cc
+++ b/chrome/updater/ipc/update_service_internal_proxy_win.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/updater/win/update_service_internal_proxy.h"
+#include "chrome/updater/ipc/update_service_internal_proxy_win.h"
 
 #include <windows.h>
 #include <wrl/client.h>
@@ -18,9 +18,9 @@
 #include "base/sequence_checker.h"
 #include "base/threading/platform_thread.h"
 #include "chrome/updater/app/server/win/updater_internal_idl.h"
+#include "chrome/updater/ipc/proxy_impl_base_win.h"
 #include "chrome/updater/updater_scope.h"
 #include "chrome/updater/util/util.h"
-#include "chrome/updater/win/proxy_impl_base.h"
 #include "chrome/updater/win/win_constants.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
 
diff --git a/chrome/updater/win/update_service_internal_proxy.h b/chrome/updater/ipc/update_service_internal_proxy_win.h
similarity index 81%
rename from chrome/updater/win/update_service_internal_proxy.h
rename to chrome/updater/ipc/update_service_internal_proxy_win.h
index ccbf5ca..f5741bdaa 100644
--- a/chrome/updater/win/update_service_internal_proxy.h
+++ b/chrome/updater/ipc/update_service_internal_proxy_win.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_UPDATER_WIN_UPDATE_SERVICE_INTERNAL_PROXY_H_
-#define CHROME_UPDATER_WIN_UPDATE_SERVICE_INTERNAL_PROXY_H_
+#ifndef CHROME_UPDATER_IPC_UPDATE_SERVICE_INTERNAL_PROXY_WIN_H_
+#define CHROME_UPDATER_IPC_UPDATE_SERVICE_INTERNAL_PROXY_WIN_H_
 
 #include "base/callback_forward.h"
 #include "base/memory/scoped_refptr.h"
@@ -33,4 +33,4 @@
 
 }  // namespace updater
 
-#endif  // CHROME_UPDATER_WIN_UPDATE_SERVICE_INTERNAL_PROXY_H_
+#endif  // CHROME_UPDATER_IPC_UPDATE_SERVICE_INTERNAL_PROXY_WIN_H_
diff --git a/chrome/updater/ipc/update_service_proxy_win.cc b/chrome/updater/ipc/update_service_proxy_win.cc
index 651085a..0be80636 100644
--- a/chrome/updater/ipc/update_service_proxy_win.cc
+++ b/chrome/updater/ipc/update_service_proxy_win.cc
@@ -27,10 +27,10 @@
 #include "base/version.h"
 #include "base/win/scoped_bstr.h"
 #include "chrome/updater/app/server/win/updater_idl.h"
+#include "chrome/updater/ipc/proxy_impl_base_win.h"
 #include "chrome/updater/registration_data.h"
 #include "chrome/updater/updater_scope.h"
 #include "chrome/updater/util/util.h"
-#include "chrome/updater/win/proxy_impl_base.h"
 #include "chrome/updater/win/win_constants.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
diff --git a/chrome/updater/test/integration_tests.cc b/chrome/updater/test/integration_tests.cc
index 46550ac..0edb35c6 100644
--- a/chrome/updater/test/integration_tests.cc
+++ b/chrome/updater/test/integration_tests.cc
@@ -96,6 +96,7 @@
                          true,    // enable_thread_id
                          true,    // enable_timestamp
                          false);  // enable_tickcount
+    EXPECT_TRUE(WaitForUpdaterExit());
     Clean();
     ExpectClean();
     // TODO(crbug.com/1233612) - reenable the code when system tests pass.
@@ -108,11 +109,16 @@
     if (!HasFatalFailure())
       ExpectClean();
     PrintLog();
+
     // TODO(crbug.com/1159189): Use a specific test output directory
     // because Uninstall() deletes the files under GetDataDirPath().
     CopyLog();
+
     // TODO(crbug.com/1233612) - reenable the code when system tests pass.
     // TearDownTestService();
+
+    // Updater process must not be running for `Clean()` to succeed.
+    EXPECT_TRUE(WaitForUpdaterExit());
     Clean();
   }
 
diff --git a/chrome/updater/unittest_util_unittest.cc b/chrome/updater/unittest_util_unittest.cc
index f7faa1f..7f5f98e6 100644
--- a/chrome/updater/unittest_util_unittest.cc
+++ b/chrome/updater/unittest_util_unittest.cc
@@ -80,6 +80,14 @@
   const base::FilePath path_not_found(FILE_PATH_LITERAL("path-not-found"));
   EXPECT_TRUE(DeleteFileAndEmptyParentDirectories(path_not_found));
 
+  // Create something in temp so that `DeleteFileAndEmptyParentDirectories()`
+  // does not delete the temp directory of this process because it is empty.
+  base::ScopedTempDir a_temp_dir;
+  ASSERT_TRUE(a_temp_dir.CreateUniqueTempDir());
+
+  base::FilePath temp_path;
+  ASSERT_TRUE(GetTempDir(&temp_path));
+
   // Create and delete the following path "some_dir/dir_in_dir/file_in_dir".
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
@@ -90,6 +98,7 @@
   EXPECT_TRUE(CreateTemporaryFileInDir(dir_in_dir, &file_in_dir));
   EXPECT_TRUE(DeleteFileAndEmptyParentDirectories(file_in_dir));
   EXPECT_FALSE(base::DirectoryExists(temp_dir.GetPath()));
+  EXPECT_TRUE(base::DirectoryExists(temp_path));
 }
 
 }  // namespace updater::test
diff --git a/chromecast/base/java/src/org/chromium/chromecast/base/Both.java b/chromecast/base/java/src/org/chromium/chromecast/base/Both.java
index 0d29a40..c30c0936 100644
--- a/chromecast/base/java/src/org/chromium/chromecast/base/Both.java
+++ b/chromecast/base/java/src/org/chromium/chromecast/base/Both.java
@@ -4,9 +4,8 @@
 
 package org.chromium.chromecast.base;
 
-import org.chromium.base.Function;
-
 import java.util.Objects;
+import java.util.function.Function;
 
 /**
  * Represents a structure containing an instance of both A and B.
diff --git a/chromecast/base/java/src/org/chromium/chromecast/base/Cell.java b/chromecast/base/java/src/org/chromium/chromecast/base/Cell.java
index 89417ac..c3c31ba0 100644
--- a/chromecast/base/java/src/org/chromium/chromecast/base/Cell.java
+++ b/chromecast/base/java/src/org/chromium/chromecast/base/Cell.java
@@ -4,12 +4,11 @@
 
 package org.chromium.chromecast.base;
 
-import org.chromium.base.Function;
-
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 
 /**
  * An Observable with exactly one activation at a time, which provides a way to mutate the
diff --git a/chromecast/base/java/src/org/chromium/chromecast/base/Observable.java b/chromecast/base/java/src/org/chromium/chromecast/base/Observable.java
index ef8b8f8..afc5b1c0b 100644
--- a/chromecast/base/java/src/org/chromium/chromecast/base/Observable.java
+++ b/chromecast/base/java/src/org/chromium/chromecast/base/Observable.java
@@ -4,7 +4,7 @@
 
 package org.chromium.chromecast.base;
 
-import org.chromium.base.Function;
+import java.util.function.Function;
 
 /**
  * Interface for Observable state.
diff --git a/chromecast/base/java/test/org/chromium/chromecast/base/BothTest.java b/chromecast/base/java/test/org/chromium/chromecast/base/BothTest.java
index f2b0b53..1756a67 100644
--- a/chromecast/base/java/test/org/chromium/chromecast/base/BothTest.java
+++ b/chromecast/base/java/test/org/chromium/chromecast/base/BothTest.java
@@ -14,12 +14,12 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.BlockJUnit4ClassRunner;
 
-import org.chromium.base.Function;
 import org.chromium.chromecast.base.Inheritance.Base;
 import org.chromium.chromecast.base.Inheritance.Derived;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.Function;
 
 /**
  * Tests for Both.
diff --git a/chromecast/base/java/test/org/chromium/chromecast/base/ObservableMapTest.java b/chromecast/base/java/test/org/chromium/chromecast/base/ObservableMapTest.java
index e3eb3c6..3a593d9 100644
--- a/chromecast/base/java/test/org/chromium/chromecast/base/ObservableMapTest.java
+++ b/chromecast/base/java/test/org/chromium/chromecast/base/ObservableMapTest.java
@@ -8,10 +8,11 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.BlockJUnit4ClassRunner;
 
-import org.chromium.base.Function;
 import org.chromium.chromecast.base.Inheritance.Base;
 import org.chromium.chromecast.base.Inheritance.Derived;
 
+import java.util.function.Function;
+
 /**
  * Tests for Observable#map().
  */
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsService.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsService.java
index 742dcd3..b23a69e 100644
--- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsService.java
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsService.java
@@ -16,7 +16,6 @@
 
 import androidx.core.app.NotificationCompat;
 
-import org.chromium.base.Function;
 import org.chromium.base.Log;
 import org.chromium.chromecast.base.Controller;
 import org.chromium.chromecast.base.Observable;
@@ -24,6 +23,8 @@
 import org.chromium.content.browser.MediaSessionImpl;
 import org.chromium.content_public.browser.WebContents;
 
+import java.util.function.Function;
+
 /**
  * Service for "displaying" a WebContents in CastShell.
  * <p>
diff --git a/chromecast/renderer/BUILD.gn b/chromecast/renderer/BUILD.gn
index 655edf8f..0561289 100644
--- a/chromecast/renderer/BUILD.gn
+++ b/chromecast/renderer/BUILD.gn
@@ -36,14 +36,13 @@
     "queryable_data_store.h",
     "settings_ui_bindings.cc",
     "settings_ui_bindings.h",
-    "url_rewrite_rules_provider.cc",
-    "url_rewrite_rules_provider.h",
   ]
 
   public_deps = [
     "//chromecast:chromecast_buildflags",
     "//chromecast/browser/mojom",
     "//chromecast/common/mojom",
+    "//components/cast_receiver/renderer",
     "//components/url_rewrite/common",
     "//content/public/renderer",
     "//media",
diff --git a/chromecast/renderer/DEPS b/chromecast/renderer/DEPS
index f818f5c..1c707f5 100644
--- a/chromecast/renderer/DEPS
+++ b/chromecast/renderer/DEPS
@@ -3,6 +3,7 @@
   "+chromecast/common",
   "+chromecast/crash",
   "+chromecast/media",
+  "+components/cast_receiver/renderer",
   "+components/cdm/renderer",
   "+components/guest_view/renderer",
   "+components/media_control/renderer",
diff --git a/chromecast/renderer/cast_content_renderer_client.cc b/chromecast/renderer/cast_content_renderer_client.cc
index dc9d6688..c9005c8 100644
--- a/chromecast/renderer/cast_content_renderer_client.cc
+++ b/chromecast/renderer/cast_content_renderer_client.cc
@@ -22,7 +22,7 @@
 #include "chromecast/renderer/cast_websocket_handshake_throttle_provider.h"
 #include "chromecast/renderer/media/key_systems_cast.h"
 #include "chromecast/renderer/media/media_caps_observer_impl.h"
-#include "chromecast/renderer/url_rewrite_rules_provider.h"
+#include "components/cast_receiver/renderer/public/url_rewrite_rules_provider.h"
 #include "components/media_control/renderer/media_playback_options.h"
 #include "components/network_hints/renderer/web_prescient_networking_impl.h"
 #include "components/on_load_script_injector/renderer/on_load_script_injector.h"
@@ -166,7 +166,7 @@
   // CastContentRendererClient should be alive.
   url_rewrite_rules_providers_.emplace(
       render_frame->GetRoutingID(),
-      std::make_unique<UrlRewriteRulesProvider>(
+      std::make_unique<cast_receiver::UrlRewriteRulesProvider>(
           render_frame,
           base::BindOnce(&CastContentRendererClient::OnRenderFrameRemoved,
                          base::Unretained(this))));
diff --git a/chromecast/renderer/cast_content_renderer_client.h b/chromecast/renderer/cast_content_renderer_client.h
index 014aae33c..45a143c 100644
--- a/chromecast/renderer/cast_content_renderer_client.h
+++ b/chromecast/renderer/cast_content_renderer_client.h
@@ -20,9 +20,12 @@
 #include "media/base/audio_parameters.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 
+namespace cast_receiver {
+class UrlRewriteRulesProvider;
+}  // namespace cast_receiver
+
 namespace chromecast {
 class MemoryPressureObserverImpl;
-class UrlRewriteRulesProvider;
 namespace media {
 class MediaCapsObserverImpl;
 class SupportedCodecProfileLevelsMemo;
@@ -124,8 +127,10 @@
 
   BitstreamAudioCodecsInfo supported_bitstream_audio_codecs_info_;
 
+  // TODO(crbug.com/1382903): Clean this up by moving RenderFrame details
+  // into cast_receiver.
   base::flat_map<int /* render_frame_id */,
-                 std::unique_ptr<UrlRewriteRulesProvider>>
+                 std::unique_ptr<cast_receiver::UrlRewriteRulesProvider>>
       url_rewrite_rules_providers_;
   std::unique_ptr<CastActivityUrlFilterManager> activity_url_filter_manager_;
 };
diff --git a/chromeos/ash/services/ime/public/mojom/japanese_settings.mojom b/chromeos/ash/services/ime/public/mojom/japanese_settings.mojom
index bfba250b..6ea7ac0 100644
--- a/chromeos/ash/services/ime/public/mojom/japanese_settings.mojom
+++ b/chromeos/ash/services/ime/public/mojom/japanese_settings.mojom
@@ -17,55 +17,55 @@
 
 [Stable, Extensible]
 enum InputMode {
-    [Default] ROMAJI = 0,
-    KANA = 1
+    [Default] kRomaji = 0,
+    kKana = 1
 };
 
 [Stable, Extensible]
 enum PunctuationStyle {
-    [Default] KUTEN_TOUTEN = 0,
-    COMMA_PERIOD = 1,
-    KUTEN_PERIOD = 2,
-    COMMA_TOUTEN = 3
+    [Default] kKutenTouten = 0,
+    kCommaPeriod = 1,
+    kKutenPeriod = 2,
+    kCommaTouten = 3
 };
 
 [Stable, Extensible]
 enum SymbolStyle {
-    [Default] CORNER_BRACKET_MIDDLE_DOT = 0,
-    SQUARE_BRACKET_SLASH = 1,
-    CORNER_BRACKET_SLASH = 2,
-    SQUARE_BRACKET_MIDDLE_DOT = 3
+    [Default] kCornerBracketMiddleDot = 0,
+    kSquareBracketSlash = 1,
+    kCornerBracketSlash = 2,
+    kSquareBracketMiddleDot = 3
 };
 
 [Stable, Extensible]
 enum SpaceInputStyle {
-    [Default] INPUT_MODE = 0,
-    FULLWIDTH = 1,
-    HALFWIDTH = 2
+    [Default] kInputMode = 0,
+    kFullwidth = 1,
+    kHalfwidth = 2
 };
 
 [Stable, Extensible]
 enum SelectionShortcut {
-    NO_SHORTCUT = 0,
-    [Default] DIGITS_123456789 = 1,
-    ASDFGHJKL = 2
+    kNoShortcut = 0,
+    [Default] kDigits123456789 = 1,
+    kAsdfghjkl = 2
 };
 
 [Stable, Extensible]
 enum KeymapStyle {
-    [Default] CUSTOM = 0,
-    ATOK = 1,
-    MS_IME = 2,
-    KOTOERI = 3,
-    MOBILE = 4,
-    CHROME_OS = 5
+    [Default] kCustom = 0,
+    kAtok = 1,
+    kMsIme = 2,
+    kKotoeri = 3,
+    kMobile = 4,
+    kChromeOs = 5
 };
 
 [Stable, Extensible]
 enum ShiftKeyModeSwitch {
-    OFF = 0,
-    [Default] ALPHANUMERIC = 1,
-    KATAKANA = 2,
+    kOff = 0,
+    [Default] kAlphanumeric = 1,
+    kKatakana = 2,
 };
 
 [Stable]
diff --git a/chromeos/crosapi/mojom/BUILD.gn b/chromeos/crosapi/mojom/BUILD.gn
index 284216a..c361401 100644
--- a/chromeos/crosapi/mojom/BUILD.gn
+++ b/chromeos/crosapi/mojom/BUILD.gn
@@ -111,6 +111,7 @@
     "//components/digital_goods/mojom:mojom",
     "//components/metrics/structured/mojom",
     "//components/services/app_service/public/mojom:mojom",
+    "//components/tab_groups/public/mojom:mojo_bindings",
     "//media/capture/mojom:image_capture",
     "//media/capture/mojom:video_capture_types",
     "//media/mojo/mojom:speech_recognition",
diff --git a/chromeos/crosapi/mojom/desk_template.mojom b/chromeos/crosapi/mojom/desk_template.mojom
index 0483344e..e9dbdcc 100644
--- a/chromeos/crosapi/mojom/desk_template.mojom
+++ b/chromeos/crosapi/mojom/desk_template.mojom
@@ -4,11 +4,38 @@
 
 module crosapi.mojom;
 
+import "components/tab_groups/public/mojom/tab_group_types.mojom";
 import "ui/base/mojom/ui_base_types.mojom";
 import "ui/gfx/geometry/mojom/geometry.mojom";
 import "url/mojom/url.mojom";
 import "ui/gfx/image/mojom/image.mojom";
 
+// Structure representing the state of a tab group in a browser instance.
+[Stable]
+struct TabGroup {
+  // The title of the tab group
+  string title;
+
+  // The background color of the tab group.
+  tab_groups.mojom.Color color;
+
+  // Whether the group is collapsed.
+  bool is_collapsed;
+
+  // The index of the first tab in this group.  This index cannot overlap with
+  // the indexes of other tab groups associated with the window this group
+  // belongs with.  The start index also cannot be less than the value
+  // associated with the `first_non_pinned_tab_index`.
+  uint32 start_index;
+
+  // Number of tabs in this group.  The sum of this and the start index cannot
+  // result in an index that is greater than the total number of tabs associated
+  // with the owning window.  The sum of this and the start index also cannot
+  // result in an index that overlaps with another tab group.
+  uint32 tab_count;
+};
+
+
 // Additional state of the browser in the single Lacros window for saving in the
 // desk template.
 [Stable]
@@ -22,6 +49,14 @@
   [MinVersion=2] string? browser_app_name@2;
 
   [MinVersion=3] int64 restore_window_id@3;
+
+  // Index of the first non-pinned tab. 0 if no tabs are pinned. This index
+  // cannot be contained within the range of any tab groups and tab group
+  // indexes cannot overlap with any index less than this value.
+  [MinVersion=4] uint32 first_non_pinned_index@4;
+
+  // List of tab groups associated with this browser.
+  [MinVersion=4] array<TabGroup>? groups@5;
 };
 
 // Interface for desk template clients.  Implemented by lacros-chrome.
diff --git a/chromeos/services/tts/COMMON_METADATA b/chromeos/services/tts/COMMON_METADATA
new file mode 100644
index 0000000..47d13708
--- /dev/null
+++ b/chromeos/services/tts/COMMON_METADATA
@@ -0,0 +1,10 @@
+monorail: {
+    component: "Internals>SpeechSynthesis"
+}
+team_email: "chromium-accessibility@chromium.org"
+buganizer {
+  component_id: 1279168
+}
+buganizer_public {
+  component_id: 1279189
+}
diff --git a/chromeos/services/tts/DIR_METADATA b/chromeos/services/tts/DIR_METADATA
index e9c88d5..e77aa423 100644
--- a/chromeos/services/tts/DIR_METADATA
+++ b/chromeos/services/tts/DIR_METADATA
@@ -1,4 +1 @@
-monorail {
-  component: "Internals>SpeechSynthesis"
-}
-team_email: "chromium-accessibility@chromium.org"
+mixins: "//chromeos/services/tts/COMMON_METADATA"
diff --git a/components/attribution_reporting/BUILD.gn b/components/attribution_reporting/BUILD.gn
index a6523b0..594b1f4 100644
--- a/components/attribution_reporting/BUILD.gn
+++ b/components/attribution_reporting/BUILD.gn
@@ -61,6 +61,7 @@
     "aggregatable_values_unittest.cc",
     "aggregation_keys_unittest.cc",
     "bounded_list_unittest.cc",
+    "event_trigger_data_unittest.cc",
     "filters_unittest.cc",
     "os_registration_unittest.cc",
     "parsing_utils_unittest.cc",
diff --git a/components/attribution_reporting/event_trigger_data.cc b/components/attribution_reporting/event_trigger_data.cc
index cc6881f..53d39ad 100644
--- a/components/attribution_reporting/event_trigger_data.cc
+++ b/components/attribution_reporting/event_trigger_data.cc
@@ -4,10 +4,51 @@
 
 #include "components/attribution_reporting/event_trigger_data.h"
 
+#include <stdint.h>
+
 #include <utility>
 
+#include "base/types/expected.h"
+#include "base/values.h"
+#include "components/attribution_reporting/filters.h"
+#include "components/attribution_reporting/parsing_utils.h"
+#include "components/attribution_reporting/trigger_registration_error.mojom.h"
+
 namespace attribution_reporting {
 
+namespace {
+
+using ::attribution_reporting::mojom::TriggerRegistrationError;
+
+}  // namespace
+
+// static
+base::expected<EventTriggerData, TriggerRegistrationError>
+EventTriggerData::FromJSON(base::Value& value) {
+  base::Value::Dict* dict = value.GetIfDict();
+  if (!dict) {
+    return base::unexpected(
+        TriggerRegistrationError::kEventTriggerDataWrongType);
+  }
+
+  auto filters = Filters::FromJSON(dict->Find("filters"));
+  if (!filters.has_value())
+    return base::unexpected(filters.error());
+
+  auto not_filters = Filters::FromJSON(dict->Find("not_filters"));
+  if (!not_filters.has_value())
+    return base::unexpected(not_filters.error());
+
+  uint64_t data = ParseUint64(*dict, "trigger_data").value_or(0);
+  int64_t priority = ParsePriority(*dict);
+  absl::optional<uint64_t> dedup_key = ParseUint64(*dict, "deduplication_key");
+
+  return EventTriggerData(data, priority, dedup_key, std::move(*filters),
+                          std::move(*not_filters));
+}
+
+EventTriggerData::EventTriggerData() = default;
+
 EventTriggerData::EventTriggerData(uint64_t data,
                                    int64_t priority,
                                    absl::optional<uint64_t> dedup_key,
diff --git a/components/attribution_reporting/event_trigger_data.h b/components/attribution_reporting/event_trigger_data.h
index 8cbfd439f..e7479960 100644
--- a/components/attribution_reporting/event_trigger_data.h
+++ b/components/attribution_reporting/event_trigger_data.h
@@ -8,23 +8,32 @@
 #include <stdint.h>
 
 #include "base/component_export.h"
+#include "base/types/expected.h"
 #include "components/attribution_reporting/bounded_list.h"
 #include "components/attribution_reporting/constants.h"
 #include "components/attribution_reporting/filters.h"
+#include "components/attribution_reporting/trigger_registration_error.mojom-forward.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
+namespace base {
+class Value;
+}  // namespace  base
+
 namespace attribution_reporting {
 
 struct COMPONENT_EXPORT(ATTRIBUTION_REPORTING) EventTriggerData {
+  static base::expected<EventTriggerData, mojom::TriggerRegistrationError>
+  FromJSON(base::Value& value);
+
   // Data associated with trigger.
   // Will be sanitized to a lower entropy by the `AttributionStorageDelegate`
   // before storage.
-  uint64_t data;
+  uint64_t data = 0;
 
   // Priority specified in conversion redirect. Used to prioritize which
   // reports to send among multiple different reports for the same attribution
   // source. Defaults to 0 if not provided.
-  int64_t priority;
+  int64_t priority = 0;
 
   // Key specified in conversion redirect for deduplication against existing
   // conversions with the same source. If absent, no deduplication is
@@ -39,6 +48,8 @@
   // fields are used.
   Filters not_filters;
 
+  EventTriggerData();
+
   EventTriggerData(uint64_t data,
                    int64_t priority,
                    absl::optional<uint64_t> dedup_key,
diff --git a/components/attribution_reporting/event_trigger_data_unittest.cc b/components/attribution_reporting/event_trigger_data_unittest.cc
new file mode 100644
index 0000000..5661f0b
--- /dev/null
+++ b/components/attribution_reporting/event_trigger_data_unittest.cc
@@ -0,0 +1,120 @@
+// 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 "components/attribution_reporting/event_trigger_data.h"
+
+#include <utility>
+
+#include "base/functional/invoke.h"
+#include "base/test/values_test_util.h"
+#include "base/types/expected.h"
+#include "base/values.h"
+#include "components/attribution_reporting/filters.h"
+#include "components/attribution_reporting/test_utils.h"
+#include "components/attribution_reporting/trigger_registration_error.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace attribution_reporting {
+namespace {
+
+using ::attribution_reporting::mojom::TriggerRegistrationError;
+
+template <typename F>
+EventTriggerData EventTriggerDataWith(F&& f) {
+  EventTriggerData data;
+  base::invoke<F, EventTriggerData&>(std::move(f), data);
+  return data;
+}
+
+TEST(EventTriggerDataTest, FromJSON) {
+  const struct {
+    const char* description;
+    const char* json;
+    base::expected<EventTriggerData, TriggerRegistrationError> expected;
+  } kTestCases[] = {
+      {
+          "empty",
+          R"json({})json",
+          EventTriggerData(),
+      },
+      {
+          "trigger_data_valid",
+          R"json({"trigger_data":"123"})json",
+          EventTriggerDataWith([](auto& data) { data.data = 123; }),
+      },
+      {
+          "trigger_data_wrong_type",
+          R"json({"trigger_data":123})json",
+          EventTriggerData(),
+      },
+      {
+          "trigger_data_invalid",
+          R"json({"trigger_data":"-5"})json",
+          EventTriggerData(),
+      },
+      {
+          "priority_valid",
+          R"json({"priority":"-5"})json",
+          EventTriggerDataWith([](auto& data) { data.priority = -5; }),
+      },
+      {
+          "priority_wrong_type",
+          R"json({"priority":123})json",
+          EventTriggerData(),
+      },
+      {
+          "priority_invalid",
+          R"json({"priority":"abc"})json",
+          EventTriggerData(),
+      },
+      {
+          "dedup_key_valid",
+          R"json({"deduplication_key":"3"})json",
+          EventTriggerDataWith([](auto& data) { data.dedup_key = 3; }),
+      },
+      {
+          "dedup_key_wrong_type",
+          R"json({"deduplication_key":123})json",
+          EventTriggerData(),
+      },
+      {
+          "dedup_key_invalid",
+          R"json({"deduplication_key":"abc"})json",
+          EventTriggerData(),
+      },
+      {
+          "filters_valid",
+          R"json({"filters":{"a":["b"]}})json",
+          EventTriggerDataWith([](auto& data) {
+            data.filters = *Filters::Create({{"a", {"b"}}});
+          }),
+      },
+      {
+          "filters_wrong_type",
+          R"json({"filters":123})json",
+          base::unexpected(TriggerRegistrationError::kFiltersWrongType),
+      },
+      {
+          "not_filters_valid",
+          R"json({"not_filters":{"a":["b"]}})json",
+          EventTriggerDataWith([](auto& data) {
+            data.not_filters = *Filters::Create({{"a", {"b"}}});
+          }),
+      },
+      {
+          "not_filters_wrong_type",
+          R"json({"not_filters":123})json",
+          base::unexpected(TriggerRegistrationError::kFiltersWrongType),
+      },
+  };
+
+  for (const auto& test_case : kTestCases) {
+    base::Value value = base::test::ParseJson(test_case.json);
+    EXPECT_EQ(EventTriggerData::FromJSON(value), test_case.expected)
+        << test_case.description;
+  }
+}
+
+}  // namespace
+}  // namespace attribution_reporting
diff --git a/components/attribution_reporting/parsing_utils.cc b/components/attribution_reporting/parsing_utils.cc
index 929b5a2..cad6a75 100644
--- a/components/attribution_reporting/parsing_utils.cc
+++ b/components/attribution_reporting/parsing_utils.cc
@@ -4,8 +4,15 @@
 
 #include "components/attribution_reporting/parsing_utils.h"
 
+#include <stdint.h>
+
+#include <string>
+
 #include "base/strings/abseil_string_number_conversions.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
+#include "base/values.h"
 #include "components/attribution_reporting/constants.h"
 #include "third_party/abseil-cpp/absl/numeric/int128.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -28,4 +35,30 @@
   return key.size() <= kMaxBytesPerAggregationKeyId;
 }
 
+absl::optional<uint64_t> ParseUint64(const base::Value::Dict& dict,
+                                     base::StringPiece key) {
+  const std::string* s = dict.FindString(key);
+  if (!s)
+    return absl::nullopt;
+
+  uint64_t value;
+  return base::StringToUint64(*s, &value) ? absl::make_optional(value)
+                                          : absl::nullopt;
+}
+
+absl::optional<int64_t> ParseInt64(const base::Value::Dict& dict,
+                                   base::StringPiece key) {
+  const std::string* s = dict.FindString(key);
+  if (!s)
+    return absl::nullopt;
+
+  int64_t value;
+  return base::StringToInt64(*s, &value) ? absl::make_optional(value)
+                                         : absl::nullopt;
+}
+
+int64_t ParsePriority(const base::Value::Dict& dict) {
+  return ParseInt64(dict, "priority").value_or(0);
+}
+
 }  // namespace attribution_reporting
diff --git a/components/attribution_reporting/parsing_utils.h b/components/attribution_reporting/parsing_utils.h
index fe375ff..8de7848 100644
--- a/components/attribution_reporting/parsing_utils.h
+++ b/components/attribution_reporting/parsing_utils.h
@@ -5,9 +5,13 @@
 #ifndef COMPONENTS_ATTRIBUTION_REPORTING_PARSING_UTILS_H_
 #define COMPONENTS_ATTRIBUTION_REPORTING_PARSING_UTILS_H_
 
+#include <stdint.h>
+
 #include <string>
 
 #include "base/component_export.h"
+#include "base/strings/string_piece_forward.h"
+#include "base/values.h"
 #include "third_party/abseil-cpp/absl/numeric/int128.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -19,6 +23,16 @@
 COMPONENT_EXPORT(ATTRIBUTION_REPORTING)
 bool AggregationKeyIdHasValidLength(const std::string& key);
 
+COMPONENT_EXPORT(ATTRIBUTION_REPORTING)
+absl::optional<uint64_t> ParseUint64(const base::Value::Dict& dict,
+                                     base::StringPiece key);
+
+COMPONENT_EXPORT(ATTRIBUTION_REPORTING)
+absl::optional<int64_t> ParseInt64(const base::Value::Dict& dict,
+                                   base::StringPiece key);
+
+int64_t ParsePriority(const base::Value::Dict& dict);
+
 }  // namespace attribution_reporting
 
 #endif  // COMPONENTS_ATTRIBUTION_REPORTING_PARSING_UTILS_H_
diff --git a/components/attribution_reporting/parsing_utils_unittest.cc b/components/attribution_reporting/parsing_utils_unittest.cc
index fd563048..cc91eae 100644
--- a/components/attribution_reporting/parsing_utils_unittest.cc
+++ b/components/attribution_reporting/parsing_utils_unittest.cc
@@ -4,8 +4,13 @@
 
 #include "components/attribution_reporting/parsing_utils.h"
 
+#include <stdint.h>
+
+#include <limits>
 #include <string>
 
+#include "base/test/values_test_util.h"
+#include "base/values.h"
 #include "components/attribution_reporting/constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/numeric/int128.h"
@@ -14,7 +19,7 @@
 namespace attribution_reporting {
 namespace {
 
-TEST(AggregationKeyUtilsTest, StringToAggregationKeyPiece) {
+TEST(AttributionReportingParsingUtilsTest, StringToAggregationKeyPiece) {
   const struct {
     const char* string;
     absl::optional<absl::uint128> expected;
@@ -31,12 +36,102 @@
   }
 }
 
-TEST(AggregationKeyUtilsTest, AggregationKeyIdHasValidLength) {
+TEST(AttributionReportingParsingUtilsTest, AggregationKeyIdHasValidLength) {
   EXPECT_TRUE(AggregationKeyIdHasValidLength(
       std::string(kMaxBytesPerAggregationKeyId, 'a')));
   EXPECT_FALSE(AggregationKeyIdHasValidLength(
       std::string(kMaxBytesPerAggregationKeyId + 1, 'a')));
 }
 
+TEST(AttributionReportingParsingUtilsTest, ParseUint64) {
+  const struct {
+    const char* description;
+    const char* json;
+    absl::optional<uint64_t> expected;
+  } kTestCases[] = {
+      {
+          "missing_key",
+          R"json({})json",
+          absl::nullopt,
+      },
+      {
+          "not_string",
+          R"json({"key":123})json",
+          absl::nullopt,
+      },
+      {
+          "negative",
+          R"json({"key":"-1"})json",
+          absl::nullopt,
+      },
+      {
+          "zero",
+          R"json({"key":"0"})json",
+          0,
+      },
+      {
+          "max",
+          R"json({"key":"18446744073709551615"})json",
+          std::numeric_limits<uint64_t>::max(),
+      },
+      {
+          "out_of_range",
+          R"json({"key":"18446744073709551616"})json",
+          absl::nullopt,
+      },
+  };
+
+  for (const auto& test_case : kTestCases) {
+    base::Value value = base::test::ParseJson(test_case.json);
+    EXPECT_EQ(ParseUint64(value.GetDict(), "key"), test_case.expected)
+        << test_case.description;
+  }
+}
+
+TEST(AttributionReportingParsingUtilsTest, ParseInt64) {
+  const struct {
+    const char* description;
+    const char* json;
+    absl::optional<int64_t> expected;
+  } kTestCases[] = {
+      {
+          "missing_key",
+          R"json({})json",
+          absl::nullopt,
+      },
+      {
+          "not_string",
+          R"json({"key":123})json",
+          absl::nullopt,
+      },
+      {
+          "zero",
+          R"json({"key":"0"})json",
+          0,
+      },
+      {
+          "min",
+          R"json({"key":"-9223372036854775808"})json",
+          std::numeric_limits<int64_t>::min(),
+      },
+      {
+          "max",
+          R"json({"key":"9223372036854775807"})json",
+          std::numeric_limits<int64_t>::max(),
+      },
+      {
+          "out_of_range",
+          R"json({"key":"9223372036854775808"})json",
+          absl::nullopt,
+      },
+  };
+
+  for (const auto& test_case : kTestCases) {
+    base::Value value = base::test::ParseJson(test_case.json);
+    EXPECT_EQ(ParseInt64(value.GetDict(), "key"), test_case.expected)
+        << test_case.description;
+  }
+}
+
 }  // namespace
 }  // namespace attribution_reporting
diff --git a/components/attribution_reporting/source_registration.cc b/components/attribution_reporting/source_registration.cc
index 0a0e8bf..86cd048 100644
--- a/components/attribution_reporting/source_registration.cc
+++ b/components/attribution_reporting/source_registration.cc
@@ -16,6 +16,7 @@
 #include "base/values.h"
 #include "components/attribution_reporting/aggregation_keys.h"
 #include "components/attribution_reporting/filters.h"
+#include "components/attribution_reporting/parsing_utils.h"
 #include "components/attribution_reporting/source_registration_error.mojom.h"
 #include "components/attribution_reporting/suitable_origin.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -26,28 +27,6 @@
 
 using ::attribution_reporting::mojom::SourceRegistrationError;
 
-absl::optional<uint64_t> ParseUint64(const base::Value::Dict& dict,
-                                     base::StringPiece key) {
-  const std::string* s = dict.FindString(key);
-  if (!s)
-    return absl::nullopt;
-
-  uint64_t value;
-  return base::StringToUint64(*s, &value) ? absl::make_optional(value)
-                                          : absl::nullopt;
-}
-
-absl::optional<int64_t> ParseInt64(const base::Value::Dict& dict,
-                                   base::StringPiece key) {
-  const std::string* s = dict.FindString(key);
-  if (!s)
-    return absl::nullopt;
-
-  int64_t value;
-  return base::StringToInt64(*s, &value) ? absl::make_optional(value)
-                                         : absl::nullopt;
-}
-
 absl::optional<base::TimeDelta> ParseTimeDeltaInSeconds(
     const base::Value::Dict& registration,
     base::StringPiece key) {
@@ -106,7 +85,7 @@
   result.source_event_id =
       ParseUint64(registration, "source_event_id").value_or(0);
 
-  result.priority = ParseInt64(registration, "priority").value_or(0);
+  result.priority = ParsePriority(registration);
 
   result.expiry = ParseTimeDeltaInSeconds(registration, "expiry");
 
diff --git a/components/attribution_reporting/trigger_registration_error.mojom b/components/attribution_reporting/trigger_registration_error.mojom
index d7e167d..260d49c6 100644
--- a/components/attribution_reporting/trigger_registration_error.mojom
+++ b/components/attribution_reporting/trigger_registration_error.mojom
@@ -28,4 +28,6 @@
   kAggregatableTriggerDataSourceKeysTooManyKeys,
   kAggregatableTriggerDataSourceKeysKeyWrongType,
   kAggregatableTriggerDataSourceKeysKeyTooLong,
+
+  kEventTriggerDataWrongType,
 };
diff --git a/components/autofill/core/browser/payments/payments_client_unittest.cc b/components/autofill/core/browser/payments/payments_client_unittest.cc
index 6d34111..2b85cf8b 100644
--- a/components/autofill/core/browser/payments/payments_client_unittest.cc
+++ b/components/autofill/core/browser/payments/payments_client_unittest.cc
@@ -942,10 +942,6 @@
 }
 
 TEST_F(PaymentsClientTest, UnmaskIncludesLegacyAndNonLegacyId) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(
-      features::kAutofillEnableUnmaskCardRequestSetInstrumentId);
-
   StartUnmasking(CardUnmaskOptions());
   IssueOAuthToken();
   ReturnResponse(net::HTTP_OK, "{}");
@@ -958,10 +954,6 @@
 }
 
 TEST_F(PaymentsClientTest, UnmaskIncludesOnlyLegacyId) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(
-      features::kAutofillEnableUnmaskCardRequestSetInstrumentId);
-
   StartUnmasking(CardUnmaskOptions().with_only_legacy_id());
   IssueOAuthToken();
   ReturnResponse(net::HTTP_OK, "{}");
@@ -973,10 +965,6 @@
 }
 
 TEST_F(PaymentsClientTest, UnmaskIncludesOnlyNonLegacyId) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(
-      features::kAutofillEnableUnmaskCardRequestSetInstrumentId);
-
   StartUnmasking(CardUnmaskOptions().with_only_non_legacy_id());
   IssueOAuthToken();
   ReturnResponse(net::HTTP_OK, "{}");
@@ -987,21 +975,6 @@
   EXPECT_TRUE(GetUploadData().find("credit_card_id") == std::string::npos);
 }
 
-TEST_F(PaymentsClientTest, UnmaskDoesNotIncludeInstrumentIdIfFlagDisabled) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndDisableFeature(
-      features::kAutofillEnableUnmaskCardRequestSetInstrumentId);
-
-  StartUnmasking(CardUnmaskOptions());
-  IssueOAuthToken();
-  ReturnResponse(net::HTTP_OK, "{}");
-
-  // Instrument id is not set if flag is disabled.
-  EXPECT_TRUE(GetUploadData().find("instrument_id") == std::string::npos);
-  EXPECT_TRUE(GetUploadData().find("%22credit_card_id%22:%22a123%22") !=
-              std::string::npos);
-}
-
 TEST_F(PaymentsClientTest,
        UnmaskIncludesChromeUserContextIfWalletStorageFlagEnabled) {
   base::test::ScopedFeatureList feature_list;
diff --git a/components/autofill/core/browser/payments/payments_requests/unmask_card_request.cc b/components/autofill/core/browser/payments/payments_requests/unmask_card_request.cc
index 3f68e572..7fc41620 100644
--- a/components/autofill/core/browser/payments/payments_requests/unmask_card_request.cc
+++ b/components/autofill/core/browser/payments/payments_requests/unmask_card_request.cc
@@ -183,9 +183,7 @@
   if (!request_details_.card.server_id().empty()) {
     request_dict.Set("credit_card_id", request_details_.card.server_id());
   }
-  if (base::FeatureList::IsEnabled(
-          features::kAutofillEnableUnmaskCardRequestSetInstrumentId) &&
-      request_details_.card.instrument_id() != 0) {
+  if (request_details_.card.instrument_id() != 0) {
     request_dict.Set(
         "instrument_id",
         base::NumberToString(request_details_.card.instrument_id()));
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc
index 7eeb7cc..036888a 100644
--- a/components/autofill/core/common/autofill_payments_features.cc
+++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -118,12 +118,6 @@
              "AutofillEnableStickyManualFallbackForCards",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-// When enabled, UnmaskCardRequest will set instrument id, which is Chrome-side
-// field for non-legacy ID.
-BASE_FEATURE(kAutofillEnableUnmaskCardRequestSetInstrumentId,
-             "AutofillEnableUnmaskCardRequestSetInstrumentId",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 // When enabled, the user will have the ability to update the virtual card
 // enrollment of a credit card through their chrome browser after certain
 // autofill flows (for example, downstream and upstream), and from the settings
diff --git a/components/autofill/core/common/autofill_payments_features.h b/components/autofill/core/common/autofill_payments_features.h
index 00ed44f..aa5f05f 100644
--- a/components/autofill/core/common/autofill_payments_features.h
+++ b/components/autofill/core/common/autofill_payments_features.h
@@ -28,7 +28,6 @@
 BASE_DECLARE_FEATURE(kAutofillEnableOffersInClankKeyboardAccessory);
 BASE_DECLARE_FEATURE(kAutofillEnableRemadeDownstreamMetrics);
 BASE_DECLARE_FEATURE(kAutofillEnableStickyManualFallbackForCards);
-BASE_DECLARE_FEATURE(kAutofillEnableUnmaskCardRequestSetInstrumentId);
 BASE_DECLARE_FEATURE(kAutofillEnableUpdateVirtualCardEnrollment);
 BASE_DECLARE_FEATURE(kAutofillEnableVirtualCard);
 BASE_DECLARE_FEATURE(kAutofillEnableVirtualCardFidoEnrollment);
diff --git a/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AssistantIsGsaFunction.java b/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AssistantIsGsaFunction.java
index 6a4e739..5371c40 100644
--- a/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AssistantIsGsaFunction.java
+++ b/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AssistantIsGsaFunction.java
@@ -6,7 +6,7 @@
 
 import android.app.Activity;
 
-import org.chromium.base.Function;
+import java.util.function.Function;
 
 /**
  * Determines whether the activity was launched by GSA.
diff --git a/components/cast_receiver/renderer/BUILD.gn b/components/cast_receiver/renderer/BUILD.gn
index 721dbe5..f083f12 100644
--- a/components/cast_receiver/renderer/BUILD.gn
+++ b/components/cast_receiver/renderer/BUILD.gn
@@ -2,14 +2,26 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+# TODO(crbug.com/1385152): Remove this condition once Windows builds are fixed.
 if (!is_win) {
   source_set("renderer") {
+    public = [
+      "public/content_renderer_client_mixins.h",
+      "public/url_rewrite_rules_provider.h",
+    ]
+    sources = [
+      "content_renderer_client_mixins.cc",
+      "url_rewrite_rules_provider.cc",
+    ]
+    public_deps = [
+      "//components/url_rewrite/renderer",
+      "//content/public/renderer",
+    ]
     deps = [
       "//components/media_control/renderer",
       "//components/on_load_script_injector/renderer",
+      "//third_party/blink/public:blink",
     ]
-    public = [ "public/content_renderer_client_mixins.h" ]
-    sources = [ "content_renderer_client_mixins.cc" ]
   }
 }
 
diff --git a/components/cast_receiver/renderer/DEPS b/components/cast_receiver/renderer/DEPS
index 1388d12..1cab500 100644
--- a/components/cast_receiver/renderer/DEPS
+++ b/components/cast_receiver/renderer/DEPS
@@ -1,4 +1,7 @@
 include_rules = [
   "+components/media_control/renderer",
   "+components/on_load_script_injector/renderer",
+  "+components/url_rewrite/renderer",
+  "+content/public/renderer",
+  "+third_party/blink/public/common",
 ]
diff --git a/chromecast/renderer/url_rewrite_rules_provider.h b/components/cast_receiver/renderer/public/url_rewrite_rules_provider.h
similarity index 83%
rename from chromecast/renderer/url_rewrite_rules_provider.h
rename to components/cast_receiver/renderer/public/url_rewrite_rules_provider.h
index 2be84d6..18a9496 100644
--- a/chromecast/renderer/url_rewrite_rules_provider.h
+++ b/components/cast_receiver/renderer/public/url_rewrite_rules_provider.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMECAST_RENDERER_URL_REWRITE_RULES_PROVIDER_H_
-#define CHROMECAST_RENDERER_URL_REWRITE_RULES_PROVIDER_H_
+#ifndef COMPONENTS_CAST_RECEIVER_RENDERER_PUBLIC_URL_REWRITE_RULES_PROVIDER_H_
+#define COMPONENTS_CAST_RECEIVER_RENDERER_PUBLIC_URL_REWRITE_RULES_PROVIDER_H_
 
 #include "base/callback.h"
 #include "components/url_rewrite/renderer/url_request_rules_receiver.h"
@@ -13,7 +13,7 @@
 class RenderFrame;
 }  // namespace content
 
-namespace chromecast {
+namespace cast_receiver {
 
 // This class provides URL request rewrite rules by binding a
 // UrlRequestRulesReceiver mojo interface and listening for updates from
@@ -43,6 +43,6 @@
   base::OnceCallback<void(int)> on_render_frame_deleted_callback_;
 };
 
-}  // namespace chromecast
+}  // namespace cast_receiver
 
-#endif  // CHROMECAST_RENDERER_URL_REWRITE_RULES_PROVIDER_H_
+#endif  // COMPONENTS_CAST_RECEIVER_RENDERER_PUBLIC_URL_REWRITE_RULES_PROVIDER_H_
diff --git a/chromecast/renderer/url_rewrite_rules_provider.cc b/components/cast_receiver/renderer/url_rewrite_rules_provider.cc
similarity index 88%
rename from chromecast/renderer/url_rewrite_rules_provider.cc
rename to components/cast_receiver/renderer/url_rewrite_rules_provider.cc
index a81a860..4dee425 100644
--- a/chromecast/renderer/url_rewrite_rules_provider.cc
+++ b/components/cast_receiver/renderer/url_rewrite_rules_provider.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromecast/renderer/url_rewrite_rules_provider.h"
+#include "components/cast_receiver/renderer/public/url_rewrite_rules_provider.h"
 
 #include "base/bind.h"
 #include "content/public/renderer/render_frame.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
 
-namespace chromecast {
+namespace cast_receiver {
 
 UrlRewriteRulesProvider::UrlRewriteRulesProvider(
     content::RenderFrame* render_frame,
@@ -32,4 +32,4 @@
   std::move(on_render_frame_deleted_callback_).Run(routing_id());
 }
 
-}  // namespace chromecast
+}  // namespace cast_receiver
diff --git a/components/custom_handlers/protocol_handler_registry.cc b/components/custom_handlers/protocol_handler_registry.cc
index db7caae..62af553 100644
--- a/components/custom_handlers/protocol_handler_registry.cc
+++ b/components/custom_handlers/protocol_handler_registry.cc
@@ -714,6 +714,10 @@
   is_loading_ = is_loading;
 }
 
+base::WeakPtr<ProtocolHandlerRegistry> ProtocolHandlerRegistry::GetWeakPtr() {
+  return weak_ptr_factory_.GetWeakPtr();
+}
+
 void ProtocolHandlerRegistry::AddPredefinedHandler(
     const ProtocolHandler& handler) {
   DCHECK(!is_loaded_);  // Must be called prior InitProtocolSettings.
diff --git a/components/custom_handlers/protocol_handler_registry.h b/components/custom_handlers/protocol_handler_registry.h
index 1e9fb348..ab95d42 100644
--- a/components/custom_handlers/protocol_handler_registry.h
+++ b/components/custom_handlers/protocol_handler_registry.h
@@ -218,6 +218,8 @@
 
   void SetIsLoading(bool is_loading);
 
+  base::WeakPtr<ProtocolHandlerRegistry> GetWeakPtr();
+
  private:
   friend class base::DeleteHelper<ProtocolHandlerRegistry>;
   friend struct content::BrowserThread::DeleteOnThread<
diff --git a/components/custom_handlers/protocol_handler_throttle.cc b/components/custom_handlers/protocol_handler_throttle.cc
index 3e7182f..0232dfa 100644
--- a/components/custom_handlers/protocol_handler_throttle.cc
+++ b/components/custom_handlers/protocol_handler_throttle.cc
@@ -10,8 +10,10 @@
 namespace custom_handlers {
 
 ProtocolHandlerThrottle::ProtocolHandlerThrottle(
-    const custom_handlers::ProtocolHandlerRegistry& protocol_handler_registry)
-    : protocol_handler_registry_(&protocol_handler_registry) {}
+    custom_handlers::ProtocolHandlerRegistry& protocol_handler_registry)
+    : protocol_handler_registry_(protocol_handler_registry.GetWeakPtr()) {}
+
+ProtocolHandlerThrottle::~ProtocolHandlerThrottle() = default;
 
 void ProtocolHandlerThrottle::WillStartRequest(
     network::ResourceRequest* request,
@@ -31,9 +33,11 @@
 
 void ProtocolHandlerThrottle::TranslateUrl(GURL& url) {
   // TODO(jfernandez): We should use scheme_piece instead, which would imply
-  // adadpting the ProtocolHandlerRegistry code to use StringPiece.
-  if (!protocol_handler_registry_->IsHandledProtocol(url.scheme()))
+  // adapting the ProtocolHandlerRegistry code to use StringPiece.
+  if (!protocol_handler_registry_ ||
+      !protocol_handler_registry_->IsHandledProtocol(url.scheme())) {
     return;
+  }
   GURL translated_url = protocol_handler_registry_->Translate(url);
   if (!translated_url.is_empty())
     url = translated_url;
diff --git a/components/custom_handlers/protocol_handler_throttle.h b/components/custom_handlers/protocol_handler_throttle.h
index ccc0691..6b8245d 100644
--- a/components/custom_handlers/protocol_handler_throttle.h
+++ b/components/custom_handlers/protocol_handler_throttle.h
@@ -5,7 +5,7 @@
 #ifndef COMPONENTS_CUSTOM_HANDLERS_PROTOCOL_HANDLER_THROTTLE_H_
 #define COMPONENTS_CUSTOM_HANDLERS_PROTOCOL_HANDLER_THROTTLE_H_
 
-#include "base/memory/raw_ptr.h"
+#include "base/memory/ref_counted.h"
 #include "url/gurl.h"
 
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
@@ -16,8 +16,8 @@
 
 class ProtocolHandlerThrottle : public blink::URLLoaderThrottle {
  public:
-  explicit ProtocolHandlerThrottle(const ProtocolHandlerRegistry&);
-  ~ProtocolHandlerThrottle() override = default;
+  explicit ProtocolHandlerThrottle(ProtocolHandlerRegistry&);
+  ~ProtocolHandlerThrottle() override;
 
   void WillStartRequest(network::ResourceRequest* request,
                         bool* defer) override;
@@ -35,9 +35,9 @@
   // translated url.
   void TranslateUrl(GURL& url);
   // The ProtocolHandlerRegistry instance is a KeyedService which ownership is
-  // managed by the BrowseContext.
-  raw_ptr<const ProtocolHandlerRegistry, DanglingUntriaged>
-      protocol_handler_registry_;
+  // managed by the BrowserContext. BrowserContext can be destroyed before this
+  // throttle.
+  base::WeakPtr<ProtocolHandlerRegistry> protocol_handler_registry_;
 };
 
 }  // namespace custom_handlers
diff --git a/components/desks_storage/BUILD.gn b/components/desks_storage/BUILD.gn
index dad81af..b958372 100644
--- a/components/desks_storage/BUILD.gn
+++ b/components/desks_storage/BUILD.gn
@@ -82,7 +82,5 @@
     "//components/app_constants",
     "//components/sync:test_support",
     "//testing/gtest",
-    "//ui/gfx/geometry",
-    "//ui/gfx/range",
   ]
 }
diff --git a/components/desks_storage/DEPS b/components/desks_storage/DEPS
index 3cb20ab..e27267f6 100644
--- a/components/desks_storage/DEPS
+++ b/components/desks_storage/DEPS
@@ -13,6 +13,5 @@
   "+third_party/re2",
   "+ui/base/ui_base_types.h",
   "+ui/base/window_open_disposition.h",
-  "+ui/gfx/geometry",
-  "+ui/gfx/range",
+  "+ui/gfx/geometry"
 ]
diff --git a/components/desks_storage/core/desk_sync_bridge_unittest.cc b/components/desks_storage/core/desk_sync_bridge_unittest.cc
index 03fd2a0..7858ce54 100644
--- a/components/desks_storage/core/desk_sync_bridge_unittest.cc
+++ b/components/desks_storage/core/desk_sync_bridge_unittest.cc
@@ -935,14 +935,9 @@
       SavedDeskBuilder()
           .SetUuid(base::StringPrintf(kUuidFormat, kDefaultTemplateIndex))
           .SetName(base::StringPrintf(kNameFormat, kDefaultTemplateIndex))
-          .AddAppWindow(
-              SavedDeskBrowserBuilder()
-                  .SetUrls({GURL(base::StringPrintf(kTestUrlFormat, 1)),
-                            GURL(base::StringPrintf(kTestUrlFormat, 2))})
-                  .SetIsLacros(false)
-                  .SetGenericBuilder(SavedDeskGenericAppBuilder().SetWindowId(
-                      kBrowserWindowId))
-                  .Build())
+          .AddAshBrowserAppWindow(kBrowserWindowId,
+                                  {GURL(base::StringPrintf(kTestUrlFormat, 1)),
+                                   GURL(base::StringPrintf(kTestUrlFormat, 2))})
           .Build();
 
   EXPECT_THAT(
@@ -961,14 +956,9 @@
       SavedDeskBuilder()
           .SetUuid(base::StringPrintf(kUuidFormat, kDefaultTemplateIndex))
           .SetName(base::StringPrintf(kNameFormat, kDefaultTemplateIndex))
-          .AddAppWindow(
-              SavedDeskBrowserBuilder()
-                  .SetUrls({GURL(base::StringPrintf(kTestUrlFormat, 1)),
-                            GURL(base::StringPrintf(kTestUrlFormat, 2))})
-                  .SetIsLacros(true)
-                  .SetGenericBuilder(SavedDeskGenericAppBuilder().SetWindowId(
-                      kBrowserWindowId))
-                  .Build())
+          .AddLacrosBrowserAppWindow(
+              kBrowserWindowId, {GURL(base::StringPrintf(kTestUrlFormat, 1)),
+                                 GURL(base::StringPrintf(kTestUrlFormat, 2))})
           .Build();
 
   EXPECT_THAT(
@@ -984,14 +974,8 @@
       SavedDeskBuilder()
           .SetUuid(base::StringPrintf(kUuidFormat, kDefaultTemplateIndex))
           .SetName(base::StringPrintf(kNameFormat, kDefaultTemplateIndex))
-          .AddAppWindow(
-              SavedDeskBrowserBuilder()
-                  .SetUrls({GURL(base::StringPrintf(kTestUrlFormat, 1))})
-                  .SetIsLacros(false)
-                  .SetIsApp(true)
-                  .SetGenericBuilder(
-                      SavedDeskGenericAppBuilder().SetWindowId(kPwaWindowId))
-                  .Build())
+          .AddAshPwaAppWindow(kPwaWindowId,
+                              base::StringPrintf(kTestUrlFormat, 1))
           .Build();
 
   EXPECT_THAT(
@@ -1007,14 +991,8 @@
       SavedDeskBuilder()
           .SetUuid(base::StringPrintf(kUuidFormat, kDefaultTemplateIndex))
           .SetName(base::StringPrintf(kNameFormat, kDefaultTemplateIndex))
-          .AddAppWindow(
-              SavedDeskBrowserBuilder()
-                  .SetUrls({GURL(base::StringPrintf(kTestUrlFormat, 1))})
-                  .SetIsLacros(true)
-                  .SetIsApp(true)
-                  .SetGenericBuilder(
-                      SavedDeskGenericAppBuilder().SetWindowId(kPwaWindowId))
-                  .Build())
+          .AddLacrosPwaAppWindow(kPwaWindowId,
+                                 base::StringPrintf(kTestUrlFormat, 1))
           .Build();
 
   EXPECT_THAT(
@@ -1030,10 +1008,8 @@
       SavedDeskBuilder()
           .SetUuid(base::StringPrintf(kUuidFormat, kDefaultTemplateIndex))
           .SetName(base::StringPrintf(kNameFormat, kDefaultTemplateIndex))
-          .AddAppWindow(SavedDeskGenericAppBuilder()
-                            .SetAppId(desk_test_util::kTestChromeAppId)
-                            .SetWindowId(kChromeAppWindowId)
-                            .Build())
+          .AddChromeAppWindow(kChromeAppWindowId,
+                              desk_test_util::kTestChromeAppId)
           .Build();
 
   EXPECT_THAT(
@@ -1050,10 +1026,8 @@
       SavedDeskBuilder()
           .SetUuid(base::StringPrintf(kUuidFormat, kDefaultTemplateIndex))
           .SetName(base::StringPrintf(kNameFormat, kDefaultTemplateIndex))
-          .AddAppWindow(SavedDeskGenericAppBuilder()
-                            .SetAppId(desk_test_util::kTestLacrosChromeAppId)
-                            .SetWindowId(kChromeAppWindowId)
-                            .Build())
+          .AddChromeAppWindow(kChromeAppWindowId,
+                              desk_test_util::kTestLacrosChromeAppId)
           .Build();
 
   EXPECT_THAT(
@@ -1071,14 +1045,10 @@
       SavedDeskBuilder()
           .SetUuid(base::StringPrintf(kUuidFormat, kDefaultTemplateIndex))
           .SetName(base::StringPrintf(kNameFormat, kDefaultTemplateIndex))
-          .AddAppWindow(SavedDeskGenericAppBuilder()
-                            .SetWindowId(kChromeAppWindowId)
-                            .SetAppId(desk_test_util::kTestChromeAppId)
-                            .Build())
-          .AddAppWindow(SavedDeskGenericAppBuilder()
-                            .SetWindowId(kUnsupportedAppWindowId)
-                            .SetAppId(desk_test_util::kTestUnsupportedAppId)
-                            .Build())
+          .AddChromeAppWindow(kChromeAppWindowId,
+                              desk_test_util::kTestChromeAppId)
+          .AddGenericAppWindow(kUnsupportedAppWindowId,
+                               desk_test_util::kTestUnsupportedAppId)
           .Build();
 
   EXPECT_THAT(
diff --git a/components/desks_storage/core/desk_template_conversion_unittests.cc b/components/desks_storage/core/desk_template_conversion_unittests.cc
index d7e6d89..af19b3f 100644
--- a/components/desks_storage/core/desk_template_conversion_unittests.cc
+++ b/components/desks_storage/core/desk_template_conversion_unittests.cc
@@ -365,12 +365,8 @@
           .SetName(kBrowserTemplateName)
           .SetType(ash::DeskTemplateType::kSaveAndRecall)
           .SetCreatedTime(created_time)
-          .AddAppWindow(
-              SavedDeskBrowserBuilder()
-                  .SetGenericBuilder(SavedDeskGenericAppBuilder().SetWindowId(
-                      kBrowserWindowId))
-                  .SetUrls({GURL(kBrowserUrl1), GURL(kBrowserUrl2)})
-                  .Build())
+          .AddLacrosBrowserAppWindow(kBrowserWindowId,
+                                     {GURL(kBrowserUrl1), GURL(kBrowserUrl2)})
           .Build();
 
   base::Value desk_template_value =
diff --git a/components/desks_storage/core/saved_desk_builder.cc b/components/desks_storage/core/saved_desk_builder.cc
index 2a6b747..cf90199e 100644
--- a/components/desks_storage/core/saved_desk_builder.cc
+++ b/components/desks_storage/core/saved_desk_builder.cc
@@ -6,357 +6,28 @@
 
 #include "ash/public/cpp/desk_template.h"
 #include "base/guid.h"
-#include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
-#include "components/app_constants/constants.h"
 #include "components/app_restore/app_launch_info.h"
-#include "components/desks_storage/core/desk_template_conversion.h"
 #include "components/desks_storage/core/saved_desk_test_util.h"
-#include "components/tab_groups/tab_group_visual_data.h"
 
 namespace desks_storage {
 
-namespace {
-
-// Fills restore data by invoking `builder`s build method.  Drops data if the
-// build fails.
-void FillRestoreData(BuiltApp& app,
-                     app_restore::RestoreData* out_restore_data) {
-  if (app.status != BuiltApp::Status::kOk)
-    return;
-
-  // Something has gone very wrong if we built with OK status and don't have
-  // a `window_id` or `app_id` which are needed to construct a valid launch
-  // info.
-  DCHECK(app.launch_info);
-  DCHECK(app.window_info);
-
-  int32_t window_id = app.launch_info->window_id.value();
-  std::string app_id = app.launch_info->app_id;
-
-  out_restore_data->AddAppLaunchInfo(std::move(app.launch_info));
-  out_restore_data->ModifyWindowInfo(app_id, window_id, *app.window_info.get());
-}
-
-}  // namespace
-
-// SavedDeskGenericAppBuilder implementation.
-SavedDeskGenericAppBuilder::SavedDeskGenericAppBuilder() = default;
-SavedDeskGenericAppBuilder::SavedDeskGenericAppBuilder(
-    SavedDeskGenericAppBuilder&&) = default;
-SavedDeskGenericAppBuilder& SavedDeskGenericAppBuilder::operator=(
-    SavedDeskGenericAppBuilder&&) = default;
-SavedDeskGenericAppBuilder::~SavedDeskGenericAppBuilder() = default;
-
-SavedDeskGenericAppBuilder& SavedDeskGenericAppBuilder::SetWindowBound(
-    gfx::Rect bounds) {
-  window_bounds_ = bounds;
-  return *this;
-}
-
-SavedDeskGenericAppBuilder& SavedDeskGenericAppBuilder::SetWindowState(
-    chromeos::WindowStateType state) {
-  window_show_state_ = state;
-  return *this;
-}
-
-SavedDeskGenericAppBuilder&
-SavedDeskGenericAppBuilder::SetPreMinimizedWindowState(
-    ui::WindowShowState state) {
-  pre_minimized_window_show_state_ = state;
-  return *this;
-}
-
-SavedDeskGenericAppBuilder& SavedDeskGenericAppBuilder::SetAppId(
-    std::string app_id) {
-  app_id_ = app_id;
-  return *this;
-}
-
-SavedDeskGenericAppBuilder& SavedDeskGenericAppBuilder::SetZIndex(int index) {
-  z_index_ = index;
-  return *this;
-}
-
-SavedDeskGenericAppBuilder& SavedDeskGenericAppBuilder::SetWindowId(
-    int window_id) {
-  window_id_ = window_id;
-  return *this;
-}
-
-SavedDeskGenericAppBuilder& SavedDeskGenericAppBuilder::SetDisplayId(
-    int64_t display_id) {
-  display_id_ = display_id;
-  return *this;
-}
-
-SavedDeskGenericAppBuilder& SavedDeskGenericAppBuilder::SetLaunchContainer(
-    apps::LaunchContainer container) {
-  launch_conatiner_ = container;
-  return *this;
-}
-
-SavedDeskGenericAppBuilder&
-SavedDeskGenericAppBuilder::SetWindowOpenDisposition(
-    WindowOpenDisposition disposition) {
-  disposition_ = disposition;
-  return *this;
-}
-
-SavedDeskGenericAppBuilder& SavedDeskGenericAppBuilder::SetName(
-    std::string name) {
-  name_ = name;
-  return *this;
-}
-
-SavedDeskGenericAppBuilder& SavedDeskGenericAppBuilder::SetSnapPercentage(
-    int percentage) {
-  snap_percentage_ = percentage;
-  return *this;
-}
-
-BuiltApp SavedDeskGenericAppBuilder::Build() {
-  if (!window_id_)
-    return BuiltApp(BuiltApp::Status::kNoWindowId, nullptr, nullptr);
-
-  if (!app_id_)
-    app_id_ = GetAppId();
-
-  auto app_launch_info = std::make_unique<app_restore::AppLaunchInfo>(
-      GetAppId(), window_id_.value());
-  auto window_info = std::make_unique<app_restore::WindowInfo>();
-
-  window_info->window_state_type = window_show_state_;
-  window_info->pre_minimized_show_state_type = pre_minimized_window_show_state_;
-  window_info->current_bounds = window_bounds_;
-  window_info->activation_index = z_index_;
-  window_info->snap_percentage = snap_percentage_;
-  window_info->display_id = display_id_;
-
-  if (launch_conatiner_) {
-    app_launch_info->container = absl::optional<int32_t>(
-        static_cast<int32_t>(launch_conatiner_.value()));
-  }
-
-  if (disposition_) {
-    app_launch_info->disposition =
-        absl::optional<int32_t>(static_cast<int32_t>(disposition_.value()));
-  }
-
-  app_launch_info->window_id = window_id_;
-
-  return BuiltApp(BuiltApp::Status::kOk, std::move(window_info),
-                  std::move(app_launch_info));
-}
-
-const std::string& SavedDeskGenericAppBuilder::GetAppId() {
-  if (app_id_)
-    return app_id_.value();
-
-  app_id_ = base::GUID::GenerateRandomV4().AsLowercaseString();
-  return app_id_.value();
-}
-
-// SavedDeskGenericAppBuilder::BuiltApp implementation
-BuiltApp::BuiltApp(BuiltApp::Status status,
-                   std::unique_ptr<app_restore::WindowInfo> window_info,
-                   std::unique_ptr<app_restore::AppLaunchInfo> launch_info)
-    : status(status),
-      window_info(std::move(window_info)),
-      launch_info(std::move(launch_info)) {}
-BuiltApp::BuiltApp(BuiltApp&&) = default;
-BuiltApp& BuiltApp::operator=(BuiltApp&&) = default;
-BuiltApp::~BuiltApp() = default;
-
-// TabGroupWithStatus implementation
-SavedDeskTabGroupBuilder::TabGroupWithStatus::TabGroupWithStatus(
-    TabGroupBuildStatus status,
-    std::unique_ptr<app_restore::TabGroupInfo> tab_group)
-    : status(status), tab_group(std::move(tab_group)) {}
-SavedDeskTabGroupBuilder::TabGroupWithStatus::~TabGroupWithStatus() = default;
-
-// SavedDeskTabGroup builder implementation.
-SavedDeskTabGroupBuilder::SavedDeskTabGroupBuilder() = default;
-SavedDeskTabGroupBuilder::SavedDeskTabGroupBuilder(SavedDeskTabGroupBuilder&&) =
-    default;
-SavedDeskTabGroupBuilder::~SavedDeskTabGroupBuilder() = default;
-
-SavedDeskTabGroupBuilder& SavedDeskTabGroupBuilder::SetRange(gfx::Range range) {
-  range_ = range;
-  return *this;
-}
-
-SavedDeskTabGroupBuilder& SavedDeskTabGroupBuilder::SetTitle(
-    std::string title) {
-  title_ = title;
-  return *this;
-}
-
-SavedDeskTabGroupBuilder& SavedDeskTabGroupBuilder::SetColor(
-    tab_groups::TabGroupColorId color) {
-  color_ = color;
-  return *this;
-}
-
-SavedDeskTabGroupBuilder& SavedDeskTabGroupBuilder::SetIsCollapsed(
-    bool is_collapsed) {
-  is_collapsed_ = is_collapsed;
-  return *this;
-}
-
-SavedDeskTabGroupBuilder::TabGroupWithStatus SavedDeskTabGroupBuilder::Build() {
-  if (!range_ || !title_ || !color_ || !is_collapsed_)
-    return TabGroupWithStatus(TabGroupBuildStatus::kNotAllFieldsSet, nullptr);
-
-  auto tab_group = std::make_unique<app_restore::TabGroupInfo>(
-      range_.value(),
-      tab_groups::TabGroupVisualData(base::UTF8ToUTF16(title_.value()),
-                                     color_.value(), is_collapsed_.value()));
-
-  return TabGroupWithStatus(TabGroupBuildStatus::kOk, std::move(tab_group));
-}
-
-// SavedDeskBrowserBuilder implementation.
-SavedDeskBrowserBuilder::SavedDeskBrowserBuilder() = default;
-SavedDeskBrowserBuilder::~SavedDeskBrowserBuilder() = default;
-
-SavedDeskBrowserBuilder& SavedDeskBrowserBuilder::SetActiveTabIndex(int index) {
-  active_tab_index_ = index;
-  return *this;
-}
-
-SavedDeskBrowserBuilder& SavedDeskBrowserBuilder::SetFirstNonPinnedTabIndex(
-    int index) {
-  first_non_pinned_tab_index_ = index;
-  return *this;
-}
-
-SavedDeskBrowserBuilder& SavedDeskBrowserBuilder::SetUrls(
-    std::vector<GURL> urls) {
-  urls_ = urls;
-  return *this;
-}
-
-SavedDeskBrowserBuilder& SavedDeskBrowserBuilder::SetIsLacros(bool is_lacros) {
-  is_lacros_ = is_lacros;
-  return *this;
-}
-
-SavedDeskBrowserBuilder& SavedDeskBrowserBuilder::SetIsApp(bool is_app) {
-  is_app_ = is_app;
-  return *this;
-}
-
-SavedDeskBrowserBuilder& SavedDeskBrowserBuilder::AddTabGroupBuilder(
-    SavedDeskTabGroupBuilder tab_group) {
-  tab_group_builders_.push_back(std::move(tab_group));
-  return *this;
-}
-
-BuiltApp SavedDeskBrowserBuilder::Build() {
-  generic_builder_.SetAppId(is_lacros_ ? app_constants::kLacrosAppId
-                                       : app_constants::kChromeAppId);
-
-  BuiltApp generic_app = generic_builder_.Build();
-  if (generic_app.status != BuiltApp::Status::kOk)
-    return BuiltApp(generic_app.status, nullptr, nullptr);
-
-  generic_app.launch_info->active_tab_index = active_tab_index_;
-  generic_app.launch_info->first_non_pinned_tab_index =
-      first_non_pinned_tab_index_;
-  generic_app.launch_info->urls = urls_;
-  generic_app.launch_info->app_type_browser = is_app_;
-
-  for (auto& tab_group : tab_group_builders_) {
-    SavedDeskTabGroupBuilder::TabGroupWithStatus built_group =
-        tab_group.Build();
-    if (built_group.status !=
-        SavedDeskTabGroupBuilder::TabGroupBuildStatus::kOk)
-      continue;
-    DCHECK(built_group.tab_group);
-
-    generic_app.launch_info->tab_group_infos.value().push_back(
-        *built_group.tab_group.release());
-  }
-
-  return BuiltApp(BuiltApp::Status::kOk, std::move(generic_app.window_info),
-                  std::move(generic_app.launch_info));
-}
-
-SavedDeskBrowserBuilder& SavedDeskBrowserBuilder::SetGenericBuilder(
-    SavedDeskGenericAppBuilder& generic_builder) {
-  generic_builder_ = std::move(generic_builder);
-  return *this;
-}
-
-// SavedDeskArcAppBuilder implementation
-SavedDeskArcAppBuilder::SavedDeskArcAppBuilder() = default;
-SavedDeskArcAppBuilder::~SavedDeskArcAppBuilder() = default;
-
-SavedDeskArcAppBuilder& SavedDeskArcAppBuilder::SetAppId(std::string app_id) {
-  app_id_ = app_id;
-  return *this;
-}
-
-SavedDeskArcAppBuilder& SavedDeskArcAppBuilder::SetMinimumSize(gfx::Size size) {
-  minimum_size_ = size;
-  return *this;
-}
-
-SavedDeskArcAppBuilder& SavedDeskArcAppBuilder::SetMaximumSize(gfx::Size size) {
-  maximum_size_ = size;
-  return *this;
-}
-
-SavedDeskArcAppBuilder& SavedDeskArcAppBuilder::SetBoundsInRoot(
-    gfx::Rect bounds) {
-  bounds_in_root_ = bounds;
-  return *this;
-}
-
-BuiltApp SavedDeskArcAppBuilder::Build() {
-  BuiltApp generic_app = generic_builder_.SetAppId(app_id_.value()).Build();
-
-  if (generic_app.status != BuiltApp::Status::kOk)
-    return BuiltApp(generic_app.status, nullptr, nullptr);
-
-  app_restore::WindowInfo::ArcExtraInfo arc_info_;
-  arc_info_.bounds_in_root = bounds_in_root_;
-  arc_info_.maximum_size = maximum_size_;
-  arc_info_.minimum_size = minimum_size_;
-
-  generic_app.window_info->arc_extra_info = arc_info_;
-
-  return BuiltApp(BuiltApp::Status::kOk, std::move(generic_app.window_info),
-                  std::move(generic_app.launch_info));
-}
-
-SavedDeskArcAppBuilder& SavedDeskArcAppBuilder::SetGenericBuilder(
-    SavedDeskGenericAppBuilder& generic_builder) {
-  generic_builder_ = std::move(generic_builder);
-  return *this;
-}
-
-// SavedDeskBuilder implementation.
 SavedDeskBuilder::SavedDeskBuilder()
     : desk_name_("unnamed desk"),
       desk_source_(ash::DeskTemplateSource::kUser),
-      desk_type_(ash::DeskTemplateType::kTemplate) {
+      desk_type_(ash::DeskTemplateType::kTemplate),
+      restore_data_(std::make_unique<app_restore::RestoreData>()) {
   desk_uuid_ = base::GUID::GenerateRandomV4();
   created_time_ = base::Time::Now();
 }
-SavedDeskBuilder::~SavedDeskBuilder() = default;
+
+SavedDeskBuilder::~SavedDeskBuilder() {}
 
 std::unique_ptr<ash::DeskTemplate> SavedDeskBuilder::Build() {
   auto desk_template = std::make_unique<ash::DeskTemplate>(
       desk_uuid_, desk_source_, desk_name_, created_time_, desk_type_);
 
-  auto restore_data = std::make_unique<app_restore::RestoreData>();
-
-  for (auto& app : built_apps_)
-    FillRestoreData(app, restore_data.get());
-
-  desk_template->set_desk_restore_data(std::move(restore_data));
+  desk_template->set_desk_restore_data(std::move(restore_data_));
 
   return desk_template;
 }
@@ -387,8 +58,50 @@
   return *this;
 }
 
-SavedDeskBuilder& SavedDeskBuilder::AddAppWindow(BuiltApp built_app) {
-  built_apps_.push_back(std::move(built_app));
+SavedDeskBuilder& SavedDeskBuilder::AddAshBrowserAppWindow(
+    int window_id,
+    std::vector<GURL> urls) {
+  saved_desk_test_util::AddBrowserWindow(/*is_lacros=*/false, window_id, urls,
+                                         restore_data_.get());
+  return *this;
+}
+
+SavedDeskBuilder& SavedDeskBuilder::AddLacrosBrowserAppWindow(
+    int window_id,
+    std::vector<GURL> urls) {
+  saved_desk_test_util::AddBrowserWindow(/*is_lacros=*/true, window_id, urls,
+                                         restore_data_.get());
+  return *this;
+}
+
+SavedDeskBuilder& SavedDeskBuilder::AddAshPwaAppWindow(int window_id,
+                                                       const std::string url) {
+  saved_desk_test_util::AddPwaWindow(/*is_lacros=*/false, window_id, url,
+                                     restore_data_.get());
+  return *this;
+}
+
+SavedDeskBuilder& SavedDeskBuilder::AddLacrosPwaAppWindow(
+    int window_id,
+    const std::string url) {
+  saved_desk_test_util::AddPwaWindow(/*is_lacros=*/true, window_id, url,
+                                     restore_data_.get());
+  return *this;
+}
+
+SavedDeskBuilder& SavedDeskBuilder::AddChromeAppWindow(
+    int window_id,
+    const std::string app_id) {
+  saved_desk_test_util::AddGenericAppWindow(window_id, app_id,
+                                            restore_data_.get());
+  return *this;
+}
+
+SavedDeskBuilder& SavedDeskBuilder::AddGenericAppWindow(
+    int window_id,
+    const std::string app_id) {
+  saved_desk_test_util::AddGenericAppWindow(window_id, app_id,
+                                            restore_data_.get());
   return *this;
 }
 
diff --git a/components/desks_storage/core/saved_desk_builder.h b/components/desks_storage/core/saved_desk_builder.h
index 448a5a80..b3a2e46 100644
--- a/components/desks_storage/core/saved_desk_builder.h
+++ b/components/desks_storage/core/saved_desk_builder.h
@@ -10,19 +10,7 @@
 
 #include "base/guid.h"
 #include "base/time/time.h"
-#include "chromeos/ui/base/window_state_type.h"
-#include "components/app_restore/app_launch_info.h"
 #include "components/app_restore/restore_data.h"
-#include "components/app_restore/tab_group_info.h"
-#include "components/app_restore/window_info.h"
-#include "components/services/app_service/public/cpp/app_launch_util.h"
-#include "components/sync/protocol/workspace_desk_specifics.pb.h"
-#include "components/tab_groups/tab_group_color.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "ui/base/ui_base_types.h"
-#include "ui/base/window_open_disposition.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/range/range.h"
 #include "url/gurl.h"
 
 namespace ash {
@@ -33,198 +21,6 @@
 
 namespace desks_storage {
 
-// This structure represents an app that has been built by a builder.
-// Both the window_info struct and the launch info struct are needed by the
-// AppRestoreClass to add a new app.
-struct BuiltApp {
-  enum Status {
-    kOk,
-    // All apps must have a window Id.
-    kNoWindowId
-  };
-
-  BuiltApp(Status status,
-           std::unique_ptr<app_restore::WindowInfo> window_info,
-           std::unique_ptr<app_restore::AppLaunchInfo> launch_info);
-  BuiltApp(BuiltApp&&);
-  BuiltApp& operator=(BuiltApp&&);
-  ~BuiltApp();
-
-  // Any BuiltApp that does not have status kOk should be discarded.
-  Status status;
-  std::unique_ptr<app_restore::WindowInfo> window_info;
-  std::unique_ptr<app_restore::AppLaunchInfo> launch_info;
-};
-
-// Generic App Builder class that contains the definitions for the
-// base fields that can be set for every app.  Chrome Apps, SWAs
-// and other unknown types can be generated via this class.
-class SavedDeskGenericAppBuilder {
- public:
-  SavedDeskGenericAppBuilder();
-  SavedDeskGenericAppBuilder(const SavedDeskGenericAppBuilder&) = delete;
-  SavedDeskGenericAppBuilder& operator=(const SavedDeskGenericAppBuilder&) =
-      delete;
-  SavedDeskGenericAppBuilder(SavedDeskGenericAppBuilder&&);
-  SavedDeskGenericAppBuilder& operator=(SavedDeskGenericAppBuilder&&);
-  ~SavedDeskGenericAppBuilder();
-
-  // This method builds a generic app and populates a BuiltApp struct with
-  // initial fields.
-  BuiltApp Build();
-
-  // Setters and Adders.
-  SavedDeskGenericAppBuilder& SetAppId(std::string app_id_);
-  SavedDeskGenericAppBuilder& SetWindowBound(gfx::Rect bounds);
-  SavedDeskGenericAppBuilder& SetWindowState(chromeos::WindowStateType state);
-  SavedDeskGenericAppBuilder& SetPreMinimizedWindowState(
-      ui::WindowShowState state);
-  SavedDeskGenericAppBuilder& SetZIndex(int index);
-  SavedDeskGenericAppBuilder& SetWindowId(int window_id);
-  SavedDeskGenericAppBuilder& SetDisplayId(int64_t display_id);
-  SavedDeskGenericAppBuilder& SetLaunchContainer(
-      apps::LaunchContainer container);
-  SavedDeskGenericAppBuilder& SetWindowOpenDisposition(
-      WindowOpenDisposition disposition);
-  SavedDeskGenericAppBuilder& SetName(std::string name);
-  SavedDeskGenericAppBuilder& SetSnapPercentage(int percentage);
-
-  // Apps are keyed by their ID, this returns the ID associated with this app
-  // assuming it has been set.  There are some special app cases in which this
-  // ID is a constant (i.e. a browser)  In the case where this is an app
-  // with an assignable ID then a random one is assigned upon calling this
-  // method.
-  const std::string& GetAppId();
-
- private:
-  absl::optional<std::string> app_id_;
-  absl::optional<gfx::Rect> window_bounds_;
-  absl::optional<chromeos::WindowStateType> window_show_state_;
-  absl::optional<ui::WindowShowState> pre_minimized_window_show_state_;
-  absl::optional<int> z_index_;
-  absl::optional<int> window_id_;
-  absl::optional<int64_t> display_id_;
-  absl::optional<apps::LaunchContainer> launch_conatiner_;
-  absl::optional<WindowOpenDisposition> disposition_;
-  absl::optional<std::string> name_;
-  absl::optional<int> snap_percentage_;
-};
-
-// Builder for TabGroups.  Each instance represents a single tab group.
-class SavedDeskTabGroupBuilder {
- public:
-  enum TabGroupBuildStatus {
-    kOk,
-    // All fields must be set to build a TabGroup.
-    kNotAllFieldsSet
-  };
-
-  // Caller will have to release the TabGroup from the unique_ptr contained
-  // within.  This will help facilitate moving this result object around after
-  // calling build.
-  struct TabGroupWithStatus {
-    TabGroupWithStatus(TabGroupBuildStatus status,
-                       std::unique_ptr<app_restore::TabGroupInfo> tab_group);
-    ~TabGroupWithStatus();
-
-    TabGroupBuildStatus status;
-    std::unique_ptr<app_restore::TabGroupInfo> tab_group;
-  };
-
-  SavedDeskTabGroupBuilder();
-  SavedDeskTabGroupBuilder(const SavedDeskTabGroupBuilder&) = delete;
-  SavedDeskTabGroupBuilder& operator=(const SavedDeskTabGroupBuilder&) = delete;
-  SavedDeskTabGroupBuilder(SavedDeskTabGroupBuilder&&);
-  ~SavedDeskTabGroupBuilder();
-
-  // Setters and adders.
-  SavedDeskTabGroupBuilder& SetRange(gfx::Range range);
-  SavedDeskTabGroupBuilder& SetTitle(std::string title);
-  SavedDeskTabGroupBuilder& SetColor(tab_groups::TabGroupColorId color);
-  SavedDeskTabGroupBuilder& SetIsCollapsed(bool is_collapsed);
-
-  // Returns a TabGroupWithStatus, pointer to the tab group will be nullptr
-  // unless all fields associated with this struct are set.
-  TabGroupWithStatus Build();
-
- private:
-  absl::optional<gfx::Range> range_;
-  absl::optional<std::string> title_;
-  absl::optional<tab_groups::TabGroupColorId> color_;
-  absl::optional<bool> is_collapsed_;
-};
-
-// Builder that constructs Browser representations, this can also be used to
-// create PWAs.  To construct a PWA only use a single URL in the URLs field
-// and set IsApp to true.  Requires a GenericAppBuilder with `window_id` set
-// in order to correctly build.
-class SavedDeskBrowserBuilder {
- public:
-  SavedDeskBrowserBuilder();
-  SavedDeskBrowserBuilder(const SavedDeskBrowserBuilder&) = delete;
-  SavedDeskBrowserBuilder& operator=(const SavedDeskBrowserBuilder&) = delete;
-  ~SavedDeskBrowserBuilder();
-
-  BuiltApp Build();
-
-  // Compose a generic builder to build with altered generic traits.
-  SavedDeskBrowserBuilder& SetGenericBuilder(
-      SavedDeskGenericAppBuilder& generic_builder);
-
-  // setters and adders.
-  SavedDeskBrowserBuilder& SetFirstNonPinnedTabIndex(int index);
-  SavedDeskBrowserBuilder& SetActiveTabIndex(int index);
-  SavedDeskBrowserBuilder& SetUrls(std::vector<GURL> urls);
-  SavedDeskBrowserBuilder& SetIsLacros(bool is_lacros);
-  SavedDeskBrowserBuilder& AddTabGroupBuilder(
-      SavedDeskTabGroupBuilder tab_group);
-
-  // Indicates that this browser instance is a PWA.
-  SavedDeskBrowserBuilder& SetIsApp(bool is_app);
-
-  const std::string& GetAppId();
-
- private:
-  SavedDeskGenericAppBuilder generic_builder_;
-
-  bool is_lacros_;
-  absl::optional<bool> is_app_;
-  std::vector<SavedDeskTabGroupBuilder> tab_group_builders_;
-  absl::optional<int> active_tab_index_;
-  absl::optional<int> first_non_pinned_tab_index_;
-  absl::optional<std::vector<GURL>> urls_;
-};
-
-// Builder that constructs arc apps.  Requires a GenericAppBuilder with the
-// `window_id` field set to construct properly.
-class SavedDeskArcAppBuilder {
- public:
-  SavedDeskArcAppBuilder();
-  SavedDeskArcAppBuilder(const SavedDeskArcAppBuilder&) = delete;
-  SavedDeskArcAppBuilder operator=(const SavedDeskArcAppBuilder&) = delete;
-  ~SavedDeskArcAppBuilder();
-
-  BuiltApp Build();
-
-  // set composed generic builder for setting generic traits.
-  SavedDeskArcAppBuilder& SetGenericBuilder(
-      SavedDeskGenericAppBuilder& generic_builder);
-
-  // setters and adders.
-  SavedDeskArcAppBuilder& SetAppId(std::string app_id);
-  SavedDeskArcAppBuilder& SetMinimumSize(gfx::Size size);
-  SavedDeskArcAppBuilder& SetMaximumSize(gfx::Size size);
-  SavedDeskArcAppBuilder& SetBoundsInRoot(gfx::Rect bounds_in_root);
-
- private:
-  SavedDeskGenericAppBuilder generic_builder_;
-
-  absl::optional<std::string> app_id_;
-  absl::optional<gfx::Size> minimum_size_;
-  absl::optional<gfx::Size> maximum_size_;
-  absl::optional<gfx::Rect> bounds_in_root_;
-};
-
 // Helper class for building a saved desk for test.
 class SavedDeskBuilder {
  public:
@@ -254,8 +50,26 @@
   // its creation timestamp set at the creation time of the SavedDeskBuilder.
   SavedDeskBuilder& SetCreatedTime(base::Time& created_time);
 
-  // Adds an app window.
-  SavedDeskBuilder& AddAppWindow(BuiltApp built_app);
+  // Adds a Ash Chrome Browser App window.
+  SavedDeskBuilder& AddAshBrowserAppWindow(int window_id,
+                                           std::vector<GURL> urls);
+
+  // Adds a Lacros Chrome Browser App window.
+  SavedDeskBuilder& AddLacrosBrowserAppWindow(int window_id,
+                                              std::vector<GURL> urls);
+
+  // Adds a PWA window hosted in Ash Chrome.
+  SavedDeskBuilder& AddAshPwaAppWindow(int window_id, const std::string url);
+
+  // Adds a PWA window hosted in Lacros Chrome.
+  SavedDeskBuilder& AddLacrosPwaAppWindow(int window_id, const std::string url);
+
+  // Adds a Chrome app window.
+  SavedDeskBuilder& AddChromeAppWindow(int window_id, const std::string app_id);
+
+  // Adds a generic app window.
+  SavedDeskBuilder& AddGenericAppWindow(int window_id,
+                                        const std::string app_id);
 
  private:
   base::GUID desk_uuid_;
@@ -263,7 +77,7 @@
   ash::DeskTemplateSource desk_source_;
   ash::DeskTemplateType desk_type_;
   base::Time created_time_;
-  std::vector<BuiltApp> built_apps_;
+  std::unique_ptr<app_restore::RestoreData> restore_data_;
 };
 
 }  // namespace desks_storage
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java
index 50ae73f..b4cbd95 100644
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java
@@ -11,7 +11,6 @@
 import androidx.annotation.IntDef;
 
 import org.chromium.base.Callback;
-import org.chromium.base.Function;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.WebContents;
@@ -21,6 +20,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
+import java.util.function.Function;
 
 /**
  * A delegate for {@link ExternalNavigationHandler}.
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java
index 3de49c1..4ad32655 100644
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java
@@ -14,7 +14,6 @@
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.ContextUtils;
-import org.chromium.base.Function;
 import org.chromium.base.IntentUtils;
 import org.chromium.base.Log;
 import org.chromium.base.metrics.RecordHistogram;
@@ -22,6 +21,7 @@
 
 import java.util.HashSet;
 import java.util.List;
+import java.util.function.Function;
 
 /**
  * This class contains the logic to determine effective navigation/redirect.
diff --git a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
index f6c73579..92fdbeb 100644
--- a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
+++ b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
@@ -42,7 +42,6 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.ContextUtils;
-import org.chromium.base.Function;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
@@ -68,6 +67,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Function;
 import java.util.regex.Pattern;
 
 /**
diff --git a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/RedirectHandlerTest.java b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/RedirectHandlerTest.java
index 8ed05c5..30553a56 100644
--- a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/RedirectHandlerTest.java
+++ b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/RedirectHandlerTest.java
@@ -21,7 +21,6 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.ContextUtils;
-import org.chromium.base.Function;
 import org.chromium.base.PackageManagerUtils;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.util.AdvancedMockContext;
@@ -33,6 +32,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Function;
 
 /**
  * Unittests for tab redirect handler.
diff --git a/components/module_installer/android/java/src/org/chromium/components/module_installer/engine/SplitCompatEngine.java b/components/module_installer/android/java/src/org/chromium/components/module_installer/engine/SplitCompatEngine.java
index 0c76f34..a09fe3429 100644
--- a/components/module_installer/android/java/src/org/chromium/components/module_installer/engine/SplitCompatEngine.java
+++ b/components/module_installer/android/java/src/org/chromium/components/module_installer/engine/SplitCompatEngine.java
@@ -19,7 +19,6 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
@@ -60,16 +59,17 @@
     public void install(String moduleName, InstallListener listener) {
         ThreadUtils.assertOnUiThread();
 
-        if (sSessions.containsKey(moduleName)) {
-            sSessions.get(moduleName).add(listener);
+        List<InstallListener> listeners = sSessions.get(moduleName);
+        if (listeners != null) {
+            listeners.add(listener);
             return;
         }
 
         registerUpdateListener();
 
-        sSessions.put(moduleName, new ArrayList<InstallListener>() {
-            { add(listener); }
-        });
+        listeners = new ArrayList<>();
+        listeners.add(listener);
+        sSessions.put(moduleName, listeners);
 
         SplitInstallRequest request = mFacade.createSplitInstallRequest(moduleName);
 
@@ -80,8 +80,6 @@
                     ex instanceof SplitInstallException
                             ? ((SplitInstallException) ex).getErrorCode()
                             : mFacade.getLogger().getUnknownRequestErrorCode());
-
-            String message = String.format(Locale.US, "Request Exception: %s", ex.getMessage());
             notifyListeners(moduleName, false);
         });
 
diff --git a/components/optimization_guide/core/tflite_op_resolver.cc b/components/optimization_guide/core/tflite_op_resolver.cc
index 87da57d4a..947645c7 100644
--- a/components/optimization_guide/core/tflite_op_resolver.cc
+++ b/components/optimization_guide/core/tflite_op_resolver.cc
@@ -384,8 +384,8 @@
 
 #if BUILDFLAG(BUILD_TFLITE_WITH_XNNPACK)
   if (features::TFLiteXNNPACKDelegateEnabled()) {
-    delegate_creators_.push_back([](int num_threads) {
-      return tflite::MaybeCreateXNNPACKDelegate(num_threads);
+    delegate_creators_.push_back([](TfLiteContext* context) {
+      return tflite::MaybeCreateXNNPACKDelegate(context);
     });
   }
 #endif
diff --git a/components/paint_preview/browser/paint_preview_base_service.cc b/components/paint_preview/browser/paint_preview_base_service.cc
index 2ff63fc..452f63e 100644
--- a/components/paint_preview/browser/paint_preview_base_service.cc
+++ b/components/paint_preview/browser/paint_preview_base_service.cc
@@ -56,8 +56,7 @@
     params.root_dir = *capture_params.root_dir;
   }
   params.inner.clip_rect = capture_params.clip_rect;
-  params.inner.is_main_frame =
-      (render_frame_host == web_contents->GetPrimaryMainFrame());
+  params.inner.is_main_frame = render_frame_host->IsInPrimaryMainFrame();
   params.inner.capture_links = capture_params.capture_links;
   params.inner.max_capture_size = capture_params.max_per_capture_size;
   params.inner.max_decoded_image_size_bytes =
diff --git a/components/reporting/client/mock_report_queue_provider.cc b/components/reporting/client/mock_report_queue_provider.cc
index 657bc8d..9d389064 100644
--- a/components/reporting/client/mock_report_queue_provider.cc
+++ b/components/reporting/client/mock_report_queue_provider.cc
@@ -12,7 +12,7 @@
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/thread_pool.h"
 #include "base/test/gmock_callback_support.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "components/reporting/client/mock_report_queue.h"
 #include "components/reporting/client/report_queue.h"
 #include "components/reporting/client/report_queue_configuration.h"
@@ -34,7 +34,7 @@
                 std::move(storage_created_cb)
                     .Run(base::MakeRefCounted<test::TestStorageModule>());
               }),
-          base::ThreadTaskRunnerHandle::Get()) {}
+          base::SequencedTaskRunner::GetCurrentDefault()) {}
 
 MockReportQueueProvider::~MockReportQueueProvider() = default;
 
diff --git a/components/reporting/client/report_queue_factory.cc b/components/reporting/client/report_queue_factory.cc
index 459bd92f..92b8897 100644
--- a/components/reporting/client/report_queue_factory.cc
+++ b/components/reporting/client/report_queue_factory.cc
@@ -12,7 +12,7 @@
 #include "base/task/bind_post_task.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/thread_pool.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "components/reporting/client/report_queue_configuration.h"
 #include "components/reporting/client/report_queue_provider.h"
 #include "components/reporting/util/backoff_settings.h"
@@ -28,7 +28,7 @@
                                 Destination destination,
                                 SuccessCallback success_cb,
                                 int64_t reserved_space) {
-  DCHECK(base::ThreadTaskRunnerHandle::IsSet());
+  DCHECK(base::SequencedTaskRunner::HasCurrentDefault());
 
   auto config_result = ReportQueueConfiguration::Create(
       event_type, destination,
@@ -85,7 +85,7 @@
     SuccessCallback success_cb,
     std::unique_ptr<::net::BackoffEntry> backoff_entry) {
   return base::BindPostTask(
-      base::ThreadTaskRunnerHandle::Get(),
+      base::SequencedTaskRunner::GetCurrentDefault(),
       base::BindOnce(&ReportQueueFactory::TrySetReportQueue,
                      std::move(success_cb)));
 }
diff --git a/components/reporting/encryption/decryption.h b/components/reporting/encryption/decryption.h
index 20dbdad..d11c960 100644
--- a/components/reporting/encryption/decryption.h
+++ b/components/reporting/encryption/decryption.h
@@ -13,7 +13,6 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/strings/string_piece.h"
 #include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "components/reporting/encryption/encryption.h"
 #include "components/reporting/util/status.h"
 #include "components/reporting/util/statusor.h"
diff --git a/components/reporting/metrics/metric_event_observer_manager.cc b/components/reporting/metrics/metric_event_observer_manager.cc
index e18af40..21bf5aa 100644
--- a/components/reporting/metrics/metric_event_observer_manager.cc
+++ b/components/reporting/metrics/metric_event_observer_manager.cc
@@ -45,7 +45,8 @@
                          std::move(on_event_observed_cb)));
 
   reporting_controller_ = std::make_unique<MetricReportingController>(
-      reporting_settings, enable_setting_path, setting_enabled_default_value,
+      reporting_settings, enable_setting_path, setting_enabled_default_value);
+  reporting_controller_->SetSettingUpdateCb(
       base::BindRepeating(&MetricEventObserverManager::SetReportingEnabled,
                           base::Unretained(this),
                           /*is_enabled=*/true),
diff --git a/components/reporting/metrics/metric_reporting_controller.cc b/components/reporting/metrics/metric_reporting_controller.cc
index 5107dabd..84b2dba 100644
--- a/components/reporting/metrics/metric_reporting_controller.cc
+++ b/components/reporting/metrics/metric_reporting_controller.cc
@@ -4,7 +4,9 @@
 
 #include "components/reporting/metrics/metric_reporting_controller.h"
 
-#include "base/bind.h"
+#include <utility>
+
+#include "base/functional/bind.h"
 #include "base/task/bind_post_task.h"
 #include "base/task/sequenced_task_runner.h"
 #include "components/reporting/metrics/reporting_settings.h"
@@ -14,14 +16,10 @@
 MetricReportingController::MetricReportingController(
     ReportingSettings* reporting_settings,
     const std::string& setting_path,
-    bool setting_enabled_default_value,
-    base::RepeatingClosure on_setting_enabled,
-    base::RepeatingClosure on_setting_disabled)
+    bool setting_enabled_default_value)
     : reporting_settings_(reporting_settings),
       setting_path_(setting_path),
-      setting_enabled_default_value_(setting_enabled_default_value),
-      on_setting_enabled_(std::move(on_setting_enabled)),
-      on_setting_disabled_(std::move(on_setting_disabled)) {
+      setting_enabled_default_value_(setting_enabled_default_value) {
   UpdateSetting();
 
   subscription_ = reporting_settings_->AddSettingsObserver(
@@ -34,6 +32,18 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
+void MetricReportingController::SetSettingUpdateCb(
+    base::RepeatingClosure on_setting_enabled,
+    base::RepeatingClosure on_setting_disabled) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  on_setting_enabled_ = std::move(on_setting_enabled);
+  on_setting_disabled_ = std::move(on_setting_disabled);
+  if (setting_enabled_) {
+    on_setting_enabled_.Run();
+  }
+}
+
 void MetricReportingController::UpdateSetting() {
   CHECK(base::SequencedTaskRunner::HasCurrentDefault());
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/components/reporting/metrics/metric_reporting_controller.h b/components/reporting/metrics/metric_reporting_controller.h
index b49ed7a..41614990 100644
--- a/components/reporting/metrics/metric_reporting_controller.h
+++ b/components/reporting/metrics/metric_reporting_controller.h
@@ -7,9 +7,9 @@
 
 #include <string>
 
-#include "base/callback_forward.h"
-#include "base/callback_helpers.h"
 #include "base/callback_list.h"
+#include "base/functional/callback_forward.h"
+#include "base/functional/callback_helpers.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
@@ -22,12 +22,9 @@
 // specified by the setting path.
 class MetricReportingController {
  public:
-  MetricReportingController(
-      ReportingSettings* reporting_settings,
-      const std::string& setting_path,
-      bool setting_enabled_default_value,
-      base::RepeatingClosure on_setting_enabled,
-      base::RepeatingClosure on_setting_disabled = base::DoNothing());
+  MetricReportingController(ReportingSettings* reporting_settings,
+                            const std::string& setting_path,
+                            bool setting_enabled_default_value);
 
   MetricReportingController(const MetricReportingController& other) = delete;
   MetricReportingController& operator=(const MetricReportingController& other) =
@@ -35,14 +32,22 @@
 
   ~MetricReportingController();
 
+  // When called, `on_setting_enabled` will run if the setting is enabled and
+  // nothing will run otherwise, then whenever the setting state changes, the
+  // corresponding callback will run.
+  void SetSettingUpdateCb(
+      base::RepeatingClosure on_setting_enabled,
+      base::RepeatingClosure on_setting_disabled = base::DoNothing());
+
  private:
   void UpdateSetting();
 
   const raw_ptr<ReportingSettings> reporting_settings_;
   const std::string setting_path_;
   const bool setting_enabled_default_value_;
-  const base::RepeatingClosure on_setting_enabled_;
-  const base::RepeatingClosure on_setting_disabled_;
+
+  base::RepeatingClosure on_setting_enabled_ = base::DoNothing();
+  base::RepeatingClosure on_setting_disabled_ = base::DoNothing();
 
   bool setting_enabled_ = false;
 
diff --git a/components/reporting/metrics/metric_reporting_controller_unittest.cc b/components/reporting/metrics/metric_reporting_controller_unittest.cc
index c5545ea..0710254 100644
--- a/components/reporting/metrics/metric_reporting_controller_unittest.cc
+++ b/components/reporting/metrics/metric_reporting_controller_unittest.cc
@@ -7,7 +7,6 @@
 #include <memory>
 #include <string>
 
-#include "base/callback_forward.h"
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
 #include "components/reporting/metrics/fakes/fake_reporting_settings.h"
@@ -41,8 +40,8 @@
 
 TEST_F(MetricReportingControllerTest, InvalidPath_DefaultDisabled) {
   MetricReportingController controller(settings_.get(), "invalid/path",
-                                       /*setting_enabled_default_value=*/false,
-                                       enable_cb_, disable_cb_);
+                                       /*setting_enabled_default_value=*/false);
+  controller.SetSettingUpdateCb(std::move(enable_cb_), std::move(disable_cb_));
 
   EXPECT_EQ(enable_count_, 0);
   EXPECT_EQ(disable_count_, 0);
@@ -50,8 +49,8 @@
 
 TEST_F(MetricReportingControllerTest, InvalidPath_DefaultEnabled) {
   MetricReportingController controller(settings_.get(), "invalid/path",
-                                       /*setting_enabled_default_value=*/true,
-                                       enable_cb_, disable_cb_);
+                                       /*setting_enabled_default_value=*/true);
+  controller.SetSettingUpdateCb(std::move(enable_cb_), std::move(disable_cb_));
 
   EXPECT_EQ(enable_count_, 1);
   EXPECT_EQ(disable_count_, 0);
@@ -62,8 +61,8 @@
   settings_->SetIsTrusted(false);
 
   MetricReportingController controller(settings_.get(), kSettingPath,
-                                       /*setting_enabled_default_value=*/false,
-                                       enable_cb_, disable_cb_);
+                                       /*setting_enabled_default_value=*/false);
+  controller.SetSettingUpdateCb(std::move(enable_cb_), std::move(disable_cb_));
 
   EXPECT_EQ(enable_count_, 0);
   EXPECT_EQ(disable_count_, 0);
@@ -78,8 +77,8 @@
   settings_->SetBoolean(kSettingPath, true);
 
   MetricReportingController controller(settings_.get(), kSettingPath,
-                                       /*setting_enabled_default_value=*/false,
-                                       enable_cb_, disable_cb_);
+                                       /*setting_enabled_default_value=*/false);
+  controller.SetSettingUpdateCb(std::move(enable_cb_), std::move(disable_cb_));
 
   // Only enable_cb_ is called.
   EXPECT_EQ(enable_count_, 1);
@@ -104,8 +103,8 @@
   settings_->SetBoolean(kSettingPath, false);
 
   MetricReportingController controller(settings_.get(), kSettingPath,
-                                       /*setting_enabled_default_value=*/false,
-                                       enable_cb_, disable_cb_);
+                                       /*setting_enabled_default_value=*/false);
+  controller.SetSettingUpdateCb(std::move(enable_cb_), std::move(disable_cb_));
 
   // No callbacks are called.
   EXPECT_EQ(enable_count_, 0);
@@ -126,5 +125,50 @@
   EXPECT_EQ(disable_count_, 1);
 }
 
+TEST_F(MetricReportingControllerTest, SetCallbackAfterEnable) {
+  settings_->SetBoolean(kSettingPath, false);
+
+  MetricReportingController controller(settings_.get(), kSettingPath,
+                                       /*setting_enabled_default_value=*/false);
+
+  // Change to enable.
+  settings_->SetBoolean(kSettingPath, true);
+
+  controller.SetSettingUpdateCb(std::move(enable_cb_), std::move(disable_cb_));
+
+  // Only enable_cb_ is called.
+  EXPECT_EQ(enable_count_, 1);
+  EXPECT_EQ(disable_count_, 0);
+
+  // Change to disable.
+  settings_->SetBoolean(kSettingPath, false);
+
+  // Only disable_cb_ is called.
+  EXPECT_EQ(enable_count_, 1);
+  EXPECT_EQ(disable_count_, 1);
+}
+
+TEST_F(MetricReportingControllerTest, SetCallbackAfterDisable) {
+  settings_->SetBoolean(kSettingPath, true);
+
+  MetricReportingController controller(settings_.get(), kSettingPath,
+                                       /*setting_enabled_default_value=*/false);
+
+  // Change to disable.
+  settings_->SetBoolean(kSettingPath, false);
+
+  controller.SetSettingUpdateCb(std::move(enable_cb_), std::move(disable_cb_));
+
+  // No callbacks are called.
+  EXPECT_EQ(enable_count_, 0);
+  EXPECT_EQ(disable_count_, 0);
+
+  // Change to enable.
+  settings_->SetBoolean(kSettingPath, true);
+
+  // Only enable_cb_ is called.
+  EXPECT_EQ(enable_count_, 1);
+  EXPECT_EQ(disable_count_, 0);
+}
 }  // namespace
 }  // namespace reporting
diff --git a/components/reporting/metrics/one_shot_collector.cc b/components/reporting/metrics/one_shot_collector.cc
index c0be1aa7..a1c0c8e 100644
--- a/components/reporting/metrics/one_shot_collector.cc
+++ b/components/reporting/metrics/one_shot_collector.cc
@@ -9,7 +9,9 @@
 
 #include "base/check.h"
 #include "base/functional/bind.h"
-#include "base/sequence_checker.h"
+#include "base/location.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/time/time.h"
 #include "components/reporting/client/report_queue.h"
 #include "components/reporting/metrics/collector_base.h"
 #include "components/reporting/metrics/metric_report_queue.h"
@@ -27,12 +29,37 @@
     const std::string& setting_path,
     bool setting_enabled_default_value,
     ReportQueue::EnqueueCallback on_data_reported)
+    : OneShotCollector(sampler,
+                       metric_report_queue,
+                       reporting_settings,
+                       setting_path,
+                       setting_enabled_default_value,
+                       /*init_delay=*/base::TimeDelta(),
+                       std::move(on_data_reported)) {}
+
+OneShotCollector::OneShotCollector(
+    Sampler* sampler,
+    MetricReportQueue* metric_report_queue,
+    ReportingSettings* reporting_settings,
+    const std::string& setting_path,
+    bool setting_enabled_default_value,
+    base::TimeDelta init_delay,
+    ReportQueue::EnqueueCallback on_data_reported)
     : CollectorBase(sampler),
       metric_report_queue_(metric_report_queue),
       on_data_reported_(std::move(on_data_reported)) {
   reporting_controller_ = std::make_unique<MetricReportingController>(
-      reporting_settings, setting_path, setting_enabled_default_value,
-      base::BindRepeating(&OneShotCollector::Collect, base::Unretained(this)));
+      reporting_settings, setting_path, setting_enabled_default_value);
+  if (init_delay.is_zero()) {
+    SetReportingControllerCb();
+    return;
+  }
+  CHECK(base::SequencedTaskRunner::HasCurrentDefault());
+  base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
+      FROM_HERE,
+      base::BindOnce(&OneShotCollector::SetReportingControllerCb,
+                     weak_ptr_factory_.GetWeakPtr()),
+      init_delay);
 }
 
 OneShotCollector::~OneShotCollector() = default;
@@ -60,4 +87,11 @@
   metric_report_queue_->Enqueue(std::move(metric_data.value()),
                                 std::move(on_data_reported_));
 }
+
+void OneShotCollector::SetReportingControllerCb() {
+  CheckOnSequence();
+
+  reporting_controller_->SetSettingUpdateCb(
+      base::BindRepeating(&OneShotCollector::Collect, base::Unretained(this)));
+}
 }  // namespace reporting
diff --git a/components/reporting/metrics/one_shot_collector.h b/components/reporting/metrics/one_shot_collector.h
index 7453da8a..ca2d4da 100644
--- a/components/reporting/metrics/one_shot_collector.h
+++ b/components/reporting/metrics/one_shot_collector.h
@@ -10,6 +10,9 @@
 
 #include "base/functional/callback_helpers.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "components/reporting/client/report_queue.h"
 #include "components/reporting/metrics/collector_base.h"
 #include "components/reporting/proto/synced/metric_data.pb.h"
@@ -25,6 +28,7 @@
 // setting is enabled.
 class OneShotCollector : public CollectorBase {
  public:
+  // Start observing the reporting setting immediately to start collection.
   OneShotCollector(
       Sampler* sampler,
       MetricReportQueue* metric_report_queue,
@@ -33,6 +37,17 @@
       bool setting_enabled_default_value,
       ReportQueue::EnqueueCallback on_data_reported = base::DoNothing());
 
+  // Start observing the reporting setting after `init_delay` to start
+  // collection.
+  OneShotCollector(
+      Sampler* sampler,
+      MetricReportQueue* metric_report_queue,
+      ReportingSettings* reporting_settings,
+      const std::string& setting_path,
+      bool setting_enabled_default_value,
+      base::TimeDelta init_delay,
+      ReportQueue::EnqueueCallback on_data_reported = base::DoNothing());
+
   OneShotCollector(const OneShotCollector& other) = delete;
   OneShotCollector& operator=(const OneShotCollector& other) = delete;
 
@@ -44,6 +59,8 @@
   void OnMetricDataCollected(absl::optional<MetricData> metric_data) override;
 
  private:
+  void SetReportingControllerCb();
+
   const raw_ptr<MetricReportQueue> metric_report_queue_;
 
   std::unique_ptr<MetricReportingController> reporting_controller_;
@@ -51,6 +68,8 @@
   ReportQueue::EnqueueCallback on_data_reported_;
 
   bool data_collected_ = false;
+
+  base::WeakPtrFactory<OneShotCollector> weak_ptr_factory_{this};
 };
 }  // namespace reporting
 
diff --git a/components/reporting/metrics/one_shot_collector_unittest.cc b/components/reporting/metrics/one_shot_collector_unittest.cc
index 9b2fba1..f906d1b 100644
--- a/components/reporting/metrics/one_shot_collector_unittest.cc
+++ b/components/reporting/metrics/one_shot_collector_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_future.h"
+#include "base/time/time.h"
 #include "components/reporting/metrics/fakes/fake_metric_report_queue.h"
 #include "components/reporting/metrics/fakes/fake_reporting_settings.h"
 #include "components/reporting/metrics/fakes/fake_sampler.h"
@@ -20,6 +21,8 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using ::testing::Eq;
+
 namespace reporting {
 namespace {
 
@@ -55,14 +58,55 @@
                              test_future.GetCallback());
 
   // Setting is initially enabled, data is being collected.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 1);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(1));
 
   settings_->SetBoolean(kEnableSettingPath, false);
   settings_->SetBoolean(kEnableSettingPath, true);
 
   // No more data should be collected even if the setting was disabled then
   // re-enabled.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 1);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(1));
+  EXPECT_TRUE(test_future.Wait());
+
+  MetricData metric_data_reported =
+      metric_report_queue_->GetMetricDataReported();
+
+  EXPECT_TRUE(metric_data_reported.has_timestamp_ms());
+  EXPECT_TRUE(metric_data_reported.has_info_data());
+  EXPECT_TRUE(metric_report_queue_->IsEmpty());
+}
+
+TEST_F(OneShotCollectorTest, InitiallyEnabled_Delayed) {
+  constexpr base::TimeDelta init_delay = base::Minutes(2);
+  settings_->SetBoolean(kEnableSettingPath, true);
+
+  MetricData metric_data;
+  metric_data.mutable_info_data();
+  sampler_->SetMetricData(std::move(metric_data));
+  base::test::TestFuture<Status> test_future;
+
+  OneShotCollector collector(sampler_.get(), metric_report_queue_.get(),
+                             settings_.get(), kEnableSettingPath,
+                             /*setting_enabled_default_value=*/false,
+                             init_delay, test_future.GetCallback());
+
+  base::TimeDelta elapsed = base::Seconds(90);
+  task_environment_.FastForwardBy(elapsed);
+
+  // `init_delay` is not elapsed yet.
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(0));
+
+  task_environment_.FastForwardBy(init_delay - elapsed);
+
+  // Setting is initially enabled, data is being collected.
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(1));
+
+  settings_->SetBoolean(kEnableSettingPath, false);
+  settings_->SetBoolean(kEnableSettingPath, true);
+
+  // No more data should be collected even if the setting was disabled then
+  // re-enabled.
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(1));
   EXPECT_TRUE(test_future.Wait());
 
   MetricData metric_data_reported =
@@ -83,7 +127,7 @@
                              /*setting_enabled_default_value=*/false);
 
   // Setting is initially enabled, data is being collected.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 1);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(1));
 
   base::RunLoop().RunUntilIdle();
 
@@ -102,19 +146,57 @@
                              /*setting_enabled_default_value=*/false);
 
   // Setting is initially disabled, no data is collected.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 0);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(0));
 
   settings_->SetBoolean(kEnableSettingPath, true);
 
   // Setting is enabled, data is being collected.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 1);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(1));
 
   settings_->SetBoolean(kEnableSettingPath, false);
   settings_->SetBoolean(kEnableSettingPath, true);
 
   // No more data should be collected even if the setting was disabled then
   // re-enabled.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 1);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(1));
+
+  MetricData metric_data_reported =
+      metric_report_queue_->GetMetricDataReported();
+
+  EXPECT_TRUE(metric_data_reported.has_timestamp_ms());
+  EXPECT_TRUE(metric_data_reported.has_info_data());
+  EXPECT_TRUE(metric_report_queue_->IsEmpty());
+}
+
+TEST_F(OneShotCollectorTest, InitiallyDisabled_Delayed) {
+  constexpr base::TimeDelta init_delay = base::Minutes(1);
+  settings_->SetBoolean(kEnableSettingPath, false);
+
+  MetricData metric_data;
+  metric_data.mutable_info_data();
+  sampler_->SetMetricData(std::move(metric_data));
+
+  OneShotCollector collector(sampler_.get(), metric_report_queue_.get(),
+                             settings_.get(), kEnableSettingPath,
+                             /*setting_enabled_default_value=*/false,
+                             init_delay);
+
+  task_environment_.FastForwardBy(init_delay);
+
+  // Setting is initially disabled, no data is collected.
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(0));
+
+  settings_->SetBoolean(kEnableSettingPath, true);
+
+  // Setting is enabled, data is being collected.
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(1));
+
+  settings_->SetBoolean(kEnableSettingPath, false);
+  settings_->SetBoolean(kEnableSettingPath, true);
+
+  // No more data should be collected even if the setting was disabled then
+  // re-enabled.
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(1));
 
   MetricData metric_data_reported =
       metric_report_queue_->GetMetricDataReported();
@@ -136,7 +218,7 @@
                              test_future.GetCallback());
 
   // Setting is enabled by default, data is being collected.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 1);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(1));
   EXPECT_TRUE(test_future.Wait());
 
   const auto& metric_data_reported =
@@ -158,7 +240,7 @@
   base::RunLoop().RunUntilIdle();
 
   // Setting is disabled by default, no data is collected.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 0);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(0));
   EXPECT_TRUE(metric_report_queue_->IsEmpty());
 }
 }  // namespace
diff --git a/components/reporting/metrics/periodic_collector.cc b/components/reporting/metrics/periodic_collector.cc
index 041d5d4..9bda6c5 100644
--- a/components/reporting/metrics/periodic_collector.cc
+++ b/components/reporting/metrics/periodic_collector.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/functional/bind.h"
+#include "base/location.h"
 #include "base/sequence_checker.h"
 #include "base/time/time.h"
 #include "components/reporting/client/report_queue.h"
@@ -28,7 +29,8 @@
                                      bool setting_enabled_default_value,
                                      const std::string& rate_setting_path,
                                      base::TimeDelta default_rate,
-                                     int rate_unit_to_ms)
+                                     int rate_unit_to_ms,
+                                     base::TimeDelta init_delay)
     : CollectorBase(sampler),
       metric_report_queue_(metric_report_queue),
       rate_controller_(std::make_unique<MetricRateController>(
@@ -41,11 +43,36 @@
       reporting_controller_(std::make_unique<MetricReportingController>(
           reporting_settings,
           enable_setting_path,
-          setting_enabled_default_value,
-          base::BindRepeating(&PeriodicCollector::StartPeriodicCollection,
-                              base::Unretained(this)),
-          base::BindRepeating(&PeriodicCollector::StopPeriodicCollection,
-                              base::Unretained(this)))) {}
+          setting_enabled_default_value)) {
+  if (init_delay.is_zero()) {
+    SetReportingControllerCb();
+    return;
+  }
+  CHECK(base::SequencedTaskRunner::HasCurrentDefault());
+  base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
+      FROM_HERE,
+      base::BindOnce(&PeriodicCollector::SetReportingControllerCb,
+                     weak_ptr_factory_.GetWeakPtr()),
+      init_delay);
+}
+
+PeriodicCollector::PeriodicCollector(Sampler* sampler,
+                                     MetricReportQueue* metric_report_queue,
+                                     ReportingSettings* reporting_settings,
+                                     const std::string& enable_setting_path,
+                                     bool setting_enabled_default_value,
+                                     const std::string& rate_setting_path,
+                                     base::TimeDelta default_rate,
+                                     int rate_unit_to_ms)
+    : PeriodicCollector(sampler,
+                        metric_report_queue,
+                        reporting_settings,
+                        enable_setting_path,
+                        setting_enabled_default_value,
+                        rate_setting_path,
+                        default_rate,
+                        rate_unit_to_ms,
+                        base::TimeDelta()) {}
 
 PeriodicCollector::~PeriodicCollector() = default;
 
@@ -71,4 +98,12 @@
   CheckOnSequence();
   rate_controller_->Stop();
 }
+
+void PeriodicCollector::SetReportingControllerCb() {
+  reporting_controller_->SetSettingUpdateCb(
+      base::BindRepeating(&PeriodicCollector::StartPeriodicCollection,
+                          base::Unretained(this)),
+      base::BindRepeating(&PeriodicCollector::StopPeriodicCollection,
+                          base::Unretained(this)));
+}
 }  // namespace reporting
diff --git a/components/reporting/metrics/periodic_collector.h b/components/reporting/metrics/periodic_collector.h
index b449e2f..d6931d7 100644
--- a/components/reporting/metrics/periodic_collector.h
+++ b/components/reporting/metrics/periodic_collector.h
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/memory/raw_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "components/reporting/metrics/collector_base.h"
 #include "components/reporting/proto/synced/metric_data.pb.h"
@@ -26,6 +27,18 @@
 // is enabled.
 class PeriodicCollector : public CollectorBase {
  public:
+  // Start periodic collection after `init_delay`.
+  PeriodicCollector(Sampler* sampler,
+                    MetricReportQueue* metric_report_queue,
+                    ReportingSettings* reporting_settings,
+                    const std::string& enable_setting_path,
+                    bool setting_enabled_default_value,
+                    const std::string& rate_setting_path,
+                    base::TimeDelta default_rate,
+                    int rate_unit_to_ms,
+                    base::TimeDelta init_delay);
+
+  // Start periodic collection immediately.
   PeriodicCollector(Sampler* sampler,
                     MetricReportQueue* metric_report_queue,
                     ReportingSettings* reporting_settings,
@@ -44,17 +57,21 @@
   void OnMetricDataCollected(absl::optional<MetricData> metric_data) override;
 
  private:
-  virtual void StartPeriodicCollection();
+  void StartPeriodicCollection();
 
-  virtual void StopPeriodicCollection();
+  void StopPeriodicCollection();
+
+  void SetReportingControllerCb();
 
   const raw_ptr<MetricReportQueue> metric_report_queue_;
 
-  // `rate_controller_` should be initialized before `reporting_controller_` as
-  // initializing `reporting_controller` will trigger `rate_controller_` call if
-  // the setting is enabled.
+  // `rate_controller_` should be initialized before the setting update
+  // callbacks of `reporting_controller_` are set, as `reporting_controller`
+  // will trigger `rate_controller_` call if the setting is enabled.
   const std::unique_ptr<MetricRateController> rate_controller_;
   const std::unique_ptr<MetricReportingController> reporting_controller_;
+
+  base::WeakPtrFactory<PeriodicCollector> weak_ptr_factory_{this};
 };
 }  // namespace reporting
 
diff --git a/components/reporting/metrics/periodic_collector_unittest.cc b/components/reporting/metrics/periodic_collector_unittest.cc
index 25ee90f..7923889 100644
--- a/components/reporting/metrics/periodic_collector_unittest.cc
+++ b/components/reporting/metrics/periodic_collector_unittest.cc
@@ -20,12 +20,16 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
+using ::testing::Eq;
+
 namespace reporting {
 namespace {
 
 constexpr char kEnableSettingPath[] = "enable_path";
 constexpr char kRateSettingPath[] = "rate_path";
 
+constexpr base::TimeDelta interval = base::Milliseconds(10000);
+
 class PeriodicCollectorTest : public ::testing::Test {
  protected:
   void SetUp() override {
@@ -43,9 +47,8 @@
 };
 
 TEST_F(PeriodicCollectorTest, InitiallyEnabled) {
-  constexpr int interval = 10000;
   settings_->SetBoolean(kEnableSettingPath, true);
-  settings_->SetInteger(kRateSettingPath, interval);
+  settings_->SetInteger(kRateSettingPath, interval.InMilliseconds());
 
   MetricData metric_data_list[5];
   metric_data_list[0].mutable_telemetry_data();
@@ -57,108 +60,146 @@
   metric_data_list[4].mutable_event_data();
 
   sampler_->SetMetricData(metric_data_list[0]);
-  PeriodicCollector collector(
-      sampler_.get(), metric_report_queue_.get(), settings_.get(),
-      kEnableSettingPath, /*setting_enabled_default_value=*/false,
-      kRateSettingPath, base::Milliseconds(interval / 2));
+  PeriodicCollector collector(sampler_.get(), metric_report_queue_.get(),
+                              settings_.get(), kEnableSettingPath,
+                              /*setting_enabled_default_value=*/false,
+                              kRateSettingPath, interval / 2);
 
   // One initial collection at startup.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 1);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(1));
 
   // Expected calls count initialized to 1 to reflect the initial collection.
   int expected_collect_calls = 1;
   for (int i = 0; i < 2; ++i) {
     sampler_->SetMetricData(metric_data_list[i + 1]);
     // 5 secs elapsed, no new data collected.
-    task_environment_.FastForwardBy(base::Milliseconds(interval / 2));
-    EXPECT_EQ(sampler_->GetNumCollectCalls(), expected_collect_calls);
+    task_environment_.FastForwardBy(interval / 2);
+    EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(expected_collect_calls));
 
     ++expected_collect_calls;
     // 10 secs elapsed, data should be collected.
-    task_environment_.FastForwardBy(base::Milliseconds(interval / 2));
-    EXPECT_EQ(sampler_->GetNumCollectCalls(), expected_collect_calls);
+    task_environment_.FastForwardBy(interval / 2);
+    EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(expected_collect_calls));
     ;
   }
 
   sampler_->SetMetricData(metric_data_list[3]);
   settings_->SetBoolean(kEnableSettingPath, false);
   // Setting disabled, no data should be collected.
-  task_environment_.FastForwardBy(base::Milliseconds(interval));
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), expected_collect_calls);
+  task_environment_.FastForwardBy(interval);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(expected_collect_calls));
 
   settings_->SetBoolean(kEnableSettingPath, true);
   // Initial collection at policy enablement.
   ++expected_collect_calls;
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), expected_collect_calls);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(expected_collect_calls));
 
   sampler_->SetMetricData(metric_data_list[4]);
   // Setting enabled, data should be collected after interval.
-  task_environment_.FastForwardBy(base::Milliseconds(interval / 2));
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), expected_collect_calls);
+  task_environment_.FastForwardBy(interval / 2);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(expected_collect_calls));
   ++expected_collect_calls;
-  task_environment_.FastForwardBy(base::Milliseconds(interval / 2));
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), expected_collect_calls);
+  task_environment_.FastForwardBy(interval / 2);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(expected_collect_calls));
 
   for (const auto& metric_data : metric_data_list) {
     MetricData metric_data_reported =
         metric_report_queue_->GetMetricDataReported();
     EXPECT_TRUE(metric_data_reported.has_timestamp_ms());
-    EXPECT_EQ(metric_data_reported.has_telemetry_data(),
-              metric_data.has_telemetry_data());
-    EXPECT_EQ(metric_data_reported.has_info_data(),
-              metric_data.has_info_data());
-    EXPECT_EQ(metric_data_reported.has_event_data(),
-              metric_data.has_event_data());
+    EXPECT_THAT(metric_data_reported.has_telemetry_data(),
+                Eq(metric_data.has_telemetry_data()));
+    EXPECT_THAT(metric_data_reported.has_info_data(),
+                Eq(metric_data.has_info_data()));
+    EXPECT_THAT(metric_data_reported.has_event_data(),
+                Eq(metric_data.has_event_data()));
   }
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(metric_report_queue_->IsEmpty());
 }
 
-TEST_F(PeriodicCollectorTest, NoMetricData) {
-  constexpr int interval = 10000;
+TEST_F(PeriodicCollectorTest, InitiallyEnabled_Delayed) {
+  constexpr base::TimeDelta init_delay = base::Minutes(1);
+
   settings_->SetBoolean(kEnableSettingPath, true);
-  settings_->SetInteger(kRateSettingPath, interval);
+  settings_->SetInteger(kRateSettingPath, interval.InMilliseconds());
+
+  MetricData metric_data;
+  metric_data.mutable_telemetry_data();
+
+  sampler_->SetMetricData(metric_data);
+  PeriodicCollector collector(sampler_.get(), metric_report_queue_.get(),
+                              settings_.get(), kEnableSettingPath,
+                              /*setting_enabled_default_value=*/false,
+                              kRateSettingPath, interval / 2,
+                              /*rate_unit_to_ms=*/1, init_delay);
+
+  // No collection since the init delay is not elapsed.
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(0));
+
+  task_environment_.FastForwardBy(interval);
+
+  // Only interval is elapsed which is less than init delay so still no
+  // collection.
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(0));
+
+  task_environment_.FastForwardBy(init_delay - interval);
+
+  // One initial collection when the init delay is elapsed.
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(1));
+
+  MetricData metric_data_reported =
+      metric_report_queue_->GetMetricDataReported();
+  EXPECT_TRUE(metric_data_reported.has_timestamp_ms());
+  EXPECT_TRUE(metric_data_reported.has_telemetry_data());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(metric_report_queue_->IsEmpty());
+
+  sampler_->SetMetricData(absl::nullopt);
+}
+
+TEST_F(PeriodicCollectorTest, NoMetricData) {
+  settings_->SetBoolean(kEnableSettingPath, true);
+  settings_->SetInteger(kRateSettingPath, interval.InMilliseconds());
 
   sampler_->SetMetricData(absl::nullopt);
 
-  PeriodicCollector collector(
-      sampler_.get(), metric_report_queue_.get(), settings_.get(),
-      kEnableSettingPath, /*setting_enabled_default_value=*/false,
-      kRateSettingPath, base::Milliseconds(interval / 2));
+  PeriodicCollector collector(sampler_.get(), metric_report_queue_.get(),
+                              settings_.get(), kEnableSettingPath,
+                              /*setting_enabled_default_value=*/false,
+                              kRateSettingPath, interval / 2);
 
   // One initial collection at startup.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 1);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(1));
 
   base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(metric_report_queue_->IsEmpty());
 }
 
 TEST_F(PeriodicCollectorTest, InitiallyDisabled) {
-  constexpr int interval = 10000;
   settings_->SetBoolean(kEnableSettingPath, false);
-  settings_->SetInteger(kRateSettingPath, interval);
+  settings_->SetInteger(kRateSettingPath, interval.InMilliseconds());
 
   MetricData metric_data;
   metric_data.mutable_telemetry_data();
 
   sampler_->SetMetricData(std::move(metric_data));
 
-  PeriodicCollector collector(
-      sampler_.get(), metric_report_queue_.get(), settings_.get(),
-      kEnableSettingPath, /*setting_enabled_default_value=*/false,
-      kRateSettingPath, base::Milliseconds(interval / 2));
+  PeriodicCollector collector(sampler_.get(), metric_report_queue_.get(),
+                              settings_.get(), kEnableSettingPath,
+                              /*setting_enabled_default_value=*/false,
+                              kRateSettingPath, interval / 2);
 
-  task_environment_.FastForwardBy(base::Milliseconds(interval));
+  task_environment_.FastForwardBy(interval);
   // Setting is disabled, no data collected.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 0);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(0));
 
   settings_->SetBoolean(kEnableSettingPath, true);
   // One initial collection at policy enablement.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 1);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(1));
 
-  task_environment_.FastForwardBy(base::Milliseconds(interval));
+  task_environment_.FastForwardBy(interval);
   // 1 collection at policy enablement + 1 collection after interval.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 2);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(2));
 
   MetricData metric_data_reported =
       metric_report_queue_->GetMetricDataReported();
@@ -173,28 +214,27 @@
 }
 
 TEST_F(PeriodicCollectorTest, DefaultEnabled) {
-  constexpr int interval = 10000;
-  settings_->SetInteger(kRateSettingPath, interval);
+  settings_->SetInteger(kRateSettingPath, interval.InMilliseconds());
 
   MetricData metric_data;
   metric_data.mutable_telemetry_data();
 
   sampler_->SetMetricData(std::move(metric_data));
-  PeriodicCollector collector(
-      sampler_.get(), metric_report_queue_.get(), settings_.get(),
-      "invalid/path", /*setting_enabled_default_value=*/true, kRateSettingPath,
-      base::Milliseconds(interval / 2));
+  PeriodicCollector collector(sampler_.get(), metric_report_queue_.get(),
+                              settings_.get(), "invalid/path",
+                              /*setting_enabled_default_value=*/true,
+                              kRateSettingPath, interval / 2);
 
   // One initial collection at startup.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 1);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(1));
 
   metric_data.Clear();
   metric_data.mutable_event_data();
   sampler_->SetMetricData(std::move(metric_data));
   // 10 secs elapsed, data should be collected.
-  task_environment_.FastForwardBy(base::Milliseconds(interval));
+  task_environment_.FastForwardBy(interval);
   // 1 collection at startup + 1 collection after interval.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 2);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(2));
 
   MetricData metric_data_reported =
       metric_report_queue_->GetMetricDataReported();
@@ -210,23 +250,22 @@
 }
 
 TEST_F(PeriodicCollectorTest, DefaultDisabled) {
-  constexpr int interval = 10000;
-  settings_->SetInteger(kRateSettingPath, interval);
+  settings_->SetInteger(kRateSettingPath, interval.InMilliseconds());
 
   MetricData metric_data;
   metric_data.mutable_telemetry_data();
 
-  PeriodicCollector collector(
-      sampler_.get(), metric_report_queue_.get(), settings_.get(),
-      "invalid/path", /*setting_enabled_default_value=*/false, kRateSettingPath,
-      base::Milliseconds(interval / 2));
+  PeriodicCollector collector(sampler_.get(), metric_report_queue_.get(),
+                              settings_.get(), "invalid/path",
+                              /*setting_enabled_default_value=*/false,
+                              kRateSettingPath, interval / 2);
 
   sampler_->SetMetricData(std::move(metric_data));
-  task_environment_.FastForwardBy(base::Milliseconds(interval));
+  task_environment_.FastForwardBy(interval);
   base::RunLoop().RunUntilIdle();
 
   // Setting is disabled by default, no data collected.
-  EXPECT_EQ(sampler_->GetNumCollectCalls(), 0);
+  EXPECT_THAT(sampler_->GetNumCollectCalls(), Eq(0));
   EXPECT_TRUE(metric_report_queue_->IsEmpty());
 }
 }  // namespace
diff --git a/components/reporting/storage/storage_queue.h b/components/reporting/storage/storage_queue.h
index 16e199f..18b28913 100644
--- a/components/reporting/storage/storage_queue.h
+++ b/components/reporting/storage/storage_queue.h
@@ -25,7 +25,6 @@
 #include "base/strings/string_piece.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "base/timer/timer.h"
 #include "components/reporting/compression/compression_module.h"
 #include "components/reporting/encryption/encryption_module_interface.h"
diff --git a/components/reporting/util/refcounted_closure_list.cc b/components/reporting/util/refcounted_closure_list.cc
index a679e4f2..3c35d2d5 100644
--- a/components/reporting/util/refcounted_closure_list.cc
+++ b/components/reporting/util/refcounted_closure_list.cc
@@ -13,7 +13,6 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
 
 namespace reporting {
 
diff --git a/components/reporting/util/refcounted_closure_list_unittest.cc b/components/reporting/util/refcounted_closure_list_unittest.cc
index 419b1da..c6113f8b 100644
--- a/components/reporting/util/refcounted_closure_list_unittest.cc
+++ b/components/reporting/util/refcounted_closure_list_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/thread_pool.h"
 #include "base/test/task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "base/time/time.h"
 #include "components/reporting/util/refcounted_closure_list.h"
 #include "components/reporting/util/test_support_callbacks.h"
diff --git a/components/reporting/util/test_support_callbacks.h b/components/reporting/util/test_support_callbacks.h
index 0b65ac67..5e7929b 100644
--- a/components/reporting/util/test_support_callbacks.h
+++ b/components/reporting/util/test_support_callbacks.h
@@ -43,7 +43,7 @@
   TestMultiEvent(const TestMultiEvent& other) = delete;
   TestMultiEvent& operator=(const TestMultiEvent& other) = delete;
 
-  using TupleType = std::tuple<ResType...>;
+  using TupleType = std::tuple<std::remove_reference_t<ResType>...>;
 
   [[nodiscard]] const TupleType& ref_result() {
     static_assert(
@@ -53,7 +53,6 @@
     return result_.value();
   }
 
-  template <typename T = TupleType>
   [[nodiscard]] TupleType result() {
     static_assert(
         IsMovable<TupleType>(),
diff --git a/components/resources/version_ui_scaled_resources.grdp b/components/resources/version_ui_scaled_resources.grdp
index 4cd808e..8cf9c9b 100644
--- a/components/resources/version_ui_scaled_resources.grdp
+++ b/components/resources/version_ui_scaled_resources.grdp
@@ -1,15 +1,15 @@
 <?xml version="1.0" encoding="utf-8"?>
 <grit-part>
-  <if expr="_google_chrome_for_testing">
+  <if expr="_google_chrome">
     <then>
-      <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO" file="google_chrome/google_chrome_for_testing/product_logo.png" />
-      <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_WHITE" file="google_chrome/google_chrome_for_testing/product_logo_white.png" />
+      <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO" file="google_chrome/product_logo.png" />
+      <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_WHITE" file="google_chrome/product_logo_white.png" />
     </then>
     <else>
-      <if expr="_google_chrome">
+      <if expr="_google_chrome_for_testing and _use_internal_chrome_for_testing_icons">
         <then>
-          <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO" file="google_chrome/product_logo.png" />
-          <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_WHITE" file="google_chrome/product_logo_white.png" />
+          <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO" file="google_chrome/google_chrome_for_testing/product_logo.png" />
+          <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_WHITE" file="google_chrome/google_chrome_for_testing/product_logo_white.png" />
         </then>
         <else>
           <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO" file="chromium/product_logo.png" />
@@ -18,4 +18,4 @@
       </if>
     </else>
   </if>
-</grit-part>
+</grit-part>
\ No newline at end of file
diff --git a/components/safe_browsing/core/browser/db/v4_store_fuzzer.cc b/components/safe_browsing/core/browser/db/v4_store_fuzzer.cc
index e119c1c8..7bdff3d 100644
--- a/components/safe_browsing/core/browser/db/v4_store_fuzzer.cc
+++ b/components/safe_browsing/core/browser/db/v4_store_fuzzer.cc
@@ -51,7 +51,7 @@
     store->MergeUpdate(prefix_map_old, prefix_map_additions, &raw_removals,
                        empty_checksum);
 #ifndef NDEBUG
-    DisplayHashPrefixMapDetails(store->hash_prefix_map_);
+    DisplayHashPrefixMapDetails(*store->hash_prefix_map_);
 #endif
 
     return 0;
diff --git a/components/services/app_service/public/cpp/features.cc b/components/services/app_service/public/cpp/features.cc
index 19f22bb..2ded2dd3 100644
--- a/components/services/app_service/public/cpp/features.cc
+++ b/components/services/app_service/public/cpp/features.cc
@@ -6,10 +6,6 @@
 
 namespace apps {
 
-BASE_FEATURE(kAppServiceLaunchWithoutMojom,
-             "AppServiceLaunchWithoutMojom",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 BASE_FEATURE(kAppServiceWithoutMojom,
              "AppServiceWithoutMojom",
              base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/components/services/app_service/public/cpp/features.h b/components/services/app_service/public/cpp/features.h
index 5b128a80c..b6326a3 100644
--- a/components/services/app_service/public/cpp/features.h
+++ b/components/services/app_service/public/cpp/features.h
@@ -10,7 +10,6 @@
 
 namespace apps {
 
-COMPONENT_EXPORT(APP_TYPES) BASE_DECLARE_FEATURE(kAppServiceLaunchWithoutMojom);
 COMPONENT_EXPORT(APP_TYPES) BASE_DECLARE_FEATURE(kAppServiceWithoutMojom);
 COMPONENT_EXPORT(APP_TYPES)
 BASE_DECLARE_FEATURE(kAppServiceGetMenuWithoutMojom);
diff --git a/components/services/app_service/public/cpp/preferred_app.cc b/components/services/app_service/public/cpp/preferred_app.cc
index bb0df60..f81eca2 100644
--- a/components/services/app_service/public/cpp/preferred_app.cc
+++ b/components/services/app_service/public/cpp/preferred_app.cc
@@ -71,50 +71,4 @@
   return true;
 }
 
-PreferredAppPtr ConvertMojomPreferredAppToPreferredApp(
-    const apps::mojom::PreferredAppPtr& mojom_preferred_app) {
-  if (!mojom_preferred_app) {
-    return nullptr;
-  }
-
-  PreferredAppPtr preferred_app =
-      std::make_unique<PreferredApp>(ConvertMojomIntentFilterToIntentFilter(
-                                         mojom_preferred_app->intent_filter),
-                                     mojom_preferred_app->app_id);
-  return preferred_app;
-}
-
-apps::mojom::PreferredAppPtr ConvertPreferredAppToMojomPreferredApp(
-    const PreferredAppPtr& preferred_app) {
-  auto mojom_preferred_app = apps::mojom::PreferredApp::New();
-  if (!preferred_app) {
-    return mojom_preferred_app;
-  }
-
-  mojom_preferred_app->intent_filter =
-      ConvertIntentFilterToMojomIntentFilter(preferred_app->intent_filter);
-  mojom_preferred_app->app_id = preferred_app->app_id;
-  return mojom_preferred_app;
-}
-
-PreferredApps ConvertMojomPreferredAppsToPreferredApps(
-    const std::vector<apps::mojom::PreferredAppPtr>& mojom_preferred_apps) {
-  PreferredApps ret;
-  ret.reserve(mojom_preferred_apps.size());
-  for (const auto& mojom_preferred_app : mojom_preferred_apps) {
-    ret.push_back(ConvertMojomPreferredAppToPreferredApp(mojom_preferred_app));
-  }
-  return ret;
-}
-
-std::vector<apps::mojom::PreferredAppPtr>
-ConvertPreferredAppsToMojomPreferredApps(const PreferredApps& preferred_apps) {
-  std::vector<apps::mojom::PreferredAppPtr> ret;
-  ret.reserve(preferred_apps.size());
-  for (const auto& preferred_app : preferred_apps) {
-    ret.push_back(ConvertPreferredAppToMojomPreferredApp(preferred_app));
-  }
-  return ret;
-}
-
 }  // namespace apps
diff --git a/components/services/app_service/public/cpp/preferred_app.h b/components/services/app_service/public/cpp/preferred_app.h
index 4156407..6fa0840 100644
--- a/components/services/app_service/public/cpp/preferred_app.h
+++ b/components/services/app_service/public/cpp/preferred_app.h
@@ -56,20 +56,6 @@
 
 bool IsEqual(const PreferredApps& source, const PreferredApps& target);
 
-// TODO(crbug.com/1253250): Remove these functions after migrating to non-mojo
-// AppService.
-PreferredAppPtr ConvertMojomPreferredAppToPreferredApp(
-    const apps::mojom::PreferredAppPtr& mojom_preferred_app);
-
-apps::mojom::PreferredAppPtr ConvertPreferredAppToMojomPreferredApp(
-    const PreferredAppPtr& preferred_app);
-
-PreferredApps ConvertMojomPreferredAppsToPreferredApps(
-    const std::vector<apps::mojom::PreferredAppPtr>& mojom_preferred_apps);
-
-std::vector<apps::mojom::PreferredAppPtr>
-ConvertPreferredAppsToMojomPreferredApps(const PreferredApps& preferred_apps);
-
 }  // namespace apps
 
 #endif  // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_PREFERRED_APP_H_
diff --git a/components/services/app_service/public/mojom/types.mojom b/components/services/app_service/public/mojom/types.mojom
index 09cb8ac..95233b4f 100644
--- a/components/services/app_service/public/mojom/types.mojom
+++ b/components/services/app_service/public/mojom/types.mojom
@@ -408,12 +408,6 @@
   string? activity_label;
 };
 
-// The preferred app represents by |app_id| for |intent_fitler|.
-struct PreferredApp {
-  IntentFilter intent_filter;
-  string app_id;
-};
-
 struct FilePaths {
   array<mojo_base.mojom.FilePath> file_paths;
 };
diff --git a/components/strictmode/android/java/src/org/chromium/components/strictmode/ReflectiveThreadStrictModeInterceptor.java b/components/strictmode/android/java/src/org/chromium/components/strictmode/ReflectiveThreadStrictModeInterceptor.java
index d66a89a..bd5472a 100644
--- a/components/strictmode/android/java/src/org/chromium/components/strictmode/ReflectiveThreadStrictModeInterceptor.java
+++ b/components/strictmode/android/java/src/org/chromium/components/strictmode/ReflectiveThreadStrictModeInterceptor.java
@@ -16,7 +16,6 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 
-import org.chromium.base.Function;
 import org.chromium.base.Log;
 
 import java.lang.reflect.Field;
@@ -25,6 +24,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.function.Consumer;
+import java.util.function.Function;
 
 /**
  * StrictMode whitelist installer.
diff --git a/components/strictmode/android/java/src/org/chromium/components/strictmode/ThreadStrictModeInterceptor.java b/components/strictmode/android/java/src/org/chromium/components/strictmode/ThreadStrictModeInterceptor.java
index 8426e9e..67c59eb 100644
--- a/components/strictmode/android/java/src/org/chromium/components/strictmode/ThreadStrictModeInterceptor.java
+++ b/components/strictmode/android/java/src/org/chromium/components/strictmode/ThreadStrictModeInterceptor.java
@@ -10,11 +10,10 @@
 
 import androidx.annotation.Nullable;
 
-import org.chromium.base.Function;
-
 import java.util.ArrayList;
 import java.util.List;
 import java.util.function.Consumer;
+import java.util.function.Function;
 
 /** Installs a whitelist configuration for StrictMode's ThreadPolicy feature. */
 public interface ThreadStrictModeInterceptor {
diff --git a/components/strictmode/android/java/src/org/chromium/components/strictmode/Violation.java b/components/strictmode/android/java/src/org/chromium/components/strictmode/Violation.java
index 2b90397e..7ef978f 100644
--- a/components/strictmode/android/java/src/org/chromium/components/strictmode/Violation.java
+++ b/components/strictmode/android/java/src/org/chromium/components/strictmode/Violation.java
@@ -4,9 +4,8 @@
 
 package org.chromium.components.strictmode;
 
-import org.chromium.base.Function;
-
 import java.util.List;
+import java.util.function.Function;
 
 /** Violation that occurred. */
 public class Violation {
diff --git a/components/sync/driver/sync_service.h b/components/sync/driver/sync_service.h
index e28803e..267daf2e 100644
--- a/components/sync/driver/sync_service.h
+++ b/components/sync/driver/sync_service.h
@@ -43,6 +43,10 @@
 
   ~SyncSetupInProgressHandle();
 
+  SyncSetupInProgressHandle(const SyncSetupInProgressHandle&) = delete;
+  SyncSetupInProgressHandle& operator=(const SyncSetupInProgressHandle&) =
+      delete;
+
  private:
   base::OnceClosure on_destroy_;
 };
diff --git a/components/url_formatter/android/javatests/src/org/chromium/components/url_formatter/UrlFormatterUnitTest.java b/components/url_formatter/android/javatests/src/org/chromium/components/url_formatter/UrlFormatterUnitTest.java
index b89ce4017..3830507 100644
--- a/components/url_formatter/android/javatests/src/org/chromium/components/url_formatter/UrlFormatterUnitTest.java
+++ b/components/url_formatter/android/javatests/src/org/chromium/components/url_formatter/UrlFormatterUnitTest.java
@@ -13,13 +13,14 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import org.chromium.base.Function;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.util.Batch;
 import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
 import org.chromium.url.GURL;
 import org.chromium.url.GURLJavaTestHelper;
 
+import java.util.function.Function;
+
 /**
  * Unit tests for {@link UrlFormatter}.
  *
diff --git a/components/webapps/browser/banners/app_banner_manager.cc b/components/webapps/browser/banners/app_banner_manager.cc
index 7c42245..01657d94e 100644
--- a/components/webapps/browser/banners/app_banner_manager.cc
+++ b/components/webapps/browser/banners/app_banner_manager.cc
@@ -549,6 +549,7 @@
   validated_url_ = GURL();
   UpdateState(State::INACTIVE);
   SetInstallableWebAppCheckResult(InstallableWebAppCheckResult::kUnknown);
+  passed_worker_check_ = false;
   install_path_tracker_.Reset();
   screenshots_.clear();
 }
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 4504428..f82737e 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1449,6 +1449,8 @@
     "preloading/prefetch/prefetched_mainframe_response_container.h",
     "preloading/prefetch/proxy_lookup_client_impl.cc",
     "preloading/prefetch/proxy_lookup_client_impl.h",
+    "preloading/prefetcher.cc",
+    "preloading/prefetcher.h",
     "preloading/preloading.cc",
     "preloading/preloading.h",
     "preloading/preloading_attempt_impl.cc",
diff --git a/content/browser/attribution_reporting/attribution_debug_report.cc b/content/browser/attribution_reporting/attribution_debug_report.cc
index fd4c87c3..fb1e2d5 100644
--- a/content/browser/attribution_reporting/attribution_debug_report.cc
+++ b/content/browser/attribution_reporting/attribution_debug_report.cc
@@ -61,6 +61,7 @@
     case EventLevelResult::kSuccess:
     case EventLevelResult::kProhibitedByBrowserPolicy:
     case EventLevelResult::kSuccessDroppedLowerPriority:
+    case EventLevelResult::kReportWindowPassed:
       return absl::nullopt;
     case EventLevelResult::kInternalError:
       return DataTypeIfCookieSet(DebugDataType::kTriggerUnknownError,
@@ -107,6 +108,7 @@
     case AggregatableResult::kSuccess:
     case AggregatableResult::kNotRegistered:
     case AggregatableResult::kProhibitedByBrowserPolicy:
+    case AggregatableResult::kReportWindowPassed:
       return absl::nullopt;
     case AggregatableResult::kInternalError:
       return DataTypeIfCookieSet(DebugDataType::kTriggerUnknownError,
diff --git a/content/browser/attribution_reporting/attribution_internals.mojom b/content/browser/attribution_reporting/attribution_internals.mojom
index 5c602ce..583e3df 100644
--- a/content/browser/attribution_reporting/attribution_internals.mojom
+++ b/content/browser/attribution_reporting/attribution_internals.mojom
@@ -158,6 +158,7 @@
     kExcessiveReportingOrigins,
     kProhibitedByBrowserPolicy,
     kDeduplicated,
+    kReportWindowPassed,
 
     // Event-level statuses:
     kLowPriority,
diff --git a/content/browser/attribution_reporting/attribution_internals_handler_impl.cc b/content/browser/attribution_reporting/attribution_internals_handler_impl.cc
index e1e1935..d8a10dd 100644
--- a/content/browser/attribution_reporting/attribution_internals_handler_impl.cc
+++ b/content/browser/attribution_reporting/attribution_internals_handler_impl.cc
@@ -424,6 +424,8 @@
       return WebUITriggerStatus::kNoMatchingConfigurations;
     case EventLevelStatus::kExcessiveReports:
       return WebUITriggerStatus::kExcessiveEventLevelReports;
+    case EventLevelStatus::kReportWindowPassed:
+      return WebUITriggerStatus::kReportWindowPassed;
   }
 }
 
@@ -453,6 +455,8 @@
       return WebUITriggerStatus::kProhibitedByBrowserPolicy;
     case AggregatableStatus::kDeduplicated:
       return WebUITriggerStatus::kDeduplicated;
+    case AggregatableStatus::kReportWindowPassed:
+      return WebUITriggerStatus::kReportWindowPassed;
   }
 }
 
diff --git a/content/browser/attribution_reporting/attribution_manager_impl.cc b/content/browser/attribution_reporting/attribution_manager_impl.cc
index 6bee3bf8..73b3433 100644
--- a/content/browser/attribution_reporting/attribution_manager_impl.cc
+++ b/content/browser/attribution_reporting/attribution_manager_impl.cc
@@ -173,19 +173,18 @@
 }
 
 void RecordCreateReportStatus(CreateReportResult result) {
-  static_assert(
-      AttributionTrigger::EventLevelResult::kMaxValue ==
-          AttributionTrigger::EventLevelResult::kFalselyAttributedSource,
-      "Bump version of Conversions.CreateReportStatus5 histogram.");
-  base::UmaHistogramEnumeration("Conversions.CreateReportStatus5",
+  static_assert(AttributionTrigger::EventLevelResult::kMaxValue ==
+                    AttributionTrigger::EventLevelResult::kReportWindowPassed,
+                "Bump version of Conversions.CreateReportStatus6 histogram.");
+  base::UmaHistogramEnumeration("Conversions.CreateReportStatus6",
                                 result.event_level_status());
   static_assert(
       AttributionTrigger::AggregatableResult::kMaxValue ==
-          AttributionTrigger::AggregatableResult::kDeduplicated,
-      "Bump version of Conversions.AggregatableReport.CreateReportStatus2 "
+          AttributionTrigger::AggregatableResult::kReportWindowPassed,
+      "Bump version of Conversions.AggregatableReport.CreateReportStatus3 "
       "histogram.");
   base::UmaHistogramEnumeration(
-      "Conversions.AggregatableReport.CreateReportStatus2",
+      "Conversions.AggregatableReport.CreateReportStatus3",
       result.aggregatable_status());
 }
 
diff --git a/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc b/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc
index d182b3d..0f60075 100644
--- a/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc
@@ -1046,10 +1046,10 @@
   attribution_manager_->HandleTrigger(DefaultTrigger());
   EXPECT_THAT(StoredReports(), IsEmpty());
   histograms.ExpectUniqueSample(
-      "Conversions.CreateReportStatus5",
+      "Conversions.CreateReportStatus6",
       AttributionTrigger::EventLevelResult::kNoMatchingImpressions, 1);
   histograms.ExpectUniqueSample(
-      "Conversions.AggregatableReport.CreateReportStatus2",
+      "Conversions.AggregatableReport.CreateReportStatus3",
       AttributionTrigger::AggregatableResult::kNotRegistered, 1);
 }
 
diff --git a/content/browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc b/content/browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc
index adb8608..755ad852 100644
--- a/content/browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc
@@ -37,13 +37,16 @@
     base::Time source_time,
     base::Time trigger_time,
     base::TimeDelta expiry = kDefaultExpiry,
+    base::TimeDelta report_window = kDefaultExpiry,
     AttributionSourceType source_type = AttributionSourceType::kNavigation) {
-  return ReportBuilder(AttributionInfoBuilder(SourceBuilder(source_time)
-                                                  .SetExpiry(expiry)
-                                                  .SetSourceType(source_type)
-                                                  .BuildStored())
-                           .SetTime(trigger_time)
-                           .Build())
+  return ReportBuilder(
+             AttributionInfoBuilder(SourceBuilder(source_time)
+                                        .SetExpiry(expiry)
+                                        .SetEventReportWindow(report_window)
+                                        .SetSourceType(source_type)
+                                        .BuildStored())
+                 .SetTime(trigger_time)
+                 .Build())
       .Build();
 }
 
@@ -143,14 +146,14 @@
 }
 
 TEST(AttributionStorageDelegateImplTest,
-     ImpressionExpiryBeforeTwoDayWindow_TwoDayWindowUsed) {
+     ImpressionExpiryBeforeTwoDayWindow_ExpiryUsed) {
   base::Time source_time = base::Time::Now();
   base::Time trigger_time = source_time + base::Hours(1);
 
   // Set the impression to expire before the two day window.
   const AttributionReport report = GetReport(source_time, trigger_time,
                                              /*expiry=*/base::Hours(2));
-  EXPECT_EQ(source_time + base::Days(2) + base::Hours(1),
+  EXPECT_EQ(source_time + base::Hours(3),
             AttributionStorageDelegateImpl().GetEventLevelReportTime(
                 report.attribution_info().source.common_info(),
                 report.attribution_info().time));
@@ -188,13 +191,14 @@
 }
 
 TEST(AttributionStorageDelegateImplTest,
-     SourceTypeEvent_ExpiryLessThanTwoDays_TwoDaysUsed) {
+     SourceTypeEvent_ExpiryLessThanTwoDays_ExpiryUsed) {
   base::Time source_time = base::Time::Now();
   base::Time trigger_time = source_time + base::Days(3);
   const AttributionReport report =
       GetReport(source_time, trigger_time,
-                /*expiry=*/base::Days(1), AttributionSourceType::kEvent);
-  EXPECT_EQ(source_time + base::Days(2) + base::Hours(1),
+                /*expiry=*/base::Days(1),
+                /*report_window=*/base::Days(1), AttributionSourceType::kEvent);
+  EXPECT_EQ(source_time + base::Days(1) + base::Hours(1),
             AttributionStorageDelegateImpl().GetEventLevelReportTime(
                 report.attribution_info().source.common_info(),
                 report.attribution_info().time));
@@ -206,7 +210,23 @@
   base::Time trigger_time = source_time + base::Days(3);
   const AttributionReport report =
       GetReport(source_time, trigger_time,
-                /*expiry=*/base::Days(4), AttributionSourceType::kEvent);
+                /*expiry=*/base::Days(4),
+                /*report_window=*/base::Days(4), AttributionSourceType::kEvent);
+  EXPECT_EQ(source_time + base::Days(4) + base::Hours(1),
+            AttributionStorageDelegateImpl().GetEventLevelReportTime(
+                report.attribution_info().source.common_info(),
+                report.attribution_info().time));
+}
+
+TEST(AttributionStorageDelegateImplTest,
+     ImpressionEventReportWindowBeforeExpiry_ReportWindowUsed) {
+  base::Time source_time = base::Time::Now();
+  base::Time trigger_time = source_time + base::Days(3);
+
+  // Set the impression to expire before the two day window.
+  const AttributionReport report = GetReport(source_time, trigger_time,
+                                             /*expiry=*/base::Days(5),
+                                             /*report_window=*/base::Days(4));
   EXPECT_EQ(source_time + base::Days(4) + base::Hours(1),
             AttributionStorageDelegateImpl().GetEventLevelReportTime(
                 report.attribution_info().source.common_info(),
diff --git a/content/browser/attribution_reporting/attribution_storage_sql.cc b/content/browser/attribution_reporting/attribution_storage_sql.cc
index 9f7fc2e..2bb2bbd 100644
--- a/content/browser/attribution_reporting/attribution_storage_sql.cc
+++ b/content/browser/attribution_reporting/attribution_storage_sql.cc
@@ -1144,6 +1144,9 @@
 
   const CommonSourceInfo& common_info = attribution_info.source.common_info();
 
+  if (attribution_info.time > common_info.event_report_window_time())
+    return EventLevelResult::kReportWindowPassed;
+
   const AttributionSourceType source_type = common_info.source_type();
 
   auto event_trigger = base::ranges::find_if(
@@ -2790,11 +2793,15 @@
   const attribution_reporting::TriggerRegistration& trigger_registration =
       trigger.registration();
 
+  const CommonSourceInfo& common_info = attribution_info.source.common_info();
+
+  if (attribution_info.time > common_info.aggregatable_report_window_time())
+    return AggregatableResult::kReportWindowPassed;
+
   std::vector<AggregatableHistogramContribution> contributions =
       CreateAggregatableHistogram(
-          attribution_info.source.common_info().filter_data(),
-          attribution_info.source.common_info().source_type(),
-          attribution_info.source.common_info().aggregation_keys(),
+          common_info.filter_data(), common_info.source_type(),
+          common_info.aggregation_keys(),
           trigger_registration.aggregatable_trigger_data,
           trigger_registration.aggregatable_values);
   if (contributions.empty())
diff --git a/content/browser/attribution_reporting/attribution_storage_unittest.cc b/content/browser/attribution_reporting/attribution_storage_unittest.cc
index 17bc505..189b897 100644
--- a/content/browser/attribution_reporting/attribution_storage_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_storage_unittest.cc
@@ -309,6 +309,33 @@
             MaybeCreateAndStoreEventLevelReport(DefaultTrigger()));
 }
 
+TEST_F(AttributionStorageTest, ImpressionReportWindowPassed_NoReportGenerated) {
+  storage()->StoreSource(
+      SourceBuilder().SetEventReportWindow(base::Milliseconds(2)).Build());
+  task_environment_.FastForwardBy(base::Milliseconds(3));
+
+  EXPECT_EQ(AttributionTrigger::EventLevelResult::kReportWindowPassed,
+            MaybeCreateAndStoreEventLevelReport(DefaultTrigger()));
+}
+
+TEST_F(AttributionStorageTest,
+       AggregatableReportWindowPassed_NoReportGenerated) {
+  SourceBuilder source_builder = TestAggregatableSourceProvider().GetBuilder();
+
+  storage()->StoreSource(
+      source_builder.SetAggregatableReportWindow(base::Milliseconds(2))
+          .Build());
+
+  task_environment_.FastForwardBy(base::Milliseconds(3));
+  EXPECT_THAT(
+      storage()->MaybeCreateAndStoreReport(
+          DefaultAggregatableTriggerBuilder().Build()),
+      AllOf(CreateReportEventLevelStatusIs(
+                AttributionTrigger::EventLevelResult::kSuccess),
+            CreateReportAggregatableStatusIs(
+                AttributionTrigger::AggregatableResult::kReportWindowPassed)));
+}
+
 TEST_F(AttributionStorageTest, ImpressionExpired_ConversionsStoredPrior) {
   storage()->StoreSource(
       SourceBuilder().SetExpiry(base::Milliseconds(4)).Build());
diff --git a/content/browser/attribution_reporting/attribution_test_utils.cc b/content/browser/attribution_reporting/attribution_test_utils.cc
index f3c8309..5708bb3 100644
--- a/content/browser/attribution_reporting/attribution_test_utils.cc
+++ b/content/browser/attribution_reporting/attribution_test_utils.cc
@@ -1024,6 +1024,9 @@
     case AttributionTrigger::EventLevelResult::kFalselyAttributedSource:
       out << "falselyAttributedSource";
       break;
+    case AttributionTrigger::EventLevelResult::kReportWindowPassed:
+      out << "reportWindowPassed";
+      break;
   }
   return out;
 }
@@ -1068,6 +1071,9 @@
     case AttributionTrigger::AggregatableResult::kDeduplicated:
       out << "deduplicated";
       break;
+    case AttributionTrigger::AggregatableResult::kReportWindowPassed:
+      out << "reportWindowPassed";
+      break;
   }
   return out;
 }
diff --git a/content/browser/attribution_reporting/attribution_trigger.h b/content/browser/attribution_reporting/attribution_trigger.h
index 960253c4..c07eff6 100644
--- a/content/browser/attribution_reporting/attribution_trigger.h
+++ b/content/browser/attribution_reporting/attribution_trigger.h
@@ -38,7 +38,8 @@
     kNoMatchingConfigurations = 12,
     kExcessiveReports = 13,
     kFalselyAttributedSource = 14,
-    kMaxValue = kFalselyAttributedSource,
+    kReportWindowPassed = 15,
+    kMaxValue = kReportWindowPassed,
   };
 
   // Represents the potential aggregatable outcomes from attempting to register
@@ -59,7 +60,8 @@
     kNotRegistered = 9,
     kProhibitedByBrowserPolicy = 10,
     kDeduplicated = 11,
-    kMaxValue = kDeduplicated,
+    kReportWindowPassed = 12,
+    kMaxValue = kReportWindowPassed,
   };
 
   AttributionTrigger(attribution_reporting::TriggerRegistration registration,
diff --git a/content/browser/attribution_reporting/attribution_utils.cc b/content/browser/attribution_reporting/attribution_utils.cc
index 363fba4..fbb80e17 100644
--- a/content/browser/attribution_reporting/attribution_utils.cc
+++ b/content/browser/attribution_reporting/attribution_utils.cc
@@ -38,13 +38,7 @@
 }
 
 base::TimeDelta ExpiryDeadline(const CommonSourceInfo& source) {
-  base::TimeDelta expiry_deadline = source.expiry_time() - source.source_time();
-
-  constexpr base::TimeDelta kMinExpiryDeadline = base::Days(2);
-  if (expiry_deadline < kMinExpiryDeadline)
-    expiry_deadline = kMinExpiryDeadline;
-
-  return expiry_deadline;
+  return source.event_report_window_time() - source.source_time();
 }
 
 base::Time ReportTimeFromDeadline(base::Time source_time,
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc
index 9cb25649..2390c56 100644
--- a/content/browser/devtools/devtools_instrumentation.cc
+++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -1212,6 +1212,13 @@
     exclusion_reasons->push_back(
         protocol::Audits::CookieExclusionReasonEnum::ExcludeDomainNonASCII);
   }
+  if (status.HasExclusionReason(
+          net::CookieInclusionStatus::
+              EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET)) {
+    exclusion_reasons->push_back(
+        protocol::Audits::CookieExclusionReasonEnum::
+            ExcludeThirdPartyCookieBlockedInFirstPartySet);
+  }
 
   return exclusion_reasons;
 }
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc
index 6b8b113..79ad67fcd 100644
--- a/content/browser/devtools/protocol/network_handler.cc
+++ b/content/browser/devtools/protocol/network_handler.cc
@@ -775,6 +775,12 @@
         Network::SetCookieBlockedReasonEnum::UserPreferences);
   }
   if (status.HasExclusionReason(
+          net::CookieInclusionStatus::
+              EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET)) {
+    blockedReasons->push_back(
+        Network::SetCookieBlockedReasonEnum::ThirdPartyBlockedInFirstPartySet);
+  }
+  if (status.HasExclusionReason(
           net::CookieInclusionStatus::EXCLUDE_SAMEPARTY_CROSS_PARTY_CONTEXT)) {
     blockedReasons->push_back(
         Network::SetCookieBlockedReasonEnum::SamePartyFromCrossPartyContext);
@@ -880,6 +886,12 @@
         Network::CookieBlockedReasonEnum::UserPreferences);
   }
   if (status.HasExclusionReason(
+          net::CookieInclusionStatus::
+              EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET)) {
+    blockedReasons->push_back(
+        Network::CookieBlockedReasonEnum::ThirdPartyBlockedInFirstPartySet);
+  }
+  if (status.HasExclusionReason(
           net::CookieInclusionStatus::EXCLUDE_SAMEPARTY_CROSS_PARTY_CONTEXT)) {
     blockedReasons->push_back(
         Network::CookieBlockedReasonEnum::SamePartyFromCrossPartyContext);
diff --git a/content/browser/media/media_capabilities_browsertest.cc b/content/browser/media/media_capabilities_browsertest.cc
index a275f5e..0d7957e 100644
--- a/content/browser/media/media_capabilities_browsertest.cc
+++ b/content/browser/media/media_capabilities_browsertest.cc
@@ -371,16 +371,9 @@
                               /*spatial_rendering*/ true));
 }
 
-// Fails on Linux and Chrome OS: http://crbug.com/1220321.
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-#define MAYBE_VideoTypesWithDynamicRange DISABLED_VideoTypesWithDynamicRange
-#else
-#define MAYBE_VideoTypesWithDynamicRange VideoTypesWithDynamicRange
-#endif
-
 // Cover basic HDR support.
 IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType,
-                       MAYBE_VideoTypesWithDynamicRange) {
+                       VideoTypesWithDynamicRange) {
   base::FilePath file_path = media::GetTestDataFilePath(kDecodeTestFile);
 
   const std::string& config_type = GetTypeString();
diff --git a/content/browser/media/webaudio/audio_context_manager_impl.cc b/content/browser/media/webaudio/audio_context_manager_impl.cc
index aa79c38..230c201 100644
--- a/content/browser/media/webaudio/audio_context_manager_impl.cc
+++ b/content/browser/media/webaudio/audio_context_manager_impl.cc
@@ -91,12 +91,9 @@
   ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get();
   DCHECK(ukm_recorder);
 
-  // TODO(danakj): SetIsMainFrame(render_frame_host().IsInPrimaryMainFrame()) is
-  // simpler.
   ukm::builders::Media_WebAudio_AudioContext_AudibleTime(
       render_frame_host().GetPageUkmSourceId())
-      .SetIsMainFrame(WebContents::FromRenderFrameHost(&render_frame_host())
-                          ->GetPrimaryMainFrame() == &render_frame_host())
+      .SetIsMainFrame(render_frame_host().IsInPrimaryMainFrame())
       .SetAudibleTime(GetBucketedTimeInMilliseconds(audible_time))
       .Record(ukm_recorder);
 }
diff --git a/content/browser/preloading/prefetch/prefetch_document_manager.cc b/content/browser/preloading/prefetch/prefetch_document_manager.cc
index 3ec6d78..2e0a5629 100644
--- a/content/browser/preloading/prefetch/prefetch_document_manager.cc
+++ b/content/browser/preloading/prefetch/prefetch_document_manager.cc
@@ -188,6 +188,60 @@
   return prefetch_container;
 }
 
+bool PrefetchDocumentManager::IsPrefetchAttemptFailedOrDiscarded(
+    const GURL& url) {
+  auto it = all_prefetches_.find(url);
+  if (it == all_prefetches_.end() || !it->second)
+    return true;
+
+  const auto& container = it->second;
+  if (!container->HasPrefetchStatus())
+    return false;  // the container is not processed yet
+
+  switch (container->GetPrefetchStatus()) {
+    case PrefetchStatus::kPrefetchSuccessful:
+      return false;
+    case PrefetchStatus::kPrefetchNotEligibleUserHasCookies:
+    case PrefetchStatus::kPrefetchNotEligibleUserHasServiceWorker:
+    case PrefetchStatus::kPrefetchNotEligibleGoogleDomain:
+    case PrefetchStatus::kPrefetchNotEligibleSchemeIsNotHttps:
+    case PrefetchStatus::kPrefetchNotEligibleNonDefaultStoragePartition:
+    case PrefetchStatus::kPrefetchPositionIneligible:
+    case PrefetchStatus::kPrefetchIneligibleRetryAfter:
+    case PrefetchStatus::kPrefetchProxyNotAvailable:
+    case PrefetchStatus::kPrefetchNotEligibleHostIsNonUnique:
+    case PrefetchStatus::kPrefetchNotEligibleDataSaverEnabled:
+    case PrefetchStatus::kPrefetchNotEligibleExistingProxy:
+    case PrefetchStatus::kPrefetchUsedNoProbe:
+    case PrefetchStatus::kPrefetchUsedProbeSuccess:
+    case PrefetchStatus::kPrefetchNotUsedProbeFailed:
+    case PrefetchStatus::kPrefetchNotStarted:
+    case PrefetchStatus::kPrefetchNotFinishedInTime:
+    case PrefetchStatus::kPrefetchFailedNetError:
+    case PrefetchStatus::kPrefetchFailedNon2XX:
+    case PrefetchStatus::kPrefetchFailedMIMENotSupported:
+    case PrefetchStatus::kNavigatedToLinkNotOnSRP:
+    case PrefetchStatus::kSubresourceThrottled:
+    case PrefetchStatus::kPrefetchUsedNoProbeWithNSP:
+    case PrefetchStatus::kPrefetchUsedProbeSuccessWithNSP:
+    case PrefetchStatus::kPrefetchNotUsedProbeFailedWithNSP:
+    case PrefetchStatus::kPrefetchUsedNoProbeNSPAttemptDenied:
+    case PrefetchStatus::kPrefetchUsedProbeSuccessNSPAttemptDenied:
+    case PrefetchStatus::kPrefetchNotUsedProbeFailedNSPAttemptDenied:
+    case PrefetchStatus::kPrefetchUsedNoProbeNSPNotStarted:
+    case PrefetchStatus::kPrefetchUsedProbeSuccessNSPNotStarted:
+    case PrefetchStatus::kPrefetchNotUsedProbeFailedNSPNotStarted:
+    case PrefetchStatus::kPrefetchIsPrivacyDecoy:
+    case PrefetchStatus::kPrefetchIsStale:
+    case PrefetchStatus::kPrefetchIsStaleWithNSP:
+    case PrefetchStatus::kPrefetchIsStaleNSPAttemptDenied:
+    case PrefetchStatus::kPrefetchIsStaleNSPNotStarted:
+    case PrefetchStatus::kPrefetchNotUsedCookiesChanged:
+    case PrefetchStatus::kPrefetchFailedRedirectsDisabled:
+      return true;
+  }
+}
+
 // static
 void PrefetchDocumentManager::SetPrefetchServiceForTesting(
     PrefetchService* prefetch_service) {
diff --git a/content/browser/preloading/prefetch/prefetch_document_manager.h b/content/browser/preloading/prefetch/prefetch_document_manager.h
index 6d50e19..d149616 100644
--- a/content/browser/preloading/prefetch/prefetch_document_manager.h
+++ b/content/browser/preloading/prefetch/prefetch_document_manager.h
@@ -85,6 +85,9 @@
   // load is received.
   void OnPrefetchSuccessful();
 
+  // Whether the prefetch attempt for target |url| failed or discarded
+  bool IsPrefetchAttemptFailedOrDiscarded(const GURL& url);
+
   static void SetPrefetchServiceForTesting(PrefetchService* prefetch_service);
 
  private:
diff --git a/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc b/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc
index 8eb9d8a9..0bb98b8 100644
--- a/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc
+++ b/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc
@@ -140,8 +140,11 @@
 
   // Process the candidates with the |PrefetchDocumentManager| for the current
   // document.
-  PrefetchDocumentManager::GetOrCreateForCurrentDocument(&GetPrimaryMainFrame())
-      ->ProcessCandidates(candidates, /*devtools_observer=*/nullptr);
+  auto* prefetch_document_manager =
+      PrefetchDocumentManager::GetOrCreateForCurrentDocument(
+          &GetPrimaryMainFrame());
+  prefetch_document_manager->ProcessCandidates(candidates,
+                                               /*devtools_observer=*/nullptr);
 
   // Check that the candidates that should be prefetched were sent to
   // |PrefetchService|.
@@ -165,6 +168,29 @@
   ASSERT_EQ(candidates.size(), 2U);
   EXPECT_EQ(candidates[0]->url, GetCrossOriginUrl("/candidate4.html"));
   EXPECT_EQ(candidates[1]->url, GetCrossOriginUrl("/candidate5.html"));
+
+  // Check IsPrefetchAttemptFailedOrDiscarded method
+  // Discarded candidate
+  EXPECT_TRUE(prefetch_document_manager->IsPrefetchAttemptFailedOrDiscarded(
+      GetCrossOriginUrl("/candidate4.html")));
+  // URLs that were not processed
+  EXPECT_TRUE(prefetch_document_manager->IsPrefetchAttemptFailedOrDiscarded(
+      GetSameOriginUrl("/random_page.html")));
+  // Prefetches with no status yet
+  EXPECT_FALSE(prefetch_urls[0]->HasPrefetchStatus());
+  EXPECT_FALSE(prefetch_document_manager->IsPrefetchAttemptFailedOrDiscarded(
+      GetCrossOriginUrl("/candidate1.html")));
+  // Prefetches with status
+  prefetch_urls[0]->SetPrefetchStatus(PrefetchStatus::kPrefetchSuccessful);
+  EXPECT_FALSE(prefetch_document_manager->IsPrefetchAttemptFailedOrDiscarded(
+      GetCrossOriginUrl("/candidate1.html")));
+  prefetch_urls[0]->SetPrefetchStatus(
+      PrefetchStatus::kPrefetchNotEligibleSchemeIsNotHttps);
+  EXPECT_TRUE(prefetch_document_manager->IsPrefetchAttemptFailedOrDiscarded(
+      GetCrossOriginUrl("/candidate1.html")));
+  prefetch_urls[0]->SetPrefetchStatus(PrefetchStatus::kPrefetchFailedNetError);
+  EXPECT_TRUE(prefetch_document_manager->IsPrefetchAttemptFailedOrDiscarded(
+      GetCrossOriginUrl("/candidate1.html")));
 }
 
 }  // namespace
diff --git a/content/browser/preloading/prefetcher.cc b/content/browser/preloading/prefetcher.cc
new file mode 100644
index 0000000..9739941
--- /dev/null
+++ b/content/browser/preloading/prefetcher.cc
@@ -0,0 +1,90 @@
+// 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/preloading/prefetcher.h"
+
+#include "content/browser/devtools/devtools_instrumentation.h"
+#include "content/browser/devtools/network_service_devtools_observer.h"
+#include "content/browser/preloading/prefetch/prefetch_document_manager.h"
+#include "content/browser/preloading/prefetch/prefetch_features.h"
+
+namespace content {
+
+Prefetcher::Prefetcher(content::RenderFrameHost& render_frame_host)
+    : render_frame_host_(render_frame_host),
+      render_frame_host_impl_(
+          static_cast<RenderFrameHostImpl*>(&render_frame_host)) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  delegate_ = GetContentClient()->browser()->CreateSpeculationHostDelegate(
+      render_frame_host);
+}
+Prefetcher::~Prefetcher() = default;
+
+bool Prefetcher::IsPrefetchAttemptFailedOrDiscarded(const GURL& url) {
+  if (base::FeatureList::IsEnabled(features::kPrefetchUseContentRefactor)) {
+    PrefetchDocumentManager* prefetch_document_manager =
+        PrefetchDocumentManager::GetOrCreateForCurrentDocument(
+            &render_frame_host());
+    return prefetch_document_manager->IsPrefetchAttemptFailedOrDiscarded(url);
+  }
+
+  // TODO(isaboori): Implement |IsPrefetchAttemptFailed| for the delegate case.
+  return true;
+}
+
+void Prefetcher::OnStartSinglePrefetch(
+    const std::string& request_id,
+    const network::ResourceRequest& request) {
+  auto* ftn = render_frame_host_impl()->frame_tree_node();
+  devtools_instrumentation::OnPrefetchRequestWillBeSent(
+      ftn, request_id, render_frame_host().GetLastCommittedURL(), request);
+}
+
+void Prefetcher::OnPrefetchResponseReceived(
+    const GURL& url,
+    const std::string& request_id,
+    const network::mojom::URLResponseHead& response) {
+  auto* ftn = render_frame_host_impl()->frame_tree_node();
+  devtools_instrumentation::OnPrefetchResponseReceived(ftn, request_id, url,
+                                                       response);
+}
+
+void Prefetcher::OnPrefetchRequestComplete(
+    const std::string& request_id,
+    const network::URLLoaderCompletionStatus& status) {
+  auto* ftn = render_frame_host_impl()->frame_tree_node();
+  devtools_instrumentation::OnPrefetchRequestComplete(ftn, request_id, status);
+}
+
+void Prefetcher::OnPrefetchBodyDataReceived(const std::string& request_id,
+                                            const std::string& body,
+                                            bool is_base64_encoded) {
+  auto* ftn = render_frame_host_impl()->frame_tree_node();
+  devtools_instrumentation::OnPrefetchBodyDataReceived(ftn, request_id, body,
+                                                       is_base64_encoded);
+}
+
+mojo::PendingRemote<network::mojom::DevToolsObserver>
+Prefetcher::MakeSelfOwnedNetworkServiceDevToolsObserver() {
+  auto* ftn = render_frame_host_impl()->frame_tree_node();
+  return NetworkServiceDevToolsObserver::MakeSelfOwned(ftn);
+}
+
+void Prefetcher::ProcessCandidatesForPrefetch(
+    std::vector<blink::mojom::SpeculationCandidatePtr>& candidates) {
+  if (base::FeatureList::IsEnabled(features::kPrefetchUseContentRefactor)) {
+    PrefetchDocumentManager* prefetch_document_manager =
+        PrefetchDocumentManager::GetOrCreateForCurrentDocument(
+            &render_frame_host());
+
+    prefetch_document_manager->ProcessCandidates(
+        candidates, weak_ptr_factory_.GetWeakPtr());
+  }
+
+  // Let `delegate_` process the candidates that it is interested in.
+  if (delegate_)
+    delegate_->ProcessCandidates(candidates, weak_ptr_factory_.GetWeakPtr());
+}
+
+}  // namespace content
diff --git a/content/browser/preloading/prefetcher.h b/content/browser/preloading/prefetcher.h
new file mode 100644
index 0000000..0e77221
--- /dev/null
+++ b/content/browser/preloading/prefetcher.h
@@ -0,0 +1,75 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_PRELOADING_PREFETCHER_H_
+#define CONTENT_BROWSER_PRELOADING_PREFETCHER_H_
+
+#include "content/public/browser/speculation_host_delegate.h"
+
+namespace content {
+
+class RenderFrameHost;
+class RenderFrameHostImpl;
+
+// Handles speculation-rules bases prefetches.
+// TODO(isaboori  crbug.com/1384496): Currently Prefetcher class supports the
+// integration of speculation rule based prefetches with the DevTools. It serves
+// as an abstraction layer to avoid implementing the DevTools logic twice in
+// SpeculationHostDelegate and PrefetchDocumentManager. After the refactoring of
+// SpeculationHostDelegate, we can get rid of this layer and implement all the
+// logic in a single class by merging existing Prefetcher and
+// PrefetchDocumentManager into a single class. We should also rename
+// SpeculationHostDevToolsObserver to PrefetcherDevToolsObserver and the class
+// declaration should be moved to this header file.
+class CONTENT_EXPORT Prefetcher : public SpeculationHostDevToolsObserver {
+ public:
+  Prefetcher() = delete;
+  explicit Prefetcher(content::RenderFrameHost& render_frame_host);
+  ~Prefetcher();
+
+  // SpeculationHostDevToolsObserver implementation:
+  void OnStartSinglePrefetch(const std::string& request_id,
+                             const network::ResourceRequest& request) override;
+  void OnPrefetchResponseReceived(
+      const GURL& url,
+      const std::string& request_id,
+      const network::mojom::URLResponseHead& response) override;
+  void OnPrefetchRequestComplete(
+      const std::string& request_id,
+      const network::URLLoaderCompletionStatus& status) override;
+  void OnPrefetchBodyDataReceived(const std::string& request_id,
+                                  const std::string& body,
+                                  bool is_base64_encoded) override;
+  mojo::PendingRemote<network::mojom::DevToolsObserver>
+  MakeSelfOwnedNetworkServiceDevToolsObserver() override;
+
+  RenderFrameHost& render_frame_host() const { return *render_frame_host_; }
+
+  RenderFrameHostImpl* render_frame_host_impl() const {
+    return render_frame_host_impl_;
+  }
+
+  void ProcessCandidatesForPrefetch(
+      std::vector<blink::mojom::SpeculationCandidatePtr>& candidates);
+
+  // Whether the prefetch attempt for target |url| failed or discarded.
+  bool IsPrefetchAttemptFailedOrDiscarded(const GURL& url);
+
+ private:
+  // content::PreloadingDecider, which inherits content::DocumentUserData, owns
+  // `this`, so `this` can access `render_frame_host_` safely.
+  const raw_ref<content::RenderFrameHost> render_frame_host_;
+
+  // content::PreloadingDecider, which inherits content::DocumentUserData, owns
+  // `this`, so `this` can access `render_frame_host_impl_` safely.
+  const raw_ptr<content::RenderFrameHostImpl> render_frame_host_impl_;
+
+  std::unique_ptr<SpeculationHostDelegate> delegate_;
+
+  base::WeakPtrFactory<Prefetcher> weak_ptr_factory_{this};
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_PRELOADING_PREFETCHER_H_
\ No newline at end of file
diff --git a/content/browser/preloading/prefetcher_unittest.cc b/content/browser/preloading/prefetcher_unittest.cc
new file mode 100644
index 0000000..467ce3f
--- /dev/null
+++ b/content/browser/preloading/prefetcher_unittest.cc
@@ -0,0 +1,274 @@
+// 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/preloading/prefetcher.h"
+
+#include <vector>
+
+#include "base/test/scoped_feature_list.h"
+#include "content/browser/preloading/prefetch/prefetch_document_manager.h"
+#include "content/browser/preloading/prefetch/prefetch_features.h"
+#include "content/browser/preloading/prefetch/prefetch_service.h"
+#include "content/public/browser/speculation_host_delegate.h"
+#include "content/public/common/content_client.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_renderer_host.h"
+#include "content/test/test_content_browser_client.h"
+#include "content/test/test_web_contents.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+class MockSpeculationHostDelegate : public SpeculationHostDelegate {
+ public:
+  explicit MockSpeculationHostDelegate(
+      content::RenderFrameHost& render_frame_host) {}
+  ~MockSpeculationHostDelegate() override = default;
+
+  void ProcessCandidates(
+      std::vector<blink::mojom::SpeculationCandidatePtr>& candidates,
+      base::WeakPtr<SpeculationHostDevToolsObserver> devtools_observer)
+      override {
+    for (auto&& candidate : candidates) {
+      candidates_.push_back(std::move(candidate));
+    }
+  }
+  std::vector<blink::mojom::SpeculationCandidatePtr>& Candidates() {
+    return candidates_;
+  }
+
+ private:
+  std::vector<blink::mojom::SpeculationCandidatePtr> candidates_;
+};
+
+class TestPrefetchService : public PrefetchService {
+ public:
+  explicit TestPrefetchService(BrowserContext* browser_context)
+      : PrefetchService(browser_context) {}
+
+  void PrefetchUrl(
+      base::WeakPtr<PrefetchContainer> prefetch_container) override {
+    prefetches_.push_back(prefetch_container);
+
+    const auto& devtools_observer = prefetch_container->GetDevToolsObserver();
+    std::unique_ptr<network::ResourceRequest> request =
+        std::make_unique<network::ResourceRequest>();
+    network::ResourceRequest::TrustedParams trusted_params;
+    request->trusted_params = trusted_params;
+    request->trusted_params->devtools_observer =
+        devtools_observer->MakeSelfOwnedNetworkServiceDevToolsObserver();
+    devtools_observer->OnStartSinglePrefetch(prefetch_container->RequestId(),
+                                             *request);
+
+    network::mojom::URLResponseHead response_head;
+    devtools_observer->OnPrefetchResponseReceived(
+        prefetch_container->GetURL(), prefetch_container->RequestId(),
+        response_head);
+
+    devtools_observer->OnPrefetchRequestComplete(
+        prefetch_container->RequestId(),
+        network::URLLoaderCompletionStatus{net::ERR_NOT_IMPLEMENTED});
+
+    devtools_observer->OnPrefetchBodyDataReceived(
+        prefetch_container->RequestId(), /*body*/ std::string{},
+        /*is_base64_encoded=*/false);
+  }
+
+  std::vector<base::WeakPtr<PrefetchContainer>> prefetches_;
+};
+
+class MockContentBrowserClient : public TestContentBrowserClient {
+ public:
+  MockContentBrowserClient() {
+    old_browser_client_ = SetBrowserClientForTesting(this);
+  }
+  ~MockContentBrowserClient() override {
+    EXPECT_EQ(this, SetBrowserClientForTesting(old_browser_client_));
+  }
+
+  std::unique_ptr<SpeculationHostDelegate> CreateSpeculationHostDelegate(
+      RenderFrameHost& render_frame_host) override {
+    auto delegate =
+        std::make_unique<MockSpeculationHostDelegate>(render_frame_host);
+    delegate_ = delegate.get();
+    return delegate;
+  }
+
+  MockSpeculationHostDelegate* GetDelegate() { return delegate_; }
+
+ private:
+  raw_ptr<ContentBrowserClient> old_browser_client_;
+  raw_ptr<MockSpeculationHostDelegate> delegate_;
+};
+
+class PrefetcherTest : public RenderViewHostTestHarness {
+ public:
+  PrefetcherTest() = default;
+  void SetUp() override {
+    RenderViewHostTestHarness::SetUp();
+
+    browser_context_ = std::make_unique<TestBrowserContext>();
+    web_contents_ = TestWebContents::Create(
+        browser_context_.get(),
+        SiteInstanceImpl::Create(browser_context_.get()));
+    web_contents_->NavigateAndCommit(GetSameOriginUrl("/"));
+    prefetch_service_ =
+        std::make_unique<TestPrefetchService>(GetBrowserContext());
+    PrefetchDocumentManager::SetPrefetchServiceForTesting(
+        prefetch_service_.get());
+  }
+  void TearDown() override {
+    web_contents_.reset();
+    browser_context_.reset();
+    PrefetchDocumentManager::SetPrefetchServiceForTesting(nullptr);
+    RenderViewHostTestHarness::TearDown();
+  }
+
+  RenderFrameHostImpl& GetPrimaryMainFrame() {
+    return web_contents_->GetPrimaryPage().GetMainDocument();
+  }
+
+  GURL GetSameOriginUrl(const std::string& path) {
+    return GURL("https://example.com" + path);
+  }
+
+  GURL GetCrossOriginUrl(const std::string& path) {
+    return GURL("https://other.example.com" + path);
+  }
+
+  TestPrefetchService* GetPrefetchService() { return prefetch_service_.get(); }
+
+ private:
+  std::unique_ptr<TestBrowserContext> browser_context_;
+  std::unique_ptr<TestWebContents> web_contents_;
+  std::unique_ptr<TestPrefetchService> prefetch_service_;
+};
+
+TEST_F(PrefetcherTest, PrefetcherWithDelegate) {
+  MockContentBrowserClient browser_client;
+  auto prefetcher = Prefetcher(GetPrimaryMainFrame());
+  auto* delegate = browser_client.GetDelegate();
+  EXPECT_TRUE(delegate != nullptr);
+
+  // Create list of SpeculationCandidatePtrs.
+  std::vector<blink::mojom::SpeculationCandidatePtr> candidates;
+
+  auto candidate1 = blink::mojom::SpeculationCandidate::New();
+  candidate1->action = blink::mojom::SpeculationAction::kPrefetch;
+  candidate1->requires_anonymous_client_ip_when_cross_origin = true;
+  candidate1->url = GetCrossOriginUrl("/candidate1.html");
+  candidate1->referrer = blink::mojom::Referrer::New();
+  candidates.push_back(std::move(candidate1));
+
+  prefetcher.ProcessCandidatesForPrefetch(candidates);
+  EXPECT_EQ(1u, delegate->Candidates().size());
+
+  EXPECT_TRUE(prefetcher.IsPrefetchAttemptFailedOrDiscarded(
+      GetCrossOriginUrl("/candidate1.html")));
+}
+
+TEST_F(PrefetcherTest, PrefetcherWithoutDelegate) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      content::features::kPrefetchUseContentRefactor,
+      {{"proxy_host", "https://testproxyhost.com"}});
+
+  MockContentBrowserClient browser_client;
+  auto prefetcher = Prefetcher(GetPrimaryMainFrame());
+  auto* delegate = browser_client.GetDelegate();
+  EXPECT_TRUE(delegate != nullptr);
+
+  // Create list of SpeculationCandidatePtrs.
+  std::vector<blink::mojom::SpeculationCandidatePtr> candidates;
+
+  auto candidate1 = blink::mojom::SpeculationCandidate::New();
+  candidate1->action = blink::mojom::SpeculationAction::kPrefetch;
+  candidate1->requires_anonymous_client_ip_when_cross_origin = true;
+  candidate1->url = GetCrossOriginUrl("/candidate1.html");
+  candidate1->referrer = blink::mojom::Referrer::New();
+  candidates.push_back(std::move(candidate1));
+
+  prefetcher.ProcessCandidatesForPrefetch(candidates);
+  EXPECT_TRUE(delegate->Candidates().empty());
+  EXPECT_EQ(1u, GetPrefetchService()->prefetches_.size());
+
+  EXPECT_FALSE(prefetcher.IsPrefetchAttemptFailedOrDiscarded(
+      GetCrossOriginUrl("/candidate1.html")));
+  GetPrefetchService()->prefetches_[0]->SetPrefetchStatus(
+      PrefetchStatus::kPrefetchFailedNetError);
+  EXPECT_TRUE(prefetcher.IsPrefetchAttemptFailedOrDiscarded(
+      GetCrossOriginUrl("/candidate1.html")));
+}
+
+class MockPrefetcher : public Prefetcher {
+ public:
+  explicit MockPrefetcher(content::RenderFrameHost& render_frame_host)
+      : Prefetcher(render_frame_host) {}
+
+  void OnStartSinglePrefetch(const std::string& request_id,
+                             const network::ResourceRequest& request) override {
+    on_start_signle_prefetch_was_called_ = true;
+    dev_tools_observer_is_valid_ =
+        request.trusted_params->devtools_observer.is_valid();
+  }
+  void OnPrefetchResponseReceived(
+      const GURL& url,
+      const std::string& request_id,
+      const network::mojom::URLResponseHead& response) override {
+    on_prefetch_response_received_was_called_ = true;
+  }
+  void OnPrefetchRequestComplete(
+      const std::string& request_id,
+      const network::URLLoaderCompletionStatus& status) override {
+    on_prefetch_request_complete_was_called_ = true;
+  }
+  void OnPrefetchBodyDataReceived(const std::string& request_id,
+                                  const std::string& body,
+                                  bool is_base64_encoded) override {
+    on_prefetch_body_data_received_was_called_ = true;
+  }
+
+  bool on_start_signle_prefetch_was_called_ = false;
+  bool on_prefetch_response_received_was_called_ = false;
+  bool on_prefetch_request_complete_was_called_ = false;
+  bool on_prefetch_body_data_received_was_called_ = false;
+  bool dev_tools_observer_is_valid_ = false;
+};
+
+TEST_F(PrefetcherTest, MockPrefetcher) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      content::features::kPrefetchUseContentRefactor,
+      {{"proxy_host", "https://testproxyhost.com"}});
+
+  MockContentBrowserClient browser_client;
+  auto prefetcher = MockPrefetcher(GetPrimaryMainFrame());
+  auto* delegate = browser_client.GetDelegate();
+  EXPECT_TRUE(delegate != nullptr);
+
+  // Create list of SpeculationCandidatePtrs.
+  std::vector<blink::mojom::SpeculationCandidatePtr> candidates;
+
+  auto candidate1 = blink::mojom::SpeculationCandidate::New();
+  candidate1->action = blink::mojom::SpeculationAction::kPrefetch;
+  candidate1->requires_anonymous_client_ip_when_cross_origin = true;
+  candidate1->url = GetCrossOriginUrl("/candidate1.html");
+  candidate1->referrer = blink::mojom::Referrer::New();
+  candidates.push_back(std::move(candidate1));
+
+  prefetcher.ProcessCandidatesForPrefetch(candidates);
+  EXPECT_TRUE(delegate->Candidates().empty());
+  EXPECT_EQ(1u, GetPrefetchService()->prefetches_.size());
+
+  EXPECT_TRUE(prefetcher.on_start_signle_prefetch_was_called_);
+  EXPECT_TRUE(prefetcher.on_prefetch_response_received_was_called_);
+  EXPECT_TRUE(prefetcher.on_prefetch_request_complete_was_called_);
+  EXPECT_TRUE(prefetcher.on_prefetch_body_data_received_was_called_);
+  EXPECT_TRUE(prefetcher.dev_tools_observer_is_valid_);
+}
+
+}  // namespace
+}  // namespace content
diff --git a/content/browser/renderer_host/cookie_utils.cc b/content/browser/renderer_host/cookie_utils.cc
index 4278b64..dfdaa67 100644
--- a/content/browser/renderer_host/cookie_utils.cc
+++ b/content/browser/renderer_host/cookie_utils.cc
@@ -44,7 +44,10 @@
          status.HasExclusionReason(
              net::CookieInclusionStatus::EXCLUDE_INVALID_SAMEPARTY) ||
          status.HasExclusionReason(
-             net::CookieInclusionStatus::EXCLUDE_DOMAIN_NON_ASCII);
+             net::CookieInclusionStatus::EXCLUDE_DOMAIN_NON_ASCII) ||
+         status.HasExclusionReason(
+             net::CookieInclusionStatus::
+                 EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET);
 }
 
 }  // namespace
diff --git a/content/browser/renderer_host/input/input_router_config_helper.cc b/content/browser/renderer_host/input/input_router_config_helper.cc
index 05b4f523..b77566c 100644
--- a/content/browser/renderer_host/input/input_router_config_helper.cc
+++ b/content/browser/renderer_host/input/input_router_config_helper.cc
@@ -13,20 +13,9 @@
 namespace content {
 namespace {
 
-// Default time allowance for the touch ack delay before the touch sequence is
-// cancelled, depending on whether the site has a mobile-friendly viewport.
-// Note that these constants are effective only when the timeout is supported.
-const int kDesktopTouchAckTimeoutDelayMs = 200;
-const int kMobileTouchAckTimeoutDelayMs = 1000;
-
 PassthroughTouchEventQueue::Config GetTouchEventQueueConfig() {
   PassthroughTouchEventQueue::Config config;
 
-  config.desktop_touch_ack_timeout_delay =
-      base::Milliseconds(kDesktopTouchAckTimeoutDelayMs);
-  config.mobile_touch_ack_timeout_delay =
-      base::Milliseconds(kMobileTouchAckTimeoutDelayMs);
-
 #if BUILDFLAG(IS_ANDROID)
   // For historical reasons only Android enables the touch ack timeout.
   config.touch_ack_timeout_supported = true;
diff --git a/content/browser/renderer_host/input/passthrough_touch_event_queue.h b/content/browser/renderer_host/input/passthrough_touch_event_queue.h
index d5b4180..8946e62 100644
--- a/content/browser/renderer_host/input/passthrough_touch_event_queue.h
+++ b/content/browser/renderer_host/input/passthrough_touch_event_queue.h
@@ -60,30 +60,24 @@
 class CONTENT_EXPORT PassthroughTouchEventQueue {
  public:
   struct CONTENT_EXPORT Config {
-    Config()
-        : desktop_touch_ack_timeout_delay(base::Milliseconds(200)),
-          mobile_touch_ack_timeout_delay(base::Milliseconds(1000)),
-          touch_ack_timeout_supported(false),
-          skip_touch_filter(base::FeatureList::IsEnabled(
-              blink::features::kSkipTouchEventFilter)),
-          events_to_always_forward(kSkipTouchEventFilterType.Get()) {}
-
     // Touch ack timeout delay for desktop sites. If zero, timeout behavior
     // is disabled for such sites. Defaults to 200ms.
-    base::TimeDelta desktop_touch_ack_timeout_delay;
+    base::TimeDelta desktop_touch_ack_timeout_delay = base::Milliseconds(200);
 
     // Touch ack timeout delay for mobile sites. If zero, timeout behavior
     // is disabled for such sites. Defaults to 1000ms.
-    base::TimeDelta mobile_touch_ack_timeout_delay;
+    base::TimeDelta mobile_touch_ack_timeout_delay = base::Milliseconds(1000);
 
     // Whether the platform supports touch ack timeout behavior.
     // Defaults to false (disabled).
-    bool touch_ack_timeout_supported;
+    bool touch_ack_timeout_supported = false;
 
     // Whether we should allow events to bypass normal queue filter rules.
-    bool skip_touch_filter;
+    bool skip_touch_filter =
+        base::FeatureList::IsEnabled(blink::features::kSkipTouchEventFilter);
+
     // What events types are allowed to bypass the filter.
-    std::string events_to_always_forward;
+    std::string events_to_always_forward = kSkipTouchEventFilterType.Get();
   };
 
   PassthroughTouchEventQueue(PassthroughTouchEventQueueClient* client,
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index c97e31d0..e10f7234 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -930,28 +930,28 @@
 
 // Returns the "document" URL used for a navigation, which might be different
 // than the commit URL (CommonNavigationParam's URL) for certain cases such as
-// error page and loadDataWithBaseURL() commits.
+// error document and loadDataWithBaseURL() commits.
 GURL GetLastDocumentURL(
     NavigationRequest* request,
     const mojom::DidCommitProvisionalLoadParams& params,
-    bool last_document_is_error_page,
+    bool last_document_is_error_document,
     const RenderFrameHostImpl::RendererURLInfo& renderer_url_info) {
   if (request->DidEncounterError() ||
-      (request->IsSameDocument() && last_document_is_error_page)) {
-    // If the navigation happens on an error page, the document URL is set to
-    // kUnreachableWebDataURL. Note that if a same-document navigation happens
-    // in an error page it's possible for the document URL to have changed, but
-    // the browser has no way of knowing that URL since it isn't exposed in any
-    // way. Additionally, all current known ways to do a same-document
-    // navigation on an error page (history.pushState/replaceState without
-    // changing the URL) won't change the URL, so it's probably OK to keep using
-    // kUnreachableWebDataURL here.
+      (request->IsSameDocument() && last_document_is_error_document)) {
+    // If the navigation happens on an error document, the document URL is set
+    // to kUnreachableWebDataURL. Note that if a same-document navigation
+    // happens in an error document it's possible for the document URL to have
+    // changed, but the browser has no way of knowing that URL since it isn't
+    // exposed in any way. Additionally, all current known ways to do a
+    // same-document navigation on an error document
+    // (history.pushState/replaceState without changing the URL) won't change
+    // the URL, so it's probably OK to keep using kUnreachableWebDataURL here.
     return GURL(kUnreachableWebDataURL);
   }
   if (request->IsLoadDataWithBaseURL()) {
     // loadDataWithBaseURL() navigation can set its own "base URL", which is
     // also used by the renderer as the document URL unless the navigation
-    // failed (which is already accounted for in the error page case above).
+    // failed (which is already accounted for in the error document case above).
     return request->common_params().base_url_for_data_url;
   }
   if (renderer_url_info.was_loaded_from_load_data_with_base_url &&
@@ -2336,7 +2336,7 @@
   // commit.
   DCHECK_NE(lifecycle_state(), LifecycleStateImpl::kSpeculative);
   DCHECK_NE(lifecycle_state(), LifecycleStateImpl::kPendingCommit);
-  return is_error_page_;
+  return is_error_document_;
 }
 
 DocumentRef RenderFrameHostImpl::GetDocumentRef() {
@@ -3787,7 +3787,7 @@
     last_successful_url_ = params.url;
 
   renderer_url_info_.last_document_url = GetLastDocumentURL(
-      navigation_request, params, is_error_page_, renderer_url_info_);
+      navigation_request, params, is_error_document_, renderer_url_info_);
 
   // Set the last committed HTTP method and POST ID. Note that we're setting
   // this here instead of in DidCommitNewDocument because same-document
@@ -11807,7 +11807,7 @@
     NavigationRequest* navigation_request) {
   // It should be kept in sync with the check in
   // NavigationRequest::DidCommitNavigation.
-  is_error_page_ = navigation_request->DidEncounterError();
+  is_error_document_ = navigation_request->DidEncounterError();
   // Overwrite reporter's reporting source with rfh's reporting source.
   std::unique_ptr<CrossOriginOpenerPolicyReporter> coop_reporter =
       navigation_request->coop_status().TakeCoopReporter();
@@ -12716,14 +12716,14 @@
   const bool has_valid_page_state = blink::PageState::CreateFromEncodedData(
                                         request->commit_params().page_state)
                                         .IsValid();
-  const bool is_error_page = request->DidEncounterError();
+  const bool is_error_document = request->DidEncounterError();
 
   // Predict if the renderer classified the navigation as a "back/forward"
   // navigation (WebFrameLoadType::kBackForward).
   bool will_be_classified_as_back_forward_navigation = false;
-  if (is_error_page) {
-    // For error pages, whenever the navigation has a valid PageState, it will
-    // be considered as a back/forward navigation. This includes history
+  if (is_error_document) {
+    // For error documents, whenever the navigation has a valid PageState, it
+    // will be considered as a back/forward navigation. This includes history
     // navigations and restores. See RenderFrameImpl's CommitFailedNavigation().
     will_be_classified_as_back_forward_navigation = has_valid_page_state;
   } else {
@@ -12740,8 +12740,8 @@
     return RendererLoadType::kBackForward;
   }
 
-  if (!is_error_page && is_reload) {
-    // For non-error pages, if the NavigationType given by the browser is
+  if (!is_error_document && is_reload) {
+    // For non-error documents, if the NavigationType given by the browser is
     // a reload, then the navigation will be classified as a reload.
     return RendererLoadType::kReload;
   }
@@ -12817,7 +12817,7 @@
     NavigationRequest* request,
     const mojom::DidCommitProvisionalLoadParams& params,
     const RenderFrameHostImpl::RendererURLInfo& last_renderer_url_info,
-    bool last_document_is_error_page,
+    bool last_document_is_error_document,
     const GURL& last_committed_url) {
   if (params.url.IsAboutBlank() && params.url.ref_piece() == "blocked") {
     // Some navigations can still be blocked by the renderer during the commit,
@@ -12837,10 +12837,10 @@
   }
 
   if (request->IsSameDocument() &&
-      (last_document_is_error_page ||
+      (last_document_is_error_document ||
        last_renderer_url_info.was_loaded_from_load_data_with_base_url)) {
     // Documents that have an "override" URL (loadDataWithBaseURL navigations,
-    // error pages) will continue using that URL even after same-document
+    // error documents) will continue using that URL even after same-document
     // navigations.
     return last_committed_url;
   }
@@ -12931,14 +12931,15 @@
   // - history_list_was_cleared
   // - origin
   // TODO(crbug.com/1131832): Verify more params.
-  // We can know if we're going to be in an error page after this navigation
+  // We can know if we're going to be in an error document after this navigation
   // if the net error code is not net::OK, or if we're doing a same-document
-  // navigation on an error page (only possible for renderer-initiated
+  // navigation on an error document (only possible for renderer-initiated
   // navigations).
-  const bool is_error_page = (request->DidEncounterError() ||
-                              (is_error_page_ && request->IsSameDocument()));
+  const bool is_error_document =
+      (request->DidEncounterError() ||
+       (is_error_document_ && request->IsSameDocument()));
 
-  const bool browser_url_is_unreachable = is_error_page;
+  const bool browser_url_is_unreachable = is_error_document;
 
   const bool is_same_document_navigation = !!same_document_params;
   const bool is_same_document_history_api_navigation =
@@ -12974,8 +12975,9 @@
   const bool should_replace_current_entry =
       request->common_params().should_replace_current_entry;
 
-  const GURL browser_url = CalculateLoadingURL(
-      request, params, renderer_url_info_, is_error_page_, last_committed_url_);
+  const GURL browser_url =
+      CalculateLoadingURL(request, params, renderer_url_info_,
+                          is_error_document_, last_committed_url_);
 
   const RendererLoadType renderer_load_type =
       CalculateRendererLoadType(request, should_replace_current_entry,
@@ -13130,7 +13132,8 @@
                         !request->frame_tree_node()->IsMainFrame());
   SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "is_form_submission",
                         request->IsFormSubmission());
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "is_error_page", is_error_page);
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "is_error_document",
+                        is_error_document);
   SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "net_error",
                           request->GetNetErrorCode());
 
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index 98b0135..7208de9 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -3801,8 +3801,8 @@
   // HasStickyUserActivation() or HasTransientUserActivation() instead.
   bool last_navigation_started_with_transient_activation_ = false;
 
-  // Whether the last committed navigation is to an error page.
-  bool is_error_page_ = false;
+  // Whether the last committed navigation is to an error document.
+  bool is_error_document_ = false;
 
   // Local root subframes directly own their RenderWidgetHost.
   // Please see comments about the GetLocalRenderWidgetHost() function.
diff --git a/content/browser/resources/attribution_reporting/attribution_internals.ts b/content/browser/resources/attribution_reporting/attribution_internals.ts
index 601e1be..662fe4b 100644
--- a/content/browser/resources/attribution_reporting/attribution_internals.ts
+++ b/content/browser/resources/attribution_reporting/attribution_internals.ts
@@ -991,6 +991,8 @@
       return 'Failure: Excessive reporting origins';
     case WebUITrigger_Status.kDeduplicated:
       return 'Failure: Deduplicated against an earlier report';
+    case WebUITrigger_Status.kReportWindowPassed:
+      return 'Failure: Report window has passed';
     case WebUITrigger_Status.kLowPriority:
       return 'Failure: Priority too low';
     case WebUITrigger_Status.kNoised:
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index fe46213..c6e2672 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -2296,6 +2296,7 @@
     "../browser/preloading/prefetch/prefetch_type_unittest.cc",
     "../browser/preloading/prefetch/prefetch_url_loader_interceptor_unittest.cc",
     "../browser/preloading/prefetch/proxy_lookup_client_impl_unittest.cc",
+    "../browser/preloading/prefetcher_unittest.cc",
     "../browser/preloading/prerender/prerender_host_registry_unittest.cc",
     "../browser/preloading/prerender/prerender_host_unittest.cc",
     "../browser/preloading/prerender/prerender_metrics_unittest.cc",
diff --git a/content/test/attribution_simulator_impl.cc b/content/test/attribution_simulator_impl.cc
index b35dd7f..9d320b5 100644
--- a/content/test/attribution_simulator_impl.cc
+++ b/content/test/attribution_simulator_impl.cc
@@ -422,6 +422,7 @@
       case AttributionTrigger::EventLevelResult::kNoMatchingConfigurations:
       case AttributionTrigger::EventLevelResult::kExcessiveReports:
       case AttributionTrigger::EventLevelResult::kFalselyAttributedSource:
+      case AttributionTrigger::EventLevelResult::kReportWindowPassed:
         event_level_reason << result.event_level_status();
         break;
     }
@@ -442,6 +443,7 @@
       case AttributionTrigger::AggregatableResult::kNoHistograms:
       case AttributionTrigger::AggregatableResult::kProhibitedByBrowserPolicy:
       case AttributionTrigger::AggregatableResult::kDeduplicated:
+      case AttributionTrigger::AggregatableResult::kReportWindowPassed:
         aggregatable_reason << result.aggregatable_status();
         break;
     }
diff --git a/content/test/attribution_simulator_input_parser.cc b/content/test/attribution_simulator_input_parser.cc
index 1f28227..1844cd51 100644
--- a/content/test/attribution_simulator_input_parser.cc
+++ b/content/test/attribution_simulator_input_parser.cc
@@ -353,36 +353,19 @@
       return event_triggers;
 
     auto context = PushContext(kKey);
-    ParseList(
-        *values,
-        base::BindLambdaForTesting([&](const base::Value& event_trigger) {
-          if (!EnsureDictionary(event_trigger))
-            return;
+    ParseList(*values,
+              base::BindLambdaForTesting([&](const base::Value& event_trigger) {
+                base::Value event_trigger_copy = event_trigger.Clone();
+                auto data = attribution_reporting::EventTriggerData::FromJSON(
+                    event_trigger_copy);
+                if (!data.has_value()) {
+                  *Error() << data.error();
+                  return;
+                }
 
-          const base::Value::Dict& dict = event_trigger.GetDict();
-
-          uint64_t trigger_data =
-              ParseOptionalUint64(dict, "trigger_data").value_or(0);
-
-          int64_t priority = ParseOptionalInt64(dict, "priority").value_or(0);
-
-          absl::optional<uint64_t> dedup_key =
-              ParseOptionalUint64(dict, "deduplication_key");
-
-          attribution_reporting::Filters filters =
-              ParseFilters(dict, "filters");
-
-          attribution_reporting::Filters not_filters =
-              ParseFilters(dict, "not_filters");
-
-          if (has_error())
-            return;
-
-          event_triggers.emplace_back(trigger_data, priority, dedup_key,
-                                      std::move(filters),
-                                      std::move(not_filters));
-        }),
-        /*max_size=*/attribution_reporting::kMaxEventTriggerData);
+                event_triggers.emplace_back(std::move(*data));
+              }),
+              /*max_size=*/attribution_reporting::kMaxEventTriggerData);
 
     return event_triggers;
   }
@@ -456,15 +439,6 @@
     return ParseUint64(value->GetIfString(), key);
   }
 
-  absl::optional<int64_t> ParseOptionalInt64(const base::Value::Dict& dict,
-                                             base::StringPiece key) {
-    const base::Value* value = dict.Find(key);
-    if (!value)
-      return absl::nullopt;
-
-    return ParseInt64(value->GetIfString(), key);
-  }
-
   bool ParseDebugReporting(const base::Value::Dict& dict) {
     static constexpr char kKey[] = "debug_reporting";
 
diff --git a/content/test/attribution_simulator_input_parser_unittest.cc b/content/test/attribution_simulator_input_parser_unittest.cc
index 19c2866..bc705c8f 100644
--- a/content/test/attribution_simulator_input_parser_unittest.cc
+++ b/content/test/attribution_simulator_input_parser_unittest.cc
@@ -1052,7 +1052,7 @@
         }]})json",
     },
     {
-        R"(["triggers"][0]["Attribution-Reporting-Register-Trigger"]["event_trigger_data"][0]: must be a dictionary)",
+        R"(["triggers"][0]["Attribution-Reporting-Register-Trigger"]["event_trigger_data"][0]: kEventTriggerDataWrongType)",
         R"json({"triggers":[{
           "Attribution-Reporting-Register-Trigger": {
             "timestamp": "1643235576000",
diff --git a/content/test/data/attribution_reporting/interop/destination_limit.json b/content/test/data/attribution_reporting/interop/destination_limit.json
index 5a3d191e..d70326c 100644
--- a/content/test/data/attribution_reporting/interop/destination_limit.json
+++ b/content/test/data/attribution_reporting/interop/destination_limit.json
@@ -210,7 +210,7 @@
           "trigger_data": "1"
         },
         "report_url": "https://reporter1.test/.well-known/attribution-reporting/report-event-attribution",
-        "report_time": "1643411973000"
+        "report_time": "1643325573000"
       },
       {
         "payload": {
diff --git a/content/test/data/attribution_reporting/interop/rate_limit_max_attributions.json b/content/test/data/attribution_reporting/interop/rate_limit_max_attributions.json
index 7cdce30..187cc03b 100644
--- a/content/test/data/attribution_reporting/interop/rate_limit_max_attributions.json
+++ b/content/test/data/attribution_reporting/interop/rate_limit_max_attributions.json
@@ -233,7 +233,7 @@
           "trigger_data": "1"
         },
         "report_url": "https://reporter.test/.well-known/attribution-reporting/report-event-attribution",
-        "report_time": "1643411973000"
+        "report_time": "1643325573000"
       },
       {
         "payload": {
diff --git a/content/test/gpu/flake_suppressor/gpu_queries.py b/content/test/gpu/flake_suppressor/gpu_queries.py
index 5592ef0b..2984f9c 100644
--- a/content/test/gpu/flake_suppressor/gpu_queries.py
+++ b/content/test/gpu/flake_suppressor/gpu_queries.py
@@ -143,3 +143,6 @@
 
   def GetResultCountTryQuery(self) -> str:
     return TRY_RESULT_COUNT_QUERY
+
+  def GetFailingBuildCulpritFromCiQuery(self) -> str:
+    raise NotImplementedError
diff --git a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
index 4f1a622d..354626f 100644
--- a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
@@ -126,6 +126,8 @@
 crbug.com/1383609 [ android android-sm-a235m ] GpuProcess_canvas2d [ Failure ]
 crbug.com/1383609 [ android android-sm-a235m ] GpuProcess_css3d [ Failure ]
 
+crbug.com/1384930 [ android android-sm-a135m ] GpuProcess_visibility [ RetryOnFailure ]
+
 
 #######################################################################
 # Automated Entries After This Point - Do Not Manually Add Below Here #
diff --git a/content/utility/services.cc b/content/utility/services.cc
index 90d23fa..f4c8c6a 100644
--- a/content/utility/services.cc
+++ b/content/utility/services.cc
@@ -95,7 +95,7 @@
 #if BUILDFLAG(ENABLE_ACCESSIBILITY_SERVICE)
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "services/accessibility/accessibility_service_cros.h"  // nogncheck
-#elif  // !BUILDFLAG(IS_CHROMEOS_ASH)
+#else  // !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "services/accessibility/accessibility_service_chrome.h"  // nogncheck
 #endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "services/accessibility/public/mojom/accessibility_service.mojom.h"  // nogncheck
@@ -260,8 +260,8 @@
     mojo::PendingReceiver<ax::mojom::AccessibilityService> receiver) {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   return std::make_unique<ax::AccessibilityServiceCros>(std::move(receiver));
-#elif   // !BUILDFLAG(IS_CHROMEOS_ASH)
-  return std::make_unique<ax::AccessibilityServiceChrome>(std::move(reciver));
+#else   // !BUILDFLAG(IS_CHROMEOS_ASH)
+  return std::make_unique<ax::AccessibilityServiceChrome>(std::move(receiver));
 #endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 }
 #endif  // BUILDFLAG(ENABLE_ACCESSIBILITY_SERVICE)
diff --git a/device/bluetooth/bluez/bluetooth_device_bluez.cc b/device/bluetooth/bluez/bluetooth_device_bluez.cc
index 32248fa1..f8268ab 100644
--- a/device/bluetooth/bluez/bluetooth_device_bluez.cc
+++ b/device/bluetooth/bluez/bluetooth_device_bluez.cc
@@ -1122,14 +1122,7 @@
                        << " still in progress";
 
   // Determine the error code from error_name.
-  ConnectErrorCode error_code = ERROR_UNKNOWN;
-  if (error_name == bluetooth_device::kErrorFailed) {
-    error_code = ERROR_FAILED;
-  } else if (error_name == bluetooth_device::kErrorInProgress) {
-    error_code = ERROR_INPROGRESS;
-  } else if (error_name == bluetooth_device::kErrorNotSupported) {
-    error_code = ERROR_UNSUPPORTED_DEVICE;
-  }
+  ConnectErrorCode error_code = DBusErrorToConnectError(error_name);
 
   std::move(callback).Run(error_code);
 }
diff --git a/extensions/browser/api/automation_internal/DIR_METADATA b/extensions/browser/api/automation_internal/DIR_METADATA
index 64ab044..43ecd79 100644
--- a/extensions/browser/api/automation_internal/DIR_METADATA
+++ b/extensions/browser/api/automation_internal/DIR_METADATA
@@ -1,3 +1 @@
-monorail {
-  component: "UI>Accessibility"
-}
+mixins: "//extensions/renderer/api/automation/COMMON_METADATA"
diff --git a/extensions/renderer/api/automation/COMMON_METADATA b/extensions/renderer/api/automation/COMMON_METADATA
new file mode 100644
index 0000000..23df930
--- /dev/null
+++ b/extensions/renderer/api/automation/COMMON_METADATA
@@ -0,0 +1,10 @@
+monorail {
+  component: "OS>Accessibility"
+}
+team_email: "chromium-accessibility@chromium.org"
+buganizer {
+  component_id: 1279375
+}
+buganizer_public {
+  component_id: 1279374
+}
diff --git a/extensions/renderer/api/automation/DIR_METADATA b/extensions/renderer/api/automation/DIR_METADATA
index 64ab044..43ecd79 100644
--- a/extensions/renderer/api/automation/DIR_METADATA
+++ b/extensions/renderer/api/automation/DIR_METADATA
@@ -1,3 +1 @@
-monorail {
-  component: "UI>Accessibility"
-}
+mixins: "//extensions/renderer/api/automation/COMMON_METADATA"
diff --git a/fuchsia_web/runners/BUILD.gn b/fuchsia_web/runners/BUILD.gn
index 6dfab26..1376774f 100644
--- a/fuchsia_web/runners/BUILD.gn
+++ b/fuchsia_web/runners/BUILD.gn
@@ -340,6 +340,9 @@
 }
 
 test("web_runner_integration_tests") {
+  # TODO(crbug/1383262): Remove when tests can be migrated.
+  fuchsia_legacy_script_required = true
+
   sources = [ "web/web_runner_smoke_test.cc" ]
   deps = [
     "//base",
diff --git a/fuchsia_web/shell/BUILD.gn b/fuchsia_web/shell/BUILD.gn
index aebd22d..fe635dc 100644
--- a/fuchsia_web/shell/BUILD.gn
+++ b/fuchsia_web/shell/BUILD.gn
@@ -138,7 +138,7 @@
       "//fuchsia_web/webinstance_host",
       "//media",
       "//media/gpu/test:test_helpers",
-      "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.element",
+      "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.policy",
       "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.web",
       "//third_party/fuchsia-sdk/sdk/pkg/fdio",
       "//third_party/fuchsia-sdk/sdk/pkg/scenic_cpp",
diff --git a/fuchsia_web/shell/cast_streaming_shell.cc b/fuchsia_web/shell/cast_streaming_shell.cc
index f7135ed..bef9cc9e 100644
--- a/fuchsia_web/shell/cast_streaming_shell.cc
+++ b/fuchsia_web/shell/cast_streaming_shell.cc
@@ -2,12 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <fuchsia/element/cpp/fidl.h>
+#include <fuchsia/ui/policy/cpp/fidl.h>
 #include <fuchsia/web/cpp/fidl.h>
 #include <lib/sys/cpp/component_context.h>
-#include <lib/ui/scenic/cpp/view_ref_pair.h>
 #include <lib/ui/scenic/cpp/view_token_pair.h>
-#include <zircon/rights.h>
 
 #include "base/command_line.h"
 #include "base/files/file_path.h"
@@ -85,18 +83,8 @@
   return create_context_params;
 }
 
-::fuchsia::ui::views::ViewRef CloneViewRef(
-    const ::fuchsia::ui::views::ViewRef& view_ref) {
-  ::fuchsia::ui::views::ViewRef dup;
-  zx_status_t status =
-      view_ref.reference.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup.reference);
-  ZX_CHECK(status == ZX_OK, status) << "zx_object_duplicate";
-  return dup;
-}
-
 // Set autoplay, enable all logging, and present fullscreen view of `frame`.
-void ConfigureFrame(fuchsia::web::Frame* frame,
-                    ::fuchsia::element::GraphicalPresenter* presenter) {
+void ConfigureFrame(fuchsia::web::Frame* frame) {
   fuchsia::web::ContentAreaSettings settings;
   settings.set_autoplay_policy(fuchsia::web::AutoplayPolicy::ALLOW);
   frame->SetContentAreaSettings(std::move(settings));
@@ -104,17 +92,12 @@
   frame->SetJavaScriptLogLevel(fuchsia::web::ConsoleLogLevel::DEBUG);
 
   auto view_tokens = scenic::ViewTokenPair::New();
-  auto view_ref_pair = scenic::ViewRefPair::New();
-  frame->CreateViewWithViewRef(std::move(view_tokens.view_token),
-                               std::move(view_ref_pair.control_ref),
-                               CloneViewRef(view_ref_pair.view_ref));
-
-  ::fuchsia::element::ViewControllerPtr view_controller;
-  ::fuchsia::element::ViewSpec view_spec;
-  view_spec.set_view_holder_token(std::move(view_tokens.view_holder_token));
-  view_spec.set_view_ref(CloneViewRef(view_ref_pair.view_ref));
-  presenter->PresentView(std::move(view_spec), nullptr,
-                         view_controller.NewRequest(), [](auto) {});
+  frame->CreateView(std::move(view_tokens.view_token));
+  auto presenter = base::ComponentContextForProcess()
+                       ->svc()
+                       ->Connect<fuchsia::ui::policy::Presenter>();
+  presenter->PresentOrReplaceView(std::move(view_tokens.view_holder_token),
+                                  nullptr);
 }
 
 }  // namespace
@@ -174,16 +157,7 @@
         quit_run_loop.Run();
       });
 
-  ::fuchsia::element::GraphicalPresenterPtr presenter =
-      base::ComponentContextForProcess()
-          ->svc()
-          ->Connect<::fuchsia::element::GraphicalPresenter>();
-  presenter.set_error_handler(
-      [quit_run_loop = run_loop.QuitClosure()](zx_status_t status) {
-        ZX_LOG(ERROR, status) << "GraphicalPresenter disconnected.";
-        quit_run_loop.Run();
-      });
-  ConfigureFrame(frame.get(), presenter.get());
+  ConfigureFrame(frame.get());
 
   // Register the MessagePort for the Cast Streaming Receiver.
   std::unique_ptr<cast_api_bindings::MessagePort> sender_message_port;
diff --git a/fuchsia_web/shell/cast_streaming_shell.cmx b/fuchsia_web/shell/cast_streaming_shell.cmx
index b48a464..a2ebfd7 100644
--- a/fuchsia_web/shell/cast_streaming_shell.cmx
+++ b/fuchsia_web/shell/cast_streaming_shell.cmx
@@ -12,7 +12,6 @@
       "fuchsia.accessibility.semantics.SemanticsManager",
       "fuchsia.buildinfo.Provider",
       "fuchsia.device.NameProvider",
-      "fuchsia.element.GraphicalPresenter",
       "fuchsia.feedback.ComponentDataRegister",
       "fuchsia.feedback.CrashReportingProductRegister",
       "fuchsia.fonts.Provider",
@@ -35,6 +34,7 @@
       "fuchsia.sysmem.Allocator",
       "fuchsia.ui.composition.Allocator",
       "fuchsia.ui.composition.Flatland",
+      "fuchsia.ui.policy.Presenter",
       "fuchsia.ui.scenic.Scenic",
       "fuchsia.vulkan.loader.Loader"
     ]
diff --git a/infra/config/generated/builders/ci/fuchsia-arm64-rel/properties.json b/infra/config/generated/builders/ci/fuchsia-arm64-rel/properties.json
index 4780a4d..5d7c0c3 100644
--- a/infra/config/generated/builders/ci/fuchsia-arm64-rel/properties.json
+++ b/infra/config/generated/builders/ci/fuchsia-arm64-rel/properties.json
@@ -45,6 +45,10 @@
         {
           "builder": "fuchsia-arm64-rel",
           "group": "tryserver.chromium.fuchsia"
+        },
+        {
+          "builder": "fuchsia-arm64-rel-orchestrator",
+          "group": "tryserver.chromium.fuchsia"
         }
       ]
     }
diff --git a/infra/config/generated/builders/ci/fuchsia-x64-cast-receiver-rel/properties.json b/infra/config/generated/builders/ci/fuchsia-x64-cast-receiver-rel/properties.json
index d81db15..ee877dd 100644
--- a/infra/config/generated/builders/ci/fuchsia-x64-cast-receiver-rel/properties.json
+++ b/infra/config/generated/builders/ci/fuchsia-x64-cast-receiver-rel/properties.json
@@ -41,10 +41,6 @@
       ],
       "mirroring_builder_group_and_names": [
         {
-          "builder": "fuchsia-arm64-rel-orchestrator",
-          "group": "tryserver.chromium.fuchsia"
-        },
-        {
           "builder": "fuchsia-x64-cast-receiver-rel",
           "group": "tryserver.chromium.fuchsia"
         }
diff --git a/infra/config/generated/builders/ci/mac-arm64-rel/properties.json b/infra/config/generated/builders/ci/mac-arm64-rel/properties.json
index fae2b2b..ac03682 100644
--- a/infra/config/generated/builders/ci/mac-arm64-rel/properties.json
+++ b/infra/config/generated/builders/ci/mac-arm64-rel/properties.json
@@ -30,6 +30,33 @@
           {
             "builder_id": {
               "bucket": "ci",
+              "builder": "mac-fieldtrial-tester",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "builder_group": "chromium.fyi",
+              "execution_mode": "TEST",
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
+                "build_config": "Release",
+                "config": "chromium",
+                "target_bits": 64
+              },
+              "legacy_gclient_config": {
+                "config": "chromium"
+              },
+              "parent": {
+                "bucket": "ci",
+                "builder": "mac-arm64-rel",
+                "project": "chromium"
+              }
+            }
+          },
+          {
+            "builder_id": {
+              "bucket": "ci",
               "builder": "mac11-arm64-rel-tests",
               "project": "chromium"
             },
@@ -97,6 +124,11 @@
       "builder_ids_in_scope_for_testing": [
         {
           "bucket": "ci",
+          "builder": "mac-fieldtrial-tester",
+          "project": "chromium"
+        },
+        {
+          "bucket": "ci",
           "builder": "mac11-arm64-rel-tests",
           "project": "chromium"
         },
@@ -108,6 +140,10 @@
       ],
       "mirroring_builder_group_and_names": [
         {
+          "builder": "mac-fieldtrial-tester",
+          "group": "tryserver.chromium.mac"
+        },
+        {
           "builder": "mac11-arm64-rel",
           "group": "tryserver.chromium.mac"
         },
diff --git a/infra/config/generated/builders/ci/mac-fieldtrial-rel/properties.json b/infra/config/generated/builders/ci/mac-fieldtrial-rel/properties.json
deleted file mode 100644
index 5b4d6d1..0000000
--- a/infra/config/generated/builders/ci/mac-fieldtrial-rel/properties.json
+++ /dev/null
@@ -1,59 +0,0 @@
-{
-  "$build/chromium_tests_builder_config": {
-    "builder_config": {
-      "builder_db": {
-        "entries": [
-          {
-            "builder_id": {
-              "bucket": "ci",
-              "builder": "mac-fieldtrial-rel",
-              "project": "chromium"
-            },
-            "builder_spec": {
-              "builder_group": "chromium.fyi",
-              "execution_mode": "COMPILE_AND_TEST",
-              "legacy_chromium_config": {
-                "apply_configs": [
-                  "mb"
-                ],
-                "build_config": "Release",
-                "config": "chromium",
-                "target_bits": 64
-              },
-              "legacy_gclient_config": {
-                "config": "chromium"
-              }
-            }
-          }
-        ]
-      },
-      "builder_ids": [
-        {
-          "bucket": "ci",
-          "builder": "mac-fieldtrial-rel",
-          "project": "chromium"
-        }
-      ],
-      "mirroring_builder_group_and_names": [
-        {
-          "builder": "mac-fieldtrial-rel",
-          "group": "tryserver.chromium.mac"
-        }
-      ]
-    }
-  },
-  "$build/reclient": {
-    "instance": "rbe-chromium-trusted",
-    "jobs": 250,
-    "metrics_project": "chromium-reclient-metrics"
-  },
-  "$recipe_engine/resultdb/test_presentation": {
-    "column_keys": [],
-    "grouping_keys": [
-      "status",
-      "v.test_suite"
-    ]
-  },
-  "builder_group": "chromium.fyi",
-  "recipe": "chromium"
-}
\ No newline at end of file
diff --git a/infra/config/generated/builders/ci/mac-fieldtrial-tester/properties.json b/infra/config/generated/builders/ci/mac-fieldtrial-tester/properties.json
new file mode 100644
index 0000000..1b17d99
--- /dev/null
+++ b/infra/config/generated/builders/ci/mac-fieldtrial-tester/properties.json
@@ -0,0 +1,83 @@
+{
+  "$build/chromium_tests_builder_config": {
+    "builder_config": {
+      "builder_db": {
+        "entries": [
+          {
+            "builder_id": {
+              "bucket": "ci",
+              "builder": "mac-arm64-rel",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "builder_group": "chromium.mac",
+              "execution_mode": "COMPILE_AND_TEST",
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
+                "build_config": "Release",
+                "config": "chromium",
+                "target_arch": "arm",
+                "target_bits": 64,
+                "target_platform": "mac"
+              },
+              "legacy_gclient_config": {
+                "config": "chromium"
+              }
+            }
+          },
+          {
+            "builder_id": {
+              "bucket": "ci",
+              "builder": "mac-fieldtrial-tester",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "builder_group": "chromium.fyi",
+              "execution_mode": "TEST",
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
+                "build_config": "Release",
+                "config": "chromium",
+                "target_bits": 64
+              },
+              "legacy_gclient_config": {
+                "config": "chromium"
+              },
+              "parent": {
+                "bucket": "ci",
+                "builder": "mac-arm64-rel",
+                "project": "chromium"
+              }
+            }
+          }
+        ]
+      },
+      "builder_ids": [
+        {
+          "bucket": "ci",
+          "builder": "mac-fieldtrial-tester",
+          "project": "chromium"
+        }
+      ],
+      "mirroring_builder_group_and_names": [
+        {
+          "builder": "mac-fieldtrial-tester",
+          "group": "tryserver.chromium.mac"
+        }
+      ]
+    }
+  },
+  "$recipe_engine/resultdb/test_presentation": {
+    "column_keys": [],
+    "grouping_keys": [
+      "status",
+      "v.test_suite"
+    ]
+  },
+  "builder_group": "chromium.fyi",
+  "recipe": "chromium"
+}
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/fuchsia-arm64-rel-compilator/properties.json b/infra/config/generated/builders/try/fuchsia-arm64-rel-compilator/properties.json
index 02598f1..04ce346 100644
--- a/infra/config/generated/builders/try/fuchsia-arm64-rel-compilator/properties.json
+++ b/infra/config/generated/builders/try/fuchsia-arm64-rel-compilator/properties.json
@@ -6,7 +6,7 @@
           {
             "builder_id": {
               "bucket": "ci",
-              "builder": "fuchsia-x64-cast-receiver-rel",
+              "builder": "fuchsia-arm64-rel",
               "project": "chromium"
             },
             "builder_spec": {
@@ -19,12 +19,14 @@
                 ],
                 "build_config": "Release",
                 "config": "chromium",
+                "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "fuchsia"
               },
               "legacy_gclient_config": {
                 "apply_configs": [
-                  "fuchsia_x64"
+                  "fuchsia_arm64",
+                  "fuchsia_arm64_host"
                 ],
                 "config": "chromium"
               }
@@ -35,7 +37,7 @@
       "builder_ids": [
         {
           "bucket": "ci",
-          "builder": "fuchsia-x64-cast-receiver-rel",
+          "builder": "fuchsia-arm64-rel",
           "project": "chromium"
         }
       ]
diff --git a/infra/config/generated/builders/try/fuchsia-arm64-rel-orchestrator/properties.json b/infra/config/generated/builders/try/fuchsia-arm64-rel-orchestrator/properties.json
index 4d970d7..3889e0c1 100644
--- a/infra/config/generated/builders/try/fuchsia-arm64-rel-orchestrator/properties.json
+++ b/infra/config/generated/builders/try/fuchsia-arm64-rel-orchestrator/properties.json
@@ -10,7 +10,7 @@
           {
             "builder_id": {
               "bucket": "ci",
-              "builder": "fuchsia-x64-cast-receiver-rel",
+              "builder": "fuchsia-arm64-rel",
               "project": "chromium"
             },
             "builder_spec": {
@@ -23,12 +23,14 @@
                 ],
                 "build_config": "Release",
                 "config": "chromium",
+                "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "fuchsia"
               },
               "legacy_gclient_config": {
                 "apply_configs": [
-                  "fuchsia_x64"
+                  "fuchsia_arm64",
+                  "fuchsia_arm64_host"
                 ],
                 "config": "chromium"
               }
@@ -39,7 +41,7 @@
       "builder_ids": [
         {
           "bucket": "ci",
-          "builder": "fuchsia-x64-cast-receiver-rel",
+          "builder": "fuchsia-arm64-rel",
           "project": "chromium"
         }
       ]
diff --git a/infra/config/generated/builders/try/mac-fieldtrial-rel/properties.json b/infra/config/generated/builders/try/mac-fieldtrial-rel/properties.json
deleted file mode 100644
index da292221..0000000
--- a/infra/config/generated/builders/try/mac-fieldtrial-rel/properties.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
-  "$build/chromium_tests_builder_config": {
-    "builder_config": {
-      "builder_db": {
-        "entries": [
-          {
-            "builder_id": {
-              "bucket": "ci",
-              "builder": "mac-fieldtrial-rel",
-              "project": "chromium"
-            },
-            "builder_spec": {
-              "builder_group": "chromium.fyi",
-              "execution_mode": "COMPILE_AND_TEST",
-              "legacy_chromium_config": {
-                "apply_configs": [
-                  "mb"
-                ],
-                "build_config": "Release",
-                "config": "chromium",
-                "target_bits": 64
-              },
-              "legacy_gclient_config": {
-                "config": "chromium"
-              }
-            }
-          }
-        ]
-      },
-      "builder_ids": [
-        {
-          "bucket": "ci",
-          "builder": "mac-fieldtrial-rel",
-          "project": "chromium"
-        }
-      ]
-    }
-  },
-  "$build/goma": {
-    "rpc_extra_params": "?prod",
-    "server_host": "goma.chromium.org"
-  },
-  "$recipe_engine/resultdb/test_presentation": {
-    "column_keys": [],
-    "grouping_keys": [
-      "status",
-      "v.test_suite"
-    ]
-  },
-  "builder_group": "tryserver.chromium.mac",
-  "recipe": "chromium_trybot"
-}
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/mac-fieldtrial-tester/properties.json b/infra/config/generated/builders/try/mac-fieldtrial-tester/properties.json
new file mode 100644
index 0000000..901325a
--- /dev/null
+++ b/infra/config/generated/builders/try/mac-fieldtrial-tester/properties.json
@@ -0,0 +1,88 @@
+{
+  "$build/chromium_tests_builder_config": {
+    "builder_config": {
+      "builder_db": {
+        "entries": [
+          {
+            "builder_id": {
+              "bucket": "ci",
+              "builder": "mac-arm64-rel",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "builder_group": "chromium.mac",
+              "execution_mode": "COMPILE_AND_TEST",
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
+                "build_config": "Release",
+                "config": "chromium",
+                "target_arch": "arm",
+                "target_bits": 64,
+                "target_platform": "mac"
+              },
+              "legacy_gclient_config": {
+                "config": "chromium"
+              }
+            }
+          },
+          {
+            "builder_id": {
+              "bucket": "ci",
+              "builder": "mac-fieldtrial-tester",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "builder_group": "chromium.fyi",
+              "execution_mode": "TEST",
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
+                "build_config": "Release",
+                "config": "chromium",
+                "target_bits": 64
+              },
+              "legacy_gclient_config": {
+                "config": "chromium"
+              },
+              "parent": {
+                "bucket": "ci",
+                "builder": "mac-arm64-rel",
+                "project": "chromium"
+              }
+            }
+          }
+        ]
+      },
+      "builder_ids": [
+        {
+          "bucket": "ci",
+          "builder": "mac-arm64-rel",
+          "project": "chromium"
+        }
+      ],
+      "builder_ids_in_scope_for_testing": [
+        {
+          "bucket": "ci",
+          "builder": "mac-fieldtrial-tester",
+          "project": "chromium"
+        }
+      ]
+    }
+  },
+  "$build/goma": {
+    "rpc_extra_params": "?prod",
+    "server_host": "goma.chromium.org"
+  },
+  "$recipe_engine/resultdb/test_presentation": {
+    "column_keys": [],
+    "grouping_keys": [
+      "status",
+      "v.test_suite"
+    ]
+  },
+  "builder_group": "tryserver.chromium.mac",
+  "recipe": "chromium_trybot"
+}
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/win-annotator-rel/properties.json b/infra/config/generated/builders/try/win-annotator-rel/properties.json
index 07097fb..a895634 100644
--- a/infra/config/generated/builders/try/win-annotator-rel/properties.json
+++ b/infra/config/generated/builders/try/win-annotator-rel/properties.json
@@ -4,6 +4,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 150,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win-asan/properties.json b/infra/config/generated/builders/try/win-asan/properties.json
index 4df0236..61ebd181 100644
--- a/infra/config/generated/builders/try/win-asan/properties.json
+++ b/infra/config/generated/builders/try/win-asan/properties.json
@@ -43,6 +43,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 150,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win-fieldtrial-rel/properties.json b/infra/config/generated/builders/try/win-fieldtrial-rel/properties.json
index be89b16..4bf66e3 100644
--- a/infra/config/generated/builders/try/win-fieldtrial-rel/properties.json
+++ b/infra/config/generated/builders/try/win-fieldtrial-rel/properties.json
@@ -43,6 +43,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 150,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win-perfetto-rel/properties.json b/infra/config/generated/builders/try/win-perfetto-rel/properties.json
index 0944f63..8d50233 100644
--- a/infra/config/generated/builders/try/win-perfetto-rel/properties.json
+++ b/infra/config/generated/builders/try/win-perfetto-rel/properties.json
@@ -41,6 +41,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 150,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win-rel-compilator/properties.json b/infra/config/generated/builders/try/win-rel-compilator/properties.json
index d2b9b19..308bafc 100644
--- a/infra/config/generated/builders/try/win-rel-compilator/properties.json
+++ b/infra/config/generated/builders/try/win-rel-compilator/properties.json
@@ -168,6 +168,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 300,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win10-wpt-content-shell-fyi-rel/properties.json b/infra/config/generated/builders/try/win10-wpt-content-shell-fyi-rel/properties.json
index e8b4b52a..fc64c14d 100644
--- a/infra/config/generated/builders/try/win10-wpt-content-shell-fyi-rel/properties.json
+++ b/infra/config/generated/builders/try/win10-wpt-content-shell-fyi-rel/properties.json
@@ -41,6 +41,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 150,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win10_chromium_inverse_fieldtrials_x64_fyi_rel_ng/properties.json b/infra/config/generated/builders/try/win10_chromium_inverse_fieldtrials_x64_fyi_rel_ng/properties.json
index 2a4e486..a7fcbc7 100644
--- a/infra/config/generated/builders/try/win10_chromium_inverse_fieldtrials_x64_fyi_rel_ng/properties.json
+++ b/infra/config/generated/builders/try/win10_chromium_inverse_fieldtrials_x64_fyi_rel_ng/properties.json
@@ -154,6 +154,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 150,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win10_chromium_x64_dbg_ng/properties.json b/infra/config/generated/builders/try/win10_chromium_x64_dbg_ng/properties.json
index 156a0cb..ce57f63 100644
--- a/infra/config/generated/builders/try/win10_chromium_x64_dbg_ng/properties.json
+++ b/infra/config/generated/builders/try/win10_chromium_x64_dbg_ng/properties.json
@@ -77,6 +77,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 150,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win10_chromium_x64_rel_ng-compilator/properties.json b/infra/config/generated/builders/try/win10_chromium_x64_rel_ng-compilator/properties.json
index d2b9b19..308bafc 100644
--- a/infra/config/generated/builders/try/win10_chromium_x64_rel_ng-compilator/properties.json
+++ b/infra/config/generated/builders/try/win10_chromium_x64_rel_ng-compilator/properties.json
@@ -168,6 +168,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 300,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win11-x64-fyi-rel/properties.json b/infra/config/generated/builders/try/win11-x64-fyi-rel/properties.json
index f5e6a979..1214454 100644
--- a/infra/config/generated/builders/try/win11-x64-fyi-rel/properties.json
+++ b/infra/config/generated/builders/try/win11-x64-fyi-rel/properties.json
@@ -92,6 +92,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 150,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win7-rel/properties.json b/infra/config/generated/builders/try/win7-rel/properties.json
index 350e5ca8..c1cec07 100644
--- a/infra/config/generated/builders/try/win7-rel/properties.json
+++ b/infra/config/generated/builders/try/win7-rel/properties.json
@@ -80,6 +80,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 150,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win_archive/properties.json b/infra/config/generated/builders/try/win_archive/properties.json
index 8c91f5f..b2edd7f 100644
--- a/infra/config/generated/builders/try/win_archive/properties.json
+++ b/infra/config/generated/builders/try/win_archive/properties.json
@@ -42,6 +42,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 150,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win_chromium_compile_dbg_ng/properties.json b/infra/config/generated/builders/try/win_chromium_compile_dbg_ng/properties.json
index 1736790..052a5f18 100644
--- a/infra/config/generated/builders/try/win_chromium_compile_dbg_ng/properties.json
+++ b/infra/config/generated/builders/try/win_chromium_compile_dbg_ng/properties.json
@@ -44,6 +44,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 150,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win_chromium_compile_rel_ng/properties.json b/infra/config/generated/builders/try/win_chromium_compile_rel_ng/properties.json
index 21b3f3d..871c4c5 100644
--- a/infra/config/generated/builders/try/win_chromium_compile_rel_ng/properties.json
+++ b/infra/config/generated/builders/try/win_chromium_compile_rel_ng/properties.json
@@ -148,6 +148,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 150,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win_chromium_x64_rel_ng/properties.json b/infra/config/generated/builders/try/win_chromium_x64_rel_ng/properties.json
index b7949ac..d1faa2c 100644
--- a/infra/config/generated/builders/try/win_chromium_x64_rel_ng/properties.json
+++ b/infra/config/generated/builders/try/win_chromium_x64_rel_ng/properties.json
@@ -82,6 +82,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 150,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win_optional_gpu_tests_rel/properties.json b/infra/config/generated/builders/try/win_optional_gpu_tests_rel/properties.json
index 3503d3e..03f9c72 100644
--- a/infra/config/generated/builders/try/win_optional_gpu_tests_rel/properties.json
+++ b/infra/config/generated/builders/try/win_optional_gpu_tests_rel/properties.json
@@ -46,6 +46,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 150,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/win_x64_archive/properties.json b/infra/config/generated/builders/try/win_x64_archive/properties.json
index beb247f..be6d2d0d 100644
--- a/infra/config/generated/builders/try/win_x64_archive/properties.json
+++ b/infra/config/generated/builders/try/win_x64_archive/properties.json
@@ -42,6 +42,11 @@
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org"
   },
+  "$build/reclient": {
+    "instance": "rbe-chromium-untrusted",
+    "jobs": 150,
+    "metrics_project": "chromium-reclient-metrics"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg
index 106f9ff..3c351383 100644
--- a/infra/config/generated/luci/commit-queue.cfg
+++ b/infra/config/generated/luci/commit-queue.cfg
@@ -3239,7 +3239,7 @@
         includable_only: true
       }
       builders {
-        name: "chromium/try/mac-fieldtrial-rel"
+        name: "chromium/try/mac-fieldtrial-tester"
         includable_only: true
       }
       builders {
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index 8aa693c..6c11114 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -43280,12 +43280,14 @@
       }
     }
     builders {
-      name: "mac-fieldtrial-rel"
+      name: "mac-fieldtrial-tester"
       swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:mac-fieldtrial-rel"
+      dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
-      dimensions: "os:Mac-12"
+      dimensions: "free_space:standard"
+      dimensions: "os:Ubuntu-18.04"
       dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -43303,7 +43305,7 @@
         '    }'
         '  },'
         '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/ci/mac-fieldtrial-rel/properties.json",'
+        '    "properties_file": "infra/config/generated/builders/ci/mac-fieldtrial-tester/properties.json",'
         '    "top_level_project": {'
         '      "ref": "refs/heads/main",'
         '      "repo": {'
@@ -81853,6 +81855,14 @@
         value: 5
       }
       experiments {
+        key: "chromium_rts.inverted_rts"
+        value: 100
+      }
+      experiments {
+        key: "chromium_rts.inverted_rts_bail_early"
+        value: 100
+      }
+      experiments {
         key: "chromium_swarming.expose_merge_script_failures"
         value: 100
       }
@@ -85962,7 +85972,7 @@
       }
     }
     builders {
-      name: "mac-fieldtrial-rel"
+      name: "mac-fieldtrial-tester"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
@@ -85986,7 +85996,7 @@
         '    }'
         '  },'
         '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/try/mac-fieldtrial-rel/properties.json",'
+        '    "properties_file": "infra/config/generated/builders/try/mac-fieldtrial-tester/properties.json",'
         '    "top_level_project": {'
         '      "ref": "refs/heads/main",'
         '      "repo": {'
@@ -91123,6 +91133,11 @@
         '    "rpc_extra_params": "?prod",'
         '    "server_host": "goma.chromium.org"'
         '  },'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-untrusted",'
+        '    "jobs": 150,'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
         '  "$recipe_engine/resultdb/test_presentation": {'
         '    "column_keys": [],'
         '    "grouping_keys": ['
@@ -91446,6 +91461,11 @@
         '    "rpc_extra_params": "?prod",'
         '    "server_host": "goma.chromium.org"'
         '  },'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-untrusted",'
+        '    "jobs": 150,'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
         '  "$recipe_engine/resultdb/test_presentation": {'
         '    "column_keys": [],'
         '    "grouping_keys": ['
diff --git a/infra/config/generated/luci/luci-analysis-dev.cfg b/infra/config/generated/luci/luci-analysis-dev.cfg
index 94c4360..c963118 100644
--- a/infra/config/generated/luci/luci-analysis-dev.cfg
+++ b/infra/config/generated/luci/luci-analysis-dev.cfg
@@ -91,6 +91,16 @@
         seconds: 86400 # 24 hours
       }
     }
+    bq_exports {
+      table {
+        cloud_project: "chrome-flakiness"
+        dataset: "weetbix_dev"
+        table: "ci_flaky_test_variants"
+      }
+      predicate {
+        status: FLAKY
+      }
+    }
   }
 }
 
@@ -105,5 +115,15 @@
         seconds: 86400 # 24 hours
       }
     }
+    bq_exports {
+      table {
+        cloud_project: "chrome-flakiness"
+        dataset: "weetbix_dev"
+        table: "try_flaky_test_variants"
+      }
+      predicate {
+        status: FLAKY
+      }
+    }
   }
 }
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg
index 0f5a860..fcc622e 100644
--- a/infra/config/generated/luci/luci-milo.cfg
+++ b/infra/config/generated/luci/luci-milo.cfg
@@ -8489,7 +8489,7 @@
     category: "mac"
   }
   builders {
-    name: "buildbucket/luci.chromium.ci/mac-fieldtrial-rel"
+    name: "buildbucket/luci.chromium.ci/mac-fieldtrial-tester"
     category: "mac"
   }
   builders {
@@ -17232,7 +17232,7 @@
     name: "buildbucket/luci.chromium.try/mac-dawn-rel"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/mac-fieldtrial-rel"
+    name: "buildbucket/luci.chromium.try/mac-fieldtrial-tester"
   }
   builders {
     name: "buildbucket/luci.chromium.try/mac-inverse-fieldtrials-fyi-rel"
@@ -18379,7 +18379,7 @@
     name: "buildbucket/luci.chromium.try/mac-builder-next-rel"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/mac-fieldtrial-rel"
+    name: "buildbucket/luci.chromium.try/mac-fieldtrial-tester"
   }
   builders {
     name: "buildbucket/luci.chromium.try/mac-inverse-fieldtrials-fyi-rel"
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg
index 3f97db87..2a46edf 100644
--- a/infra/config/generated/luci/luci-scheduler.cfg
+++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -381,6 +381,7 @@
 job {
   id: "ChromeOS FYI Release Skylab (kevin)"
   realm: "ci"
+  schedule: "0 3,6,9 * * *"
   buildbucket {
     server: "cr-buildbucket.appspot.com"
     bucket: "ci"
@@ -5285,12 +5286,12 @@
   }
 }
 job {
-  id: "mac-fieldtrial-rel"
+  id: "mac-fieldtrial-tester"
   realm: "ci"
   buildbucket {
     server: "cr-buildbucket.appspot.com"
     bucket: "ci"
-    builder: "mac-fieldtrial-rel"
+    builder: "mac-fieldtrial-tester"
   }
 }
 job {
@@ -6194,7 +6195,6 @@
   triggers: "mac-arm64-rel"
   triggers: "mac-backuprefptr-x64-fyi-rel"
   triggers: "mac-code-coverage"
-  triggers: "mac-fieldtrial-rel"
   triggers: "mac-hermetic-upgrade-rel"
   triggers: "mac-official"
   triggers: "mac-swangle-chromium-x64"
diff --git a/infra/config/generated/luci/realms.cfg b/infra/config/generated/luci/realms.cfg
index 3576fd5a..8bca16a 100644
--- a/infra/config/generated/luci/realms.cfg
+++ b/infra/config/generated/luci/realms.cfg
@@ -164,6 +164,7 @@
         values: "linux-lacros-dbg-tests-fyi"
         values: "linux-lacros-tester-fyi-rel"
         values: "linux-lacros-tester-rel"
+        values: "mac-fieldtrial-tester"
         values: "mac-osxbeta-rel"
         values: "mac10.13-updater-tester-dbg"
         values: "mac10.13-updater-tester-rel"
diff --git a/infra/config/lib/orchestrator.star b/infra/config/lib/orchestrator.star
index e232ea95..ceb0d40 100644
--- a/infra/config/lib/orchestrator.star
+++ b/infra/config/lib/orchestrator.star
@@ -37,11 +37,11 @@
 _EXPERIMENTAL_ORCHESTRATOR_NAMES_BY_COMPILATOR_NAME = {
     "try/android-nougat-x86-rel-compilator": ["try/android-nougat-x86-rel-inverse-fyi"],
     "try/android-pie-arm64-rel-compilator": ["try/android-pie-arm64-rel-inverse-fyi"],
-    "try/mac-rel-compilator": ["try/mac-rel-inverse-fyi"],
     "try/linux_chromium_asan_rel_ng-compilator": ["try/linux_chromium_asan_rel_ng-inverse-fyi"],
     "try/linux_chromium_tsan_rel_ng-compilator": ["try/linux_chromium_tsan_rel_ng-inverse-fyi"],
     "try/linux-rel-compilator": ["try/linux-rel-inverse-fyi"],
     "try/linux-wayland-rel-compilator": ["try/linux-wayland-rel-inverse-fyi"],
+    "try/mac-rel-compilator": ["try/mac-rel-inverse-fyi"],
     "try/win-rel-compilator": ["try/win-rel-inverse-fyi"],
 }
 
diff --git a/infra/config/luci-analysis-dev.cfg b/infra/config/luci-analysis-dev.cfg
index 94c4360..c963118 100644
--- a/infra/config/luci-analysis-dev.cfg
+++ b/infra/config/luci-analysis-dev.cfg
@@ -91,6 +91,16 @@
         seconds: 86400 # 24 hours
       }
     }
+    bq_exports {
+      table {
+        cloud_project: "chrome-flakiness"
+        dataset: "weetbix_dev"
+        table: "ci_flaky_test_variants"
+      }
+      predicate {
+        status: FLAKY
+      }
+    }
   }
 }
 
@@ -105,5 +115,15 @@
         seconds: 86400 # 24 hours
       }
     }
+    bq_exports {
+      table {
+        cloud_project: "chrome-flakiness"
+        dataset: "weetbix_dev"
+        table: "try_flaky_test_variants"
+      }
+      predicate {
+        status: FLAKY
+      }
+    }
   }
 }
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star
index 32f66dcb..be0cdccd 100644
--- a/infra/config/subprojects/chromium/ci/chromium.fyi.star
+++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -453,13 +453,13 @@
     os = os.LINUX_DEFAULT,
 )
 
-ci.builder(
-    name = "mac-fieldtrial-rel",
-    builderless = False,
+ci.thin_tester(
+    name = "mac-fieldtrial-tester",
     console_view_entry = consoles.console_view_entry(
         category = "mac",
     ),
     builder_spec = builder_config.builder_spec(
+        execution_mode = builder_config.execution_mode.TEST,
         chromium_config = builder_config.chromium_config(
             config = "chromium",
             apply_configs = ["mb"],
@@ -471,7 +471,7 @@
         ),
     ),
     cores = None,
-    os = os.MAC_DEFAULT,
+    triggered_by = ["ci/mac-arm64-rel"],
 )
 
 ci.builder(
diff --git a/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star b/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star
index b2b4181d..dbe2852a 100644
--- a/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star
+++ b/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star
@@ -375,6 +375,10 @@
         short_name = "kvn",
     ),
     reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CI,
+    # Kevin is a busy board in OS lab. As this is an FYI builder,
+    # we try to avoid peak hours and run it from 8PM TO 4AM PST.
+    # It is 3 AM to 11 AM UTC.
+    schedule = "0 3,6,9 * * *",
 )
 
 ci.gpu.linux_builder(
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star b/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star
index e2d9e75..649c9ab 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star
@@ -77,7 +77,7 @@
     branch_selector = branches.FUCHSIA_LTS_MILESTONE,
     main_list_view = "try",
     mirrors = [
-        "ci/fuchsia-x64-cast-receiver-rel",
+        "ci/fuchsia-arm64-rel",
     ],
     experiments = {
         "enable_weetbix_queries": 100,
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
index aca385d46..34d5c695 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
@@ -252,6 +252,10 @@
             condition = builder_config.rts_condition.QUICK_RUN_ONLY,
         ),
     ),
+    experiments = {
+        "chromium_rts.inverted_rts": 100,
+        "chromium_rts.inverted_rts_bail_early": 100,
+    },
     use_orchestrator_pool = True,
 
     # TODO(crbug.com/1366987): remove this.
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star
index 2e7893c5..155a408 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star
@@ -69,9 +69,12 @@
 )
 
 try_.builder(
-    name = "mac-fieldtrial-rel",
+    name = "mac-fieldtrial-tester",
     os = os.MAC_DEFAULT,
-    mirrors = ["ci/mac-fieldtrial-rel"],
+    mirrors = [
+        "ci/mac-arm64-rel",
+        "ci/mac-fieldtrial-tester",
+    ],
 )
 
 try_.builder(
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.win.star b/infra/config/subprojects/chromium/try/tryserver.chromium.win.star
index 0949ae95..5113955 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.win.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.win.star
@@ -19,8 +19,11 @@
     execution_timeout = try_.DEFAULT_EXECUTION_TIMEOUT,
     goma_backend = goma.backend.RBE_PROD,
     compilator_goma_jobs = goma.jobs.J300,
+    compilator_reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CQ,
     os = os.WINDOWS_DEFAULT,
     pool = try_.DEFAULT_POOL,
+    reclient_instance = reclient.instance.DEFAULT_UNTRUSTED,
+    reclient_jobs = reclient.jobs.LOW_JOBS_FOR_CQ,
     service_account = try_.DEFAULT_SERVICE_ACCOUNT,
 )
 
@@ -166,6 +169,7 @@
     goma_backend = None,
     os = os.WINDOWS_ANY,
     execution_timeout = 6 * time.hour,
+    reclient_instance = None,
 )
 
 try_.builder(
diff --git a/ios/build/bots/scripts/run.py b/ios/build/bots/scripts/run.py
index 1967d30..0284c18f 100755
--- a/ios/build/bots/scripts/run.py
+++ b/ios/build/bots/scripts/run.py
@@ -312,7 +312,8 @@
       # Swarming infra marks device status unavailable for any device related
       # issue using this return code.
       return 3
-    except test_runner.SimulatorNotFoundError as e:
+    except (test_runner.SimulatorNotFoundError,
+            test_runner.HostIsDownError) as e:
       # This means there's probably some issue in simulator runtime so we don't
       # want to cache it anymore (when it's in new Xcode format).
       self.should_move_xcode_runtime_to_cache = False
diff --git a/ios/build/bots/scripts/run_test.py b/ios/build/bots/scripts/run_test.py
index 7541301..8d11018 100755
--- a/ios/build/bots/scripts/run_test.py
+++ b/ios/build/bots/scripts/run_test.py
@@ -10,7 +10,7 @@
 import unittest
 
 import run
-from test_runner import SimulatorNotFoundError
+from test_runner import HostIsDownError, SimulatorNotFoundError
 import test_runner_test
 
 
@@ -572,6 +572,35 @@
   @mock.patch('xcode_util.construct_runtime_cache_folder', autospec=True)
   @mock.patch('xcode_util.install', autospec=True, return_value=False)
   @mock.patch('xcode_util.move_runtime', autospec=True)
+  @mock.patch('xcode_util.remove_runtimes', autospec=True)
+  def test_error_host_is_down(self, mock_remove_runtimes, mock_move_runtime,
+                              mock_install, mock_construct_runtime_cache_folder,
+                              mock_tr, _1, _2, _3, _4):
+    mock_construct_runtime_cache_folder.side_effect = lambda a, b: a + b
+    mock_tr.side_effect = HostIsDownError
+
+    with mock.patch('run.open', mock.mock_open()):
+      self.runner.run(None)
+
+    mock_install.assert_called_with(
+        'mac_toolchain',
+        'testXcodeVersion',
+        'test/xcode/path',
+        runtime_cache_folder='test/runtime-ios-14.4',
+        ios_version='14.4')
+    self.assertEqual(1, mock_construct_runtime_cache_folder.call_count)
+    self.assertEqual(0, mock_move_runtime.call_count)
+    self.assertFalse(self.runner.should_move_xcode_runtime_to_cache)
+    mock_remove_runtimes.assert_called_with('test/xcode/path')
+
+  @mock.patch('test_runner.defaults_delete')
+  @mock.patch('json.dump')
+  @mock.patch('xcode_util.select', autospec=True)
+  @mock.patch('os.path.exists', autospec=True, return_value=True)
+  @mock.patch('xcodebuild_runner.SimulatorParallelTestRunner')
+  @mock.patch('xcode_util.construct_runtime_cache_folder', autospec=True)
+  @mock.patch('xcode_util.install', autospec=True, return_value=False)
+  @mock.patch('xcode_util.move_runtime', autospec=True)
   def test_device_task(self, mock_move_runtime, mock_install,
                        mock_construct_runtime_cache_folder, mock_tr, _1, _2, _3,
                        _4):
diff --git a/ios/build/bots/scripts/test_runner.py b/ios/build/bots/scripts/test_runner.py
index fec9b713..4d4fa41a8 100644
--- a/ios/build/bots/scripts/test_runner.py
+++ b/ios/build/bots/scripts/test_runner.py
@@ -31,6 +31,7 @@
 LOGGER = logging.getLogger(__name__)
 DERIVED_DATA = os.path.expanduser('~/Library/Developer/Xcode/DerivedData')
 DEFAULT_TEST_REPO = 'https://chromium.googlesource.com/chromium/src'
+HOST_IS_DOWN_ERROR = 'Domain=NSPOSIXErrorDomain Code=64 "Host is down"'
 
 
 # TODO(crbug.com/1077277): Move commonly used error classes to
@@ -140,6 +141,13 @@
       'Sharding has not been implemented!')
 
 
+class HostIsDownError(TestRunnerError):
+  """Simulator host is down, usually due to a corrupted runtime."""
+
+  def __init__(self):
+    super(HostIsDownError, self).__init__('Simulator host is down!')
+
+
 def get_device_ios_version(udid):
   """Gets device iOS version.
 
@@ -266,6 +274,13 @@
     LOGGER.info(line)
     sys.stdout.flush()
 
+    # This is a temporary mitigation to surface this issue so that
+    # test runner can clear runtime cache for the next run.
+    # TODO(crbug.com/1370522): remove this workaround once the issue
+    # is resolved.
+    if HOST_IS_DOWN_ERROR in line:
+      raise HostIsDownError()
+
   if parser:
     parser.Finalize()
   LOGGER.debug('Finished print_process_output.')
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index e588df4..c3839dd 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -1018,13 +1018,6 @@
      flag_descriptions::kTailoredSecurityIntegrationDescription,
      flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(safe_browsing::kTailoredSecurityIntegration)},
-    {"autofill-enable-unmask-card-request-set-instrument-id",
-     flag_descriptions::kAutofillEnableUnmaskCardRequestSetInstrumentIdName,
-     flag_descriptions::
-         kAutofillEnableUnmaskCardRequestSetInstrumentIdDescription,
-     flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(
-         autofill::features::kAutofillEnableUnmaskCardRequestSetInstrumentId)},
     {"autofill-enable-card-product-name",
      flag_descriptions::kAutofillEnableCardProductNameName,
      flag_descriptions::kAutofillEnableCardProductNameDescription,
@@ -1346,6 +1339,10 @@
      FEATURE_WITH_PARAMS_VALUE_TYPE(kEnablePinnedTabs,
                                     kEnablePinnedTabsVariations,
                                     "EnablePinnedTabs")},
+    {"remove-crash-infobar", flag_descriptions::kRemoveCrashInfobarName,
+     flag_descriptions::kRemoveCrashInfobarDescription, flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(kRemoveCrashInfobar)},
+
 };
 
 bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index 4de084c..25392bd 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -50,12 +50,6 @@
     "When enabled, some extra metrics logging for Autofill Downstream will "
     "start.";
 
-const char kAutofillEnableUnmaskCardRequestSetInstrumentIdName[] =
-    "When enabled, sets non-legacy instrument ID in UnmaskCardRequest";
-const char kAutofillEnableUnmaskCardRequestSetInstrumentIdDescription[] =
-    "When enabled, UnmaskCardRequest will set the card's non-legacy ID when "
-    "available.";
-
 const char kAutofillEnableCardProductNameName[] =
     "Enable showing card product name";
 const char kAutofillEnableCardProductNameDescription[] =
@@ -657,6 +651,11 @@
     "snapshots. PDF snaphot will be taken just for the purpose of the "
     "histogram recording.";
 
+const char kRemoveCrashInfobarName[] = "Remove Crash Infobars";
+const char kRemoveCrashInfobarDescription[] =
+    "When enabled, always auto restore tabs rather than showing a crash "
+    "infobar";
+
 const char kRemoveExcessNTPsExperimentName[] = "Remove extra New Tab Pages";
 const char kRemoveExcessNTPsExperimentDescription[] =
     "When enabled, extra tabs with the New Tab Page open and no navigation "
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index 957b335..55284c1 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -46,11 +46,6 @@
 extern const char kAutofillEnableRemadeDownstreamMetricsName[];
 extern const char kAutofillEnableRemadeDownstreamMetricsDescription[];
 
-// Title and description for flag to enable sending non-legacy instrument ID in
-// UnmaskCardRequest.
-extern const char kAutofillEnableUnmaskCardRequestSetInstrumentIdName[];
-extern const char kAutofillEnableUnmaskCardRequestSetInstrumentIdDescription[];
-
 // Title and description for flag to enable showing card product name (instead
 // of issuer network) in Payments UI.
 extern const char kAutofillEnableCardProductNameName[];
@@ -589,6 +584,9 @@
 extern const char kRecordSnapshotSizeName[];
 extern const char kRecordSnapshotSizeDescription[];
 
+extern const char kRemoveCrashInfobarName[];
+extern const char kRemoveCrashInfobarDescription[];
+
 // Title and description for the flag to remove excess NTP tabs that don't have
 // navigation history.
 extern const char kRemoveExcessNTPsExperimentName[];
diff --git a/ios/chrome/browser/ui/ui_feature_flags.cc b/ios/chrome/browser/ui/ui_feature_flags.cc
index 78a69a81..c23a1c8 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.cc
+++ b/ios/chrome/browser/ui/ui_feature_flags.cc
@@ -48,6 +48,10 @@
              "IOSOmniboxUpdatedPopupUI",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kRemoveCrashInfobar,
+             "RemoveCrashInfobar",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 const char kIOSOmniboxUpdatedPopupUIVariationName[] = "PopupUIVariant";
 
 extern const char kIOSOmniboxUpdatedPopupUIVariation1[] = "variant-one";
diff --git a/ios/chrome/browser/ui/ui_feature_flags.h b/ios/chrome/browser/ui/ui_feature_flags.h
index 2a0b563e..0c058784 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.h
+++ b/ios/chrome/browser/ui/ui_feature_flags.h
@@ -50,6 +50,9 @@
 // Feature flag that toggles the SwiftUI omnibox popup implementation.
 BASE_DECLARE_FEATURE(kIOSOmniboxUpdatedPopupUI);
 
+// Feature flag that removes the crash infobar.
+BASE_DECLARE_FEATURE(kRemoveCrashInfobar);
+
 // Parameter name for the parameter controlling which UI variation to use for
 // the SwiftUI omnibox popup.
 extern const char kIOSOmniboxUpdatedPopupUIVariationName[];
diff --git a/ios/chrome/credential_provider_extension/ui/new_password_coordinator.mm b/ios/chrome/credential_provider_extension/ui/new_password_coordinator.mm
index f2f425d9..f0d4f75 100644
--- a/ios/chrome/credential_provider_extension/ui/new_password_coordinator.mm
+++ b/ios/chrome/credential_provider_extension/ui/new_password_coordinator.mm
@@ -77,7 +77,7 @@
 
   NSString* identifier = self.serviceIdentifiers.firstObject.identifier;
   NSURL* url = identifier ? [NSURL URLWithString:identifier] : nil;
-  newPasswordViewController.currentHost = url.host;
+  newPasswordViewController.currentHost = url ? url.host : @"";
 
   self.viewController = [[UINavigationController alloc]
       initWithRootViewController:newPasswordViewController];
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
index a5272b6..c51a3ca 100644
--- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-62b2edfc2c8ce20b575685d0ad14aac7304272bf
\ No newline at end of file
+0f5cc6941f3d11b7f4a3ae4aface9dc359bd6c30
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
index 61e7e6d..aee61a3b 100644
--- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-aa1a256d9a5c5e24c5bb4fa4563c500136d87677
\ No newline at end of file
+a059a2cb30ff58495753e2098b7e715c3942a408
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
index c3e82979..d6dca25 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-9a03701490b336d0654772727924fa407c12fdbe
\ No newline at end of file
+a162aa8b249d456c267d0894c450718c011f9eee
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
index 8cde477..40f52c5 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-e39495a2b4bada7066d30cee6a81facccb975b27
\ No newline at end of file
+4eff299ede3d15c58c22f19dc00ffb3655face27
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
index f2fedd0..4a76f83f 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-ab791dbe50b529e04dd23165e72d1e095f94a599
\ No newline at end of file
+e0c1992a70c0cc7b04359b12d6970dbf8d90bbe3
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
index 0f942fd..5d1a21f 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-ee542295f6e87541c7786782b3f8e27700f82a71
\ No newline at end of file
+e65d6909ce5160607e87aeedcb95f86620f6c757
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
index dd48431..d3a89df 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-5e68f178776c6c40defdfd70bfdbad3fe2cddbca
\ No newline at end of file
+66c7f4ccf7a610985b4bf7b3f04f8a4365851758
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
index 73f6504..af459e5 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-2b845fe2176305c920e142de68d3dd0805bbfeef
\ No newline at end of file
+fb3f729c4c91538ff2e4de648103c5861ca235e9
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
index d764fec9..4c04e45 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-83de0693446e6c325ac752b55509524d8260eea4
\ No newline at end of file
+a61710c27f12cfdda5c1fec75e0c5c5194212a2c
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
index 3ed9f671..6523d7af 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-00e28a67b25e22af41478afb395497f37c336be1
\ No newline at end of file
+d385fb902fe3ebdf498c26b07945a46116e12598
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
index 57c315d3..6842c4f 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-b9491e8a2464f6f80b5fb81ec133bdbe2918f4ac
\ No newline at end of file
+0a37225d94cb7c3187d9c7b53f29c3aad4847d92
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
index 6822222..daa07613 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-db525c5dc9c372fa331c7f14ce7652629575d2c7
\ No newline at end of file
+abd7962dc032b58b52b9eeab3e5b6d9408fdb5e2
\ No newline at end of file
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn
index 7be534e..efc3ed03 100644
--- a/media/audio/BUILD.gn
+++ b/media/audio/BUILD.gn
@@ -402,6 +402,7 @@
     "audio_debug_file_writer_unittest.cc",
     "audio_debug_recording_helper_unittest.cc",
     "audio_debug_recording_manager_unittest.cc",
+    "audio_device_description_unittest.cc",
     "audio_encoders_unittest.cc",
     "audio_input_device_unittest.cc",
     "audio_input_stream_data_interceptor_unittest.cc",
diff --git a/media/audio/audio_device_description.cc b/media/audio/audio_device_description.cc
index a9cb921..4f71c9a5 100644
--- a/media/audio/audio_device_description.cc
+++ b/media/audio/audio_device_description.cc
@@ -19,6 +19,19 @@
 const char AudioDeviceDescription::kLoopbackWithMuteDeviceId[] =
     "loopbackWithMute";
 
+namespace {
+constexpr char kAirpodsNameSubstring[] = "AirPods";
+
+// Sanitize names which are known to contain the user's name, such as AirPods'
+// default name. See crbug.com/1163072 and crbug.com/1293761.
+void RedactDeviceName(std::string& name) {
+  if (name.find(kAirpodsNameSubstring) != std::string::npos) {
+    name = kAirpodsNameSubstring;
+  }
+}
+
+}  // namespace
+
 // static
 bool AudioDeviceDescription::IsDefaultDevice(const std::string& device_id) {
   return device_id.empty() ||
@@ -92,6 +105,8 @@
 void AudioDeviceDescription::LocalizeDeviceDescriptions(
     AudioDeviceDescriptions* device_descriptions) {
   for (auto& description : *device_descriptions) {
+    RedactDeviceName(description.device_name);
+
     if (media::AudioDeviceDescription::IsDefaultDevice(description.unique_id)) {
       description.device_name =
           media::AudioDeviceDescription::GetDefaultDeviceName(
diff --git a/media/audio/audio_device_description.h b/media/audio/audio_device_description.h
index 23e8c0af..47f24bd 100644
--- a/media/audio/audio_device_description.h
+++ b/media/audio/audio_device_description.h
@@ -74,7 +74,8 @@
       const std::string& real_device_name);
 
   // This prepends localized "Default" or "Communications" strings to
-  // default and communications device names in |device_descriptions|.
+  // default and communications device names in |device_descriptions|, and
+  // sanitizes devices known to contain users' names etc.
   static void LocalizeDeviceDescriptions(
       std::vector<AudioDeviceDescription>* device_descriptions);
 
diff --git a/media/audio/audio_device_description_unittest.cc b/media/audio/audio_device_description_unittest.cc
new file mode 100644
index 0000000..44c558e5
--- /dev/null
+++ b/media/audio/audio_device_description_unittest.cc
@@ -0,0 +1,37 @@
+// 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 "media/audio/audio_device_description.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+namespace media {
+
+TEST(AudioDeviceDescriptionTest, LocalizedGenericLabelLeftUnchanged) {
+  std::vector<AudioDeviceDescription> device_descriptions{
+      AudioDeviceDescription("Super fantastic microphone", "uniqueId",
+                             "groupId")};
+  AudioDeviceDescription::LocalizeDeviceDescriptions(&device_descriptions);
+
+  EXPECT_EQ(device_descriptions[0].device_name, "Super fantastic microphone");
+}
+
+TEST(AudioDeviceDescriptionTest, LocalizedUserNameInLabelIsSanitized) {
+  std::vector<AudioDeviceDescription> device_descriptions{
+      AudioDeviceDescription("User's AirPods", "uniqueId", "groupId")};
+  AudioDeviceDescription::LocalizeDeviceDescriptions(&device_descriptions);
+
+  EXPECT_EQ(device_descriptions[0].device_name, "AirPods");
+}
+
+TEST(AudioDeviceDescriptionTest, LocalizedUserNameInDefaultDeviceIsSanitized) {
+  std::vector<AudioDeviceDescription> device_descriptions{
+      AudioDeviceDescription("User's AirPods", "default", "groupId"),
+      AudioDeviceDescription("User's AirPods", "uniqueId", "groupId")};
+  AudioDeviceDescription::LocalizeDeviceDescriptions(&device_descriptions);
+
+  EXPECT_EQ(device_descriptions[0].device_name, "Default - AirPods");
+  EXPECT_EQ(device_descriptions[1].device_name, "AirPods");
+}
+
+}  // namespace media
\ No newline at end of file
diff --git a/net/data/ssl/chrome_root_store/faq.md b/net/data/ssl/chrome_root_store/faq.md
index ee650af..fdc525a 100644
--- a/net/data/ssl/chrome_root_store/faq.md
+++ b/net/data/ssl/chrome_root_store/faq.md
@@ -1,5 +1,5 @@
 # Frequently Asked Questions
-Last updated: September 1, 2022
+Last updated: November 11, 2022
 
 - [What is the Chrome Root Store?](#what-is-the-chrome-root-store)
 - [Where is the Chrome Root Store source code located?](#where-is-the-chrome-root-store-source-code-located)
@@ -35,6 +35,12 @@
 [Chrome Root Store](https://g.co/chrome/root-store) contains the set of
 certificates Chrome trusts by default.
 
+In Chrome 105, we began rolling out the Chrome Root Store to apply a common
+certificate verification process on Windows and macOS. The rollout of the
+Chrome Root Store on Android, Chrome OS, and Linux  will be announced at a later
+date. Apple policies prevent the Chrome Root Store and corresponding Chrome
+Certificate Verifier from being used on Chrome for iOS.
+
 ## Where is the Chrome Root Store source code located?
 Source locations include
 [//net/data/ssl/chrome_root_store](/net/data/ssl/chrome_root_store),
@@ -45,14 +51,19 @@
 Historically, Chrome integrated certificate verification processes with the
 platform on which it was running. This resulted in inconsistent user experiences
 across platforms, while also making it difficult for developers to understand
-Chrome's expected behavior. Beginning in Chrome 105, we'll begin rolling out the
-Chrome Certificate Verifier to apply a common certificate verification process
-on Windows and macOS. The rollout of the Chrome Certificate Verifier on Chrome
-OS, Linux, and Android will be announced at a later date. The launch of the
-Chrome Certificate Verifier will ensure users have a consistent experience
-across platforms, that developers have a consistent understanding of Chrome's
-behavior, and that Chrome better protects the security and privacy of users'
-connections to websites.
+Chrome's expected behavior.
+
+In Chrome 105, we began rolling out the Chrome Certificate Verifier to apply a
+common certificate verification process on Windows and macOS. The rollout of the
+Chrome Certificate Verifier on Android will be announced at a later date. The 
+Chrome Certificate Verifier launched on Chrome OS in Chrome 77 and Linux in
+Chrome 79. Apple policies prevent the Chrome Certificate Verifier and
+corresponding Chrome Root Store from being used on Chrome for iOS.
+
+Once complete, the launch of the Chrome Certificate Verifier will ensure users
+have a consistent experience across platforms, that developers have a consistent
+understanding of Chrome's behavior, and that Chrome better protects the security
+and privacy of users' connections to websites.
 
 ## Where is Chrome Certificate Verifier source code?
 Source locations include
@@ -131,7 +142,7 @@
 smoothly, we don’t enable a new feature for all of our users at once. Instead,
 we start with a small percentage of users and increase that percentage over time
 to ensure we minimize unanticipated compatibility issues. The Chrome Root Store
-and Certificate Verifier will begin rolling out on Windows and macOS in Chrome
+and Certificate Verifier began rolling out on Windows and macOS in Chrome
 105, with other platforms to follow.
 
 ## Given the rollout is gradual, how can I tell if these features are in use on my system?
@@ -142,8 +153,7 @@
 - **Expected outcome with Chrome Root Store disabled:** Page loads
 
 **If on macOS:** Navigate to https://valid-ctrca.certificates.certum.pl/ …
-- **Expected outcome with Chrome Root Store enabled:** Page does not load
-(NET::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED)
+- **Expected outcome with Chrome Root Store enabled:** Page loads
 - **Expected outcome with Chrome Root Store disabled:** Page does not load
 (NET::ERR_CERT_AUTHORITY_INVALID)
 
@@ -173,19 +183,22 @@
      more about common connection errors
      [here](https://support.google.com/chrome/answer/6098869?hl=en).
 2. Choose to *either* add the website’s corresponding root CA certificate to
-your platform root store *or* temporarily use these Chrome Enterprise Policies
+your platform root store *or* temporarily use a Chrome Enterprise Policy
 to disable the use of the Chrome Root Store and Certificate Verifier.
 
-    * **Adding a CA certificate to the platform root store:** Refer to your
+    * **Add a CA certificate to the platform root store:** Refer to your
     operating system instructions for managing certificates. <br><br>*Warning*:
     You should **never** install a root certificate without careful
     consideration to the impact this might have on your privacy and security.
     *Only* install a root certificate after obtaining it from a trusted source
     and verifying its authenticity (e.g., verifying its SHA-256 thumbprint).
 
-    * **Use Chrome Enterprise Policies:** See
+    * **Use the Chrome Enterprise Policy:** See
     [below](#can-you-help_i_m-experiencing-problems).
 
+If you believe the Chrome Certificate Verifier is not working as intended,
+submit a [bug](https://bugs.chromium.org/p/chromium/issues/entry).
+
 ## Can I revert to the platform root store and verifier?
 The Chrome Certificate Verifier evaluates certificate profile conformance
 against [RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280), and in some
@@ -195,7 +208,7 @@
 store and verifier.
 
 This enterprise policy is planned to be removed from Windows and macOS beginning
-in Chrome 111, and should only be used as a temporary solution while
+in Chrome 113, and should only be used as a temporary solution while
 troubleshooting and remediating instances of certificate profile conformance
 issues.
 
@@ -233,8 +246,7 @@
 Root Store during Chrome browser application updates.
 
 ## Why does the certificate viewer look different?
-Beginning in Chrome 105, Chrome on Windows and macOS transitioned from using the
+In Chrome 105, Chrome on Windows and macOS transitioned from using the
 native platform certificate viewer to the Chrome Certificate Viewer. This
-transition is intended to promote a consistent experience across platforms
-as we begin the [rollout](#when-are-these-changes-taking-place) of the Chrome
-Root Store.
\ No newline at end of file
+transition promotes a consistent experience across platforms as we begin the
+[rollout](#when-are-these-changes-taking-place) of the Chrome Root Store.
\ No newline at end of file
diff --git a/net/dns/dns_transaction.cc b/net/dns/dns_transaction.cc
index c339210..9c0072ab 100644
--- a/net/dns/dns_transaction.cc
+++ b/net/dns/dns_transaction.cc
@@ -215,20 +215,15 @@
     DCHECK_EQ(STATE_NONE, next_state_);
     callback_ = std::move(callback);
     start_time_ = base::TimeTicks::Now();
-    next_state_ = STATE_SEND_QUERY;
+    next_state_ = STATE_CONNECT_COMPLETE;
 
-    int rv = socket_->Connect(server_);
-    if (rv != OK) {
-      DVLOG(1) << "Failed to connect socket: " << rv;
-      udp_tracker_->RecordConnectionError(rv);
-      return ERR_CONNECTION_REFUSED;
+    int rv = socket_->ConnectAsync(
+        server_,
+        base::BindOnce(&DnsUDPAttempt::OnIOComplete, base::Unretained(this)));
+    if (rv == ERR_IO_PENDING) {
+      return rv;
     }
-
-    IPEndPoint local_address;
-    if (socket_->GetLocalAddress(&local_address) == OK)
-      udp_tracker_->RecordQuery(local_address.port(), query_->id());
-
-    return DoLoop(OK);
+    return DoLoop(rv);
   }
 
   const DnsQuery* GetQuery() const override { return query_.get(); }
@@ -252,6 +247,7 @@
 
  private:
   enum State {
+    STATE_CONNECT_COMPLETE,
     STATE_SEND_QUERY,
     STATE_SEND_QUERY_COMPLETE,
     STATE_READ_RESPONSE,
@@ -266,8 +262,11 @@
       State state = next_state_;
       next_state_ = STATE_NONE;
       switch (state) {
+        case STATE_CONNECT_COMPLETE:
+          rv = DoConnectComplete(rv);
+          break;
         case STATE_SEND_QUERY:
-          rv = DoSendQuery();
+          rv = DoSendQuery(rv);
           break;
         case STATE_SEND_QUERY_COMPLETE:
           rv = DoSendQueryComplete(rv);
@@ -290,7 +289,23 @@
     return rv;
   }
 
-  int DoSendQuery() {
+  int DoConnectComplete(int rv) {
+    if (rv != OK) {
+      DVLOG(1) << "Failed to connect socket: " << rv;
+      udp_tracker_->RecordConnectionError(rv);
+      return ERR_CONNECTION_REFUSED;
+    }
+    next_state_ = STATE_SEND_QUERY;
+    IPEndPoint local_address;
+    if (socket_->GetLocalAddress(&local_address) == OK)
+      udp_tracker_->RecordQuery(local_address.port(), query_->id());
+    return OK;
+  }
+
+  int DoSendQuery(int rv) {
+    DCHECK_NE(ERR_IO_PENDING, rv);
+    if (rv < 0)
+      return rv;
     next_state_ = STATE_SEND_QUERY_COMPLETE;
     return socket_->Write(
         query_->io_buffer(), query_->io_buffer()->size(),
@@ -1497,8 +1512,6 @@
   // Resolves the result of a DnsAttempt until a terminal result is reached
   // or it will complete asynchronously (ERR_IO_PENDING).
   AttemptResult ProcessAttemptResult(AttemptResult result) {
-    DCHECK(!callback_.is_null());
-
     while (result.rv != ERR_IO_PENDING) {
       LogResponse(result.attempt);
 
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc
index 0ec63a6..331b9b6 100644
--- a/net/dns/dns_transaction_unittest.cc
+++ b/net/dns/dns_transaction_unittest.cc
@@ -158,6 +158,7 @@
 
   ~DnsSocketData() = default;
 
+  void ClearWrites() { writes_.clear(); }
   // All responses must be added before GetProvider.
 
   // Adds pre-built DnsResponse. |tcp_length| will be used in TCP mode only.
@@ -282,6 +283,8 @@
 
   ~TestUDPClientSocket() override = default;
   int Connect(const IPEndPoint& endpoint) override;
+  int ConnectAsync(const IPEndPoint& address,
+                   CompletionOnceCallback callback) override;
 
  private:
   raw_ptr<TestSocketFactory> factory_;
@@ -344,6 +347,12 @@
   return MockUDPClientSocket::Connect(endpoint);
 }
 
+int TestUDPClientSocket::ConnectAsync(const IPEndPoint& address,
+                                      CompletionOnceCallback callback) {
+  factory_->OnConnect(address);
+  return MockUDPClientSocket::ConnectAsync(address, std::move(callback));
+}
+
 // Helper class that holds a DnsTransaction and handles OnTransactionComplete.
 class TransactionHelper {
  public:
@@ -686,6 +695,21 @@
     socket_data_.push_back(std::move(data));
   }
 
+  void AddQueryAndResponseNoWrite(uint16_t id,
+                                  const char* dotted_name,
+                                  uint16_t qtype,
+                                  IoMode mode,
+                                  Transport transport,
+                                  const OptRecordRdata* opt_rdata = nullptr,
+                                  DnsQuery::PaddingStrategy padding_strategy =
+                                      DnsQuery::PaddingStrategy::NONE) {
+    CHECK(socket_factory_.get());
+    auto data = std::make_unique<DnsSocketData>(
+        id, dotted_name, qtype, mode, transport, opt_rdata, padding_strategy);
+    data->ClearWrites();
+    AddSocketData(std::move(data), true);
+  }
+
   // Add expected query for |dotted_name| and |qtype| with |id| and response
   // taken verbatim from |data| of |data_length| bytes. The transaction id in
   // |data| should equal |id|, unless testing mismatched response.
@@ -1085,8 +1109,9 @@
 }
 
 TEST_F(DnsTransactionTest, CancelLookup) {
-  AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
-                           kT0ResponseDatagram, std::size(kT0ResponseDatagram));
+  AddQueryAndResponseNoWrite(0 /* id */, kT0HostName, kT0Qtype, ASYNC,
+                             Transport::UDP, nullptr);
+
   AddAsyncQueryAndResponse(1 /* id */, kT1HostName, kT1Qtype,
                            kT1ResponseDatagram, std::size(kT1ResponseDatagram));
 
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index 3ec771f..7ec65be 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -120956,7 +120956,6 @@
     { "name": "fitnetion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fixaslowcomputer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fizzcompetitions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "flagcity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "flashset.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "flexfitnessusa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "flexibsd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 661b057..6716e0a 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -703,6 +703,11 @@
     for (auto it = partition_it; it < maybe_included_cookies.end(); ++it) {
       it->access_result.status.AddExclusionReason(
           CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
+      if (first_party_set_metadata_.AreSitesInSameFirstPartySet()) {
+        it->access_result.status.AddExclusionReason(
+            CookieInclusionStatus::
+                EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET);
+      }
     }
     excluded_cookies.insert(
         excluded_cookies.end(), std::make_move_iterator(partition_it),
diff --git a/ppapi/host/message_filter_host.h b/ppapi/host/message_filter_host.h
index 170ce7f..16df9725 100644
--- a/ppapi/host/message_filter_host.h
+++ b/ppapi/host/message_filter_host.h
@@ -6,7 +6,7 @@
 #define PPAPI_HOST_MESSAGE_FILTER_HOST_H_
 
 #include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/host/ppapi_host_export.h"
 #include "ppapi/host/resource_host.h"
 
diff --git a/ppapi/host/resource_host.h b/ppapi/host/resource_host.h
index eed75842..18f531c6 100644
--- a/ppapi/host/resource_host.h
+++ b/ppapi/host/resource_host.h
@@ -7,7 +7,7 @@
 
 #include <vector>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/pp_resource.h"
 #include "ppapi/host/ppapi_host_export.h"
 #include "ppapi/host/resource_message_handler.h"
diff --git a/ppapi/nacl_irt/manifest_service.h b/ppapi/nacl_irt/manifest_service.h
index c4433ca7..b855a9fc 100644
--- a/ppapi/nacl_irt/manifest_service.h
+++ b/ppapi/nacl_irt/manifest_service.h
@@ -7,7 +7,7 @@
 
 #include <memory>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/synchronization/lock.h"
 
 namespace base {
diff --git a/ppapi/nacl_irt/ppapi_dispatcher.h b/ppapi/nacl_irt/ppapi_dispatcher.h
index cdc39709..d578db2 100644
--- a/ppapi/nacl_irt/ppapi_dispatcher.h
+++ b/ppapi/nacl_irt/ppapi_dispatcher.h
@@ -12,7 +12,7 @@
 #include <string>
 
 #include "base/files/file.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/process/process_handle.h"
 #include "ipc/ipc_channel_handle.h"
 #include "ipc/ipc_listener.h"
diff --git a/ppapi/proxy/audio_input_resource.h b/ppapi/proxy/audio_input_resource.h
index 470efc0..f33fdd3 100644
--- a/ppapi/proxy/audio_input_resource.h
+++ b/ppapi/proxy/audio_input_resource.h
@@ -12,7 +12,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/memory/read_only_shared_memory_region.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/sync_socket.h"
 #include "base/threading/simple_thread.h"
 #include "ppapi/proxy/device_enumeration_resource_helper.h"
diff --git a/ppapi/proxy/audio_output_resource.h b/ppapi/proxy/audio_output_resource.h
index a6384194..a22d008 100644
--- a/ppapi/proxy/audio_output_resource.h
+++ b/ppapi/proxy/audio_output_resource.h
@@ -11,7 +11,7 @@
 #include <memory>
 
 #include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/memory/unsafe_shared_memory_region.h"
 #include "base/sync_socket.h"
 #include "base/threading/simple_thread.h"
diff --git a/ppapi/proxy/device_enumeration_resource_helper.h b/ppapi/proxy/device_enumeration_resource_helper.h
index d9db0983..f6041c4 100644
--- a/ppapi/proxy/device_enumeration_resource_helper.h
+++ b/ppapi/proxy/device_enumeration_resource_helper.h
@@ -10,7 +10,7 @@
 #include <memory>
 #include <vector>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "ppapi/c/dev/ppb_device_ref_dev.h"
 #include "ppapi/proxy/ppapi_proxy_export.h"
diff --git a/ppapi/proxy/dispatcher.h b/ppapi/proxy/dispatcher.h
index 5fe8ac5..f2b29b1 100644
--- a/ppapi/proxy/dispatcher.h
+++ b/ppapi/proxy/dispatcher.h
@@ -10,7 +10,7 @@
 #include <vector>
 
 #include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ipc/message_filter.h"
 #include "ppapi/c/pp_instance.h"
 #include "ppapi/c/pp_module.h"
diff --git a/ppapi/proxy/file_system_resource.h b/ppapi/proxy/file_system_resource.h
index 3c7947d5..126978f 100644
--- a/ppapi/proxy/file_system_resource.h
+++ b/ppapi/proxy/file_system_resource.h
@@ -11,7 +11,7 @@
 #include <string>
 
 #include "base/containers/queue.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/pp_file_info.h"
 #include "ppapi/c/pp_resource.h"
 #include "ppapi/c/private/ppb_isolated_file_system_private.h"
diff --git a/ppapi/proxy/host_resolver_resource_base.h b/ppapi/proxy/host_resolver_resource_base.h
index 9a38fc7..479ef5a 100644
--- a/ppapi/proxy/host_resolver_resource_base.h
+++ b/ppapi/proxy/host_resolver_resource_base.h
@@ -11,7 +11,7 @@
 #include <vector>
 
 #include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/private/ppb_host_resolver_private.h"
 #include "ppapi/proxy/plugin_resource.h"
 #include "ppapi/proxy/ppapi_proxy_export.h"
diff --git a/ppapi/proxy/isolated_file_system_private_resource.h b/ppapi/proxy/isolated_file_system_private_resource.h
index 34e1eda5..f2aad14 100644
--- a/ppapi/proxy/isolated_file_system_private_resource.h
+++ b/ppapi/proxy/isolated_file_system_private_resource.h
@@ -23,7 +23,7 @@
 
 #include <string>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/proxy/connection.h"
 #include "ppapi/proxy/plugin_resource.h"
 #include "ppapi/proxy/ppapi_proxy_export.h"
diff --git a/ppapi/proxy/media_stream_audio_track_resource.h b/ppapi/proxy/media_stream_audio_track_resource.h
index bcd4661..c8989e3 100644
--- a/ppapi/proxy/media_stream_audio_track_resource.h
+++ b/ppapi/proxy/media_stream_audio_track_resource.h
@@ -10,7 +10,7 @@
 #include <map>
 #include <string>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/proxy/media_stream_track_resource_base.h"
 #include "ppapi/proxy/ppapi_proxy_export.h"
 #include "ppapi/thunk/ppb_media_stream_audio_track_api.h"
diff --git a/ppapi/proxy/media_stream_video_track_resource.h b/ppapi/proxy/media_stream_video_track_resource.h
index 32dbe46..3df8650 100644
--- a/ppapi/proxy/media_stream_video_track_resource.h
+++ b/ppapi/proxy/media_stream_video_track_resource.h
@@ -9,7 +9,7 @@
 
 #include <map>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/proxy/media_stream_track_resource_base.h"
 #include "ppapi/proxy/ppapi_proxy_export.h"
 #include "ppapi/thunk/ppb_media_stream_video_track_api.h"
diff --git a/ppapi/proxy/message_handler.h b/ppapi/proxy/message_handler.h
index a17e50f..43c09f4 100644
--- a/ppapi/proxy/message_handler.h
+++ b/ppapi/proxy/message_handler.h
@@ -9,7 +9,7 @@
 
 #include <memory>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/pp_resource.h"
 #include "ppapi/c/ppp_message_handler.h"
 #include "ppapi/proxy/ppapi_proxy_export.h"
diff --git a/ppapi/proxy/plugin_globals.h b/ppapi/proxy/plugin_globals.h
index 5ce7aa8..a0d99c88 100644
--- a/ppapi/proxy/plugin_globals.h
+++ b/ppapi/proxy/plugin_globals.h
@@ -9,7 +9,7 @@
 #include <string>
 
 #include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/threading/thread_local_storage.h"
 #include "ppapi/proxy/connection.h"
 #include "ppapi/proxy/plugin_resource_tracker.h"
diff --git a/ppapi/proxy/plugin_message_filter.h b/ppapi/proxy/plugin_message_filter.h
index 75f28991..ef5eb65 100644
--- a/ppapi/proxy/plugin_message_filter.h
+++ b/ppapi/proxy/plugin_message_filter.h
@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ipc/ipc_sender.h"
 #include "ipc/message_filter.h"
 #include "ppapi/c/pp_instance.h"
diff --git a/ppapi/proxy/plugin_resource.h b/ppapi/proxy/plugin_resource.h
index 8fad44b..2369200 100644
--- a/ppapi/proxy/plugin_resource.h
+++ b/ppapi/proxy/plugin_resource.h
@@ -10,7 +10,7 @@
 #include <map>
 
 #include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_sender.h"
 #include "ppapi/c/pp_errors.h"
diff --git a/ppapi/proxy/plugin_var_tracker.h b/ppapi/proxy/plugin_var_tracker.h
index 2f4250e6..1783c3e 100644
--- a/ppapi/proxy/plugin_var_tracker.h
+++ b/ppapi/proxy/plugin_var_tracker.h
@@ -9,7 +9,7 @@
 #include <string>
 
 #include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/memory/unsafe_shared_memory_region.h"
 #include "ppapi/c/pp_stdint.h"
 #include "ppapi/c/pp_var.h"
diff --git a/ppapi/proxy/ppapi_proxy_test.h b/ppapi/proxy/ppapi_proxy_test.h
index 9ec7aa0..c8e3508d 100644
--- a/ppapi/proxy/ppapi_proxy_test.h
+++ b/ppapi/proxy/ppapi_proxy_test.h
@@ -12,7 +12,7 @@
 #include <string>
 
 #include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/test/task_environment.h"
 #include "base/threading/simple_thread.h"
diff --git a/ppapi/proxy/ppb_message_loop_proxy.h b/ppapi/proxy/ppb_message_loop_proxy.h
index 2b999f61..bda71524 100644
--- a/ppapi/proxy/ppb_message_loop_proxy.h
+++ b/ppapi/proxy/ppb_message_loop_proxy.h
@@ -10,7 +10,7 @@
 #include <memory>
 
 #include "base/bind.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/run_loop.h"
 #include "base/task/single_thread_task_executor.h"
 #include "base/task/single_thread_task_runner.h"
diff --git a/ppapi/proxy/tcp_server_socket_private_resource.h b/ppapi/proxy/tcp_server_socket_private_resource.h
index 9fbfad0..57e7876 100644
--- a/ppapi/proxy/tcp_server_socket_private_resource.h
+++ b/ppapi/proxy/tcp_server_socket_private_resource.h
@@ -8,7 +8,7 @@
 #include <stdint.h>
 
 #include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/proxy/plugin_resource.h"
 #include "ppapi/proxy/ppapi_proxy_export.h"
 #include "ppapi/shared_impl/tracked_callback.h"
diff --git a/ppapi/proxy/tcp_socket_resource_base.h b/ppapi/proxy/tcp_socket_resource_base.h
index ff5477a..00edded 100644
--- a/ppapi/proxy/tcp_socket_resource_base.h
+++ b/ppapi/proxy/tcp_socket_resource_base.h
@@ -11,7 +11,7 @@
 #include <vector>
 
 #include "base/containers/queue.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/ppb_tcp_socket.h"
 #include "ppapi/c/private/ppb_net_address_private.h"
 #include "ppapi/proxy/plugin_resource.h"
diff --git a/ppapi/proxy/udp_socket_resource_base.h b/ppapi/proxy/udp_socket_resource_base.h
index 5381b97..cad606ad 100644
--- a/ppapi/proxy/udp_socket_resource_base.h
+++ b/ppapi/proxy/udp_socket_resource_base.h
@@ -10,7 +10,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/containers/queue.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/ppb_udp_socket.h"
 #include "ppapi/c/private/ppb_net_address_private.h"
 #include "ppapi/proxy/plugin_resource.h"
diff --git a/ppapi/proxy/video_decoder_resource.h b/ppapi/proxy/video_decoder_resource.h
index 51a576c..3463093 100644
--- a/ppapi/proxy/video_decoder_resource.h
+++ b/ppapi/proxy/video_decoder_resource.h
@@ -12,7 +12,7 @@
 #include <vector>
 
 #include "base/containers/queue.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/proxy/connection.h"
 #include "ppapi/proxy/plugin_resource.h"
 #include "ppapi/proxy/ppapi_proxy_export.h"
diff --git a/ppapi/proxy/video_encoder_resource.h b/ppapi/proxy/video_encoder_resource.h
index 83979c0d..0aa0194 100644
--- a/ppapi/proxy/video_encoder_resource.h
+++ b/ppapi/proxy/video_encoder_resource.h
@@ -11,7 +11,7 @@
 #include <vector>
 
 #include "base/containers/circular_deque.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/memory/shared_memory_mapping.h"
 #include "ppapi/proxy/connection.h"
 #include "ppapi/proxy/plugin_resource.h"
diff --git a/ppapi/shared_impl/array_writer.h b/ppapi/shared_impl/array_writer.h
index b5c59d7..0a55147 100644
--- a/ppapi/shared_impl/array_writer.h
+++ b/ppapi/shared_impl/array_writer.h
@@ -10,7 +10,7 @@
 
 #include <vector>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/pp_array_output.h"
 #include "ppapi/c/pp_resource.h"
 #include "ppapi/c/pp_var.h"
diff --git a/ppapi/shared_impl/ppapi_globals.h b/ppapi/shared_impl/ppapi_globals.h
index 6a34d3c5..0a0f23f 100644
--- a/ppapi/shared_impl/ppapi_globals.h
+++ b/ppapi/shared_impl/ppapi_globals.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/threading/thread_local.h"  // For testing purposes only.
 #include "ppapi/c/pp_instance.h"
 #include "ppapi/c/pp_module.h"
diff --git a/ppapi/shared_impl/thread_aware_callback.h b/ppapi/shared_impl/thread_aware_callback.h
index 0b0abec..c695c9f 100644
--- a/ppapi/shared_impl/thread_aware_callback.h
+++ b/ppapi/shared_impl/thread_aware_callback.h
@@ -6,7 +6,7 @@
 #define PPAPI_SHARED_IMPL_THREAD_AWARE_CALLBACK_H_
 
 #include "base/bind.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/shared_impl/ppapi_shared_export.h"
 #include "ppapi/shared_impl/proxy_lock.h"
 
diff --git a/ppapi/shared_impl/url_request_info_data.h b/ppapi/shared_impl/url_request_info_data.h
index e2d3c10..e01bcd2d 100644
--- a/ppapi/shared_impl/url_request_info_data.h
+++ b/ppapi/shared_impl/url_request_info_data.h
@@ -8,7 +8,7 @@
 #include <string>
 #include <vector>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/pp_resource.h"
 #include "ppapi/c/pp_stdint.h"
 #include "ppapi/c/pp_time.h"
diff --git a/ppapi/thunk/enter.h b/ppapi/thunk/enter.h
index b42cc42a..6e7b646 100644
--- a/ppapi/thunk/enter.h
+++ b/ppapi/thunk/enter.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/pp_resource.h"
 #include "ppapi/shared_impl/ppapi_globals.h"
diff --git a/ppapi/thunk/ppb_audio_api.h b/ppapi/thunk/ppb_audio_api.h
index 8851333f..1165a84e 100644
--- a/ppapi/thunk/ppb_audio_api.h
+++ b/ppapi/thunk/ppb_audio_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/pp_completion_callback.h"
 #include "ppapi/c/ppb_audio.h"
 #include "ppapi/thunk/ppapi_thunk_export.h"
diff --git a/ppapi/thunk/ppb_audio_input_api.h b/ppapi/thunk/ppb_audio_input_api.h
index 799bc7f..50cf7ee 100644
--- a/ppapi/thunk/ppb_audio_input_api.h
+++ b/ppapi/thunk/ppb_audio_input_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/dev/ppb_audio_input_dev.h"
 
 namespace ppapi {
diff --git a/ppapi/thunk/ppb_audio_output_api.h b/ppapi/thunk/ppb_audio_output_api.h
index 55ed372b..e8c9ec8 100644
--- a/ppapi/thunk/ppb_audio_output_api.h
+++ b/ppapi/thunk/ppb_audio_output_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/dev/ppb_audio_output_dev.h"
 
 namespace ppapi {
diff --git a/ppapi/thunk/ppb_file_chooser_api.h b/ppapi/thunk/ppb_file_chooser_api.h
index b2911a19..093e3f8 100644
--- a/ppapi/thunk/ppb_file_chooser_api.h
+++ b/ppapi/thunk/ppb_file_chooser_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/dev/ppb_file_chooser_dev.h"
 
 namespace ppapi {
diff --git a/ppapi/thunk/ppb_file_io_api.h b/ppapi/thunk/ppb_file_io_api.h
index 2f2d769..1948473 100644
--- a/ppapi/thunk/ppb_file_io_api.h
+++ b/ppapi/thunk/ppb_file_io_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/ppb_file_io.h"
 #include "ppapi/c/private/pp_file_handle.h"
 #include "ppapi/thunk/ppapi_thunk_export.h"
diff --git a/ppapi/thunk/ppb_file_ref_api.h b/ppapi/thunk/ppb_file_ref_api.h
index 93dd86aa..f57c391f 100644
--- a/ppapi/thunk/ppb_file_ref_api.h
+++ b/ppapi/thunk/ppb_file_ref_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/ppb_file_ref.h"
 #include "ppapi/shared_impl/file_ref_create_info.h"
 #include "ppapi/thunk/ppapi_thunk_export.h"
diff --git a/ppapi/thunk/ppb_file_system_api.h b/ppapi/thunk/ppb_file_system_api.h
index 6db40f1d..8aaaeea7 100644
--- a/ppapi/thunk/ppb_file_system_api.h
+++ b/ppapi/thunk/ppb_file_system_api.h
@@ -8,7 +8,7 @@
 #include <stdint.h>
 
 #include "base/callback_forward.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/ppb_file_system.h"
 
 namespace ppapi {
diff --git a/ppapi/thunk/ppb_graphics_2d_api.h b/ppapi/thunk/ppb_graphics_2d_api.h
index 52fd326..d894b99 100644
--- a/ppapi/thunk/ppb_graphics_2d_api.h
+++ b/ppapi/thunk/ppb_graphics_2d_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/pp_bool.h"
 #include "ppapi/c/pp_completion_callback.h"
 #include "ppapi/c/pp_point.h"
diff --git a/ppapi/thunk/ppb_graphics_3d_api.h b/ppapi/thunk/ppb_graphics_3d_api.h
index 754eee4..621dca2 100644
--- a/ppapi/thunk/ppb_graphics_3d_api.h
+++ b/ppapi/thunk/ppb_graphics_3d_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "gpu/command_buffer/common/command_buffer.h"
 #include "ppapi/c/dev/ppb_gles_chromium_texture_mapping_dev.h"
 #include "ppapi/c/ppb_graphics_3d.h"
diff --git a/ppapi/thunk/ppb_host_resolver_api.h b/ppapi/thunk/ppb_host_resolver_api.h
index 1dffb92..fe67bd8 100644
--- a/ppapi/thunk/ppb_host_resolver_api.h
+++ b/ppapi/thunk/ppb_host_resolver_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/ppb_host_resolver.h"
 #include "ppapi/thunk/ppapi_thunk_export.h"
 
diff --git a/ppapi/thunk/ppb_host_resolver_private_api.h b/ppapi/thunk/ppb_host_resolver_private_api.h
index deae5186..aacaa84 100644
--- a/ppapi/thunk/ppb_host_resolver_private_api.h
+++ b/ppapi/thunk/ppb_host_resolver_private_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/private/ppb_host_resolver_private.h"
 #include "ppapi/thunk/ppapi_thunk_export.h"
 
diff --git a/ppapi/thunk/ppb_instance_api.h b/ppapi/thunk/ppb_instance_api.h
index e4ffd14..e80ac50 100644
--- a/ppapi/thunk/ppb_instance_api.h
+++ b/ppapi/thunk/ppb_instance_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "build/build_config.h"
 #include "ppapi/c/dev/ppb_url_util_dev.h"
 #include "ppapi/c/pp_bool.h"
diff --git a/ppapi/thunk/ppb_isolated_file_system_private_api.h b/ppapi/thunk/ppb_isolated_file_system_private_api.h
index 40c9fd4..6a4f2257 100644
--- a/ppapi/thunk/ppb_isolated_file_system_private_api.h
+++ b/ppapi/thunk/ppb_isolated_file_system_private_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/private/ppb_isolated_file_system_private.h"
 #include "ppapi/shared_impl/singleton_resource_id.h"
 #include "ppapi/shared_impl/tracked_callback.h"
diff --git a/ppapi/thunk/ppb_message_loop_api.h b/ppapi/thunk/ppb_message_loop_api.h
index 3073f1e..bf1f106a 100644
--- a/ppapi/thunk/ppb_message_loop_api.h
+++ b/ppapi/thunk/ppb_message_loop_api.h
@@ -5,7 +5,7 @@
 #ifndef PPAPI_THUNK_PPB_MESSAGE_LOOP_API_H_
 #define PPAPI_THUNK_PPB_MESSAGE_LOOP_API_H_
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/pp_bool.h"
 #include "ppapi/c/pp_completion_callback.h"
 #include "ppapi/c/pp_stdint.h"
diff --git a/ppapi/thunk/ppb_network_proxy_api.h b/ppapi/thunk/ppb_network_proxy_api.h
index 26a95cb1..fffbb84b 100644
--- a/ppapi/thunk/ppb_network_proxy_api.h
+++ b/ppapi/thunk/ppb_network_proxy_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/pp_instance.h"
 #include "ppapi/shared_impl/singleton_resource_id.h"
 #include "ppapi/thunk/ppapi_thunk_export.h"
diff --git a/ppapi/thunk/ppb_printing_api.h b/ppapi/thunk/ppb_printing_api.h
index fa9e38b..a81ab21 100644
--- a/ppapi/thunk/ppb_printing_api.h
+++ b/ppapi/thunk/ppb_printing_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/dev/ppb_printing_dev.h"
 
 namespace ppapi {
diff --git a/ppapi/thunk/ppb_tcp_server_socket_private_api.h b/ppapi/thunk/ppb_tcp_server_socket_private_api.h
index e342e01..f6d58cc 100644
--- a/ppapi/thunk/ppb_tcp_server_socket_private_api.h
+++ b/ppapi/thunk/ppb_tcp_server_socket_private_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/private/ppb_tcp_server_socket_private.h"
 #include "ppapi/thunk/ppapi_thunk_export.h"
 
diff --git a/ppapi/thunk/ppb_tcp_socket_api.h b/ppapi/thunk/ppb_tcp_socket_api.h
index 9a687f8..beebec3 100644
--- a/ppapi/thunk/ppb_tcp_socket_api.h
+++ b/ppapi/thunk/ppb_tcp_socket_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/ppb_tcp_socket.h"
 #include "ppapi/thunk/ppapi_thunk_export.h"
 
diff --git a/ppapi/thunk/ppb_tcp_socket_private_api.h b/ppapi/thunk/ppb_tcp_socket_private_api.h
index 0794306e..927bd70 100644
--- a/ppapi/thunk/ppb_tcp_socket_private_api.h
+++ b/ppapi/thunk/ppb_tcp_socket_private_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/private/ppb_tcp_socket_private.h"
 #include "ppapi/thunk/ppapi_thunk_export.h"
 
diff --git a/ppapi/thunk/ppb_udp_socket_api.h b/ppapi/thunk/ppb_udp_socket_api.h
index 15b91368..4c09a2e 100644
--- a/ppapi/thunk/ppb_udp_socket_api.h
+++ b/ppapi/thunk/ppb_udp_socket_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/ppb_udp_socket.h"
 #include "ppapi/thunk/ppapi_thunk_export.h"
 
diff --git a/ppapi/thunk/ppb_udp_socket_private_api.h b/ppapi/thunk/ppb_udp_socket_private_api.h
index a248dc01..fa96236 100644
--- a/ppapi/thunk/ppb_udp_socket_private_api.h
+++ b/ppapi/thunk/ppb_udp_socket_private_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/private/ppb_udp_socket_private.h"
 #include "ppapi/thunk/ppapi_thunk_export.h"
 
diff --git a/ppapi/thunk/ppb_url_loader_api.h b/ppapi/thunk/ppb_url_loader_api.h
index b0fe421..2daaa82 100644
--- a/ppapi/thunk/ppb_url_loader_api.h
+++ b/ppapi/thunk/ppb_url_loader_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/ppb_url_loader.h"
 #include "ppapi/c/trusted/ppb_url_loader_trusted.h"
 
diff --git a/ppapi/thunk/ppb_video_capture_api.h b/ppapi/thunk/ppb_video_capture_api.h
index fbc3c64a..7af5710 100644
--- a/ppapi/thunk/ppb_video_capture_api.h
+++ b/ppapi/thunk/ppb_video_capture_api.h
@@ -10,7 +10,7 @@
 #include <string>
 #include <vector>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/dev/ppb_video_capture_dev.h"
 #include "ppapi/c/pp_array_output.h"
 #include "ppapi/c/pp_resource.h"
diff --git a/ppapi/thunk/ppb_video_decoder_dev_api.h b/ppapi/thunk/ppb_video_decoder_dev_api.h
index 1bf58c3..23ffdf9 100644
--- a/ppapi/thunk/ppb_video_decoder_dev_api.h
+++ b/ppapi/thunk/ppb_video_decoder_dev_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/dev/ppb_video_decoder_dev.h"
 
 namespace ppapi {
diff --git a/ppapi/thunk/ppb_websocket_api.h b/ppapi/thunk/ppb_websocket_api.h
index eb07956f..586a0dc5 100644
--- a/ppapi/thunk/ppb_websocket_api.h
+++ b/ppapi/thunk/ppb_websocket_api.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "ppapi/c/pp_completion_callback.h"
 #include "ppapi/c/ppb_websocket.h"
 #include "ppapi/thunk/ppapi_thunk_export.h"
diff --git a/services/device/serial/bluetooth_serial_port_impl.cc b/services/device/serial/bluetooth_serial_port_impl.cc
index 0bcdcb7..9f5c035 100644
--- a/services/device/serial/bluetooth_serial_port_impl.cc
+++ b/services/device/serial/bluetooth_serial_port_impl.cc
@@ -135,12 +135,12 @@
     mojo::ScopedDataPipeProducerHandle producer) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (out_stream_) {
-    mojo::ReportBadMessage("Data pipe producer still open.");
+    receiver_.ReportBadMessage("Data pipe producer still open.");
     return;
   }
 
   if (!bluetooth_socket_) {
-    mojo::ReportBadMessage("No Bluetooth socket.");
+    receiver_.ReportBadMessage("No Bluetooth socket.");
     return;
   }
 
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 5359d3d..19a9e38 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -35247,6 +35247,7 @@
     "gtest_tests": [
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--gtest_filter=-ImportantSitesUtilBrowserTest.DSENotConsideredImportantInRegularMode"
@@ -35294,6 +35295,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -35338,6 +35340,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -35382,6 +35385,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -35426,6 +35430,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -35470,6 +35475,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--git-revision=${got_revision}",
@@ -35524,6 +35530,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--git-revision=${got_revision}"
@@ -35576,6 +35583,7 @@
       {
         "args": [
           "--use-persistent-shell",
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--git-revision=${got_revision}"
@@ -35630,6 +35638,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -35674,6 +35683,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -35721,6 +35731,7 @@
       {
         "args": [
           "--use-persistent-shell",
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -35769,6 +35780,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -35813,6 +35825,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -35857,6 +35870,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -35901,6 +35915,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -35945,6 +35960,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -35997,6 +36013,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--use-persistent-shell"
@@ -36044,6 +36061,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 8dfdea55..f07eab3 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -5086,7 +5086,8 @@
       {
         "args": [
           "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
+          "--recover-devices",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/android.pie_tot.base_unittests.filter"
         ],
         "merge": {
           "args": [
@@ -5943,7 +5944,8 @@
       {
         "args": [
           "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
+          "--recover-devices",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/android.pie_tot.crashpad_tests.filter"
         ],
         "merge": {
           "args": [
@@ -6296,7 +6298,8 @@
         "args": [
           "--use-cmd-decoder=validating",
           "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
+          "--recover-devices",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/android.pie_tot.gl_tests.filter"
         ],
         "merge": {
           "args": [
@@ -6958,7 +6961,8 @@
       {
         "args": [
           "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
+          "--recover-devices",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/android.pie_tot.services_unittests.filter"
         ],
         "merge": {
           "args": [
diff --git a/testing/buildbot/chromium.fuchsia.fyi.json b/testing/buildbot/chromium.fuchsia.fyi.json
index d8cfaf66..6d6abb2d 100644
--- a/testing/buildbot/chromium.fuchsia.fyi.json
+++ b/testing/buildbot/chromium.fuchsia.fyi.json
@@ -4170,7 +4170,7 @@
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.browser_tests.filter",
           "--test-arg=--test-launcher-timeout=60000",
-          "--custom-image=workstation_eng.qemu-x64-release"
+          "--custom-image=workstation_eng.qemu-x64"
         ],
         "merge": {
           "args": [],
@@ -4195,7 +4195,7 @@
           "--test-arg=--disable-gpu",
           "--test-arg=--headless",
           "--test-arg=--ozone-platform=headless",
-          "--custom-image=workstation_eng.qemu-x64-release"
+          "--custom-image=workstation_eng.qemu-x64"
         ],
         "merge": {
           "args": [],
@@ -4217,7 +4217,7 @@
       },
       {
         "args": [
-          "--custom-image=workstation_eng.qemu-x64-release"
+          "--custom-image=workstation_eng.qemu-x64"
         ],
         "merge": {
           "args": [],
@@ -4239,7 +4239,7 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.unit_tests.filter",
-          "--custom-image=workstation_eng.qemu-x64-release"
+          "--custom-image=workstation_eng.qemu-x64"
         ],
         "merge": {
           "args": [],
@@ -4271,7 +4271,7 @@
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--expected-vendor-id",
           "1ae0",
-          "--custom-image=workstation_eng.qemu-x64-release",
+          "--custom-image=workstation_eng.qemu-x64",
           "--expected-device-id",
           "c0de"
         ],
@@ -4308,7 +4308,7 @@
           "-v",
           "--stable-jobs",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_higher_performance_gpu --use-cmd-decoder=validating",
-          "--custom-image=workstation_eng.qemu-x64-release"
+          "--custom-image=workstation_eng.qemu-x64"
         ],
         "isolate_name": "telemetry_gpu_integration_test_fuchsia",
         "merge": {
@@ -4346,7 +4346,7 @@
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
-          "--custom-image=workstation_eng.qemu-x64-release",
+          "--custom-image=workstation_eng.qemu-x64",
           "--git-revision=${got_revision}"
         ],
         "isolate_name": "telemetry_gpu_integration_test_fuchsia",
@@ -4388,7 +4388,7 @@
           "--stable-jobs",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
-          "--custom-image=workstation_eng.qemu-x64-release"
+          "--custom-image=workstation_eng.qemu-x64"
         ],
         "isolate_name": "telemetry_gpu_integration_test_fuchsia",
         "merge": {
@@ -4423,7 +4423,7 @@
           "-v",
           "--stable-jobs",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
-          "--custom-image=workstation_eng.qemu-x64-release"
+          "--custom-image=workstation_eng.qemu-x64"
         ],
         "isolate_name": "telemetry_gpu_integration_test_fuchsia",
         "merge": {
@@ -4458,7 +4458,7 @@
           "-v",
           "--stable-jobs",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
-          "--custom-image=workstation_eng.qemu-x64-release"
+          "--custom-image=workstation_eng.qemu-x64"
         ],
         "isolate_name": "telemetry_gpu_integration_test_fuchsia",
         "merge": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 91219c7..991246a 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -99142,7 +99142,7 @@
       }
     ]
   },
-  "mac-fieldtrial-rel": {
+  "mac-fieldtrial-tester": {
     "gtest_tests": [
       {
         "args": [
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 6a7710b..2806cf0 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -9288,7 +9288,8 @@
               "os": "Ubuntu-18.04"
             }
           ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
         },
         "test": "components_browsertests",
         "test_id_prefix": "ninja://components:components_browsertests/"
@@ -9349,9 +9350,8 @@
               "os": "Ubuntu-18.04"
             }
           ],
-          "quickrun_shards": 30,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 15
+          "shards": 30
         },
         "test": "content_browsertests",
         "test_id_prefix": "ninja://content/test:content_browsertests/"
@@ -21572,7 +21572,8 @@
               "os": "Windows-10-15063"
             }
           ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
         },
         "test": "components_unittests",
         "test_id_prefix": "ninja://components:components_unittests/"
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index c93951d..a82dd26 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -32,6 +32,7 @@
 
   data = [
     "//testing/buildbot/filters/android.emulator.base_unittests.filter",
+    "//testing/buildbot/filters/android.pie_tot.base_unittests.filter",
     "//testing/buildbot/filters/fuchsia.lsan.base_unittests.filter",
   ]
 }
@@ -167,6 +168,7 @@
   data = [
     "//testing/buildbot/filters/android.emulator_11.crashpad_tests.filter",
     "//testing/buildbot/filters/android.emulator_12.crashpad_tests.filter",
+    "//testing/buildbot/filters/android.pie_tot.crashpad_tests.filter",
   ]
 }
 
@@ -213,7 +215,10 @@
 source_set("services_unittests_filters") {
   testonly = true
 
-  data = [ "//testing/buildbot/filters/fuchsia.services_unittests.filter" ]
+  data = [
+    "//testing/buildbot/filters/android.pie_tot.services_unittests.filter",
+    "//testing/buildbot/filters/fuchsia.services_unittests.filter",
+  ]
 }
 
 source_set("ui_base_unittests_filters") {
@@ -257,6 +262,7 @@
     "//testing/buildbot/filters/android.emulator_12.gl_tests.filter",
     "//testing/buildbot/filters/android.emulator_n.gl_tests.filter",
     "//testing/buildbot/filters/android.pie_arm64_rel.gl_tests.filter",
+    "//testing/buildbot/filters/android.pie_tot.gl_tests.filter",
     "//testing/buildbot/filters/android.samsung_a13.gl_tests.filter",
     "//testing/buildbot/filters/android.samsung_a23.gl_tests.filter",
   ]
diff --git a/testing/buildbot/filters/android.pie_tot.base_unittests.filter b/testing/buildbot/filters/android.pie_tot.base_unittests.filter
new file mode 100644
index 0000000..2f8e2140
--- /dev/null
+++ b/testing/buildbot/filters/android.pie_tot.base_unittests.filter
@@ -0,0 +1,2 @@
+# crbug.com/1384173
+-LibunwindstackUnwinderAndroidTest.JavaFunction
diff --git a/testing/buildbot/filters/android.pie_tot.crashpad_tests.filter b/testing/buildbot/filters/android.pie_tot.crashpad_tests.filter
new file mode 100644
index 0000000..acaa76bf
--- /dev/null
+++ b/testing/buildbot/filters/android.pie_tot.crashpad_tests.filter
@@ -0,0 +1,4 @@
+# crbug.com/1384185
+-StartHandlerForSelfTestSuite/StartHandlerForSelfTest.StartHandlerInChild/*
+
+
diff --git a/testing/buildbot/filters/android.pie_tot.gl_tests.filter b/testing/buildbot/filters/android.pie_tot.gl_tests.filter
new file mode 100644
index 0000000..d52ff99c
--- /dev/null
+++ b/testing/buildbot/filters/android.pie_tot.gl_tests.filter
@@ -0,0 +1,19 @@
+# crbug.com/1034007
+-TranslatorVariants/EXTBlendFuncExtendedDrawTest.ESSL1FragColor/0
+-TranslatorVariants/EXTBlendFuncExtendedDrawTest.ESSL1FragColor/1
+-TranslatorVariants/EXTBlendFuncExtendedDrawTest.ESSL1FragData/0
+-TranslatorVariants/EXTBlendFuncExtendedDrawTest.ESSL1FragData/1
+-TranslatorVariants/EXTBlendFuncExtendedES3DrawTest.ES3Conflicts/0
+-TranslatorVariants/EXTBlendFuncExtendedES3DrawTest.ES3Conflicts/1
+-TranslatorVariants/EXTBlendFuncExtendedES3DrawTest.ES3Getters/0
+-TranslatorVariants/EXTBlendFuncExtendedES3DrawTest.ES3Getters/1
+-TranslatorVariants/EXTBlendFuncExtendedES3DrawTest.ES3GettersArray/0
+-TranslatorVariants/EXTBlendFuncExtendedES3DrawTest.ES3GettersArray/1
+-TranslatorVariants/EXTBlendFuncExtendedES3DrawTest.ESSL3BindArrayAsArray/0
+-TranslatorVariants/EXTBlendFuncExtendedES3DrawTest.ESSL3BindArrayAsArray/1
+-TranslatorVariants/EXTBlendFuncExtendedES3DrawTest.ESSL3BindArrayWithSimpleName/0
+-TranslatorVariants/EXTBlendFuncExtendedES3DrawTest.ESSL3BindArrayWithSimpleName/1
+-TranslatorVariants/EXTBlendFuncExtendedES3DrawTest.ESSL3BindSimpleVarAsArrayNoBind/0
+-TranslatorVariants/EXTBlendFuncExtendedES3DrawTest.ESSL3BindSimpleVarAsArrayNoBind/1
+-TranslatorVariants/EXTBlendFuncExtendedES3DrawTest.ESSL3Var/0
+-TranslatorVariants/EXTBlendFuncExtendedES3DrawTest.ESSL3Var/1
diff --git a/testing/buildbot/filters/android.pie_tot.services_unittests.filter b/testing/buildbot/filters/android.pie_tot.services_unittests.filter
new file mode 100644
index 0000000..64ec493f
--- /dev/null
+++ b/testing/buildbot/filters/android.pie_tot.services_unittests.filter
@@ -0,0 +1,4 @@
+# crbug.com/1384180
+-TracingSampleProfilerTest.JoinRunningTracing
+-TracingSampleProfilerTest.OnSampleCompleted
+-TracingSampleProfilerTest.SamplingChildThread
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index 64b0240..d88bb72f 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -508,7 +508,7 @@
   'fuchsia-test-workstation': {
     '$mixin_append': {
       'args': [
-        '--custom-image=workstation_eng.qemu-x64-release',
+        '--custom-image=workstation_eng.qemu-x64',
       ],
     }
   },
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 3bfccf7..c831899 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -144,6 +144,11 @@
   },
   'base_unittests': {
     'modifications': {
+      'ToTAndroid': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/android.pie_tot.base_unittests.filter',
+        ],
+      },
       'android-11-x86-rel': {
         'args': [
           '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator.base_unittests.filter',
@@ -1555,6 +1560,11 @@
   },
   'components_browsertests': {
     'modifications': {
+      'Linux TSan Tests': {
+        'swarming': {
+          'shards': 2,
+        },
+      },
       'android-11-x86-rel': {
         'swarming': {
           'shards': 2,
@@ -1611,6 +1621,12 @@
           '--gtest_filter=-FieldFormatterTest.DifferentLocales',
         ],
       },
+      'win-asan': {
+        # With a single shard seems to hit time limit.
+        'swarming': {
+          'shards': 2,
+        },
+      },
     },
   },
   'compositor_unittests': {
@@ -1656,8 +1672,7 @@
       },
       'Linux TSan Tests': {
         'swarming': {
-          'shards': 15,
-          'quickrun_shards': 30,
+          'shards': 30,
         },
       },
       'Mac ASan 64 Tests (1)': { # https://crbug.com/1200640
@@ -1978,6 +1993,11 @@
       'Mac Builder Next': {
         'experiment_percentage': 100,
       },
+      'ToTAndroid': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/android.pie_tot.crashpad_tests.filter',
+        ],
+      },
       'android-11-x86-rel': {
         'args': [
           '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_11.crashpad_tests.filter',
@@ -2241,6 +2261,11 @@
           '--test-launcher-filter-file=../../testing/buildbot/filters/android.samsung_a23.gl_tests.filter',
         ],
       },
+      'ToTAndroid': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/android.pie_tot.gl_tests.filter', # https://crbug.com/1034007
+        ],
+      },
       'android-11-x86-rel': {
         'args': [
           '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_11.gl_tests.filter',
@@ -3227,6 +3252,11 @@
           'quickrun_shards': 2,
         },
       },
+      'ToTAndroid': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/android.pie_tot.services_unittests.filter',
+        ]
+      },
       'android-11-x86-rel': {
         'args': [
           # TODO(crbug.com/1264654): Fix the failed tests
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 75fbb5d..28dc691 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -1013,6 +1013,9 @@
         'additional_compile_targets': [
           'monochrome_static_initializers',
         ],
+        'args': [
+          '--use-persistent-shell',
+        ],
         'test_suites': {
           'gtest_tests': 'android_pie_rel_gtests',
           # TODO(crbug.com/1111436): Re-enable this if/when additional capacity
@@ -3583,7 +3586,7 @@
           'gtest_tests': 'chromium_mac_gtests',
         },
       },
-      'mac-fieldtrial-rel': {
+      'mac-fieldtrial-tester': {
         'mixins': [
           'mac_12_arm64',
         ],
diff --git a/testing/test.gni b/testing/test.gni
index cf984513..60b6c3f 100644
--- a/testing/test.gni
+++ b/testing/test.gni
@@ -113,6 +113,9 @@
 #      job_policy_ambient_mark_vmo_exec.
 #   fuchsia_package_deps: (Fuchsia, optional) List of fuchsia_component()
 #      targets that this test package contains.
+#   # TODO(crbug/1280705): remove when all tests are migrated to CFv2.
+#   fuchsia_legacy_script_required: (Fuchsia, optional) Whether the old test
+#      scripts are required to run the test target.
 #   is_xctest: (iOS, optional) whether to build the executable as XCTest.
 #      Similar to the GN arg 'enable_run_ios_unittests_with_xctest' but
 #      for build targets.
@@ -458,6 +461,12 @@
       output_conversion = "json"
     }
 
+    use_v2_script = use_v2_script_default
+    if (defined(invoker.fuchsia_legacy_script_required) &&
+        invoker.fuchsia_legacy_script_required) {
+      use_v2_script = false
+    }
+
     _test_runner_shard =
         "//build/config/fuchsia/test/elf_test_runner.shard.test-cml"
     if (defined(invoker.test_runner_shard)) {
@@ -555,6 +564,7 @@
                                "data_deps",
                                "package_deps",
                                "use_test_server",
+                               "use_v2_script",
                              ])
 
       is_test_exe = true
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 50453e4..39265b3 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -3086,6 +3086,8 @@
     "CombinedPowerExperiment": [
         {
             "platforms": [
+                "android",
+                "android_weblayer",
                 "chromeos",
                 "chromeos_lacros",
                 "fuchsia",
@@ -3111,36 +3113,6 @@
                         "ReduceCpuUtilization",
                         "RemoveCanceledTasksInTaskQueue2",
                         "V8DelayMemoryReducer"
-                    ],
-                    "disable_features": [
-                        "FontManagerEarlyInit"
-                    ]
-                }
-            ]
-        },
-        {
-            "platforms": [
-                "android",
-                "android_weblayer"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "params": {
-                        "delay": "30s"
-                    },
-                    "enable_features": [
-                        "AlignWakeUps",
-                        "AlwaysAbandonScheduledTask",
-                        "CacheFeatureOverrideState",
-                        "DelayFirstParkingOfStrings",
-                        "EarlyExitOnNoopClassOrStyleChange",
-                        "ExplicitHighResolutionTimerWin",
-                        "MessagePumpMacDelayedWorkOptimizations",
-                        "NoWakeUpsForCanceledTasks",
-                        "ReduceCpuUtilization",
-                        "RemoveCanceledTasksInTaskQueue2",
-                        "V8DelayMemoryReducer"
                     ]
                 }
             ]
@@ -7265,38 +7237,6 @@
             ]
         }
     ],
-    "NtpRealboxDesignUpdates": [
-        {
-            "platforms": [
-                "chromeos",
-                "chromeos_lacros",
-                "fuchsia",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "params": {
-                        "RealboxMatchSearchboxThemeParam": "0"
-                    },
-                    "enable_features": [
-                        "NtpRealboxMatchSearchboxTheme"
-                    ]
-                },
-                {
-                    "name": "Enabled_Rounded_Corners",
-                    "params": {
-                        "RealboxMatchSearchboxThemeParam": "1"
-                    },
-                    "enable_features": [
-                        "NtpRealboxMatchSearchboxTheme"
-                    ]
-                }
-            ]
-        }
-    ],
     "NtpRealboxPedals": [
         {
             "platforms": [
@@ -7317,6 +7257,26 @@
             ]
         }
     ],
+    "NtpRealboxRundedCorners": [
+        {
+            "platforms": [
+                "chromeos",
+                "chromeos_lacros",
+                "fuchsia",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "NtpRealboxRoundedCorners"
+                    ]
+                }
+            ]
+        }
+    ],
     "NtpRemoveScrim": [
         {
             "platforms": [
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
index a9e44ab..ccb820f 100644
--- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl
+++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -482,6 +482,7 @@
       ExcludeInvalidSameParty
       ExcludeSamePartyCrossPartyContext
       ExcludeDomainNonASCII
+      ExcludeThirdPartyCookieBlockedInFirstPartySet
 
   type CookieWarningReason extends string
     enum
@@ -5479,6 +5480,9 @@
       SameSiteNoneInsecure
       # The cookie was not stored due to user preferences.
       UserPreferences
+      # The cookie was blocked by third-party cookie blocking between sites in
+      # the same First-Party Set.
+      ThirdPartyBlockedInFirstPartySet
       # The syntax of the Set-Cookie header of the response was invalid.
       SyntaxError
       # The scheme of the connection is not allowed to store cookies.
@@ -5543,6 +5547,9 @@
       SameSiteNoneInsecure
       # The cookie was not sent due to user preferences.
       UserPreferences
+      # The cookie was blocked by third-party cookie blocking between sites in
+      # the same First-Party Set.
+      ThirdPartyBlockedInFirstPartySet
       # An unknown error was encountered when trying to send this cookie.
       UnknownError
       # The cookie had the "SameSite=Strict" attribute but came from a response
diff --git a/third_party/blink/renderer/core/dom/build.gni b/third_party/blink/renderer/core/dom/build.gni
index b2789ed..664811e 100644
--- a/third_party/blink/renderer/core/dom/build.gni
+++ b/third_party/blink/renderer/core/dom/build.gni
@@ -243,6 +243,7 @@
   "scripted_idle_task_controller.h",
   "shadow_root.cc",
   "shadow_root.h",
+  "shadow_including_tree_order_traversal.h",
   "sink_document.cc",
   "sink_document.h",
   "slot_assignment.cc",
@@ -312,6 +313,7 @@
   "range_test.cc",
   "scripted_animation_controller_test.cc",
   "scripted_idle_task_controller_test.cc",
+  "shadow_including_tree_order_traversal_test.cc",
   "slot_assignment_test.cc",
   "space_split_string_test.cc",
   "static_range_test.cc",
diff --git a/third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal.h b/third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal.h
new file mode 100644
index 0000000..1b9c560
--- /dev/null
+++ b/third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal.h
@@ -0,0 +1,76 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SHADOW_INCLUDING_TREE_ORDER_TRAVERSAL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SHADOW_INCLUDING_TREE_ORDER_TRAVERSAL_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/dom/node.h"
+#include "third_party/blink/renderer/core/dom/shadow_root.h"
+#include "third_party/blink/renderer/core/dom/traversal_range.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+// Does a traversal of the tree in "shadow-including tree order", see
+// https://dom.spec.whatwg.org/#concept-shadow-including-tree-order for
+// definition.
+class CORE_EXPORT ShadowIncludingTreeOrderTraversal {
+  STATIC_ONLY(ShadowIncludingTreeOrderTraversal);
+
+ public:
+  using TraversalNodeType = Node;
+
+  static Node* Next(const Node& current, const Node* stay_within);
+  static Node* FirstWithin(const Node& current);
+
+  static TraversalDescendantRange<ShadowIncludingTreeOrderTraversal>
+  DescendantsOf(const Node&);
+
+ private:
+  static Node* TraverseParent(const Node& current);
+  static Node* TraverseNextSibling(const Node& current);
+};
+
+inline Node* ShadowIncludingTreeOrderTraversal::Next(const Node& current,
+                                                     const Node* stay_within) {
+  if (Node* first_child = FirstWithin(current))
+    return first_child;
+  for (const Node* node = &current; node && node != stay_within;
+       node = TraverseParent(*node)) {
+    if (Node* sibling = TraverseNextSibling(*node))
+      return sibling;
+  }
+  return nullptr;
+}
+
+inline Node* ShadowIncludingTreeOrderTraversal::FirstWithin(
+    const Node& current) {
+  if (ShadowRoot* shadow_root = current.GetShadowRoot())
+    return shadow_root;
+  return current.firstChild();
+}
+
+inline TraversalDescendantRange<ShadowIncludingTreeOrderTraversal>
+ShadowIncludingTreeOrderTraversal::DescendantsOf(const Node& root) {
+  return TraversalDescendantRange<ShadowIncludingTreeOrderTraversal>(&root);
+}
+
+inline Node* ShadowIncludingTreeOrderTraversal::TraverseParent(
+    const Node& current) {
+  return current.ParentOrShadowHostNode();
+}
+
+inline Node* ShadowIncludingTreeOrderTraversal::TraverseNextSibling(
+    const Node& current) {
+  if (Node* sibling = current.nextSibling())
+    return sibling;
+  if (current.IsShadowRoot())
+    return current.ParentOrShadowHostNode()->firstChild();
+  return nullptr;
+}
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SHADOW_INCLUDING_TREE_ORDER_TRAVERSAL_H_
diff --git a/third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal_test.cc b/third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal_test.cc
new file mode 100644
index 0000000..71831dc
--- /dev/null
+++ b/third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal_test.cc
@@ -0,0 +1,145 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal.h"
+
+#include "testing/gmock/include/gmock/gmock-matchers.h"
+#include "third_party/blink/renderer/core/dom/node_traversal.h"
+#include "third_party/blink/renderer/core/dom/text.h"
+#include "third_party/blink/renderer/core/html/html_element.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+
+namespace blink {
+namespace {
+using ShadowIncludingTreeOrderTraversalTest = PageTestBase;
+
+void RemoveWhiteSpaceOnlyTextNodes(ContainerNode& container) {
+  HeapVector<Member<Text>> to_remove;
+  for (Node& descendant : NodeTraversal::DescendantsOf(container)) {
+    if (auto* text = DynamicTo<Text>(&descendant);
+        text && text->ContainsOnlyWhitespaceOrEmpty()) {
+      to_remove.push_back(text);
+    }
+  }
+
+  for (Text* text : to_remove)
+    text->remove();
+}
+
+TEST_F(ShadowIncludingTreeOrderTraversalTest, Next) {
+  GetDocument().body()->setInnerHTMLWithDeclarativeShadowDOMForTesting(R"HTML(
+    <div id="c0">
+      <div id="c00">
+        <template shadowroot="open"></template>
+      </div>
+      <div id="c01">
+        <template shadowroot="open">
+          <div id="s0"></div>
+          <div id="s1">
+            <div id="s10"></div>
+          </div>
+        </template>
+      </div>
+      <div id="c02">
+        <div id="c020"></div>
+        <div id="c021" slot="t01"></div>
+        <template shadowroot="open">
+          <div id="t0">
+            <slot id="t00"></slot>
+            <slot id="t01"></slot>
+          </div>
+        </template>
+      </div>
+    </div>
+    <div id="c1"></div>
+  )HTML");
+  RemoveWhiteSpaceOnlyTextNodes(*GetDocument().body());
+  auto* c0 = GetElementById("c0");
+  auto* c1 = GetElementById("c1");
+  auto* c00 = GetElementById("c00");
+  auto* c01 = GetElementById("c01");
+  auto* c02 = GetElementById("c02");
+  auto* c020 = GetElementById("c020");
+  auto* c021 = GetElementById("c021");
+
+  ShadowRoot* shadow_root_0 = c00->GetShadowRoot();
+  ASSERT_TRUE(shadow_root_0);
+
+  ShadowRoot* shadow_root_1 = c01->GetShadowRoot();
+  ASSERT_TRUE(shadow_root_1);
+  RemoveWhiteSpaceOnlyTextNodes(*shadow_root_1);
+  auto* s0 = shadow_root_1->getElementById("s0");
+  auto* s1 = shadow_root_1->getElementById("s1");
+  auto* s10 = shadow_root_1->getElementById("s10");
+
+  ShadowRoot* shadow_root_2 = c02->GetShadowRoot();
+  ASSERT_TRUE(shadow_root_2);
+  RemoveWhiteSpaceOnlyTextNodes(*shadow_root_2);
+  auto* t0 = shadow_root_2->getElementById("t0");
+  auto* t00 = shadow_root_2->getElementById("t00");
+  auto* t01 = shadow_root_2->getElementById("t01");
+
+  // Test iteration order using Next.
+  EXPECT_EQ(ShadowIncludingTreeOrderTraversal::Next(*GetDocument().body(),
+                                                    &GetDocument()),
+            c0);
+  EXPECT_EQ(ShadowIncludingTreeOrderTraversal::Next(*c0, &GetDocument()), c00);
+  EXPECT_EQ(ShadowIncludingTreeOrderTraversal::Next(*c00, &GetDocument()),
+            shadow_root_0);
+  EXPECT_EQ(
+      ShadowIncludingTreeOrderTraversal::Next(*shadow_root_0, &GetDocument()),
+      c01);
+  EXPECT_EQ(ShadowIncludingTreeOrderTraversal::Next(*c01, &GetDocument()),
+            shadow_root_1);
+  EXPECT_EQ(
+      ShadowIncludingTreeOrderTraversal::Next(*shadow_root_1, &GetDocument()),
+      s0);
+  EXPECT_EQ(ShadowIncludingTreeOrderTraversal::Next(*s0, &GetDocument()), s1);
+  EXPECT_EQ(ShadowIncludingTreeOrderTraversal::Next(*s1, &GetDocument()), s10);
+  EXPECT_EQ(ShadowIncludingTreeOrderTraversal::Next(*s10, &GetDocument()), c02);
+  EXPECT_EQ(ShadowIncludingTreeOrderTraversal::Next(*c02, &GetDocument()),
+            shadow_root_2);
+  EXPECT_EQ(
+      ShadowIncludingTreeOrderTraversal::Next(*shadow_root_2, &GetDocument()),
+      t0);
+  EXPECT_EQ(ShadowIncludingTreeOrderTraversal::Next(*t0, &GetDocument()), t00);
+  EXPECT_EQ(ShadowIncludingTreeOrderTraversal::Next(*t00, &GetDocument()), t01);
+  EXPECT_EQ(ShadowIncludingTreeOrderTraversal::Next(*t01, &GetDocument()),
+            c020);
+  EXPECT_EQ(ShadowIncludingTreeOrderTraversal::Next(*c020, &GetDocument()),
+            c021);
+  EXPECT_EQ(ShadowIncludingTreeOrderTraversal::Next(*c021, &GetDocument()), c1);
+
+  // c1 is not in c0's tree, so this returns nullptr.
+  EXPECT_EQ(ShadowIncludingTreeOrderTraversal::Next(*c021, c0), nullptr);
+}
+
+TEST_F(ShadowIncludingTreeOrderTraversalTest, DescendantsOf) {
+  GetDocument().body()->setInnerHTMLWithDeclarativeShadowDOMForTesting(R"HTML(
+    <div id="a0">
+      <div id="a00"></div>
+      <div id="a01"></div>
+    </div>
+    <div id="a1">
+      <template shadowroot="open" id="sr1">
+        <div id="b0">
+          <div id="b00"></div>
+        </div>
+      </template>
+      <div id="a10">
+    </div>
+    <div id="a2"></div>
+  )HTML");
+
+  Vector<String> traversed_ids;
+  for (const Node& node : ShadowIncludingTreeOrderTraversal::DescendantsOf(
+           *GetDocument().body())) {
+    if (auto* el = DynamicTo<Element>(node))
+      traversed_ids.push_back(el->GetIdAttribute());
+  }
+  EXPECT_THAT(traversed_ids, ::testing::ElementsAre("a0", "a00", "a01", "a1",
+                                                    "b0", "b00", "a10", "a2"));
+}
+}  // namespace
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config.cc b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config.cc
index 80178620..f9e6c6d 100644
--- a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config.cc
+++ b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config.cc
@@ -6,8 +6,12 @@
 
 namespace blink {
 
-FencedFrameInnerConfig::FencedFrameInnerConfig(const String& src)
-    : url_attribute_visibility_(AttributeVisibility::kOpaque), url_(src) {}
+FencedFrameInnerConfig* FencedFrameInnerConfig::Create(const String& url) {
+  return MakeGarbageCollected<FencedFrameInnerConfig>(url);
+}
+
+FencedFrameInnerConfig::FencedFrameInnerConfig(const String& url)
+    : url_(url), url_attribute_visibility_(AttributeVisibility::kTransparent) {}
 
 V8UnionOpaquePropertyOrUSVString* FencedFrameInnerConfig::url() const {
   return Get<Attribute::kURL>();
diff --git a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config.h b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config.h
index 25fe777..e37f935 100644
--- a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config.h
+++ b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config.h
@@ -24,6 +24,12 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
+  enum class Attribute {
+    kURL,
+    kWidth,
+    kHeight,
+  };
+
   // Note this visibility has different semantics from
   // FencedFrameURLMapping::VisibilityToEmbedder and
   // FencedFrameURLMapping::VisibilityToContent. Here `AttributeVisibility`
@@ -37,7 +43,11 @@
     kNull,
   };
 
-  explicit FencedFrameInnerConfig(const String& src);
+  // Create an inner config with a given url, the url will be transparent.
+  static FencedFrameInnerConfig* Create(const String& url);
+
+  // Construct an inner config with a given url, the url will be transparent.
+  explicit FencedFrameInnerConfig(const String& url);
   FencedFrameInnerConfig(const FencedFrameInnerConfig&) = delete;
   FencedFrameInnerConfig& operator=(const FencedFrameInnerConfig&) = delete;
 
@@ -45,20 +55,27 @@
   V8UnionOpaquePropertyOrUnsignedLong* width() const;
   V8UnionOpaquePropertyOrUnsignedLong* height() const;
 
+  // Get attribute's value ignoring visibility.
+  template <Attribute attr>
+  auto GetValueIgnoringVisibility() const {
+    if constexpr (attr == Attribute::kURL) {
+      return url_;
+    } else if constexpr (attr == Attribute::kWidth) {
+      return width_;
+    } else if constexpr (attr == Attribute::kHeight) {
+      return height_;
+    }
+    NOTREACHED();
+  }
+
  private:
-  enum class Attribute {
-    kURL,
-    kWidth,
-    kHeight,
-  };
-
-  AttributeVisibility url_attribute_visibility_ = AttributeVisibility::kNull;
-  AttributeVisibility size_attribute_visibility_ = AttributeVisibility::kNull;
-
   KURL url_;
   uint32_t width_;
   uint32_t height_;
 
+  AttributeVisibility url_attribute_visibility_ = AttributeVisibility::kNull;
+  AttributeVisibility size_attribute_visibility_ = AttributeVisibility::kNull;
+
   // Attribute's union type based on its value type.
   template <typename T>
   struct AttributeUnion;
diff --git a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config.idl b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config.idl
index 96b6bbd..2b72433c 100644
--- a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config.idl
+++ b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config.idl
@@ -13,6 +13,7 @@
   // of FencedFrameURLMapping::FencedFrameConfiguration.
   // For more information on why this is needed please see:
   // https://github.com/WICG/fenced-frame/issues/48#issuecomment-1245809738
+  constructor(USVString url);
   readonly attribute FencedFrameInnerConfigURL? url;
   readonly attribute FencedFrameInnerConfigSize? width;
   readonly attribute FencedFrameInnerConfigSize? height;
diff --git a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config_test.cc b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config_test.cc
index fa392ce..28a6570 100644
--- a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config_test.cc
+++ b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_inner_config_test.cc
@@ -25,14 +25,35 @@
 };
 
 TEST_F(FencedFrameInnerConfigTest, FencedFrameInnerConfigConstructionWithURL) {
-  FencedFrameInnerConfig inner_config("https://example.com");
+  String url = "https://example.com/";
+  FencedFrameInnerConfig inner_config(url);
 
   EXPECT_NE(inner_config.url(), nullptr);
-  EXPECT_TRUE(inner_config.url()->IsOpaqueProperty());
-  EXPECT_FALSE(inner_config.url()->IsUSVString());
+  EXPECT_FALSE(inner_config.url()->IsOpaqueProperty());
+  EXPECT_TRUE(inner_config.url()->IsUSVString());
+  EXPECT_EQ(inner_config.url()->GetAsUSVString(), url);
+  EXPECT_EQ(inner_config.GetValueIgnoringVisibility<
+                FencedFrameInnerConfig::Attribute::kURL>(),
+            url);
 
   EXPECT_EQ(inner_config.width(), nullptr);
   EXPECT_EQ(inner_config.height(), nullptr);
 }
 
+TEST_F(FencedFrameInnerConfigTest, FencedFrameInnerConfigCreateWithURL) {
+  String url = "https://example.com/";
+  FencedFrameInnerConfig* inner_config = FencedFrameInnerConfig::Create(url);
+
+  EXPECT_NE(inner_config->url(), nullptr);
+  EXPECT_FALSE(inner_config->url()->IsOpaqueProperty());
+  EXPECT_TRUE(inner_config->url()->IsUSVString());
+  EXPECT_EQ(inner_config->url()->GetAsUSVString(), url);
+  EXPECT_EQ(inner_config->GetValueIgnoringVisibility<
+                FencedFrameInnerConfig::Attribute::kURL>(),
+            url);
+
+  EXPECT_EQ(inner_config->width(), nullptr);
+  EXPECT_EQ(inner_config->height(), nullptr);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc b/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc
index 7b05132e..359fbfd9 100644
--- a/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc
+++ b/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc
@@ -140,6 +140,7 @@
   HTMLFrameOwnerElement::Trace(visitor);
   visitor->Trace(frame_delegate_);
   visitor->Trace(resize_observer_);
+  visitor->Trace(inner_config_);
 }
 
 void HTMLFencedFrameElement::DisconnectContentFrame() {
@@ -284,6 +285,18 @@
   return nullptr;
 }
 
+void HTMLFencedFrameElement::setInnerConfig(FencedFrameInnerConfig* config) {
+  inner_config_ = config;
+
+  if (inner_config_) {
+    // Navigate to the specified url in the installed inner config.
+    DCHECK(inner_config_->url());
+    KURL url = inner_config_->GetValueIgnoringVisibility<
+        FencedFrameInnerConfig::Attribute::kURL>();
+    Navigate(url);
+  }
+}
+
 // static
 bool HTMLFencedFrameElement::canLoadOpaqueURL(ScriptState* script_state) {
   if (!script_state->ContextIsValid())
@@ -392,7 +405,19 @@
 
     mode_ = new_mode;
   } else if (params.name == html_names::kSrcAttr) {
-    Navigate();
+    if (inner_config_) {
+      DCHECK(inner_config_->url());
+      GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+          mojom::blink::ConsoleMessageSource::kJavaScript,
+          mojom::blink::ConsoleMessageLevel::kWarning,
+          "Changing the `src` attribute on a fenced frame has no effect after "
+          "it has already been installed an inner config with a specified "
+          "url."));
+      return;
+    }
+
+    KURL url = GetNonEmptyURLAttribute(html_names::kSrcAttr);
+    Navigate(url);
   } else {
     HTMLFrameOwnerElement::ParseAttribute(params);
   }
@@ -423,7 +448,7 @@
   }
 }
 
-void HTMLFencedFrameElement::Navigate() {
+void HTMLFencedFrameElement::Navigate(const KURL& url) {
   TRACE_EVENT0("navigation", "HTMLFencedFrameElement::Navigate");
   if (!isConnected())
     return;
@@ -437,8 +462,6 @@
   if (!frame_delegate_)
     return;
 
-  KURL url = GetNonEmptyURLAttribute(html_names::kSrcAttr);
-
   if (url.IsEmpty())
     return;
 
@@ -513,7 +536,16 @@
   freeze_mode_attribute_ = true;
 
   frame_delegate_ = FencedFrameDelegate::Create(this);
-  Navigate();
+
+  KURL url = GetNonEmptyURLAttribute(html_names::kSrcAttr);
+  if (inner_config_) {
+    // If there is an inner config, the url will be retrieved from it.
+    DCHECK(inner_config_->url());
+    url = inner_config_->GetValueIgnoringVisibility<
+        FencedFrameInnerConfig::Attribute::kURL>();
+  }
+
+  Navigate(url);
 }
 
 void HTMLFencedFrameElement::AttachLayoutTree(AttachContext& context) {
diff --git a/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h b/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h
index 29b782d..323a2e2 100644
--- a/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h
+++ b/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h
@@ -105,8 +105,8 @@
   // while keeping the inner frame size unchanged.
   HTMLIFrameElement* InnerIFrameElement() const;
 
-  FencedFrameInnerConfig* innerConfig() const { return nullptr; }
-  void setInnerConfig(FencedFrameInnerConfig* config) const {}
+  FencedFrameInnerConfig* innerConfig() const { return inner_config_; }
+  void setInnerConfig(FencedFrameInnerConfig* config);
   // Web-exposed API that returns whether an opaque-ads fenced frame would be
   // allowed to be created in the current active document of this node.
   // Checks the following criteria:
@@ -120,7 +120,7 @@
  private:
   // This method will only navigate the underlying frame if the element
   // `isConnected()`. It will be deferred if the page is currently prerendering.
-  void Navigate();
+  void Navigate(const KURL& url);
 
   // Delegate creation will be deferred if the page is currently prerendering.
   void CreateDelegateAndNavigate();
@@ -170,6 +170,7 @@
   // `kFencedFrameMandatoryUnsandboxedFlags`.
   Member<FencedFrameDelegate> frame_delegate_;
   Member<ResizeObserver> resize_observer_;
+  Member<FencedFrameInnerConfig> inner_config_;
   // See |FrozenFrameSize| above. Stored in CSS pixel (without DSF multiplied.)
   absl::optional<PhysicalSize> frozen_frame_size_;
   absl::optional<PhysicalRect> content_rect_;
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 0fcfae7b..ce3ddac9 100644
--- a/third_party/blink/renderer/core/html/html_anchor_element.cc
+++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -54,6 +54,7 @@
 #include "third_party/blink/renderer/core/navigation_api/navigation_api.h"
 #include "third_party/blink/renderer/core/page/chrome_client.h"
 #include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
@@ -262,6 +263,11 @@
         }
       }
     }
+    if (auto* document_rules =
+            DocumentSpeculationRules::FromIfExists(GetDocument())) {
+      document_rules->HrefAttributeChanged(this, params.old_value,
+                                           params.new_value);
+    }
     InvalidateCachedVisitedLinkHash();
     LogUpdateAttributeIfIsolatedWorldAndInDocument("a", params);
   } else if (params.name == html_names::kNameAttr ||
@@ -600,9 +606,27 @@
     AnchorElementMetricsSender::From(top_document)->AddAnchorElement(*this);
   }
 
+  if (IsLink()) {
+    if (auto* document_rules =
+            DocumentSpeculationRules::FromIfExists(GetDocument())) {
+      document_rules->LinkInserted(this);
+    }
+  }
+
   return request;
 }
 
+void HTMLAnchorElement::RemovedFrom(ContainerNode& insertion_point) {
+  HTMLElement::RemovedFrom(insertion_point);
+
+  if (IsLink()) {
+    if (auto* document_rules =
+            DocumentSpeculationRules::FromIfExists(GetDocument())) {
+      document_rules->LinkRemoved(this);
+    }
+  }
+}
+
 void HTMLAnchorElement::Trace(Visitor* visitor) const {
   visitor->Trace(rel_list_);
   HTMLElement::Trace(visitor);
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 162c874..f96d873 100644
--- a/third_party/blink/renderer/core/html/html_anchor_element.h
+++ b/third_party/blink/renderer/core/html/html_anchor_element.h
@@ -118,6 +118,7 @@
   bool draggable() const final;
   bool IsInteractiveContent() const final;
   InsertionNotificationRequest InsertedInto(ContainerNode&) override;
+  void RemovedFrom(ContainerNode&) override;
   void HandleClick(Event&);
 
   unsigned link_relations_ : 31;
diff --git a/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc b/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc
index c000c1c..77188ceb 100644
--- a/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc
+++ b/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_url_pattern_init.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/html/html_anchor_element.h"
 #include "third_party/blink/renderer/core/url_pattern/url_pattern.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/member.h"
@@ -28,7 +29,7 @@
       : clauses_(std::move(clauses)) {}
   ~Conjunction() override = default;
 
-  bool Matches(const Element& el) const override {
+  bool Matches(const HTMLAnchorElement& el) const override {
     return base::ranges::all_of(clauses_, [&](DocumentRulePredicate* clause) {
       return clause->Matches(el);
     });
@@ -70,7 +71,7 @@
       : clauses_(std::move(clauses)) {}
   ~Disjunction() override = default;
 
-  bool Matches(const Element& el) const override {
+  bool Matches(const HTMLAnchorElement& el) const override {
     return base::ranges::any_of(clauses_, [&](DocumentRulePredicate* clause) {
       return clause->Matches(el);
     });
@@ -111,7 +112,7 @@
   explicit Negation(DocumentRulePredicate* clause) : clause_(clause) {}
   ~Negation() override = default;
 
-  bool Matches(const Element& el) const override {
+  bool Matches(const HTMLAnchorElement& el) const override {
     return !clause_->Matches(el);
   }
 
@@ -151,7 +152,7 @@
       : patterns_(std::move(patterns)) {}
   ~URLPatternPredicate() override = default;
 
-  bool Matches(const Element& el) const override {
+  bool Matches(const HTMLAnchorElement& el) const override {
     // Let href be the result of running el’s href getter steps.
     const KURL href = el.HrefURL();
     // For each pattern of predicate’s patterns:
diff --git a/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.h b/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.h
index f940f37..d98fe8e 100644
--- a/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.h
+++ b/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.h
@@ -13,7 +13,7 @@
 
 namespace blink {
 
-class Element;
+class HTMLAnchorElement;
 class ExceptionState;
 class JSONObject;
 class KURL;
@@ -32,7 +32,7 @@
   // always returns true).
   static DocumentRulePredicate* MakeDefaultPredicate();
 
-  virtual bool Matches(const Element& link) const = 0;
+  virtual bool Matches(const HTMLAnchorElement& link) const = 0;
 
   // Methods for testing.
   enum class Type { kAnd, kOr, kNot, kURLPatterns };
diff --git a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
index 2daed8f..f69c083 100644
--- a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
+++ b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
@@ -9,10 +9,15 @@
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
+#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
+#include "third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal.h"
 #include "third_party/blink/renderer/core/execution_context/agent.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/html/html_anchor_element.h"
+#include "third_party/blink/renderer/core/html/html_area_element.h"
 #include "third_party/blink/renderer/core/loader/speculation_rule_loader.h"
+#include "third_party/blink/renderer/core/speculation_rules/document_rule_predicate.h"
 #include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
 #include "third_party/blink/renderer/platform/weborigin/referrer.h"
 #include "third_party/blink/renderer/platform/weborigin/security_policy.h"
@@ -97,6 +102,10 @@
 void DocumentSpeculationRules::AddRuleSet(SpeculationRuleSet* rule_set) {
   DCHECK(!base::Contains(rule_sets_, rule_set));
   rule_sets_.push_back(rule_set);
+  if (rule_set->has_document_rule()) {
+    InitializeIfNecessary();
+    InvalidateAllLinks();
+  }
   QueueUpdateSpeculationCandidates();
 }
 
@@ -104,6 +113,8 @@
   auto* it = base::ranges::remove(rule_sets_, rule_set);
   DCHECK(it != rule_sets_.end()) << "rule set was removed without existing";
   rule_sets_.erase(it, rule_sets_.end());
+  if (rule_set->has_document_rule())
+    InvalidateAllLinks();
   QueueUpdateSpeculationCandidates();
 }
 
@@ -117,11 +128,45 @@
   speculation_rule_loaders_.erase(speculation_rule_loader);
 }
 
+void DocumentSpeculationRules::LinkInserted(HTMLAnchorElement* link) {
+  DCHECK(link->IsLink());
+  AddLink(link);
+  QueueUpdateSpeculationCandidates();
+}
+
+void DocumentSpeculationRules::LinkRemoved(HTMLAnchorElement* link) {
+  DCHECK(link->IsLink());
+  RemoveLink(link);
+  QueueUpdateSpeculationCandidates();
+}
+
+void DocumentSpeculationRules::HrefAttributeChanged(
+    HTMLAnchorElement* link,
+    const AtomicString& old_value,
+    const AtomicString& new_value) {
+  DCHECK_NE(old_value, new_value);
+
+  if (!link->isConnected())
+    return;
+
+  if (old_value.IsNull())
+    AddLink(link);
+  else if (new_value.IsNull())
+    RemoveLink(link);
+  else
+    InvalidateLink(link);
+
+  QueueUpdateSpeculationCandidates();
+}
+
 void DocumentSpeculationRules::Trace(Visitor* visitor) const {
   Supplement::Trace(visitor);
   visitor->Trace(rule_sets_);
   visitor->Trace(host_);
   visitor->Trace(speculation_rule_loaders_);
+  visitor->Trace(matched_links_);
+  visitor->Trace(unmatched_links_);
+  visitor->Trace(pending_links_);
 }
 
 mojom::blink::SpeculationHost* DocumentSpeculationRules::GetHost() {
@@ -225,7 +270,150 @@
     }
   }
 
+  // Add candidates derived from document rule predicates.
+  AddLinkBasedSpeculationCandidates(candidates);
+
   host->UpdateSpeculationCandidates(std::move(candidates));
 }
 
+void DocumentSpeculationRules::AddLinkBasedSpeculationCandidates(
+    Vector<mojom::blink::SpeculationCandidatePtr>& candidates) {
+  // Match all the unmatched
+  while (!pending_links_.empty()) {
+    auto it = pending_links_.begin();
+    HTMLAnchorElement* link = *it;
+    Vector<mojom::blink::SpeculationCandidatePtr> link_candidates;
+    ExecutionContext* execution_context =
+        GetSupplementable()->GetExecutionContext();
+    DCHECK(execution_context);
+
+    const auto push_link_candidates =
+        [&link, &link_candidates](
+            mojom::blink::SpeculationAction action,
+            const HeapVector<Member<SpeculationRule>>& speculation_rules) {
+          for (SpeculationRule* rule : speculation_rules) {
+            if (!rule->predicate())
+              continue;
+            if (!rule->predicate()->Matches(*link))
+              continue;
+
+            // TODO(crbug.com/1371522): This should be computed based on the
+            // speculation rule's referrer policy or the link's referrer
+            // policy, and the execution context's referrer url.
+            mojom::blink::ReferrerPtr referrer = mojom::blink::Referrer::New(
+                KURL(), network::mojom::ReferrerPolicy::kNever);
+
+            // TODO(crbug.com/1371522): We should be generating a target hint
+            // based on the link's target.
+            mojom::blink::SpeculationCandidatePtr candidate =
+                mojom::blink::SpeculationCandidate::New(
+                    link->HrefURL(), action, std::move(referrer),
+                    rule->requires_anonymous_client_ip_when_cross_origin(),
+                    rule->target_browsing_context_name_hint().value_or(
+                        mojom::blink::SpeculationTargetHint::kNoHint));
+            link_candidates.push_back(std::move(candidate));
+          }
+        };
+
+    for (SpeculationRuleSet* rule_set : rule_sets_) {
+      if (RuntimeEnabledFeatures::SpeculationRulesPrefetchProxyEnabled(
+              execution_context)) {
+        push_link_candidates(mojom::blink::SpeculationAction::kPrefetch,
+                             rule_set->prefetch_rules());
+      }
+
+      if (RuntimeEnabledFeatures::
+              SpeculationRulesPrefetchWithSubresourcesEnabled(
+                  execution_context)) {
+        push_link_candidates(
+            mojom::blink::SpeculationAction::kPrefetchWithSubresources,
+            rule_set->prefetch_with_subresources_rules());
+      }
+
+      if (RuntimeEnabledFeatures::Prerender2Enabled(execution_context)) {
+        push_link_candidates(mojom::blink::SpeculationAction::kPrerender,
+                             rule_set->prerender_rules());
+      }
+    }
+
+    if (!link_candidates.empty())
+      matched_links_.Set(link, std::move(link_candidates));
+    else
+      unmatched_links_.insert(link);
+
+    pending_links_.erase(it);
+  }
+
+  for (auto& it : matched_links_) {
+    for (const auto& candidate : it.value) {
+      candidates.push_back(candidate.Clone());
+    }
+  }
+}
+
+void DocumentSpeculationRules::InitializeIfNecessary() {
+  if (initialized_)
+    return;
+  initialized_ = true;
+  for (Node& node :
+       ShadowIncludingTreeOrderTraversal::DescendantsOf(*GetSupplementable())) {
+    if (!node.IsLink())
+      continue;
+    if (auto* anchor = DynamicTo<HTMLAnchorElement>(node))
+      pending_links_.insert(anchor);
+    else if (auto* area = DynamicTo<HTMLAreaElement>(node))
+      pending_links_.insert(area);
+  }
+}
+
+void DocumentSpeculationRules::AddLink(HTMLAnchorElement* link) {
+  DCHECK(link->IsLink());
+  DCHECK(!base::Contains(unmatched_links_, link));
+  DCHECK(!base::Contains(matched_links_, link));
+  DCHECK(!base::Contains(pending_links_, link));
+
+  pending_links_.insert(link);
+}
+
+void DocumentSpeculationRules::RemoveLink(HTMLAnchorElement* link) {
+  if (auto it = matched_links_.find(link); it != matched_links_.end()) {
+    matched_links_.erase(it);
+    DCHECK(!base::Contains(unmatched_links_, link));
+    DCHECK(!base::Contains(pending_links_, link));
+    return;
+  }
+  // TODO(crbug.com/1371522): Removing a link that doesn't match anything isn't
+  // going to change the candidate list, we could skip calling
+  // QueueUpdateSpeculationCandidates in this scenario.
+  if (auto it = unmatched_links_.find(link); it != unmatched_links_.end()) {
+    unmatched_links_.erase(it);
+    DCHECK(!base::Contains(pending_links_, link));
+    return;
+  }
+  auto it = pending_links_.find(link);
+  DCHECK(it != pending_links_.end());
+  pending_links_.erase(it);
+}
+
+void DocumentSpeculationRules::InvalidateLink(HTMLAnchorElement* link) {
+  pending_links_.insert(link);
+  if (auto it = matched_links_.find(link); it != matched_links_.end()) {
+    matched_links_.erase(it);
+    DCHECK(!base::Contains(unmatched_links_, link));
+    return;
+  }
+  if (auto it = unmatched_links_.find(link); it != unmatched_links_.end())
+    unmatched_links_.erase(it);
+}
+
+void DocumentSpeculationRules::InvalidateAllLinks() {
+  for (const auto& it : matched_links_)
+    pending_links_.insert(it.key);
+  matched_links_.clear();
+
+  for (HTMLAnchorElement* link : unmatched_links_)
+    pending_links_.insert(link);
+  unmatched_links_.clear();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h
index 47f1587..49af4629 100644
--- a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h
+++ b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h
@@ -17,6 +17,7 @@
 namespace blink {
 
 class SpeculationRuleLoader;
+class HTMLAnchorElement;
 
 // This corresponds to the document's list of speculation rule sets.
 //
@@ -45,6 +46,12 @@
   void AddSpeculationRuleLoader(SpeculationRuleLoader*);
   void RemoveSpeculationRuleLoader(SpeculationRuleLoader*);
 
+  void LinkInserted(HTMLAnchorElement* link);
+  void LinkRemoved(HTMLAnchorElement* link);
+  void HrefAttributeChanged(HTMLAnchorElement* link,
+                            const AtomicString& old_value,
+                            const AtomicString& new_value);
+
   void Trace(Visitor*) const override;
 
  private:
@@ -59,11 +66,42 @@
   // Pushes the current speculation candidates to the browser, immediately.
   void UpdateSpeculationCandidates();
 
+  // Appends all candidates populated from links in the document (based on
+  // document rules in all the rule sets).
+  void AddLinkBasedSpeculationCandidates(
+      Vector<mojom::blink::SpeculationCandidatePtr>& candidates);
+
+  // Initializes |link_map_| with all links in the document by traversing
+  // through the document in shadow-including tree order.
+  void InitializeIfNecessary();
+
+  // Helper methods to modify |link_map_|.
+  void AddLink(HTMLAnchorElement* link);
+  void RemoveLink(HTMLAnchorElement* link);
+  void InvalidateLink(HTMLAnchorElement* link);
+  void InvalidateAllLinks();
+
   HeapVector<Member<SpeculationRuleSet>> rule_sets_;
   HeapMojoRemote<mojom::blink::SpeculationHost> host_;
   HeapHashSet<Member<SpeculationRuleLoader>> speculation_rule_loaders_;
 
+  // The following data structures together keep track of all the links in
+  // the document. |matched_links_| contains links that match at least one
+  // document rule, and also caches a list of speculation candidates created for
+  // that link. |unmatched_links_| are links that are known to not match any
+  // document rules. |pending_links_| are links that haven't been matched
+  // against all the document rules yet.
+  // TODO(crbug.com/1371522): Consider removing |unmatched_links_| and
+  // re-traverse the document to find all links when a new ruleset is
+  // added/removed.
+  HeapHashMap<Member<HTMLAnchorElement>,
+              Vector<mojom::blink::SpeculationCandidatePtr>>
+      matched_links_;
+  HeapHashSet<Member<HTMLAnchorElement>> unmatched_links_;
+  HeapHashSet<Member<HTMLAnchorElement>> pending_links_;
+
   bool has_pending_update_ = false;
+  bool initialized_ = false;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc
index 6550b1531..79d71084f 100644
--- a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc
+++ b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc
@@ -262,6 +262,9 @@
             continue;
           }
 
+          if (rule->predicate())
+            result->has_document_rule_ = true;
+
           // Append rule to result's prefetch/prerender rules.
           destination.push_back(rule);
         }
diff --git a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h
index b63b78a7..3b45b740 100644
--- a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h
+++ b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h
@@ -43,12 +43,15 @@
     return prerender_rules_;
   }
 
+  bool has_document_rule() const { return has_document_rule_; }
+
   void Trace(Visitor*) const;
 
  private:
   HeapVector<Member<SpeculationRule>> prefetch_rules_;
   HeapVector<Member<SpeculationRule>> prefetch_with_subresources_rules_;
   HeapVector<Member<SpeculationRule>> prerender_rules_;
+  bool has_document_rule_ = false;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc
index 031c830..0e95ecb 100644
--- a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc
+++ b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc
@@ -17,13 +17,16 @@
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom-blink.h"
 #include "third_party/blink/public/web/blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_urlpatterninit_usvstring.h"
+#include "third_party/blink/renderer/core/dom/shadow_root.h"
 #include "third_party/blink/renderer/core/execution_context/agent.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
 #include "third_party/blink/renderer/core/html/html_anchor_element.h"
+#include "third_party/blink/renderer/core/html/html_area_element.h"
 #include "third_party/blink/renderer/core/html/html_head_element.h"
 #include "third_party/blink/renderer/core/html/html_script_element.h"
 #include "third_party/blink/renderer/core/loader/empty_clients.h"
@@ -516,6 +519,22 @@
   broker.SetBinderForTesting(mojom::blink::SpeculationHost::Name_, {});
 }
 
+// Same as above method except it performs a microtask checkpoint (and therefore
+// runs any queued microtasks) immediately after executing the functor.
+template <typename F>
+void PropagateRulesToStubSpeculationHostWithMicrotasksScope(
+    DummyPageHolder& page_holder,
+    StubSpeculationHost& speculation_host,
+    const F& functor) {
+  PropagateRulesToStubSpeculationHost(page_holder, speculation_host, [&]() {
+    auto* script_state = ToScriptStateForMainWorld(&page_holder.GetFrame());
+    v8::MicrotasksScope microtasks_scope(script_state->GetIsolate(),
+                                         ToMicrotaskQueue(script_state),
+                                         v8::MicrotasksScope::kRunMicrotasks);
+    functor();
+  });
+}
+
 // This function adds a speculationrules script to the given page, and simulates
 // the process of sending the parsed candidates to the browser.
 void PropagateRulesToStubSpeculationHost(DummyPageHolder& page_holder,
@@ -1222,7 +1241,7 @@
 TEST_F(DocumentRulesTest, EvaluateCombinators) {
   DummyPageHolder page_holder;
   Document& document = page_holder.GetDocument();
-  Element* link = MakeGarbageCollected<HTMLAnchorElement>(document);
+  HTMLAnchorElement* link = MakeGarbageCollected<HTMLAnchorElement>(document);
 
   auto* empty_and = CreatePredicate(R"("and": [])");
   EXPECT_THAT(empty_and, And());
@@ -1298,5 +1317,348 @@
   EXPECT_TRUE(pass_fail->Matches(*link));
 }
 
+// Matches a SpeculationCandidatePtr list with a KURL list (without requiring
+// candidates to be in a specific order).
+template <typename... Matchers>
+auto HasURLs(Matchers&&... urls) {
+  return ::testing::ResultOf(
+      "urls",
+      [](const auto& candidates) {
+        Vector<KURL> urls;
+        base::ranges::transform(
+            candidates.begin(), candidates.end(), std::back_inserter(urls),
+            [](const auto& candidate) { return candidate->url; });
+        return urls;
+      },
+      ::testing::UnorderedElementsAre(urls...));
+}
+
+// Matches a SpeculationCandidatePtr with a SpeculationAction.
+auto HasAction(::testing::Matcher<mojom::blink::SpeculationAction> matcher) {
+  return ::testing::Pointee(
+      ::testing::Field("action", &mojom::blink::SpeculationCandidate::action,
+                       std::forward<decltype(matcher)>(matcher)));
+}
+
+HTMLAnchorElement* AddAnchor(ContainerNode& parent, const String& href) {
+  HTMLAnchorElement* link =
+      MakeGarbageCollected<HTMLAnchorElement>(parent.GetDocument());
+  link->setHref(href);
+  parent.appendChild(link);
+  return link;
+}
+
+HTMLAreaElement* AddAreaElement(ContainerNode& parent, const String& href) {
+  HTMLAreaElement* area =
+      MakeGarbageCollected<HTMLAreaElement>(parent.GetDocument());
+  area->setHref(href);
+  parent.appendChild(area);
+  return area;
+}
+
+// Tests that speculation candidates based of existing links are reported after
+// a document rule is inserted.
+TEST_F(DocumentRulesTest, SpeculationCandidatesReportedAfterInitialization) {
+  DummyPageHolder page_holder;
+  StubSpeculationHost speculation_host;
+  Document& document = page_holder.GetDocument();
+
+  AddAnchor(*document.body(), "https://foo.com/doc.html");
+  AddAnchor(*document.body(), "https://bar.com/doc.html");
+  AddAnchor(*document.body(), "https://foo.com/doc2.html");
+
+  String speculation_script = R"(
+    {"prefetch": [
+      {"source": "document", "where": {"href_matches": "https://foo.com/*"}}
+    ]}
+  )";
+  PropagateRulesToStubSpeculationHost(page_holder, speculation_host,
+                                      speculation_script);
+
+  const auto& candidates = speculation_host.candidates();
+  EXPECT_THAT(candidates, HasURLs(KURL("https://foo.com/doc.html"),
+                                  KURL("https://foo.com/doc2.html")));
+}
+
+// Tests that a new speculation candidate is reported after different
+// modifications to a link.
+TEST_F(DocumentRulesTest, SpeculationCandidatesUpdatedAfterLinkModifications) {
+  DummyPageHolder page_holder;
+  StubSpeculationHost speculation_host;
+  Document& document = page_holder.GetDocument();
+
+  String speculation_script = R"(
+    {"prefetch": [
+      {"source": "document", "where": {"href_matches": "https://foo.com/*"}}
+    ]}
+  )";
+  PropagateRulesToStubSpeculationHost(page_holder, speculation_host,
+                                      speculation_script);
+  const auto& candidates = speculation_host.candidates();
+  ASSERT_TRUE(candidates.empty());
+  HTMLAnchorElement* link = nullptr;
+
+  // Add link with href that matches.
+  PropagateRulesToStubSpeculationHostWithMicrotasksScope(
+      page_holder, speculation_host, [&]() {
+        link = AddAnchor(*document.body(), "https://foo.com/action.html");
+      });
+  ASSERT_EQ(candidates.size(), 1u);
+  EXPECT_EQ(candidates[0]->url, KURL("https://foo.com/action.html"));
+
+  // Update link href to URL that doesn't match.
+  PropagateRulesToStubSpeculationHostWithMicrotasksScope(
+      page_holder, speculation_host,
+      [&]() { link->setHref("https://bar.com/document.html"); });
+  EXPECT_TRUE(candidates.empty());
+
+  // Update link href to URL that matches.
+  PropagateRulesToStubSpeculationHostWithMicrotasksScope(
+      page_holder, speculation_host,
+      [&]() { link->setHref("https://foo.com/document.html"); });
+  ASSERT_EQ(candidates.size(), 1u);
+  EXPECT_EQ(candidates[0]->url, KURL("https://foo.com/document.html"));
+
+  // Remove link.
+  PropagateRulesToStubSpeculationHostWithMicrotasksScope(
+      page_holder, speculation_host, [&]() { link->remove(); });
+  EXPECT_TRUE(candidates.empty());
+}
+
+// Tests that a new list of speculation candidates is reported after a rule set
+// is added/removed.
+TEST_F(DocumentRulesTest, SpeculationCandidatesUpdatedAfterRuleSetsChanged) {
+  DummyPageHolder page_holder;
+  StubSpeculationHost speculation_host;
+  Document& document = page_holder.GetDocument();
+
+  KURL url_1 = KURL("https://foo.com/abc");
+  KURL url_2 = KURL("https://foo.com/xyz");
+  AddAnchor(*document.body(), url_1);
+  AddAnchor(*document.body(), url_2);
+
+  String speculation_script_1 = R"(
+    {"prefetch": [
+      {"source": "document", "where": {"href_matches": "https://foo.com/*"}}
+    ]}
+  )";
+  PropagateRulesToStubSpeculationHost(page_holder, speculation_host,
+                                      speculation_script_1);
+  const auto& candidates = speculation_host.candidates();
+  EXPECT_THAT(candidates, HasURLs(url_1, url_2));
+
+  // Add a new rule set; the number of candidates should double.
+  String speculation_script_2 = R"(
+    {"prerender": [
+      {"source": "document", "where": {"not":
+        {"href_matches": {"protocol": "https", "hostname": "bar.com"}}
+      }}
+    ]}
+  )";
+  HTMLScriptElement* script_el = nullptr;
+  PropagateRulesToStubSpeculationHost(page_holder, speculation_host, [&]() {
+    script_el = InsertSpeculationRules(document, speculation_script_2);
+  });
+  EXPECT_THAT(candidates, HasURLs(url_1, url_1, url_2, url_2));
+  EXPECT_THAT(candidates, ::testing::UnorderedElementsAre(
+                              HasAction(mojom::SpeculationAction::kPrefetch),
+                              HasAction(mojom::SpeculationAction::kPrefetch),
+                              HasAction(mojom::SpeculationAction::kPrerender),
+                              HasAction(mojom::SpeculationAction::kPrerender)));
+
+  // Remove the recently added rule set, the number of candidates should be
+  // halved.
+  PropagateRulesToStubSpeculationHostWithMicrotasksScope(
+      page_holder, speculation_host, [&]() { script_el->remove(); });
+  ASSERT_EQ(candidates.size(), 2u);
+  EXPECT_THAT(candidates, HasURLs(url_1, url_2));
+  EXPECT_THAT(candidates,
+              ::testing::Each(HasAction(mojom::SpeculationAction::kPrefetch)));
+}
+
+// Tests that list and document speculation rules work in combination correctly.
+TEST_F(DocumentRulesTest, ListRuleCombinedWithDocumentRule) {
+  DummyPageHolder page_holder;
+  StubSpeculationHost speculation_host;
+  Document& document = page_holder.GetDocument();
+
+  AddAnchor(*document.body(), "https://foo.com/bar");
+  String speculation_script = R"(
+    {"prefetch": [
+      {"source": "document"},
+      {"source": "list", "urls": ["https://bar.com/foo"]}
+    ]}
+  )";
+  PropagateRulesToStubSpeculationHost(page_holder, speculation_host,
+                                      speculation_script);
+  const auto& candidates = speculation_host.candidates();
+  EXPECT_THAT(candidates, HasURLs(KURL("https://foo.com/bar"),
+                                  KURL("https://bar.com/foo")));
+}
+
+// Tests that candidates created for document rules are correct when
+// "anonyomour-client-ip-when-origin" is specified.
+TEST_F(DocumentRulesTest, RequiresAnonymousClientIPWhenCrossOrigin) {
+  DummyPageHolder page_holder;
+  StubSpeculationHost speculation_host;
+  Document& document = page_holder.GetDocument();
+
+  AddAnchor(*document.body(), "https://foo.com/bar");
+  String speculation_script = R"(
+    {"prefetch": [{
+      "source": "document",
+      "requires": ["anonymous-client-ip-when-cross-origin"]
+    }]}
+  )";
+  PropagateRulesToStubSpeculationHost(page_holder, speculation_host,
+                                      speculation_script);
+  const auto& candidates = speculation_host.candidates();
+  ASSERT_EQ(candidates.size(), 1u);
+  EXPECT_TRUE(candidates[0]->requires_anonymous_client_ip_when_cross_origin);
+}
+
+// Tests that a link inside a shadow tree is included when creating
+// document-rule based speculation candidates. Also tests that an "unslotted"
+// link (link inside shadow host that isn't assigned to a slot) is included.
+TEST_F(DocumentRulesTest, LinkInShadowTreeIncluded) {
+  DummyPageHolder page_holder;
+  StubSpeculationHost speculation_host;
+  Document& document = page_holder.GetDocument();
+  ShadowRoot& shadow_root =
+      document.body()->AttachShadowRootInternal(ShadowRootType::kOpen);
+  auto* link_1 = AddAnchor(shadow_root, "https://foo.com/bar.html");
+  auto* link_2 = AddAnchor(*document.body(), "https://foo.com/fizz.html");
+
+  String speculation_script = R"(
+    {"prefetch": [
+      {"source": "document", "where": {"href_matches": "https://foo.com/*"}}
+    ]}
+  )";
+  PropagateRulesToStubSpeculationHost(page_holder, speculation_host,
+                                      speculation_script);
+  const auto& candidates = speculation_host.candidates();
+  EXPECT_THAT(candidates, HasURLs(KURL("https://foo.com/bar.html"),
+                                  KURL("https://foo.com/fizz.html")));
+
+  PropagateRulesToStubSpeculationHostWithMicrotasksScope(
+      page_holder, speculation_host, [&]() {
+        link_1->setHref("https://bar.com/foo.html");
+        link_2->remove();
+      });
+  EXPECT_TRUE(candidates.empty());
+
+  PropagateRulesToStubSpeculationHostWithMicrotasksScope(
+      page_holder, speculation_host,
+      [&]() { link_1 = AddAnchor(shadow_root, "https://foo.com/buzz"); });
+  ASSERT_EQ(candidates.size(), 1u);
+  EXPECT_EQ(candidates[0]->url, KURL("https://foo.com/buzz"));
+
+  PropagateRulesToStubSpeculationHostWithMicrotasksScope(
+      page_holder, speculation_host, [&]() { link_1->remove(); });
+  EXPECT_TRUE(candidates.empty());
+}
+
+// Tests that an anchor element with no href attribute is handled correctly.
+TEST_F(DocumentRulesTest, LinkWithNoHrefAttribute) {
+  DummyPageHolder page_holder;
+  StubSpeculationHost speculation_host;
+  Document& document = page_holder.GetDocument();
+
+  auto* link = MakeGarbageCollected<HTMLAnchorElement>(document);
+  document.body()->appendChild(link);
+  ASSERT_FALSE(link->FastHasAttribute(html_names::kHrefAttr));
+
+  String speculation_script = R"(
+    {"prefetch": [
+      {"source": "document", "where": {"href_matches": "https://foo.com/*"}}
+    ]}
+  )";
+  PropagateRulesToStubSpeculationHost(page_holder, speculation_host,
+                                      speculation_script);
+  const auto& candidates = speculation_host.candidates();
+  ASSERT_TRUE(candidates.empty());
+
+  PropagateRulesToStubSpeculationHostWithMicrotasksScope(
+      page_holder, speculation_host,
+      [&]() { link->setHref("https://foo.com/bar"); });
+  ASSERT_EQ(candidates.size(), 1u);
+  ASSERT_EQ(candidates[0]->url, "https://foo.com/bar");
+
+  PropagateRulesToStubSpeculationHostWithMicrotasksScope(
+      page_holder, speculation_host,
+      [&]() { link->removeAttribute(html_names::kHrefAttr); });
+  ASSERT_TRUE(candidates.empty());
+
+  // Just to test that no DCHECKs are hit.
+  link->remove();
+}
+
+// Tests a couple of edge cases:
+// 1) Removing a link that doesn't match any rules
+// 2) Adding and removing a link before running microtasks (i.e. before calling
+// UpdateSpeculationCandidates).
+TEST_F(DocumentRulesTest, RemovingUnmatchedAndPendingLinks) {
+  DummyPageHolder page_holder;
+  StubSpeculationHost speculation_host;
+  Document& document = page_holder.GetDocument();
+
+  auto* unmatched_link = AddAnchor(*document.body(), "https://bar.com/foo");
+  String speculation_script = R"(
+    {"prefetch": [
+      {"source": "document", "where": {"href_matches": "https://foo.com/*"}}
+    ]}
+  )";
+  PropagateRulesToStubSpeculationHost(page_holder, speculation_host,
+                                      speculation_script);
+  const auto& candidates = speculation_host.candidates();
+  EXPECT_TRUE(candidates.empty());
+
+  PropagateRulesToStubSpeculationHostWithMicrotasksScope(
+      page_holder, speculation_host, [&]() {
+        auto* pending_link = AddAnchor(*document.body(), "https://foo.com/bar");
+        unmatched_link->remove();
+        pending_link->remove();
+      });
+  EXPECT_TRUE(candidates.empty());
+}
+
+// Tests if things still work if we use <area> instead of <a>.
+TEST_F(DocumentRulesTest, AreaElement) {
+  DummyPageHolder page_holder;
+  StubSpeculationHost speculation_host;
+  Document& document = page_holder.GetDocument();
+  HTMLAreaElement* area =
+      AddAreaElement(*document.body(), "https://foo.com/action.html");
+
+  String speculation_script = R"(
+    {"prefetch": [
+      {"source": "document", "where": {"href_matches": "https://foo.com/*"}}
+    ]}
+  )";
+  PropagateRulesToStubSpeculationHost(page_holder, speculation_host,
+                                      speculation_script);
+  const auto& candidates = speculation_host.candidates();
+  ASSERT_EQ(candidates.size(), 1u);
+  EXPECT_EQ(candidates[0]->url, KURL("https://foo.com/action.html"));
+
+  // Update area href to URL that doesn't match.
+  PropagateRulesToStubSpeculationHostWithMicrotasksScope(
+      page_holder, speculation_host,
+      [&]() { area->setHref("https://bar.com/document.html"); });
+  EXPECT_TRUE(candidates.empty());
+
+  // Update area href to URL that matches.
+  PropagateRulesToStubSpeculationHostWithMicrotasksScope(
+      page_holder, speculation_host,
+      [&]() { area->setHref("https://foo.com/document.html"); });
+  ASSERT_EQ(candidates.size(), 1u);
+  EXPECT_EQ(candidates[0]->url, KURL("https://foo.com/document.html"));
+
+  // Remove area.
+  PropagateRulesToStubSpeculationHostWithMicrotasksScope(
+      page_holder, speculation_host, [&]() { area->remove(); });
+  EXPECT_TRUE(candidates.empty());
+}
+
 }  // namespace
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/url_pattern/url_pattern.cc b/third_party/blink/renderer/core/url_pattern/url_pattern.cc
index f2dce41..7873510 100644
--- a/third_party/blink/renderer/core/url_pattern/url_pattern.cc
+++ b/third_party/blink/renderer/core/url_pattern/url_pattern.cc
@@ -24,6 +24,7 @@
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/liburlpattern/pattern.h"
 #include "third_party/liburlpattern/tokenize.h"
+#include "third_party/liburlpattern/utils.h"
 
 namespace blink {
 
@@ -78,6 +79,23 @@
   return default_port != url::PORT_UNSPECIFIED && default_port == port_number;
 }
 
+// Base URL values that include pattern string characters should not blow
+// up pattern parsing.  Automatically escape them.  We must not escape inputs
+// for non-pattern base URLs, though.
+String EscapeBaseURLString(const String& input, ValueType type) {
+  if (type != ValueType::kPattern || !input.length())
+    return input;
+
+  std::string result;
+  result.reserve(input.length());
+
+  StringUTF8Adaptor utf8(input);
+  liburlpattern::EscapePatternStringAndAppend(
+      absl::string_view(utf8.data(), utf8.size()), result);
+
+  return String::FromUTF8(result);
+}
+
 // A utility method that takes a URLPatternInit, splits it apart, and applies
 // the individual component values in the given set of strings.  The strings
 // are only applied if a value is present in the init structure.
@@ -107,16 +125,25 @@
       return;
     }
 
-    protocol = base_url.Protocol() ? base_url.Protocol() : g_empty_string;
-    username = base_url.User() ? base_url.User() : g_empty_string;
-    password = base_url.Pass() ? base_url.Pass() : g_empty_string;
-    hostname = base_url.Host() ? base_url.Host() : g_empty_string;
+    protocol = base_url.Protocol()
+                   ? EscapeBaseURLString(base_url.Protocol(), type)
+                   : g_empty_string;
+    username = base_url.User() ? EscapeBaseURLString(base_url.User(), type)
+                               : g_empty_string;
+    password = base_url.Pass() ? EscapeBaseURLString(base_url.Pass(), type)
+                               : g_empty_string;
+    hostname = base_url.Host() ? EscapeBaseURLString(base_url.Host(), type)
+                               : g_empty_string;
     port =
         base_url.Port() > 0 ? String::Number(base_url.Port()) : g_empty_string;
-    pathname = base_url.GetPath() ? base_url.GetPath() : g_empty_string;
-    search = base_url.Query() ? base_url.Query() : g_empty_string;
-    hash = base_url.HasFragmentIdentifier() ? base_url.FragmentIdentifier()
-                                            : g_empty_string;
+    pathname = base_url.GetPath()
+                   ? EscapeBaseURLString(base_url.GetPath(), type)
+                   : g_empty_string;
+    search = base_url.Query() ? EscapeBaseURLString(base_url.Query(), type)
+                              : g_empty_string;
+    hash = base_url.HasFragmentIdentifier()
+               ? EscapeBaseURLString(base_url.FragmentIdentifier(), type)
+               : g_empty_string;
   }
 
   // Apply the URLPatternInit component values on top of the default and
@@ -157,11 +184,12 @@
       // and check.  If there is no slash then we cannot use resolve the
       // relative pathname and just treat the init pathname as an absolute
       // value.
-      auto slash_index = base_url.GetPath().ReverseFind("/");
+      String base_path = EscapeBaseURLString(base_url.GetPath(), type);
+      auto slash_index = base_path.ReverseFind("/");
       if (slash_index != kNotFound) {
         // Extract the baseURL path up to and including the first slash.  Append
         // the relative init pathname to it.
-        pathname = base_url.GetPath().Substring(0, slash_index + 1) + pathname;
+        pathname = base_path.Substring(0, slash_index + 1) + pathname;
       }
     }
     pathname = url_pattern::CanonicalizePathname(protocol, pathname, type,
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index 345143d3..347fb41 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -2840,6 +2840,9 @@
   return kDefaultBehavior;
 }
 
+// Note: do not rely on the value of this inside of display:none.
+// In practice, it does not matter because nodes in display:none subtrees are
+// marked ignored either way.
 bool AXObject::IsInert() const {
   UpdateCachedAttributeValuesIfNeeded();
   return cached_is_inert_;
@@ -3824,6 +3827,14 @@
   if (!node)
     return nullptr;
 
+#if DCHECK_IS_ON()
+  DCHECK(GetDocument());
+  DCHECK(GetDocument()->Lifecycle().GetState() >=
+         DocumentLifecycle::kLayoutClean)
+      << "Unclean document at lifecycle "
+      << GetDocument()->Lifecycle().ToString();
+#endif
+
   // content-visibility:hidden or content-visibility: auto.
   if (DisplayLockUtilities::IsDisplayLockedPreventingPaint(node))
     return nullptr;
@@ -3832,8 +3843,13 @@
   if (GetLayoutObject())
     return GetLayoutObject()->Style();
 
-  // No layout object: must ensure computed style.
-  return node->EnsureComputedStyle();
+  // No layout object: if possible, use EnsureComputedStyle().
+  // Cannot call EnsureComputedStyle() here because we may be in post lifecycle
+  // steps, and EnsureComputedStyle() can cause a style recalc which is not
+  // allowed at that time (enforced by DCHECK).
+  // TODO(szager) Figure out how to make this code cleaner.
+  return GetDocument()->InPostLifecycleSteps() ? node->GetComputedStyle()
+                                               : node->EnsureComputedStyle();
 }
 
 // There are 4 ways to use CSS to hide something:
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
index 8f2aaaa..9f6283f 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -3290,22 +3290,11 @@
     if (parent->IsInert() || parent->IsAriaHidden())
       return;
     // If the parent is 'display: none', then the subtree will be ignored and
-    // changing aria-hidden will have no effect.
-    if (!parent->GetLayoutObject()) {
-      // No layout object: may be in display: none.
-      if (Element* parent_element = parent->GetElement()) {
-        if (!IsDisplayLocked(parent_element)) {
-          // No layout object: must ensure computed style.
-          // Do not perform this check for display locked content, where
-          // computed styles are not updated. In that case, we will need to
-          // assume the need for marking the subtree dirty.
-          const ComputedStyle* parent_style =
-              parent_element->EnsureComputedStyle();
-          if (!parent_style || parent_style->IsEnsuredInDisplayNone())
-            return;
-        }
-      }
-    }
+    // changing aria-hidden will have no effect. However, determining whether
+    // something is in display:none would require calling EnsureComputedStyle(),
+    // which is not ok during post lifecycle tasks. Ultimately, it does not
+    // really matter if we perform this check, because it's just an optimization
+    // to avoid invalidating the entire aria-hidden subtree.
     // Unlike AXObject's |IsVisible| or |IsHiddenViaStyle| this method does not
     // consider 'visibility: [hidden|collapse]', because while the visibility
     // property is inherited it can be overridden by any descendant by providing
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices.cc b/third_party/blink/renderer/modules/mediastream/media_devices.cc
index 1eac9ca..7270dc9 100644
--- a/third_party/blink/renderer/modules/mediastream/media_devices.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_devices.cc
@@ -831,9 +831,6 @@
           static_cast<mojom::blink::MediaDeviceType>(i);
       WebMediaDeviceInfo device_info = enumeration[i][j];
       String device_label = String::FromUTF8(device_info.label);
-      if (device_label.Contains("AirPods")) {
-        device_label = "AirPods";
-      }
       if (device_type == mojom::blink::MediaDeviceType::MEDIA_AUDIO_INPUT ||
           device_type == mojom::blink::MediaDeviceType::MEDIA_VIDEO_INPUT) {
         InputDeviceInfo* input_device_info =
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices_test.cc b/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
index 09afe7af..55b9c05 100644
--- a/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
@@ -93,7 +93,7 @@
           .push_back(device_info);
 
       device_info.device_id = kFakeAudioInputDeviceId2;
-      device_info.label = "X's AirPods";
+      device_info.label = "Fake Audio Input 2";
       device_info.group_id = kFakeCommonGroupId2;
       enumeration[static_cast<size_t>(
                       blink::mojom::blink::MediaDeviceType::MEDIA_AUDIO_INPUT)]
@@ -148,7 +148,7 @@
           .push_back(device_info);
 
       device_info.device_id = kFakeAudioOutputDeviceId2;
-      device_info.label = "X's AirPods";
+      device_info.label = "Fake Audio Input 2";
       device_info.group_id = kFakeCommonGroupId2;
       enumeration[static_cast<size_t>(
                       blink::mojom::blink::MediaDeviceType::MEDIA_AUDIO_OUTPUT)]
@@ -387,7 +387,7 @@
   EXPECT_FALSE(device->label().empty());
   EXPECT_FALSE(device->groupId().empty());
 
-  // Audio input device with Airpods label.
+  // Audio input device with second matched output ID
   device = device_infos()[1];
   EXPECT_FALSE(device->deviceId().empty());
   EXPECT_EQ("audioinput", device->kind());
@@ -421,7 +421,7 @@
   EXPECT_FALSE(device->label().empty());
   EXPECT_FALSE(device->groupId().empty());
 
-  // Audio output device with Airpods label.
+  // Second audio output device
   device = device_infos()[6];
   EXPECT_FALSE(device->deviceId().empty());
   EXPECT_EQ("audiooutput", device->kind());
@@ -432,14 +432,6 @@
   EXPECT_EQ(device_infos()[0]->groupId(), device_infos()[3]->groupId());
   EXPECT_EQ(device_infos()[0]->groupId(), device_infos()[5]->groupId());
   EXPECT_NE(device_infos()[2]->groupId(), device_infos()[5]->groupId());
-
-  // Verify device labels do not expose user's information.
-  EXPECT_EQ(device_infos()[1]->label(), "AirPods");
-  EXPECT_EQ(device_infos()[6]->label(), "AirPods");
-
-  // Verify the code does not change non-sensitive device labels.
-  EXPECT_EQ(device_infos()[0]->label(), "Fake Audio Input 1");
-  EXPECT_EQ(device_infos()[3]->label(), "Fake Video Input 1");
 }
 
 TEST_F(MediaDevicesTest, EnumerateDevicesAfterConnectionError) {
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.cc b/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.cc
index 1a6ae8b..0a764291 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.cc
@@ -309,11 +309,7 @@
 }
 
 String MediaStreamTrackImpl::label() const {
-  String label = component_->GetSourceName();
-  if (label.Contains("AirPods")) {
-    label = "AirPods";
-  }
-  return label;
+  return component_->GetSourceName();
 }
 
 bool MediaStreamTrackImpl::enabled() const {
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track_impl_test.cc b/third_party/blink/renderer/modules/mediastream/media_stream_track_impl_test.cc
index f221c86..9a2195a 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_track_impl_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_track_impl_test.cc
@@ -97,19 +97,6 @@
   EXPECT_EQ(testObserver->ObservationCount(), 2);
 }
 
-TEST_F(MediaStreamTrackImplTest, LabelSanitizer) {
-  V8TestingScope v8_scope;
-
-  MediaStreamSource* source = MakeGarbageCollected<MediaStreamSource>(
-      "id", MediaStreamSource::StreamType::kTypeAudio, "Chromiums AirPods",
-      false /* remote */);
-  MediaStreamComponent* component =
-      MakeGarbageCollected<MediaStreamComponentImpl>(source);
-  MediaStreamTrack* track = MakeGarbageCollected<MediaStreamTrackImpl>(
-      v8_scope.GetExecutionContext(), component);
-  EXPECT_EQ(track->label(), "AirPods");
-}
-
 TEST_F(MediaStreamTrackImplTest, StopTrackSynchronouslyDisablesMedia) {
   V8TestingScope v8_scope;
 
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index c9cf2e93..c254ea8e 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -646,10 +646,8 @@
     {
       // Support for CSS Color Module Level 4
       // https://www.w3.org/TR/css-color-4/
-      // It has a kill-switch in case we see that something is not proplery working"
       name: "CSSColor4",
-      status:  "stable",
-      base_feature: "CSSColor4",
+      status:  "experimental",
     },
     {
       name: "CSSColorContrast",
diff --git a/third_party/blink/tools/blinkpy/w3c/test_importer.py b/third_party/blink/tools/blinkpy/w3c/test_importer.py
index 611224c..c2e100bc 100644
--- a/third_party/blink/tools/blinkpy/w3c/test_importer.py
+++ b/third_party/blink/tools/blinkpy/w3c/test_importer.py
@@ -11,9 +11,11 @@
 """
 
 import argparse
+import datetime
 import json
 import logging
 import re
+from typing import Collection, Set
 
 from blinkpy.common.net.git_cl import GitCL
 from blinkpy.common.net.network_transaction import NetworkTimeout
@@ -168,26 +170,32 @@
         # TODO(crbug.com/800570 robertma): Re-enable it once we fix the bug.
         # self._delete_orphaned_baselines()
 
-        if not self.chromium_git.has_working_directory_changes():
-            _log.info('Done: no changes to import.')
-            return 0
-
-        if not self._has_wpt_changes():
-            _log.info('Only manifest or expectations was updated; skipping the import.')
-            return 0
-
-        self._commit_changes(commit_message)
-        _log.info('Changes imported and committed.')
+        if self.chromium_git.has_working_directory_changes():
+            self._commit_changes(commit_message)
+            _log.info('Changes imported and committed.')
+        else:
+            _log.info('No tests to import.')
 
         if not options.auto_upload and not options.auto_update:
             return 0
 
+        builders = self.builders_to_trigger()
+        if not builders:
+            _log.info('No builders to trigger (no new tests '
+                      'and not scheduled to update metadata).')
+            return 0
+
         self._upload_cl()
         _log.info('Issue: %s', self.git_cl.run(['issue']).strip())
 
-        if not self.update_expectations_for_cl():
+        if not self.update_expectations_for_cl(builders):
             return 1
 
+        if not self._has_wpt_changes():
+            _log.info('Only manifest or expectations was updated; '
+                      'skipping CQ.')
+            return 0
+
         if not options.auto_update:
             return 0
 
@@ -200,18 +208,21 @@
 
         return 0
 
-    def update_expectations_for_cl(self):
+    def update_expectations_for_cl(self, builders: Collection[str]) -> bool:
         """Performs the expectation-updating part of an auto-import job.
 
         This includes triggering try jobs and waiting; then, if applicable,
-        writing new baselines and TestExpectation lines, committing, and
-        uploading a new patchset.
+        writing new baselines, metadata, and TestExpectation lines, committing,
+        and uploading a new patchset.
 
-        This assumes that there is CL associated with the current branch.
+        This assumes that there is CL associated with the current branch. The
+        current CL may be empty (i.e., contain no new tests) because this method
+        may still need to update stale metadata.
 
         Returns True if everything is OK to continue, or False on failure.
         """
-        self._trigger_try_jobs()
+        _log.info('Triggering try jobs for updating expectations.')
+        self.git_cl.trigger_try_jobs(builders)
         cl_status = self.git_cl.wait_for_try_jobs(
             poll_delay_seconds=POLL_DELAY_SECONDS,
             timeout_seconds=TIMEOUT_SECONDS)
@@ -230,6 +241,8 @@
 
         if try_results and self.git_cl.some_failed(try_results):
             self.fetch_new_expectations_and_baselines()
+            # If no wptrunner builders were triggered, this call is a no-op.
+            self._expectations_updater.update_metadata()
             if self.chromium_git.has_working_directory_changes():
                 # Skip slow and timeout tests so that presubmit check passes
                 port = self.host.port_factory.get()
@@ -243,24 +256,32 @@
                 self._upload_patchset(message)
         return True
 
-    def _trigger_try_jobs(self):
-        _log.info('Triggering try jobs for updating expectations.')
-        try_bots = set(self.blink_try_bots())
+    def builders_to_trigger(self) -> Set[str]:
+        builders = set(self.host.builders.filter_builders(is_try=True))
         wptrunner_builders = {
             builder
-            for builder in try_bots
+            for builder in builders
             if self.host.builders.is_wpt_builder(builder)
         }
-        rebaselining_builders = try_bots - wptrunner_builders
-        if rebaselining_builders:
+        rebaselining_builders = builders - wptrunner_builders
+
+        if not self._has_wpt_changes():
+            builders -= rebaselining_builders
+        else:
             _log.info('For rebaselining:')
             for builder in sorted(rebaselining_builders):
                 _log.info('  %s', builder)
-        if wptrunner_builders:
+
+        # Due to limited infra capacity, only update metadata during off-peak
+        # hours (12am - 6am PST).
+        if datetime.datetime.now().time() > datetime.time(hour=6):
+            builders -= wptrunner_builders
+        elif wptrunner_builders:
             _log.info('For updating WPT metadata:')
             for builder in sorted(wptrunner_builders):
                 _log.info('  %s', builder)
-        self.git_cl.trigger_try_jobs(try_bots)
+
+        return builders
 
     def run_commit_queue_for_cl(self):
         """Triggers CQ and either commits or aborts; returns True on success."""
@@ -334,10 +355,6 @@
                 raise e
         return False
 
-    def blink_try_bots(self):
-        """Returns the collection of builders used for updating expectations."""
-        return self.host.builders.filter_builders(is_try=True)
-
     def parse_args(self, argv):
         parser = argparse.ArgumentParser()
         parser.description = __doc__
@@ -480,10 +497,13 @@
 
     def _has_wpt_changes(self):
         changed_files = self.chromium_git.changed_files()
-        rel_dest_path = self.fs.relpath(self.dest_path,
-                                        self.finder.chromium_base())
-        for cf in changed_files:
-            if cf.startswith(rel_dest_path):
+        test_roots = [
+            self.fs.relpath(self.finder.path_from_web_tests(subdir),
+                            self.finder.chromium_base())
+            for subdir in Port.WPT_DIRS
+        ]
+        for changed_file in changed_files:
+            if any(changed_file.startswith(root) for root in test_roots):
                 return True
         return False
 
@@ -567,15 +587,12 @@
         temp_file.write(description)
         temp_file.close()
 
-        self.git_cl.run([
-            'upload',
-            '--bypass-hooks',
-            '-f',
-            '--message-file',
-            temp_path
-        ])
-
-        self.fs.remove(temp_path)
+        try:
+            self.git_cl.run([
+                'upload', '--bypass-hooks', '-f', '--message-file', temp_path
+            ])
+        finally:
+            self.fs.remove(temp_path)
 
     def get_directory_owners(self):
         """Returns a mapping of email addresses to owners of changed tests."""
diff --git a/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py b/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
index 62da12eb..4a0a544 100644
--- a/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
+++ b/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
@@ -2,11 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-from __future__ import print_function
-
+import datetime
 import json
 import six
 import unittest
+from unittest.mock import Mock, patch
 
 from blinkpy.common.checkout.git_mock import MockGit
 from blinkpy.common.host_mock import MockHost
@@ -34,6 +34,15 @@
 ]
 
 
+_datetime_mock = Mock()
+_datetime_mock.datetime.now.return_value = datetime.datetime(2022, 1, 1, 3)
+
+
+# `datetime` is a natively compiled library, so patch the module in the
+# importer's namespace instead of patching individual methods. See also:
+#   https://docs.python.org/3/library/unittest.mock-examples.html#partial-mocking
+@patch('blinkpy.w3c.test_importer.datetime.time', new=datetime.time)
+@patch('blinkpy.w3c.test_importer.datetime', new=_datetime_mock)
 class TestImporterTest(LoggingTestCase):
 
     def mock_host(self):
@@ -78,15 +87,22 @@
             MOCK_WEB_TESTS + 'W3CImportExpectations', '')
         importer = self._get_test_importer(host)
         importer.git_cl = MockGitCL(host, time_out=True)
-        success = importer.update_expectations_for_cl()
+        with patch.object(
+                importer.chromium_git,
+                'changed_files',
+                return_value=[
+                    'third_party/blink/web_tests/external/wpt/new-test.html'
+                ]):
+            success = importer.update_expectations_for_cl(
+                importer.builders_to_trigger())
         self.assertFalse(success)
         self.assertLog([
-            'INFO: Triggering try jobs for updating expectations.\n',
             'INFO: For rebaselining:\n',
             'INFO:   cq-builder-a\n',
             'INFO:   cq-builder-b\n',
             'INFO: For updating WPT metadata:\n',
             'INFO:   cq-wpt-builder-c\n',
+            'INFO: Triggering try jobs for updating expectations.\n',
             'ERROR: No initial try job results, aborting.\n',
         ])
         self.assertEqual(importer.git_cl.calls[-1], ['git', 'cl', 'set-close'])
@@ -102,15 +118,22 @@
             try_job_results={
                 Build('builder-a', 123): TryJobStatus('COMPLETED', 'SUCCESS'),
             })
-        success = importer.update_expectations_for_cl()
+        with patch.object(
+                importer.chromium_git,
+                'changed_files',
+                return_value=[
+                    'third_party/blink/web_tests/external/wpt/new-test.html'
+                ]):
+            success = importer.update_expectations_for_cl(
+                importer.builders_to_trigger())
         self.assertFalse(success)
         self.assertLog([
-            'INFO: Triggering try jobs for updating expectations.\n',
             'INFO: For rebaselining:\n',
             'INFO:   cq-builder-a\n',
             'INFO:   cq-builder-b\n',
             'INFO: For updating WPT metadata:\n',
             'INFO:   cq-wpt-builder-c\n',
+            'INFO: Triggering try jobs for updating expectations.\n',
             'ERROR: The CL was closed, aborting.\n',
         ])
 
@@ -125,14 +148,21 @@
             try_job_results={
                 Build('builder-a', 123): TryJobStatus('COMPLETED', 'SUCCESS'),
             })
-        success = importer.update_expectations_for_cl()
+        with patch.object(
+                importer.chromium_git,
+                'changed_files',
+                return_value=[
+                    'third_party/blink/web_tests/external/wpt/new-test.html'
+                ]):
+            success = importer.update_expectations_for_cl(
+                importer.builders_to_trigger())
         self.assertLog([
-            'INFO: Triggering try jobs for updating expectations.\n',
             'INFO: For rebaselining:\n',
             'INFO:   cq-builder-a\n',
             'INFO:   cq-builder-b\n',
             'INFO: For updating WPT metadata:\n',
             'INFO:   cq-wpt-builder-c\n',
+            'INFO: Triggering try jobs for updating expectations.\n',
             'INFO: All jobs finished.\n',
         ])
         self.assertTrue(success)
@@ -150,17 +180,31 @@
             })
         importer.fetch_new_expectations_and_baselines = lambda: None
         importer.fetch_wpt_override_expectations = lambda: None
-        success = importer.update_expectations_for_cl()
+        with patch.object(
+                importer.chromium_git,
+                'changed_files',
+                return_value=[
+                    'third_party/blink/web_tests/external/wpt/new-test.html'
+                ]):
+            success = importer.update_expectations_for_cl(
+                importer.builders_to_trigger())
         self.assertTrue(success)
         self.assertLog([
-            'INFO: Triggering try jobs for updating expectations.\n',
             'INFO: For rebaselining:\n',
             'INFO:   cq-builder-a\n',
             'INFO:   cq-builder-b\n',
             'INFO: For updating WPT metadata:\n',
             'INFO:   cq-wpt-builder-c\n',
+            'INFO: Triggering try jobs for updating expectations.\n',
             'INFO: All jobs finished.\n',
+            'INFO: Output of update-metadata:\n',
+            'INFO:   update-metadata: MOCK output of child process\n',
+            'INFO: -- end of update-metadata output --\n',
         ])
+        self.assertIn([
+            'python', '/mock-checkout/third_party/blink/tools/blink_tool.py',
+            'update-metadata', '--no-trigger-jobs'
+        ], host.executive.calls)
 
     def test_run_commit_queue_for_cl_pass(self):
         host = self.mock_host()
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py b/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py
index 0f117a4..6e6f2f26 100644
--- a/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py
+++ b/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py
@@ -12,8 +12,8 @@
 import copy
 import logging
 import re
-import sys
 from collections import defaultdict, namedtuple
+from typing import List
 
 from blinkpy.common.memoized import memoized
 from blinkpy.common.net.git_cl import GitCL
@@ -1190,22 +1190,34 @@
         for test in tests_to_rebaseline:
             _log.info('  %s', test)
 
-        blink_tool = self.finder.path_from_blink_tools('blink_tool.py')
-        command = [
-            sys.executable,
-            blink_tool,
-            'rebaseline-cl',
-            '--no-trigger-jobs',
-        ]
+        args = ['--no-trigger-jobs']
         if self.options.verbose:
-            command.append('--verbose')
+            args.append('--verbose')
         if self.patchset:
-            command.append('--patchset=' + str(self.patchset))
-        command += tests_to_rebaseline
-        rebaseline_output = self.host.executive.run_command(command)
-        _log.info(
-            "Output of rebaseline-cl:\n%s\n--end of rebaseline-cl output --" %
-            rebaseline_output)
+            args.append('--patchset=%d' % self.patchset)
+        args += tests_to_rebaseline
+        self._run_blink_tool('rebaseline-cl', args)
+
+    def update_metadata(self):
+        """Update WPT metadata for all tests with unexpected results."""
+        args = ['--no-trigger-jobs']
+        if self.options.verbose:
+            args.append('--verbose')
+        if self.patchset:
+            args.append('--patchset=%d', self.patchset)
+        self._run_blink_tool('update-metadata', args)
+
+    def _run_blink_tool(self, subcommand: str, args: List[str]):
+        output = self.host.executive.run_command([
+            self.host.executable,
+            self.finder.path_from_blink_tools('blink_tool.py'),
+            subcommand,
+            *args,
+        ])
+        _log.info('Output of %s:', subcommand)
+        for line in output.splitlines():
+            _log.info('  %s: %s', subcommand, line)
+        _log.info('-- end of %s output --', subcommand)
 
     def get_tests_to_rebaseline(self, test_results):
         """Filters failing tests that can be rebaselined.
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index c74bb53..4257a4a 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -4593,7 +4593,7 @@
 crbug.com/1059262 [ Mac ] webexposed/global-interface-listing-platform-specific.html [ Failure Pass ]
 
 # Sheriff 2020-03-08
-crbug.com/1059645 external/wpt/pointerevents/pointerevent_coalesced_events_attributes.html [ Failure Pass ]
+crbug.com/1059645 external/wpt/pointerevents/pointerevent_coalesced_events_attributes.html [ Failure Pass Timeout ]
 
 # [virtual/...]external/wpt/web-animation test flakes
 crbug.com/1064065 virtual/threaded/external/wpt/css/css-animations/event-dispatch.tentative.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 709717dd..c85ea66 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -170,6 +170,10 @@
     "platforms": ["Linux", "Mac", "Win", "Fuchsia"],
     "bases": ["fast/css3-text/css3-text-decoration/stable",
               "fast/dom/Window",
+              "external/wpt/css/css-color/parsing/",
+              "external/wpt/css/css-transitions/parsing/",
+              "external/wpt/css/css-animations/parsing/",
+              "external/wpt/css/css-images/parsing/",
               "http/tests/navigation",
               "http/tests/sendbeacon",
               "http/tests/serviceworker/webexposed",
@@ -948,7 +952,10 @@
   {
     "prefix": "first-party-sets",
     "platforms": ["Linux", "Mac", "Win"],
-    "bases": ["http/tests/inspector-protocol/network"],
+    "bases": [
+      "http/tests/inspector-protocol/network",
+      "http/tests/inspector-protocol/issues"
+    ],
     "args": ["--use-first-party-set={\"primary\":\"https://firstparty.test\",\"associatedSites\":[\"https://cookie.test\"]}"]
   },
   {
@@ -1193,7 +1200,8 @@
       "wpt_internal/fenced_frame",
       "http/tests/inspector-protocol/fenced-frame"
     ],
-    "args": ["--enable-features=FencedFrames:implementation_type/mparch,PrivacySandboxAdsAPIsOverride,SharedStorageAPI,NoncedPartitionedCookies"]
+    "args": ["--enable-features=FencedFrames:implementation_type/mparch,PrivacySandboxAdsAPIsOverride,SharedStorageAPI,NoncedPartitionedCookies",
+             "--enable-blink-features=FencedFramesAPIChanges"]
   },
   {
     "prefix": "cors-non-wildcard-request-headers",
diff --git a/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/partitioned-cookies.tentative.https.html b/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/partitioned-cookies.tentative.https.html
index a2d92c53..deab669 100644
--- a/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/partitioned-cookies.tentative.https.html
+++ b/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/partitioned-cookies.tentative.https.html
@@ -24,30 +24,34 @@
   const domCookieName = "__Host-pcdom";
   document.cookie = `${domCookieName}=foobar;${attributes}`;
 
-  // Set another partitioned cookie using the CookieStore API.
-  const cookieStoreCookieName = "__Host-pccookistore";
-  await cookieStore.set({
-    name: cookieStoreCookieName,
-    value: "foobar",
-    path: "/",
-    sameSite: "none",
-    partitioned: true,
-  });
+  // Set another partitioned cookie using the CookieStore API, if supported.
+  if (window.cookieStore) {
+    const cookieStoreCookieName = "__Host-pccookiestore";
+    await cookieStore.set({
+      name: cookieStoreCookieName,
+      value: "foobar",
+      path: "/",
+      sameSite: "none",
+      partitioned: true,
+    });
+  }
+
+  const cookieNames = getCookieNames();
 
   // Verify that the cookies are sent in requests from this top-level site.
   testHttpPartitionedCookies({
     origin: self.origin,
-    cookieNames: [httpCookieName, domCookieName, cookieStoreCookieName],
+    cookieNames,
     expectsCookie: true,
   });
 
   // Verify that the cookies are exposed to the DOM on this top-level site.
   testDomPartitionedCookies({
-    cookieNames: [httpCookieName, domCookieName, cookieStoreCookieName],
+    cookieNames,
     expectsCookie: true,
   });
   testCookieStorePartitionedCookies({
-    cookieNames: [httpCookieName, domCookieName, cookieStoreCookieName],
+    cookieNames,
     expectsCookie: true,
   });
 
diff --git a/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/resources/partitioned-cookies-cross-site-embed.html b/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/resources/partitioned-cookies-cross-site-embed.html
index f48268d..05a9962 100644
--- a/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/resources/partitioned-cookies-cross-site-embed.html
+++ b/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/resources/partitioned-cookies-cross-site-embed.html
@@ -10,7 +10,7 @@
 <body>
 <script>
 
-const cookieNames = ["__Host-pchttp", "__Host-pcdom", "__Host-pccookiestore"];
+const cookieNames = getCookieNames();
 
 testDomPartitionedCookies({
   cookieNames,
diff --git a/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/resources/partitioned-cookies-cross-site-window.html b/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/resources/partitioned-cookies-cross-site-window.html
index e341993..ca1a27c 100644
--- a/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/resources/partitioned-cookies-cross-site-window.html
+++ b/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/resources/partitioned-cookies-cross-site-window.html
@@ -23,7 +23,7 @@
 // partitioned cookie.
 testHttpPartitionedCookies({
   origin,
-  cookieNames: ["__Host-pchttp", "__Host-pcdom"],
+  cookieNames: getCookieNames(),
   expectsCookie: false,
 });
 
diff --git a/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/resources/test-helpers.js b/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/resources/test-helpers.js
index 6ba7f89..0ecaa63 100644
--- a/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/resources/test-helpers.js
+++ b/third_party/blink/web_tests/external/wpt/cookies/partitioned-cookies/resources/test-helpers.js
@@ -44,6 +44,7 @@
 }
 
 function testCookieStorePartitionedCookies({cookieNames, expectsCookie}) {
+  if (!window.cookieStore) return;
   promise_test(async () => {
     const cookies = await cookieStore.getAll({partitioned: true});
     for (const cookieName of cookieNames) {
@@ -53,3 +54,11 @@
     }
   }, getPartitionedCookieTestName(expectsCookie, "CookieStore"));
 }
+
+function getCookieNames() {
+  const cookieNames = ["__Host-pchttp", "__Host-pcdom"];
+  if (window.cookieStore) {
+    cookieNames.push("__Host-pccookiestore");
+  }
+  return cookieNames;
+}
diff --git a/third_party/blink/web_tests/external/wpt/urlpattern/resources/urlpatterntestdata.json b/third_party/blink/web_tests/external/wpt/urlpattern/resources/urlpatterntestdata.json
index 58a1ea3..56b3a0c 100644
--- a/third_party/blink/web_tests/external/wpt/urlpattern/resources/urlpatterntestdata.json
+++ b/third_party/blink/web_tests/external/wpt/urlpattern/resources/urlpatterntestdata.json
@@ -2794,5 +2794,50 @@
     "inputs": [{ "pathname": "/FOO", "search": "BAR", "hash": "BAZ",
                  "baseURL": "https://example.com:8080" }],
     "expected_obj": "error"
+  },
+  {
+    "pattern": [{ "search": "foo", "baseURL": "https://example.com/a/+/b" }],
+    "inputs": [{ "search": "foo", "baseURL": "https://example.com/a/+/b" }],
+    "exactly_empty_components": [ "username", "password", "port", "hash" ],
+    "expected_obj": {
+      "pathname": "/a/\\+/b"
+    },
+    "expected_match": {
+      "hostname": { "input": "example.com", "groups": {} },
+      "pathname": { "input": "/a/+/b", "groups": {} },
+      "protocol": { "input": "https", "groups": {} },
+      "search": { "input": "foo", "groups": {} }
+    }
+  },
+  {
+    "pattern": [{ "hash": "foo", "baseURL": "https://example.com/?q=*&v=?&hmm={}&umm=()" }],
+    "inputs": [{ "hash": "foo", "baseURL": "https://example.com/?q=*&v=?&hmm={}&umm=()" }],
+    "exactly_empty_components": [ "username", "password", "port" ],
+    "expected_obj": {
+      "search": "q=\\*&v=\\?&hmm=\\{\\}&umm=\\(\\)"
+    },
+    "expected_match": {
+      "hostname": { "input": "example.com", "groups": {} },
+      "pathname": { "input": "/", "groups": {} },
+      "protocol": { "input": "https", "groups": {} },
+      "search": { "input": "q=*&v=?&hmm={}&umm=()", "groups": {} },
+      "hash": { "input": "foo", "groups": {} }
+    }
+  },
+  {
+    "pattern": [ "#foo", "https://example.com/?q=*&v=?&hmm={}&umm=()" ],
+    "inputs": [ "https://example.com/?q=*&v=?&hmm={}&umm=()#foo" ],
+    "exactly_empty_components": [ "username", "password", "port" ],
+    "expected_obj": {
+      "search": "q=\\*&v=\\?&hmm=\\{\\}&umm=\\(\\)",
+      "hash": "foo"
+    },
+    "expected_match": {
+      "hostname": { "input": "example.com", "groups": {} },
+      "pathname": { "input": "/", "groups": {} },
+      "protocol": { "input": "https", "groups": {} },
+      "search": { "input": "q=*&v=?&hmm={}&umm=()", "groups": {} },
+      "hash": { "input": "foo", "groups": {} }
+    }
   }
 ]
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/third-party-cookie-blocking-first-party-set-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/third-party-cookie-blocking-first-party-set-expected.txt
new file mode 100644
index 0000000..2376934f
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/third-party-cookie-blocking-first-party-set-expected.txt
@@ -0,0 +1,14 @@
+Test third-party cookie blocking between sites in same First-Party Set
+Test started
+
+Running test: thirdPartyCookieBlockingDisabled
+Number of cookies: 0
+Number of cookies: 1
+Cookie not blocked: true
+
+Running test: thirdPartyCookieBlockingEnabled
+Number of cookies: 0
+Number of cookies: 1
+Cookie blocked: true
+Reasons: UserPreferences
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/third-party-cookie-blocking-first-party-set.js b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/third-party-cookie-blocking-first-party-set.js
new file mode 100644
index 0000000..580b0f01
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/third-party-cookie-blocking-first-party-set.js
@@ -0,0 +1,73 @@
+(async testRunner => {
+  const {page, session, dp} = await testRunner.startBlank(
+      'Test third-party cookie blocking between sites in same First-Party Set');
+
+  testRunner.log('Test started');
+  await dp.Network.enable();
+  await dp.Audits.enable();
+
+  testRunner.runTestSuite([
+    // Without third-party cookie blocking.
+    async function thirdPartyCookieBlockingDisabled() {
+      // Set the cookie.
+      const response = await dp.Network.setCookie({
+        url: 'https://cookie.test:8443',
+        secure: true,
+        name: 'foo',
+        value: 'bar',
+        sameSite: 'None',
+      });
+      if (response.error)
+        testRunner.log(`setCookie failed: ${response.error.message}`);
+
+      const handleRequestWillBeSent = event => {
+        testRunner.log(`Number of cookies: ${event.params.associatedCookies.length}`);
+        for (const cookie of event.params.associatedCookies) {
+          testRunner.log(`Cookie not blocked: ${!cookie.blockedReasons.length}`);
+        }
+      };
+      await dp.Network.onRequestWillBeSentExtraInfo(handleRequestWillBeSent);
+
+      await page.navigate('https://firstparty.test:8443/inspector-protocol/resources/iframe-third-party-cookie-parent-first-party-set.php');
+
+      await dp.Network.offRequestWillBeSentExtraInfo(handleRequestWillBeSent);
+    },
+    // With third-party cookie blocking.
+    async function thirdPartyCookieBlockingEnabled() {
+      await session.evaluate('testRunner.setBlockThirdPartyCookies(true)');
+
+      // Push events to arrays to prevent async races from causing flakes.
+      const requestWillBeSentExtraInfos = [];
+      const issueAddeds = [];
+
+      const handleRequestWillBeSent = event => {
+        requestWillBeSentExtraInfos.push(event.params);
+      };
+      await dp.Network.onRequestWillBeSentExtraInfo(handleRequestWillBeSent);
+
+      const handleIssueAdded = event => {
+        // Safely ignore irrelevant issue...
+        if (event.params.issue.code === 'QuirksModeIssue') return;
+        issueAddeds.push(event.params);
+      };
+      await dp.Audits.onIssueAdded(handleIssueAdded);
+
+      await page.navigate('https://firstparty.test:8443/inspector-protocol/resources/iframe-third-party-cookie-parent-first-party-set.php');
+
+      await dp.Network.offRequestWillBeSentExtraInfo(handleRequestWillBeSent);
+      await dp.Audits.offIssueAdded(handleIssueAdded);
+
+      for (const params of requestWillBeSentExtraInfos) {
+        testRunner.log(`Number of cookies: ${params.associatedCookies.length}`);
+        for (const cookie of params.associatedCookies) {
+          testRunner.log(`Cookie blocked: ${!!cookie.blockedReasons.length}`);
+          testRunner.log(`Reasons: ${cookie.blockedReasons}`);
+        }
+      }
+
+      for (const params of issueAddeds) {
+        testRunner.log(params);
+      }
+    },
+  ]);
+});
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/iframe-third-party-cookie-parent-first-party-set.php b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/iframe-third-party-cookie-parent-first-party-set.php
new file mode 100644
index 0000000..7002edb9
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/iframe-third-party-cookie-parent-first-party-set.php
@@ -0,0 +1 @@
+<iframe src="https://cookie.test:8443/inspector-protocol/resources/iframe-third-party-cookie-child.php"></iframe>
diff --git a/third_party/blink/web_tests/virtual/first-party-sets/http/tests/inspector-protocol/issues/third-party-cookie-blocking-first-party-set-expected.txt b/third_party/blink/web_tests/virtual/first-party-sets/http/tests/inspector-protocol/issues/third-party-cookie-blocking-first-party-set-expected.txt
new file mode 100644
index 0000000..e8bd4cb0
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/first-party-sets/http/tests/inspector-protocol/issues/third-party-cookie-blocking-first-party-set-expected.txt
@@ -0,0 +1,40 @@
+Test third-party cookie blocking between sites in same First-Party Set
+Test started
+
+Running test: thirdPartyCookieBlockingDisabled
+Number of cookies: 0
+Number of cookies: 1
+Cookie not blocked: true
+
+Running test: thirdPartyCookieBlockingEnabled
+Number of cookies: 0
+Number of cookies: 1
+Cookie blocked: true
+Reasons: UserPreferences,ThirdPartyBlockedInFirstPartySet
+{
+    issue : {
+        code : CookieIssue
+        details : {
+            cookieIssueDetails : {
+                cookie : {
+                    domain : cookie.test
+                    name : foo
+                    path : /
+                }
+                cookieExclusionReasons : [
+                    [0] : ExcludeThirdPartyCookieBlockedInFirstPartySet
+                ]
+                cookieUrl : https://cookie.test:8443/inspector-protocol/resources/iframe-third-party-cookie-child.php
+                cookieWarningReasons : [
+                ]
+                operation : ReadCookie
+                request : {
+                    requestId : <string>
+                    url : https://cookie.test:8443/inspector-protocol/resources/iframe-third-party-cookie-child.php
+                }
+                siteForCookies : https://firstparty.test/
+            }
+        }
+    }
+}
+
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-animations/parsing/animation-delay-end-computed-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-animations/parsing/animation-delay-end-computed-expected.txt
new file mode 100644
index 0000000..6e97800
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-animations/parsing/animation-delay-end-computed-expected.txt
@@ -0,0 +1,17 @@
+This is a testharness.js-based test.
+FAIL Property animation-delay-start value 'initial' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value '-500ms' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'calc(2 * 3s)' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value '20s, 10s' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'cover 0%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'COVER 0%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'cover 100%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'cover 120%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'cover 42%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'cover -42%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'contain 42%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'exit 42%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'exit calc(41% + 1%)' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'exit 1%, cover 2%, contain 100%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-animations/parsing/animation-delay-end-valid-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-animations/parsing/animation-delay-end-valid-expected.txt
new file mode 100644
index 0000000..160aedc
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-animations/parsing/animation-delay-end-valid-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+FAIL e.style['animation-delay-start'] = "-5ms" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "0s" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "10s" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "20s, 10s" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "cover 0%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "cover 100%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "cover 120%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "cover 42%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "cover -42%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "contain 42%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "exit 42%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "exit 1%, cover 2%, contain 100%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "enter 42%" should set the property value assert_not_equals: property should be set got disallowed value ""
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-animations/parsing/animation-delay-start-computed-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-animations/parsing/animation-delay-start-computed-expected.txt
new file mode 100644
index 0000000..6e97800
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-animations/parsing/animation-delay-start-computed-expected.txt
@@ -0,0 +1,17 @@
+This is a testharness.js-based test.
+FAIL Property animation-delay-start value 'initial' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value '-500ms' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'calc(2 * 3s)' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value '20s, 10s' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'cover 0%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'COVER 0%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'cover 100%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'cover 120%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'cover 42%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'cover -42%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'contain 42%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'exit 42%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'exit calc(41% + 1%)' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+FAIL Property animation-delay-start value 'exit 1%, cover 2%, contain 100%' assert_true: animation-delay-start doesn't seem to be supported in the computed style expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-animations/parsing/animation-delay-start-valid-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-animations/parsing/animation-delay-start-valid-expected.txt
new file mode 100644
index 0000000..160aedc
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-animations/parsing/animation-delay-start-valid-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+FAIL e.style['animation-delay-start'] = "-5ms" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "0s" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "10s" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "20s, 10s" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "cover 0%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "cover 100%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "cover 120%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "cover 42%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "cover -42%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "contain 42%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "exit 42%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "exit 1%, cover 2%, contain 100%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-delay-start'] = "enter 42%" should set the property value assert_not_equals: property should be set got disallowed value ""
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-animations/parsing/animation-shorthand-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-animations/parsing/animation-shorthand-expected.txt
new file mode 100644
index 0000000..90c1d9dad
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-animations/parsing/animation-shorthand-expected.txt
@@ -0,0 +1,33 @@
+This is a testharness.js-based test.
+PASS e.style['animation'] = "anim paused both reverse 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-delay
+PASS e.style['animation'] = "anim paused both reverse 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-direction
+PASS e.style['animation'] = "anim paused both reverse 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-duration
+PASS e.style['animation'] = "anim paused both reverse 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-fill-mode
+PASS e.style['animation'] = "anim paused both reverse 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-iteration-count
+PASS e.style['animation'] = "anim paused both reverse 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-name
+PASS e.style['animation'] = "anim paused both reverse 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-play-state
+FAIL e.style['animation'] = "anim paused both reverse 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-timeline assert_equals: animation-timeline should be canonical expected (string) "auto" but got (undefined) undefined
+PASS e.style['animation'] = "anim paused both reverse 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-timing-function
+PASS e.style['animation'] = "anim paused both reverse 4 1s -3s cubic-bezier(0, -2, 1, 3)" should not set unrelated longhands
+PASS e.style['animation'] = "anim paused both reverse, 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-delay
+PASS e.style['animation'] = "anim paused both reverse, 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-direction
+PASS e.style['animation'] = "anim paused both reverse, 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-duration
+PASS e.style['animation'] = "anim paused both reverse, 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-fill-mode
+PASS e.style['animation'] = "anim paused both reverse, 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-iteration-count
+PASS e.style['animation'] = "anim paused both reverse, 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-name
+PASS e.style['animation'] = "anim paused both reverse, 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-play-state
+FAIL e.style['animation'] = "anim paused both reverse, 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-timeline assert_equals: animation-timeline should be canonical expected (string) "auto, auto" but got (undefined) undefined
+PASS e.style['animation'] = "anim paused both reverse, 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set animation-timing-function
+PASS e.style['animation'] = "anim paused both reverse, 4 1s -3s cubic-bezier(0, -2, 1, 3)" should not set unrelated longhands
+PASS e.style['animation'] = "4 1s -3s cubic-bezier(0, -2, 1, 3), anim paused both reverse" should set animation-delay
+PASS e.style['animation'] = "4 1s -3s cubic-bezier(0, -2, 1, 3), anim paused both reverse" should set animation-direction
+PASS e.style['animation'] = "4 1s -3s cubic-bezier(0, -2, 1, 3), anim paused both reverse" should set animation-duration
+PASS e.style['animation'] = "4 1s -3s cubic-bezier(0, -2, 1, 3), anim paused both reverse" should set animation-fill-mode
+PASS e.style['animation'] = "4 1s -3s cubic-bezier(0, -2, 1, 3), anim paused both reverse" should set animation-iteration-count
+PASS e.style['animation'] = "4 1s -3s cubic-bezier(0, -2, 1, 3), anim paused both reverse" should set animation-name
+PASS e.style['animation'] = "4 1s -3s cubic-bezier(0, -2, 1, 3), anim paused both reverse" should set animation-play-state
+FAIL e.style['animation'] = "4 1s -3s cubic-bezier(0, -2, 1, 3), anim paused both reverse" should set animation-timeline assert_equals: animation-timeline should be canonical expected (string) "auto, auto" but got (undefined) undefined
+PASS e.style['animation'] = "4 1s -3s cubic-bezier(0, -2, 1, 3), anim paused both reverse" should set animation-timing-function
+PASS e.style['animation'] = "4 1s -3s cubic-bezier(0, -2, 1, 3), anim paused both reverse" should not set unrelated longhands
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-color-contrast-function-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-color-contrast-function-expected.txt
new file mode 100644
index 0000000..da359f0
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-color-contrast-function-expected.txt
@@ -0,0 +1,25 @@
+This is a testharness.js-based test.
+FAIL Property color value 'color-contrast(white vs red, blue)' assert_true: 'color-contrast(white vs red, blue)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(white vs blue, red)' assert_true: 'color-contrast(white vs blue, red)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(white vs red, blue, green)' assert_true: 'color-contrast(white vs red, blue, green)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(white vs white, white)' assert_true: 'color-contrast(white vs white, white)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(blue vs red, white)' assert_true: 'color-contrast(blue vs red, white)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(red vs blue, white, red)' assert_true: 'color-contrast(red vs blue, white, red)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(black vs red, blue)' assert_true: 'color-contrast(black vs red, blue)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(black vs blue, red)' assert_true: 'color-contrast(black vs blue, red)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(black vs white, white)' assert_true: 'color-contrast(black vs white, white)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(red vs blue, rgb(255, 255, 255, .5))' assert_true: 'color-contrast(red vs blue, rgb(255, 255, 255, .5))' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AA)' assert_true: 'color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AA)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AA-large)' assert_true: 'color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AA-large)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AAA)' assert_true: 'color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AAA)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AAA-large)' assert_true: 'color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AAA-large)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to 5.8)' assert_true: 'color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to 5.8)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(wheat vs bisque, darkgoldenrod, olive to 100)' assert_true: 'color-contrast(wheat vs bisque, darkgoldenrod, olive to 100)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(green vs bisque, darkgoldenrod, olive to 100)' assert_true: 'color-contrast(green vs bisque, darkgoldenrod, olive to 100)' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(green vs color(display-p3 0 1 0), color(display-p3 0 0 1))' assert_true: 'color-contrast(green vs color(display-p3 0 1 0), color(display-p3 0 0 1))' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(color(display-p3 1 1 0) vs color(display-p3 0 1 0), color(display-p3 0 0 1))' assert_true: 'color-contrast(color(display-p3 1 1 0) vs color(display-p3 0 1 0), color(display-p3 0 0 1))' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(green vs lab(50% -160 160), lch(0.2 50 20deg))' assert_true: 'color-contrast(green vs lab(50% -160 160), lch(0.2 50 20deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast(lab(50% -160 160) vs green, lch(0.2 50 20deg))' assert_true: 'color-contrast(lab(50% -160 160) vs green, lch(0.2 50 20deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-contrast( white vs red, blue )' assert_true: 'color-contrast( white vs red, blue )' is a supported value for color. expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-color-function-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-color-function-expected.txt
new file mode 100644
index 0000000..a892595
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-color-function-expected.txt
@@ -0,0 +1,444 @@
+This is a testharness.js-based test.
+Found 440 tests; 0 PASS, 440 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL Property color value 'color(srgb 0% 0% 0%)' assert_true: 'color(srgb 0% 0% 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 10% 10% 10%)' assert_true: 'color(srgb 10% 10% 10%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb .2 .2 25%)' assert_true: 'color(srgb .2 .2 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 0 0 0 / 1)' assert_true: 'color(srgb 0 0 0 / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 0% 0 0 / 0.5)' assert_true: 'color(srgb 0% 0 0 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 20% 0 10/0.5)' assert_true: 'color(srgb 20% 0 10/0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 20% 0 10/50%)' assert_true: 'color(srgb 20% 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 400% 0 10/50%)' assert_true: 'color(srgb 400% 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 50% -160 160)' assert_true: 'color(srgb 50% -160 160)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 50% -200 200)' assert_true: 'color(srgb 50% -200 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 0 0 0 / -10%)' assert_true: 'color(srgb 0 0 0 / -10%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 0 0 0 / 110%)' assert_true: 'color(srgb 0 0 0 / 110%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 0 0 0 / 300%)' assert_true: 'color(srgb 0 0 0 / 300%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 50% -200)' assert_true: 'color(srgb 50% -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 50%)' assert_true: 'color(srgb 50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb)' assert_true: 'color(srgb)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 50% -200 / 0.5)' assert_true: 'color(srgb 50% -200 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 50% / 0.5)' assert_true: 'color(srgb 50% / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb / 0.5)' assert_true: 'color(srgb / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 200 200 200)' assert_true: 'color(srgb 200 200 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 200 200 200 / 200)' assert_true: 'color(srgb 200 200 200 / 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb -200 -200 -200)' assert_true: 'color(srgb -200 -200 -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb -200 -200 -200 / -200)' assert_true: 'color(srgb -200 -200 -200 / -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 200% 200% 200%)' assert_true: 'color(srgb 200% 200% 200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 200% 200% 200% / 200%)' assert_true: 'color(srgb 200% 200% 200% / 200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb -200% -200% -200% / -200%)' assert_true: 'color(srgb -200% -200% -200% / -200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(srgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(srgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb none none none / none)' assert_true: 'color(srgb none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb none none none)' assert_true: 'color(srgb none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 10% none none / none)' assert_true: 'color(srgb 10% none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb none none none / 0.5)' assert_true: 'color(srgb none none none / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 0 0 0 / none)' assert_true: 'color(srgb 0 0 0 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 0% 0% 0%)' assert_true: 'color(srgb-linear 0% 0% 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 10% 10% 10%)' assert_true: 'color(srgb-linear 10% 10% 10%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear .2 .2 25%)' assert_true: 'color(srgb-linear .2 .2 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 0 0 0 / 1)' assert_true: 'color(srgb-linear 0 0 0 / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 0% 0 0 / 0.5)' assert_true: 'color(srgb-linear 0% 0 0 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 20% 0 10/0.5)' assert_true: 'color(srgb-linear 20% 0 10/0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 20% 0 10/50%)' assert_true: 'color(srgb-linear 20% 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 400% 0 10/50%)' assert_true: 'color(srgb-linear 400% 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 50% -160 160)' assert_true: 'color(srgb-linear 50% -160 160)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 50% -200 200)' assert_true: 'color(srgb-linear 50% -200 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 0 0 0 / -10%)' assert_true: 'color(srgb-linear 0 0 0 / -10%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 0 0 0 / 110%)' assert_true: 'color(srgb-linear 0 0 0 / 110%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 0 0 0 / 300%)' assert_true: 'color(srgb-linear 0 0 0 / 300%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 50% -200)' assert_true: 'color(srgb-linear 50% -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 50%)' assert_true: 'color(srgb-linear 50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear)' assert_true: 'color(srgb-linear)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 50% -200 / 0.5)' assert_true: 'color(srgb-linear 50% -200 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 50% / 0.5)' assert_true: 'color(srgb-linear 50% / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear / 0.5)' assert_true: 'color(srgb-linear / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 200 200 200)' assert_true: 'color(srgb-linear 200 200 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 200 200 200 / 200)' assert_true: 'color(srgb-linear 200 200 200 / 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear -200 -200 -200)' assert_true: 'color(srgb-linear -200 -200 -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear -200 -200 -200 / -200)' assert_true: 'color(srgb-linear -200 -200 -200 / -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 200% 200% 200%)' assert_true: 'color(srgb-linear 200% 200% 200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 200% 200% 200% / 200%)' assert_true: 'color(srgb-linear 200% 200% 200% / 200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear -200% -200% -200% / -200%)' assert_true: 'color(srgb-linear -200% -200% -200% / -200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(srgb-linear calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(srgb-linear calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear none none none / none)' assert_true: 'color(srgb-linear none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear none none none)' assert_true: 'color(srgb-linear none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 10% none none / none)' assert_true: 'color(srgb-linear 10% none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear none none none / 0.5)' assert_true: 'color(srgb-linear none none none / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 0 0 0 / none)' assert_true: 'color(srgb-linear 0 0 0 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 0% 0% 0%)' assert_true: 'color(a98-rgb 0% 0% 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 10% 10% 10%)' assert_true: 'color(a98-rgb 10% 10% 10%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb .2 .2 25%)' assert_true: 'color(a98-rgb .2 .2 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 0 0 0 / 1)' assert_true: 'color(a98-rgb 0 0 0 / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 0% 0 0 / 0.5)' assert_true: 'color(a98-rgb 0% 0 0 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 20% 0 10/0.5)' assert_true: 'color(a98-rgb 20% 0 10/0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 20% 0 10/50%)' assert_true: 'color(a98-rgb 20% 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 400% 0 10/50%)' assert_true: 'color(a98-rgb 400% 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 50% -160 160)' assert_true: 'color(a98-rgb 50% -160 160)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 50% -200 200)' assert_true: 'color(a98-rgb 50% -200 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 0 0 0 / -10%)' assert_true: 'color(a98-rgb 0 0 0 / -10%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 0 0 0 / 110%)' assert_true: 'color(a98-rgb 0 0 0 / 110%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 0 0 0 / 300%)' assert_true: 'color(a98-rgb 0 0 0 / 300%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 50% -200)' assert_true: 'color(a98-rgb 50% -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 50%)' assert_true: 'color(a98-rgb 50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb)' assert_true: 'color(a98-rgb)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 50% -200 / 0.5)' assert_true: 'color(a98-rgb 50% -200 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 50% / 0.5)' assert_true: 'color(a98-rgb 50% / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb / 0.5)' assert_true: 'color(a98-rgb / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 200 200 200)' assert_true: 'color(a98-rgb 200 200 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 200 200 200 / 200)' assert_true: 'color(a98-rgb 200 200 200 / 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb -200 -200 -200)' assert_true: 'color(a98-rgb -200 -200 -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb -200 -200 -200 / -200)' assert_true: 'color(a98-rgb -200 -200 -200 / -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 200% 200% 200%)' assert_true: 'color(a98-rgb 200% 200% 200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 200% 200% 200% / 200%)' assert_true: 'color(a98-rgb 200% 200% 200% / 200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb -200% -200% -200% / -200%)' assert_true: 'color(a98-rgb -200% -200% -200% / -200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(a98-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(a98-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb none none none / none)' assert_true: 'color(a98-rgb none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb none none none)' assert_true: 'color(a98-rgb none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 10% none none / none)' assert_true: 'color(a98-rgb 10% none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb none none none / 0.5)' assert_true: 'color(a98-rgb none none none / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 0 0 0 / none)' assert_true: 'color(a98-rgb 0 0 0 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 0% 0% 0%)' assert_true: 'color(rec2020 0% 0% 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 10% 10% 10%)' assert_true: 'color(rec2020 10% 10% 10%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 .2 .2 25%)' assert_true: 'color(rec2020 .2 .2 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 0 0 0 / 1)' assert_true: 'color(rec2020 0 0 0 / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 0% 0 0 / 0.5)' assert_true: 'color(rec2020 0% 0 0 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 20% 0 10/0.5)' assert_true: 'color(rec2020 20% 0 10/0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 20% 0 10/50%)' assert_true: 'color(rec2020 20% 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 400% 0 10/50%)' assert_true: 'color(rec2020 400% 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 50% -160 160)' assert_true: 'color(rec2020 50% -160 160)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 50% -200 200)' assert_true: 'color(rec2020 50% -200 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 0 0 0 / -10%)' assert_true: 'color(rec2020 0 0 0 / -10%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 0 0 0 / 110%)' assert_true: 'color(rec2020 0 0 0 / 110%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 0 0 0 / 300%)' assert_true: 'color(rec2020 0 0 0 / 300%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 50% -200)' assert_true: 'color(rec2020 50% -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 50%)' assert_true: 'color(rec2020 50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020)' assert_true: 'color(rec2020)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 50% -200 / 0.5)' assert_true: 'color(rec2020 50% -200 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 50% / 0.5)' assert_true: 'color(rec2020 50% / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 / 0.5)' assert_true: 'color(rec2020 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 200 200 200)' assert_true: 'color(rec2020 200 200 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 200 200 200 / 200)' assert_true: 'color(rec2020 200 200 200 / 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 -200 -200 -200)' assert_true: 'color(rec2020 -200 -200 -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 -200 -200 -200 / -200)' assert_true: 'color(rec2020 -200 -200 -200 / -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 200% 200% 200%)' assert_true: 'color(rec2020 200% 200% 200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 200% 200% 200% / 200%)' assert_true: 'color(rec2020 200% 200% 200% / 200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 -200% -200% -200% / -200%)' assert_true: 'color(rec2020 -200% -200% -200% / -200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(rec2020 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(rec2020 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 none none none / none)' assert_true: 'color(rec2020 none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 none none none)' assert_true: 'color(rec2020 none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 10% none none / none)' assert_true: 'color(rec2020 10% none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 none none none / 0.5)' assert_true: 'color(rec2020 none none none / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 0 0 0 / none)' assert_true: 'color(rec2020 0 0 0 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 0% 0% 0%)' assert_true: 'color(prophoto-rgb 0% 0% 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 10% 10% 10%)' assert_true: 'color(prophoto-rgb 10% 10% 10%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb .2 .2 25%)' assert_true: 'color(prophoto-rgb .2 .2 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 0 0 0 / 1)' assert_true: 'color(prophoto-rgb 0 0 0 / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 0% 0 0 / 0.5)' assert_true: 'color(prophoto-rgb 0% 0 0 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 20% 0 10/0.5)' assert_true: 'color(prophoto-rgb 20% 0 10/0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 20% 0 10/50%)' assert_true: 'color(prophoto-rgb 20% 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 400% 0 10/50%)' assert_true: 'color(prophoto-rgb 400% 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 50% -160 160)' assert_true: 'color(prophoto-rgb 50% -160 160)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 50% -200 200)' assert_true: 'color(prophoto-rgb 50% -200 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 0 0 0 / -10%)' assert_true: 'color(prophoto-rgb 0 0 0 / -10%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 0 0 0 / 110%)' assert_true: 'color(prophoto-rgb 0 0 0 / 110%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 0 0 0 / 300%)' assert_true: 'color(prophoto-rgb 0 0 0 / 300%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 50% -200)' assert_true: 'color(prophoto-rgb 50% -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 50%)' assert_true: 'color(prophoto-rgb 50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb)' assert_true: 'color(prophoto-rgb)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 50% -200 / 0.5)' assert_true: 'color(prophoto-rgb 50% -200 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 50% / 0.5)' assert_true: 'color(prophoto-rgb 50% / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb / 0.5)' assert_true: 'color(prophoto-rgb / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 200 200 200)' assert_true: 'color(prophoto-rgb 200 200 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 200 200 200 / 200)' assert_true: 'color(prophoto-rgb 200 200 200 / 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb -200 -200 -200)' assert_true: 'color(prophoto-rgb -200 -200 -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb -200 -200 -200 / -200)' assert_true: 'color(prophoto-rgb -200 -200 -200 / -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 200% 200% 200%)' assert_true: 'color(prophoto-rgb 200% 200% 200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 200% 200% 200% / 200%)' assert_true: 'color(prophoto-rgb 200% 200% 200% / 200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb -200% -200% -200% / -200%)' assert_true: 'color(prophoto-rgb -200% -200% -200% / -200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(prophoto-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(prophoto-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb none none none / none)' assert_true: 'color(prophoto-rgb none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb none none none)' assert_true: 'color(prophoto-rgb none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 10% none none / none)' assert_true: 'color(prophoto-rgb 10% none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb none none none / 0.5)' assert_true: 'color(prophoto-rgb none none none / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 0 0 0 / none)' assert_true: 'color(prophoto-rgb 0 0 0 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 0% 0% 0%)' assert_true: 'color(display-p3 0% 0% 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 10% 10% 10%)' assert_true: 'color(display-p3 10% 10% 10%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 .2 .2 25%)' assert_true: 'color(display-p3 .2 .2 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 0 0 0 / 1)' assert_true: 'color(display-p3 0 0 0 / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 0% 0 0 / 0.5)' assert_true: 'color(display-p3 0% 0 0 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 20% 0 10/0.5)' assert_true: 'color(display-p3 20% 0 10/0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 20% 0 10/50%)' assert_true: 'color(display-p3 20% 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 400% 0 10/50%)' assert_true: 'color(display-p3 400% 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 50% -160 160)' assert_true: 'color(display-p3 50% -160 160)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 50% -200 200)' assert_true: 'color(display-p3 50% -200 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 0 0 0 / -10%)' assert_true: 'color(display-p3 0 0 0 / -10%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 0 0 0 / 110%)' assert_true: 'color(display-p3 0 0 0 / 110%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 0 0 0 / 300%)' assert_true: 'color(display-p3 0 0 0 / 300%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 50% -200)' assert_true: 'color(display-p3 50% -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 50%)' assert_true: 'color(display-p3 50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3)' assert_true: 'color(display-p3)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 50% -200 / 0.5)' assert_true: 'color(display-p3 50% -200 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 50% / 0.5)' assert_true: 'color(display-p3 50% / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 / 0.5)' assert_true: 'color(display-p3 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 200 200 200)' assert_true: 'color(display-p3 200 200 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 200 200 200 / 200)' assert_true: 'color(display-p3 200 200 200 / 200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 -200 -200 -200)' assert_true: 'color(display-p3 -200 -200 -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 -200 -200 -200 / -200)' assert_true: 'color(display-p3 -200 -200 -200 / -200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 200% 200% 200%)' assert_true: 'color(display-p3 200% 200% 200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 200% 200% 200% / 200%)' assert_true: 'color(display-p3 200% 200% 200% / 200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 -200% -200% -200% / -200%)' assert_true: 'color(display-p3 -200% -200% -200% / -200%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(display-p3 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(display-p3 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 none none none / none)' assert_true: 'color(display-p3 none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 none none none)' assert_true: 'color(display-p3 none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 10% none none / none)' assert_true: 'color(display-p3 10% none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 none none none / 0.5)' assert_true: 'color(display-p3 none none none / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 0 0 0 / none)' assert_true: 'color(display-p3 0 0 0 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 0 0 0)' assert_true: 'color(xyz 0 0 0)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 0 0 0 / 1)' assert_true: 'color(xyz 0 0 0 / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 1 1 1)' assert_true: 'color(xyz 1 1 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 1 1 1 / 1)' assert_true: 'color(xyz 1 1 1 / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz -1 -1 -1)' assert_true: 'color(xyz -1 -1 -1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 0.1 0.1 0.1)' assert_true: 'color(xyz 0.1 0.1 0.1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 10 10 10)' assert_true: 'color(xyz 10 10 10)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz .2 .2 .25)' assert_true: 'color(xyz .2 .2 .25)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 0 0 0 / 0.5)' assert_true: 'color(xyz 0 0 0 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz .20 0 10/0.5)' assert_true: 'color(xyz .20 0 10/0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz .20 0 10/50%)' assert_true: 'color(xyz .20 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 0 0 0 / -10%)' assert_true: 'color(xyz 0 0 0 / -10%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 0 0 0 / 110%)' assert_true: 'color(xyz 0 0 0 / 110%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 0 0 0 / 300%)' assert_true: 'color(xyz 0 0 0 / 300%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 1 1)' assert_true: 'color(xyz 1 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 1)' assert_true: 'color(xyz 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz)' assert_true: 'color(xyz)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 1 1 / .5)' assert_true: 'color(xyz 1 1 / .5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 1 / 0.5)' assert_true: 'color(xyz 1 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz / 50%)' assert_true: 'color(xyz / 50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(xyz calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz none none none / none)' assert_true: 'color(xyz none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz none none none)' assert_true: 'color(xyz none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 0.2 none none / none)' assert_true: 'color(xyz 0.2 none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz none none none / 0.5)' assert_true: 'color(xyz none none none / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 0 0 0 / none)' assert_true: 'color(xyz 0 0 0 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 0 0 0)' assert_true: 'color(xyz-d50 0 0 0)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 0 0 0 / 1)' assert_true: 'color(xyz-d50 0 0 0 / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 1 1 1)' assert_true: 'color(xyz-d50 1 1 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 1 1 1 / 1)' assert_true: 'color(xyz-d50 1 1 1 / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 -1 -1 -1)' assert_true: 'color(xyz-d50 -1 -1 -1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 0.1 0.1 0.1)' assert_true: 'color(xyz-d50 0.1 0.1 0.1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 10 10 10)' assert_true: 'color(xyz-d50 10 10 10)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 .2 .2 .25)' assert_true: 'color(xyz-d50 .2 .2 .25)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 0 0 0 / 0.5)' assert_true: 'color(xyz-d50 0 0 0 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 .20 0 10/0.5)' assert_true: 'color(xyz-d50 .20 0 10/0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 .20 0 10/50%)' assert_true: 'color(xyz-d50 .20 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 0 0 0 / -10%)' assert_true: 'color(xyz-d50 0 0 0 / -10%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 0 0 0 / 110%)' assert_true: 'color(xyz-d50 0 0 0 / 110%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 0 0 0 / 300%)' assert_true: 'color(xyz-d50 0 0 0 / 300%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 1 1)' assert_true: 'color(xyz-d50 1 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 1)' assert_true: 'color(xyz-d50 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50)' assert_true: 'color(xyz-d50)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 1 1 / .5)' assert_true: 'color(xyz-d50 1 1 / .5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 1 / 0.5)' assert_true: 'color(xyz-d50 1 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 / 50%)' assert_true: 'color(xyz-d50 / 50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(xyz-d50 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 none none none / none)' assert_true: 'color(xyz-d50 none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 none none none)' assert_true: 'color(xyz-d50 none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 0.2 none none / none)' assert_true: 'color(xyz-d50 0.2 none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 none none none / 0.5)' assert_true: 'color(xyz-d50 none none none / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 0 0 0 / none)' assert_true: 'color(xyz-d50 0 0 0 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 0 0 0)' assert_true: 'color(xyz-d65 0 0 0)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 0 0 0 / 1)' assert_true: 'color(xyz-d65 0 0 0 / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 1 1 1)' assert_true: 'color(xyz-d65 1 1 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 1 1 1 / 1)' assert_true: 'color(xyz-d65 1 1 1 / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 -1 -1 -1)' assert_true: 'color(xyz-d65 -1 -1 -1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 0.1 0.1 0.1)' assert_true: 'color(xyz-d65 0.1 0.1 0.1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 10 10 10)' assert_true: 'color(xyz-d65 10 10 10)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 .2 .2 .25)' assert_true: 'color(xyz-d65 .2 .2 .25)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 0 0 0 / 0.5)' assert_true: 'color(xyz-d65 0 0 0 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 .20 0 10/0.5)' assert_true: 'color(xyz-d65 .20 0 10/0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 .20 0 10/50%)' assert_true: 'color(xyz-d65 .20 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 0 0 0 / -10%)' assert_true: 'color(xyz-d65 0 0 0 / -10%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 0 0 0 / 110%)' assert_true: 'color(xyz-d65 0 0 0 / 110%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 0 0 0 / 300%)' assert_true: 'color(xyz-d65 0 0 0 / 300%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 1 1)' assert_true: 'color(xyz-d65 1 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 1)' assert_true: 'color(xyz-d65 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65)' assert_true: 'color(xyz-d65)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 1 1 / .5)' assert_true: 'color(xyz-d65 1 1 / .5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 1 / 0.5)' assert_true: 'color(xyz-d65 1 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 / 50%)' assert_true: 'color(xyz-d65 / 50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(xyz-d65 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 none none none / none)' assert_true: 'color(xyz-d65 none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 none none none)' assert_true: 'color(xyz-d65 none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 0.2 none none / none)' assert_true: 'color(xyz-d65 0.2 none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 none none none / 0.5)' assert_true: 'color(xyz-d65 none none none / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 0 0 0 / none)' assert_true: 'color(xyz-d65 0 0 0 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 1.00 0.50 0.200)' [sRGB all numbers] assert_true: 'color(srgb 1.00 0.50 0.200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 100% 50% 20%)' [sRGB all percent] assert_true: 'color(srgb 100% 50% 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 100% 0.5 20%)' [sRGB mixed number and percent] assert_true: 'color(srgb 100% 0.5 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 1.00 50% 0.2)' [sRGB mixed number and percent 2] assert_true: 'color(srgb 1.00 50% 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb none none none)' [sRGB all none] assert_true: 'color(srgb none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 1.00 none 0.2)' [sRGB number and none] assert_true: 'color(srgb 1.00 none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 100% none 20%)' [sRGB percent and none] assert_true: 'color(srgb 100% none 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 100% none 0.2)' [sRGB number, percent and none] assert_true: 'color(srgb 100% none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 1.00 0.50 0.200 / 0.6)' [sRGB with alpha, all numbers] assert_true: 'color(srgb 1.00 0.50 0.200 / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 100% 50% 20% / 60%)' [sRGB with alpha, all percent] assert_true: 'color(srgb 100% 50% 20% / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 100% 0.5 20% / 0.6)' [sRGB with alpha, mixed number and percent] assert_true: 'color(srgb 100% 0.5 20% / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 1.00 50% 0.2 / 60%)' [sRGB with alpha, mixed number and percent 2] assert_true: 'color(srgb 1.00 50% 0.2 / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb none none none / none)' [sRGB with alpha, all none] assert_true: 'color(srgb none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 1.00 none 0.2 / none)' [sRGB with alpha, number and none] assert_true: 'color(srgb 1.00 none 0.2 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 100% none 20% / 30%)' [sRGB with alpha, percent and none] assert_true: 'color(srgb 100% none 20% / 30%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 100% none 0.2 / 23.7%)' [sRGB with alpha, number, percent and none] assert_true: 'color(srgb 100% none 0.2 / 23.7%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 1.00 0.50 0.200)' [Linear-light sRGB all numbers] assert_true: 'color(srgb-linear 1.00 0.50 0.200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 100% 50% 20%)' [Linear-light sRGB all percent] assert_true: 'color(srgb-linear 100% 50% 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 100% 0.5 20%)' [Linear-light sRGB mixed number and percent] assert_true: 'color(srgb-linear 100% 0.5 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 1.00 50% 0.2)' [Linear-light sRGB mixed number and percent 2] assert_true: 'color(srgb-linear 1.00 50% 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear none none none)' [Linear-light sRGB all none] assert_true: 'color(srgb-linear none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 1.00 none 0.2)' [Linear-light sRGB number and none] assert_true: 'color(srgb-linear 1.00 none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 100% none 20%)' [Linear-light sRGB percent and none] assert_true: 'color(srgb-linear 100% none 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 100% none 0.2)' [Linear-light sRGB number, percent and none] assert_true: 'color(srgb-linear 100% none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 1.00 0.50 0.200 / 0.6)' [Linear-light sRGB with alpha, all numbers] assert_true: 'color(srgb-linear 1.00 0.50 0.200 / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 100% 50% 20% / 60%)' [Linear-light sRGB with alpha, all percent] assert_true: 'color(srgb-linear 100% 50% 20% / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 100% 0.5 20% / 0.6)' [Linear-light sRGB with alpha, mixed number and percent] assert_true: 'color(srgb-linear 100% 0.5 20% / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 1.00 50% 0.2 / 60%)' [Linear-light sRGB with alpha, mixed number and percent 2] assert_true: 'color(srgb-linear 1.00 50% 0.2 / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear none none none / none)' [Linear-light sRGB with alpha, all none] assert_true: 'color(srgb-linear none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 1.00 none 0.2 / none)' [Linear-light sRGB with alpha, number and none] assert_true: 'color(srgb-linear 1.00 none 0.2 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 100% none 20% / 30%)' [Linear-light sRGB with alpha, percent and none] assert_true: 'color(srgb-linear 100% none 20% / 30%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb-linear 100% none 0.2 / 23.7%)' [Linear-light sRGB with alpha, number, percent and none] assert_true: 'color(srgb-linear 100% none 0.2 / 23.7%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 1.00 0.50 0.200)' [Display P3 all numbers] assert_true: 'color(display-p3 1.00 0.50 0.200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 100% 50% 20%)' [Display P3 all percent] assert_true: 'color(display-p3 100% 50% 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 100% 0.5 20%)' [Display P3 mixed number and percent] assert_true: 'color(display-p3 100% 0.5 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 1.00 50% 0.2)' [Display P3 mixed number and percent 2] assert_true: 'color(display-p3 1.00 50% 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 none none none)' [Display P3 all none] assert_true: 'color(display-p3 none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 1.00 none 0.2)' [Display P3 number and none] assert_true: 'color(display-p3 1.00 none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 100% none 20%)' [Display P3 percent and none] assert_true: 'color(display-p3 100% none 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 100% none 0.2)' [Display P3 number, percent and none] assert_true: 'color(display-p3 100% none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 1.00 0.50 0.200 / 0.6)' [Display P3 with alpha, all numbers] assert_true: 'color(display-p3 1.00 0.50 0.200 / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 100% 50% 20% / 60%)' [Display P3 with alpha, all percent] assert_true: 'color(display-p3 100% 50% 20% / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 100% 0.5 20% / 0.6)' [Display P3 with alpha, mixed number and percent] assert_true: 'color(display-p3 100% 0.5 20% / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 1.00 50% 0.2 / 60%)' [Display P3 with alpha, mixed number and percent 2] assert_true: 'color(display-p3 1.00 50% 0.2 / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 none none none / none)' [Display P3 with alpha, all none] assert_true: 'color(display-p3 none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 1.00 none 0.2 / none)' [Display P3 with alpha, number and none] assert_true: 'color(display-p3 1.00 none 0.2 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 100% none 20% / 30%)' [Display P3 with alpha, percent and none] assert_true: 'color(display-p3 100% none 20% / 30%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 100% none 0.2 / 23.7%)' [Display P3 with alpha, number, percent and none] assert_true: 'color(display-p3 100% none 0.2 / 23.7%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 1.00 0.50 0.200)' [A98 RGB all numbers] assert_true: 'color(a98-rgb 1.00 0.50 0.200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 100% 50% 20%)' [A98 RGB all percent] assert_true: 'color(a98-rgb 100% 50% 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 100% 0.5 20%)' [A98 RGB mixed number and percent] assert_true: 'color(a98-rgb 100% 0.5 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 1.00 50% 0.2)' [A98 RGB mixed number and percent 2] assert_true: 'color(a98-rgb 1.00 50% 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb none none none)' [A98 RGB all none] assert_true: 'color(a98-rgb none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 1.00 none 0.2)' [A98 RGB number and none] assert_true: 'color(a98-rgb 1.00 none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 100% none 20%)' [A98 RGB percent and none] assert_true: 'color(a98-rgb 100% none 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 100% none 0.2)' [A98 RGB number, percent and none] assert_true: 'color(a98-rgb 100% none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 1.00 0.50 0.200 / 0.6)' [A98 RGB with alpha, all numbers] assert_true: 'color(a98-rgb 1.00 0.50 0.200 / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 100% 50% 20% / 60%)' [A98 RGB with alpha, all percent] assert_true: 'color(a98-rgb 100% 50% 20% / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 100% 0.5 20% / 0.6)' [A98 RGB with alpha, mixed number and percent] assert_true: 'color(a98-rgb 100% 0.5 20% / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 1.00 50% 0.2 / 60%)' [A98 RGB with alpha, mixed number and percent 2] assert_true: 'color(a98-rgb 1.00 50% 0.2 / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb none none none / none)' [A98 RGB with alpha, all none] assert_true: 'color(a98-rgb none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 1.00 none 0.2 / none)' [A98 RGB with alpha, number and none] assert_true: 'color(a98-rgb 1.00 none 0.2 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 100% none 20% / 30%)' [A98 RGB with alpha, percent and none] assert_true: 'color(a98-rgb 100% none 20% / 30%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(a98-rgb 100% none 0.2 / 23.7%)' [A98 RGB with alpha, number, percent and none] assert_true: 'color(a98-rgb 100% none 0.2 / 23.7%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 1.00 0.50 0.200)' [ProPhoto RGB all numbers] assert_true: 'color(prophoto-rgb 1.00 0.50 0.200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 100% 50% 20%)' [ProPhoto RGB all percent] assert_true: 'color(prophoto-rgb 100% 50% 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 100% 0.5 20%)' [ProPhoto RGB mixed number and percent] assert_true: 'color(prophoto-rgb 100% 0.5 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 1.00 50% 0.2)' [ProPhoto RGB mixed number and percent 2] assert_true: 'color(prophoto-rgb 1.00 50% 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb none none none)' [ProPhoto RGB all none] assert_true: 'color(prophoto-rgb none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 1.00 none 0.2)' [ProPhoto RGB number and none] assert_true: 'color(prophoto-rgb 1.00 none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 100% none 20%)' [ProPhoto RGB percent and none] assert_true: 'color(prophoto-rgb 100% none 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 100% none 0.2)' [ProPhoto RGB number, percent and none] assert_true: 'color(prophoto-rgb 100% none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 1.00 0.50 0.200 / 0.6)' [ProPhoto RGB with alpha, all numbers] assert_true: 'color(prophoto-rgb 1.00 0.50 0.200 / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 100% 50% 20% / 60%)' [ProPhoto RGB with alpha, all percent] assert_true: 'color(prophoto-rgb 100% 50% 20% / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 100% 0.5 20% / 0.6)' [ProPhoto RGB with alpha, mixed number and percent] assert_true: 'color(prophoto-rgb 100% 0.5 20% / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 1.00 50% 0.2 / 60%)' [ProPhoto RGB with alpha, mixed number and percent 2] assert_true: 'color(prophoto-rgb 1.00 50% 0.2 / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb none none none / none)' [ProPhoto RGB with alpha, all none] assert_true: 'color(prophoto-rgb none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 1.00 none 0.2 / none)' [ProPhoto RGB with alpha, number and none] assert_true: 'color(prophoto-rgb 1.00 none 0.2 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 100% none 20% / 30%)' [ProPhoto RGB with alpha, percent and none] assert_true: 'color(prophoto-rgb 100% none 20% / 30%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(prophoto-rgb 100% none 0.2 / 23.7%)' [ProPhoto RGB with alpha, number, percent and none] assert_true: 'color(prophoto-rgb 100% none 0.2 / 23.7%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 1.00 0.50 0.200)' [Rec BT.2020 all numbers] assert_true: 'color(rec2020 1.00 0.50 0.200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 100% 50% 20%)' [Rec BT.2020 all percent] assert_true: 'color(rec2020 100% 50% 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 100% 0.5 20%)' [Rec BT.2020 mixed number and percent] assert_true: 'color(rec2020 100% 0.5 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 1.00 50% 0.2)' [Rec BT.2020 mixed number and percent 2] assert_true: 'color(rec2020 1.00 50% 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 none none none)' [Rec BT.2020 all none] assert_true: 'color(rec2020 none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 1.00 none 0.2)' [Rec BT.2020 number and none] assert_true: 'color(rec2020 1.00 none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 100% none 20%)' [Rec BT.2020 percent and none] assert_true: 'color(rec2020 100% none 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 100% none 0.2)' [Rec BT.2020 number, percent and none] assert_true: 'color(rec2020 100% none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 1.00 0.50 0.200 / 0.6)' [Rec BT.2020 with alpha, all numbers] assert_true: 'color(rec2020 1.00 0.50 0.200 / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 100% 50% 20% / 60%)' [Rec BT.2020 with alpha, all percent] assert_true: 'color(rec2020 100% 50% 20% / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 100% 0.5 20% / 0.6)' [Rec BT.2020 with alpha, mixed number and percent] assert_true: 'color(rec2020 100% 0.5 20% / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 1.00 50% 0.2 / 60%)' [Rec BT.2020 with alpha, mixed number and percent 2] assert_true: 'color(rec2020 1.00 50% 0.2 / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 none none none / none)' [Rec BT.2020 with alpha, all none] assert_true: 'color(rec2020 none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 1.00 none 0.2 / none)' [Rec BT.2020 with alpha, number and none] assert_true: 'color(rec2020 1.00 none 0.2 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 100% none 20% / 30%)' [Rec BT.2020 with alpha, percent and none] assert_true: 'color(rec2020 100% none 20% / 30%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(rec2020 100% none 0.2 / 23.7%)' [Rec BT.2020 with alpha, number, percent and none] assert_true: 'color(rec2020 100% none 0.2 / 23.7%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 1.00 0.50 0.200)' [CIE XYZ D50 all numbers] assert_true: 'color(xyz-d50 1.00 0.50 0.200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 100% 50% 20%)' [CIE XYZ D50 all percent] assert_true: 'color(xyz-d50 100% 50% 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 100% 0.5 20%)' [CIE XYZ D50 mixed number and percent] assert_true: 'color(xyz-d50 100% 0.5 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 1.00 50% 0.2)' [CIE XYZ D50 mixed number and percent 2] assert_true: 'color(xyz-d50 1.00 50% 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 none none none)' [CIE XYZ D50 all none] assert_true: 'color(xyz-d50 none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 1.00 none 0.2)' [CIE XYZ D50 number and none] assert_true: 'color(xyz-d50 1.00 none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 100% none 20%)' [CIE XYZ D50 percent and none] assert_true: 'color(xyz-d50 100% none 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 100% none 0.2)' [CIE XYZ D50 number, percent and none] assert_true: 'color(xyz-d50 100% none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 1.00 0.50 0.200 / 0.6)' [CIE XYZ D50 with alpha, all numbers] assert_true: 'color(xyz-d50 1.00 0.50 0.200 / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 100% 50% 20% / 60%)' [CIE XYZ D50 with alpha, all percent] assert_true: 'color(xyz-d50 100% 50% 20% / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 100% 0.5 20% / 0.6)' [CIE XYZ D50 with alpha, mixed number and percent] assert_true: 'color(xyz-d50 100% 0.5 20% / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 1.00 50% 0.2 / 60%)' [CIE XYZ D50 with alpha, mixed number and percent 2] assert_true: 'color(xyz-d50 1.00 50% 0.2 / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 none none none / none)' [CIE XYZ D50 with alpha, all none] assert_true: 'color(xyz-d50 none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 1.00 none 0.2 / none)' [CIE XYZ D50 with alpha, number and none] assert_true: 'color(xyz-d50 1.00 none 0.2 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 100% none 20% / 30%)' [CIE XYZ D50 with alpha, percent and none] assert_true: 'color(xyz-d50 100% none 20% / 30%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d50 100% none 0.2 / 23.7%)' [CIE XYZ D50 with alpha, number, percent and none] assert_true: 'color(xyz-d50 100% none 0.2 / 23.7%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 1.00 0.50 0.200)' [CIE XYZ D65 all numbers] assert_true: 'color(xyz-d65 1.00 0.50 0.200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 100% 50% 20%)' [CIE XYZ D65 all percent] assert_true: 'color(xyz-d65 100% 50% 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 100% 0.5 20%)' [CIE XYZ D65 mixed number and percent] assert_true: 'color(xyz-d65 100% 0.5 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 1.00 50% 0.2)' [CIE XYZ D65 mixed number and percent 2] assert_true: 'color(xyz-d65 1.00 50% 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 none none none)' [CIE XYZ D65 all none] assert_true: 'color(xyz-d65 none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 1.00 none 0.2)' [CIE XYZ D65 number and none] assert_true: 'color(xyz-d65 1.00 none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 100% none 20%)' [CIE XYZ D65 percent and none] assert_true: 'color(xyz-d65 100% none 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 100% none 0.2)' [CIE XYZ D65 number, percent and none] assert_true: 'color(xyz-d65 100% none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 1.00 0.50 0.200 / 0.6)' [CIE XYZ D65 with alpha, all numbers] assert_true: 'color(xyz-d65 1.00 0.50 0.200 / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 100% 50% 20% / 60%)' [CIE XYZ D65 with alpha, all percent] assert_true: 'color(xyz-d65 100% 50% 20% / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 100% 0.5 20% / 0.6)' [CIE XYZ D65 with alpha, mixed number and percent] assert_true: 'color(xyz-d65 100% 0.5 20% / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 1.00 50% 0.2 / 60%)' [CIE XYZ D65 with alpha, mixed number and percent 2] assert_true: 'color(xyz-d65 1.00 50% 0.2 / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 none none none / none)' [CIE XYZ D65 with alpha, all none] assert_true: 'color(xyz-d65 none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 1.00 none 0.2 / none)' [CIE XYZ D65 with alpha, number and none] assert_true: 'color(xyz-d65 1.00 none 0.2 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 100% none 20% / 30%)' [CIE XYZ D65 with alpha, percent and none] assert_true: 'color(xyz-d65 100% none 20% / 30%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz-d65 100% none 0.2 / 23.7%)' [CIE XYZ D65 with alpha, number, percent and none] assert_true: 'color(xyz-d65 100% none 0.2 / 23.7%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 1.00 0.50 0.200)' [CIE XYZ (implicit D65) all numbers] assert_true: 'color(xyz 1.00 0.50 0.200)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 100% 50% 20%)' [CIE XYZ (implicit D65) all percent] assert_true: 'color(xyz 100% 50% 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 100% 0.5 20%)' [CIE XYZ (implicit D65) mixed number and percent] assert_true: 'color(xyz 100% 0.5 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 1.00 50% 0.2)' [CIE XYZ (implicit D65) mixed number and percent 2] assert_true: 'color(xyz 1.00 50% 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz none none none)' [CIE XYZ (implicit D65) all none] assert_true: 'color(xyz none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 1.00 none 0.2)' [CIE XYZ (implicit D65) number and none] assert_true: 'color(xyz 1.00 none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 100% none 20%)' [CIE XYZ (implicit D65) percent and none] assert_true: 'color(xyz 100% none 20%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 100% none 0.2)' [CIE XYZ (implicit D65) number, percent and none] assert_true: 'color(xyz 100% none 0.2)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 1.00 0.50 0.200 / 0.6)' [CIE XYZ (implicit D65) with alpha, all numbers] assert_true: 'color(xyz 1.00 0.50 0.200 / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 100% 50% 20% / 60%)' [CIE XYZ (implicit D65) with alpha, all percent] assert_true: 'color(xyz 100% 50% 20% / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 100% 0.5 20% / 0.6)' [CIE XYZ (implicit D65) with alpha, mixed number and percent] assert_true: 'color(xyz 100% 0.5 20% / 0.6)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 1.00 50% 0.2 / 60%)' [CIE XYZ (implicit D65) with alpha, mixed number and percent 2] assert_true: 'color(xyz 1.00 50% 0.2 / 60%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz none none none / none)' [CIE XYZ (implicit D65) with alpha, all none] assert_true: 'color(xyz none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 1.00 none 0.2 / none)' [CIE XYZ (implicit D65) with alpha, number and none] assert_true: 'color(xyz 1.00 none 0.2 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 100% none 20% / 30%)' [CIE XYZ (implicit D65) with alpha, percent and none] assert_true: 'color(xyz 100% none 20% / 30%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(xyz 100% none 0.2 / 23.7%)' [CIE XYZ (implicit D65) with alpha, number, percent and none] assert_true: 'color(xyz 100% none 0.2 / 23.7%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 1 1 1)' [Basic sRGB white] assert_true: 'color(srgb 1 1 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(    srgb         1      1 1       )' [White with lots of space] assert_true: 'color(    srgb         1      1 1       )' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 0.25 0.5 0.75)' [sRGB color] assert_true: 'color(srgb 0.25 0.5 0.75)' is a supported value for color. expected true got false
+FAIL Property color value 'color(SrGb 0.25 0.5 0.75)' [Different case for sRGB] assert_true: 'color(SrGb 0.25 0.5 0.75)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 1.00000 0.500000 0.20)' [sRGB color with unnecessary decimals] assert_true: 'color(srgb 1.00000 0.500000 0.20)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 1 1 1 / 0.5)' [sRGB white with 0.5 alpha] assert_true: 'color(srgb 1 1 1 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 1 1 1 / 0)' [sRGB white with 0 alpha] assert_true: 'color(srgb 1 1 1 / 0)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 1 1 1 / 50%)' [sRGB white with 50% alpha] assert_true: 'color(srgb 1 1 1 / 50%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 1 1 1 / 0%)' [sRGB white with 0% alpha] assert_true: 'color(srgb 1 1 1 / 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 1 1)' [One missing component is 0] assert_true: 'color(srgb 1 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 1)' [Two missing components are 0] assert_true: 'color(srgb 1)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb)' [All components missing] assert_true: 'color(srgb)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 0.6 0.7 0.8)' [Display P3 color] assert_true: 'color(display-p3 0.6 0.7 0.8)' is a supported value for color. expected true got false
+FAIL Property color value 'color(dIspLaY-P3 0.6 0.7 0.8)' [Different case for Display P3] assert_true: 'color(dIspLaY-P3 0.6 0.7 0.8)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb -0.25 0.5 0.75)' [sRGB color with negative component should not clamp to 0] assert_true: 'color(srgb -0.25 0.5 0.75)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 0.25 1.5 0.75)' [sRGB color with component > 1 should not clamp] assert_true: 'color(srgb 0.25 1.5 0.75)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 0.5 -199 0.75)' [Display P3 color with negative component should not clamp to 0] assert_true: 'color(display-p3 0.5 -199 0.75)' is a supported value for color. expected true got false
+FAIL Property color value 'color(display-p3 184 1.00001 2347329746587)' [Display P3 color with component > 1 should not clamp] assert_true: 'color(display-p3 184 1.00001 2347329746587)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 0.1 0.2 0.3 / 1.9)' [Alpha > 1 should clamp] assert_true: 'color(srgb 0.1 0.2 0.3 / 1.9)' is a supported value for color. expected true got false
+FAIL Property color value 'color(srgb 1 1 1 / -0.2)' [Negative alpha should clamp] assert_true: 'color(srgb 1 1 1 / -0.2)' is a supported value for color. expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-color-mix-function-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-color-mix-function-expected.txt
new file mode 100644
index 0000000..78784ba
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-color-mix-function-expected.txt
@@ -0,0 +1,478 @@
+This is a testharness.js-based test.
+Found 474 tests; 0 PASS, 474 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%), 25% hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%), 25% hsl(30deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 30%, hsl(30deg 30% 40%) 90%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 30%, hsl(30deg 30% 40%) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40% / .8))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40% / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, 25% hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))' assert_true: 'color-mix(in hsl, 25% hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4), 25% hsl(30deg 30% 40% / .8))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4), 25% hsl(30deg 30% 40% / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8) 25%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 25%, hsl(30deg 30% 40% / .8) 75%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 25%, hsl(30deg 30% 40% / .8) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 30%, hsl(30deg 30% 40% / .8) 90%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 30%, hsl(30deg 30% 40% / .8) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 12.5%, hsl(30deg 30% 40% / .8) 37.5%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 12.5%, hsl(30deg 30% 40% / .8) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 0%, hsl(30deg 30% 40% / .8))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 0%, hsl(30deg 30% 40% / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl shorter hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl shorter hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl shorter hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl shorter hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl shorter hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl shorter hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl longer hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl longer hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl longer hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl longer hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl longer hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl longer hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl increasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl increasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl increasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl increasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl increasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl increasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl specified hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl specified hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl specified hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl specified hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(none none none), hsl(none none none))' assert_true: 'color-mix(in hsl, hsl(none none none), hsl(none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))' assert_true: 'color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))' assert_true: 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))' assert_true: 'color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))' assert_true: 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))' assert_true: 'color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))' assert_true: 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))' assert_true: 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, lab(100 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lab(100 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, lab(0 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lab(0 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, lch(100 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lch(100 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, lch(0 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lch(0 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, oklab(100 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklab(100 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, oklab(0 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklab(0 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, oklch(100 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklch(100 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hsl, oklch(0 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklch(0 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 30%, hwb(30deg 30% 40%) 90%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 30%, hwb(30deg 30% 40%) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, 25% hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))' assert_true: 'color-mix(in hwb, 25% hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40% / .8))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40% / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8) 25%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8) 75%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 30%, hwb(30deg 30% 40% / .8) 90%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 30%, hwb(30deg 30% 40% / .8) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 12.5%, hwb(30deg 30% 40% / .8) 37.5%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 12.5%, hwb(30deg 30% 40% / .8) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 0%, hwb(30deg 30% 40% / .8))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 0%, hwb(30deg 30% 40% / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb shorter hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb shorter hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb shorter hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb shorter hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb shorter hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb shorter hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb longer hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb longer hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb longer hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb longer hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb longer hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb longer hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb increasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb increasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb increasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb increasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb increasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb increasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb specified hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb specified hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb specified hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb specified hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(none none none), hwb(none none none))' assert_true: 'color-mix(in hwb, hwb(none none none), hwb(none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))' assert_true: 'color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, lab(100 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lab(100 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, lab(0 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lab(0 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, lch(100 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lch(100 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, lch(0 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lch(0 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, oklab(100 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklab(100 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, oklab(0 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklab(0 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, oklch(100 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklch(100 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in hwb, oklch(0 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklch(0 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg), lch(50 60 70deg))' assert_true: 'color-mix(in lch, lch(10 20 30deg), lch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg) 25%, lch(50 60 70deg))' assert_true: 'color-mix(in lch, lch(10 20 30deg) 25%, lch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, 25% lch(10 20 30deg), lch(50 60 70deg))' assert_true: 'color-mix(in lch, 25% lch(10 20 30deg), lch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg), 25% lch(50 60 70deg))' assert_true: 'color-mix(in lch, lch(10 20 30deg), 25% lch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg), lch(50 60 70deg) 25%)' assert_true: 'color-mix(in lch, lch(10 20 30deg), lch(50 60 70deg) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg) 25%, lch(50 60 70deg) 75%)' assert_true: 'color-mix(in lch, lch(10 20 30deg) 25%, lch(50 60 70deg) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg) 30%, lch(50 60 70deg) 90%)' assert_true: 'color-mix(in lch, lch(10 20 30deg) 30%, lch(50 60 70deg) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg) 12.5%, lch(50 60 70deg) 37.5%)' assert_true: 'color-mix(in lch, lch(10 20 30deg) 12.5%, lch(50 60 70deg) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg) 0%, lch(50 60 70deg))' assert_true: 'color-mix(in lch, lch(10 20 30deg) 0%, lch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg / .4), lch(50 60 70deg / .8))' assert_true: 'color-mix(in lch, lch(10 20 30deg / .4), lch(50 60 70deg / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg / .4) 25%, lch(50 60 70deg / .8))' assert_true: 'color-mix(in lch, lch(10 20 30deg / .4) 25%, lch(50 60 70deg / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, 25% lch(10 20 30deg / .4), lch(50 60 70deg / .8))' assert_true: 'color-mix(in lch, 25% lch(10 20 30deg / .4), lch(50 60 70deg / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg / .4), 25% lch(50 60 70deg / .8))' assert_true: 'color-mix(in lch, lch(10 20 30deg / .4), 25% lch(50 60 70deg / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg / .4), lch(50 60 70deg / .8) 25%)' assert_true: 'color-mix(in lch, lch(10 20 30deg / .4), lch(50 60 70deg / .8) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg / .4) 25%, lch(50 60 70deg / .8) 75%)' assert_true: 'color-mix(in lch, lch(10 20 30deg / .4) 25%, lch(50 60 70deg / .8) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg / .4) 30%, lch(50 60 70deg / .8) 90%)' assert_true: 'color-mix(in lch, lch(10 20 30deg / .4) 30%, lch(50 60 70deg / .8) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg / .4) 12.5%, lch(50 60 70deg / .8) 37.5%)' assert_true: 'color-mix(in lch, lch(10 20 30deg / .4) 12.5%, lch(50 60 70deg / .8) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg / .4) 0%, lch(50 60 70deg / .8))' assert_true: 'color-mix(in lch, lch(10 20 30deg / .4) 0%, lch(50 60 70deg / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(100 0 40deg), lch(100 0 60deg))' assert_true: 'color-mix(in lch, lch(100 0 40deg), lch(100 0 60deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(100 0 60deg), lch(100 0 40deg))' assert_true: 'color-mix(in lch, lch(100 0 60deg), lch(100 0 40deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(100 0 50deg), lch(100 0 330deg))' assert_true: 'color-mix(in lch, lch(100 0 50deg), lch(100 0 330deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(100 0 330deg), lch(100 0 50deg))' assert_true: 'color-mix(in lch, lch(100 0 330deg), lch(100 0 50deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(100 0 20deg), lch(100 0 320deg))' assert_true: 'color-mix(in lch, lch(100 0 20deg), lch(100 0 320deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(100 0 320deg), lch(100 0 20deg))' assert_true: 'color-mix(in lch, lch(100 0 320deg), lch(100 0 20deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch shorter hue, lch(100 0 40deg), lch(100 0 60deg))' assert_true: 'color-mix(in lch shorter hue, lch(100 0 40deg), lch(100 0 60deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch shorter hue, lch(100 0 60deg), lch(100 0 40deg))' assert_true: 'color-mix(in lch shorter hue, lch(100 0 60deg), lch(100 0 40deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch shorter hue, lch(100 0 50deg), lch(100 0 330deg))' assert_true: 'color-mix(in lch shorter hue, lch(100 0 50deg), lch(100 0 330deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch shorter hue, lch(100 0 330deg), lch(100 0 50deg))' assert_true: 'color-mix(in lch shorter hue, lch(100 0 330deg), lch(100 0 50deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch shorter hue, lch(100 0 20deg), lch(100 0 320deg))' assert_true: 'color-mix(in lch shorter hue, lch(100 0 20deg), lch(100 0 320deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch shorter hue, lch(100 0 320deg), lch(100 0 20deg))' assert_true: 'color-mix(in lch shorter hue, lch(100 0 320deg), lch(100 0 20deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch longer hue, lch(100 0 40deg), lch(100 0 60deg))' assert_true: 'color-mix(in lch longer hue, lch(100 0 40deg), lch(100 0 60deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch longer hue, lch(100 0 60deg), lch(100 0 40deg))' assert_true: 'color-mix(in lch longer hue, lch(100 0 60deg), lch(100 0 40deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch longer hue, lch(100 0 50deg), lch(100 0 330deg))' assert_true: 'color-mix(in lch longer hue, lch(100 0 50deg), lch(100 0 330deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch longer hue, lch(100 0 330deg), lch(100 0 50deg))' assert_true: 'color-mix(in lch longer hue, lch(100 0 330deg), lch(100 0 50deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch longer hue, lch(100 0 20deg), lch(100 0 320deg))' assert_true: 'color-mix(in lch longer hue, lch(100 0 20deg), lch(100 0 320deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch longer hue, lch(100 0 320deg), lch(100 0 20deg))' assert_true: 'color-mix(in lch longer hue, lch(100 0 320deg), lch(100 0 20deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch increasing hue, lch(100 0 40deg), lch(100 0 60deg))' assert_true: 'color-mix(in lch increasing hue, lch(100 0 40deg), lch(100 0 60deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch increasing hue, lch(100 0 60deg), lch(100 0 40deg))' assert_true: 'color-mix(in lch increasing hue, lch(100 0 60deg), lch(100 0 40deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch increasing hue, lch(100 0 50deg), lch(100 0 330deg))' assert_true: 'color-mix(in lch increasing hue, lch(100 0 50deg), lch(100 0 330deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch increasing hue, lch(100 0 330deg), lch(100 0 50deg))' assert_true: 'color-mix(in lch increasing hue, lch(100 0 330deg), lch(100 0 50deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch increasing hue, lch(100 0 20deg), lch(100 0 320deg))' assert_true: 'color-mix(in lch increasing hue, lch(100 0 20deg), lch(100 0 320deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch increasing hue, lch(100 0 320deg), lch(100 0 20deg))' assert_true: 'color-mix(in lch increasing hue, lch(100 0 320deg), lch(100 0 20deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch decreasing hue, lch(100 0 40deg), lch(100 0 60deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100 0 40deg), lch(100 0 60deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch decreasing hue, lch(100 0 60deg), lch(100 0 40deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100 0 60deg), lch(100 0 40deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch decreasing hue, lch(100 0 50deg), lch(100 0 330deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100 0 50deg), lch(100 0 330deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch decreasing hue, lch(100 0 330deg), lch(100 0 50deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100 0 330deg), lch(100 0 50deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch decreasing hue, lch(100 0 20deg), lch(100 0 320deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100 0 20deg), lch(100 0 320deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch decreasing hue, lch(100 0 320deg), lch(100 0 20deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100 0 320deg), lch(100 0 20deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch specified hue, lch(100 0 40deg), lch(100 0 60deg))' assert_true: 'color-mix(in lch specified hue, lch(100 0 40deg), lch(100 0 60deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch specified hue, lch(100 0 60deg), lch(100 0 40deg))' assert_true: 'color-mix(in lch specified hue, lch(100 0 60deg), lch(100 0 40deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch specified hue, lch(100 0 50deg), lch(100 0 330deg))' assert_true: 'color-mix(in lch specified hue, lch(100 0 50deg), lch(100 0 330deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch specified hue, lch(100 0 330deg), lch(100 0 50deg))' assert_true: 'color-mix(in lch specified hue, lch(100 0 330deg), lch(100 0 50deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch specified hue, lch(100 0 20deg), lch(100 0 320deg))' assert_true: 'color-mix(in lch specified hue, lch(100 0 20deg), lch(100 0 320deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch specified hue, lch(100 0 320deg), lch(100 0 20deg))' assert_true: 'color-mix(in lch specified hue, lch(100 0 320deg), lch(100 0 20deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(none none none), lch(none none none))' assert_true: 'color-mix(in lch, lch(none none none), lch(none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(none none none), lch(50 60 70deg))' assert_true: 'color-mix(in lch, lch(none none none), lch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg), lch(none none none))' assert_true: 'color-mix(in lch, lch(10 20 30deg), lch(none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 none), lch(50 60 70deg))' assert_true: 'color-mix(in lch, lch(10 20 none), lch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg), lch(50 60 none))' assert_true: 'color-mix(in lch, lch(10 20 30deg), lch(50 60 none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(none 20 30deg), lch(50 none 70deg))' assert_true: 'color-mix(in lch, lch(none 20 30deg), lch(50 none 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg))' assert_true: 'color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg / 0.5))' assert_true: 'color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg / 0.5))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg / none))' assert_true: 'color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg / none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg), oklch(50 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10 20 30deg), oklch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg) 25%, oklch(50 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10 20 30deg) 25%, oklch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, 25% oklch(10 20 30deg), oklch(50 60 70deg))' assert_true: 'color-mix(in oklch, 25% oklch(10 20 30deg), oklch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg), 25% oklch(50 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10 20 30deg), 25% oklch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg), oklch(50 60 70deg) 25%)' assert_true: 'color-mix(in oklch, oklch(10 20 30deg), oklch(50 60 70deg) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg) 25%, oklch(50 60 70deg) 75%)' assert_true: 'color-mix(in oklch, oklch(10 20 30deg) 25%, oklch(50 60 70deg) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg) 30%, oklch(50 60 70deg) 90%)' assert_true: 'color-mix(in oklch, oklch(10 20 30deg) 30%, oklch(50 60 70deg) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg) 12.5%, oklch(50 60 70deg) 37.5%)' assert_true: 'color-mix(in oklch, oklch(10 20 30deg) 12.5%, oklch(50 60 70deg) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg) 0%, oklch(50 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10 20 30deg) 0%, oklch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg / .4), oklch(50 60 70deg / .8))' assert_true: 'color-mix(in oklch, oklch(10 20 30deg / .4), oklch(50 60 70deg / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg / .4) 25%, oklch(50 60 70deg / .8))' assert_true: 'color-mix(in oklch, oklch(10 20 30deg / .4) 25%, oklch(50 60 70deg / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, 25% oklch(10 20 30deg / .4), oklch(50 60 70deg / .8))' assert_true: 'color-mix(in oklch, 25% oklch(10 20 30deg / .4), oklch(50 60 70deg / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg / .4), 25% oklch(50 60 70deg / .8))' assert_true: 'color-mix(in oklch, oklch(10 20 30deg / .4), 25% oklch(50 60 70deg / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg / .4), oklch(50 60 70deg / .8) 25%)' assert_true: 'color-mix(in oklch, oklch(10 20 30deg / .4), oklch(50 60 70deg / .8) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg / .4) 25%, oklch(50 60 70deg / .8) 75%)' assert_true: 'color-mix(in oklch, oklch(10 20 30deg / .4) 25%, oklch(50 60 70deg / .8) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg / .4) 30%, oklch(50 60 70deg / .8) 90%)' assert_true: 'color-mix(in oklch, oklch(10 20 30deg / .4) 30%, oklch(50 60 70deg / .8) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg / .4) 12.5%, oklch(50 60 70deg / .8) 37.5%)' assert_true: 'color-mix(in oklch, oklch(10 20 30deg / .4) 12.5%, oklch(50 60 70deg / .8) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg / .4) 0%, oklch(50 60 70deg / .8))' assert_true: 'color-mix(in oklch, oklch(10 20 30deg / .4) 0%, oklch(50 60 70deg / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(100 0 40deg), oklch(100 0 60deg))' assert_true: 'color-mix(in oklch, oklch(100 0 40deg), oklch(100 0 60deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(100 0 60deg), oklch(100 0 40deg))' assert_true: 'color-mix(in oklch, oklch(100 0 60deg), oklch(100 0 40deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(100 0 50deg), oklch(100 0 330deg))' assert_true: 'color-mix(in oklch, oklch(100 0 50deg), oklch(100 0 330deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(100 0 330deg), oklch(100 0 50deg))' assert_true: 'color-mix(in oklch, oklch(100 0 330deg), oklch(100 0 50deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(100 0 20deg), oklch(100 0 320deg))' assert_true: 'color-mix(in oklch, oklch(100 0 20deg), oklch(100 0 320deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(100 0 320deg), oklch(100 0 20deg))' assert_true: 'color-mix(in oklch, oklch(100 0 320deg), oklch(100 0 20deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100 0 40deg), oklch(100 0 60deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100 0 40deg), oklch(100 0 60deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100 0 60deg), oklch(100 0 40deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100 0 60deg), oklch(100 0 40deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100 0 50deg), oklch(100 0 330deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100 0 50deg), oklch(100 0 330deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100 0 330deg), oklch(100 0 50deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100 0 330deg), oklch(100 0 50deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100 0 20deg), oklch(100 0 320deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100 0 20deg), oklch(100 0 320deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100 0 320deg), oklch(100 0 20deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100 0 320deg), oklch(100 0 20deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch longer hue, oklch(100 0 40deg), oklch(100 0 60deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100 0 40deg), oklch(100 0 60deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch longer hue, oklch(100 0 60deg), oklch(100 0 40deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100 0 60deg), oklch(100 0 40deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch longer hue, oklch(100 0 50deg), oklch(100 0 330deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100 0 50deg), oklch(100 0 330deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch longer hue, oklch(100 0 330deg), oklch(100 0 50deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100 0 330deg), oklch(100 0 50deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch longer hue, oklch(100 0 20deg), oklch(100 0 320deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100 0 20deg), oklch(100 0 320deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch longer hue, oklch(100 0 320deg), oklch(100 0 20deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100 0 320deg), oklch(100 0 20deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100 0 40deg), oklch(100 0 60deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100 0 40deg), oklch(100 0 60deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100 0 60deg), oklch(100 0 40deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100 0 60deg), oklch(100 0 40deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100 0 50deg), oklch(100 0 330deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100 0 50deg), oklch(100 0 330deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100 0 330deg), oklch(100 0 50deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100 0 330deg), oklch(100 0 50deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100 0 20deg), oklch(100 0 320deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100 0 20deg), oklch(100 0 320deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100 0 320deg), oklch(100 0 20deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100 0 320deg), oklch(100 0 20deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100 0 40deg), oklch(100 0 60deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100 0 40deg), oklch(100 0 60deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100 0 60deg), oklch(100 0 40deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100 0 60deg), oklch(100 0 40deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100 0 50deg), oklch(100 0 330deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100 0 50deg), oklch(100 0 330deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100 0 330deg), oklch(100 0 50deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100 0 330deg), oklch(100 0 50deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100 0 20deg), oklch(100 0 320deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100 0 20deg), oklch(100 0 320deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100 0 320deg), oklch(100 0 20deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100 0 320deg), oklch(100 0 20deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch specified hue, oklch(100 0 40deg), oklch(100 0 60deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100 0 40deg), oklch(100 0 60deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch specified hue, oklch(100 0 60deg), oklch(100 0 40deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100 0 60deg), oklch(100 0 40deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch specified hue, oklch(100 0 50deg), oklch(100 0 330deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100 0 50deg), oklch(100 0 330deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch specified hue, oklch(100 0 330deg), oklch(100 0 50deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100 0 330deg), oklch(100 0 50deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch specified hue, oklch(100 0 20deg), oklch(100 0 320deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100 0 20deg), oklch(100 0 320deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch specified hue, oklch(100 0 320deg), oklch(100 0 20deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100 0 320deg), oklch(100 0 20deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(none none none), oklch(none none none))' assert_true: 'color-mix(in oklch, oklch(none none none), oklch(none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(none none none), oklch(50 60 70deg))' assert_true: 'color-mix(in oklch, oklch(none none none), oklch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg), oklch(none none none))' assert_true: 'color-mix(in oklch, oklch(10 20 30deg), oklch(none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 none), oklch(50 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10 20 none), oklch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg), oklch(50 60 none))' assert_true: 'color-mix(in oklch, oklch(10 20 30deg), oklch(50 60 none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(none 20 30deg), oklch(50 none 70deg))' assert_true: 'color-mix(in oklch, oklch(none 20 30deg), oklch(50 none 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg / 0.5))' assert_true: 'color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg / 0.5))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg / none))' assert_true: 'color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg / none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30), lab(50 60 70))' assert_true: 'color-mix(in lab, lab(10 20 30), lab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30) 25%, lab(50 60 70))' assert_true: 'color-mix(in lab, lab(10 20 30) 25%, lab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, 25% lab(10 20 30), lab(50 60 70))' assert_true: 'color-mix(in lab, 25% lab(10 20 30), lab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30), 25% lab(50 60 70))' assert_true: 'color-mix(in lab, lab(10 20 30), 25% lab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30), lab(50 60 70) 25%)' assert_true: 'color-mix(in lab, lab(10 20 30), lab(50 60 70) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30) 25%, lab(50 60 70) 75%)' assert_true: 'color-mix(in lab, lab(10 20 30) 25%, lab(50 60 70) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30) 30%, lab(50 60 70) 90%)' assert_true: 'color-mix(in lab, lab(10 20 30) 30%, lab(50 60 70) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30) 12.5%, lab(50 60 70) 37.5%)' assert_true: 'color-mix(in lab, lab(10 20 30) 12.5%, lab(50 60 70) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30) 0%, lab(50 60 70))' assert_true: 'color-mix(in lab, lab(10 20 30) 0%, lab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30 / .4), lab(50 60 70 / .8))' assert_true: 'color-mix(in lab, lab(10 20 30 / .4), lab(50 60 70 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30 / .4) 25%, lab(50 60 70 / .8))' assert_true: 'color-mix(in lab, lab(10 20 30 / .4) 25%, lab(50 60 70 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, 25% lab(10 20 30 / .4), lab(50 60 70 / .8))' assert_true: 'color-mix(in lab, 25% lab(10 20 30 / .4), lab(50 60 70 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30 / .4), 25% lab(50 60 70 / .8))' assert_true: 'color-mix(in lab, lab(10 20 30 / .4), 25% lab(50 60 70 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30 / .4), lab(50 60 70 / .8) 25%)' assert_true: 'color-mix(in lab, lab(10 20 30 / .4), lab(50 60 70 / .8) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30 / .4) 25%, lab(50 60 70 / .8) 75%)' assert_true: 'color-mix(in lab, lab(10 20 30 / .4) 25%, lab(50 60 70 / .8) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30 / .4) 30%, lab(50 60 70 / .8) 90%)' assert_true: 'color-mix(in lab, lab(10 20 30 / .4) 30%, lab(50 60 70 / .8) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30 / .4) 12.5%, lab(50 60 70 / .8) 37.5%)' assert_true: 'color-mix(in lab, lab(10 20 30 / .4) 12.5%, lab(50 60 70 / .8) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30 / .4) 0%, lab(50 60 70 / .8))' assert_true: 'color-mix(in lab, lab(10 20 30 / .4) 0%, lab(50 60 70 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(none none none), lab(none none none))' assert_true: 'color-mix(in lab, lab(none none none), lab(none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(none none none), lab(50 60 70))' assert_true: 'color-mix(in lab, lab(none none none), lab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30), lab(none none none))' assert_true: 'color-mix(in lab, lab(10 20 30), lab(none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 none), lab(50 60 70))' assert_true: 'color-mix(in lab, lab(10 20 none), lab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30), lab(50 60 none))' assert_true: 'color-mix(in lab, lab(10 20 30), lab(50 60 none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(none 20 30), lab(50 none 70))' assert_true: 'color-mix(in lab, lab(none 20 30), lab(50 none 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30 / none), lab(50 60 70))' assert_true: 'color-mix(in lab, lab(10 20 30 / none), lab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30 / none), lab(50 60 70 / 0.5))' assert_true: 'color-mix(in lab, lab(10 20 30 / none), lab(50 60 70 / 0.5))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in lab, lab(10 20 30 / none), lab(50 60 70 / none))' assert_true: 'color-mix(in lab, lab(10 20 30 / none), lab(50 60 70 / none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30), oklab(50 60 70))' assert_true: 'color-mix(in oklab, oklab(10 20 30), oklab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30) 25%, oklab(50 60 70))' assert_true: 'color-mix(in oklab, oklab(10 20 30) 25%, oklab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, 25% oklab(10 20 30), oklab(50 60 70))' assert_true: 'color-mix(in oklab, 25% oklab(10 20 30), oklab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30), 25% oklab(50 60 70))' assert_true: 'color-mix(in oklab, oklab(10 20 30), 25% oklab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30), oklab(50 60 70) 25%)' assert_true: 'color-mix(in oklab, oklab(10 20 30), oklab(50 60 70) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30) 25%, oklab(50 60 70) 75%)' assert_true: 'color-mix(in oklab, oklab(10 20 30) 25%, oklab(50 60 70) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30) 30%, oklab(50 60 70) 90%)' assert_true: 'color-mix(in oklab, oklab(10 20 30) 30%, oklab(50 60 70) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30) 12.5%, oklab(50 60 70) 37.5%)' assert_true: 'color-mix(in oklab, oklab(10 20 30) 12.5%, oklab(50 60 70) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30) 0%, oklab(50 60 70))' assert_true: 'color-mix(in oklab, oklab(10 20 30) 0%, oklab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30 / .4), oklab(50 60 70 / .8))' assert_true: 'color-mix(in oklab, oklab(10 20 30 / .4), oklab(50 60 70 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30 / .4) 25%, oklab(50 60 70 / .8))' assert_true: 'color-mix(in oklab, oklab(10 20 30 / .4) 25%, oklab(50 60 70 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, 25% oklab(10 20 30 / .4), oklab(50 60 70 / .8))' assert_true: 'color-mix(in oklab, 25% oklab(10 20 30 / .4), oklab(50 60 70 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30 / .4), 25% oklab(50 60 70 / .8))' assert_true: 'color-mix(in oklab, oklab(10 20 30 / .4), 25% oklab(50 60 70 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30 / .4), oklab(50 60 70 / .8) 25%)' assert_true: 'color-mix(in oklab, oklab(10 20 30 / .4), oklab(50 60 70 / .8) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30 / .4) 25%, oklab(50 60 70 / .8) 75%)' assert_true: 'color-mix(in oklab, oklab(10 20 30 / .4) 25%, oklab(50 60 70 / .8) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30 / .4) 30%, oklab(50 60 70 / .8) 90%)' assert_true: 'color-mix(in oklab, oklab(10 20 30 / .4) 30%, oklab(50 60 70 / .8) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30 / .4) 12.5%, oklab(50 60 70 / .8) 37.5%)' assert_true: 'color-mix(in oklab, oklab(10 20 30 / .4) 12.5%, oklab(50 60 70 / .8) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30 / .4) 0%, oklab(50 60 70 / .8))' assert_true: 'color-mix(in oklab, oklab(10 20 30 / .4) 0%, oklab(50 60 70 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(none none none), oklab(none none none))' assert_true: 'color-mix(in oklab, oklab(none none none), oklab(none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(none none none), oklab(50 60 70))' assert_true: 'color-mix(in oklab, oklab(none none none), oklab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30), oklab(none none none))' assert_true: 'color-mix(in oklab, oklab(10 20 30), oklab(none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 none), oklab(50 60 70))' assert_true: 'color-mix(in oklab, oklab(10 20 none), oklab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30), oklab(50 60 none))' assert_true: 'color-mix(in oklab, oklab(10 20 30), oklab(50 60 none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(none 20 30), oklab(50 none 70))' assert_true: 'color-mix(in oklab, oklab(none 20 30), oklab(50 none 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70))' assert_true: 'color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70 / 0.5))' assert_true: 'color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70 / 0.5))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70 / none))' assert_true: 'color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70 / none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, 25% color(srgb .1 .2 .3), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, 25% color(srgb .1 .2 .3), color(srgb .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7) 25%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), 25% color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), 25% color(srgb .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7) 75%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 30%, color(srgb .5 .6 .7) 90%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 30%, color(srgb .5 .6 .7) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 12.5%, color(srgb .5 .6 .7) 37.5%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 12.5%, color(srgb .5 .6 .7) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 0%, color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 0%, color(srgb .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .5), color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .5), color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, 25% color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, 25% color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) 25%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4), 25% color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4), 25% color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8) 75%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 30%, color(srgb .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 30%, color(srgb .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb 2 3 4 / 5), color(srgb 4 6 8 / 10))' assert_true: 'color-mix(in srgb, color(srgb 2 3 4 / 5), color(srgb 4 6 8 / 10))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb -2 -3 -4), color(srgb -4 -6 -8))' assert_true: 'color-mix(in srgb, color(srgb -2 -3 -4), color(srgb -4 -6 -8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb -2 -3 -4 / -5), color(srgb -4 -6 -8 / -10))' assert_true: 'color-mix(in srgb, color(srgb -2 -3 -4 / -5), color(srgb -4 -6 -8 / -10))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb none none none), color(srgb none none none))' assert_true: 'color-mix(in srgb, color(srgb none none none), color(srgb none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb none none none), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb none none none), color(srgb .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb none none none))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))' assert_true: 'color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7) 25%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), 25% color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), 25% color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7) 75%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 30%, color(srgb-linear .5 .6 .7) 90%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 30%, color(srgb-linear .5 .6 .7) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 12.5%, color(srgb-linear .5 .6 .7) 37.5%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 12.5%, color(srgb-linear .5 .6 .7) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 0%, color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 0%, color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .5), color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .5), color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8) 25%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), 25% color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), 25% color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8) 75%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 30%, color(srgb-linear .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 30%, color(srgb-linear .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 12.5%, color(srgb-linear .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 12.5%, color(srgb-linear .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 0%, color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 0%, color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear 2 3 4 / 5), color(srgb-linear 4 6 8 / 10))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear 2 3 4 / 5), color(srgb-linear 4 6 8 / 10))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4), color(srgb-linear -4 -6 -8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4), color(srgb-linear -4 -6 -8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4 / -5), color(srgb-linear -4 -6 -8 / -10))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4 / -5), color(srgb-linear -4 -6 -8 / -10))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear none none none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear none none none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, 25% color(xyz .1 .2 .3), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, 25% color(xyz .1 .2 .3), color(xyz .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7) 25%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), 25% color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), 25% color(xyz .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7) 75%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 30%, color(xyz .5 .6 .7) 90%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 30%, color(xyz .5 .6 .7) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 12.5%, color(xyz .5 .6 .7) 37.5%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 12.5%, color(xyz .5 .6 .7) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 0%, color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 0%, color(xyz .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .5), color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .5), color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, 25% color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, 25% color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) 25%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4), 25% color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4), 25% color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8) 75%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 30%, color(xyz .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 30%, color(xyz .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz 2 3 4 / 5), color(xyz 4 6 8 / 10))' assert_true: 'color-mix(in xyz, color(xyz 2 3 4 / 5), color(xyz 4 6 8 / 10))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz -2 -3 -4), color(xyz -4 -6 -8))' assert_true: 'color-mix(in xyz, color(xyz -2 -3 -4), color(xyz -4 -6 -8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz -2 -3 -4 / -5), color(xyz -4 -6 -8 / -10))' assert_true: 'color-mix(in xyz, color(xyz -2 -3 -4 / -5), color(xyz -4 -6 -8 / -10))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz none none none), color(xyz none none none))' assert_true: 'color-mix(in xyz, color(xyz none none none), color(xyz none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz none none none), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz none none none), color(xyz .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz none none none))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))' assert_true: 'color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7) 25%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), 25% color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), 25% color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7) 75%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 30%, color(xyz-d50 .5 .6 .7) 90%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 30%, color(xyz-d50 .5 .6 .7) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 12.5%, color(xyz-d50 .5 .6 .7) 37.5%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 12.5%, color(xyz-d50 .5 .6 .7) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 0%, color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 0%, color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .5), color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .5), color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8) 25%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), 25% color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), 25% color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8) 75%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 30%, color(xyz-d50 .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 30%, color(xyz-d50 .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 12.5%, color(xyz-d50 .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 12.5%, color(xyz-d50 .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 0%, color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 0%, color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 2 3 4 / 5), color(xyz-d50 4 6 8 / 10))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 2 3 4 / 5), color(xyz-d50 4 6 8 / 10))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4), color(xyz-d50 -4 -6 -8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4), color(xyz-d50 -4 -6 -8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4 / -5), color(xyz-d50 -4 -6 -8 / -10))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4 / -5), color(xyz-d50 -4 -6 -8 / -10))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 none none none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 none none none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7) 25%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), 25% color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), 25% color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7) 75%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 30%, color(xyz-d65 .5 .6 .7) 90%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 30%, color(xyz-d65 .5 .6 .7) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 12.5%, color(xyz-d65 .5 .6 .7) 37.5%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 12.5%, color(xyz-d65 .5 .6 .7) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 0%, color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 0%, color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .5), color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .5), color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8) 25%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8) 25%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), 25% color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), 25% color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8) 75%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8) 75%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 30%, color(xyz-d65 .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 30%, color(xyz-d65 .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 12.5%, color(xyz-d65 .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 12.5%, color(xyz-d65 .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 0%, color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 0%, color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 2 3 4 / 5), color(xyz-d65 4 6 8 / 10))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 2 3 4 / 5), color(xyz-d65 4 6 8 / 10))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4), color(xyz-d65 -4 -6 -8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4), color(xyz-d65 -4 -6 -8))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4 / -5), color(xyz-d65 -4 -6 -8 / -10))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4 / -5), color(xyz-d65 -4 -6 -8 / -10))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 none none none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 none none none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 none none none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))' is a supported value for color. expected true got false
+FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))' is a supported value for color. expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-lab-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-lab-expected.txt
new file mode 100644
index 0000000..f471fa0
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-lab-expected.txt
@@ -0,0 +1,96 @@
+This is a testharness.js-based test.
+Found 92 tests; 0 PASS, 92 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL Property color value 'lab(0 0 0)' assert_true: 'lab(0 0 0)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(0 0 0 / 1)' assert_true: 'lab(0 0 0 / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(0 0 0 / 0.5)' assert_true: 'lab(0 0 0 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(20 0 10/0.5)' assert_true: 'lab(20 0 10/0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(20 0 10/50%)' assert_true: 'lab(20 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(400 0 10/50%)' assert_true: 'lab(400 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(50 -160 160)' assert_true: 'lab(50 -160 160)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(50 -200 200)' assert_true: 'lab(50 -200 200)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(0 0 0 / -10%)' assert_true: 'lab(0 0 0 / -10%)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(0 0 0 / 110%)' assert_true: 'lab(0 0 0 / 110%)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(0 0 0 / 300%)' assert_true: 'lab(0 0 0 / 300%)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(-40 0 0)' assert_true: 'lab(-40 0 0)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(50 -20 0)' assert_true: 'lab(50 -20 0)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(50 0 -20)' assert_true: 'lab(50 0 -20)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(calc(50 * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' assert_true: 'lab(calc(50 * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false
+FAIL Property color value 'lab(calc(-50 * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' assert_true: 'lab(calc(-50 * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' is a supported value for color. expected true got false
+FAIL Property color value 'lab(none none none / none)' assert_true: 'lab(none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(none none none)' assert_true: 'lab(none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(20 none none / none)' assert_true: 'lab(20 none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(none none none / 0.5)' assert_true: 'lab(none none none / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'lab(0 0 0 / none)' assert_true: 'lab(0 0 0 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(0 0 0)' assert_true: 'oklab(0 0 0)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(0 0 0 / 1)' assert_true: 'oklab(0 0 0 / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(0 0 0 / 0.5)' assert_true: 'oklab(0 0 0 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(20 0 10/0.5)' assert_true: 'oklab(20 0 10/0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(20 0 10/50%)' assert_true: 'oklab(20 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(400 0 10/50%)' assert_true: 'oklab(400 0 10/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(50 -160 160)' assert_true: 'oklab(50 -160 160)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(50 -200 200)' assert_true: 'oklab(50 -200 200)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(0 0 0 / -10%)' assert_true: 'oklab(0 0 0 / -10%)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(0 0 0 / 110%)' assert_true: 'oklab(0 0 0 / 110%)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(0 0 0 / 300%)' assert_true: 'oklab(0 0 0 / 300%)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(-40 0 0)' assert_true: 'oklab(-40 0 0)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(50 -20 0)' assert_true: 'oklab(50 -20 0)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(50 0 -20)' assert_true: 'oklab(50 0 -20)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(calc(50 * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' assert_true: 'oklab(calc(50 * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(calc(-50 * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' assert_true: 'oklab(calc(-50 * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(none none none / none)' assert_true: 'oklab(none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(none none none)' assert_true: 'oklab(none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(20 none none / none)' assert_true: 'oklab(20 none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(none none none / 0.5)' assert_true: 'oklab(none none none / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'oklab(0 0 0 / none)' assert_true: 'oklab(0 0 0 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(0 0 0deg)' assert_true: 'lch(0 0 0deg)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(0 0 0deg / 1)' assert_true: 'lch(0 0 0deg / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(0 0 0deg / 0.5)' assert_true: 'lch(0 0 0deg / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(100 230 0deg / 0.5)' assert_true: 'lch(100 230 0deg / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(20 50 20deg/0.5)' assert_true: 'lch(20 50 20deg/0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(20 50 20deg/50%)' assert_true: 'lch(20 50 20deg/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(10 20 20deg / -10%)' assert_true: 'lch(10 20 20deg / -10%)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(10 20 20deg / 110%)' assert_true: 'lch(10 20 20deg / 110%)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(10 20 1.28rad)' assert_true: 'lch(10 20 1.28rad)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(10 20 380deg)' assert_true: 'lch(10 20 380deg)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(10 20 -340deg)' assert_true: 'lch(10 20 -340deg)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(10 20 740deg)' assert_true: 'lch(10 20 740deg)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(10 20 -700deg)' assert_true: 'lch(10 20 -700deg)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(-40 0 0)' assert_true: 'lch(-40 0 0)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(20 -20 0)' assert_true: 'lch(20 -20 0)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(0 0 0 / 0.5)' assert_true: 'lch(0 0 0 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(10 20 20 / 110%)' assert_true: 'lch(10 20 20 / 110%)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(10 20 -700)' assert_true: 'lch(10 20 -700)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(calc(50 * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' assert_true: 'lch(calc(50 * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' is a supported value for color. expected true got false
+FAIL Property color value 'lch(calc(-50 * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' assert_true: 'lch(calc(-50 * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' is a supported value for color. expected true got false
+FAIL Property color value 'lch(none none none / none)' assert_true: 'lch(none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(none none none)' assert_true: 'lch(none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(20 none none / none)' assert_true: 'lch(20 none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(none none none / 0.5)' assert_true: 'lch(none none none / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'lch(0 0 0 / none)' assert_true: 'lch(0 0 0 / none)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(0 0 0deg)' assert_true: 'oklch(0 0 0deg)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(0 0 0deg / 1)' assert_true: 'oklch(0 0 0deg / 1)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(0 0 0deg / 0.5)' assert_true: 'oklch(0 0 0deg / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(100 230 0deg / 0.5)' assert_true: 'oklch(100 230 0deg / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(20 50 20deg/0.5)' assert_true: 'oklch(20 50 20deg/0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(20 50 20deg/50%)' assert_true: 'oklch(20 50 20deg/50%)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(10 20 20deg / -10%)' assert_true: 'oklch(10 20 20deg / -10%)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(10 20 20deg / 110%)' assert_true: 'oklch(10 20 20deg / 110%)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(10 20 1.28rad)' assert_true: 'oklch(10 20 1.28rad)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(10 20 380deg)' assert_true: 'oklch(10 20 380deg)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(10 20 -340deg)' assert_true: 'oklch(10 20 -340deg)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(10 20 740deg)' assert_true: 'oklch(10 20 740deg)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(10 20 -700deg)' assert_true: 'oklch(10 20 -700deg)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(-40 0 0)' assert_true: 'oklch(-40 0 0)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(20 -20 0)' assert_true: 'oklch(20 -20 0)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(0 0 0 / 0.5)' assert_true: 'oklch(0 0 0 / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(10 20 20 / 110%)' assert_true: 'oklch(10 20 20 / 110%)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(10 20 -700)' assert_true: 'oklch(10 20 -700)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(calc(50 * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' assert_true: 'oklch(calc(50 * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(calc(-50 * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' assert_true: 'oklch(calc(-50 * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(none none none / none)' assert_true: 'oklch(none none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(none none none)' assert_true: 'oklch(none none none)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(20 none none / none)' assert_true: 'oklch(20 none none / none)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(none none none / 0.5)' assert_true: 'oklch(none none none / 0.5)' is a supported value for color. expected true got false
+FAIL Property color value 'oklch(0 0 0 / none)' assert_true: 'oklch(0 0 0 / none)' is a supported value for color. expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-valid-color-contrast-function-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-valid-color-contrast-function-expected.txt
new file mode 100644
index 0000000..bcfcf80
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-valid-color-contrast-function-expected.txt
@@ -0,0 +1,25 @@
+This is a testharness.js-based test.
+FAIL e.style['color'] = "color-contrast(white vs red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(white vs blue, red)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(white vs red, blue, green)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(white vs white, white)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(blue vs red, white)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(red vs blue, white, red)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(black vs red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(black vs blue, red)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(black vs white, white)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(red vs blue, rgb(255, 255, 255, .5))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AA)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AA-large)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AAA)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AAA-large)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to 5.8)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(wheat vs bisque, darkgoldenrod, olive to 100)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(green vs bisque, darkgoldenrod, olive to 100)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(green vs color(display-p3 0 1 0), color(display-p3 0 0 1))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(color(display-p3 1 1 0) vs color(display-p3 0 1 0), color(display-p3 0 0 1))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(green vs lab(50% -160 160), lch(0.2 50 20deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast(lab(50% -160 160) vs green, lch(0.2 50 20deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-contrast( white vs red, blue )" should set the property value assert_not_equals: property should be set got disallowed value ""
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-valid-color-function-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-valid-color-function-expected.txt
new file mode 100644
index 0000000..fc26cda3
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-valid-color-function-expected.txt
@@ -0,0 +1,280 @@
+This is a testharness.js-based test.
+Found 276 tests; 0 PASS, 276 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL e.style['color'] = "color(srgb 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear none none none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(srgb-linear 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(a98-rgb 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 none none none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(rec2020 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 none none none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(display-p3 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 1 1 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 1 1 1 / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz -1 -1 -1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 0.1 0.1 0.1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 10 10 10)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz .2 .2 .25)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 0 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz .20 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz .20 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 1 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 1 1 / .5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 1 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz / 50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz none none none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 0.2 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 1 1 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 1 1 1 / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 -1 -1 -1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 0.1 0.1 0.1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 10 10 10)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 .2 .2 .25)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 0 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 .20 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 .20 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 1 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 1 1 / .5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 1 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 / 50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 none none none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 0.2 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d50 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 1 1 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 1 1 1 / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 -1 -1 -1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 0.1 0.1 0.1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 10 10 10)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 .2 .2 .25)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 0 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 .20 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 .20 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 1 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 1 1 / .5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 1 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 / 50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 none none none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 0.2 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color(xyz-d65 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-valid-color-mix-function-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-valid-color-mix-function-expected.txt
new file mode 100644
index 0000000..eaad608d
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-valid-color-mix-function-expected.txt
@@ -0,0 +1,441 @@
+This is a testharness.js-based test.
+Found 437 tests; 1 PASS, 436 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL e.style['color'] = "color-mix(in srgb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, red calc(20%), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+PASS e.style['color'] = "color-mix(in hsl, red calc(var(--v)*1%), blue)" should set the property value
+FAIL e.style['color'] = "color-mix(in hsl, currentcolor, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, red 60%, blue 40%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch decreasing hue, red, hsl(120, 100%, 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%), 25% hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 30%, hsl(30deg 30% 40%) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, 25% hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4), 25% hsl(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4) 25%, hsl(30deg 30% 40% / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4) 30%, hsl(30deg 30% 40% / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4) 12.5%, hsl(30deg 30% 40% / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4) 0%, hsl(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(none none none), hsl(none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, lab(100 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, lab(0 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, lch(100 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, lch(0 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, oklab(100 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, oklab(0 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, oklch(100 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hsl, oklch(0 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 30%, hwb(30deg 30% 40%) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, 25% hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4) 30%, hwb(30deg 30% 40% / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4) 12.5%, hwb(30deg 30% 40% / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4) 0%, hwb(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(none none none), hwb(none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, lab(100 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, lab(0 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, lch(100 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, lch(0 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, oklab(100 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, oklab(0 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, oklch(100 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in hwb, oklch(0 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg), lch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg) 25%, lch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, 25% lch(10 20 30deg), lch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg), 25% lch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg), lch(50 60 70deg) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg) 25%, lch(50 60 70deg) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg) 30%, lch(50 60 70deg) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg) 12.5%, lch(50 60 70deg) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg) 0%, lch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg / .4), lch(50 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg / .4) 25%, lch(50 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, 25% lch(10 20 30deg / .4), lch(50 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg / .4), 25% lch(50 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg / .4), lch(50 60 70deg / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg / .4) 25%, lch(50 60 70deg / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg / .4) 30%, lch(50 60 70deg / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg / .4) 12.5%, lch(50 60 70deg / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg / .4) 0%, lch(50 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(100 0 40deg), lch(100 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(100 0 60deg), lch(100 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(100 0 50deg), lch(100 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(100 0 330deg), lch(100 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(100 0 20deg), lch(100 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(100 0 320deg), lch(100 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100 0 40deg), lch(100 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100 0 60deg), lch(100 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100 0 50deg), lch(100 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100 0 330deg), lch(100 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100 0 20deg), lch(100 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100 0 320deg), lch(100 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100 0 40deg), lch(100 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100 0 60deg), lch(100 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100 0 50deg), lch(100 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100 0 330deg), lch(100 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100 0 20deg), lch(100 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100 0 320deg), lch(100 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100 0 40deg), lch(100 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100 0 60deg), lch(100 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100 0 50deg), lch(100 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100 0 330deg), lch(100 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100 0 20deg), lch(100 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100 0 320deg), lch(100 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100 0 40deg), lch(100 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100 0 60deg), lch(100 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100 0 50deg), lch(100 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100 0 330deg), lch(100 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100 0 20deg), lch(100 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100 0 320deg), lch(100 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(none none none), lch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(none none none), lch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg), lch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 none), lch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg), lch(50 60 none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(none 20 30deg), lch(50 none 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg / none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg), oklch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg) 25%, oklch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, 25% oklch(10 20 30deg), oklch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg), 25% oklch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg), oklch(50 60 70deg) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg) 25%, oklch(50 60 70deg) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg) 30%, oklch(50 60 70deg) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg) 12.5%, oklch(50 60 70deg) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg) 0%, oklch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg / .4), oklch(50 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg / .4) 25%, oklch(50 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, 25% oklch(10 20 30deg / .4), oklch(50 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg / .4), 25% oklch(50 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg / .4), oklch(50 60 70deg / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg / .4) 25%, oklch(50 60 70deg / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg / .4) 30%, oklch(50 60 70deg / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg / .4) 12.5%, oklch(50 60 70deg / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg / .4) 0%, oklch(50 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(100 0 40deg), oklch(100 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(100 0 60deg), oklch(100 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(100 0 50deg), oklch(100 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(100 0 330deg), oklch(100 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(100 0 20deg), oklch(100 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(100 0 320deg), oklch(100 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100 0 40deg), oklch(100 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100 0 60deg), oklch(100 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100 0 50deg), oklch(100 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100 0 330deg), oklch(100 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100 0 20deg), oklch(100 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100 0 320deg), oklch(100 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100 0 40deg), oklch(100 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100 0 60deg), oklch(100 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100 0 50deg), oklch(100 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100 0 330deg), oklch(100 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100 0 20deg), oklch(100 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100 0 320deg), oklch(100 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100 0 40deg), oklch(100 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100 0 60deg), oklch(100 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100 0 50deg), oklch(100 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100 0 330deg), oklch(100 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100 0 20deg), oklch(100 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100 0 320deg), oklch(100 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100 0 40deg), oklch(100 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100 0 60deg), oklch(100 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100 0 50deg), oklch(100 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100 0 330deg), oklch(100 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100 0 20deg), oklch(100 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100 0 320deg), oklch(100 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(none none none), oklch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(none none none), oklch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg), oklch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 none), oklch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg), oklch(50 60 none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(none 20 30deg), oklch(50 none 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg / none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30), lab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30) 25%, lab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, 25% lab(10 20 30), lab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30), 25% lab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30), lab(50 60 70) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30) 25%, lab(50 60 70) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30) 30%, lab(50 60 70) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30) 12.5%, lab(50 60 70) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30) 0%, lab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30 / .4), lab(50 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30 / .4) 25%, lab(50 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, 25% lab(10 20 30 / .4), lab(50 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30 / .4), 25% lab(50 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30 / .4), lab(50 60 70 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30 / .4) 25%, lab(50 60 70 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30 / .4) 30%, lab(50 60 70 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30 / .4) 12.5%, lab(50 60 70 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30 / .4) 0%, lab(50 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(none none none), lab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(none none none), lab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30), lab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 none), lab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30), lab(50 60 none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(none 20 30), lab(50 none 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30 / none), lab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30 / none), lab(50 60 70 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in lab, lab(10 20 30 / none), lab(50 60 70 / none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30), oklab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30) 25%, oklab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, 25% oklab(10 20 30), oklab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30), 25% oklab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30), oklab(50 60 70) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30) 25%, oklab(50 60 70) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30) 30%, oklab(50 60 70) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30) 12.5%, oklab(50 60 70) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30) 0%, oklab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30 / .4), oklab(50 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30 / .4) 25%, oklab(50 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, 25% oklab(10 20 30 / .4), oklab(50 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30 / .4), 25% oklab(50 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30 / .4), oklab(50 60 70 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30 / .4) 25%, oklab(50 60 70 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30 / .4) 30%, oklab(50 60 70 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30 / .4) 12.5%, oklab(50 60 70 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30 / .4) 0%, oklab(50 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(none none none), oklab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(none none none), oklab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30), oklab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 none), oklab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30), oklab(50 60 none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(none 20 30), oklab(50 none 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70 / none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 30%, color(srgb .5 .6 .7) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 12.5%, color(srgb .5 .6 .7) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 0%, color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .5), color(srgb .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 30%, color(srgb .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb 2 3 4 / 5), color(srgb 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb -2 -3 -4), color(srgb -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb -2 -3 -4 / -5), color(srgb -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb none none none), color(srgb none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb none none none), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 30%, color(srgb-linear .5 .6 .7) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 12.5%, color(srgb-linear .5 .6 .7) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 0%, color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .5), color(srgb-linear .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 30%, color(srgb-linear .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 12.5%, color(srgb-linear .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 0%, color(srgb-linear .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear 2 3 4 / 5), color(srgb-linear 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear -2 -3 -4), color(srgb-linear -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear -2 -3 -4 / -5), color(srgb-linear -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 30%, color(xyz .5 .6 .7) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 12.5%, color(xyz .5 .6 .7) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 0%, color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .5), color(xyz .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 30%, color(xyz .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz 2 3 4 / 5), color(xyz 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz -2 -3 -4), color(xyz -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz -2 -3 -4 / -5), color(xyz -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz none none none), color(xyz none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz none none none), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 30%, color(xyz-d50 .5 .6 .7) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 12.5%, color(xyz-d50 .5 .6 .7) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 0%, color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .5), color(xyz-d50 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 30%, color(xyz-d50 .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 12.5%, color(xyz-d50 .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 0%, color(xyz-d50 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 2 3 4 / 5), color(xyz-d50 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4), color(xyz-d50 -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4 / -5), color(xyz-d50 -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 30%, color(xyz-d65 .5 .6 .7) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 12.5%, color(xyz-d65 .5 .6 .7) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 0%, color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .5), color(xyz-d65 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 30%, color(xyz-d65 .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 12.5%, color(xyz-d65 .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 0%, color(xyz-d65 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 2 3 4 / 5), color(xyz-d65 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4), color(xyz-d65 -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4 / -5), color(xyz-d65 -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 none none none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value ""
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-valid-lab-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-valid-lab-expected.txt
new file mode 100644
index 0000000..4645bce
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-valid-lab-expected.txt
@@ -0,0 +1,96 @@
+This is a testharness.js-based test.
+Found 92 tests; 0 PASS, 92 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL e.style['color'] = "lab(0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(0 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(20 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(20 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(400 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(50 -160 160)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(50 -200 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(-40 0 0)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(50 -20 0)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(50 0 -20)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(calc(50 * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(calc(-50 * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(none none none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(20 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lab(0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(0 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(20 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(20 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(400 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(50 -160 160)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(50 -200 200)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(-40 0 0)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(50 -20 0)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(50 0 -20)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(calc(50 * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(calc(-50 * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(none none none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(20 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklab(0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(0 0 0deg)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(0 0 0deg / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(0 0 0deg / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(100 230 0deg / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(20 50 20deg/0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(20 50 20deg/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(10 20 20deg / -10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(10 20 20deg / 110%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(10 20 1.28rad)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(10 20 380deg)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(10 20 -340deg)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(10 20 740deg)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(10 20 -700deg)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(-40 0 0)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(20 -20 0)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(0 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(10 20 20 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(10 20 -700)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(calc(50 * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(calc(-50 * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(none none none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(20 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "lch(0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(0 0 0deg)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(0 0 0deg / 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(0 0 0deg / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(100 230 0deg / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(20 50 20deg/0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(20 50 20deg/50%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(10 20 20deg / -10%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(10 20 20deg / 110%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(10 20 1.28rad)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(10 20 380deg)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(10 20 -340deg)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(10 20 740deg)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(10 20 -700deg)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(-40 0 0)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(20 -20 0)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(0 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(10 20 20 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(10 20 -700)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(calc(50 * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(calc(-50 * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(none none none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(20 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "oklch(0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value ""
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-images/parsing/gradient-interpolation-method-computed-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-images/parsing/gradient-interpolation-method-computed-expected.txt
new file mode 100644
index 0000000..bbd2cb6f
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-images/parsing/gradient-interpolation-method-computed-expected.txt
@@ -0,0 +1,936 @@
+This is a testharness.js-based test.
+Found 932 tests; 7 PASS, 925 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS Property background-image value 'linear-gradient(30deg, red, blue)'
+PASS Property background-image value 'linear-gradient(to right bottom, red, blue)'
+FAIL Property background-image value 'linear-gradient(30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lab, red, blue)' assert_true: 'linear-gradient(in lab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in lab, red, blue)' assert_true: 'linear-gradient(30deg in lab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lab 30deg, red, blue)' assert_true: 'linear-gradient(in lab 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in lab, red, blue)' assert_true: 'linear-gradient(to right bottom in lab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lab to right bottom, red, blue)' assert_true: 'linear-gradient(in lab to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lab, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in lab, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in lab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lab 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lab 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in lab, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in lab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lab to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lab to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklab, red, blue)' assert_true: 'linear-gradient(in oklab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in oklab, red, blue)' assert_true: 'linear-gradient(30deg in oklab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklab 30deg, red, blue)' assert_true: 'linear-gradient(in oklab 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in oklab, red, blue)' assert_true: 'linear-gradient(to right bottom in oklab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklab to right bottom, red, blue)' assert_true: 'linear-gradient(in oklab to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklab, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in oklab, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in oklab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklab 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklab 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in oklab, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in oklab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklab to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklab to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in srgb, red, blue)' assert_true: 'linear-gradient(in srgb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in srgb, red, blue)' assert_true: 'linear-gradient(30deg in srgb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in srgb 30deg, red, blue)' assert_true: 'linear-gradient(in srgb 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in srgb, red, blue)' assert_true: 'linear-gradient(to right bottom in srgb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in srgb to right bottom, red, blue)' assert_true: 'linear-gradient(in srgb to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in srgb, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in srgb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in srgb, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in srgb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in srgb 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in srgb 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in srgb, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in srgb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in srgb to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in srgb to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in srgb-linear, red, blue)' assert_true: 'linear-gradient(in srgb-linear, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in srgb-linear, red, blue)' assert_true: 'linear-gradient(30deg in srgb-linear, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in srgb-linear 30deg, red, blue)' assert_true: 'linear-gradient(in srgb-linear 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in srgb-linear, red, blue)' assert_true: 'linear-gradient(to right bottom in srgb-linear, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in srgb-linear to right bottom, red, blue)' assert_true: 'linear-gradient(in srgb-linear to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in srgb-linear, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in srgb-linear, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in srgb-linear, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in srgb-linear, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in srgb-linear 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in srgb-linear 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in srgb-linear, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in srgb-linear, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in srgb-linear to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in srgb-linear to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz, red, blue)' assert_true: 'linear-gradient(in xyz, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in xyz, red, blue)' assert_true: 'linear-gradient(30deg in xyz, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz 30deg, red, blue)' assert_true: 'linear-gradient(in xyz 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in xyz, red, blue)' assert_true: 'linear-gradient(to right bottom in xyz, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz to right bottom, red, blue)' assert_true: 'linear-gradient(in xyz to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in xyz, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in xyz, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in xyz, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in xyz 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in xyz, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in xyz, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in xyz to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz-d50, red, blue)' assert_true: 'linear-gradient(in xyz-d50, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in xyz-d50, red, blue)' assert_true: 'linear-gradient(30deg in xyz-d50, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz-d50 30deg, red, blue)' assert_true: 'linear-gradient(in xyz-d50 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in xyz-d50, red, blue)' assert_true: 'linear-gradient(to right bottom in xyz-d50, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz-d50 to right bottom, red, blue)' assert_true: 'linear-gradient(in xyz-d50 to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz-d50, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in xyz-d50, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in xyz-d50, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in xyz-d50, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz-d50 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in xyz-d50 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in xyz-d50, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in xyz-d50, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz-d50 to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in xyz-d50 to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz-d65, red, blue)' assert_true: 'linear-gradient(in xyz-d65, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in xyz-d65, red, blue)' assert_true: 'linear-gradient(30deg in xyz-d65, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz-d65 30deg, red, blue)' assert_true: 'linear-gradient(in xyz-d65 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in xyz-d65, red, blue)' assert_true: 'linear-gradient(to right bottom in xyz-d65, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz-d65 to right bottom, red, blue)' assert_true: 'linear-gradient(in xyz-d65 to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz-d65, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in xyz-d65, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in xyz-d65, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in xyz-d65, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz-d65 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in xyz-d65 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in xyz-d65, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in xyz-d65, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in xyz-d65 to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in xyz-d65 to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl, red, blue)' assert_true: 'linear-gradient(in hsl, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hsl, red, blue)' assert_true: 'linear-gradient(30deg in hsl, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl 30deg, red, blue)' assert_true: 'linear-gradient(in hsl 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hsl, red, blue)' assert_true: 'linear-gradient(to right bottom in hsl, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl to right bottom, red, blue)' assert_true: 'linear-gradient(in hsl to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hsl, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hsl, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in hsl, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hsl 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hsl, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in hsl, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hsl to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl shorter hue, red, blue)' assert_true: 'linear-gradient(in hsl shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hsl shorter hue, red, blue)' assert_true: 'linear-gradient(30deg in hsl shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl shorter hue 30deg, red, blue)' assert_true: 'linear-gradient(in hsl shorter hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hsl shorter hue, red, blue)' assert_true: 'linear-gradient(to right bottom in hsl shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl shorter hue to right bottom, red, blue)' assert_true: 'linear-gradient(in hsl shorter hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl shorter hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hsl shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hsl shorter hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in hsl shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl shorter hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hsl shorter hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hsl shorter hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in hsl shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl shorter hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hsl shorter hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl longer hue, red, blue)' assert_true: 'linear-gradient(in hsl longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hsl longer hue, red, blue)' assert_true: 'linear-gradient(30deg in hsl longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl longer hue 30deg, red, blue)' assert_true: 'linear-gradient(in hsl longer hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hsl longer hue, red, blue)' assert_true: 'linear-gradient(to right bottom in hsl longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl longer hue to right bottom, red, blue)' assert_true: 'linear-gradient(in hsl longer hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl longer hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hsl longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hsl longer hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in hsl longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl longer hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hsl longer hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hsl longer hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in hsl longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl longer hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hsl longer hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl increasing hue, red, blue)' assert_true: 'linear-gradient(in hsl increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hsl increasing hue, red, blue)' assert_true: 'linear-gradient(30deg in hsl increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl increasing hue 30deg, red, blue)' assert_true: 'linear-gradient(in hsl increasing hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hsl increasing hue, red, blue)' assert_true: 'linear-gradient(to right bottom in hsl increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl increasing hue to right bottom, red, blue)' assert_true: 'linear-gradient(in hsl increasing hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl increasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hsl increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hsl increasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in hsl increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl increasing hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hsl increasing hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hsl increasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in hsl increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl increasing hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hsl increasing hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl decreasing hue, red, blue)' assert_true: 'linear-gradient(in hsl decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hsl decreasing hue, red, blue)' assert_true: 'linear-gradient(30deg in hsl decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl decreasing hue 30deg, red, blue)' assert_true: 'linear-gradient(in hsl decreasing hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hsl decreasing hue, red, blue)' assert_true: 'linear-gradient(to right bottom in hsl decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl decreasing hue to right bottom, red, blue)' assert_true: 'linear-gradient(in hsl decreasing hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hsl decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hsl decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in hsl decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl decreasing hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hsl decreasing hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hsl decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in hsl decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hsl decreasing hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hsl decreasing hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb, red, blue)' assert_true: 'linear-gradient(in hwb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hwb, red, blue)' assert_true: 'linear-gradient(30deg in hwb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb 30deg, red, blue)' assert_true: 'linear-gradient(in hwb 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hwb, red, blue)' assert_true: 'linear-gradient(to right bottom in hwb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb to right bottom, red, blue)' assert_true: 'linear-gradient(in hwb to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hwb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hwb, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in hwb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hwb 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hwb, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in hwb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hwb to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb shorter hue, red, blue)' assert_true: 'linear-gradient(in hwb shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hwb shorter hue, red, blue)' assert_true: 'linear-gradient(30deg in hwb shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb shorter hue 30deg, red, blue)' assert_true: 'linear-gradient(in hwb shorter hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hwb shorter hue, red, blue)' assert_true: 'linear-gradient(to right bottom in hwb shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb shorter hue to right bottom, red, blue)' assert_true: 'linear-gradient(in hwb shorter hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb shorter hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hwb shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hwb shorter hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in hwb shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb shorter hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hwb shorter hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hwb shorter hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in hwb shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb shorter hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hwb shorter hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb longer hue, red, blue)' assert_true: 'linear-gradient(in hwb longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hwb longer hue, red, blue)' assert_true: 'linear-gradient(30deg in hwb longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb longer hue 30deg, red, blue)' assert_true: 'linear-gradient(in hwb longer hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hwb longer hue, red, blue)' assert_true: 'linear-gradient(to right bottom in hwb longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb longer hue to right bottom, red, blue)' assert_true: 'linear-gradient(in hwb longer hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb longer hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hwb longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hwb longer hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in hwb longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb longer hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hwb longer hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hwb longer hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in hwb longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb longer hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hwb longer hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb increasing hue, red, blue)' assert_true: 'linear-gradient(in hwb increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hwb increasing hue, red, blue)' assert_true: 'linear-gradient(30deg in hwb increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb increasing hue 30deg, red, blue)' assert_true: 'linear-gradient(in hwb increasing hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hwb increasing hue, red, blue)' assert_true: 'linear-gradient(to right bottom in hwb increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb increasing hue to right bottom, red, blue)' assert_true: 'linear-gradient(in hwb increasing hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb increasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hwb increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hwb increasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in hwb increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb increasing hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hwb increasing hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hwb increasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in hwb increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb increasing hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hwb increasing hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb decreasing hue, red, blue)' assert_true: 'linear-gradient(in hwb decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hwb decreasing hue, red, blue)' assert_true: 'linear-gradient(30deg in hwb decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb decreasing hue 30deg, red, blue)' assert_true: 'linear-gradient(in hwb decreasing hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hwb decreasing hue, red, blue)' assert_true: 'linear-gradient(to right bottom in hwb decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb decreasing hue to right bottom, red, blue)' assert_true: 'linear-gradient(in hwb decreasing hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hwb decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in hwb decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in hwb decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb decreasing hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hwb decreasing hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in hwb decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in hwb decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in hwb decreasing hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in hwb decreasing hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch, red, blue)' assert_true: 'linear-gradient(in lch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in lch, red, blue)' assert_true: 'linear-gradient(30deg in lch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch 30deg, red, blue)' assert_true: 'linear-gradient(in lch 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in lch, red, blue)' assert_true: 'linear-gradient(to right bottom in lch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch to right bottom, red, blue)' assert_true: 'linear-gradient(in lch to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in lch, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in lch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lch 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in lch, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in lch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lch to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch shorter hue, red, blue)' assert_true: 'linear-gradient(in lch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in lch shorter hue, red, blue)' assert_true: 'linear-gradient(30deg in lch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch shorter hue 30deg, red, blue)' assert_true: 'linear-gradient(in lch shorter hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in lch shorter hue, red, blue)' assert_true: 'linear-gradient(to right bottom in lch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch shorter hue to right bottom, red, blue)' assert_true: 'linear-gradient(in lch shorter hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in lch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in lch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch shorter hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lch shorter hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in lch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in lch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch shorter hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lch shorter hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch longer hue, red, blue)' assert_true: 'linear-gradient(in lch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in lch longer hue, red, blue)' assert_true: 'linear-gradient(30deg in lch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch longer hue 30deg, red, blue)' assert_true: 'linear-gradient(in lch longer hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in lch longer hue, red, blue)' assert_true: 'linear-gradient(to right bottom in lch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch longer hue to right bottom, red, blue)' assert_true: 'linear-gradient(in lch longer hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch longer hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in lch longer hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in lch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch longer hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lch longer hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in lch longer hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in lch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch longer hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lch longer hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch increasing hue, red, blue)' assert_true: 'linear-gradient(in lch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in lch increasing hue, red, blue)' assert_true: 'linear-gradient(30deg in lch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch increasing hue 30deg, red, blue)' assert_true: 'linear-gradient(in lch increasing hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in lch increasing hue, red, blue)' assert_true: 'linear-gradient(to right bottom in lch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch increasing hue to right bottom, red, blue)' assert_true: 'linear-gradient(in lch increasing hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in lch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in lch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch increasing hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lch increasing hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in lch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in lch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch increasing hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lch increasing hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch decreasing hue, red, blue)' assert_true: 'linear-gradient(in lch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in lch decreasing hue, red, blue)' assert_true: 'linear-gradient(30deg in lch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch decreasing hue 30deg, red, blue)' assert_true: 'linear-gradient(in lch decreasing hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in lch decreasing hue, red, blue)' assert_true: 'linear-gradient(to right bottom in lch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch decreasing hue to right bottom, red, blue)' assert_true: 'linear-gradient(in lch decreasing hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in lch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in lch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch decreasing hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lch decreasing hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in lch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in lch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in lch decreasing hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in lch decreasing hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch, red, blue)' assert_true: 'linear-gradient(in oklch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in oklch, red, blue)' assert_true: 'linear-gradient(30deg in oklch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch 30deg, red, blue)' assert_true: 'linear-gradient(in oklch 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in oklch, red, blue)' assert_true: 'linear-gradient(to right bottom in oklch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch to right bottom, red, blue)' assert_true: 'linear-gradient(in oklch to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in oklch, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in oklch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklch 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in oklch, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in oklch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklch to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch shorter hue, red, blue)' assert_true: 'linear-gradient(in oklch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in oklch shorter hue, red, blue)' assert_true: 'linear-gradient(30deg in oklch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch shorter hue 30deg, red, blue)' assert_true: 'linear-gradient(in oklch shorter hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in oklch shorter hue, red, blue)' assert_true: 'linear-gradient(to right bottom in oklch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch shorter hue to right bottom, red, blue)' assert_true: 'linear-gradient(in oklch shorter hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in oklch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in oklch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch shorter hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklch shorter hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in oklch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in oklch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch shorter hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklch shorter hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch longer hue, red, blue)' assert_true: 'linear-gradient(in oklch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in oklch longer hue, red, blue)' assert_true: 'linear-gradient(30deg in oklch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch longer hue 30deg, red, blue)' assert_true: 'linear-gradient(in oklch longer hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in oklch longer hue, red, blue)' assert_true: 'linear-gradient(to right bottom in oklch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch longer hue to right bottom, red, blue)' assert_true: 'linear-gradient(in oklch longer hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch longer hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in oklch longer hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in oklch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch longer hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklch longer hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in oklch longer hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in oklch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch longer hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklch longer hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch increasing hue, red, blue)' assert_true: 'linear-gradient(in oklch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in oklch increasing hue, red, blue)' assert_true: 'linear-gradient(30deg in oklch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch increasing hue 30deg, red, blue)' assert_true: 'linear-gradient(in oklch increasing hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in oklch increasing hue, red, blue)' assert_true: 'linear-gradient(to right bottom in oklch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch increasing hue to right bottom, red, blue)' assert_true: 'linear-gradient(in oklch increasing hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in oklch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in oklch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch increasing hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklch increasing hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in oklch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in oklch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch increasing hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklch increasing hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch decreasing hue, red, blue)' assert_true: 'linear-gradient(in oklch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in oklch decreasing hue, red, blue)' assert_true: 'linear-gradient(30deg in oklch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch decreasing hue 30deg, red, blue)' assert_true: 'linear-gradient(in oklch decreasing hue 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in oklch decreasing hue, red, blue)' assert_true: 'linear-gradient(to right bottom in oklch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch decreasing hue to right bottom, red, blue)' assert_true: 'linear-gradient(in oklch decreasing hue to right bottom, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(30deg in oklch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(30deg in oklch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch decreasing hue 30deg, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklch decreasing hue 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(to right bottom in oklch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(to right bottom in oklch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'linear-gradient(in oklch decreasing hue to right bottom, color(srgb 1 0 0), blue)' assert_true: 'linear-gradient(in oklch decreasing hue to right bottom, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+PASS Property background-image value 'radial-gradient(50px, red, blue)'
+PASS Property background-image value 'radial-gradient(ellipse 50% 40em, red, blue)'
+PASS Property background-image value 'radial-gradient(at right center, red, blue)'
+FAIL Property background-image value 'radial-gradient(50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lab, red, blue)' assert_true: 'radial-gradient(in lab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in lab, red, blue)' assert_true: 'radial-gradient(50px in lab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lab 50px, red, blue)' assert_true: 'radial-gradient(in lab 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in lab, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in lab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lab ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in lab ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in lab, red, blue)' assert_true: 'radial-gradient(at right center in lab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lab at right center, red, blue)' assert_true: 'radial-gradient(in lab at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lab, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in lab, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in lab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lab 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lab 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in lab, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in lab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lab ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lab ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in lab, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in lab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lab at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lab at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklab, red, blue)' assert_true: 'radial-gradient(in oklab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in oklab, red, blue)' assert_true: 'radial-gradient(50px in oklab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklab 50px, red, blue)' assert_true: 'radial-gradient(in oklab 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in oklab, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in oklab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklab ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in oklab ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in oklab, red, blue)' assert_true: 'radial-gradient(at right center in oklab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklab at right center, red, blue)' assert_true: 'radial-gradient(in oklab at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklab, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in oklab, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in oklab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklab 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklab 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in oklab, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in oklab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklab ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklab ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in oklab, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in oklab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklab at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklab at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb, red, blue)' assert_true: 'radial-gradient(in srgb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in srgb, red, blue)' assert_true: 'radial-gradient(50px in srgb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb 50px, red, blue)' assert_true: 'radial-gradient(in srgb 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in srgb, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in srgb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in srgb ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in srgb, red, blue)' assert_true: 'radial-gradient(at right center in srgb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb at right center, red, blue)' assert_true: 'radial-gradient(in srgb at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in srgb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in srgb, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in srgb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in srgb 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in srgb, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in srgb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in srgb ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in srgb, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in srgb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in srgb at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb-linear, red, blue)' assert_true: 'radial-gradient(in srgb-linear, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in srgb-linear, red, blue)' assert_true: 'radial-gradient(50px in srgb-linear, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb-linear 50px, red, blue)' assert_true: 'radial-gradient(in srgb-linear 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in srgb-linear, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in srgb-linear, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb-linear ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in srgb-linear ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in srgb-linear, red, blue)' assert_true: 'radial-gradient(at right center in srgb-linear, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb-linear at right center, red, blue)' assert_true: 'radial-gradient(in srgb-linear at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb-linear, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in srgb-linear, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in srgb-linear, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in srgb-linear, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb-linear 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in srgb-linear 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in srgb-linear, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in srgb-linear, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb-linear ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in srgb-linear ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in srgb-linear, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in srgb-linear, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in srgb-linear at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in srgb-linear at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz, red, blue)' assert_true: 'radial-gradient(in xyz, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in xyz, red, blue)' assert_true: 'radial-gradient(50px in xyz, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz 50px, red, blue)' assert_true: 'radial-gradient(in xyz 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in xyz, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in xyz, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in xyz ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in xyz, red, blue)' assert_true: 'radial-gradient(at right center in xyz, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz at right center, red, blue)' assert_true: 'radial-gradient(in xyz at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in xyz, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in xyz, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in xyz, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in xyz 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in xyz, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in xyz, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in xyz ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in xyz, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in xyz, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in xyz at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d50, red, blue)' assert_true: 'radial-gradient(in xyz-d50, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in xyz-d50, red, blue)' assert_true: 'radial-gradient(50px in xyz-d50, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d50 50px, red, blue)' assert_true: 'radial-gradient(in xyz-d50 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in xyz-d50, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in xyz-d50, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d50 ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in xyz-d50 ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in xyz-d50, red, blue)' assert_true: 'radial-gradient(at right center in xyz-d50, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d50 at right center, red, blue)' assert_true: 'radial-gradient(in xyz-d50 at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d50, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in xyz-d50, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in xyz-d50, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in xyz-d50, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d50 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in xyz-d50 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in xyz-d50, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in xyz-d50, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d50 ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in xyz-d50 ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in xyz-d50, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in xyz-d50, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d50 at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in xyz-d50 at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d65, red, blue)' assert_true: 'radial-gradient(in xyz-d65, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in xyz-d65, red, blue)' assert_true: 'radial-gradient(50px in xyz-d65, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d65 50px, red, blue)' assert_true: 'radial-gradient(in xyz-d65 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in xyz-d65, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in xyz-d65, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d65 ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in xyz-d65 ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in xyz-d65, red, blue)' assert_true: 'radial-gradient(at right center in xyz-d65, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d65 at right center, red, blue)' assert_true: 'radial-gradient(in xyz-d65 at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d65, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in xyz-d65, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in xyz-d65, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in xyz-d65, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d65 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in xyz-d65 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in xyz-d65, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in xyz-d65, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d65 ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in xyz-d65 ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in xyz-d65, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in xyz-d65, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in xyz-d65 at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in xyz-d65 at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl, red, blue)' assert_true: 'radial-gradient(in hsl, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hsl, red, blue)' assert_true: 'radial-gradient(50px in hsl, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl 50px, red, blue)' assert_true: 'radial-gradient(in hsl 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hsl, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hsl, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in hsl ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hsl, red, blue)' assert_true: 'radial-gradient(at right center in hsl, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl at right center, red, blue)' assert_true: 'radial-gradient(in hsl at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hsl, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in hsl, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hsl, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hsl, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hsl, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in hsl, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl shorter hue, red, blue)' assert_true: 'radial-gradient(in hsl shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hsl shorter hue, red, blue)' assert_true: 'radial-gradient(50px in hsl shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl shorter hue 50px, red, blue)' assert_true: 'radial-gradient(in hsl shorter hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hsl shorter hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hsl shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl shorter hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in hsl shorter hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hsl shorter hue, red, blue)' assert_true: 'radial-gradient(at right center in hsl shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl shorter hue at right center, red, blue)' assert_true: 'radial-gradient(in hsl shorter hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hsl shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in hsl shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl shorter hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl shorter hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hsl shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hsl shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl shorter hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl shorter hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hsl shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in hsl shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl shorter hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl shorter hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl longer hue, red, blue)' assert_true: 'radial-gradient(in hsl longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hsl longer hue, red, blue)' assert_true: 'radial-gradient(50px in hsl longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl longer hue 50px, red, blue)' assert_true: 'radial-gradient(in hsl longer hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hsl longer hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hsl longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl longer hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in hsl longer hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hsl longer hue, red, blue)' assert_true: 'radial-gradient(at right center in hsl longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl longer hue at right center, red, blue)' assert_true: 'radial-gradient(in hsl longer hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hsl longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in hsl longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl longer hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl longer hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hsl longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hsl longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl longer hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl longer hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hsl longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in hsl longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl longer hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl longer hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl increasing hue, red, blue)' assert_true: 'radial-gradient(in hsl increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hsl increasing hue, red, blue)' assert_true: 'radial-gradient(50px in hsl increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl increasing hue 50px, red, blue)' assert_true: 'radial-gradient(in hsl increasing hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hsl increasing hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hsl increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl increasing hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in hsl increasing hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hsl increasing hue, red, blue)' assert_true: 'radial-gradient(at right center in hsl increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl increasing hue at right center, red, blue)' assert_true: 'radial-gradient(in hsl increasing hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hsl increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in hsl increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl increasing hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl increasing hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hsl increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hsl increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl increasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl increasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hsl increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in hsl increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl increasing hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl increasing hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl decreasing hue, red, blue)' assert_true: 'radial-gradient(in hsl decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hsl decreasing hue, red, blue)' assert_true: 'radial-gradient(50px in hsl decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl decreasing hue 50px, red, blue)' assert_true: 'radial-gradient(in hsl decreasing hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hsl decreasing hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hsl decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl decreasing hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in hsl decreasing hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hsl decreasing hue, red, blue)' assert_true: 'radial-gradient(at right center in hsl decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl decreasing hue at right center, red, blue)' assert_true: 'radial-gradient(in hsl decreasing hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hsl decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in hsl decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl decreasing hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl decreasing hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hsl decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hsl decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl decreasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl decreasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hsl decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in hsl decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hsl decreasing hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hsl decreasing hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb, red, blue)' assert_true: 'radial-gradient(in hwb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hwb, red, blue)' assert_true: 'radial-gradient(50px in hwb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb 50px, red, blue)' assert_true: 'radial-gradient(in hwb 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hwb, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hwb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in hwb ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hwb, red, blue)' assert_true: 'radial-gradient(at right center in hwb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb at right center, red, blue)' assert_true: 'radial-gradient(in hwb at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hwb, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in hwb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hwb, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hwb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hwb, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in hwb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb shorter hue, red, blue)' assert_true: 'radial-gradient(in hwb shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hwb shorter hue, red, blue)' assert_true: 'radial-gradient(50px in hwb shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb shorter hue 50px, red, blue)' assert_true: 'radial-gradient(in hwb shorter hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hwb shorter hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hwb shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb shorter hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in hwb shorter hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hwb shorter hue, red, blue)' assert_true: 'radial-gradient(at right center in hwb shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb shorter hue at right center, red, blue)' assert_true: 'radial-gradient(in hwb shorter hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hwb shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in hwb shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb shorter hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb shorter hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hwb shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hwb shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb shorter hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb shorter hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hwb shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in hwb shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb shorter hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb shorter hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb longer hue, red, blue)' assert_true: 'radial-gradient(in hwb longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hwb longer hue, red, blue)' assert_true: 'radial-gradient(50px in hwb longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb longer hue 50px, red, blue)' assert_true: 'radial-gradient(in hwb longer hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hwb longer hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hwb longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb longer hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in hwb longer hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hwb longer hue, red, blue)' assert_true: 'radial-gradient(at right center in hwb longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb longer hue at right center, red, blue)' assert_true: 'radial-gradient(in hwb longer hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hwb longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in hwb longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb longer hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb longer hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hwb longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hwb longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb longer hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb longer hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hwb longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in hwb longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb longer hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb longer hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb increasing hue, red, blue)' assert_true: 'radial-gradient(in hwb increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hwb increasing hue, red, blue)' assert_true: 'radial-gradient(50px in hwb increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb increasing hue 50px, red, blue)' assert_true: 'radial-gradient(in hwb increasing hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hwb increasing hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hwb increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb increasing hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in hwb increasing hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hwb increasing hue, red, blue)' assert_true: 'radial-gradient(at right center in hwb increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb increasing hue at right center, red, blue)' assert_true: 'radial-gradient(in hwb increasing hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hwb increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in hwb increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb increasing hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb increasing hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hwb increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hwb increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb increasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb increasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hwb increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in hwb increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb increasing hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb increasing hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb decreasing hue, red, blue)' assert_true: 'radial-gradient(in hwb decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hwb decreasing hue, red, blue)' assert_true: 'radial-gradient(50px in hwb decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb decreasing hue 50px, red, blue)' assert_true: 'radial-gradient(in hwb decreasing hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hwb decreasing hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hwb decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb decreasing hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in hwb decreasing hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hwb decreasing hue, red, blue)' assert_true: 'radial-gradient(at right center in hwb decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb decreasing hue at right center, red, blue)' assert_true: 'radial-gradient(in hwb decreasing hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in hwb decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in hwb decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb decreasing hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb decreasing hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in hwb decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in hwb decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb decreasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb decreasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in hwb decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in hwb decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in hwb decreasing hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in hwb decreasing hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch, red, blue)' assert_true: 'radial-gradient(in lch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in lch, red, blue)' assert_true: 'radial-gradient(50px in lch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch 50px, red, blue)' assert_true: 'radial-gradient(in lch 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in lch, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in lch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in lch ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in lch, red, blue)' assert_true: 'radial-gradient(at right center in lch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch at right center, red, blue)' assert_true: 'radial-gradient(in lch at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in lch, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in lch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in lch, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in lch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in lch, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in lch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch shorter hue, red, blue)' assert_true: 'radial-gradient(in lch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in lch shorter hue, red, blue)' assert_true: 'radial-gradient(50px in lch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch shorter hue 50px, red, blue)' assert_true: 'radial-gradient(in lch shorter hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in lch shorter hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in lch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch shorter hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in lch shorter hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in lch shorter hue, red, blue)' assert_true: 'radial-gradient(at right center in lch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch shorter hue at right center, red, blue)' assert_true: 'radial-gradient(in lch shorter hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in lch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in lch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch shorter hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch shorter hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in lch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in lch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch shorter hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch shorter hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in lch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in lch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch shorter hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch shorter hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch longer hue, red, blue)' assert_true: 'radial-gradient(in lch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in lch longer hue, red, blue)' assert_true: 'radial-gradient(50px in lch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch longer hue 50px, red, blue)' assert_true: 'radial-gradient(in lch longer hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in lch longer hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in lch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch longer hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in lch longer hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in lch longer hue, red, blue)' assert_true: 'radial-gradient(at right center in lch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch longer hue at right center, red, blue)' assert_true: 'radial-gradient(in lch longer hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in lch longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in lch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch longer hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch longer hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in lch longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in lch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch longer hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch longer hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in lch longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in lch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch longer hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch longer hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch increasing hue, red, blue)' assert_true: 'radial-gradient(in lch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in lch increasing hue, red, blue)' assert_true: 'radial-gradient(50px in lch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch increasing hue 50px, red, blue)' assert_true: 'radial-gradient(in lch increasing hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in lch increasing hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in lch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch increasing hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in lch increasing hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in lch increasing hue, red, blue)' assert_true: 'radial-gradient(at right center in lch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch increasing hue at right center, red, blue)' assert_true: 'radial-gradient(in lch increasing hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in lch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in lch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch increasing hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch increasing hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in lch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in lch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch increasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch increasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in lch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in lch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch increasing hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch increasing hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch decreasing hue, red, blue)' assert_true: 'radial-gradient(in lch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in lch decreasing hue, red, blue)' assert_true: 'radial-gradient(50px in lch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch decreasing hue 50px, red, blue)' assert_true: 'radial-gradient(in lch decreasing hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in lch decreasing hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in lch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch decreasing hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in lch decreasing hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in lch decreasing hue, red, blue)' assert_true: 'radial-gradient(at right center in lch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch decreasing hue at right center, red, blue)' assert_true: 'radial-gradient(in lch decreasing hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in lch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in lch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch decreasing hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch decreasing hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in lch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in lch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch decreasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch decreasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in lch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in lch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in lch decreasing hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in lch decreasing hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch, red, blue)' assert_true: 'radial-gradient(in oklch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in oklch, red, blue)' assert_true: 'radial-gradient(50px in oklch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch 50px, red, blue)' assert_true: 'radial-gradient(in oklch 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in oklch, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in oklch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in oklch ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in oklch, red, blue)' assert_true: 'radial-gradient(at right center in oklch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch at right center, red, blue)' assert_true: 'radial-gradient(in oklch at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in oklch, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in oklch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in oklch, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in oklch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in oklch, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in oklch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch shorter hue, red, blue)' assert_true: 'radial-gradient(in oklch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in oklch shorter hue, red, blue)' assert_true: 'radial-gradient(50px in oklch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch shorter hue 50px, red, blue)' assert_true: 'radial-gradient(in oklch shorter hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in oklch shorter hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in oklch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch shorter hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in oklch shorter hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in oklch shorter hue, red, blue)' assert_true: 'radial-gradient(at right center in oklch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch shorter hue at right center, red, blue)' assert_true: 'radial-gradient(in oklch shorter hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in oklch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in oklch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch shorter hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch shorter hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in oklch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in oklch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch shorter hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch shorter hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in oklch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in oklch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch shorter hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch shorter hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch longer hue, red, blue)' assert_true: 'radial-gradient(in oklch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in oklch longer hue, red, blue)' assert_true: 'radial-gradient(50px in oklch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch longer hue 50px, red, blue)' assert_true: 'radial-gradient(in oklch longer hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in oklch longer hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in oklch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch longer hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in oklch longer hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in oklch longer hue, red, blue)' assert_true: 'radial-gradient(at right center in oklch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch longer hue at right center, red, blue)' assert_true: 'radial-gradient(in oklch longer hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in oklch longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in oklch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch longer hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch longer hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in oklch longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in oklch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch longer hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch longer hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in oklch longer hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in oklch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch longer hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch longer hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch increasing hue, red, blue)' assert_true: 'radial-gradient(in oklch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in oklch increasing hue, red, blue)' assert_true: 'radial-gradient(50px in oklch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch increasing hue 50px, red, blue)' assert_true: 'radial-gradient(in oklch increasing hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in oklch increasing hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in oklch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch increasing hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in oklch increasing hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in oklch increasing hue, red, blue)' assert_true: 'radial-gradient(at right center in oklch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch increasing hue at right center, red, blue)' assert_true: 'radial-gradient(in oklch increasing hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in oklch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in oklch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch increasing hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch increasing hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in oklch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in oklch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch increasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch increasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in oklch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in oklch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch increasing hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch increasing hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch decreasing hue, red, blue)' assert_true: 'radial-gradient(in oklch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in oklch decreasing hue, red, blue)' assert_true: 'radial-gradient(50px in oklch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch decreasing hue 50px, red, blue)' assert_true: 'radial-gradient(in oklch decreasing hue 50px, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in oklch decreasing hue, red, blue)' assert_true: 'radial-gradient(ellipse 50% 40em in oklch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch decreasing hue ellipse 50% 40em, red, blue)' assert_true: 'radial-gradient(in oklch decreasing hue ellipse 50% 40em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in oklch decreasing hue, red, blue)' assert_true: 'radial-gradient(at right center in oklch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch decreasing hue at right center, red, blue)' assert_true: 'radial-gradient(in oklch decreasing hue at right center, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(50px in oklch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(50px in oklch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch decreasing hue 50px, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch decreasing hue 50px, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(ellipse 50% 40em in oklch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(ellipse 50% 40em in oklch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch decreasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch decreasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(at right center in oklch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(at right center in oklch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'radial-gradient(in oklch decreasing hue at right center, color(srgb 1 0 0), blue)' assert_true: 'radial-gradient(in oklch decreasing hue at right center, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+PASS Property background-image value 'conic-gradient(from 30deg, red, blue)'
+PASS Property background-image value 'conic-gradient(at left 10px top 50em, red, blue)'
+FAIL Property background-image value 'conic-gradient(from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lab, red, blue)' assert_true: 'conic-gradient(in lab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in lab, red, blue)' assert_true: 'conic-gradient(from 30deg in lab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lab from 30deg, red, blue)' assert_true: 'conic-gradient(in lab from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in lab, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in lab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lab at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in lab at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lab, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in lab, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in lab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lab from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lab from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in lab, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in lab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lab at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lab at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklab, red, blue)' assert_true: 'conic-gradient(in oklab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in oklab, red, blue)' assert_true: 'conic-gradient(from 30deg in oklab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklab from 30deg, red, blue)' assert_true: 'conic-gradient(in oklab from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in oklab, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in oklab, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklab at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in oklab at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklab, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in oklab, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in oklab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklab from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklab from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in oklab, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in oklab, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklab at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklab at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in srgb, red, blue)' assert_true: 'conic-gradient(in srgb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in srgb, red, blue)' assert_true: 'conic-gradient(from 30deg in srgb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in srgb from 30deg, red, blue)' assert_true: 'conic-gradient(in srgb from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in srgb, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in srgb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in srgb at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in srgb at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in srgb, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in srgb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in srgb, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in srgb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in srgb from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in srgb from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in srgb, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in srgb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in srgb at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in srgb at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in srgb-linear, red, blue)' assert_true: 'conic-gradient(in srgb-linear, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in srgb-linear, red, blue)' assert_true: 'conic-gradient(from 30deg in srgb-linear, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in srgb-linear from 30deg, red, blue)' assert_true: 'conic-gradient(in srgb-linear from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in srgb-linear, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in srgb-linear, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in srgb-linear at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in srgb-linear at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in srgb-linear, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in srgb-linear, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in srgb-linear, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in srgb-linear, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in srgb-linear from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in srgb-linear from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in srgb-linear, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in srgb-linear, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in srgb-linear at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in srgb-linear at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz, red, blue)' assert_true: 'conic-gradient(in xyz, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in xyz, red, blue)' assert_true: 'conic-gradient(from 30deg in xyz, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz from 30deg, red, blue)' assert_true: 'conic-gradient(in xyz from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in xyz, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in xyz, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in xyz at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in xyz, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in xyz, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in xyz, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in xyz from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in xyz, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in xyz, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in xyz at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz-d50, red, blue)' assert_true: 'conic-gradient(in xyz-d50, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in xyz-d50, red, blue)' assert_true: 'conic-gradient(from 30deg in xyz-d50, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz-d50 from 30deg, red, blue)' assert_true: 'conic-gradient(in xyz-d50 from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in xyz-d50, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in xyz-d50, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz-d50 at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in xyz-d50 at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz-d50, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in xyz-d50, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in xyz-d50, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in xyz-d50, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz-d50 from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in xyz-d50 from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in xyz-d50, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in xyz-d50, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz-d50 at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in xyz-d50 at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz-d65, red, blue)' assert_true: 'conic-gradient(in xyz-d65, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in xyz-d65, red, blue)' assert_true: 'conic-gradient(from 30deg in xyz-d65, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz-d65 from 30deg, red, blue)' assert_true: 'conic-gradient(in xyz-d65 from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in xyz-d65, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in xyz-d65, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz-d65 at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in xyz-d65 at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz-d65, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in xyz-d65, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in xyz-d65, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in xyz-d65, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz-d65 from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in xyz-d65 from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in xyz-d65, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in xyz-d65, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in xyz-d65 at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in xyz-d65 at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl, red, blue)' assert_true: 'conic-gradient(in hsl, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hsl, red, blue)' assert_true: 'conic-gradient(from 30deg in hsl, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl from 30deg, red, blue)' assert_true: 'conic-gradient(in hsl from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hsl, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in hsl, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in hsl at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hsl, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hsl, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in hsl, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hsl from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hsl, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in hsl, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hsl at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl shorter hue, red, blue)' assert_true: 'conic-gradient(in hsl shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hsl shorter hue, red, blue)' assert_true: 'conic-gradient(from 30deg in hsl shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl shorter hue from 30deg, red, blue)' assert_true: 'conic-gradient(in hsl shorter hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hsl shorter hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in hsl shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl shorter hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in hsl shorter hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl shorter hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hsl shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hsl shorter hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in hsl shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl shorter hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hsl shorter hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hsl shorter hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in hsl shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl shorter hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hsl shorter hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl longer hue, red, blue)' assert_true: 'conic-gradient(in hsl longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hsl longer hue, red, blue)' assert_true: 'conic-gradient(from 30deg in hsl longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl longer hue from 30deg, red, blue)' assert_true: 'conic-gradient(in hsl longer hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hsl longer hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in hsl longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl longer hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in hsl longer hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl longer hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hsl longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hsl longer hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in hsl longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl longer hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hsl longer hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hsl longer hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in hsl longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl longer hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hsl longer hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl increasing hue, red, blue)' assert_true: 'conic-gradient(in hsl increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hsl increasing hue, red, blue)' assert_true: 'conic-gradient(from 30deg in hsl increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl increasing hue from 30deg, red, blue)' assert_true: 'conic-gradient(in hsl increasing hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hsl increasing hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in hsl increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl increasing hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in hsl increasing hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl increasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hsl increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hsl increasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in hsl increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl increasing hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hsl increasing hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hsl increasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in hsl increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl increasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hsl increasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl decreasing hue, red, blue)' assert_true: 'conic-gradient(in hsl decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hsl decreasing hue, red, blue)' assert_true: 'conic-gradient(from 30deg in hsl decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl decreasing hue from 30deg, red, blue)' assert_true: 'conic-gradient(in hsl decreasing hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hsl decreasing hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in hsl decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl decreasing hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in hsl decreasing hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hsl decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hsl decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in hsl decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl decreasing hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hsl decreasing hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hsl decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in hsl decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hsl decreasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hsl decreasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb, red, blue)' assert_true: 'conic-gradient(in hwb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hwb, red, blue)' assert_true: 'conic-gradient(from 30deg in hwb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb from 30deg, red, blue)' assert_true: 'conic-gradient(in hwb from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hwb, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in hwb, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in hwb at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hwb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hwb, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in hwb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hwb from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hwb, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in hwb, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hwb at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb shorter hue, red, blue)' assert_true: 'conic-gradient(in hwb shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hwb shorter hue, red, blue)' assert_true: 'conic-gradient(from 30deg in hwb shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb shorter hue from 30deg, red, blue)' assert_true: 'conic-gradient(in hwb shorter hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hwb shorter hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in hwb shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb shorter hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in hwb shorter hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb shorter hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hwb shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hwb shorter hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in hwb shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb shorter hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hwb shorter hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hwb shorter hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in hwb shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb shorter hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hwb shorter hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb longer hue, red, blue)' assert_true: 'conic-gradient(in hwb longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hwb longer hue, red, blue)' assert_true: 'conic-gradient(from 30deg in hwb longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb longer hue from 30deg, red, blue)' assert_true: 'conic-gradient(in hwb longer hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hwb longer hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in hwb longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb longer hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in hwb longer hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb longer hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hwb longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hwb longer hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in hwb longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb longer hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hwb longer hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hwb longer hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in hwb longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb longer hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hwb longer hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb increasing hue, red, blue)' assert_true: 'conic-gradient(in hwb increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hwb increasing hue, red, blue)' assert_true: 'conic-gradient(from 30deg in hwb increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb increasing hue from 30deg, red, blue)' assert_true: 'conic-gradient(in hwb increasing hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hwb increasing hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in hwb increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb increasing hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in hwb increasing hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb increasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hwb increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hwb increasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in hwb increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb increasing hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hwb increasing hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hwb increasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in hwb increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb increasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hwb increasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb decreasing hue, red, blue)' assert_true: 'conic-gradient(in hwb decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hwb decreasing hue, red, blue)' assert_true: 'conic-gradient(from 30deg in hwb decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb decreasing hue from 30deg, red, blue)' assert_true: 'conic-gradient(in hwb decreasing hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hwb decreasing hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in hwb decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb decreasing hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in hwb decreasing hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hwb decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in hwb decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in hwb decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb decreasing hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hwb decreasing hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in hwb decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in hwb decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in hwb decreasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in hwb decreasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch, red, blue)' assert_true: 'conic-gradient(in lch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in lch, red, blue)' assert_true: 'conic-gradient(from 30deg in lch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch from 30deg, red, blue)' assert_true: 'conic-gradient(in lch from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in lch, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in lch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in lch at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in lch, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in lch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lch from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in lch, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in lch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lch at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch shorter hue, red, blue)' assert_true: 'conic-gradient(in lch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in lch shorter hue, red, blue)' assert_true: 'conic-gradient(from 30deg in lch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch shorter hue from 30deg, red, blue)' assert_true: 'conic-gradient(in lch shorter hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in lch shorter hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in lch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch shorter hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in lch shorter hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in lch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in lch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch shorter hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lch shorter hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in lch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in lch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch shorter hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lch shorter hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch longer hue, red, blue)' assert_true: 'conic-gradient(in lch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in lch longer hue, red, blue)' assert_true: 'conic-gradient(from 30deg in lch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch longer hue from 30deg, red, blue)' assert_true: 'conic-gradient(in lch longer hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in lch longer hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in lch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch longer hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in lch longer hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch longer hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in lch longer hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in lch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch longer hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lch longer hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in lch longer hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in lch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch longer hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lch longer hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch increasing hue, red, blue)' assert_true: 'conic-gradient(in lch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in lch increasing hue, red, blue)' assert_true: 'conic-gradient(from 30deg in lch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch increasing hue from 30deg, red, blue)' assert_true: 'conic-gradient(in lch increasing hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in lch increasing hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in lch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch increasing hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in lch increasing hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in lch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in lch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch increasing hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lch increasing hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in lch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in lch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch increasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lch increasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch decreasing hue, red, blue)' assert_true: 'conic-gradient(in lch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in lch decreasing hue, red, blue)' assert_true: 'conic-gradient(from 30deg in lch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch decreasing hue from 30deg, red, blue)' assert_true: 'conic-gradient(in lch decreasing hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in lch decreasing hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in lch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch decreasing hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in lch decreasing hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in lch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in lch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch decreasing hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lch decreasing hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in lch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in lch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in lch decreasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in lch decreasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch, red, blue)' assert_true: 'conic-gradient(in oklch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in oklch, red, blue)' assert_true: 'conic-gradient(from 30deg in oklch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch from 30deg, red, blue)' assert_true: 'conic-gradient(in oklch from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in oklch, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in oklch, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in oklch at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in oklch, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in oklch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklch from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in oklch, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in oklch, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklch at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch shorter hue, red, blue)' assert_true: 'conic-gradient(in oklch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in oklch shorter hue, red, blue)' assert_true: 'conic-gradient(from 30deg in oklch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch shorter hue from 30deg, red, blue)' assert_true: 'conic-gradient(in oklch shorter hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in oklch shorter hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in oklch shorter hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch shorter hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in oklch shorter hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in oklch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in oklch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch shorter hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklch shorter hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in oklch shorter hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in oklch shorter hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch shorter hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklch shorter hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch longer hue, red, blue)' assert_true: 'conic-gradient(in oklch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in oklch longer hue, red, blue)' assert_true: 'conic-gradient(from 30deg in oklch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch longer hue from 30deg, red, blue)' assert_true: 'conic-gradient(in oklch longer hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in oklch longer hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in oklch longer hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch longer hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in oklch longer hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch longer hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in oklch longer hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in oklch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch longer hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklch longer hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in oklch longer hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in oklch longer hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch longer hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklch longer hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch increasing hue, red, blue)' assert_true: 'conic-gradient(in oklch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in oklch increasing hue, red, blue)' assert_true: 'conic-gradient(from 30deg in oklch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch increasing hue from 30deg, red, blue)' assert_true: 'conic-gradient(in oklch increasing hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in oklch increasing hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in oklch increasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch increasing hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in oklch increasing hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in oklch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in oklch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch increasing hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklch increasing hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in oklch increasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in oklch increasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch increasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklch increasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch decreasing hue, red, blue)' assert_true: 'conic-gradient(in oklch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in oklch decreasing hue, red, blue)' assert_true: 'conic-gradient(from 30deg in oklch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch decreasing hue from 30deg, red, blue)' assert_true: 'conic-gradient(in oklch decreasing hue from 30deg, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in oklch decreasing hue, red, blue)' assert_true: 'conic-gradient(at left 10px top 50em in oklch decreasing hue, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch decreasing hue at left 10px top 50em, red, blue)' assert_true: 'conic-gradient(in oklch decreasing hue at left 10px top 50em, red, blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(from 30deg in oklch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(from 30deg in oklch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch decreasing hue from 30deg, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklch decreasing hue from 30deg, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(at left 10px top 50em in oklch decreasing hue, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(at left 10px top 50em in oklch decreasing hue, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+FAIL Property background-image value 'conic-gradient(in oklch decreasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' assert_true: 'conic-gradient(in oklch decreasing hue at left 10px top 50em, color(srgb 1 0 0), blue)' is a supported value for background-image. expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-images/parsing/gradient-interpolation-method-valid-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-images/parsing/gradient-interpolation-method-valid-expected.txt
new file mode 100644
index 0000000..5fb5170
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-images/parsing/gradient-interpolation-method-valid-expected.txt
@@ -0,0 +1,936 @@
+This is a testharness.js-based test.
+Found 932 tests; 7 PASS, 925 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS e.style['background-image'] = "linear-gradient(30deg, red, blue)" should set the property value
+PASS e.style['background-image'] = "linear-gradient(to right bottom, red, blue)" should set the property value
+FAIL e.style['background-image'] = "linear-gradient(30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in lab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lab 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in lab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lab to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in lab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lab 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in lab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lab to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in oklab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklab 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in oklab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklab to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in oklab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklab 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in oklab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklab to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in srgb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in srgb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in srgb 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in srgb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in srgb to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in srgb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in srgb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in srgb 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in srgb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in srgb to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in srgb-linear, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in srgb-linear, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in srgb-linear 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in srgb-linear, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in srgb-linear to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in srgb-linear, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in srgb-linear, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in srgb-linear 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in srgb-linear, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in srgb-linear to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in xyz, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in xyz, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in xyz, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in xyz, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz-d50, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in xyz-d50, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz-d50 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in xyz-d50, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz-d50 to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz-d50, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in xyz-d50, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz-d50 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in xyz-d50, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz-d50 to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz-d65, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in xyz-d65, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz-d65 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in xyz-d65, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz-d65 to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz-d65, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in xyz-d65, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz-d65 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in xyz-d65, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in xyz-d65 to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hsl, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hsl, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hsl, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hsl, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hsl shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl shorter hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hsl shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl shorter hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hsl shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl shorter hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hsl shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl shorter hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hsl longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl longer hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hsl longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl longer hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hsl longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl longer hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hsl longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl longer hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hsl increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl increasing hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hsl increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl increasing hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hsl increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl increasing hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hsl increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl increasing hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hsl decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl decreasing hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hsl decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl decreasing hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hsl decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl decreasing hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hsl decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hsl decreasing hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hwb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hwb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hwb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hwb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hwb shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb shorter hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hwb shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb shorter hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hwb shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb shorter hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hwb shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb shorter hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hwb longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb longer hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hwb longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb longer hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hwb longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb longer hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hwb longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb longer hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hwb increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb increasing hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hwb increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb increasing hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hwb increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb increasing hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hwb increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb increasing hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hwb decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb decreasing hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hwb decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb decreasing hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in hwb decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb decreasing hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in hwb decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in hwb decreasing hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in lch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in lch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in lch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in lch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in lch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch shorter hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in lch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch shorter hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in lch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch shorter hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in lch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch shorter hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in lch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch longer hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in lch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch longer hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in lch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch longer hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in lch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch longer hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in lch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch increasing hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in lch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch increasing hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in lch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch increasing hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in lch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch increasing hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in lch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch decreasing hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in lch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch decreasing hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in lch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch decreasing hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in lch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in lch decreasing hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in oklch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in oklch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in oklch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in oklch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in oklch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch shorter hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in oklch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch shorter hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in oklch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch shorter hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in oklch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch shorter hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in oklch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch longer hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in oklch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch longer hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in oklch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch longer hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in oklch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch longer hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in oklch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch increasing hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in oklch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch increasing hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in oklch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch increasing hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in oklch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch increasing hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in oklch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch decreasing hue 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in oklch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch decreasing hue to right bottom, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(30deg in oklch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch decreasing hue 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(to right bottom in oklch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "linear-gradient(in oklch decreasing hue to right bottom, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+PASS e.style['background-image'] = "radial-gradient(50px, red, blue)" should set the property value
+PASS e.style['background-image'] = "radial-gradient(ellipse 50% 40em, red, blue)" should set the property value
+PASS e.style['background-image'] = "radial-gradient(at right center, red, blue)" should set the property value
+FAIL e.style['background-image'] = "radial-gradient(50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in lab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lab 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in lab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lab ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in lab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lab at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in lab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lab 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in lab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lab ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in lab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lab at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in oklab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklab 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in oklab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklab ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in oklab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklab at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in oklab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklab 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in oklab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklab ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in oklab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklab at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in srgb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in srgb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in srgb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in srgb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in srgb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in srgb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb-linear, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in srgb-linear, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb-linear 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in srgb-linear, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb-linear ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in srgb-linear, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb-linear at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb-linear, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in srgb-linear, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb-linear 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in srgb-linear, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb-linear ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in srgb-linear, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in srgb-linear at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in xyz, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in xyz, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in xyz, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in xyz, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in xyz, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in xyz, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d50, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in xyz-d50, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d50 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in xyz-d50, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d50 ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in xyz-d50, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d50 at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d50, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in xyz-d50, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d50 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in xyz-d50, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d50 ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in xyz-d50, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d50 at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d65, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in xyz-d65, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d65 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in xyz-d65, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d65 ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in xyz-d65, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d65 at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d65, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in xyz-d65, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d65 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in xyz-d65, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d65 ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in xyz-d65, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in xyz-d65 at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hsl, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hsl, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hsl, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hsl, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hsl, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hsl, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hsl shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl shorter hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hsl shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl shorter hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hsl shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl shorter hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hsl shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl shorter hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hsl shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl shorter hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hsl shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl shorter hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hsl longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl longer hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hsl longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl longer hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hsl longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl longer hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hsl longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl longer hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hsl longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl longer hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hsl longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl longer hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hsl increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl increasing hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hsl increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl increasing hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hsl increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl increasing hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hsl increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl increasing hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hsl increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl increasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hsl increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl increasing hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hsl decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl decreasing hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hsl decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl decreasing hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hsl decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl decreasing hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hsl decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl decreasing hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hsl decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl decreasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hsl decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hsl decreasing hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hwb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hwb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hwb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hwb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hwb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hwb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hwb shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb shorter hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hwb shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb shorter hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hwb shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb shorter hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hwb shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb shorter hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hwb shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb shorter hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hwb shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb shorter hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hwb longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb longer hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hwb longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb longer hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hwb longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb longer hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hwb longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb longer hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hwb longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb longer hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hwb longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb longer hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hwb increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb increasing hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hwb increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb increasing hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hwb increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb increasing hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hwb increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb increasing hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hwb increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb increasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hwb increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb increasing hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hwb decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb decreasing hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hwb decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb decreasing hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hwb decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb decreasing hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in hwb decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb decreasing hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in hwb decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb decreasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in hwb decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in hwb decreasing hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in lch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in lch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in lch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in lch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in lch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in lch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in lch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch shorter hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in lch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch shorter hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in lch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch shorter hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in lch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch shorter hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in lch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch shorter hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in lch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch shorter hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in lch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch longer hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in lch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch longer hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in lch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch longer hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in lch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch longer hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in lch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch longer hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in lch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch longer hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in lch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch increasing hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in lch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch increasing hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in lch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch increasing hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in lch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch increasing hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in lch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch increasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in lch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch increasing hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in lch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch decreasing hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in lch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch decreasing hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in lch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch decreasing hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in lch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch decreasing hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in lch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch decreasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in lch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in lch decreasing hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in oklch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in oklch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in oklch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in oklch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in oklch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in oklch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in oklch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch shorter hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in oklch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch shorter hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in oklch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch shorter hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in oklch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch shorter hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in oklch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch shorter hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in oklch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch shorter hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in oklch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch longer hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in oklch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch longer hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in oklch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch longer hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in oklch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch longer hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in oklch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch longer hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in oklch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch longer hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in oklch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch increasing hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in oklch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch increasing hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in oklch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch increasing hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in oklch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch increasing hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in oklch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch increasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in oklch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch increasing hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in oklch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch decreasing hue 50px, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in oklch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch decreasing hue ellipse 50% 40em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in oklch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch decreasing hue at right center, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(50px in oklch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch decreasing hue 50px, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(ellipse 50% 40em in oklch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch decreasing hue ellipse 50% 40em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(at right center in oklch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "radial-gradient(in oklch decreasing hue at right center, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+PASS e.style['background-image'] = "conic-gradient(from 30deg, red, blue)" should set the property value
+PASS e.style['background-image'] = "conic-gradient(at left 10px top 50em, red, blue)" should set the property value
+FAIL e.style['background-image'] = "conic-gradient(from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in lab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lab from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in lab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lab at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in lab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lab from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in lab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lab at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in oklab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklab from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in oklab, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklab at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in oklab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklab from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in oklab, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklab at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in srgb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in srgb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in srgb from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in srgb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in srgb at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in srgb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in srgb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in srgb from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in srgb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in srgb at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in srgb-linear, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in srgb-linear, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in srgb-linear from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in srgb-linear, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in srgb-linear at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in srgb-linear, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in srgb-linear, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in srgb-linear from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in srgb-linear, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in srgb-linear at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in xyz, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in xyz, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in xyz, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in xyz, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz-d50, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in xyz-d50, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz-d50 from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in xyz-d50, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz-d50 at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz-d50, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in xyz-d50, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz-d50 from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in xyz-d50, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz-d50 at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz-d65, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in xyz-d65, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz-d65 from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in xyz-d65, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz-d65 at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz-d65, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in xyz-d65, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz-d65 from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in xyz-d65, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in xyz-d65 at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hsl, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hsl, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hsl, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hsl, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hsl shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl shorter hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hsl shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl shorter hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hsl shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl shorter hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hsl shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl shorter hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hsl longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl longer hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hsl longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl longer hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hsl longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl longer hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hsl longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl longer hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hsl increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl increasing hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hsl increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl increasing hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hsl increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl increasing hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hsl increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl increasing hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hsl decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl decreasing hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hsl decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl decreasing hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hsl decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl decreasing hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hsl decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hsl decreasing hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hwb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hwb, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hwb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hwb, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hwb shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb shorter hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hwb shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb shorter hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hwb shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb shorter hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hwb shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb shorter hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hwb longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb longer hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hwb longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb longer hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hwb longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb longer hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hwb longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb longer hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hwb increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb increasing hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hwb increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb increasing hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hwb increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb increasing hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hwb increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb increasing hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hwb decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb decreasing hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hwb decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb decreasing hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in hwb decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb decreasing hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in hwb decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in hwb decreasing hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in lch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in lch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in lch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in lch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in lch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch shorter hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in lch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch shorter hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in lch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch shorter hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in lch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch shorter hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in lch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch longer hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in lch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch longer hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in lch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch longer hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in lch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch longer hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in lch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch increasing hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in lch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch increasing hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in lch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch increasing hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in lch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch increasing hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in lch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch decreasing hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in lch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch decreasing hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in lch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch decreasing hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in lch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in lch decreasing hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in oklch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in oklch, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in oklch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in oklch, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in oklch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch shorter hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in oklch shorter hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch shorter hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in oklch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch shorter hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in oklch shorter hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch shorter hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in oklch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch longer hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in oklch longer hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch longer hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in oklch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch longer hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in oklch longer hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch longer hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in oklch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch increasing hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in oklch increasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch increasing hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in oklch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch increasing hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in oklch increasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch increasing hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in oklch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch decreasing hue from 30deg, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in oklch decreasing hue, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch decreasing hue at left 10px top 50em, red, blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(from 30deg in oklch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch decreasing hue from 30deg, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(at left 10px top 50em in oklch decreasing hue, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['background-image'] = "conic-gradient(in oklch decreasing hue at left 10px top 50em, color(srgb 1 0 0), blue)" should set the property value assert_not_equals: property should be set got disallowed value ""
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/change-src-attribute-after-inner-config-installation-does-not-trigger-navigation.https.html b/third_party/blink/web_tests/wpt_internal/fenced_frame/change-src-attribute-after-inner-config-installation-does-not-trigger-navigation.https.html
new file mode 100644
index 0000000..1a88c87
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/fenced_frame/change-src-attribute-after-inner-config-installation-does-not-trigger-navigation.https.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/utils.js"></script>
+<title>Test changing a fenced frame's src attribute when there has been an inner
+  config with url installed already does not trigger navigation.
+</title>
+
+<body>
+
+<script>
+function getTimeoutPromise(t) {
+  return new Promise(resolve =>
+    t.step_timeout(() => resolve("NOT LOADED"), 2000));
+}
+
+promise_test(async (t) => {
+  const fenced_frame_loaded_key = token();
+
+  const url = generateURL(
+    'resources/fenced-frame-loaded.html', [fenced_frame_loaded_key]);
+  const url_string = url.toString();
+
+  // Create a fenced frame and install an inner config constructed with an url.
+  const fenced_frame = document.createElement('fencedframe');
+  const config = new FencedFrameInnerConfig(url_string);
+  fenced_frame.innerConfig = config;
+  document.body.append(fenced_frame);
+
+  assert_equals(fenced_frame.mode, "default");
+
+  // Installing an inner config to the fenced frame triggers navigation.
+  const load_expected = "fenced frame loaded";
+  const load_actual = await nextValueFromServer(fenced_frame_loaded_key);
+  assert_equals(load_actual, load_expected,
+    "Fenced frame successfully loaded.");
+
+  const src_key = token();
+  const src_url = generateURL(
+    'resources/fenced-frame-loaded.html', [src_key]);
+
+  // Changing the src attribute, should not trigger navigation.
+  fenced_frame.src = src_url;
+  const src_loaded_promise = nextValueFromServer(src_key);
+  const src_loaded_result = await Promise.any([src_loaded_promise,
+    getTimeoutPromise(t)]);
+  assert_equals(src_loaded_result, "NOT LOADED");
+
+}, 'Changing the src attribute of a fenced frame when an inner config with url',
+  'has already been installed does not trigger navigation.');
+</script>
+
+</body>
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/inner-config-installation-triggers-navigation-of-navigated-fenced-frame.https.html b/third_party/blink/web_tests/wpt_internal/fenced_frame/inner-config-installation-triggers-navigation-of-navigated-fenced-frame.https.html
new file mode 100644
index 0000000..a6c444e7
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/fenced_frame/inner-config-installation-triggers-navigation-of-navigated-fenced-frame.https.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/utils.js"></script>
+<title>Test installing an inner config to a navigated fenced frame triggers
+  navigation.
+</title>
+
+<body>
+
+<script>
+promise_test(async () => {
+  const fenced_frame_loaded_key = token();
+
+  // Create a fenced frame.
+  const fenced_frame = document.createElement('fencedframe');
+  document.body.append(fenced_frame);
+  assert_equals(fenced_frame.mode, "default");
+
+  // Specify the fenced frame's src attribute to an url.
+  const url = generateURL('resources/fenced-frame-loaded.html',
+                          [fenced_frame_loaded_key]);
+  fenced_frame.src = url;
+
+  // The fenced frame should navigate to the src url.
+  const load_expected = "fenced frame loaded";
+  const load_actual = await nextValueFromServer(fenced_frame_loaded_key);
+  assert_equals(load_actual, load_expected,
+    "Fenced frame successfully loaded by specifying its src attribute.");
+
+  // Create an inner config.
+  const config_navigation_key = token();
+  const config_url = generateURL('resources/fenced-frame-loaded.html',
+                                 [config_navigation_key]);
+  const config = new FencedFrameInnerConfig(config_url.toString());
+  fenced_frame.innerConfig = config;
+
+  // Installing an inner config to the fenced frame triggers navigation.
+  const config_navigation_actual =
+    await nextValueFromServer(config_navigation_key);
+  assert_equals(config_navigation_actual, load_expected,
+    "Fenced frame successfully navigated by installing an inner config.");
+
+}, 'Installing an inner config to a fenced frame that has navigated triggers',
+  'navigation.');
+</script>
+
+</body>
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/inner-config-installation-triggers-navigation.https.html b/third_party/blink/web_tests/wpt_internal/fenced_frame/inner-config-installation-triggers-navigation.https.html
new file mode 100644
index 0000000..fe0c41e
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/fenced_frame/inner-config-installation-triggers-navigation.https.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/utils.js"></script>
+<title>Test fenced frame inner config installation triggers navigation.</title>
+
+<body>
+
+<script>
+promise_test(async () => {
+  const fenced_frame_loaded_key = token();
+
+  const url = generateURL(
+    'resources/fenced-frame-loaded.html', [fenced_frame_loaded_key]);
+  const url_string = url.toString();
+
+  // Create a fenced frame and install an inner config constructed with an url.
+  const fenced_frame = document.createElement('fencedframe');
+  const config = new FencedFrameInnerConfig(url_string);
+  fenced_frame.innerConfig = config;
+  document.body.append(fenced_frame);
+
+  assert_equals(fenced_frame.mode, "default");
+
+  // Installing an inner config to the fenced frame triggers navigation.
+  const load_expected = "fenced frame loaded";
+  const load_actual = await nextValueFromServer(fenced_frame_loaded_key);
+  assert_equals(load_actual, load_expected,
+                "Fenced frame successfully loaded.");
+
+}, 'Installing an inner config to a fenced frame triggers navigation.');
+</script>
+
+</body>
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/inner-config-with-empty-url-installation-unloads-navigated-fenced-frame.https.html b/third_party/blink/web_tests/wpt_internal/fenced_frame/inner-config-with-empty-url-installation-unloads-navigated-fenced-frame.https.html
new file mode 100644
index 0000000..71013f2
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/fenced_frame/inner-config-with-empty-url-installation-unloads-navigated-fenced-frame.https.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/utils.js"></script>
+<title>Test installing an inner config with empty url to a navigated fenced
+  frame unloads the original document.
+</title>
+
+<body>
+
+<script>
+promise_test(async () => {
+  const fenced_frame_loaded_key = token();
+
+  // Create a fenced frame and install an inner config constructed with an empty
+  // url.
+  const fenced_frame = document.createElement('fencedframe');
+  document.body.append(fenced_frame);
+  assert_equals(fenced_frame.mode, "default");
+
+  // Specify the fenced frame's src attribute to an url.
+  const url = generateURL('resources/fenced-frame-loaded.html',
+                          [fenced_frame_loaded_key]);
+  fenced_frame.src = url;
+
+  // The fenced frame should navigate to the src url.
+  const load_expected = "fenced frame loaded";
+  const load_actual = await nextValueFromServer(fenced_frame_loaded_key);
+  assert_equals(load_actual, load_expected,
+    "Fenced frame successfully loaded by specifying its src attribute.");
+
+  // Create an inner config with an empty url.
+  const empty_url_config = new FencedFrameInnerConfig('');
+  fenced_frame.innerConfig = empty_url_config;
+
+  // Installing an inner config with an empty url to the fenced frame should
+  // unload the original document.
+  const server_value = await readValueFromServer(fenced_frame_loaded_key);
+  assert_false(server_value.status);
+
+}, 'Installing an inner config with empty url to a navigated fenced unloads ',
+  'the original document.');
+</script>
+
+</body>
diff --git a/third_party/libpng/BUILD.gn b/third_party/libpng/BUILD.gn
index 151b111..e547ef4c 100644
--- a/third_party/libpng/BUILD.gn
+++ b/third_party/libpng/BUILD.gn
@@ -5,7 +5,10 @@
 import("//build/config/arm.gni")
 import("//build/config/chromecast_build.gni")
 import("//build/config/mips.gni")
-import("//testing/libfuzzer/fuzzer_test.gni")
+
+if (build_with_chromium) {
+  import("//testing/libfuzzer/fuzzer_test.gni")
+}
 
 config("libpng_config") {
   include_dirs = [ "." ]
@@ -120,15 +123,17 @@
   }
 }
 
-libpng_ossfuzz_seed_corpuses = [
-  "//components/viz/test/data",
-  "//third_party/blink/web_tests/images/png-suite/samples",
-  "//third_party/blink/web_tests/images/resources/pngfuzz",
-]
+if (build_with_chromium) {
+  libpng_ossfuzz_seed_corpuses = [
+    "//components/viz/test/data",
+    "//third_party/blink/web_tests/images/png-suite/samples",
+    "//third_party/blink/web_tests/images/resources/pngfuzz",
+  ]
 
-fuzzer_test("libpng_read_fuzzer") {
-  sources = [ "contrib/oss-fuzz/libpng_read_fuzzer.cc" ]
-  deps = [ ":libpng" ]
-  dict = "contrib/oss-fuzz/png.dict"
-  seed_corpuses = libpng_ossfuzz_seed_corpuses
+  fuzzer_test("libpng_read_fuzzer") {
+    sources = [ "contrib/oss-fuzz/libpng_read_fuzzer.cc" ]
+    deps = [ ":libpng" ]
+    dict = "contrib/oss-fuzz/png.dict"
+    seed_corpuses = libpng_ossfuzz_seed_corpuses
+  }
 }
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium
index e6d507a..57dca508 100644
--- a/third_party/nearby/README.chromium
+++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@
 Name: Nearby Connections Library
 Short Name: Nearby
 URL: https://github.com/google/nearby
-Version: 7a918e83105a1ed6b7acb5c0611518b4f3a701cf
+Version: beb67fc02a5b9fbbd5ff550acb80277d8b52be92
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/pthreadpool/BUILD.gn b/third_party/pthreadpool/BUILD.gn
index e1afe01..0e6212f 100644
--- a/third_party/pthreadpool/BUILD.gn
+++ b/third_party/pthreadpool/BUILD.gn
@@ -3,15 +3,24 @@
 # found in the LICENSE file.
 
 config("pthreadpool_config") {
-  include_dirs = [ "src/include" ]
+  include_dirs = [
+    "src/include",
+    "src/src",
+  ]
+  defines = [ "PTHREADPOOL_USE_GCD=0" ]
 }
 
 source_set("pthreadpool") {
   public = [ "src/include/pthreadpool.h" ]
 
   sources = [
+    "src/src/fastpath.c",
     "src/src/memory.c",
     "src/src/portable-api.c",
+    "src/src/threadpool-atomics.h",
+    "src/src/threadpool-common.h",
+    "src/src/threadpool-object.h",
+    "src/src/threadpool-utils.h",
   ]
 
   if (is_win) {
diff --git a/third_party/speech-dispatcher/DIR_METADATA b/third_party/speech-dispatcher/DIR_METADATA
index e81b58c5..e77aa423 100644
--- a/third_party/speech-dispatcher/DIR_METADATA
+++ b/third_party/speech-dispatcher/DIR_METADATA
@@ -1,3 +1 @@
-monorail: {
-  component: "Internals>SpeechSynthesis"
-}
+mixins: "//chromeos/services/tts/COMMON_METADATA"
diff --git a/third_party/tflite/BUILD.gn b/third_party/tflite/BUILD.gn
index 5d66106..97d7fd4b 100644
--- a/third_party/tflite/BUILD.gn
+++ b/third_party/tflite/BUILD.gn
@@ -14,7 +14,10 @@
 }
 
 config("tflite_config") {
-  include_dirs = [ "src" ]
+  include_dirs = [
+    "src",
+    "//third_party/pthreadpool/src/include",
+  ]
   if (is_android) {
     libs = [ "log" ]
   }
@@ -392,6 +395,7 @@
     "//third_party/fp16",
     "//third_party/gemmlowp",
     "//third_party/neon_2_sse",
+    "//third_party/pthreadpool",
     "//third_party/ruy",
   ]
 
@@ -529,6 +533,7 @@
     "//third_party/fp16",
     "//third_party/gemmlowp",
     "//third_party/neon_2_sse",
+    "//third_party/pthreadpool",
     "//third_party/ruy",
   ]
 
@@ -536,7 +541,6 @@
     deps += [
       ":tflite_kernel_internals",
       "//third_party/cpuinfo",
-      "//third_party/pthreadpool",
       "//third_party/xnnpack",
     ]
   }
diff --git a/third_party/tflite/README.chromium b/third_party/tflite/README.chromium
index f8e2c79..b34d2da2 100644
--- a/third_party/tflite/README.chromium
+++ b/third_party/tflite/README.chromium
@@ -1,8 +1,8 @@
 Name: TensorFlow Lite
 Short Name: tflite
 URL: https://github.com/tensorflow/tensorflow
-Version: 11eaf0880146cdd6af17b38fb1361dd031ee0f8c
-Date: 2022/11/07
+Version: 1596f8978aa6e91bf0204b9e55ac4f99ea9374df
+Date: 2022/11/15
 License: Apache 2.0
 License File: LICENSE
 Security Critical: Yes
diff --git a/third_party/zlib/contrib/tests/fuzzers/deflate_fuzzer.cc b/third_party/zlib/contrib/tests/fuzzers/deflate_fuzzer.cc
index cf1a964..ad1a985 100644
--- a/third_party/zlib/contrib/tests/fuzzers/deflate_fuzzer.cc
+++ b/third_party/zlib/contrib/tests/fuzzers/deflate_fuzzer.cc
@@ -10,7 +10,7 @@
 #include <string.h>
 #include <vector>
 
-#include "third_party/zlib/zlib.h"
+#include "zlib.h"
 
 // Fuzzer builds often have NDEBUG set, so roll our own assert macro.
 #define ASSERT(cond)                                                           \
diff --git a/third_party/zlib/contrib/tests/fuzzers/deflate_set_dictionary_fuzzer.cc b/third_party/zlib/contrib/tests/fuzzers/deflate_set_dictionary_fuzzer.cc
index 88511c1..9677820 100644
--- a/third_party/zlib/contrib/tests/fuzzers/deflate_set_dictionary_fuzzer.cc
+++ b/third_party/zlib/contrib/tests/fuzzers/deflate_set_dictionary_fuzzer.cc
@@ -7,7 +7,7 @@
 #include <cassert>
 #include <vector>
 
-#include "third_party/zlib/zlib.h"
+#include "zlib.h"
 
 static Bytef buffer[256 * 1024] = {0};
 
diff --git a/third_party/zlib/contrib/tests/fuzzers/inflate_fuzzer.cc b/third_party/zlib/contrib/tests/fuzzers/inflate_fuzzer.cc
index 836a441..d9d6202 100644
--- a/third_party/zlib/contrib/tests/fuzzers/inflate_fuzzer.cc
+++ b/third_party/zlib/contrib/tests/fuzzers/inflate_fuzzer.cc
@@ -8,7 +8,7 @@
 #include <cassert>
 #include <vector>
 
-#include "third_party/zlib/zlib.h"
+#include "zlib.h"
 
 static Bytef buffer[256 * 1024] = {0};
 
diff --git a/third_party/zlib/contrib/tests/fuzzers/streaming_inflate_fuzzer.cc b/third_party/zlib/contrib/tests/fuzzers/streaming_inflate_fuzzer.cc
index c054e98..dac170a 100644
--- a/third_party/zlib/contrib/tests/fuzzers/streaming_inflate_fuzzer.cc
+++ b/third_party/zlib/contrib/tests/fuzzers/streaming_inflate_fuzzer.cc
@@ -7,7 +7,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "third_party/zlib/zlib.h"
+#include "zlib.h"
 
 // Fuzzer builds often have NDEBUG set, so roll our own assert macro.
 #define ASSERT(cond)                                                           \
diff --git a/third_party/zlib/contrib/tests/fuzzers/uncompress_fuzzer.cc b/third_party/zlib/contrib/tests/fuzzers/uncompress_fuzzer.cc
index c41747a..e63a8c05 100644
--- a/third_party/zlib/contrib/tests/fuzzers/uncompress_fuzzer.cc
+++ b/third_party/zlib/contrib/tests/fuzzers/uncompress_fuzzer.cc
@@ -6,7 +6,7 @@
 #include <stdint.h>
 #include <string.h>
 
-#include "third_party/zlib/zlib.h"
+#include "zlib.h"
 
 static Bytef buffer[256 * 1024] = {0};
 
diff --git a/tools/android/checkstyle/chromium-style-5.0.xml b/tools/android/checkstyle/chromium-style-5.0.xml
index f5d8a99..36fd95b 100644
--- a/tools/android/checkstyle/chromium-style-5.0.xml
+++ b/tools/android/checkstyle/chromium-style-5.0.xml
@@ -180,5 +180,12 @@
       <property name="ignoreComments" value="true"/>
       <property name="message" value="Launching an ActivityScenario manually is error prone for any test run in a batch. Failing to #close will cause the Activity to leak into the next test. Consider replacing with ActivityScenarioRule. (https://crbug.com/1338271)"/>
     </module>
+    <module name="RegexpSinglelineJava">
+      <property name="id" value="GuavaOptional"/>
+      <property name="severity" value="warning"/>
+      <property name="format" value="import\ com.google.common.base.Optional;"/>
+      <property name="ignoreComments" value="true"/>
+      <property name="message" value="Use java.util.Optional instead of com.google.common.base.Optional unless required to interact with external libraries."/>
+    </module>
   </module>
 </module>
diff --git a/tools/binary_size/libsupersize/dalvik_bytecode.py b/tools/binary_size/libsupersize/dalvik_bytecode.py
new file mode 100644
index 0000000..bd3bde4
--- /dev/null
+++ b/tools/binary_size/libsupersize/dalvik_bytecode.py
@@ -0,0 +1,337 @@
+# 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.
+"""Utilities for parsing Dalvik bytecode."""
+
+import collections
+import struct
+
+# Dalvik Bytecode specs copied from first two column of table in:
+#   https://source.android.com/docs/core/runtime/dalvik-bytecode#instructions
+# with minor modification (truncating comments).
+_DALVIK_BYTECODE_SPECS = """00 10x  nop
+01 12x  move vA, vB
+02 22x  move/from16 vAA, vBBBB
+03 32x  move/16 vAAAA, vBBBB
+04 12x  move-wide vA, vB
+05 22x  move-wide/from16 vAA, vBBBB
+06 32x  move-wide/16 vAAAA, vBBBB
+07 12x  move-object vA, vB
+08 22x  move-object/from16 vAA, vBBBB
+09 32x  move-object/16 vAAAA, vBBBB
+0a 11x  move-result vAA
+0b 11x  move-result-wide vAA
+0c 11x  move-result-object vAA
+0d 11x  move-exception vAA
+0e 10x  return-void
+0f 11x  return vAA
+10 11x  return-wide vAA
+11 11x  return-object vAA
+12 11n  const/4 vA, #+B
+13 21s  const/16 vAA, #+BBBB
+14 31i  const vAA, #+BBBBBBBB
+15 21h  const/high16 vAA, #+BBBB0000
+16 21s  const-wide/16 vAA, #+BBBB
+17 31i  const-wide/32 vAA, #+BBBBBBBB
+18 51l  const-wide vAA, #+BBBBBBBBBBBBBBBB
+19 21h  const-wide/high16 vAA, #+BBBB000000000000
+1a 21c  const-string vAA, string@BBBB
+1b 31c  const-string/jumbo vAA, string@BBBBBBBB
+1c 21c  const-class vAA, type@BBBB
+1d 11x  monitor-enter vAA
+1e 11x  monitor-exit vAA
+1f 21c  check-cast vAA, type@BBBB
+20 22c  instance-of vA, vB, type@CCCC
+21 12x  array-length vA, vB
+22 21c  new-instance vAA, type@BBBB
+23 22c  new-array vA, vB, type@CCCC
+24 35c  filled-new-array {vC, vD, vE, vF, vG}, type@BBBB
+25 3rc  filled-new-array/range {vCCCC .. vNNNN}, type@BBBB
+26 31t  fill-array-data vAA, +BBBBBBBB (with supplemental data...)
+27 11x  throw vAA
+28 10t  goto +AA
+29 20t  goto/16 +AAAA
+2a 30t  goto/32 +AAAAAAAA
+2b 31t  packed-switch vAA, +BBBBBBBB (with supplemental data...)
+2c 31t  sparse-switch vAA, +BBBBBBBB (with supplemental data...)
+2d..31 23x  cmpkind vAA, vBB, vCC
+2d: cmpl-float (lt bias)
+2e: cmpg-float (gt bias)
+2f: cmpl-double (lt bias)
+30: cmpg-double (gt bias)
+31: cmp-long
+32..37 22t  if-test vA, vB, +CCCC
+32: if-eq
+33: if-ne
+34: if-lt
+35: if-ge
+36: if-gt
+37: if-le
+38..3d 21t  if-testz vAA, +BBBB
+38: if-eqz
+39: if-nez
+3a: if-ltz
+3b: if-gez
+3c: if-gtz
+3d: if-lez
+3e..43 10x  (unused)
+44..51 23x  arrayop vAA, vBB, vCC
+44: aget
+45: aget-wide
+46: aget-object
+47: aget-boolean
+48: aget-byte
+49: aget-char
+4a: aget-short
+4b: aput
+4c: aput-wide
+4d: aput-object
+4e: aput-boolean
+4f: aput-byte
+50: aput-char
+51: aput-short
+52..5f 22c  iinstanceop vA, vB, field@CCCC
+52: iget
+53: iget-wide
+54: iget-object
+55: iget-boolean
+56: iget-byte
+57: iget-char
+58: iget-short
+59: iput
+5a: iput-wide
+5b: iput-object
+5c: iput-boolean
+5d: iput-byte
+5e: iput-char
+5f: iput-short
+60..6d 21c  sstaticop vAA, field@BBBB
+60: sget
+61: sget-wide
+62: sget-object
+63: sget-boolean
+64: sget-byte
+65: sget-char
+66: sget-short
+67: sput
+68: sput-wide
+69: sput-object
+6a: sput-boolean
+6b: sput-byte
+6c: sput-char
+6d: sput-short
+6e..72 35c  invoke-kind {vC, vD, vE, vF, vG}, meth@BBBB
+6e: invoke-virtual
+6f: invoke-super
+70: invoke-direct
+71: invoke-static
+72: invoke-interface
+73 10x  (unused)
+74..78 3rc  invoke-kind/range {vCCCC .. vNNNN}, meth@BBBB
+74: invoke-virtual/range
+75: invoke-super/range
+76: invoke-direct/range
+77: invoke-static/range
+78: invoke-interface/range
+79..7a 10x  (unused)
+7b..8f 12x  unop vA, vB
+7b: neg-int
+7c: not-int
+7d: neg-long
+7e: not-long
+7f: neg-float
+80: neg-double
+81: int-to-long
+82: int-to-float
+83: int-to-double
+84: long-to-int
+85: long-to-float
+86: long-to-double
+87: float-to-int
+88: float-to-long
+89: float-to-double
+8a: double-to-int
+8b: double-to-long
+8c: double-to-float
+8d: int-to-byte
+8e: int-to-char
+8f: int-to-short
+90..af 23x  binop vAA, vBB, vCC
+90: add-int
+91: sub-int
+92: mul-int
+93: div-int
+94: rem-int
+95: and-int
+96: or-int
+97: xor-int
+98: shl-int
+99: shr-int
+9a: ushr-int
+9b: add-long
+9c: sub-long
+9d: mul-long
+9e: div-long
+9f: rem-long
+a0: and-long
+a1: or-long
+a2: xor-long
+a3: shl-long
+a4: shr-long
+a5: ushr-long
+a6: add-float
+a7: sub-float
+a8: mul-float
+a9: div-float
+aa: rem-float
+ab: add-double
+ac: sub-double
+ad: mul-double
+ae: div-double
+af: rem-double
+b0..cf 12x  binop/2addr vA, vB
+b0: add-int/2addr
+b1: sub-int/2addr
+b2: mul-int/2addr
+b3: div-int/2addr
+b4: rem-int/2addr
+b5: and-int/2addr
+b6: or-int/2addr
+b7: xor-int/2addr
+b8: shl-int/2addr
+b9: shr-int/2addr
+ba: ushr-int/2addr
+bb: add-long/2addr
+bc: sub-long/2addr
+bd: mul-long/2addr
+be: div-long/2addr
+bf: rem-long/2addr
+c0: and-long/2addr
+c1: or-long/2addr
+c2: xor-long/2addr
+c3: shl-long/2addr
+c4: shr-long/2addr
+c5: ushr-long/2addr
+c6: add-float/2addr
+c7: sub-float/2addr
+c8: mul-float/2addr
+c9: div-float/2addr
+ca: rem-float/2addr
+cb: add-double/2addr
+cc: sub-double/2addr
+cd: mul-double/2addr
+ce: div-double/2addr
+cf: rem-double/2addr
+d0..d7 22s  binop/lit16 vA, vB, #+CCCC
+d0: add-int/lit16
+d1: rsub-int (reverse subtract)
+d2: mul-int/lit16
+d3: div-int/lit16
+d4: rem-int/lit16
+d5: and-int/lit16
+d6: or-int/lit16
+d7: xor-int/lit16
+d8..e2 22b  binop/lit8 vAA, vBB, #+CC
+d8: add-int/lit8
+d9: rsub-int/lit8
+da: mul-int/lit8
+db: div-int/lit8
+dc: rem-int/lit8
+dd: and-int/lit8
+de: or-int/lit8
+df: xor-int/lit8
+e0: shl-int/lit8
+e1: shr-int/lit8
+e2: ushr-int/lit8
+e3..f9 10x  (unused)
+fa 45cc invoke-polymorphic {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH
+fb 4rcc invoke-polymorphic/range {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH
+fc 35c  invoke-custom {vC, vD, vE, vF, vG}, call_site@BBBB
+fd 3rc  invoke-custom/range {vCCCC .. vNNNN}, call_site@BBBB
+fe 21c  const-method-handle vAA, method_handle@BBBB
+ff 21c  const-method-type vAA, proto@BBBB
+"""
+
+DalvikByteCode = collections.namedtuple('DalvikByteCode',
+                                        'op,size,format,name,params')
+
+
+def _ParseByteCodeSpecs():
+  """Parses _DALVIK_BYTECODE_SPECS into DalvikByteCode array."""
+  format_map = [None] * 256
+  name_map = [None] * 256
+  params_map = [None] * 256
+  (op_lo, op_hi) = (None, None)
+  for line in _DALVIK_BYTECODE_SPECS.splitlines():
+    comment_pos = line.find(' (')
+    if comment_pos >= 0:
+      line = line[:comment_pos]
+    assert len(line) >= 5
+    if line[2] == ':':
+      # Inside op range, e.g.: 'b0: add-int/2addr'.
+      # ['b0', 'add-int/2addr'].
+      toks = line.split(': ')
+      assert len(toks) == 2
+      op = int(toks[0], 16)
+      assert op_lo <= op <= op_hi
+      name_map[op] = toks[1]  # 'add-int/2addr'.
+      if op == op_hi:
+        op_lo = op_hi = None
+    elif line[2:4] == '..':
+      # Define op range, e.g.: 'b0..cf 12x  binop/2addr vA, vB'.
+      # ['b0..cf', '12x', 'binop/2addr', 'vA, vB'].
+      toks = line.split(maxsplit=3)
+      # (0xb0, 0xcf).
+      (op_lo, op_hi) = (int(t, 16) for t in toks[0].split('..'))
+      for op in range(op_lo, op_hi + 1):
+        format_map[op] = toks[1]  # '12x'.
+      if len(toks) > 2:  # If not unused.
+        for op in range(op_lo, op_hi + 1):
+          params_map[op] = toks[3]  # 'vA, vB'.
+    else:
+      # Standalone op, e.g.: '15 21h  const/high16 vAA, #+BBBB0000'.
+      # ['15', '21h', 'const/high16', 'vAA, #+BBBB0000'].
+      toks = line.split(maxsplit=3)
+      op = int(toks[0], 16)
+      format_map[op] = toks[1]  # '21h'.
+      if len(toks) > 2:  # If not unused.
+        name_map[op] = toks[2]  # 'const/high16'.
+        params_map[op] = toks[3] if len(toks) >= 4 else ''  # 'vAA, #+BBBB0000'.
+
+  ret = []
+  for op in range(256):
+    size = int(format_map[op][0]) * 2  # '21h' -> 4.
+    bc = DalvikByteCode(op, size, format_map[op], name_map[op], params_map[op])
+    ret.append(bc)
+  return ret
+
+
+DALVIK_INSTRUCTIONS = _ParseByteCodeSpecs()
+
+
+def Split(insns):
+  """Splits Dalvik code into a series of instruction bytes.
+
+  The minimalistic approach avoids wasted work. It's up to the caller to filter
+  and/or disassemble emitted bytes. It is assumed that supplemental data (from
+  31t instructions {fill-array-data, packed-switch, sparse-switch}) are found at
+  the end of `insns`. These are detected and omitted.
+
+  Args:
+    insns: Even-length bytearray data containing valid Dalvik code.
+  """
+  pos_end = len(insns)
+  assert pos_end % 2 == 0
+  pos = 0
+  while pos < pos_end:
+    instr = DALVIK_INSTRUCTIONS[insns[pos]]
+    size = instr.size
+    chunk = insns[pos:pos + size]
+    # Instructions with supplemental data contains relative offset to where
+    # data starts, which indicates where code ends.
+    if instr.format == '31t':
+      offset = struct.unpack_from('<L', chunk, 2)[0]
+      pos_end = min(pos_end, pos + offset * 2)
+    yield chunk
+    pos += size
+  # Do not emit supplemental data.
diff --git a/tools/binary_size/libsupersize/dex_parser.py b/tools/binary_size/libsupersize/dex_parser.py
index 0945cf1..328ab05 100755
--- a/tools/binary_size/libsupersize/dex_parser.py
+++ b/tools/binary_size/libsupersize/dex_parser.py
@@ -13,12 +13,14 @@
 import argparse
 import collections
 import errno
+import itertools
 import os
 import re
 import struct
 import sys
 import zipfile
 
+import dalvik_bytecode
 import stream_reader
 
 # https://source.android.com/devices/tech/dalvik/dex-format#header-item
@@ -51,6 +53,8 @@
 # Full list of type codes:
 # https://source.android.com/devices/tech/dalvik/dex-format#type-codes
 _TYPE_TYPE_LIST = 0x1001
+_TYPE_CLASS_DATA_ITEM = 0x2000
+_TYPE_CODE_ITEM = 0x2001
 
 _CLASS_ACCESS_FLAGS = {
     0x1: 'public',
@@ -69,24 +73,115 @@
                                    ','.join(t[0] for t in _DEX_HEADER_FMT))
 
 # Simple memory items.
-_StringDataItem = collections.namedtuple('StringItem', 'utf16_size,data')
+_StringDataItem = collections.namedtuple('StringDataItem', 'utf16_size,data')
 _TypeIdItem = collections.namedtuple('TypeIdItem', 'descriptor_idx')
 _ProtoIdItem = collections.namedtuple(
     'ProtoIdItem', 'shorty_idx,return_type_idx,parameters_off')
 _MethodIdItem = collections.namedtuple('MethodIdItem',
                                        'type_idx,proto_idx,name_idx')
-_TypeItem = collections.namedtuple('TypeItem', 'type_idx')
 _ClassDefItem = collections.namedtuple(
     'ClassDefItem',
     'class_idx,access_flags,superclass_idx,interfaces_off,source_file_idx,'
     'annotations_off,class_data_off,static_values_off')
 
+_ClassDataItem = collections.namedtuple(
+    'ClassDataItem',
+    'offset,static_fields_size,instance_fields_size,direct_methods_size,'
+    'virtual_methods_size,static_fields,instance_fields,direct_methods,'
+    'virtual_methods')
+_EncodedField = collections.namedtuple('EncodedField', 'field_idx,access_flags')
+_EncodedMethod = collections.namedtuple('EncodedMethod',
+                                        'method_idx,access_flags,code_off')
+
+_TypeItem = collections.namedtuple('TypeItem', 'type_idx')
+_CodeItem = collections.namedtuple(
+    'CodeItem',
+    'offset,registers_size,ins_size,outs_size,tries_size,debug_info_off,'
+    'insns_size,insns,tries,handlers')
+_TryItem = collections.namedtuple('TryItem',
+                                  'start_addr,insn_count,handler_off')
+_EncodedCatchHandlerList = collections.namedtuple('_EncodedCatchHandlerList',
+                                                  'size,list')
+_EncodedCatchHandler = collections.namedtuple('_EncodedCatchHandler',
+                                              'size,handlers,catch_all_addr')
+_EncodedTypeAddrPair = collections.namedtuple('_EncodedTypeAddrPair',
+                                              'type_idx,addr')
+
 
 class _DexReader(stream_reader.StreamReader):
   def NextDexHeader(self):
     header_fmt = '<' + ''.join(t[1] for t in _DEX_HEADER_FMT)
     return DexHeader._make(self.NextStruct(header_fmt))
 
+  def NextClassDataItem(self):
+    offset = self.Tell()
+    static_fields_size = self.NextULeb128()
+    instance_fields_size = self.NextULeb128()
+    direct_methods_size = self.NextULeb128()
+    virtual_methods_size = self.NextULeb128()
+    static_fields = self.NextEncodedFieldList(static_fields_size)
+    instance_fields = self.NextEncodedFieldList(instance_fields_size)
+    direct_methods = self.NextEncodedMethodList(direct_methods_size)
+    virtual_methods = self.NextEncodedMethodList(virtual_methods_size)
+    return _ClassDataItem(offset, static_fields_size, instance_fields_size,
+                          direct_methods_size, virtual_methods_size,
+                          static_fields, instance_fields, direct_methods,
+                          virtual_methods)
+
+  def NextEncodedFieldList(self, count):
+    ret = []
+    field_idx = 0
+    for _ in range(count):
+      field_idx += self.NextULeb128()
+      ret.append(_EncodedField(field_idx, self.NextULeb128()))
+    return ret
+
+  def NextEncodedMethodList(self, count):
+    ret = []
+    method_idx = 0
+    for _ in range(count):
+      method_idx += self.NextULeb128()
+      ret.append(
+          _EncodedMethod(method_idx, self.NextULeb128(), self.NextULeb128()))
+    return ret
+
+  def NextCodeItem(self):
+    item_offset = self.Tell()
+    registers_size = self.NextUShort()
+    ins_size = self.NextUShort()
+    outs_size = self.NextUShort()
+    tries_size = self.NextUShort()
+    debug_info_off = self.NextUInt()
+    insns_size = self.NextUInt()
+    insns = self.NextBytes(insns_size * 2)
+    if tries_size > 0:
+      self.AlignUpTo(4)
+    tries = [self.NextTryItem() for _ in range(tries_size)]
+    handlers = None
+    if tries_size != 0:
+      handlers = self.NextEncodedCatchHandlerList()
+    self.AlignUpTo(4)
+    return _CodeItem(item_offset, registers_size, ins_size, outs_size,
+                     tries_size, debug_info_off, insns_size, insns, tries,
+                     handlers)
+
+  def NextTryItem(self):
+    return _TryItem(self.NextUInt(), self.NextUShort(), self.NextUShort())
+
+  def NextEncodedCatchHandlerList(self):
+    size = self.NextULeb128()
+    handler_list = [self.NextEncodedCatchHandler() for _ in range(size)]
+    return _EncodedCatchHandlerList(size, handler_list)
+
+  def NextEncodedCatchHandler(self):
+    size = self.NextSLeb128()
+    handlers = [self.NextEncodedTypeAddrPair() for _ in range(abs(size))]
+    catch_all_addr = self.NextULeb128() if size <= 0 else None
+    return _EncodedCatchHandler(size, handlers, catch_all_addr)
+
+  def NextEncodedTypeAddrPair(self):
+    return _EncodedTypeAddrPair(self.NextULeb128(), self.NextULeb128())
+
 
 class _MemoryItemList:
   """Base class for repeated memory items."""
@@ -140,10 +235,10 @@
 class _StringItemList(_MemoryItemList):
   def __init__(self, reader, offset, size):
     reader.Seek(offset)
-    string_item_offsets = iter([reader.NextUInt() for _ in range(size)])
+    string_data_item_offsets = iter([reader.NextUInt() for _ in range(size)])
 
     def factory(x):
-      x.Seek(next(string_item_offsets))
+      x.Seek(next(string_data_item_offsets))
       string = x.NextString()
       return _StringDataItem(len(string), string)
 
@@ -169,6 +264,23 @@
     super().__init__(reader, offset, size, factory)
 
 
+class _ClassDefItemList(_MemoryItemList):
+  def __init__(self, reader, offset, size):
+    reader.Seek(offset)
+
+    def factory(x):
+      return _ClassDefItem(*(x.NextUInt()
+                             for _ in range(len(_ClassDefItem._fields))))
+
+    super().__init__(reader, offset, size, factory)
+
+
+class _ClassDataItemList(_MemoryItemList):
+  def __init__(self, reader, offset, size):
+    reader.Seek(offset)
+    super().__init__(reader, offset, size, lambda x: x.NextClassDataItem())
+
+
 class _TypeListItem(_MemoryItemList):
   def __init__(self, reader):
     offset = reader.Tell()
@@ -190,15 +302,10 @@
     super().__init__(reader, offset, size, _TypeListItem)
 
 
-class _ClassDefItemList(_MemoryItemList):
+class _CodeItemList(_MemoryItemList):
   def __init__(self, reader, offset, size):
     reader.Seek(offset)
-
-    def factory(x):
-      return _ClassDefItem(*(x.NextUInt()
-                             for _ in range(len(_ClassDefItem._fields))))
-
-    super().__init__(reader, offset, size, factory)
+    super().__init__(reader, offset, size, lambda x: x.NextCodeItem())
 
 
 class _DexMapItem:
@@ -239,14 +346,16 @@
     reader: _DexReader object used to decode DEX file contents.
     header: DexHeader for this DEX file.
     map_list: _DexMapList object containing list of DEX file contents.
-    string_item_list: _StringItemList containing _StringDataItems that are
+    string_data_item_list: _StringItemList containing _StringDataItems that are
       referenced by index in other sections.
-    type_item_list: _TypeIdItemList containing _TypeIdItems.
-    proto_item_list: _ProtoIdItemList containing _ProtoIdItems.
-    method_item_list: _MethodIdItemList containing _MethodIdItems.
+    type_id_item_list: _TypeIdItemList containing _TypeIdItems.
+    proto_id_item_list: _ProtoIdItemList containing _ProtoIdItems.
+    method_id_item_list: _MethodIdItemList containing _MethodIdItems.
     type_list_item_list: _TypeListItemList containing _TypeListItems.
       _TypeListItems are referenced by their offsets from other DEX items.
     class_def_item_list: _ClassDefItemList containing _ClassDefItems.
+    class_data_item_list: _ClassDataItemList containing _ClassDataItems.
+    code_item_list: _CodeItemList containing _CodeItems.
   """
 
   def __init__(self, data):
@@ -258,17 +367,18 @@
     self.reader = _DexReader(data)
     self.header = self.reader.NextDexHeader()
     self.map_list = _DexMapList(self.reader, self.header.map_off)
-    self.string_item_list = _StringItemList(self.reader,
-                                            self.header.string_ids_off,
-                                            self.header.string_ids_size)
-    self.type_item_list = _TypeIdItemList(self.reader, self.header.type_ids_off,
-                                          self.header.type_ids_size)
-    self.proto_item_list = _ProtoIdItemList(self.reader,
-                                            self.header.proto_ids_off,
-                                            self.header.proto_ids_size)
-    self.method_item_list = _MethodIdItemList(self.reader,
-                                              self.header.method_ids_off,
-                                              self.header.method_ids_size)
+    self.string_data_item_list = _StringItemList(self.reader,
+                                                 self.header.string_ids_off,
+                                                 self.header.string_ids_size)
+    self.type_id_item_list = _TypeIdItemList(self.reader,
+                                             self.header.type_ids_off,
+                                             self.header.type_ids_size)
+    self.proto_id_item_list = _ProtoIdItemList(self.reader,
+                                               self.header.proto_ids_off,
+                                               self.header.proto_ids_size)
+    self.method_id_item_list = _MethodIdItemList(self.reader,
+                                                 self.header.method_ids_off,
+                                                 self.header.method_ids_size)
     self.class_def_item_list = _ClassDefItemList(self.reader,
                                                  self.header.class_defs_off,
                                                  self.header.class_defs_size)
@@ -285,13 +395,32 @@
         for type_list in self.type_list_item_list
     }
 
+    class_data_item = self.map_list.get(_TYPE_CLASS_DATA_ITEM)
+    if class_data_item:
+      self.class_data_item_list = _ClassDataItemList(self.reader,
+                                                     class_data_item.offset,
+                                                     class_data_item.size)
+      self._class_data_item_by_offset = {
+          class_data_item.offset: class_data_item
+          for class_data_item in self.class_data_item_list
+      }
+
+    code_item = self.map_list.get(_TYPE_CODE_ITEM)
+    if code_item:
+      self.code_item_list = _CodeItemList(self.reader, code_item.offset,
+                                          code_item.size)
+      self._code_item_by_offset = {
+          code_item.offset: code_item
+          for code_item in self.code_item_list
+      }
+
   def GetString(self, string_idx):
-    string_item = self.string_item_list[string_idx]
-    return string_item.data
+    string_data_item = self.string_data_item_list[string_idx]
+    return string_data_item.data
 
   def GetTypeString(self, type_idx):
-    type_item = self.type_item_list[type_idx]
-    return self.GetString(type_item.descriptor_idx)
+    type_id_item = self.type_id_item_list[type_idx]
+    return self.GetString(type_id_item.descriptor_idx)
 
   def GetTypeListStringsByOffset(self, offset):
     if not offset:
@@ -299,6 +428,12 @@
     type_list = self._type_lists_by_offset[offset]
     return tuple(self.GetTypeString(item.type_idx) for item in type_list)
 
+  def GetClassDataItemByOffset(self, offset):
+    return self._class_data_item_by_offset.get(offset)
+
+  def GetCodeItemByOffset(self, offset):
+    return self._code_item_by_offset.get(offset)
+
   @staticmethod
   def ResolveClassAccessFlags(access_flags):
     return tuple(flag_string
@@ -312,13 +447,13 @@
       Tuples that look like:
         (class name, return type, method name, (parameter type, ...)).
     """
-    for method_item in self.method_item_list:
-      class_name_string = self.GetTypeString(method_item.type_idx)
-      method_name_string = self.GetString(method_item.name_idx)
-      proto_item = self.proto_item_list[method_item.proto_idx]
-      return_type_string = self.GetTypeString(proto_item.return_type_idx)
+    for method_id_item in self.method_id_item_list:
+      class_name_string = self.GetTypeString(method_id_item.type_idx)
+      method_name_string = self.GetString(method_id_item.name_idx)
+      proto_id_item = self.proto_id_item_list[method_id_item.proto_idx]
+      return_type_string = self.GetTypeString(proto_id_item.return_type_idx)
       parameter_types = self.GetTypeListStringsByOffset(
-          proto_item.parameters_off)
+          proto_id_item.parameters_off)
       yield (class_name_string, return_type_string, method_name_string,
              parameter_types)
 
@@ -326,12 +461,14 @@
     items = [
         self.header,
         self.map_list,
-        self.type_item_list,
-        self.proto_item_list,
-        self.method_item_list,
-        self.string_item_list,
+        self.string_data_item_list,
+        self.type_id_item_list,
+        self.proto_id_item_list,
+        self.method_id_item_list,
         self.type_list_item_list,
         self.class_def_item_list,
+        self.class_data_item_list,
+        self.code_item_list,
     ]
     return '\n'.join(str(item) for item in items)
 
@@ -352,9 +489,9 @@
 
 class _DumpStrings(_DumpCommand):
   def Run(self):
-    for string_item in self._dexfile.string_item_list:
+    for string_data_item in self._dexfile.string_data_item_list:
       # Some strings are likely to be non-ascii (vs. methods/classes).
-      print(string_item.data.encode('utf-8'))
+      print(string_data_item.data.encode('utf-8'))
 
 
 class _DumpMethods(_DumpCommand):
@@ -377,6 +514,44 @@
           class_string, superclass_string, interfaces, access_flags))
 
 
+class _DumpCodes(_DumpCommand):
+  def Run(self):
+    dexfile = self._dexfile
+
+    total_insns_bytes = 0
+    total_insns_count = 0
+    total_code_bytes = 0
+    total_tries_count = 0
+    insns_popu = [0] * 256
+    attrs = [
+        'registers_size', 'ins_size', 'outs_size', 'tries_size', 'insns_size'
+    ]
+    for i, code_item in enumerate(dexfile.code_item_list):
+      total_insns_bytes += len(code_item.insns)
+      total_tries_count += code_item.tries_size
+      insns_count = 0
+      actual_insns_bytes = 0
+      for bytecode in dalvik_bytecode.Split(code_item.insns):
+        insns_popu[bytecode[0]] += 1
+        insns_count += 1
+        actual_insns_bytes += len(bytecode)
+      total_insns_count += insns_count
+      total_code_bytes += actual_insns_bytes
+      details = ', '.join('{}={}'.format(a, getattr(code_item, a))
+                          for a in attrs if getattr(code_item, a) > 0)
+      print('code(%08x) o:%08X: (%s)' % (i, code_item.offset, details))
+    total_data_bytes = total_insns_bytes - total_code_bytes
+
+    print('\n*** Summary ***')
+    print('Code item count:         %d' % len(dexfile.code_item_list))
+    print('Total instruction count: %d' % total_insns_count)
+    print('Total instruction bytes: %d' % total_insns_bytes)
+    print('  Code: %d' % total_code_bytes)
+    print('  Data: %d' % total_data_bytes)
+    print('Total tries count:       %d' % total_tries_count)
+    print('Total tries bytes:       %d' % (total_tries_count * (4 + 2 + 2)))
+
+
 def _DumpDexItems(dexfile_data, name, item):
   dexfile = DexFile(bytearray(dexfile_data))
   print('dex_parser: Dumping {} for {}'.format(item, name))
@@ -385,6 +560,7 @@
       'strings': _DumpStrings,
       'methods': _DumpMethods,
       'classes': _DumpClasses,
+      'codes': _DumpCodes,
   }
   try:
     cmds[item](dexfile).Run()
@@ -399,7 +575,8 @@
   parser.add_argument('input',
                       help='Input (.dex, .jar, .zip, .aab, .apk) file path.')
   parser.add_argument('item',
-                      choices=('summary', 'strings', 'methods', 'classes'),
+                      choices=('summary', 'strings', 'methods', 'classes',
+                               'codes'),
                       help='Item to dump',
                       nargs='?',
                       default='summary')
diff --git a/tools/grit/grit_args.gni b/tools/grit/grit_args.gni
index a60843b..bd7d65bd 100644
--- a/tools/grit/grit_args.gni
+++ b/tools/grit/grit_args.gni
@@ -24,6 +24,7 @@
   "SHARED_INTERMEDIATE_DIR=" + shared_intermediate_dir,
   "_google_chrome=${is_chrome_branded}",
   "_google_chrome_for_testing=${is_chrome_for_testing_branded}",
+  "_use_internal_chrome_for_testing_icons=${use_internal_chrome_for_testing_icons}",
   "chromeos_ash=${is_chromeos_ash}",
   "chromeos_lacros=${is_chromeos_lacros}",
 
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index be2a8f2..0dc6eb5 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -271,8 +271,8 @@
       'fuchsia-fyi-arm64-dbg': 'debug_bot_fuchsia_arm64_reclient',
       'fuchsia-fyi-x64-asan': 'asan_lsan_bot_fuchsia_reclient',
       'fuchsia-fyi-x64-dbg': 'debug_bot_fuchsia_reclient',
-      'fuchsia-x64-chrome-rel': 'release_bot_fuchsia_cfv2_script_chrome_reclient',
-      'fuchsia-x64-workstation': 'release_bot_fuchsia_workstation_reclient',
+      'fuchsia-x64-chrome-rel': 'release_bot_fuchsia_chrome_reclient',
+      'fuchsia-x64-workstation': 'release_bot_fuchsia_chrome_reclient',
     },
 
     'chromium.fuzz': {
@@ -397,8 +397,8 @@
       'chromeos-amd64-generic-rel (reclient compare)': 'chromeos_amd64-generic-vm_use_fake_dbus_clients_reclient',
       'chromeos-amd64-generic-rel (reclient)': 'chromeos_amd64-generic-vm_use_fake_dbus_clients_reclient',
       'fuchsia-code-coverage': 'fuchsia_clang_code_coverage_reclient',
-      'fuchsia-fyi-arm64-cfv2-script': 'release_bot_fuchsia_cfv2_script_arm64_reclient',
-      'fuchsia-fyi-cfv2-script': 'release_bot_fuchsia_cfv2_script_reclient',
+      'fuchsia-fyi-arm64-cfv2-script': 'release_bot_fuchsia_arm64_reclient',
+      'fuchsia-fyi-cfv2-script': 'release_bot_fuchsia_reclient',
       'ios-fieldtrial-rel': 'ios_simulator_debug_static_bot_xctest_arm64_reclient',
       'ios-m1-simulator': 'ios_simulator_debug_static_bot_xctest_arm64_reclient',
       'ios-m1-simulator-cronet': 'ios_cronet_xctest_arm64_reclient',
@@ -450,7 +450,6 @@
       'mac-arm64-on-arm64-rel-reclient': 'mac_arm64_release_bot_reclient',
       'mac-backuprefptr-x64-fyi-rel': 'release_trybot_backuprefptr_x64_reclient',
       'mac-code-coverage': 'clang_code_coverage_reclient',
-      'mac-fieldtrial-rel': 'mac_arm64_gpu_tests_release_bot_minimal_symbols_no_nacl_reclient',
       'mac-hermetic-upgrade-rel': 'release_bot_reclient',
       'mac-perfetto-rel': 'perfetto_release_bot_reclient',
       'mac-upload-perfetto': 'release_bot_perfetto_zlib_reclient',
@@ -1115,9 +1114,9 @@
       'fuchsia-fyi-arm64-dbg': 'debug_bot_fuchsia_arm64',
       'fuchsia-fyi-x64-dbg': 'debug_bot_fuchsia',
       'fuchsia-x64-cast-receiver-rel': 'release_trybot_fuchsia_cast_receiver',
-      'fuchsia-x64-chrome-rel': 'release_trybot_fuchsia_cfv2_script_chrome',
+      'fuchsia-x64-chrome-rel': 'release_trybot_fuchsia_chrome',
       'fuchsia-x64-rel': 'release_trybot_fuchsia',
-      'fuchsia-x64-workstation': 'release_trybot_fuchsia_workstation',
+      'fuchsia-x64-workstation': 'release_trybot_fuchsia_chrome',
     },
 
     'tryserver.chromium.linux': {
@@ -1239,7 +1238,7 @@
       'ios16-sdk-simulator': 'ios_simulator_debug_static_bot_xctest',
       'mac-arm64-on-arm64-rel': 'mac_arm64_release_trybot',
       'mac-builder-next-rel': 'mac_arm64_gpu_tests_release_bot_minimal_symbols_no_nacl',
-      'mac-fieldtrial-rel': 'mac_arm64_gpu_tests_release_bot_minimal_symbols_no_nacl',
+      'mac-fieldtrial-tester': 'mac_arm64_gpu_tests_release_bot_minimal_symbols_no_nacl',
       'mac-inverse-fieldtrials-fyi-rel': 'gpu_tests_release_trybot_invert_fieldtrials',
       'mac-osxbeta-rel': 'gpu_tests_debug_trybot',
       'mac-perfetto-rel': 'perfetto_release_trybot',
@@ -2497,7 +2496,7 @@
 
     'fuchsia_clang_code_coverage_reclient': [
       'clang', 'fuchsia', 'fuchsia_code_coverage', 'no_symbols', 'release_bot_reclient',
-      'use_clang_coverage'
+      'use_clang_coverage', 'fuchsia_legacy_script',
     ],
 
     'fuchsia_clang_tot_official_arm64': [
@@ -3213,11 +3212,11 @@
     ],
 
     'official_goma_fuchsia_arm64_perf': [
-      'cast_receiver_size_optimized_internal', 'official', 'goma', 'minimal_symbols', 'fuchsia', 'fuchsia_include_sd_images', 'arm64', 'ffmpeg_branding_chrome', 'proprietary_codecs', 'test_isolate_no_emulator', 'fuchsia_cfv2_script'
+      'cast_receiver_size_optimized_internal', 'official', 'goma', 'minimal_symbols', 'fuchsia', 'fuchsia_include_sd_images', 'arm64', 'ffmpeg_branding_chrome', 'proprietary_codecs', 'test_isolate_no_emulator'
     ],
 
     'official_goma_fuchsia_x64_perf': [
-      'official', 'goma', 'minimal_symbols', 'fuchsia', 'x64', 'ffmpeg_branding_chrome', 'proprietary_codecs', 'test_isolate_no_emulator', 'fuchsia_cfv2_script'
+      'official', 'goma', 'minimal_symbols', 'fuchsia', 'x64', 'ffmpeg_branding_chrome', 'proprietary_codecs', 'test_isolate_no_emulator'
     ],
 
     'official_goma_linux_perf': [
@@ -3452,26 +3451,14 @@
       'release_bot_reclient', 'fuchsia', 'cast_receiver_size_optimized',
     ],
 
-    'release_bot_fuchsia_cfv2_script_arm64_reclient': [
-      'release_bot_reclient', 'fuchsia', 'arm64', 'arm64_host', 'fuchsia_cfv2_script',
-    ],
-
-    'release_bot_fuchsia_cfv2_script_chrome_reclient': [
-      'release_bot_reclient', 'fuchsia',  'fuchsia_cfv2_script', 'fuchsia_chrome',
-    ],
-
-    'release_bot_fuchsia_cfv2_script_reclient': [
-      'release_bot_reclient', 'fuchsia', 'fuchsia_cfv2_script',
+    'release_bot_fuchsia_chrome_reclient': [
+      'release_bot_reclient', 'fuchsia', 'fuchsia_chrome'
     ],
 
     'release_bot_fuchsia_reclient': [
       'release_bot_reclient', 'fuchsia',
     ],
 
-    'release_bot_fuchsia_workstation_reclient': [
-      'release_bot_reclient', 'fuchsia', 'fuchsia_chrome'
-    ],
-
     'release_bot_mac_strip_minimal_symbols': [
       'release_bot', 'mac_strip', 'minimal_symbols',
     ],
@@ -3600,11 +3587,7 @@
       'release_trybot', 'fuchsia', 'cast_receiver_size_optimized',
     ],
 
-    'release_trybot_fuchsia_cfv2_script_chrome': [
-      'release_trybot', 'fuchsia', 'fuchsia_cfv2_script', 'fuchsia_chrome',
-    ],
-
-    'release_trybot_fuchsia_workstation': [
+    'release_trybot_fuchsia_chrome': [
       'release_trybot', 'fuchsia', 'fuchsia_chrome'
     ],
 
@@ -4188,10 +4171,6 @@
       'gn_args': 'target_os="fuchsia"',
     },
 
-    'fuchsia_cfv2_script': {
-      'gn_args': 'use_cfv2_script=true',
-    },
-
     'fuchsia_chrome': {
       'gn_args': 'fuchsia_browser_type="chrome"',
     },
@@ -4204,6 +4183,11 @@
       'gn_args': 'fuchsia_additional_boot_images=["//third_party/fuchsia-sdk/images-internal/astro-release/","//third_party/fuchsia-sdk/images-internal/sherlock-release/"]',
     },
 
+    # TODO(crbug/1336775): Remove when --ram-size-mb is added in new scripts
+    'fuchsia_legacy_script': {
+      'gn_args': 'use_v2_script_default=false',
+    },
+
     'full_symbols': {
       'gn_args': 'symbol_level=2',
     },
diff --git a/tools/mb/mb_config_expectations/chromium.fuchsia.fyi.json b/tools/mb/mb_config_expectations/chromium.fuchsia.fyi.json
index 555f801..25db0fa 100644
--- a/tools/mb/mb_config_expectations/chromium.fuchsia.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.fuchsia.fyi.json
@@ -48,7 +48,6 @@
       "is_component_build": false,
       "is_debug": false,
       "target_os": "fuchsia",
-      "use_cfv2_script": true,
       "use_remoteexec": true
     }
   },
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json
index aa5ac8e..00f0584 100644
--- a/tools/mb/mb_config_expectations/chromium.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -780,7 +780,8 @@
       "symbol_level": 0,
       "target_os": "fuchsia",
       "use_clang_coverage": true,
-      "use_remoteexec": true
+      "use_remoteexec": true,
+      "use_v2_script_default": false
     }
   },
   "fuchsia-fyi-arm64-cfv2-script": {
@@ -791,7 +792,6 @@
       "target_cpu": "arm64",
       "target_os": "fuchsia",
       "test_host_cpu": "arm64",
-      "use_cfv2_script": true,
       "use_remoteexec": true
     }
   },
@@ -801,7 +801,6 @@
       "is_component_build": false,
       "is_debug": false,
       "target_os": "fuchsia",
-      "use_cfv2_script": true,
       "use_remoteexec": true
     }
   },
@@ -1408,19 +1407,6 @@
       "use_remoteexec": true
     }
   },
-  "mac-fieldtrial-rel": {
-    "gn_args": {
-      "dcheck_always_on": false,
-      "enable_nacl": false,
-      "ffmpeg_branding": "Chrome",
-      "is_component_build": false,
-      "is_debug": false,
-      "proprietary_codecs": true,
-      "symbol_level": 1,
-      "target_cpu": "arm64",
-      "use_remoteexec": true
-    }
-  },
   "mac-hermetic-upgrade-rel": {
     "gn_args": {
       "dcheck_always_on": false,
diff --git a/tools/mb/mb_config_expectations/chromium.perf.fyi.json b/tools/mb/mb_config_expectations/chromium.perf.fyi.json
index e4681fa..aa2e6db 100644
--- a/tools/mb/mb_config_expectations/chromium.perf.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.perf.fyi.json
@@ -57,7 +57,6 @@
       "target_cpu": "arm64",
       "target_os": "fuchsia",
       "test_isolate_uses_emulator": false,
-      "use_cfv2_script": true,
       "use_goma": true
     }
   },
@@ -71,7 +70,6 @@
       "target_cpu": "x64",
       "target_os": "fuchsia",
       "test_isolate_uses_emulator": false,
-      "use_cfv2_script": true,
       "use_goma": true
     }
   }
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.fuchsia.json b/tools/mb/mb_config_expectations/tryserver.chromium.fuchsia.json
index ea57eff9..d16f57b5 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.fuchsia.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.fuchsia.json
@@ -116,7 +116,6 @@
       "is_debug": false,
       "symbol_level": 0,
       "target_os": "fuchsia",
-      "use_cfv2_script": true,
       "use_goma": true
     }
   },
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
index 8f684a8..a6fba0b 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
@@ -471,7 +471,7 @@
       "use_goma": true
     }
   },
-  "mac-fieldtrial-rel": {
+  "mac-fieldtrial-tester": {
     "gn_args": {
       "dcheck_always_on": false,
       "enable_nacl": false,
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.perf.json b/tools/mb/mb_config_expectations/tryserver.chromium.perf.json
index 090bb51..e07f102 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.perf.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.perf.json
@@ -86,7 +86,6 @@
       "target_cpu": "arm64",
       "target_os": "fuchsia",
       "test_isolate_uses_emulator": false,
-      "use_cfv2_script": true,
       "use_goma": true
     }
   },
@@ -100,7 +99,6 @@
       "target_cpu": "x64",
       "target_os": "fuchsia",
       "test_isolate_uses_emulator": false,
-      "use_cfv2_script": true,
       "use_goma": true
     }
   },
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index c1a4d39..633869a 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -19503,6 +19503,7 @@
   <int value="8" label="No matching source filter data"/>
   <int value="9" label="Not registered"/>
   <int value="10" label="Prohibited by browser policy"/>
+  <int value="11" label="Report window has passed"/>
 </enum>
 
 <enum name="ConversionDataHandleStatus">
@@ -19565,6 +19566,7 @@
   <int value="12" label="No matching configurations"/>
   <int value="13" label="Excessive reports"/>
   <int value="14" label="Falsely attributed source"/>
+  <int value="15" label="Report window has passed"/>
 </enum>
 
 <enum name="ConversionStorageSourceStatus">
@@ -76509,6 +76511,7 @@
   <int value="1507" label="Keyboard And Text Input Page"/>
   <int value="1508" label="Cursor And Touchpad Page"/>
   <int value="1509" label="Audio And Captions Page"/>
+  <int value="1510" label="Select-to-speak Subpage"/>
   <int value="1700" label="About Chrome OS Details"/>
   <int value="1701" label="Detailed Build Info"/>
   <int value="1800" label="Kerberos Accounts V2"/>
@@ -107199,6 +107202,7 @@
   <int value="2014923527" label="/storage/externalStoragePreferences"/>
   <int value="2030415176" label="/files"/>
   <int value="2121014241" label="/audioAndCaptions"/>
+  <int value="2121014242" label="/textToSpeech/selectToSpeak"/>
   <int value="2136345292" label="/privacy"/>
   <int value="2236117233" label="/cursorAndTouchpad"/>
   <int value="2292642563" label="/androidAppsDetails"/>
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml
index e7d15cd..46be5ad 100644
--- a/tools/metrics/histograms/metadata/android/histograms.xml
+++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -3647,13 +3647,6 @@
   </token>
 </histogram>
 
-<histogram name="Android.TabPersistentStore.MetadataFileSize" units="units"
-    expires_after="M85">
-  <owner>wnwen@chromium.org</owner>
-  <owner>twellington@chromium.org</owner>
-  <summary>The number of bytes written for the tab metadata file.</summary>
-</histogram>
-
 <histogram name="Android.TabStrip.TimeToSwitchTab" units="ms"
     expires_after="2023-04-16">
   <owner>gauravjj@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/arc/histograms.xml b/tools/metrics/histograms/metadata/arc/histograms.xml
index 34b53dd1..690019f 100644
--- a/tools/metrics/histograms/metadata/arc/histograms.xml
+++ b/tools/metrics/histograms/metadata/arc/histograms.xml
@@ -1290,7 +1290,7 @@
 </histogram>
 
 <histogram name="Arc.InputOverlay.MappingHintState" enum="BooleanEnabled"
-    expires_after="2022-11-12">
+    expires_after="2023-04-15">
   <owner>cuicuiruan@google.com</owner>
   <owner>arc-gaming@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/event/histograms.xml b/tools/metrics/histograms/metadata/event/histograms.xml
index 793e7a0..2ea3ac7 100644
--- a/tools/metrics/histograms/metadata/event/histograms.xml
+++ b/tools/metrics/histograms/metadata/event/histograms.xml
@@ -1727,7 +1727,7 @@
 </histogram>
 
 <histogram name="Event.Touch.TimedOutOnDesktopSite" enum="BooleanTimedOut"
-    expires_after="2021-08-15">
+    expires_after="2023-10-31">
   <owner>flackr@chromium.org</owner>
   <owner>input-dev@chromium.org</owner>
   <summary>
@@ -1735,12 +1735,15 @@
     renderer for any event in a contiguous touch sequence exceeds the
     desktop-specific timeout threshold.
 
+    Warning: This histogram has incomplete data. It expired on 2021-08-15 and
+    then got re-enabled on M110.
+
     Team: input-dev@chromium.org.
   </summary>
 </histogram>
 
 <histogram name="Event.Touch.TimedOutOnMobileSite" enum="BooleanTimedOut"
-    expires_after="2021-08-15">
+    expires_after="2023-10-31">
   <owner>flackr@chromium.org</owner>
   <owner>input-dev@chromium.org</owner>
   <summary>
@@ -1748,6 +1751,9 @@
     any event in a contiguous touch sequence exceeds the mobile-specific timeout
     threshold.
 
+    Warning: This histogram has incomplete data. It expired on 2021-08-15 and
+    then got re-enabled on M110.
+
     Team: input-dev@chromium.org.
   </summary>
 </histogram>
diff --git a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
index a99ccc4..ead4cd2d 100644
--- a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
+++ b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
@@ -10080,8 +10080,6 @@
              (small)."/>
   <suffix name="UncompressedChromeArchive"
       label="uncompressed archive: chrome.7z holding install dir (big)."/>
-  <affected-histogram name="Setup.Install.LzmaUnPackNTSTATUS"/>
-  <affected-histogram name="Setup.Install.LzmaUnPackResult"/>
   <affected-histogram name="Setup.Install.LzmaUnPackStatus"/>
 </histogram_suffixes>
 
diff --git a/tools/metrics/histograms/metadata/input/histograms.xml b/tools/metrics/histograms/metadata/input/histograms.xml
index 2d0079b..10ec50fa 100644
--- a/tools/metrics/histograms/metadata/input/histograms.xml
+++ b/tools/metrics/histograms/metadata/input/histograms.xml
@@ -922,15 +922,6 @@
   <summary>Time taken by the engine to handle a key event.</summary>
 </histogram>
 
-<histogram name="InputMethod.MatchesSystemLanguage" enum="BooleanMatched"
-    expires_after="2019-01-30">
-  <owner>aurimas@chromium.org</owner>
-  <summary>
-    Whether the currently selected keyboard language matches the system
-    language. Recorded once with every cold start of Chrome for Android.
-  </summary>
-</histogram>
-
 <histogram name="InputMethod.ModeChangeKeyAction" enum="ModeChangeKeyAction"
     expires_after="2019-12-31">
   <owner>shend@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/login/histograms.xml b/tools/metrics/histograms/metadata/login/histograms.xml
index 9bf77cd3..3a96317 100644
--- a/tools/metrics/histograms/metadata/login/histograms.xml
+++ b/tools/metrics/histograms/metadata/login/histograms.xml
@@ -39,6 +39,9 @@
 
 <histogram name="Login.ArcBugReportBackupTime" units="ms"
     expires_after="2022-12-25">
+  <obsolete>
+    Removed in M110.
+  </obsolete>
   <owner>mhasank@google.com</owner>
   <owner>arc-core@google.com</owner>
   <summary>
@@ -317,9 +320,13 @@
 </histogram>
 
 <histogram name="Login.StateKeyGenerationStatus"
-    enum="LoginStateKeyGenerationStatus" expires_after="M77">
-  <owner>mnissler@chromium.org</owner>
-  <summary>Result of a state key generation operation.</summary>
+    enum="LoginStateKeyGenerationStatus" expires_after="2023-11-01">
+  <owner>sergiyb@chromium.org</owner>
+  <owner>chromeos-commercial-remote-management@chromium.org</owner>
+  <summary>
+    Result of a state key generation operation. Warning: this histogram was
+    expired from 2019-10-22 (M78) to 2023-02-07 (M110); data may be missing.
+  </summary>
 </histogram>
 
 <histogram name="Login.SuccessReason" enum="LoginSuccessReason"
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml
index a5d97b2..fbd8dbc6 100644
--- a/tools/metrics/histograms/metadata/others/histograms.xml
+++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -3367,7 +3367,7 @@
   </summary>
 </histogram>
 
-<histogram name="Conversions.AggregatableReport.CreateReportStatus2"
+<histogram name="Conversions.AggregatableReport.CreateReportStatus3"
     enum="ConversionCreateAggregatableReportStatus" expires_after="M117">
   <owner>linnan@chromium.org</owner>
   <owner>johnidel@chromium.org</owner>
@@ -3633,7 +3633,7 @@
   </summary>
 </histogram>
 
-<histogram name="Conversions.CreateReportStatus5"
+<histogram name="Conversions.CreateReportStatus6"
     enum="ConversionStorageCreateReportStatus" expires_after="M117">
   <owner>apaseltiner@chromium.org</owner>
   <owner>johnidel@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/power/histograms.xml b/tools/metrics/histograms/metadata/power/histograms.xml
index a6521662..b2c2f743 100644
--- a/tools/metrics/histograms/metadata/power/histograms.xml
+++ b/tools/metrics/histograms/metadata/power/histograms.xml
@@ -775,6 +775,44 @@
   </summary>
 </histogram>
 
+<histogram name="Power.BatteryDischargeGranularity" units="MWh"
+    expires_after="2023-03-12">
+  <owner>pmonette@chromium.org</owner>
+  <owner>fdoray@chromium.org</owner>
+  <summary>
+    The granularity of the current battery discharge rate value as reported by
+    the operating system, if available. The battery discharge value can become
+    more precise as the charge level of the battery decreases. This histogram
+    reflects this precision.
+
+    This is reported at the end of every valid 1 minute interval. An invalid
+    interval is one that deviate too much from 1 minute, which can be caused by
+    the computer going to sleep, or the OS sending multiple notifications in a
+    row.
+
+    Reported only on Windows, when a single battery is installed and the
+    operating system says that the unit is mWh.
+  </summary>
+</histogram>
+
+<histogram name="Power.BatteryDischargeGranularityAvailable"
+    enum="BooleanAvailable" expires_after="2023-03-12">
+  <owner>pmonette@chromium.org</owner>
+  <owner>fdoray@chromium.org</owner>
+  <summary>
+    The availability of the battery discharge granularity. If true,
+    Power.BatteryDischargeGranularity is reported for this client.
+
+    This is reported at the end of every valid 1 minute interval. An invalid
+    interval is one that deviate too much from 1 minute, which can be caused by
+    the computer going to sleep, or the OS sending multiple notifications in a
+    row.
+
+    Reported only on Windows, when a single battery is installed and the
+    operating system says that the unit is mWh.
+  </summary>
+</histogram>
+
 <histogram name="Power.BatteryDischargeMode2{UsageScenario}"
     enum="BatteryDischargeMode" expires_after="2023-03-31">
   <owner>etiennep@chromium.org</owner>
@@ -1932,6 +1970,25 @@
   </summary>
 </histogram>
 
+<histogram name="Power.MaxBatteryDischargeGranularity" units="MWh"
+    expires_after="2023-03-12">
+  <owner>pmonette@chromium.org</owner>
+  <owner>fdoray@chromium.org</owner>
+  <summary>
+    The maximum granularity of the battery discharge rate as reported by the
+    operating system, if available. This value is independant of the current
+    battery capacity.
+
+    This is reported at the end of every valid 1 minute interval. An invalid
+    interval is one that deviate too much from 1 minute, which can be caused by
+    the computer going to sleep, or the OS sending multiple notifications in a
+    row.
+
+    Reported only on Windows, when a single battery is installed and the
+    operating system says that the unit is mWh.
+  </summary>
+</histogram>
+
 <histogram name="Power.MetricsDailyEventInterval" enum="DailyEventIntervalType"
     expires_after="M100">
   <owner>puthik@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 6a322b8..252f4cf 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": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "win": {
-            "hash": "c720bb4679e1d5bfbdb6335d848e9c8b5dd83174",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/8c09706981a46ece978105c3b8443cda1b08f30e/trace_processor_shell.exe"
+            "hash": "60f44f42c819e68efd57eb4d5a7437fe0ea59a07",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/3692281b7c39cb1184f1b21447374ff4d0c09335/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893",
             "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "mac": {
-            "hash": "36e7f3297e5494cabc2124f735f4bdf65b9edaa9",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/8c09706981a46ece978105c3b8443cda1b08f30e/trace_processor_shell"
+            "hash": "cb6defa22bc1b399bddd07365eacb590fff78bec",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/3692281b7c39cb1184f1b21447374ff4d0c09335/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "92318bea34f5c9beec69d2d826a9a92ec9d3cdcd",
             "full_remote_path": "perfetto-luci-artifacts/v30.0/mac-arm64/trace_processor_shell"
         },
         "linux": {
-            "hash": "cb8eb61c26649f9dcaa16c7de61ac9d6083bd50b",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/8c09706981a46ece978105c3b8443cda1b08f30e/trace_processor_shell"
+            "hash": "873d11782d877e32c4939560a3696999485b541a",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/3692281b7c39cb1184f1b21447374ff4d0c09335/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/ui/accessibility/accessibility_features.cc b/ui/accessibility/accessibility_features.cc
index 0c12cbaa..c63b031 100644
--- a/ui/accessibility/accessibility_features.cc
+++ b/ui/accessibility/accessibility_features.cc
@@ -191,14 +191,6 @@
       ::features::kAccessibilityOSSettingsVisibility);
 }
 
-BASE_FEATURE(kAccessibilityService,
-             "AccessibilityService",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
-bool IsAccessibilityServiceEnabled() {
-  return base::FeatureList::IsEnabled(::features::kAccessibilityService);
-}
-
 BASE_FEATURE(kExperimentalAccessibilityColorEnhancementSettings,
              "ExperimentalAccessibilityColorEnhancementSettings",
              base::FEATURE_DISABLED_BY_DEFAULT);
@@ -347,6 +339,15 @@
 bool IsPdfOcrEnabled() {
   return base::FeatureList::IsEnabled(::features::kPdfOcr);
 }
+
+BASE_FEATURE(kAccessibilityService,
+             "AccessibilityService",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
+bool IsAccessibilityServiceEnabled() {
+  return base::FeatureList::IsEnabled(::features::kAccessibilityService);
+}
+
 #endif  // !BUILDFLAG(IS_ANDROID)
 
 }  // namespace features
diff --git a/ui/accessibility/accessibility_features.h b/ui/accessibility/accessibility_features.h
index d1e74015..5663c11 100644
--- a/ui/accessibility/accessibility_features.h
+++ b/ui/accessibility/accessibility_features.h
@@ -143,12 +143,6 @@
 // Returns true if improved Accessibility OS Settings visibility is enabled.
 AX_BASE_EXPORT bool IsAccessibilityOSSettingsVisibilityEnabled();
 
-// Enables the experimental Accessibility Service.
-AX_BASE_EXPORT BASE_DECLARE_FEATURE(kAccessibilityService);
-
-// Returns true if the Accessibility Service enabled.
-AX_BASE_EXPORT bool IsAccessibilityServiceEnabled();
-
 // Enables the experimental color enhancements settings.
 AX_BASE_EXPORT BASE_DECLARE_FEATURE(
     kExperimentalAccessibilityColorEnhancementSettings);
@@ -277,6 +271,13 @@
 // and the resulting text, together with its layout information, will be added
 // to the accessibility tree.
 AX_BASE_EXPORT bool IsPdfOcrEnabled();
+
+// Enables the experimental Accessibility Service.
+AX_BASE_EXPORT BASE_DECLARE_FEATURE(kAccessibilityService);
+
+// Returns true if the Accessibility Service enabled.
+AX_BASE_EXPORT bool IsAccessibilityServiceEnabled();
+
 #endif  // !BUILDFLAG(IS_ANDROID)
 
 }  // namespace features
diff --git a/ui/accessibility/platform/automation/DIR_METADATA b/ui/accessibility/platform/automation/DIR_METADATA
new file mode 100644
index 0000000..2e3458c
--- /dev/null
+++ b/ui/accessibility/platform/automation/DIR_METADATA
@@ -0,0 +1,10 @@
+monorail {
+  component: "OS>Accessibility"
+}
+team_email: "chromium-accessibility@chromium.org"
+buganizer {
+  component_id: 1279373
+}
+buganizer_public {
+  component_id: 1279066
+}
diff --git a/ui/aura/window_event_dispatcher.cc b/ui/aura/window_event_dispatcher.cc
index ba3ae39..0651c7cb 100644
--- a/ui/aura/window_event_dispatcher.cc
+++ b/ui/aura/window_event_dispatcher.cc
@@ -10,7 +10,7 @@
 
 #include "base/bind.h"
 #include "base/check_op.h"
-#include "base/notreached.h"
+#include "base/debug/dump_without_crashing.h"
 #include "base/observer_list.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
@@ -591,6 +591,21 @@
   if (details.dispatcher_destroyed || details.target_destroyed)
     return details;
 
+  // TODO(crbug/1381787): Remove.
+  // Suspect there is a code path that "target_destroyed" is not reported.
+  if (target_window_tracker.windows().empty()) {
+    // Dump once per chrome run.
+    static bool has_dumped = false;
+    if (!has_dumped) {
+      LOG(ERROR) << "Target destroyed not reported"
+                 << ", event=" << event->ToString();
+      has_dumped = base::debug::DumpWithoutCrashing();
+    }
+
+    details.target_destroyed = true;
+    return details;
+  }
+
   old_dispatch_target_ = event_dispatch_target_;
   event_dispatch_target_ = target_window;
   return DispatchDetails();
diff --git a/ui/base/ime/ash/mock_ime_engine_handler.cc b/ui/base/ime/ash/mock_ime_engine_handler.cc
index 909005df..e0ac2a31d 100644
--- a/ui/base/ime/ash/mock_ime_engine_handler.cc
+++ b/ui/base/ime/ash/mock_ime_engine_handler.cc
@@ -80,10 +80,6 @@
   last_set_surrounding_anchor_pos_ = anchor_pos;
 }
 
-void MockIMEEngineHandler::SetMirroringEnabled(bool mirroring_enabled) {}
-
-void MockIMEEngineHandler::SetCastingEnabled(bool casting_enabled) {}
-
 bool MockIMEEngineHandler::IsReadyForTesting() {
   return true;
 }
diff --git a/ui/base/ime/ash/mock_ime_engine_handler.h b/ui/base/ime/ash/mock_ime_engine_handler.h
index 9f95c3df..e111fff0 100644
--- a/ui/base/ime/ash/mock_ime_engine_handler.h
+++ b/ui/base/ime/ash/mock_ime_engine_handler.h
@@ -43,8 +43,6 @@
                           uint32_t cursor_pos,
                           uint32_t anchor_pos,
                           uint32_t offset_pos) override;
-  void SetMirroringEnabled(bool mirroring_enabled) override;
-  void SetCastingEnabled(bool casting_enabled) override;
   bool IsReadyForTesting() override;
 
   const std::string& GetActiveComponentId() const;
diff --git a/ui/base/ime/ash/text_input_method.h b/ui/base/ime/ash/text_input_method.h
index 032d937..630c71ae 100644
--- a/ui/base/ime/ash/text_input_method.h
+++ b/ui/base/ime/ash/text_input_method.h
@@ -160,10 +160,6 @@
   virtual void AssistiveWindowChanged(
       const ash::ime::AssistiveWindow& window) = 0;
 
-  // Sets the mirroring/casting enable states.
-  virtual void SetMirroringEnabled(bool mirroring_enabled) = 0;
-  virtual void SetCastingEnabled(bool casting_enabled) = 0;
-
   // Returns whether the IME is ready to accept key events for testing.
   virtual bool IsReadyForTesting() = 0;
 };
diff --git a/ui/file_manager/file_manager/background/js/BUILD.gn b/ui/file_manager/file_manager/background/js/BUILD.gn
index cc09c3c..fb561d5 100644
--- a/ui/file_manager/file_manager/background/js/BUILD.gn
+++ b/ui/file_manager/file_manager/background/js/BUILD.gn
@@ -146,7 +146,7 @@
 js_unittest("crostini_unittest") {
   deps = [
     ":mock_crostini",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:mock_entry",
     "//ui/file_manager/file_manager/common/js:volume_manager_types",
     "//ui/file_manager/file_manager/externs:entry_location",
@@ -187,7 +187,7 @@
   deps = [
     ":drive_sync_handler",
     ":mock_progress_center",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:mock_chrome",
     "//ui/file_manager/file_manager/common/js:progress_center_common",
     "//ui/file_manager/file_manager/common/js:url_constants",
@@ -221,7 +221,7 @@
     ":file_operation_util",
     ":mock_file_operation_manager",
     ":mock_progress_center",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -253,7 +253,7 @@
     ":file_operation_manager",
     ":file_operation_util",
     ":volume_manager_factory",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:mock_chrome",
     "//ui/file_manager/file_manager/common/js:mock_entry",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
@@ -386,7 +386,7 @@
   deps = [
     ":mock_volume_manager",
     ":trash",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:mock_entry",
     "//ui/file_manager/file_manager/common/js:trash",
     "//ui/file_manager/file_manager/common/js:util",
@@ -433,7 +433,7 @@
     ":volume_manager_factory",
     ":volume_manager_impl",
     ":volume_manager_util",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:mock_chrome",
     "//ui/file_manager/file_manager/common/js:mock_entry",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
diff --git a/ui/file_manager/file_manager/background/js/crostini_unittest.js b/ui/file_manager/file_manager/background/js/crostini_unittest.js
index fc0c0283..6aae62b 100644
--- a/ui/file_manager/file_manager/background/js/crostini_unittest.js
+++ b/ui/file_manager/file_manager/background/js/crostini_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {installMockChrome} from '../../common/js/mock_chrome.js';
 import {MockDirectoryEntry, MockEntry, MockFileSystem} from '../../common/js/mock_entry.js';
diff --git a/ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.js b/ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.js
index c2b4e63..3110c2b0 100644
--- a/ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.js
+++ b/ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.js
@@ -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 {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {installMockChrome} from '../../common/js/mock_chrome.js';
 import {ProgressItemState} from '../../common/js/progress_center_common.js';
diff --git a/ui/file_manager/file_manager/background/js/file_operation_handler_unittest.js b/ui/file_manager/file_manager/background/js/file_operation_handler_unittest.js
index 15b50c54..2e74f2e0 100644
--- a/ui/file_manager/file_manager/background/js/file_operation_handler_unittest.js
+++ b/ui/file_manager/file_manager/background/js/file_operation_handler_unittest.js
@@ -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 {assertEquals, assertGT, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertGT, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {FileOperationHandler} from './file_operation_handler.js';
 import {fileOperationUtil} from './file_operation_util.js';
diff --git a/ui/file_manager/file_manager/background/js/file_operation_manager_unittest.js b/ui/file_manager/file_manager/background/js/file_operation_manager_unittest.js
index eef41ef8..d4ffaeb 100644
--- a/ui/file_manager/file_manager/background/js/file_operation_manager_unittest.js
+++ b/ui/file_manager/file_manager/background/js/file_operation_manager_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {assertArrayEquals, assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertArrayEquals, assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockDirectoryEntry, MockFileEntry, MockFileSystem} from '../../common/js/mock_entry.js';
 import {reportPromise} from '../../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/background/js/trash_unittest.js b/ui/file_manager/file_manager/background/js/trash_unittest.js
index 41e1cc3..d2dfd84 100644
--- a/ui/file_manager/file_manager/background/js/trash_unittest.js
+++ b/ui/file_manager/file_manager/background/js/trash_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {assert} from 'chrome://resources/js/assert.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockDirectoryEntry, MockFileEntry, MockFileSystem} from '../../common/js/mock_entry.js';
 import {TrashDirs} from '../../common/js/trash.js';
diff --git a/ui/file_manager/file_manager/background/js/volume_manager_unittest.js b/ui/file_manager/file_manager/background/js/volume_manager_unittest.js
index 72d0346..731fdb4 100644
--- a/ui/file_manager/file_manager/background/js/volume_manager_unittest.js
+++ b/ui/file_manager/file_manager/background/js/volume_manager_unittest.js
@@ -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 {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {installMockChrome, MockCommandLinePrivate} from '../../common/js/mock_chrome.js';
 import {MockDirectoryEntry, MockFileEntry, MockFileSystem} from '../../common/js/mock_entry.js';
diff --git a/ui/file_manager/file_manager/common/js/BUILD.gn b/ui/file_manager/file_manager/common/js/BUILD.gn
index f5ba78c..cf8da39 100644
--- a/ui/file_manager/file_manager/common/js/BUILD.gn
+++ b/ui/file_manager/file_manager/common/js/BUILD.gn
@@ -132,7 +132,7 @@
 js_unittest("array_data_model_unittest") {
   deps = [
     ":array_data_model",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -154,7 +154,7 @@
   deps = [
     ":files_app_entry_types",
     ":mock_entry",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
     "//ui/file_manager/file_manager/externs:volume_info",
     "//ui/webui/resources/js:assert",
@@ -195,7 +195,7 @@
   deps = [
     ":file_type",
     ":mock_entry",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:volume_manager_types",
   ]
 }
@@ -220,7 +220,7 @@
 js_unittest("filtered_volume_manager_unittest") {
   deps = [
     ":filtered_volume_manager",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/background/js:mock_volume_manager",
     "//ui/file_manager/file_manager/common/js:volume_manager_types",
     "//ui/webui/resources/js:load_time_data.m",
@@ -233,7 +233,7 @@
 js_unittest("lru_cache_unittest") {
   deps = [
     ":lru_cache",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -294,7 +294,7 @@
 js_unittest("storage_adapter_unittest") {
   deps = [
     ":storage_adapter",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -321,7 +321,7 @@
 }
 
 js_library("unittest_util") {
-  deps = [ "//chrome/test/data/webui:chai_assert" ]
+  deps = [ "//chrome/test/data/webui/chromeos:chai_assert" ]
 }
 
 js_library("url_constants") {
@@ -353,7 +353,7 @@
     ":files_app_entry_types",
     ":mock_entry",
     ":util",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/background/js:mock_volume_manager",
     "//ui/file_manager/file_manager/common/js:volume_manager_types",
   ]
diff --git a/ui/file_manager/file_manager/common/js/array_data_model_unittest.js b/ui/file_manager/file_manager/common/js/array_data_model_unittest.js
index 36e1b99..3b2676d 100644
--- a/ui/file_manager/file_manager/common/js/array_data_model_unittest.js
+++ b/ui/file_manager/file_manager/common/js/array_data_model_unittest.js
@@ -5,7 +5,7 @@
 // clang-format off
 import {ArrayDataModel} from './array_data_model.js';
 
-import {assertArrayEquals, assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertArrayEquals, assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 // clang-format on
 
 export function testSlice() {
diff --git a/ui/file_manager/file_manager/common/js/async_util_unittest.js b/ui/file_manager/file_manager/common/js/async_util_unittest.js
index 5fdc81b..080b9a1 100644
--- a/ui/file_manager/file_manager/common/js/async_util_unittest.js
+++ b/ui/file_manager/file_manager/common/js/async_util_unittest.js
@@ -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 {assertArrayEquals, assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertArrayEquals, assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {AsyncQueue} from './async_util.js';
 import {waitUntil} from './test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/common/js/file_type_unittest.js b/ui/file_manager/file_manager/common/js/file_type_unittest.js
index ad0f82b..edef452 100644
--- a/ui/file_manager/file_manager/common/js/file_type_unittest.js
+++ b/ui/file_manager/file_manager/common/js/file_type_unittest.js
@@ -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 {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {FileType} from './file_type.js';
 import {MockFileSystem} from './mock_entry.js';
diff --git a/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js b/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js
index c40553e..5dc81e2 100644
--- a/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js
+++ b/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {assert} from 'chrome://resources/js/assert.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {VolumeInfo} from '../../externs/volume_info.js';
 
diff --git a/ui/file_manager/file_manager/common/js/filtered_volume_manager_unittest.js b/ui/file_manager/file_manager/common/js/filtered_volume_manager_unittest.js
index 9da8e76..15a69c0f 100644
--- a/ui/file_manager/file_manager/common/js/filtered_volume_manager_unittest.js
+++ b/ui/file_manager/file_manager/common/js/filtered_volume_manager_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {assert} from 'chrome://resources/js/assert.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
 import {VolumeInfo} from '../../externs/volume_info.js';
diff --git a/ui/file_manager/file_manager/common/js/lru_cache_unittest.js b/ui/file_manager/file_manager/common/js/lru_cache_unittest.js
index 3e8c61b..685120ce 100644
--- a/ui/file_manager/file_manager/common/js/lru_cache_unittest.js
+++ b/ui/file_manager/file_manager/common/js/lru_cache_unittest.js
@@ -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 {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {LRUCache} from './lru_cache.js';
 
diff --git a/ui/file_manager/file_manager/common/js/recent_date_bucket_unittest.js b/ui/file_manager/file_manager/common/js/recent_date_bucket_unittest.js
index 8893302..6d58c27 100644
--- a/ui/file_manager/file_manager/common/js/recent_date_bucket_unittest.js
+++ b/ui/file_manager/file_manager/common/js/recent_date_bucket_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {getRecentDateBucket} from './recent_date_bucket.js';
 
diff --git a/ui/file_manager/file_manager/common/js/storage_adapter_unittest.js b/ui/file_manager/file_manager/common/js/storage_adapter_unittest.js
index fe3d63a..6eae21a 100644
--- a/ui/file_manager/file_manager/common/js/storage_adapter_unittest.js
+++ b/ui/file_manager/file_manager/common/js/storage_adapter_unittest.js
@@ -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 {assertDeepEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertDeepEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {storage} from './storage_adapter.js';
 import {waitUntil} from './test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/common/js/unittest_util.js b/ui/file_manager/file_manager/common/js/unittest_util.js
index ce65375c..2348f9e 100644
--- a/ui/file_manager/file_manager/common/js/unittest_util.js
+++ b/ui/file_manager/file_manager/common/js/unittest_util.js
@@ -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 {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 /**
  * Asserts that two lists contain the same set of Entries.  Entries are deemed
diff --git a/ui/file_manager/file_manager/common/js/util_unittest.js b/ui/file_manager/file_manager/common/js/util_unittest.js
index b3edfaa1..7b62b9f 100644
--- a/ui/file_manager/file_manager/common/js/util_unittest.js
+++ b/ui/file_manager/file_manager/common/js/util_unittest.js
@@ -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 {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
 
diff --git a/ui/file_manager/file_manager/common/js/volume_manager_types_unittest.js b/ui/file_manager/file_manager/common/js/volume_manager_types_unittest.js
index fd19ac8..f69c9824 100644
--- a/ui/file_manager/file_manager/common/js/volume_manager_types_unittest.js
+++ b/ui/file_manager/file_manager/common/js/volume_manager_types_unittest.js
@@ -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 {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockFileEntry, MockFileSystem} from './mock_entry.js';
 import {VolumeManagerCommon} from './volume_manager_types.js';
diff --git a/ui/file_manager/file_manager/containers/nudge_container_unittest.ts b/ui/file_manager/file_manager/containers/nudge_container_unittest.ts
index 9450ba9..b2b7ed2 100644
--- a/ui/file_manager/file_manager/containers/nudge_container_unittest.ts
+++ b/ui/file_manager/file_manager/containers/nudge_container_unittest.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 {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {waitUntil} from '../common/js/test_error_reporting.js';
 import {XfNudge} from '../widgets/xf_nudge.js';
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css b/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css
index a564c7e..9de320c9 100644
--- a/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css
+++ b/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css
@@ -378,23 +378,23 @@
   flex: none;
   justify-content: center;
   margin: 0;
-  margin-inline-end: calc(16px - 6px);
   position: relative;
-  width: 32px;
+  width: 24px;
   z-index: 500;  /* Must be below the contextmenu (600). */
 }
 
 div.splitter .splitter-button {
-  --hover-bg-color: var(--cros-ripple-color);
-  --ink-color: var(--cros-ripple-color);
-  --ripple-opacity: 100%;
+  --hover-bg-color: var(--cros-sys-hover_on_quiet);
+  --ink-color: transparent;
   border: none;
-  border-radius: 50%;
+  border-radius: 8px;
   cursor: col-resize;
-  height: 32px;
-  min-width: 32px;
+  height: 64px;
+  left: 12px;
+  min-width: 16px;
   padding: 0;
-  width: 32px;
+  position: relative;
+  width: 16px;
 }
 
 html.pointer-active div.splitter:not(.splitter-active):hover {
@@ -411,22 +411,15 @@
 }
 
 div.splitter.splitter-active .splitter-button:active:not(:hover) {
-  background-color: var(--cros-ripple-color);
+  background-color: var(--cros-sys-hover_on_quiet);
 }
 
 div.splitter.splitter-active .splitter-button:not(:active) {
-  background-color: var(--cros-icon-button-pressed-color);
+  background-color: var(--cros-sys-hover_on_quiet);
 }
 
 div.splitter .splitter-button .icon {
-  -webkit-mask-image: url(../images/common/dragger.svg);
-  -webkit-mask-position: center;
-  -webkit-mask-repeat: no-repeat;
-  /* TODO(crbug.com/1268206): the icon is not in disabled state */
-  background-color: var(--cros-icon-color-disabled);
-  height: 20px;
-  padding: 6px;
-  width: 20px;
+  display: none;
 }
 
 html.pointer-active div.splitter:not(.splitter-active) .splitter-button:not(:active):hover .icon {
diff --git a/ui/file_manager/file_manager/foreground/elements/BUILD.gn b/ui/file_manager/file_manager/foreground/elements/BUILD.gn
index 6748ec29..a15dc445 100644
--- a/ui/file_manager/file_manager/foreground/elements/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/elements/BUILD.gn
@@ -101,7 +101,7 @@
 js_unittest("files_password_dialog_unittest") {
   deps = [
     ":files_password_dialog",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
     "//ui/webui/resources/js:assert",
   ]
@@ -157,7 +157,7 @@
 js_unittest("files_tooltip_unittest") {
   deps = [
     ":files_tooltip",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
   ]
 }
@@ -169,7 +169,7 @@
 }
 
 js_unittest("files_toast_unittest") {
-  deps = [ "//chrome/test/data/webui:chai_assert" ]
+  deps = [ "//chrome/test/data/webui/chromeos:chai_assert" ]
   externs_list = [
     "//ui/file_manager/file_manager/externs/polymer_elements/files_toast.js",
   ]
@@ -178,7 +178,7 @@
 js_unittest("files_xf_elements_unittest") {
   deps = [
     ":xf_display_panel",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
     "//ui/file_manager/file_manager/common/js:util",
     "//ui/webui/resources/js:assert",
diff --git a/ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.js b/ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.js
index c30475c..52d9096 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.js
+++ b/ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.js
@@ -7,7 +7,7 @@
 import 'chrome://resources/cr_elements/cr_button/cr_button.js';
 
 import {assert} from 'chrome://resources/js/assert.js';
-import {assertEquals, assertFalse, assertNotReached} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertNotReached} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {waitUntil} from '../../common/js/test_error_reporting.js';
 
diff --git a/ui/file_manager/file_manager/foreground/elements/files_toast_unittest.js b/ui/file_manager/file_manager/foreground/elements/files_toast_unittest.js
index b39700a..1bd8e18 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_toast_unittest.js
+++ b/ui/file_manager/file_manager/foreground/elements/files_toast_unittest.js
@@ -4,7 +4,7 @@
 
 import './files_toast.js';
 
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 export function setUpPage() {
   document.body.innerHTML += '<files-toast></files-toast>';
diff --git a/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.js b/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.js
index 0dc2a14..3c1a08d 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.js
+++ b/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.js
@@ -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 {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {reportPromise} from '../../common/js/test_error_reporting.js';
 
diff --git a/ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.js b/ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.js
index 4c406fbf..8e25b69 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.js
+++ b/ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {assert} from 'chrome://resources/js/assert.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {waitUntil} from '../../common/js/test_error_reporting.js';
 import {str, util} from '../../common/js/util.js';
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn
index dbbc7a4..c4f8900 100644
--- a/ui/file_manager/file_manager/foreground/js/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -225,7 +225,7 @@
     ":banner_controller",
     ":directory_model",
     ":mock_directory_model",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/background/js:mock_volume_manager",
     "//ui/file_manager/file_manager/common/js:dialog_type",
     "//ui/file_manager/file_manager/common/js:mock_chrome",
@@ -243,7 +243,7 @@
   deps = [
     ":banner_controller",
     ":directory_model",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:volume_manager_types",
     "//ui/file_manager/file_manager/externs:banner",
     "//ui/file_manager/file_manager/externs:volume_info",
@@ -272,7 +272,7 @@
     "ui:action_model_ui",
     "ui:files_alert_dialog",
     "ui:list_container",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/background/js:mock_drive_sync_handler",
     "//ui/file_manager/file_manager/background/js:mock_volume_manager",
     "//ui/file_manager/file_manager/common/js:metrics",
@@ -411,7 +411,7 @@
 js_unittest("directory_contents_unittest") {
   deps = [
     ":directory_contents",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:mock_chrome",
     "//ui/file_manager/file_manager/common/js:volume_manager_types",
     "//ui/file_manager/file_manager/externs:entry_location",
@@ -453,7 +453,7 @@
     ":directory_contents",
     ":directory_model",
     "metadata:mock_metadata",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/background/js:mock_file_operation_manager",
     "//ui/file_manager/file_manager/background/js:mock_volume_manager",
     "//ui/file_manager/file_manager/common/js:mock_chrome",
@@ -515,7 +515,7 @@
     ":file_list_model",
     ":mock_directory_model",
     "metadata:mock_metadata",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:files_app_entry_types",
     "//ui/file_manager/file_manager/common/js:mock_chrome",
     "//ui/file_manager/file_manager/common/js:util",
@@ -559,7 +559,7 @@
   deps = [
     ":file_list_model",
     "metadata:metadata_model",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -684,7 +684,7 @@
 js_unittest("file_manager_commands_unittest") {
   deps = [
     ":file_manager_commands",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/background/js:mock_volume_manager",
     "//ui/file_manager/file_manager/common/js:mock_chrome",
     "//ui/file_manager/file_manager/common/js:mock_entry",
@@ -760,7 +760,7 @@
     "ui:file_table",
     "ui:list_container",
     "ui:list_selection_model",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/background/js:mock_volume_manager",
     "//ui/file_manager/file_manager/common/js:dialog_type",
     "//ui/file_manager/file_manager/common/js:mock_chrome",
@@ -792,7 +792,7 @@
     ":directory_model",
     ":file_type_filters_controller",
     "ui:a11y_announce",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:files_app_entry_types",
     "//ui/file_manager/file_manager/common/js:metrics",
     "//ui/file_manager/file_manager/common/js:mock_chrome",
@@ -898,7 +898,7 @@
     ":mock_thumbnail_loader",
     "metadata:metadata_model",
     "metadata:thumbnail_model",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:mock_entry",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
     "//ui/file_manager/file_manager/common/js:volume_manager_types",
@@ -988,7 +988,7 @@
     ":android_app_list_model",
     ":directory_model",
     ":folder_shortcuts_data_model",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:dialog_type",
     "//ui/file_manager/file_manager/common/js:files_app_entry_types",
     "//ui/file_manager/file_manager/common/js:trash",
@@ -1009,7 +1009,7 @@
     ":mock_directory_model",
     ":mock_folder_shortcut_data_model",
     ":navigation_list_model",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/background/js:mock_volume_manager",
     "//ui/file_manager/file_manager/background/js:volume_info_impl",
     "//ui/file_manager/file_manager/common/js:dialog_type",
@@ -1034,7 +1034,7 @@
 js_unittest("path_component_unittest") {
   deps = [
     ":path_component",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/background/js:mock_volume_manager",
     "//ui/file_manager/file_manager/common/js:mock_entry",
     "//ui/file_manager/file_manager/common/js:volume_manager_types",
@@ -1053,7 +1053,7 @@
 js_unittest("providers_model_unittest") {
   deps = [
     ":providers_model",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/background/js:mock_volume_manager",
     "//ui/file_manager/file_manager/background/js:volume_info_impl",
     "//ui/file_manager/file_manager/common/js:mock_chrome",
@@ -1158,7 +1158,7 @@
 js_unittest("spinner_controller_unittest") {
   deps = [
     ":spinner_controller",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
     "//ui/webui/resources/js:assert",
   ]
@@ -1186,7 +1186,7 @@
 js_unittest("thumbnail_loader_unittest") {
   deps = [
     ":thumbnail_loader",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:mock_entry",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
     "//ui/file_manager/image_loader:image_loader_client",
diff --git a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js
index f8c70cb..8479634 100644
--- a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js
@@ -4,7 +4,7 @@
 
 import {assert} from 'chrome://resources/js/assert.js';
 import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockDriveSyncHandler} from '../../background/js/mock_drive_sync_handler.js';
 import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
diff --git a/ui/file_manager/file_manager/foreground/js/banner_controller_unittest.js b/ui/file_manager/file_manager/foreground/js/banner_controller_unittest.js
index d6359964..0633727d 100644
--- a/ui/file_manager/file_manager/foreground/js/banner_controller_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/banner_controller_unittest.js
@@ -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 {assertDeepEquals, assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertDeepEquals, assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {DialogType} from '../../common/js/dialog_type.js';
 import {installMockChrome, MockChromeFileManagerPrivateDirectoryChanged, MockChromeStorageAPI} from '../../common/js/mock_chrome.js';
diff --git a/ui/file_manager/file_manager/foreground/js/banner_util_unittest.js b/ui/file_manager/file_manager/foreground/js/banner_util_unittest.js
index e6238ee..40021d20 100644
--- a/ui/file_manager/file_manager/foreground/js/banner_util_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/banner_util_unittest.js
@@ -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 {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
 import {Banner} from '../../externs/banner.js';
diff --git a/ui/file_manager/file_manager/foreground/js/directory_contents_unittest.js b/ui/file_manager/file_manager/foreground/js/directory_contents_unittest.js
index 7c31d35..d07a94cb 100644
--- a/ui/file_manager/file_manager/foreground/js/directory_contents_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/directory_contents_unittest.js
@@ -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 {assertEquals, assertFalse} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {installMockChrome} from '../../common/js/mock_chrome.js';
 import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
diff --git a/ui/file_manager/file_manager/foreground/js/directory_model_unittest.js b/ui/file_manager/file_manager/foreground/js/directory_model_unittest.js
index 6c17f74..61fef83 100644
--- a/ui/file_manager/file_manager/foreground/js/directory_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/directory_model_unittest.js
@@ -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 {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockFileOperationManager} from '../../background/js/mock_file_operation_manager.js';
 import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
diff --git a/ui/file_manager/file_manager/foreground/js/empty_folder_controller_unittest.js b/ui/file_manager/file_manager/foreground/js/empty_folder_controller_unittest.js
index 182fa68f..4b1deeb 100644
--- a/ui/file_manager/file_manager/foreground/js/empty_folder_controller_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/empty_folder_controller_unittest.js
@@ -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 {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {createChild} from '../../common/js/dom_utils.js';
 import {FakeEntryImpl} from '../../common/js/files_app_entry_types.js';
diff --git a/ui/file_manager/file_manager/foreground/js/file_list_model_unittest.js b/ui/file_manager/file_manager/foreground/js/file_list_model_unittest.js
index 90421d36..7fd1c3f 100644
--- a/ui/file_manager/file_manager/foreground/js/file_list_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/file_list_model_unittest.js
@@ -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 {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {str} from '../../common/js/util.js';
 
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands_unittest.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands_unittest.js
index d588824..7d88bb6 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager_commands_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands_unittest.js
@@ -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 {assertArrayEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertArrayEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
 import {FakeEntryImpl} from '../../common/js/files_app_entry_types.js';
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.ts b/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.ts
index 581ff63..fe60fc3 100644
--- a/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.ts
+++ b/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.ts
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {createCrostiniForTest} from '../../background/js/mock_crostini.js';
 import {MockProgressCenter} from '../../background/js/mock_progress_center.js';
diff --git a/ui/file_manager/file_manager/foreground/js/file_transfer_controller_unittest.js b/ui/file_manager/file_manager/foreground/js/file_transfer_controller_unittest.js
index 3b99adf5..a5bb431 100644
--- a/ui/file_manager/file_manager/foreground/js/file_transfer_controller_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/file_transfer_controller_unittest.js
@@ -5,7 +5,7 @@
 import 'chrome://resources/cr_elements/cr_input/cr_input.js';
 
 import {decorate} from '../../common/js/ui.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
 import {DialogType} from '../../common/js/dialog_type.js';
diff --git a/ui/file_manager/file_manager/foreground/js/file_type_filters_controller_unittest.js b/ui/file_manager/file_manager/foreground/js/file_type_filters_controller_unittest.js
index a98ecb5..99e9e00 100644
--- a/ui/file_manager/file_manager/foreground/js/file_type_filters_controller_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/file_type_filters_controller_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {EntryList, FakeEntryImpl} from '../../common/js/files_app_entry_types.js';
 import {metrics} from '../../common/js/metrics.js';
diff --git a/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.js b/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.js
index 76395340..2895201 100644
--- a/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.js
@@ -4,7 +4,7 @@
 
 import {assert} from 'chrome://resources/js/assert.js';
 import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockDirectoryEntry, MockEntry, MockFileSystem} from '../../common/js/mock_entry.js';
 import {reportPromise, waitUntil} from '../../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn b/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn
index 87b85a0..7d6fe21 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn
@@ -102,7 +102,7 @@
   deps = [
     ":content_metadata_provider",
     ":metadata_request",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
   ]
 }
@@ -133,7 +133,7 @@
     ":byte_reader",
     ":exif_constants",
     ":exif_parser",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/externs:exif_entry",
     "//ui/file_manager/file_manager/externs:metadata_worker_window",
   ]
@@ -153,7 +153,7 @@
   deps = [
     ":external_metadata_provider",
     ":metadata_request",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:mock_chrome",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
   ]
@@ -170,7 +170,7 @@
   deps = [
     ":file_system_metadata_provider",
     ":metadata_request",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
   ]
 }
@@ -212,7 +212,7 @@
   deps = [
     ":metadata_cache_item",
     ":metadata_item",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -229,7 +229,7 @@
 js_unittest("metadata_cache_set_unittest") {
   deps = [
     ":metadata_cache_set",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -266,7 +266,7 @@
   deps = [
     ":metadata_model",
     ":metadata_provider",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
   ]
 }
@@ -324,7 +324,7 @@
     ":file_system_metadata_provider",
     ":metadata_request",
     ":multi_metadata_provider",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
     "//ui/file_manager/file_manager/common/js:volume_manager_types",
     "//ui/file_manager/file_manager/externs:volume_manager",
@@ -343,7 +343,7 @@
     ":metadata_item",
     ":metadata_model",
     ":thumbnail_model",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
   ]
 }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.js
index 56e1e16..9898124b8 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.js
@@ -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 {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {reportPromise} from '../../../common/js/test_error_reporting.js';
 
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.js
index ddb1ad9e..c4f525d 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.js
@@ -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 {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {ExifEntry} from '../../../externs/exif_entry.js';
 import {MetadataParserLogger} from '../../../externs/metadata_worker_window.js';
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.js
index 5715d8a..5fbbff5 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.js
@@ -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 {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {installMockChrome} from '../../../common/js/mock_chrome.js';
 import {reportPromise} from '../../../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.js
index 5a9e6f56..acdfa4d 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.js
@@ -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 {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {reportPromise} from '../../../common/js/test_error_reporting.js';
 
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.js
index af7d49f..90bc7448 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.js
@@ -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 {assertEquals, assertFalse, assertThrows, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertThrows, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MetadataCacheItem} from './metadata_cache_item.js';
 import {MetadataItem} from './metadata_item.js';
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.js
index 33d821d..4efa6ef 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.js
@@ -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 {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MetadataCacheSet} from './metadata_cache_set.js';
 
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.js
index 68025b2c..533c252 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.js
@@ -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 {assertEquals, assertThrows} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertThrows} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {reportPromise} from '../../../common/js/test_error_reporting.js';
 
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js
index ce6ff87..f7f11177 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js
@@ -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 {assertArrayEquals, assertEquals, assertNotReached, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertArrayEquals, assertEquals, assertNotReached, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {reportPromise} from '../../../common/js/test_error_reporting.js';
 import {VolumeManagerCommon} from '../../../common/js/volume_manager_types.js';
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.js
index 0e7b3ab..8f1ca7c9 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.js
@@ -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 {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {reportPromise} from '../../../common/js/test_error_reporting.js';
 
diff --git a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
index 21f2cdf..785da33 100644
--- a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
 import {VolumeInfoImpl} from '../../background/js/volume_info_impl.js';
diff --git a/ui/file_manager/file_manager/foreground/js/path_component_unittest.js b/ui/file_manager/file_manager/foreground/js/path_component_unittest.js
index 775b03d4..b68afe15 100644
--- a/ui/file_manager/file_manager/foreground/js/path_component_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/path_component_unittest.js
@@ -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 {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
 import {MockFileSystem} from '../../common/js/mock_entry.js';
diff --git a/ui/file_manager/file_manager/foreground/js/providers_model_unittest.js b/ui/file_manager/file_manager/foreground/js/providers_model_unittest.js
index 67f5cd9..4da17738 100644
--- a/ui/file_manager/file_manager/foreground/js/providers_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/providers_model_unittest.js
@@ -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 {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
 import {VolumeInfoImpl} from '../../background/js/volume_info_impl.js';
diff --git a/ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.js b/ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.js
index 637d287..2275ef6 100644
--- a/ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {assert} from 'chrome://resources/js/assert.js';
-import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {reportPromise} from '../../common/js/test_error_reporting.js';
 
diff --git a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.ts b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.ts
index 4f72af4..f008f448 100644
--- a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.ts
+++ b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.ts
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {assert} from 'chrome://resources/js/assert.js';
-import {assertDeepEquals, assertNotReached, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertDeepEquals, assertNotReached, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {createCrostiniForTest} from '../../background/js/mock_crostini.js';
 import {DialogType} from '../../common/js/dialog_type.js';
@@ -244,7 +244,6 @@
       })
       .catch(error => {
         assertNotReached(error.toString());
-        callback();
       });
 }
 
@@ -272,7 +271,6 @@
   taskController.getFileTasks().then(
       (_tasks: FileTasks) => {
         assertNotReached('Fail: getFileTasks promise should be rejected');
-        callback();
       },
       () => {
         // Clears the selection handler computeAdditionalCallback so that the
@@ -287,7 +285,6 @@
             },
             () => {
               assertNotReached('Fail: getFileTasks promise was rejected');
-              callback();
             });
       });
 }
diff --git a/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.js b/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.js
index c48c25a..67cc4b81 100644
--- a/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.js
@@ -4,7 +4,7 @@
 
 import {ImageLoaderClient} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/image_loader_client.js';
 import {LoadImageRequest} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/load_image_request.js';
-import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockEntry, MockFileSystem} from '../../common/js/mock_entry.js';
 import {reportPromise} from '../../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
index c780ed6..7044d81 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
@@ -143,7 +143,7 @@
   deps = [
     ":actions_submenu",
     ":menu",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:util",
     "//ui/file_manager/file_manager/foreground/js:mock_actions_model",
     "//ui/webui/resources/js:assert",
@@ -174,7 +174,7 @@
 js_unittest("command_unittest") {
   deps = [
     ":command",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:ui",
   ]
 }
@@ -206,7 +206,7 @@
   deps = [
     ":context_menu_handler",
     ":menu",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:ui",
   ]
 }
@@ -266,7 +266,7 @@
 js_unittest("directory_tree_unittest") {
   deps = [
     ":directory_tree",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/background/js:mock_volume_manager",
     "//ui/file_manager/file_manager/common/js:files_app_entry_types",
     "//ui/file_manager/file_manager/common/js:mock_chrome",
@@ -320,7 +320,7 @@
     ":a11y_announce",
     ":file_grid",
     ":list_selection_model",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/background/js:mock_volume_manager",
     "//ui/file_manager/file_manager/common/js:files_app_entry_types",
     "//ui/file_manager/file_manager/common/js:mock_chrome",
@@ -342,7 +342,7 @@
 js_unittest("file_list_selection_model_unittest") {
   deps = [
     ":file_list_selection_model",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -357,7 +357,7 @@
 js_unittest("file_manager_dialog_base_unittest") {
   deps = [
     ":file_manager_dialog_base",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
     "//ui/webui/resources/js:assert",
   ]
@@ -448,7 +448,7 @@
   deps = [
     ":file_table",
     "table:table_column",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -480,7 +480,7 @@
     ":file_list_selection_model",
     ":file_table",
     ":file_table_list",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/background/js:mock_volume_manager",
     "//ui/file_manager/file_manager/common/js:files_app_entry_types",
     "//ui/file_manager/file_manager/common/js:volume_manager_types",
@@ -498,7 +498,7 @@
 js_unittest("file_tap_handler_unittest") {
   deps = [
     ":file_tap_handler",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
   ]
 }
@@ -547,7 +547,7 @@
 js_unittest("grid_unittest") {
   deps = [
     ":grid",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:array_data_model",
   ]
 }
@@ -563,7 +563,7 @@
 js_unittest("install_linux_package_dialog_unittest") {
   deps = [
     ":install_linux_package_dialog",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/webui/resources/js:assert",
     "//ui/webui/resources/js:load_time_data.m",
   ]
@@ -590,7 +590,7 @@
 js_unittest("list_unittest") {
   deps = [
     ":list",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:array_data_model",
     "//ui/file_manager/file_manager/common/js:ui",
   ]
@@ -632,7 +632,7 @@
   deps = [
     ":list_selection_model",
     ":list_single_selection_model",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -640,7 +640,7 @@
   deps = [
     ":list_selection_model",
     ":list_selection_model_test_util",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -655,7 +655,7 @@
   deps = [
     ":list_selection_model_test_util",
     ":list_single_selection_model",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -673,7 +673,7 @@
     ":command",
     ":menu",
     ":menu_item",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:ui",
   ]
 }
@@ -693,7 +693,7 @@
   deps = [
     ":menu",
     ":menu_button",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:ui",
   ]
 }
@@ -737,7 +737,7 @@
     ":command",
     ":menu",
     ":multi_menu_button",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:ui",
     "//ui/file_manager/file_manager/common/js:util",
     "//ui/webui/resources/js:assert",
@@ -750,7 +750,7 @@
 js_unittest("position_util_unittest") {
   deps = [
     ":position_util",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -799,7 +799,7 @@
 js_unittest("splitter_unittest") {
   deps = [
     ":splitter",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:ui",
     "//ui/webui/resources/js:util",
   ]
diff --git a/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.js
index ea99c47..34a3c9b 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {assertInstanceof} from 'chrome://resources/js/assert.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {queryDecoratedElement, queryRequiredElement} from '../../../common/js/dom_utils.js';
 import {util} from '../../../common/js/util.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/banners/BUILD.gn
index 2b23a15..3253da4 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/banners/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/ui/banners/BUILD.gn
@@ -81,7 +81,7 @@
 js_unittest("dlp_restricted_banner_unittest") {
   deps = [
     ":dlp_restricted_banner",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:dialog_type",
     "//ui/file_manager/file_manager/common/js:volume_manager_types",
   ]
@@ -168,7 +168,7 @@
 js_unittest("educational_banner_unittest") {
   deps = [
     ":educational_banner",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:mock_util",
     "//ui/file_manager/file_manager/externs:banner",
   ]
@@ -203,7 +203,7 @@
 js_unittest("state_banner_unittest") {
   deps = [
     ":state_banner",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:mock_util",
   ]
 }
@@ -227,7 +227,7 @@
 js_unittest("warning_banner_unittest") {
   deps = [
     ":warning_banner",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:mock_util",
     "//ui/file_manager/file_manager/externs:banner",
   ]
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners/dlp_restricted_banner_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/banners/dlp_restricted_banner_unittest.js
index 3aa3126..0f79df86 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/banners/dlp_restricted_banner_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/banners/dlp_restricted_banner_unittest.js
@@ -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 {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {VolumeManagerCommon} from '../../../../common/js/volume_manager_types.js';
 
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners/educational_banner_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/banners/educational_banner_unittest.js
index b4bd58f..077c315 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/banners/educational_banner_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/banners/educational_banner_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {mockUtilVisitURL} from '../../../../common/js/mock_util.js';
 import {Banner} from '../../../../externs/banner.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners/state_banner_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/banners/state_banner_unittest.js
index 4458a68..029a236 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/banners/state_banner_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/banners/state_banner_unittest.js
@@ -4,7 +4,7 @@
 
 import {decorate} from '../../../../common/js/ui.js';
 import {Command} from '../command.js';
-import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {mockUtilVisitURL} from '../../../../common/js/mock_util.js';
 import {waitUntil} from '../../../../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners/warning_banner_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/banners/warning_banner_unittest.js
index 38eb851..73cc243 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/banners/warning_banner_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/banners/warning_banner_unittest.js
@@ -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 {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {mockUtilVisitURL} from '../../../../common/js/mock_util.js';
 import {Banner} from '../../../../externs/banner.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/command_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/command_unittest.js
index 78150ccb..0a548f7 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/command_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/command_unittest.js
@@ -6,7 +6,7 @@
 import {decorate} from '../../../common/js/ui.js';
 import {Command} from './command.js';
 
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 // clang-format on
 
diff --git a/ui/file_manager/file_manager/foreground/js/ui/context_menu_handler_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/context_menu_handler_unittest.js
index 64a9198..938d9a2 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/context_menu_handler_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/context_menu_handler_unittest.js
@@ -7,7 +7,7 @@
 import {contextMenuHandler} from './context_menu_handler.js';
 import {Menu} from './menu.js';
 
-import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 // clang-format on
 
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js
index 503ee53..1db816f 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js
@@ -4,7 +4,7 @@
 
 import {assert} from 'chrome://resources/js/assert.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockVolumeManager} from '../../../background/js/mock_volume_manager.js';
 import {DialogType} from '../../../common/js/dialog_type.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_grid_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/file_grid_unittest.js
index 31f74363..84b9d54 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_grid_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_grid_unittest.js
@@ -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 {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockVolumeManager} from '../../../background/js/mock_volume_manager.js';
 import {FakeEntryImpl} from '../../../common/js/files_app_entry_types.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model_unittest.js
index d1e784f..d9fb857 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model_unittest.js
@@ -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 {assertArrayEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertArrayEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {FileListSelectionModel} from './file_list_selection_model.js';
 
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base_unittest.js
index bcdcc79..7141d053 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {assertInstanceof} from 'chrome://resources/js/assert.js';
-import {assertFalse} from 'chrome://webui-test/chai_assert.js';
+import {assertFalse} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {waitUntil} from '../../../common/js/test_error_reporting.js';
 
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.js
index 72f75555f..b243d0f 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.js
@@ -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 {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockVolumeManager} from '../../../background/js/mock_volume_manager.js';
 import {FakeEntryImpl} from '../../../common/js/files_app_entry_types.js';
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 aadf7d4..1392c03 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
@@ -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 {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {FileTableColumnModel} from './file_table.js';
 import {TableColumn} from './table/table_column.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.js
index cc0d089..fc64d09 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.js
@@ -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 {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {reportPromise} from '../../../common/js/test_error_reporting.js';
 
diff --git a/ui/file_manager/file_manager/foreground/js/ui/grid_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/grid_unittest.js
index c726a80..2e6105d 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/grid_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/grid_unittest.js
@@ -7,7 +7,7 @@
 
 import {Grid} from './grid.js';
 
-import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 // clang-format on
 
 /**
diff --git a/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.js
index a85c4017..cbcee5e 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {assertInstanceof} from 'chrome://resources/js/assert.js';
-import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {InstallLinuxPackageDialog} from './install_linux_package_dialog.js';
 
diff --git a/ui/file_manager/file_manager/foreground/js/ui/list_selection_model_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/list_selection_model_unittest.js
index 5bab707..6af8a15 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/list_selection_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/list_selection_model_unittest.js
@@ -5,7 +5,7 @@
 // clang-format off
 import {ListSelectionModel} from './list_selection_model.js';
 
-import {assertArrayEquals, assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertArrayEquals, assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {adjust, range} from './list_selection_model_test_util.js';
 // clang-format on
diff --git a/ui/file_manager/file_manager/foreground/js/ui/list_single_selection_model_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/list_single_selection_model_unittest.js
index 6f879ee..0be0ed0 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/list_single_selection_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/list_single_selection_model_unittest.js
@@ -5,7 +5,7 @@
 // clang-format off
 import {ListSingleSelectionModel} from './list_single_selection_model.js';
 
-import {assertArrayEquals, assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertArrayEquals, assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {adjust} from './list_selection_model_test_util.js';
 // clang-format on
diff --git a/ui/file_manager/file_manager/foreground/js/ui/list_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/list_unittest.js
index 78077b2..98438f3 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/list_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/list_unittest.js
@@ -9,7 +9,7 @@
 
 import {List} from './list.js';
 
-import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 // clang-format on
 
diff --git a/ui/file_manager/file_manager/foreground/js/ui/menu_button_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/menu_button_unittest.js
index ab1e43c..94e66490 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/menu_button_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/menu_button_unittest.js
@@ -7,7 +7,7 @@
 import {Menu} from './menu.js';
 import {MenuButton} from './menu_button.js';
 
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 // clang-format on
 
diff --git a/ui/file_manager/file_manager/foreground/js/ui/menu_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/menu_unittest.js
index 1937140..55e6b59 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/menu_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/menu_unittest.js
@@ -8,7 +8,7 @@
 import {Menu} from './menu.js';
 import {MenuItem} from './menu_item.js';
 
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 // clang-format on
 
 /** @type {Menu} */
diff --git a/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.js
index d607905..29157cb0 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {assert} from 'chrome://resources/js/assert.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {queryDecoratedElement} from '../../../common/js/dom_utils.js';
 import {decorate} from '../../../common/js/ui.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/position_util_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/position_util_unittest.js
index 6ea6e9cc..98b8b5e 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/position_util_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/position_util_unittest.js
@@ -5,7 +5,7 @@
 // clang-format off
 import {AnchorType, positionPopupAroundElement, positionPopupAtPoint} from './position_util.js';
 
-import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 // clang-format on
 
 /** @type {!HTMLElement} */
diff --git a/ui/file_manager/file_manager/foreground/js/ui/splitter_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/splitter_unittest.js
index 00f649a3..5b93e88 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/splitter_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/splitter_unittest.js
@@ -5,7 +5,7 @@
 // clang-format off
 import {decorate} from '../../../common/js/ui.js';
 import {getRequiredElement} from 'chrome://resources/js/util.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {Splitter} from './splitter.js';
 
diff --git a/ui/file_manager/file_manager/lib/actions_producer_unittest.ts b/ui/file_manager/file_manager/lib/actions_producer_unittest.ts
index 6cdff30..ab2d4201 100644
--- a/ui/file_manager/file_manager/lib/actions_producer_unittest.ts
+++ b/ui/file_manager/file_manager/lib/actions_producer_unittest.ts
@@ -1,7 +1,7 @@
 // Copyright 2022 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {waitUntil} from '../common/js/test_error_reporting.js';
 
diff --git a/ui/file_manager/file_manager/lib/base_store_unittest.ts b/ui/file_manager/file_manager/lib/base_store_unittest.ts
index 02861d9a..fd39508b 100644
--- a/ui/file_manager/file_manager/lib/base_store_unittest.ts
+++ b/ui/file_manager/file_manager/lib/base_store_unittest.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 {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {waitUntil} from '../common/js/test_error_reporting.js';
 
diff --git a/ui/file_manager/file_manager/state/reducers/all_entries_unittest.ts b/ui/file_manager/file_manager/state/reducers/all_entries_unittest.ts
index 5df0da9..1935b9d 100644
--- a/ui/file_manager/file_manager/state/reducers/all_entries_unittest.ts
+++ b/ui/file_manager/file_manager/state/reducers/all_entries_unittest.ts
@@ -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 {assertDeepEquals, assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertDeepEquals, assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
 import {MockFileSystem} from '../../common/js/mock_entry.js';
diff --git a/ui/file_manager/file_manager/widgets/xf_breadcrumb_unittest.ts b/ui/file_manager/file_manager/widgets/xf_breadcrumb_unittest.ts
index 953d4d64..81dc9617 100644
--- a/ui/file_manager/file_manager/widgets/xf_breadcrumb_unittest.ts
+++ b/ui/file_manager/file_manager/widgets/xf_breadcrumb_unittest.ts
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {assert} from 'chrome://resources/js/assert_ts.js';
-import {assertEquals, assertFalse, assertGT, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertGT, assertNotEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {hasOverflowEllipsis} from '../common/js/dom_utils.js';
 import {waitUntil} from '../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/widgets/xf_conflict_dialog_unittest.ts b/ui/file_manager/file_manager/widgets/xf_conflict_dialog_unittest.ts
index 1e559f64..3115a344 100644
--- a/ui/file_manager/file_manager/widgets/xf_conflict_dialog_unittest.ts
+++ b/ui/file_manager/file_manager/widgets/xf_conflict_dialog_unittest.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 {assertEquals, assertFalse, assertNotEquals, assertNotReached, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertNotEquals, assertNotReached, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {waitUntil} from '../common/js/test_error_reporting.js';
 
diff --git a/ui/file_manager/file_manager/widgets/xf_dlp_restriction_details_dialog_unittest.ts b/ui/file_manager/file_manager/widgets/xf_dlp_restriction_details_dialog_unittest.ts
index b0f3c0d..8594a267 100644
--- a/ui/file_manager/file_manager/widgets/xf_dlp_restriction_details_dialog_unittest.ts
+++ b/ui/file_manager/file_manager/widgets/xf_dlp_restriction_details_dialog_unittest.ts
@@ -5,7 +5,7 @@
 import './xf_dlp_restriction_details_dialog.js';
 
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
-import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {XfDlpRestrictionDetailsDialog} from './xf_dlp_restriction_details_dialog.js';
 
diff --git a/ui/file_manager/file_manager/widgets/xf_nudge_unittest.ts b/ui/file_manager/file_manager/widgets/xf_nudge_unittest.ts
index a274a35..2563801 100644
--- a/ui/file_manager/file_manager/widgets/xf_nudge_unittest.ts
+++ b/ui/file_manager/file_manager/widgets/xf_nudge_unittest.ts
@@ -4,7 +4,7 @@
 
 import './xf_nudge.js';
 
-import {assertEquals, assertGT, assertLT, assertThrows} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals, assertGT, assertLT, assertThrows} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {NudgeDirection, XfNudge} from './xf_nudge.js';
 
diff --git a/ui/file_manager/file_manager/widgets/xf_select_unittest.ts b/ui/file_manager/file_manager/widgets/xf_select_unittest.ts
index 911591b..aaafeee 100644
--- a/ui/file_manager/file_manager/widgets/xf_select_unittest.ts
+++ b/ui/file_manager/file_manager/widgets/xf_select_unittest.ts
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 
-import {assertDeepEquals, assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertDeepEquals, assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {SELECTION_CHANGED, XfSelect} from './xf_select.js';
 
diff --git a/ui/file_manager/image_loader/BUILD.gn b/ui/file_manager/image_loader/BUILD.gn
index 687ee593..5b8829e 100644
--- a/ui/file_manager/image_loader/BUILD.gn
+++ b/ui/file_manager/image_loader/BUILD.gn
@@ -38,7 +38,7 @@
 js_unittest("cache_unittest") {
   deps = [
     ":load_image_request",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -58,7 +58,7 @@
     ":image_loader_util",
     ":image_orientation",
     ":load_image_request",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -92,7 +92,7 @@
   deps = [
     ":image_loader_client",
     ":load_image_request",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
   ]
 }
@@ -103,7 +103,7 @@
 js_unittest("image_orientation_unittest") {
   deps = [
     ":image_orientation",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
@@ -137,7 +137,7 @@
   deps = [
     ":image_request_task",
     ":scheduler",
-    "//chrome/test/data/webui:chai_assert",
+    "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
 
diff --git a/ui/file_manager/image_loader/cache_unittest.js b/ui/file_manager/image_loader/cache_unittest.js
index 1aae68a..a506bec 100644
--- a/ui/file_manager/image_loader/cache_unittest.js
+++ b/ui/file_manager/image_loader/cache_unittest.js
@@ -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 {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {LoadImageRequest} from './load_image_request.js';
 
diff --git a/ui/file_manager/image_loader/image_loader_client_unittest.js b/ui/file_manager/image_loader/image_loader_client_unittest.js
index 3cb007bb..35baf0b0 100644
--- a/ui/file_manager/image_loader/image_loader_client_unittest.js
+++ b/ui/file_manager/image_loader/image_loader_client_unittest.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {reportPromise} from 'chrome://file-manager/common/js/test_error_reporting.js';
-import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {ImageLoaderClient} from './image_loader_client.js';
 import {LoadImageRequest, LoadImageResponse, LoadImageResponseStatus} from './load_image_request.js';
diff --git a/ui/file_manager/image_loader/image_loader_unittest.js b/ui/file_manager/image_loader/image_loader_unittest.js
index 7a6e4082..2bbe4a03d 100644
--- a/ui/file_manager/image_loader/image_loader_unittest.js
+++ b/ui/file_manager/image_loader/image_loader_unittest.js
@@ -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 {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {ImageLoaderUtil} from './image_loader_util.js';
 import {ImageOrientation} from './image_orientation.js';
diff --git a/ui/file_manager/image_loader/image_orientation_unittest.js b/ui/file_manager/image_loader/image_orientation_unittest.js
index 550de54..2da6ed8 100644
--- a/ui/file_manager/image_loader/image_orientation_unittest.js
+++ b/ui/file_manager/image_loader/image_orientation_unittest.js
@@ -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 {assertDeepEquals, assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertDeepEquals, assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {ImageOrientation} from './image_orientation.js';
 
diff --git a/ui/file_manager/image_loader/scheduler_unittest.js b/ui/file_manager/image_loader/scheduler_unittest.js
index 4f8b6f7..2d56598 100644
--- a/ui/file_manager/image_loader/scheduler_unittest.js
+++ b/ui/file_manager/image_loader/scheduler_unittest.js
@@ -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 {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {ImageRequestTask} from './image_request_task.js';
 import {Scheduler} from './scheduler.js';
diff --git a/ui/message_center/message_center_impl.cc b/ui/message_center/message_center_impl.cc
index b2afadb..292907ad 100644
--- a/ui/message_center/message_center_impl.cc
+++ b/ui/message_center/message_center_impl.cc
@@ -281,6 +281,17 @@
   for (NotificationBlocker* blocker : blockers_)
     blocker->CheckState();
 
+  auto* old_notification = notification_list_->GetNotificationById(old_id);
+  if (old_notification) {
+    DCHECK(old_notification->notifier_id() == new_notification->notifier_id());
+
+    // Copy grouping metadata to the new notification.
+    if (old_notification->group_parent())
+      new_notification->SetGroupParent();
+    if (old_notification->group_child())
+      new_notification->SetGroupChild();
+  }
+
   std::string new_id = new_notification->id();
   notification_list_->UpdateNotificationMessage(old_id,
                                                 std::move(new_notification));
diff --git a/ui/message_center/views/notification_view_base_unittest.cc b/ui/message_center/views/notification_view_base_unittest.cc
index 90fde41..f7409fd 100644
--- a/ui/message_center/views/notification_view_base_unittest.cc
+++ b/ui/message_center/views/notification_view_base_unittest.cc
@@ -822,6 +822,9 @@
 }
 
 TEST_F(NotificationViewBaseTest, SnoozeButton) {
+  MessageCenter::Get()->RemoveAllNotifications(/*by_user=*/false,
+                                               MessageCenter::RemoveType::ALL);
+
   // Create notification to replace the current one with itself.
   message_center::RichNotificationData rich_data;
   rich_data.settings_button_handler = SettingsButtonHandler::INLINE;
@@ -1074,8 +1077,11 @@
 }
 
 TEST_F(NotificationViewBaseTest, AppNameSystemNotification) {
+  MessageCenter::Get()->RemoveAllNotifications(/*by_user=*/false,
+                                               MessageCenter::RemoveType::ALL);
+
   std::u16string app_name = u"system notification";
-  message_center::MessageCenter::Get()->SetSystemNotificationAppName(app_name);
+  MessageCenter::Get()->SetSystemNotificationAppName(app_name);
   RichNotificationData data;
   data.settings_button_handler = SettingsButtonHandler::INLINE;
   auto notification = std::make_unique<Notification>(
@@ -1105,6 +1111,9 @@
 }
 
 TEST_F(NotificationViewBaseTest, AppNameWebAppNotification) {
+  MessageCenter::Get()->RemoveAllNotifications(/*by_user=*/false,
+                                               MessageCenter::RemoveType::ALL);
+
   const GURL web_app_url("http://example.com");
 
   NotifierId notifier_id(web_app_url, /*title=*/u"web app title");
diff --git a/ui/message_center/views/notification_view_unittest.cc b/ui/message_center/views/notification_view_unittest.cc
index fc3f75c..da19fcf 100644
--- a/ui/message_center/views/notification_view_unittest.cc
+++ b/ui/message_center/views/notification_view_unittest.cc
@@ -609,6 +609,9 @@
 }
 
 TEST_F(NotificationViewTest, AppIconWebAppNotification) {
+  MessageCenter::Get()->RemoveAllNotifications(/*by_user=*/false,
+                                               MessageCenter::RemoveType::ALL);
+
   const GURL web_app_url(kWebAppUrl);
 
   NotifierId notifier_id(web_app_url, /*title=*/u"web app title");
diff --git a/ui/ozone/platform/drm/gpu/drm_display.cc b/ui/ozone/platform/drm/gpu/drm_display.cc
index 70d6b8f..47a1e5d 100644
--- a/ui/ozone/platform/drm/gpu/drm_display.cc
+++ b/ui/ozone/platform/drm/gpu/drm_display.cc
@@ -344,6 +344,15 @@
   CommitGammaCorrection(degamma, gamma);
 }
 
+bool DrmDisplay::SetVrrEnabled(bool vrr_enabled) {
+  if (!drm_->plane_manager()->SetVrrEnabled(crtc_, vrr_enabled)) {
+    LOG(ERROR) << "Failed to set vrr_enabled property for crtc_id = " << crtc_;
+    return false;
+  }
+
+  return true;
+}
+
 void DrmDisplay::CommitGammaCorrection(
     const std::vector<display::GammaRampRGBEntry>& degamma_lut,
     const std::vector<display::GammaRampRGBEntry>& gamma_lut) {
diff --git a/ui/ozone/platform/drm/gpu/drm_display.h b/ui/ozone/platform/drm/gpu/drm_display.h
index 149bca4f..e8d3fbf 100644
--- a/ui/ozone/platform/drm/gpu/drm_display.h
+++ b/ui/ozone/platform/drm/gpu/drm_display.h
@@ -86,6 +86,7 @@
       const std::vector<display::GammaRampRGBEntry>& gamma_lut);
   bool SetPrivacyScreen(bool enabled);
   void SetColorSpace(const gfx::ColorSpace& color_space);
+  bool SetVrrEnabled(bool vrr_enabled);
 
   void set_is_hdr_capable_for_testing(bool value) { is_hdr_capable_ = value; }
 
diff --git a/ui/ozone/platform/drm/gpu/drm_display_unittest.cc b/ui/ozone/platform/drm/gpu/drm_display_unittest.cc
index a147be7..3246cd1df 100644
--- a/ui/ozone/platform/drm/gpu/drm_display_unittest.cc
+++ b/ui/ozone/platform/drm/gpu/drm_display_unittest.cc
@@ -16,6 +16,7 @@
 #include "ui/ozone/platform/drm/gpu/mock_drm_device.h"
 
 using ::testing::_;
+using ::testing::Return;
 using ::testing::SizeIs;
 
 // Verifies that the argument goes from 0 to the maximum uint16_t times |scale|
@@ -47,10 +48,16 @@
       : HardwareDisplayPlaneManager(drm) {}
   ~MockHardwareDisplayPlaneManager() override = default;
 
-  MOCK_METHOD3(SetGammaCorrection,
-               bool(uint32_t crtc_id,
-                    const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-                    const std::vector<display::GammaRampRGBEntry>& gamma_lut));
+  MOCK_METHOD(bool,
+              SetGammaCorrection,
+              (uint32_t crtc_id,
+               const std::vector<display::GammaRampRGBEntry>& degamma_lut,
+               const std::vector<display::GammaRampRGBEntry>& gamma_lut),
+              (override));
+  MOCK_METHOD(bool,
+              SetVrrEnabled,
+              (uint32_t crtc_id, bool vrr_enabled),
+              (override));
 
   bool Commit(CommitRequest commit_request, uint32_t flags) override {
     return false;
@@ -166,7 +173,7 @@
       AddMockHardwareDisplayPlaneManager();
 
   ON_CALL(*plane_manager, SetGammaCorrection(_, _, _))
-      .WillByDefault(::testing::Return(true));
+      .WillByDefault(Return(true));
 
   constexpr float kSDRLevel = 0.85;
   constexpr float kExponent = 1.2;
@@ -177,4 +184,15 @@
                                   std::vector<display::GammaRampRGBEntry>());
 }
 
+TEST_F(DrmDisplayTest, SetVrrEnabled) {
+  MockHardwareDisplayPlaneManager* plane_manager =
+      AddMockHardwareDisplayPlaneManager();
+
+  EXPECT_CALL(*plane_manager, SetVrrEnabled(_, _)).WillOnce(Return(false));
+  EXPECT_FALSE(drm_display_.SetVrrEnabled(true));
+
+  EXPECT_CALL(*plane_manager, SetVrrEnabled(_, _)).WillOnce(Return(true));
+  EXPECT_TRUE(drm_display_.SetVrrEnabled(true));
+}
+
 }  // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
index 36978eb..011aa4a0 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
@@ -213,7 +213,7 @@
       auto* current = hw_planes_iter->get();
       if (IsCompatible(current, plane, crtc_id)) {
         hw_plane = current;
-        ++hw_planes_iter; // bump so we don't assign the same plane twice
+        ++hw_planes_iter;  // bump so we don't assign the same plane twice
         break;
       }
     }
@@ -364,6 +364,19 @@
   return CommitGammaCorrection(*crtc_props);
 }
 
+bool HardwareDisplayPlaneManager::SetVrrEnabled(uint32_t crtc_id,
+                                                bool vrr_enabled) {
+  const auto crtc_index = LookupCrtcIndex(crtc_id);
+  if (!crtc_index) {
+    LOG(ERROR) << "Unknown CRTC ID=" << crtc_id;
+    return false;
+  }
+
+  CrtcState* crtc_state = &crtc_state_[*crtc_index];
+  crtc_state->properties.vrr_enabled.value = vrr_enabled;
+  return true;
+}
+
 bool HardwareDisplayPlaneManager::InitializeCrtcState() {
   ScopedDrmResourcesPtr resources(drm_->GetResources());
   if (!resources) {
@@ -409,6 +422,8 @@
                           &state.properties.out_fence_ptr);
     GetDrmPropertyForName(drm_, props.get(), "BACKGROUND_COLOR",
                           &state.properties.background_color);
+    GetDrmPropertyForName(drm_, props.get(), kVrrEnabledPropertyName,
+                          &state.properties.vrr_enabled);
 
     num_crtcs_with_out_fence_ptr += (state.properties.out_fence_ptr.id != 0);
 
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
index e69cf09..ebf9df2 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
@@ -82,6 +82,7 @@
     DrmDevice::Property degamma_lut_size;
     DrmDevice::Property out_fence_ptr;
     DrmDevice::Property background_color;
+    DrmDevice::Property vrr_enabled;
   };
 
   struct CrtcState {
@@ -140,6 +141,10 @@
       const std::vector<display::GammaRampRGBEntry>& degamma_lut,
       const std::vector<display::GammaRampRGBEntry>& gamma_lut);
 
+  // Sets the variable refresh rate enabled state on the CRTC object with ID
+  // |crtc_id|.
+  virtual bool SetVrrEnabled(uint32_t crtc_id, bool vrr_enabled);
+
   // Assign hardware planes from the |planes_| list to |overlay_list| entries,
   // recording the plane IDs in the |plane_list|. Only planes compatible with
   // |crtc_id| will be used. |overlay_list| must be sorted bottom-to-top.
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
index 4b6baec..814b6102 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
@@ -85,6 +85,8 @@
   bool status =
       AddPropertyIfValid(atomic_request, crtc_id, modeset_props.active);
   status &= AddPropertyIfValid(atomic_request, crtc_id, modeset_props.mode_id);
+  status &=
+      AddPropertyIfValid(atomic_request, crtc_id, modeset_props.vrr_enabled);
   return status;
 }
 
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
index 325c86b4..deb04af 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
@@ -48,6 +48,7 @@
 constexpr uint32_t kDegammaLutPropId = 1006;
 constexpr uint32_t kDegammaLutSizePropId = 1007;
 constexpr uint32_t kOutFencePtrPropId = 1008;
+constexpr uint32_t kVrrEnabledPropId = 1009;
 
 constexpr uint32_t kCrtcIdPropId = 2000;
 constexpr uint32_t kTypePropId = 3010;
@@ -217,6 +218,7 @@
   property_names_.insert({kDegammaLutPropId, "DEGAMMA_LUT"});
   property_names_.insert({kDegammaLutSizePropId, "DEGAMMA_LUT_SIZE"});
   property_names_.insert({kOutFencePtrPropId, "OUT_FENCE_PTR"});
+  property_names_.insert({kVrrEnabledPropId, "VRR_ENABLED"});
 }
 
 void HardwareDisplayPlaneManagerTest::PerformPageFlip(
@@ -1135,6 +1137,66 @@
   }
 }
 
+TEST_P(HardwareDisplayPlaneManagerAtomicTest, SetVrrEnabled_Success) {
+  InitializeDrmState(/*crtc_count=*/1, /*planes_per_crtc=*/1);
+  crtc_properties_[0].properties.push_back(
+      {.id = kVrrEnabledPropId, .value = 0});
+  fake_drm_->InitializeState(crtc_properties_, connector_properties_,
+                             plane_properties_, property_names_, use_atomic_);
+  ui::HardwareDisplayPlaneList state;
+  fake_drm_->plane_manager()->BeginFrame(&state);
+
+  // Check the property is set correctly, but isn't committed until modeset.
+  EXPECT_TRUE(
+      fake_drm_->plane_manager()->SetVrrEnabled(crtc_properties_[0].id, true));
+  {
+    EXPECT_EQ(0u, GetCrtcPropertyValue(crtc_properties_[0].id, "VRR_ENABLED"));
+
+    PerformPageFlip(/*crtc_idx=*/0, &state);
+    EXPECT_EQ(0u, GetCrtcPropertyValue(crtc_properties_[0].id, "VRR_ENABLED"));
+
+    ui::CommitRequest commit_request;
+    ui::DrmOverlayPlaneList overlays;
+    overlays.emplace_back(fake_buffer_, nullptr);
+    commit_request.push_back(ui::CrtcCommitRequest::EnableCrtcRequest(
+        crtc_properties_[0].id, connector_properties_[0].id, kDefaultMode,
+        gfx::Point(), &state, std::move(overlays)));
+    fake_drm_->plane_manager()->Commit(
+        commit_request,
+        DRM_MODE_ATOMIC_ALLOW_MODESET & DRM_MODE_ATOMIC_TEST_ONLY);
+    EXPECT_EQ(0u, GetCrtcPropertyValue(crtc_properties_[0].id, "VRR_ENABLED"));
+
+    fake_drm_->plane_manager()->Commit(commit_request,
+                                       DRM_MODE_ATOMIC_ALLOW_MODESET);
+    EXPECT_EQ(1u, GetCrtcPropertyValue(crtc_properties_[0].id, "VRR_ENABLED"));
+  }
+
+  // Check the property is reset correctly, but isn't committed until modeset.
+  EXPECT_TRUE(
+      fake_drm_->plane_manager()->SetVrrEnabled(crtc_properties_[0].id, false));
+  {
+    EXPECT_EQ(1u, GetCrtcPropertyValue(crtc_properties_[0].id, "VRR_ENABLED"));
+
+    PerformPageFlip(/*crtc_idx=*/0, &state);
+    EXPECT_EQ(1u, GetCrtcPropertyValue(crtc_properties_[0].id, "VRR_ENABLED"));
+
+    ui::CommitRequest commit_request;
+    ui::DrmOverlayPlaneList overlays;
+    overlays.emplace_back(fake_buffer_, nullptr);
+    commit_request.push_back(ui::CrtcCommitRequest::EnableCrtcRequest(
+        crtc_properties_[0].id, connector_properties_[0].id, kDefaultMode,
+        gfx::Point(), &state, std::move(overlays)));
+    fake_drm_->plane_manager()->Commit(
+        commit_request,
+        DRM_MODE_ATOMIC_ALLOW_MODESET & DRM_MODE_ATOMIC_TEST_ONLY);
+    EXPECT_EQ(1u, GetCrtcPropertyValue(crtc_properties_[0].id, "VRR_ENABLED"));
+
+    fake_drm_->plane_manager()->Commit(commit_request,
+                                       DRM_MODE_ATOMIC_ALLOW_MODESET);
+    EXPECT_EQ(0u, GetCrtcPropertyValue(crtc_properties_[0].id, "VRR_ENABLED"));
+  }
+}
+
 TEST_P(HardwareDisplayPlaneManagerAtomicTest,
        CommitReturnsNullOutFenceIfOutFencePtrNotSupported) {
   scoped_refptr<ui::DrmFramebuffer> fake_buffer2 =
diff --git a/ui/webui/resources/cr_components/help_bubble/help_bubble.gni b/ui/webui/resources/cr_components/help_bubble/help_bubble.gni
index 97bb5bc..6409638 100644
--- a/ui/webui/resources/cr_components/help_bubble/help_bubble.gni
+++ b/ui/webui/resources/cr_components/help_bubble/help_bubble.gni
@@ -22,6 +22,7 @@
 _non_web_component_files = [
   "help_bubble_mixin.ts",
   "help_bubble_proxy.ts",
+  "help_bubble_controller.ts",
 ]
 
 mojo_files = [ "help_bubble.mojom-webui.js" ]
diff --git a/ui/webui/resources/cr_components/help_bubble/help_bubble.ts b/ui/webui/resources/cr_components/help_bubble/help_bubble.ts
index 68350ca8..ac32c73 100644
--- a/ui/webui/resources/cr_components/help_bubble/help_bubble.ts
+++ b/ui/webui/resources/cr_components/help_bubble/help_bubble.ts
@@ -33,13 +33,13 @@
 export const HELP_BUBBLE_TIMED_OUT_EVENT = 'help-bubble-timed-out';
 
 export type HelpBubbleDismissedEvent = CustomEvent<{
-  anchorId: string,
+  nativeId: any,
   fromActionButton: boolean,
   buttonIndex?: number,
 }>;
 
 export type HelpBubbleTimedOutEvent = CustomEvent<{
-  anchorId: string,
+  nativeId: any,
 }>;
 
 export interface HelpBubbleElement {
@@ -68,7 +68,7 @@
 
   static get properties() {
     return {
-      anchorId: {
+      nativeId: {
         type: String,
         value: '',
         reflectToAttribute: true,
@@ -81,7 +81,7 @@
     };
   }
 
-  anchorId: string;
+  nativeId: any;
   bodyText: string;
   titleText: string;
   closeButtonAltText: string;
@@ -96,7 +96,7 @@
   timeoutTimerId: number|null = null;
 
   /**
-   * HTMLElement corresponding to |this.anchorId|.
+   * HTMLElement corresponding to |this.nativeId|.
    */
   private anchorElement_: HTMLElement|null = null;
 
@@ -109,7 +109,9 @@
   /**
    * Shows the bubble.
    */
-  show() {
+  show(anchorElement: HTMLElement) {
+    this.anchorElement_ = anchorElement;
+
     // Set up the progress track.
     if (this.progress) {
       this.progressData_ = new Array(this.progress.total);
@@ -120,12 +122,9 @@
     this.closeButtonTabIndex =
         this.buttons.length ? this.buttons.length + 2 : 1;
 
-    this.anchorElement_ =
-        this.parentElement!.querySelector<HTMLElement>(`#${this.anchorId}`)!;
     assert(
         this.anchorElement_,
-        'Tried to show a help bubble but couldn\'t find element with id ' +
-            this.anchorId);
+        'Tried to show a help bubble but anchorElement does not exist');
 
     // Reset the aria-hidden attribute as screen readers need to access the
     // contents of an opened bubble.
@@ -138,7 +137,7 @@
       const timedOutCallback = () => {
         this.dispatchEvent(new CustomEvent(HELP_BUBBLE_TIMED_OUT_EVENT, {
           detail: {
-            anchorId: this.anchorId,
+            nativeId: this.nativeId,
           },
         }));
       };
@@ -190,10 +189,10 @@
   }
 
   private dismiss_() {
-    assert(this.anchorId, 'Dismiss: expected help bubble to have an anchor.');
+    assert(this.nativeId, 'Dismiss: expected help bubble to have a native id.');
     this.dispatchEvent(new CustomEvent(HELP_BUBBLE_DISMISSED_EVENT, {
       detail: {
-        anchorId: this.anchorId,
+        nativeId: this.nativeId,
         fromActionButton: false,
       },
     }));
@@ -230,15 +229,15 @@
 
   private onButtonClick_(e: DomRepeatEvent<HelpBubbleButtonParams>) {
     assert(
-        this.anchorId,
-        'Action button clicked: expected help bubble to have an anchor.');
+        this.nativeId,
+        'Action button clicked: expected help bubble to have a native ID.');
     // There is no access to the model index here due to limitations of
     // dom-repeat. However, the index is stored in the node's identifier.
     const index: number = parseInt(
         (e.target as Element).id.substring(ACTION_BUTTON_ID_PREFIX.length));
     this.dispatchEvent(new CustomEvent(HELP_BUBBLE_DISMISSED_EVENT, {
       detail: {
-        anchorId: this.anchorId,
+        nativeId: this.nativeId,
         fromActionButton: true,
         buttonIndex: index,
       },
diff --git a/ui/webui/resources/cr_components/help_bubble/help_bubble_controller.ts b/ui/webui/resources/cr_components/help_bubble/help_bubble_controller.ts
new file mode 100644
index 0000000..da5ebc0
--- /dev/null
+++ b/ui/webui/resources/cr_components/help_bubble/help_bubble_controller.ts
@@ -0,0 +1,120 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {assert} from 'chrome://resources/js/assert_ts.js';
+
+import {HelpBubbleElement} from './help_bubble.js';
+import {HelpBubbleParams} from './help_bubble.mojom-webui.js';
+
+/**
+ * HelpBubble controller class
+ * - There should exist only one HelpBubble instance for each nativeId
+ * - The mapping between nativeId and htmlId is held within this instance
+ * - The rest of the parameters are passed to createBubble
+ */
+export class HelpBubbleController {
+  private nativeId_: string;
+  private root_: ShadowRoot;
+  private anchor_: HTMLElement|null = null;
+  private showing_: boolean = false;
+  private bubble_: HelpBubbleElement|null = null;
+
+  constructor(nativeId: string, root: ShadowRoot) {
+    assert(nativeId && root);
+
+    this.nativeId_ = nativeId;
+    this.root_ = root;
+  }
+
+  isShowing() {
+    return this.showing_;
+  }
+
+  canShow() {
+    return this.hasAnchor();
+  }
+
+  hasAnchor() {
+    return !!this.anchor_;
+  }
+
+  getAnchor() {
+    return this.anchor_;
+  }
+
+  getNativeId() {
+    return this.nativeId_;
+  }
+
+  trackId(idString: string): boolean {
+    assert(!this.anchor_);
+
+    const anchor = this.root_.querySelector<HTMLElement>(`#${idString}`);
+    if (!anchor) {
+      return false;
+    }
+    anchor.dataset['nativeId'] = this.nativeId_;
+    this.anchor_ = anchor;
+    return true;
+  }
+
+  hasElement() {
+    return !!this.bubble_;
+  }
+
+  getElement() {
+    return this.bubble_;
+  }
+
+  show() {
+    if (!(this.bubble_ && this.anchor_)) {
+      return;
+    }
+    this.bubble_.show(this.anchor_);
+    this.anchor_.focus();
+    this.showing_ = true;
+  }
+
+  hide() {
+    if (!this.bubble_) {
+      return;
+    }
+    this.bubble_.hide();
+    this.bubble_.remove();
+    this.bubble_ = null;
+    this.showing_ = false;
+  }
+
+  createBubble(params: HelpBubbleParams): HelpBubbleElement {
+    assert(this.anchor_);
+
+    this.bubble_ = document.createElement('help-bubble');
+    this.bubble_.nativeId = this.nativeId_;
+    this.bubble_.position = params.position;
+    this.bubble_.closeButtonAltText = params.closeButtonAltText;
+    this.bubble_.bodyText = params.bodyText;
+    this.bubble_.bodyIconName = params.bodyIconName || null;
+    this.bubble_.bodyIconAltText = params.bodyIconAltText;
+    this.bubble_.forceCloseButton = params.forceCloseButton;
+    this.bubble_.titleText = params.titleText || '';
+    this.bubble_.progress = params.progress || null;
+    this.bubble_.buttons = params.buttons;
+
+    if (params.timeout) {
+      this.bubble_.timeoutMs = Number(params.timeout!.microseconds / 1000n);
+      assert(this.bubble_.timeoutMs > 0);
+    }
+
+    assert(
+        !this.bubble_.progress ||
+        this.bubble_.progress.total >= this.bubble_.progress.current);
+
+    // insert after anchor - if nextSibling is null, bubble will
+    // be added as the last child of parentNode
+    this.anchor_!.parentNode!.insertBefore(
+        this.bubble_, this.anchor_!.nextSibling);
+
+    return this.bubble_;
+  }
+}
diff --git a/ui/webui/resources/cr_components/help_bubble/help_bubble_mixin.ts b/ui/webui/resources/cr_components/help_bubble/help_bubble_mixin.ts
index 2975012..cbe40d4 100644
--- a/ui/webui/resources/cr_components/help_bubble/help_bubble_mixin.ts
+++ b/ui/webui/resources/cr_components/help_bubble/help_bubble_mixin.ts
@@ -24,6 +24,7 @@
 
 import {HELP_BUBBLE_DISMISSED_EVENT, HELP_BUBBLE_TIMED_OUT_EVENT, HelpBubbleDismissedEvent, HelpBubbleElement} from './help_bubble.js';
 import {HelpBubbleClientCallbackRouter, HelpBubbleClosedReason, HelpBubbleHandlerInterface, HelpBubbleParams} from './help_bubble.mojom-webui.js';
+import {HelpBubbleController} from './help_bubble_controller.js';
 import {HelpBubbleProxyImpl} from './help_bubble_proxy.js';
 
 type Constructor<T> = new (...args: any[]) => T;
@@ -42,16 +43,10 @@
          * Example entry:
          *   "kHeightenSecuritySettingsElementId" => "toggleSecureMode"
          */
-        private helpBubbleNativeToTargetId_: Map<string, string> = new Map();
+        private helpBubbleControllerById_: Map<string, HelpBubbleController> =
+            new Map();
         private listenerIds_: number[] = [];
-        private helpBubbleTargetObserver_: IntersectionObserver|null = null;
-        /**
-         * Tracks the last known visibility of any element registered via
-         * `registerHelpBubbleIdentifier()` and tracked by
-         * `helpBubbleTargetObserver_`. Maps from HTML id to last known
-         * visibility.
-         */
-        private targetVisibility_: Map<string, boolean> = new Map();
+        private helpBubbleAnchorObserver_: IntersectionObserver|null = null;
         private dismissedEventTracker_: EventTracker = new EventTracker();
 
         constructor(...args: any[]) {
@@ -75,20 +70,20 @@
               router.hideHelpBubble.addListener(
                   this.onHideHelpBubble_.bind(this)));
 
-          this.helpBubbleTargetObserver_ =
-              new IntersectionObserver((entries, _observer) => {
-                for (const entry of entries) {
-                  this.onTargetVisibilityChanged_(
-                      entry.target, entry.isIntersecting);
-                }
-              }, {root: document.body});
+          this.helpBubbleAnchorObserver_ = new IntersectionObserver(
+              entries => entries.forEach(
+                  ({target, isIntersecting}) => this.onAnchorVisibilityChanged_(
+                      target as HTMLElement, isIntersecting)),
+              {root: document.body});
 
           // When the component is connected, if the target elements were
           // already registered, they should be observed now. Any targets
           // registered from this point forward will observed on registration.
-          for (const htmlId of this.helpBubbleNativeToTargetId_.values()) {
-            this.observeTarget_(htmlId);
-          }
+          this.controllers.forEach(ctrl => this.observeControllerAnchor_(ctrl));
+        }
+
+        private get controllers(): HelpBubbleController[] {
+          return Array.from(this.helpBubbleControllerById_.values());
         }
 
         override disconnectedCallback() {
@@ -98,11 +93,10 @@
             this.helpBubbleCallbackRouter_.removeListener(listenerId);
           }
           this.listenerIds_ = [];
-          assert(this.helpBubbleTargetObserver_);
-          this.helpBubbleTargetObserver_.disconnect();
-          this.helpBubbleTargetObserver_ = null;
-          this.helpBubbleNativeToTargetId_.clear();
-          this.targetVisibility_.clear();
+          assert(this.helpBubbleAnchorObserver_);
+          this.helpBubbleAnchorObserver_.disconnect();
+          this.helpBubbleAnchorObserver_ = null;
+          this.helpBubbleControllerById_.clear();
         }
 
         /**
@@ -117,16 +111,20 @@
          *
          * See README.md for full instructions.
          */
-        registerHelpBubbleIdentifier(nativeId: string, htmlId: string): void {
-          assert(!this.helpBubbleNativeToTargetId_.has(nativeId));
-          this.helpBubbleNativeToTargetId_.set(nativeId, htmlId);
+        registerHelpBubbleIdentifier(nativeId: string, htmlId: string):
+            HelpBubbleController {
+          assert(!this.helpBubbleControllerById_.has(nativeId));
+          const controller =
+              new HelpBubbleController(nativeId, this.shadowRoot!);
+          controller.trackId(htmlId);
+          this.helpBubbleControllerById_.set(nativeId, controller);
           // This can be called before or after `connectedCallback()`, so if the
           // component isn't connected and the observer set up yet, delay
           // observation until it is.
-          if (!this.helpBubbleTargetObserver_) {
-            return;
+          if (this.helpBubbleAnchorObserver_) {
+            this.observeControllerAnchor_(controller);
           }
-          this.observeTarget_(htmlId);
+          return controller;
         }
 
         /**
@@ -134,15 +132,51 @@
          * component.
          */
         isHelpBubbleShowing(): boolean {
-          return !!this.shadowRoot!.querySelector('help-bubble');
+          return this.controllers.some(ctrl => ctrl.isShowing());
         }
 
         /**
-         * Returns whether a help bubble anchored to element with HTML id
-         * `anchorId` is currently showing.
+         * Returns whether any help bubble is currently showing on a tag
+         * with this id.
          */
-        isHelpBubbleShowingFor(anchorId: string): boolean {
-          return !!this.getHelpBubbleFor_(anchorId);
+        isHelpBubbleShowingForTesting(id: string): boolean {
+          const ctrls =
+              this.controllers.filter(this.filterMatchingIdForTesting_(id));
+          return !!ctrls[0];
+        }
+
+        /**
+         * Returns the help bubble currently showing on a tag with this
+         * id.
+         */
+        getHelpBubbleForTesting(id: string): HelpBubbleElement|null {
+          const ctrls =
+              this.controllers.filter(this.filterMatchingIdForTesting_(id));
+          return ctrls[0] ? ctrls[0].getElement() : null;
+        }
+
+        private filterMatchingIdForTesting_(anchorId: string):
+            (ctrl: HelpBubbleController) => boolean {
+          return ctrl => ctrl.isShowing() && ctrl.getAnchor() !== null &&
+              ctrl.getAnchor()!.id === anchorId;
+        }
+
+        /**
+         * Returns whether a help bubble can be shown
+         * This requires:
+         * - the controller is in a state to be shown, e.g. `.canShow()`
+         * - no other showing bubbles are anchored to the same element
+         */
+        canShowHelpBubble(controller: HelpBubbleController): boolean {
+          if (!controller.canShow()) {
+            return false;
+          }
+          const anchor = controller.getAnchor();
+          // Make sure no other help bubble is showing for this anchor.
+          const anchorIsUsed = this.controllers.some(
+              otherCtrl =>
+                  otherCtrl.isShowing() && otherCtrl.getAnchor() === anchor);
+          return !anchorIsUsed;
         }
 
         /**
@@ -150,20 +184,10 @@
          * with id `anchorId`. Note that `params.nativeIdentifier` is ignored by
          * this method, since the anchor is already specified.
          */
-        showHelpBubble(anchorId: string, params: HelpBubbleParams): void {
-          const oldBubble = this.getHelpBubbleFor_(anchorId);
-          assert(
-              !oldBubble,
-              'Can\'t show help bubble; ' +
-                  'bubble already showing and anchored to ' + anchorId);
-
-          const bubble = document.createElement('help-bubble');
-          const anchor = this.findAnchorElement_(anchorId);
-          assert(anchor, 'Help bubble anchor element not found ' + anchorId);
-
-          // insert after anchor - if nextSibling is null, bubble will
-          // be added as the last child of parentNode
-          anchor.parentNode!.insertBefore(bubble, anchor.nextSibling);
+        showHelpBubble(
+            controller: HelpBubbleController, params: HelpBubbleParams): void {
+          assert(this.canShowHelpBubble(controller), 'Can\'t show help bubble');
+          const bubble = controller.createBubble(params);
 
           this.dismissedEventTracker_.add(
               bubble, HELP_BUBBLE_DISMISSED_EVENT,
@@ -172,41 +196,26 @@
               bubble, HELP_BUBBLE_TIMED_OUT_EVENT,
               this.onHelpBubbleTimedOut_.bind(this));
 
-          bubble.anchorId = anchorId;
-          bubble.closeButtonAltText = params.closeButtonAltText;
-          bubble.position = params.position;
-          bubble.bodyText = params.bodyText;
-          bubble.bodyIconName = params.bodyIconName || null;
-          bubble.bodyIconAltText = params.bodyIconAltText;
-          bubble.forceCloseButton = params.forceCloseButton;
-          bubble.titleText = params.titleText || '';
-          bubble.progress = params.progress || null;
-          bubble.buttons = params.buttons;
-          if (params.timeout) {
-            bubble.timeoutMs = Number(params.timeout!.microseconds / 1000n);
-            assert(bubble.timeoutMs > 0);
-          }
-
-          assert(
-              !bubble.progress ||
-              bubble.progress.total >= bubble.progress.current);
-          bubble.show();
-          anchor!.focus();
+          controller.show();
         }
 
         /**
          * Hides a help bubble anchored to element with id `anchorId` if there
          * is one. Returns true if a bubble was hidden.
          */
-        hideHelpBubble(anchorId: string): boolean {
-          const bubble = this.getHelpBubbleFor_(anchorId);
-          if (!bubble) {
+        hideHelpBubble(nativeId: string): boolean {
+          const bubble = this.helpBubbleControllerById_.get(nativeId);
+          if (!bubble || !bubble.hasElement()) {
+            // `!bubble` means this identifier is not handled by this mixin
             return false;
           }
+
           this.dismissedEventTracker_.remove(
-              bubble, HELP_BUBBLE_DISMISSED_EVENT);
+              bubble.getElement()!, HELP_BUBBLE_DISMISSED_EVENT);
+          this.dismissedEventTracker_.remove(
+              bubble.getElement()!, HELP_BUBBLE_TIMED_OUT_EVENT);
+
           bubble.hide();
-          bubble.remove();
           return true;
         }
 
@@ -220,12 +229,11 @@
          * TODO(crbug.com/1376262): Figure out how to automatically send the
          * activated event when an anchor element is clicked.
          */
-        notifyHelpBubbleAnchorActivated(anchorId: string): boolean {
-          if (!this.targetVisibility_.get(anchorId)) {
+        notifyHelpBubbleAnchorActivated(nativeId: string): boolean {
+          const bubble = this.helpBubbleControllerById_.get(nativeId);
+          if (!bubble || !bubble.isShowing()) {
             return false;
           }
-          const nativeId = this.getNativeIdForAnchor_(anchorId);
-          assert(nativeId);
           this.helpBubbleHandler_.helpBubbleAnchorActivated(nativeId);
           return true;
         }
@@ -240,26 +248,21 @@
          * ui::CustomElementEventType declared in the browser code.
          */
         notifyHelpBubbleAnchorCustomEvent(
-            anchorId: string, customEvent: string): boolean {
-          if (!this.targetVisibility_.get(anchorId)) {
+            nativeId: string, customEvent: string): boolean {
+          const bubble = this.helpBubbleControllerById_.get(nativeId);
+          if (!bubble || !bubble.isShowing()) {
             return false;
           }
-          const nativeId = this.getNativeIdForAnchor_(anchorId);
-          assert(nativeId);
           this.helpBubbleHandler_.helpBubbleAnchorCustomEvent(
               nativeId, customEvent);
           return true;
         }
 
-        private onTargetVisibilityChanged_(
-            target: Element, isVisible: boolean) {
-          if (isVisible === this.targetVisibility_.get(target.id)) {
-            return;
-          }
-          this.targetVisibility_.set(target.id, isVisible);
-          const hidden = this.hideHelpBubble(target.id);
-          const nativeId = this.getNativeIdForAnchor_(target.id);
+        private onAnchorVisibilityChanged_(
+            target: HTMLElement, isVisible: boolean) {
+          const nativeId = target.dataset['nativeId'];
           assert(nativeId);
+          const hidden = this.hideHelpBubble(nativeId);
           if (hidden) {
             this.helpBubbleHandler_.helpBubbleClosed(
                 nativeId, HelpBubbleClosedReason.kPageChanged);
@@ -269,78 +272,60 @@
         }
 
         /**
-         * Observes visibility for element with id `htmlId` to properly send
-         * visibility changed events to the associated handler.
+         * This event is emitted by the mojo router
          */
-        private observeTarget_(htmlId: string) {
-          assert(this.helpBubbleTargetObserver_);
-          const anchor = this.findAnchorElement_(htmlId);
-          assert(anchor, 'Help bubble anchor not found; expected id ' + htmlId);
-          this.helpBubbleTargetObserver_.observe(anchor);
+        private observeControllerAnchor_(controller: HelpBubbleController) {
+          assert(this.helpBubbleAnchorObserver_);
+          const anchor = controller.getAnchor();
+          assert(anchor, 'Help bubble does not have anchor');
+          this.helpBubbleAnchorObserver_.observe(anchor);
         }
 
         private onShowHelpBubble_(params: HelpBubbleParams): void {
-          if (!this.helpBubbleNativeToTargetId_.has(params.nativeIdentifier)) {
+          if (!this.helpBubbleControllerById_.has(params.nativeIdentifier)) {
             // Identifier not handled by this mixin.
             return;
           }
-
-          const anchorId: string =
-              this.helpBubbleNativeToTargetId_.get(params.nativeIdentifier)!;
-          this.showHelpBubble(anchorId, params);
+          const bubble =
+              this.helpBubbleControllerById_.get(params.nativeIdentifier)!;
+          this.showHelpBubble(bubble, params);
         }
 
+        /**
+         * This event is emitted by the mojo router
+         */
         private onToggleHelpBubbleFocusForAccessibility_(nativeId: string) {
-          if (!this.helpBubbleNativeToTargetId_.has(nativeId)) {
+          if (!this.helpBubbleControllerById_.has(nativeId)) {
             // Identifier not handled by this mixin.
             return;
           }
 
-          const anchorId = this.helpBubbleNativeToTargetId_.get(nativeId)!;
-          const bubble = this.getHelpBubbleFor_(anchorId);
+          const bubble = this.helpBubbleControllerById_.get(nativeId)!;
           if (bubble) {
-            const anchor = bubble.getAnchorElement();
+            const anchor = bubble.getAnchor();
             if (anchor) {
               anchor.focus();
             }
           }
         }
 
+        /**
+         * This event is emitted by the mojo router
+         */
         private onHideHelpBubble_(nativeId: string): void {
-          if (!this.helpBubbleNativeToTargetId_.has(nativeId)) {
-            // Identifier not handled by this mixin.
-            return;
-          }
-
-          this.hideHelpBubble(this.helpBubbleNativeToTargetId_.get(nativeId)!);
-        }
-
-        private findAnchorElement_(anchorId: string): HTMLElement|null {
-          return this.shadowRoot!.querySelector<HTMLElement>(`#${anchorId}`);
-        }
-
-        private getNativeIdForAnchor_(anchorId: string): string|null {
-          for (const [nativeId, htmlId] of this.helpBubbleNativeToTargetId_) {
-            if (htmlId === anchorId) {
-              return nativeId;
-            }
-          }
-          return null;
+          // This may be called with nativeId not handled by this mixin
+          // Ignore return value to silently fail
+          this.hideHelpBubble(nativeId);
         }
 
         /**
-         * Returns a help bubble element anchored to element with HTML id
-         * `anchorId`, or null if none.
+         * This event is emitted by the help-bubble component
          */
-        private getHelpBubbleFor_(anchorId: string): HelpBubbleElement|null {
-          return this.shadowRoot!.querySelector(
-              `help-bubble[anchor-id='${anchorId}']`);
-        }
-
         private onHelpBubbleDismissed_(e: HelpBubbleDismissedEvent) {
-          const hidden = this.hideHelpBubble(e.detail.anchorId);
+          const nativeId = e.detail.nativeId;
+          assert(nativeId);
+          const hidden = this.hideHelpBubble(nativeId);
           assert(hidden);
-          const nativeId = this.getNativeIdForAnchor_(e.detail.anchorId);
           if (nativeId) {
             if (e.detail.fromActionButton) {
               this.helpBubbleHandler_.helpBubbleButtonPressed(
@@ -352,10 +337,15 @@
           }
         }
 
+        /**
+         * This event is emitted by the help-bubble component
+         */
         private onHelpBubbleTimedOut_(e: HelpBubbleDismissedEvent) {
-          const hidden = this.hideHelpBubble(e.detail.anchorId);
+          const nativeId = e.detail.nativeId;
+          const bubble = this.helpBubbleControllerById_.get(nativeId);
+          assert(bubble);
+          const hidden = this.hideHelpBubble(nativeId);
           assert(hidden);
-          const nativeId = this.getNativeIdForAnchor_(e.detail.anchorId);
           if (nativeId) {
             this.helpBubbleHandler_.helpBubbleClosed(
                 nativeId, HelpBubbleClosedReason.kTimedOut);
@@ -367,11 +357,14 @@
     });
 
 export interface HelpBubbleMixinInterface {
-  registerHelpBubbleIdentifier(nativeId: string, htmlId: string): void;
+  registerHelpBubbleIdentifier(nativeId: string, htmlId: string):
+      HelpBubbleController;
   isHelpBubbleShowing(): boolean;
-  isHelpBubbleShowingFor(anchorId: string): boolean;
-  showHelpBubble(anchorId: string, params: HelpBubbleParams): void;
-  hideHelpBubble(anchorId: string): boolean;
+  isHelpBubbleShowingForTesting(id: string): boolean;
+  getHelpBubbleForTesting(id: string): HelpBubbleElement|null;
+  showHelpBubble(controller: HelpBubbleController, params: HelpBubbleParams):
+      void;
+  hideHelpBubble(nativeId: string): boolean;
   notifyHelpBubbleAnchorActivated(anchorId: string): boolean;
   notifyHelpBubbleAnchorCustomEvent(anchorId: string, customEvent: string):
       boolean;
diff --git a/ui/webui/resources/images/settings.svg b/ui/webui/resources/images/settings.svg
deleted file mode 100644
index 239fd71..0000000
--- a/ui/webui/resources/images/settings.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 48 48"><path d="M0 0h48v48H0z" fill="none"/><path d="M38.86 25.95c.08-.64.14-1.29.14-1.95s-.06-1.31-.14-1.95l4.23-3.31c.38-.3.49-.84.24-1.28l-4-6.93c-.25-.43-.77-.61-1.22-.43l-4.98 2.01c-1.03-.79-2.16-1.46-3.38-1.97L29 4.84c-.09-.47-.5-.84-1-.84h-8c-.5 0-.91.37-.99.84l-.75 5.3a14.8 14.8 0 0 0-3.38 1.97L9.9 10.1a1 1 0 0 0-1.22.43l-4 6.93c-.25.43-.14.97.24 1.28l4.22 3.31C9.06 22.69 9 23.34 9 24s.06 1.31.14 1.95l-4.22 3.31c-.38.3-.49.84-.24 1.28l4 6.93c.25.43.77.61 1.22.43l4.98-2.01c1.03.79 2.16 1.46 3.38 1.97l.75 5.3c.08.47.49.84.99.84h8c.5 0 .91-.37.99-.84l.75-5.3a14.8 14.8 0 0 0 3.38-1.97l4.98 2.01a1 1 0 0 0 1.22-.43l4-6.93c.25-.43.14-.97-.24-1.28l-4.22-3.31zM24 31c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></svg>
\ No newline at end of file
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java
index aedcb108..86c97627 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java
@@ -10,7 +10,6 @@
 import android.os.RemoteException;
 
 import org.chromium.base.Callback;
-import org.chromium.base.Function;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.components.embedder_support.util.UrlUtilities;
 import org.chromium.components.external_intents.ExternalNavigationDelegate;
@@ -23,6 +22,7 @@
 import org.chromium.weblayer_private.interfaces.ExternalIntentInIncognitoUserDecision;
 
 import java.util.List;
+import java.util.function.Function;
 
 /**
  * WebLayer's implementation of the {@link ExternalNavigationDelegate}.