diff --git a/DEPS b/DEPS
index 96a4ecc..f87e8925 100644
--- a/DEPS
+++ b/DEPS
@@ -297,15 +297,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'fc260b97046d28a82403248ddd561f7cc396ed58',
+  'skia_revision': 'e38ad41e26b0543bc0acea308068e31bfaf7574d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'f44131b71f7cf895fdb091a6e5248cd5ce1b68d0',
+  'v8_revision': '7a98bc62136653c82fd8379ad2cbb0438ed022bc',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'caf2b4279bfbdddddc758fc668cf6acd10b43c58',
+  'angle_revision': '6fde3568a14f816d235a432dc099be4a4dd16d68',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -376,7 +376,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': '38be459efd3e4d1ee12c5e7aefc3aef40c37f649',
+  'devtools_frontend_revision': 'bdb9c727e229eba825512e504b4e58f9927c1181',
   # 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.
@@ -412,7 +412,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': 'cf2ac51987c49d10f1d5da210a3ed369f649d10d',
+  'dawn_revision': 'd403bc88742e296c769eacddebe25d849e7078ed',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -440,7 +440,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling nearby
   # and whatever else without interference from each other.
-  'nearby_revision': '5b7bb37d41f45635fcb848841524cb18664336dd',
+  'nearby_revision': '9dc4b83ca039bd24ac3d0655dd455e47ed4e8644',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling securemessage
   # and whatever else without interference from each other.
@@ -952,7 +952,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'SK5OSmpPVWJZugMDYiKQz2ERMeOTqQVSdK-sEGm96JcC',
+          'version': 'qxpDCS74DG-uhFzfz-J5sHBgIkJXPy-S_Kpqwyyd-u8C',
       },
     ],
     'condition': 'checkout_android',
@@ -1184,7 +1184,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'e19b7624efd703aae3e29521cb902dd516df4ae2',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '19b3eb5adbe00e9da40375cb5dc47380a46f3041',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1693,7 +1693,7 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@186a4d4b9dea4d90b8b182d650af7ec41f732d65',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@1b46e43d5ccc13a6a33de74bc226daf75f4a38ad',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
@@ -1729,10 +1729,10 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '44e4c8770158c505b03ee7feafa4859d083b0912',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'd82d4e1630c29c03bd2420deac7e01386959a12a',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '4827c0c40f71d9c7b8a5034888a81516e45a71ab',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'cc9fce39fc4fa638df57b274bd81f8323e890dac',
+    Var('webrtc_git') + '/src.git' + '@' + '72c363c44a389cb6fbd1aa1c1adce45222595a98',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1762,7 +1762,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/linux-amd64',
-          'version': 'eVmrBHTaHLBRrBHBIagAjRi84M8Pih7goWAjl0ZL9H0C',
+          'version': 'BcL4zQgD0tZoFzhWm37NnERAPLdbeERfbY_SSBQ3ba4C',
         },
       ],
       'dep_type': 'cipd',
@@ -1772,7 +1772,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/windows-amd64',
-          'version': 'aYli_YA93vex9TPItiLM1AcLs64FzefvhXxh2aHEvJsC',
+          'version': '1l0XEVvr2qVUdGYrjLN9Gkt6qfv8KsXM52B8MKDShmEC',
         },
       ],
       'dep_type': 'cipd',
@@ -1783,7 +1783,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/mac-amd64',
-          'version': '3fnB8n0m7xQ9X4SWg4rYgZksJ4YFew0fj6ftsyHzbSwC',
+          'version': '8DiQ6WFPrEn56-jwyQmU4EMXFvf7_-8SYjVD2hHHmZMC',
         },
       ],
       'dep_type': 'cipd',
@@ -1794,7 +1794,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/mac-arm64',
-          'version': 'J_MizgwQbTOCG1ZKfGQJRXm-F2Ey8P3M7Dl5WxYKEwwC',
+          'version': 'lJ8l4RCPxwrg_f-Z9Lnu3Ma3uRlbRbAcdQA7xwpIzNUC',
         },
       ],
       'dep_type': 'cipd',
@@ -1805,7 +1805,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0bef0c0f8528308b015f048be5c0dd37bbba4ced',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@210f643c04c80f1c4719741de8bb478f87f3ebb2',
     'condition': 'checkout_src_internal',
   },
 
@@ -1824,7 +1824,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/eche_app/app',
-        'version': 'uWK-hoCeXK1wUicxHb7YlPKmGDebjbXvVHcCkFbCnFkC',
+        'version': 'JJXXcwB3ER61dMBrjnfPvxV8DfhgpwIE34DUr3optygC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1846,7 +1846,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'tPxFoWKjR_JjaBU-gLKVLwRG_dCZi4fltHFR4KImtPAC',
+        'version': 'f03cQfrkjG1toP0-ztpp2OrVQKZgI-VOkgzsfZPuPxEC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1857,7 +1857,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'qP7RAVop7wcvb7oCLU0qJE_yTM8UregFFXrrrQVxIhgC',
+        'version': 'jZcg7lCa6UapDLMSEZv6RKGFaKc2myQmUimwS9mUwjIC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index f0c140ea..4fe36e3 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -661,12 +661,17 @@
   // WebView Classic lets app override only top level about:blank navigations.
   // So we filter out non-top about:blank navigations here.
   //
+  // The uuid-in-package scheme is used for subframe navigation with WebBundles
+  // (https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading-opaque-origin-iframes.md),
+  // so treat it in the same way as http(s).
+  //
   // Note: about:blank navigations are not received in this path at the moment,
   // they use the old SYNC IPC path as they are not handled by network stack.
   // However, the old path should be removed in future.
   if (!is_outermost_main_frame &&
       (gurl.SchemeIs(url::kHttpScheme) || gurl.SchemeIs(url::kHttpsScheme) ||
-       gurl.SchemeIs(url::kAboutScheme)))
+       gurl.SchemeIs(url::kAboutScheme) ||
+       gurl.SchemeIs(url::kUuidInPackageScheme)))
     return true;
 
   WebContents* web_contents =
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldOverrideUrlLoadingTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldOverrideUrlLoadingTest.java
index d9abf4f..8c0550b 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldOverrideUrlLoadingTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldOverrideUrlLoadingTest.java
@@ -643,6 +643,27 @@
         Assert.assertFalse(mShouldOverrideUrlLoadingHelper.isOutermostMainFrame());
     }
 
+    @Test
+    @SmallTest
+    @Feature({"AndroidWebView", "Navigation"})
+    public void testNotCalledForIframeUuidInPackageSchemeNavigations() throws Throwable {
+        standardSetup();
+
+        final String uuidInPackageSchemeUrl =
+                "uuid-in-package:f81d4fae-7dec-11d0-a765-00a0c91e6bf6";
+        final String pageWithIframeUrl = addPageToTestServer("/iframe_intercept.html",
+                makeHtmlPageFrom("", "<iframe src=\"" + uuidInPackageSchemeUrl + "\" />"));
+
+        final int shouldOverrideUrlLoadingCallCount =
+                mShouldOverrideUrlLoadingHelper.getCallCount();
+
+        mActivityTestRule.loadUrlSync(
+                mAwContents, mContentsClient.getOnPageFinishedHelper(), pageWithIframeUrl);
+
+        Assert.assertEquals(
+                shouldOverrideUrlLoadingCallCount, mShouldOverrideUrlLoadingHelper.getCallCount());
+    }
+
     /**
      * Worker method for the various redirect tests.
      *
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 7df9b25..241a0b5 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1839,6 +1839,8 @@
     "wallpaper/wallpaper_constants.h",
     "wallpaper/wallpaper_controller_impl.cc",
     "wallpaper/wallpaper_controller_impl.h",
+    "wallpaper/wallpaper_metrics_manager.cc",
+    "wallpaper/wallpaper_metrics_manager.h",
     "wallpaper/wallpaper_pref_manager.cc",
     "wallpaper/wallpaper_pref_manager.h",
     "wallpaper/wallpaper_utils/wallpaper_calculated_colors.cc",
diff --git a/ash/components/trial_group/OWNERS b/ash/components/trial_group/OWNERS
index 84b19d8..deb6decb 100644
--- a/ash/components/trial_group/OWNERS
+++ b/ash/components/trial_group/OWNERS
@@ -1,3 +1,2 @@
 claudiomagni@chromium.org
-jiameng@chromium.org
 charleszhao@chromium.org
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index d51a4e9..8ce6350 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -700,7 +700,7 @@
 // Enables the System Web App (SWA) of Face ML.
 // This app needs both CrOS and hardware support (Face Auth Camera and System
 // Face Auth Service), therefore we only enable it on these eligible devices.
-const base::Feature kFaceMlApp{"FaceMlApp", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kFaceMLApp{"FaceMLApp", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Enables policy that controls feature to allow Family Link accounts on school
 // owned devices.
@@ -1494,7 +1494,7 @@
 
 // Enables or disables enterprise policy control for SIM PIN Lock.
 const base::Feature kSimLockPolicy{"SimLockPolicy",
-                                   base::FEATURE_DISABLED_BY_DEFAULT};
+                                   base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Uses experimental component version for smart dim.
 const base::Feature kSmartDimExperimentalComponent{
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index e25a669b..df19060 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -298,7 +298,7 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kExoOrdinalMotion;
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kExperimentalRgbKeyboardPatterns;
-COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kFaceMlApp;
+COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kFaceMLApp;
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kFamilyLinkOnSchoolDevice;
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kFastPair;
diff --git a/ash/frame/caption_buttons/frame_size_button_unittest.cc b/ash/frame/caption_buttons/frame_size_button_unittest.cc
index 120eb2f..e86f6c9 100644
--- a/ash/frame/caption_buttons/frame_size_button_unittest.cc
+++ b/ash/frame/caption_buttons/frame_size_button_unittest.cc
@@ -28,6 +28,7 @@
 #include "ui/events/gesture_detection/gesture_configuration.h"
 #include "ui/events/test/event_generator.h"
 #include "ui/gfx/vector_icon_types.h"
+#include "ui/views/widget/any_widget_observer.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 #include "ui/views/window/caption_button_layout_constants.h"
@@ -656,6 +657,24 @@
 
   ~MultitaskMenuTest() override = default;
 
+  void ShowMultitaskMenu() {
+    DCHECK(size_button());
+
+    views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{},
+                                         "MultitaskMenuBubbleWidget");
+    static_cast<FrameSizeButton*>(size_button())->ShowMultitaskMenu();
+    views::WidgetDelegate* delegate =
+        waiter.WaitIfNeededAndGet()->widget_delegate();
+    multitask_menu_ = static_cast<MultitaskMenu*>(delegate->AsDialogDelegate());
+
+    // Note that this is sync because we use `views::Widget::CloseNow()` in
+    // `MultitaskMenu.`
+    delegate->RegisterWindowClosingCallback(base::BindOnce(
+        &MultitaskMenuTest::OnMultitaskMenuClosed, base::Unretained(this)));
+  }
+
+  void OnMultitaskMenuClosed() { multitask_menu_ = nullptr; }
+
   void SetUp() override {
     // Ensure float feature is enabled.
     scoped_feature_list_.InitAndEnableFeature(
@@ -663,16 +682,10 @@
     FrameSizeButtonTest::SetUp();
   }
 
-  void ShowMultitaskMenu() {
-    DCHECK(size_button());
-    multitask_menu_ = static_cast<FrameSizeButton*>(size_button())
-                          ->GetMultitaskMenuForTesting();
-  }
-
   MultitaskMenu* multitask_menu() { return multitask_menu_; }
 
  private:
-  MultitaskMenu* multitask_menu_;
+  MultitaskMenu* multitask_menu_ = nullptr;
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
@@ -754,4 +767,13 @@
   EXPECT_TRUE(window_state()->IsFullscreen());
 }
 
+TEST_F(MultitaskMenuTest, MultitaskMenuClosesOnTabletMode) {
+  ShowMultitaskMenu();
+  ASSERT_TRUE(multitask_menu());
+  ASSERT_TRUE(multitask_menu()->GetWidget());
+
+  ash::TabletMode::Get()->SetEnabledForTest(true);
+  EXPECT_FALSE(multitask_menu());
+}
+
 }  // namespace ash
diff --git a/ash/frame/non_client_frame_view_ash.cc b/ash/frame/non_client_frame_view_ash.cc
index 2746a09..f8b3cc9a 100644
--- a/ash/frame/non_client_frame_view_ash.cc
+++ b/ash/frame/non_client_frame_view_ash.cc
@@ -144,13 +144,6 @@
     }
   }
 
-  NonClientFrameViewAsh* GetFrameView() {
-    views::Widget* widget =
-        views::Widget::GetWidgetForNativeWindow(window_state_->window());
-    return static_cast<NonClientFrameViewAsh*>(
-        widget->non_client_view()->frame_view());
-  }
-
   views::Widget* widget_;
   WindowState* window_state_;
   std::unique_ptr<ImmersiveFullscreenController>
diff --git a/ash/public/cpp/wallpaper/wallpaper_controller_observer.h b/ash/public/cpp/wallpaper/wallpaper_controller_observer.h
index e323e8a..a141a21 100644
--- a/ash/public/cpp/wallpaper/wallpaper_controller_observer.h
+++ b/ash/public/cpp/wallpaper/wallpaper_controller_observer.h
@@ -6,6 +6,7 @@
 #define ASH_PUBLIC_CPP_WALLPAPER_WALLPAPER_CONTROLLER_OBSERVER_H_
 
 #include "ash/public/cpp/ash_public_export.h"
+#include "ash/public/cpp/wallpaper/online_wallpaper_params.h"
 
 namespace ash {
 
@@ -18,6 +19,9 @@
   WallpaperControllerObserver& operator=(const WallpaperControllerObserver&) =
       delete;
 
+  // Invoked when the online wallpaper changes.
+  virtual void OnOnlineWallpaperSet(const OnlineWallpaperParams& params) {}
+
   // Invoked when the wallpaper is about to change.
   virtual void OnWallpaperChanging() {}
 
diff --git a/ash/style/ash_color_provider.cc b/ash/style/ash_color_provider.cc
index 4bae4d9..8991944 100644
--- a/ash/style/ash_color_provider.cc
+++ b/ash/style/ash_color_provider.cc
@@ -284,7 +284,8 @@
     background_color = GetBackgroundColor();
 
   const bool is_dark = color_utils::IsDark(background_color);
-  const SkColor base_color = is_dark ? SK_ColorWHITE : SK_ColorBLACK;
+  const SkColor base_color =
+      GetColorProvider()->GetColor(kColorAshInkDropOpaqueColor);
   const float opacity = is_dark ? kLightInkDropOpacity : kDarkInkDropOpacity;
   return std::make_pair(base_color, opacity);
 }
diff --git a/ash/wallpaper/wallpaper_controller_impl.cc b/ash/wallpaper/wallpaper_controller_impl.cc
index 235a30d..300c345 100644
--- a/ash/wallpaper/wallpaper_controller_impl.cc
+++ b/ash/wallpaper/wallpaper_controller_impl.cc
@@ -30,6 +30,7 @@
 #include "ash/shell.h"
 #include "ash/shell_delegate.h"
 #include "ash/style/dark_light_mode_controller_impl.h"
+#include "ash/wallpaper/wallpaper_metrics_manager.h"
 #include "ash/wallpaper/wallpaper_pref_manager.h"
 #include "ash/wallpaper/wallpaper_utils/wallpaper_calculated_colors.h"
 #include "ash/wallpaper/wallpaper_utils/wallpaper_color_calculator.h"
@@ -712,6 +713,7 @@
   Shell::Get()->window_tree_host_manager()->AddObserver(this);
   Shell::Get()->AddShellObserver(this);
   theme_observation_.Observe(ui::NativeTheme::GetInstanceForNativeUi());
+  wallpaper_metrics_manager_ = std::make_unique<WallpaperMetricsManager>();
 }
 
 WallpaperControllerImpl::~WallpaperControllerImpl() {
@@ -831,7 +833,6 @@
 
   if (preview_mode) {
     DVLOG(1) << __func__ << " preview_mode=true";
-    base::UmaHistogramBoolean("Ash.Wallpaper.Preview.Show", true);
     for (auto& observer : observers_)
       observer.OnWallpaperPreviewStarted();
   }
@@ -852,9 +853,6 @@
     return;
   }
 
-  UMA_HISTOGRAM_ENUMERATION("Ash.Wallpaper.Type", info.type,
-                            WallpaperType::kCount);
-
   // Cancel any in-flight color calculation because we have a new wallpaper.
   if (color_calculator_) {
     color_calculator_->RemoveObserver(this);
@@ -1120,21 +1118,8 @@
     return;
   }
 
-  if (params.from_user) {
-    // |unit_id| is empty when set by old wallpaper picker.
-    const absl::optional<uint64_t>& unit_id = params.unit_id;
-    if (unit_id.has_value()) {
-      const int unit_id_val = unit_id.value();
-      base::UmaHistogramSparse("Ash.Wallpaper.Image", unit_id_val);
-    }
-    const std::string& collection_id = params.collection_id;
-    // |collection_id| is empty when the wallpaper is automatically refreshed
-    // by old wallpaper app.
-    if (!collection_id.empty()) {
-      const int collection_id_hash = base::PersistentHash(collection_id);
-      base::UmaHistogramSparse("Ash.Wallpaper.Collection", collection_id_hash);
-    }
-  }
+  for (auto& observer : observers_)
+    observer.OnOnlineWallpaperSet(params);
 
   if (params.variants.empty()) {
     // |params.variants| can be empty for users who use the old wallpaper
diff --git a/ash/wallpaper/wallpaper_controller_impl.h b/ash/wallpaper/wallpaper_controller_impl.h
index 06e4705..8ba416a 100644
--- a/ash/wallpaper/wallpaper_controller_impl.h
+++ b/ash/wallpaper/wallpaper_controller_impl.h
@@ -59,6 +59,7 @@
 namespace ash {
 
 class WallpaperColorCalculator;
+class WallpaperMetricsManager;
 class WallpaperPrefManager;
 class WallpaperResizer;
 class WallpaperWindowStateManager;
@@ -766,6 +767,8 @@
 
   base::ObserverList<WallpaperControllerObserver>::Unchecked observers_;
 
+  std::unique_ptr<WallpaperMetricsManager> wallpaper_metrics_manager_;
+
   std::unique_ptr<WallpaperResizer> current_wallpaper_;
 
   // Manages interactions with relevant preferences.
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index 8d9afa17..67956030 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -1215,6 +1215,8 @@
       static_cast<int>(base::PersistentHash(
           TestWallpaperControllerClient::kDummyCollectionId)),
       1);
+  histogram_tester().ExpectBucketCount("Ash.Wallpaper.Type",
+                                       WallpaperType::kOnline, 1);
 
   // Verify that the wallpaper with |url| is available offline, and the returned
   // file name should not contain the small wallpaper suffix.
@@ -3972,52 +3974,6 @@
 }
 
 TEST_F(WallpaperControllerTest,
-       UpdateWallpaperWithMissingVariantsOnColorModeChanged) {
-  SimulateUserLogin(account_id_1);
-
-  auto run_loop = std::make_unique<base::RunLoop>();
-  ClearWallpaperCount();
-
-  const OnlineWallpaperParams& params = OnlineWallpaperParams(
-      account_id_1, kAssetId, GURL(kDummyUrl),
-      TestWallpaperControllerClient::kDummyCollectionId,
-      WALLPAPER_LAYOUT_CENTER_CROPPED,
-      /*preview_mode=*/false, /*from_user=*/true,
-      /*daily_refresh_enabled=*/false, /*unit_id=*/absl::nullopt,
-      /*variants=*/std::vector<OnlineWallpaperVariant>());
-  controller_->SetOnlineWallpaper(
-      params, base::BindLambdaForTesting([&run_loop](bool success) {
-        EXPECT_TRUE(success);
-        run_loop->Quit();
-      }));
-  run_loop->Run();
-  EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
-
-  pref_manager_->SetUserWallpaperInfo(account_id_1, WallpaperInfo(params));
-  Shell::Get()->session_controller()->GetActivePrefService()->SetBoolean(
-      prefs::kDarkModeEnabled, true);
-  controller_->OnColorModeChanged(true);
-  RunAllTasksUntilIdle();
-  EXPECT_EQ(2, GetWallpaperCount());
-
-  std::vector<OnlineWallpaperVariant> variants;
-  variants.emplace_back(kAssetId.value(), GURL(kDummyUrl),
-                        backdrop::Image::IMAGE_TYPE_DARK_MODE);
-  variants.emplace_back(kAssetId2.value(), GURL(kDummyUrl2),
-                        backdrop::Image::IMAGE_TYPE_LIGHT_MODE);
-  WallpaperInfo expected = WallpaperInfo(OnlineWallpaperParams(
-      account_id_1, kAssetId, GURL(kDummyUrl),
-      TestWallpaperControllerClient::kDummyCollectionId,
-      WALLPAPER_LAYOUT_CENTER_CROPPED, /*preview_mode=*/false,
-      /*from_user=*/true,
-      /*daily_refresh_enabled=*/false, kUnitId, variants));
-  WallpaperInfo actual;
-  EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(account_id_1, &actual));
-  EXPECT_EQ(expected, actual);
-}
-
-TEST_F(WallpaperControllerTest,
        UpdateWallpaperInfoWithOnlineWallpaperVariants) {
   SimulateUserLogin(account_id_1);
 
diff --git a/ash/wallpaper/wallpaper_metrics_manager.cc b/ash/wallpaper/wallpaper_metrics_manager.cc
new file mode 100644
index 0000000..0c565d52
--- /dev/null
+++ b/ash/wallpaper/wallpaper_metrics_manager.cc
@@ -0,0 +1,50 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/wallpaper/wallpaper_metrics_manager.h"
+
+#include "ash/public/cpp/wallpaper/online_wallpaper_params.h"
+#include "ash/session/session_controller_impl.h"
+#include "ash/shell.h"
+#include "ash/shell_delegate.h"
+#include "ash/wallpaper/wallpaper_controller_impl.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
+
+namespace ash {
+
+WallpaperMetricsManager::WallpaperMetricsManager() {
+  wallpaper_controller_observation_.Observe(WallpaperController::Get());
+}
+
+WallpaperMetricsManager::~WallpaperMetricsManager() = default;
+
+void WallpaperMetricsManager::OnOnlineWallpaperSet(
+    const OnlineWallpaperParams& params) {
+  if (params.from_user) {
+    const absl::optional<uint64_t>& unit_id = params.unit_id;
+    DCHECK(unit_id.has_value());
+    const int unit_id_val = unit_id.value();
+    base::UmaHistogramSparse("Ash.Wallpaper.Image", unit_id_val);
+
+    const std::string& collection_id = params.collection_id;
+    DCHECK(!collection_id.empty());
+    const int collection_id_hash = base::PersistentHash(collection_id);
+    base::UmaHistogramSparse("Ash.Wallpaper.Collection", collection_id_hash);
+  }
+}
+
+void WallpaperMetricsManager::OnWallpaperChanged() {
+  UMA_HISTOGRAM_ENUMERATION(
+      "Ash.Wallpaper.Type",
+      Shell::Get()->wallpaper_controller()->GetWallpaperType(),
+      WallpaperType::kCount);
+}
+
+void WallpaperMetricsManager::OnWallpaperPreviewStarted() {
+  base::UmaHistogramBoolean("Ash.Wallpaper.Preview.Show", true);
+}
+
+}  // namespace ash
diff --git a/ash/wallpaper/wallpaper_metrics_manager.h b/ash/wallpaper/wallpaper_metrics_manager.h
new file mode 100644
index 0000000..2bb125b
--- /dev/null
+++ b/ash/wallpaper/wallpaper_metrics_manager.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_WALLPAPER_WALLPAPER_METRICS_MANAGER_H_
+#define ASH_WALLPAPER_WALLPAPER_METRICS_MANAGER_H_
+
+#include "ash/ash_export.h"
+#include "ash/public/cpp/wallpaper/online_wallpaper_params.h"
+#include "ash/public/cpp/wallpaper/wallpaper_controller.h"
+#include "ash/public/cpp/wallpaper/wallpaper_controller_observer.h"
+#include "base/scoped_observation.h"
+
+namespace ash {
+
+// The implementation of WallpaperControllerObserver that saves metrics.
+class ASH_EXPORT WallpaperMetricsManager : public WallpaperControllerObserver {
+ public:
+  WallpaperMetricsManager();
+
+  WallpaperMetricsManager(const WallpaperMetricsManager&) = delete;
+  WallpaperMetricsManager& operator=(const WallpaperMetricsManager&) = delete;
+
+  ~WallpaperMetricsManager() override;
+
+  // WallpaperControllerObserver:
+  void OnOnlineWallpaperSet(const OnlineWallpaperParams& params) override;
+  void OnWallpaperChanged() override;
+  void OnWallpaperPreviewStarted() override;
+
+ private:
+  base::ScopedObservation<WallpaperController, WallpaperControllerObserver>
+      wallpaper_controller_observation_{this};
+};
+
+}  // namespace ash
+
+#endif  // ASH_WALLPAPER_WALLPAPER_METRICS_MANAGER_H_
diff --git a/ash/webui/common/resources/BUILD.gn b/ash/webui/common/resources/BUILD.gn
index 2d42dc0f..ceaf9c3 100644
--- a/ash/webui/common/resources/BUILD.gn
+++ b/ash/webui/common/resources/BUILD.gn
@@ -137,6 +137,7 @@
 }
 
 checked_in_dts_files = [
+  "fake_method_resolver.d.ts",
   "page_toolbar.d.ts",
   "navigation_view_panel.d.ts",
   "navigation_selector.d.ts",
diff --git a/ash/webui/common/resources/fake_method_resolver.d.ts b/ash/webui/common/resources/fake_method_resolver.d.ts
new file mode 100644
index 0000000..f59a0ba
--- /dev/null
+++ b/ash/webui/common/resources/fake_method_resolver.d.ts
@@ -0,0 +1,16 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+declare class FakeMethodState<T = any> {
+  resolveMethod(): Promise<T>;
+  resolveMethodWithDelay(delayMs: number): Promise<T>;
+  setResult(result: T): void;
+}
+
+export class FakeMethodResolver<T = any> {
+  register(methodName: string): void;
+  setResult(methodName: string, result: T): void;
+  resolveMethod(methodName: string): Promise<T>;
+  resolveMethodWithDelay(methodName: string, delayMs: number): Promise<T>;
+}
diff --git a/ash/webui/facial_ml_app_ui/BUILD.gn b/ash/webui/face_ml_app_ui/BUILD.gn
similarity index 60%
rename from ash/webui/facial_ml_app_ui/BUILD.gn
rename to ash/webui/face_ml_app_ui/BUILD.gn
index 601682d..e8b047d 100644
--- a/ash/webui/facial_ml_app_ui/BUILD.gn
+++ b/ash/webui/face_ml_app_ui/BUILD.gn
@@ -5,20 +5,18 @@
 import("//build/config/chromeos/ui_mode.gni")
 import("//ui/webui/resources/tools/generate_grd.gni")
 
-assert(!is_official_build,
-       "Facial ML App is only built for unofficial builds for now")
-assert(is_chromeos_ash, "Facial ML App is ash-chrome only")
+assert(is_chromeos_ash, "Face ML App is ash-chrome only")
 
-static_library("facial_ml_app_ui") {
+static_library("face_ml_app_ui") {
   sources = [
-    "facial_ml_app_ui.cc",
-    "facial_ml_app_ui.h",
+    "face_ml_app_ui.cc",
+    "face_ml_app_ui.h",
     "url_constants.cc",
     "url_constants.h",
   ]
 
   deps = [
-    "//ash/webui/resources:facial_ml_app_resources",
+    "//ash/webui/resources:face_ml_app_resources",
     "//ash/webui/system_apps/public:system_web_app_config",
     "//content/public/browser",
     "//ui/webui",
diff --git a/ash/webui/facial_ml_app_ui/DEPS b/ash/webui/face_ml_app_ui/DEPS
similarity index 100%
rename from ash/webui/facial_ml_app_ui/DEPS
rename to ash/webui/face_ml_app_ui/DEPS
diff --git a/ash/webui/facial_ml_app_ui/DIR_METADATA b/ash/webui/face_ml_app_ui/DIR_METADATA
similarity index 100%
rename from ash/webui/facial_ml_app_ui/DIR_METADATA
rename to ash/webui/face_ml_app_ui/DIR_METADATA
diff --git a/ash/webui/facial_ml_app_ui/OWNERS b/ash/webui/face_ml_app_ui/OWNERS
similarity index 100%
rename from ash/webui/facial_ml_app_ui/OWNERS
rename to ash/webui/face_ml_app_ui/OWNERS
diff --git a/ash/webui/facial_ml_app_ui/facial_ml_app_ui.cc b/ash/webui/face_ml_app_ui/face_ml_app_ui.cc
similarity index 62%
rename from ash/webui/facial_ml_app_ui/facial_ml_app_ui.cc
rename to ash/webui/face_ml_app_ui/face_ml_app_ui.cc
index fcd48065..f1c703a 100644
--- a/ash/webui/facial_ml_app_ui/facial_ml_app_ui.cc
+++ b/ash/webui/face_ml_app_ui/face_ml_app_ui.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 "ash/webui/facial_ml_app_ui/facial_ml_app_ui.h"
+#include "ash/webui/face_ml_app_ui/face_ml_app_ui.h"
 
 #include <utility>
 
-#include "ash/webui/facial_ml_app_ui/url_constants.h"
-#include "ash/webui/grit/ash_facial_ml_app_resources.h"
-#include "ash/webui/grit/ash_facial_ml_app_resources_map.h"
+#include "ash/webui/face_ml_app_ui/url_constants.h"
+#include "ash/webui/grit/ash_face_ml_app_resources.h"
+#include "ash/webui/grit/ash_face_ml_app_resources_map.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
@@ -17,26 +17,26 @@
 
 namespace ash {
 
-FacialMLAppUI::FacialMLAppUI(content::WebUI* web_ui)
+FaceMLAppUI::FaceMLAppUI(content::WebUI* web_ui)
     : ui::MojoWebUIController(web_ui) {
   auto* browser_context = web_ui->GetWebContents()->GetBrowserContext();
   content::WebUIDataSource* trusted_source =
       content::WebUIDataSource::CreateAndAdd(browser_context,
-                                             kChromeUIFacialMLAppHost);
-  trusted_source->AddResourcePath("", IDR_ASH_FACIAL_ML_APP_INDEX_HTML);
+                                             kChromeUIFaceMLAppHost);
+  trusted_source->AddResourcePath("", IDR_ASH_FACE_ML_APP_INDEX_HTML);
   trusted_source->AddResourcePaths(
-      base::make_span(kAshFacialMlAppResources, kAshFacialMlAppResourcesSize));
+      base::make_span(kAshFaceMlAppResources, kAshFaceMlAppResourcesSize));
 
 #if !DCHECK_IS_ON()
   // Skip default page setting in the product mode, so the developers will get
   // an error page if anything is wrong.
-  trusted_source->SetDefaultResource(IDR_ASH_FACIAL_ML_APP_INDEX_HTML);
+  trusted_source->SetDefaultResource(IDR_ASH_FACE_ML_APP_INDEX_HTML);
 #endif  // !DCHECK_IS_ON()
 
-  // Register common permissions for chrome://facial_ml pages.
+  // Register common permissions for chrome://face_ml pages.
   auto* webui_allowlist = WebUIAllowlist::GetOrCreate(browser_context);
   const url::Origin app_origin =
-      url::Origin::Create(GURL(kChromeUIFacialMLAppURL));
+      url::Origin::Create(GURL(kChromeUIFaceMLAppURL));
   webui_allowlist->RegisterAutoGrantedPermissions(
       app_origin, {
                       ContentSettingsType::COOKIES,
@@ -46,8 +46,8 @@
                   });
 }
 
-FacialMLAppUI::~FacialMLAppUI() = default;
+FaceMLAppUI::~FaceMLAppUI() = default;
 
-WEB_UI_CONTROLLER_TYPE_IMPL(FacialMLAppUI)
+WEB_UI_CONTROLLER_TYPE_IMPL(FaceMLAppUI)
 
 }  // namespace ash
diff --git a/ash/webui/face_ml_app_ui/face_ml_app_ui.h b/ash/webui/face_ml_app_ui/face_ml_app_ui.h
new file mode 100644
index 0000000..bf711a1
--- /dev/null
+++ b/ash/webui/face_ml_app_ui/face_ml_app_ui.h
@@ -0,0 +1,36 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_WEBUI_FACE_ML_APP_UI_FACE_ML_APP_UI_H_
+#define ASH_WEBUI_FACE_ML_APP_UI_FACE_ML_APP_UI_H_
+
+#include "ash/webui/face_ml_app_ui/url_constants.h"
+#include "ash/webui/system_apps/public/system_web_app_ui_config.h"
+#include "content/public/browser/webui_config.h"
+#include "ui/webui/mojo_web_ui_controller.h"
+
+namespace ash {
+
+class FaceMLAppUI : public ui::MojoWebUIController {
+ public:
+  explicit FaceMLAppUI(content::WebUI* web_ui);
+  FaceMLAppUI(const FaceMLAppUI&) = delete;
+  FaceMLAppUI& operator=(const FaceMLAppUI&) = delete;
+  ~FaceMLAppUI() override;
+
+ private:
+  WEB_UI_CONTROLLER_TYPE_DECL();
+};
+
+// The WebUIConfig for chrome://face-ml/.
+class FaceMLAppUIConfig : public SystemWebAppUIConfig<FaceMLAppUI> {
+ public:
+  FaceMLAppUIConfig()
+      : SystemWebAppUIConfig(kChromeUIFaceMLAppHost,
+                             SystemWebAppType::FACE_ML) {}
+};
+
+}  // namespace ash
+
+#endif  // ASH_WEBUI_FACE_ML_APP_UI_FACE_ML_APP_UI_H_
diff --git a/ash/webui/facial_ml_app_ui/resources/trusted/BUILD.gn b/ash/webui/face_ml_app_ui/resources/trusted/BUILD.gn
similarity index 91%
rename from ash/webui/facial_ml_app_ui/resources/trusted/BUILD.gn
rename to ash/webui/face_ml_app_ui/resources/trusted/BUILD.gn
index 210dd2fc..f06fdad 100644
--- a/ash/webui/facial_ml_app_ui/resources/trusted/BUILD.gn
+++ b/ash/webui/face_ml_app_ui/resources/trusted/BUILD.gn
@@ -6,7 +6,7 @@
 import("//tools/typescript/ts_library.gni")
 import("//ui/webui/resources/tools/generate_grd.gni")
 
-assert(is_chromeos_ash, "Facial ML App is ash-chrome only")
+assert(is_chromeos_ash, "Face ML App is ash-chrome only")
 
 ts_library("trusted_ts") {
   root_dir = "."
@@ -24,7 +24,7 @@
 }
 
 generate_grd("trusted_grd") {
-  grd_prefix = "ash_facial_ml_app"
+  grd_prefix = "ash_face_ml_app"
   out_grd = "$target_gen_dir/${grd_prefix}_resources.grd"
 
   input_files = [
diff --git a/ash/webui/facial_ml_app_ui/resources/trusted/app_icon_192.png b/ash/webui/face_ml_app_ui/resources/trusted/app_icon_192.png
similarity index 100%
rename from ash/webui/facial_ml_app_ui/resources/trusted/app_icon_192.png
rename to ash/webui/face_ml_app_ui/resources/trusted/app_icon_192.png
Binary files differ
diff --git a/ash/webui/facial_ml_app_ui/resources/trusted/app_icon_512.png b/ash/webui/face_ml_app_ui/resources/trusted/app_icon_512.png
similarity index 100%
rename from ash/webui/facial_ml_app_ui/resources/trusted/app_icon_512.png
rename to ash/webui/face_ml_app_ui/resources/trusted/app_icon_512.png
Binary files differ
diff --git a/ash/webui/facial_ml_app_ui/resources/trusted/index.html b/ash/webui/face_ml_app_ui/resources/trusted/index.html
similarity index 93%
rename from ash/webui/facial_ml_app_ui/resources/trusted/index.html
rename to ash/webui/face_ml_app_ui/resources/trusted/index.html
index 8b326752..16fb7e3 100644
--- a/ash/webui/facial_ml_app_ui/resources/trusted/index.html
+++ b/ash/webui/face_ml_app_ui/resources/trusted/index.html
@@ -6,7 +6,7 @@
   <head>
     <link rel="stylesheet" href="chrome://resources/chromeos/colors/cros_styles.css">
     <meta charset="utf-8">
-  <title>Facial ML App</title>
+  <title>Face ML App</title>
   </head>
   <body>
     <div id="content"></div>
diff --git a/ash/webui/facial_ml_app_ui/resources/trusted/main.ts b/ash/webui/face_ml_app_ui/resources/trusted/main.ts
similarity index 83%
rename from ash/webui/facial_ml_app_ui/resources/trusted/main.ts
rename to ash/webui/face_ml_app_ui/resources/trusted/main.ts
index eb83028..a023db1 100644
--- a/ash/webui/facial_ml_app_ui/resources/trusted/main.ts
+++ b/ash/webui/face_ml_app_ui/resources/trusted/main.ts
@@ -5,5 +5,5 @@
 // Example of fill the content.
 (async () => {
   const content = document.querySelector<HTMLElement>('#content')!;
-  content.textContent = 'Hello Facial ML user!';
+  content.textContent = 'Welcome to the Face ML app!';
 })();
diff --git a/ash/webui/facial_ml_app_ui/tsconfig_base.json b/ash/webui/face_ml_app_ui/tsconfig_base.json
similarity index 100%
rename from ash/webui/facial_ml_app_ui/tsconfig_base.json
rename to ash/webui/face_ml_app_ui/tsconfig_base.json
diff --git a/ash/webui/face_ml_app_ui/url_constants.cc b/ash/webui/face_ml_app_ui/url_constants.cc
new file mode 100644
index 0000000..250a779
--- /dev/null
+++ b/ash/webui/face_ml_app_ui/url_constants.cc
@@ -0,0 +1,12 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/webui/face_ml_app_ui/url_constants.h"
+
+namespace ash {
+
+const char kChromeUIFaceMLAppHost[] = "face-ml";
+const char kChromeUIFaceMLAppURL[] = "chrome://face-ml";
+
+}  // namespace ash
diff --git a/ash/webui/face_ml_app_ui/url_constants.h b/ash/webui/face_ml_app_ui/url_constants.h
new file mode 100644
index 0000000..6b1de4d8
--- /dev/null
+++ b/ash/webui/face_ml_app_ui/url_constants.h
@@ -0,0 +1,15 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_WEBUI_FACE_ML_APP_UI_URL_CONSTANTS_H_
+#define ASH_WEBUI_FACE_ML_APP_UI_URL_CONSTANTS_H_
+
+namespace ash {
+
+extern const char kChromeUIFaceMLAppHost[];
+extern const char kChromeUIFaceMLAppURL[];
+
+}  // namespace ash
+
+#endif  // ASH_WEBUI_FACE_ML_APP_UI_URL_CONSTANTS_H_
diff --git a/ash/webui/facial_ml_app_ui/facial_ml_app_ui.h b/ash/webui/facial_ml_app_ui/facial_ml_app_ui.h
deleted file mode 100644
index da46b40..0000000
--- a/ash/webui/facial_ml_app_ui/facial_ml_app_ui.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_WEBUI_FACIAL_ML_APP_UI_FACIAL_ML_APP_UI_H_
-#define ASH_WEBUI_FACIAL_ML_APP_UI_FACIAL_ML_APP_UI_H_
-
-#include "ash/webui/facial_ml_app_ui/url_constants.h"
-#include "ash/webui/system_apps/public/system_web_app_ui_config.h"
-#include "content/public/browser/webui_config.h"
-#include "ui/webui/mojo_web_ui_controller.h"
-
-namespace ash {
-
-class FacialMLAppUI : public ui::MojoWebUIController {
- public:
-  explicit FacialMLAppUI(content::WebUI* web_ui);
-  FacialMLAppUI(const FacialMLAppUI&) = delete;
-  FacialMLAppUI& operator=(const FacialMLAppUI&) = delete;
-  ~FacialMLAppUI() override;
-
- private:
-  WEB_UI_CONTROLLER_TYPE_DECL();
-};
-
-// The WebUIConfig for chrome://facial-ml/.
-class FacialMLAppUIConfig : public SystemWebAppUIConfig<FacialMLAppUI> {
- public:
-  FacialMLAppUIConfig()
-      : SystemWebAppUIConfig(kChromeUIFacialMLAppHost,
-                             SystemWebAppType::FACIAL_ML) {}
-};
-
-}  // namespace ash
-
-#endif  // ASH_WEBUI_FACIAL_ML_APP_UI_FACIAL_ML_APP_UI_H_
diff --git a/ash/webui/facial_ml_app_ui/url_constants.cc b/ash/webui/facial_ml_app_ui/url_constants.cc
deleted file mode 100644
index 523add6..0000000
--- a/ash/webui/facial_ml_app_ui/url_constants.cc
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/webui/facial_ml_app_ui/url_constants.h"
-
-namespace ash {
-
-const char kChromeUIFacialMLAppHost[] = "facial-ml";
-const char kChromeUIFacialMLAppURL[] = "chrome://facial-ml";
-
-}  // namespace ash
diff --git a/ash/webui/facial_ml_app_ui/url_constants.h b/ash/webui/facial_ml_app_ui/url_constants.h
deleted file mode 100644
index a7bf74e..0000000
--- a/ash/webui/facial_ml_app_ui/url_constants.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_WEBUI_FACIAL_ML_APP_UI_URL_CONSTANTS_H_
-#define ASH_WEBUI_FACIAL_ML_APP_UI_URL_CONSTANTS_H_
-
-namespace ash {
-
-extern const char kChromeUIFacialMLAppHost[];
-extern const char kChromeUIFacialMLAppURL[];
-
-}  // namespace ash
-
-#endif  // ASH_WEBUI_FACIAL_ML_APP_UI_URL_CONSTANTS_H_
diff --git a/ash/webui/resources/BUILD.gn b/ash/webui/resources/BUILD.gn
index a852219..28d00ce 100644
--- a/ash/webui/resources/BUILD.gn
+++ b/ash/webui/resources/BUILD.gn
@@ -319,10 +319,10 @@
   output_dir = "$root_gen_dir/chromeos"
 }
 
-# Resources used by chrome://facial-ml
-ash_generated_grit("facial_ml_app_resources") {
-  source = "$root_gen_dir/ash/webui/facial_ml_app_ui/resources/trusted/ash_facial_ml_app_resources.grd"
-  deps = [ "//ash/webui/facial_ml_app_ui/resources/trusted:trusted_grd" ]
+# Resources used by chrome://face-ml
+ash_generated_grit("face_ml_app_resources") {
+  source = "$root_gen_dir/ash/webui/face_ml_app_ui/resources/trusted/ash_face_ml_app_resources.grd"
+  deps = [ "//ash/webui/face_ml_app_ui/resources/trusted:trusted_grd" ]
 }
 
 # Resources used by chrome://eche-app
diff --git a/ash/webui/shimless_rma/resources/BUILD.gn b/ash/webui/shimless_rma/resources/BUILD.gn
index d5d6018e..f2243ea 100644
--- a/ash/webui/shimless_rma/resources/BUILD.gn
+++ b/ash/webui/shimless_rma/resources/BUILD.gn
@@ -231,9 +231,9 @@
     ":mojo_interface_provider",
     ":shimless_rma_types",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-    "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button",
     "//ui/webui/resources/js:i18n_behavior.m",
   ]
+  externs_list = [ "//ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_externs.js" ]
 }
 
 js_library("onboarding_choose_wipe_device_page") {
diff --git a/ash/webui/system_apps/public/system_web_app_type.h b/ash/webui/system_apps/public/system_web_app_type.h
index 9138a11b..5867da34 100644
--- a/ash/webui/system_apps/public/system_web_app_type.h
+++ b/ash/webui/system_apps/public/system_web_app_type.h
@@ -102,13 +102,13 @@
   // contact: skuhne@google.com
   OS_FLAGS = 23,
 
-  // Facial ML app aims to provide UI interactions to help Facial ML team
-  // train their models on CrOS. This is an internal app that is only enabled
-  // on pre-released Chromebooks with appropriate hardware.
+  // Face ML app aims to provide UI interactions to help Face ML team train
+  // their models on CrOS. This is an internal app that is only enabled on
+  // pre-released Chromebooks with appropriate hardware and OS support.
   //
-  // Source: //ash/webui/facial_ml_app_ui/
+  // Source: //ash/webui/face_ml_app_ui/
   // contact: googleo@google.com
-  FACIAL_ML = 24,
+  FACE_ML = 24,
 
   // When adding a new System App, remember to:
   //
@@ -145,7 +145,7 @@
   //
   // 7. Have one of System Web App Platform owners review the CL.
   //    See: //ash/webui/PLATFORM_OWNERS
-  kMaxValue = FACIAL_ML,
+  kMaxValue = FACE_ML,
 };
 
 }  // namespace ash
diff --git a/base/allocator/partition_allocator/partition_alloc_check.h b/base/allocator/partition_allocator/partition_alloc_check.h
index 80e06ee..93dee1c 100644
--- a/base/allocator/partition_allocator/partition_alloc_check.h
+++ b/base/allocator/partition_allocator/partition_alloc_check.h
@@ -30,7 +30,7 @@
 // - Otherwise, crash immediately. This provides worse error messages though.
 #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
 // For official build discard log strings to reduce binary bloat.
-#if defined(OFFICIAL_BUILD) && defined(NDEBUG)
+#if !CHECK_WILL_STREAM()
 // See base/check.h for implementation details.
 #define PA_CHECK(condition)                        \
   PA_UNLIKELY(!(condition)) ? PA_IMMEDIATE_CRASH() \
@@ -44,7 +44,7 @@
   ? ::partition_alloc::internal::logging::RawCheck(                        \
         __FILE__ "(" PA_STRINGIFY(__LINE__) ") Check failed: " #condition) \
   : PA_EAT_CHECK_STREAM_PARAMS()
-#endif  // defined(OFFICIAL_BUILD) && defined(NDEBUG)
+#endif  // !CHECK_WILL_STREAM()
 
 #if BUILDFLAG(PA_DCHECK_IS_ON)
 #define PA_DCHECK(condition) PA_CHECK(condition)
diff --git a/build/fuchsia/test/flash_device.py b/build/fuchsia/test/flash_device.py
index 7a6c4a25..15bcc86 100755
--- a/build/fuchsia/test/flash_device.py
+++ b/build/fuchsia/test/flash_device.py
@@ -13,6 +13,7 @@
 
 from common import register_device_args, run_ffx_command
 from compatible_utils import get_sdk_hash
+from ffx_integration import ScopedFfxConfig
 
 
 def _get_system_info(target: Optional[str]) -> Tuple[str, str]:
@@ -35,7 +36,10 @@
     return ('', '')
 
 
-def flash(system_image_dir: str, os_check: str, target: Optional[str]) -> None:
+def flash(system_image_dir: str,
+          os_check: str,
+          target: Optional[str],
+          serial_num: Optional[str] = None) -> None:
     """Flash the device."""
 
     if os_check == 'ignore':
@@ -46,7 +50,12 @@
             and get_sdk_hash(system_image_dir) == _get_system_info(target)):
         return
     manifest = os.path.join(system_image_dir, 'flash-manifest.manifest')
-    run_ffx_command(('target', 'flash', manifest), target)
+    if serial_num:
+        with ScopedFfxConfig('discovery.zedboot.enabled', 'true'):
+            run_ffx_command(('target', 'reboot', '-b'), target, check=False)
+        run_ffx_command(('target', 'flash', manifest), serial_num)
+    else:
+        run_ffx_command(('target', 'flash', manifest), target)
     run_ffx_command(('target', 'wait'), target)
 
 
@@ -61,6 +70,11 @@
                             'Fuchsia image used to pave the device. Only '
                             'needs to be specified if "os_check" is not '
                             '"ignore".')
+    serve_args.add_argument('--serial-num',
+                            default=os.environ.get('FUCHSIA_FASTBOOT_SERNUM'),
+                            help='Serial number of the device. Should be '
+                            'specified for devices that do not have an image '
+                            'flashed.')
     serve_args.add_argument('--os-check',
                             choices=['check', 'update', 'ignore'],
                             default=default_os_check,
@@ -68,8 +82,8 @@
                             '"check", then the deployment process will halt '
                             'if the target\'s version does not match. If '
                             '"update", then the target device will '
-                            'automatically be repaved. If "ignore", then the '
-                            'OS version won\'t be checked.')
+                            'be reflashed. If "ignore", then the OS version '
+                            'will not be checked.')
 
 
 def main():
@@ -78,7 +92,8 @@
     register_device_args(parser)
     register_flash_args(parser)
     args = parser.parse_args()
-    flash(args.system_image_dir, args.os_check, args.target_id)
+    flash(args.system_image_dir, args.os_check, args.target_id,
+          args.serial_num)
 
 
 if __name__ == '__main__':
diff --git a/build/fuchsia/test/flash_device_unittests.py b/build/fuchsia/test/flash_device_unittests.py
index 547929bb..ba1fe99 100755
--- a/build/fuchsia/test/flash_device_unittests.py
+++ b/build/fuchsia/test/flash_device_unittests.py
@@ -5,6 +5,7 @@
 """File for testing flash_device.py."""
 
 import argparse
+import os
 import unittest
 import unittest.mock as mock
 
@@ -71,12 +72,24 @@
         flash_device.flash(_TEST_IMAGE_DIR, 'check', None)
         self.assertEqual(self._ffx_mock.call_count, 3)
 
+    @mock.patch('flash_device.ScopedFfxConfig')
+    def test_flash_with_serial_num(self, mock_scoped_config) -> None:
+        """Test flash when |serial_num| is specified."""
+
+        context_mock = mock.Mock()
+        mock_scoped_config.return_value = context_mock
+        context_mock.__enter__ = mock.Mock(return_value=None)
+        context_mock.__exit__ = mock.Mock(return_value=None)
+        flash_device.flash(_TEST_IMAGE_DIR, 'update', None, 'test_serial')
+        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']):
-            flash_device.main()
+            with mock.patch.dict(os.environ, {}):
+                flash_device.main()
         self.assertEqual(self._ffx_mock.call_count, 0)
 
 
diff --git a/build/fuchsia/test/run_test.py b/build/fuchsia/test/run_test.py
index 5be5c70..bf9cb60 100755
--- a/build/fuchsia/test/run_test.py
+++ b/build/fuchsia/test/run_test.py
@@ -73,7 +73,7 @@
         log_manager = stack.enter_context(LogManager(runner_args.logs_dir))
         if runner_args.device:
             flash(runner_args.system_image_dir, runner_args.os_check,
-                  runner_args.target_id)
+                  runner_args.target_id, runner_args.serial_num)
         else:
             runner_args.target_id = stack.enter_context(
                 create_emulator_from_args(runner_args))
diff --git a/chrome/VERSION b/chrome/VERSION
index 75388d0a..809e4b60 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=107
 MINOR=0
-BUILD=5256
+BUILD=5257
 PATCH=0
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index a696b5b..12d3276 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -3457,7 +3457,10 @@
           Certificate Signature Value
         </message>
         <message name="IDS_CERT_DETAILS_EXPORT_CERTIFICATE" desc="The label of the button to export the selected certificate">
-          E&amp;xport selected certificate...
+          E&amp;xport...
+        </message>
+        <message name="IDS_CERT_DETAILS_EXPORT_CERTIFICATE_A11Y_LABEL" desc="The accessibility label of the button to export the selected certificate. This message is spoken by screen readers when the IDS_CERT_DETAILS_EXPORT_CERTIFICATE control gets focus, but is not visually rendered.">
+          Export selected certificate
         </message>
 
         <message translateable="false" name="IDS_CERT_OID_AVA_COMMON_NAME" desc="">
diff --git a/chrome/app/generated_resources_grd/IDS_CERT_DETAILS_EXPORT_CERTIFICATE.png.sha1 b/chrome/app/generated_resources_grd/IDS_CERT_DETAILS_EXPORT_CERTIFICATE.png.sha1
index cc44c34..9943333 100644
--- a/chrome/app/generated_resources_grd/IDS_CERT_DETAILS_EXPORT_CERTIFICATE.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_CERT_DETAILS_EXPORT_CERTIFICATE.png.sha1
@@ -1 +1 @@
-55a7a3c61cd9fa7ff8bf31be3214cb615ac6d55d
\ No newline at end of file
+36221f612dafc5a103e606b976fdee82fe8f6f59
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_CERT_DETAILS_EXPORT_CERTIFICATE_A11Y_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_CERT_DETAILS_EXPORT_CERTIFICATE_A11Y_LABEL.png.sha1
new file mode 100644
index 0000000..9943333
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_CERT_DETAILS_EXPORT_CERTIFICATE_A11Y_LABEL.png.sha1
@@ -0,0 +1 @@
+36221f612dafc5a103e606b976fdee82fe8f6f59
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 0d240c7..9404db9 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -5118,6 +5118,7 @@
       "//ash/webui/diagnostics_ui/mojom",
       "//ash/webui/eche_app_ui",
       "//ash/webui/eche_app_ui/mojom",
+      "//ash/webui/face_ml_app_ui",
       "//ash/webui/file_manager:file_manager_ui",
       "//ash/webui/file_manager/mojom",
       "//ash/webui/firmware_update_ui",
@@ -5301,7 +5302,6 @@
       deps += [
         "//ash/webui/demo_mode_app_ui",
         "//ash/webui/demo_mode_app_ui/mojom",
-        "//ash/webui/facial_ml_app_ui",
         "//ash/webui/sample_system_web_app_ui",
         "//ash/webui/sample_system_web_app_ui/mojom:shared",
         "//ash/webui/sample_system_web_app_ui/mojom:trusted",
@@ -5717,6 +5717,8 @@
       "chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher.h",
       "chromeos/reporting/metric_default_utils.cc",
       "chromeos/reporting/metric_default_utils.h",
+      "chromeos/reporting/metric_reporting_manager_delegate_base.cc",
+      "chromeos/reporting/metric_reporting_manager_delegate_base.h",
       "chromeos/reporting/network/network_bandwidth_sampler.cc",
       "chromeos/reporting/network/network_bandwidth_sampler.h",
       "chromeos/tablet_mode/chrome_content_browser_client_tablet_mode_part.cc",
diff --git a/chrome/browser/apps/app_deduplication_service/app_deduplication_service.cc b/chrome/browser/apps/app_deduplication_service/app_deduplication_service.cc
index f6bbd6c..d4e7430 100644
--- a/chrome/browser/apps/app_deduplication_service/app_deduplication_service.cc
+++ b/chrome/browser/apps/app_deduplication_service/app_deduplication_service.cc
@@ -27,8 +27,8 @@
   if (it == entry_to_group_map_.end()) {
     return entries;
   }
-  std::string duplication_key = it->second;
-  auto group = duplication_map_.find(duplication_key);
+  uint32_t duplication_index = it->second;
+  auto group = duplication_map_.find(duplication_index);
   if (group == duplication_map_.end()) {
     return entries;
   }
@@ -47,22 +47,26 @@
   if (it_1 == entry_to_group_map_.end()) {
     return false;
   }
-  const std::string& duplication_key_1 = it_1->second;
+  uint32_t duplication_index_1 = it_1->second;
 
   auto it_2 = entry_to_group_map_.find(entry_id_2);
   if (it_2 == entry_to_group_map_.end()) {
     return false;
   }
-  const std::string& duplication_key_2 = it_2->second;
+  uint32_t duplication_index_2 = it_2->second;
 
-  return duplication_key_1 == duplication_key_2;
+  return duplication_index_1 == duplication_index_2;
 }
 
-void AppDeduplicationService::OnDuplicatedAppsMapUpdated(
-    const proto::DuplicatedAppsMap& duplicated_apps_map) {
-  for (auto const& group : duplicated_apps_map.duplicated_apps_map()) {
+void AppDeduplicationService::OnDuplicatedGroupListUpdated(
+    const proto::DuplicatedGroupList& duplicated_group_list) {
+  // Use the index as the internal indexing key for fast look up. If the
+  // size of the duplicated groups goes over integer 32 limit, a new indexing
+  // key needs to be introduced.
+  uint32_t index = 1;
+  for (auto const& group : duplicated_group_list.duplicate_group()) {
     DuplicateGroup duplicate_group;
-    for (auto const& app : group.second.apps()) {
+    for (auto const& app : group.app()) {
       const std::string& app_id = app.app_id_for_platform();
       const std::string& source = app.source_name();
       EntryId entry_id;
@@ -75,12 +79,13 @@
         entry_id = EntryId(app_id);
       }
 
-      entry_to_group_map_[entry_id] = group.first;
+      entry_to_group_map_[entry_id] = index;
 
       Entry entry(std::move(entry_id));
       duplicate_group.entries.push_back(std::move(entry));
     }
-    duplication_map_[group.first] = std::move(duplicate_group);
+    duplication_map_[index] = std::move(duplicate_group);
+    index++;
   }
 }
 
diff --git a/chrome/browser/apps/app_deduplication_service/app_deduplication_service.h b/chrome/browser/apps/app_deduplication_service/app_deduplication_service.h
index 254429a..5e496e8 100644
--- a/chrome/browser/apps/app_deduplication_service/app_deduplication_service.h
+++ b/chrome/browser/apps/app_deduplication_service/app_deduplication_service.h
@@ -33,15 +33,15 @@
  private:
   friend class AppDeduplicationServiceTest;
   FRIEND_TEST_ALL_PREFIXES(AppDeduplicationServiceTest,
-                           OnDuplicatedAppsMapUpdated);
+                           OnDuplicatedGroupListUpdated);
   FRIEND_TEST_ALL_PREFIXES(AppDeduplicationServiceTest, ExactDuplicate);
 
   // AppProvisioningDataManager::Observer:
-  void OnDuplicatedAppsMapUpdated(
-      const proto::DuplicatedAppsMap& duplicated_apps_map) override;
+  void OnDuplicatedGroupListUpdated(
+      const proto::DuplicatedGroupList& duplicated_apps_map) override;
 
-  std::map<std::string, DuplicateGroup> duplication_map_;
-  std::map<EntryId, std::string> entry_to_group_map_;
+  std::map<uint32_t, DuplicateGroup> duplication_map_;
+  std::map<EntryId, uint32_t> entry_to_group_map_;
 
   base::ScopedObservation<AppProvisioningDataManager,
                           AppProvisioningDataManager::Observer>
diff --git a/chrome/browser/apps/app_deduplication_service/app_deduplication_service_unittest.cc b/chrome/browser/apps/app_deduplication_service/app_deduplication_service_unittest.cc
index 508ad50..c21b467 100644
--- a/chrome/browser/apps/app_deduplication_service/app_deduplication_service_unittest.cc
+++ b/chrome/browser/apps/app_deduplication_service/app_deduplication_service_unittest.cc
@@ -78,7 +78,7 @@
   EXPECT_NE(guest_otr_service, service);
 }
 
-TEST_F(AppDeduplicationServiceTest, OnDuplicatedAppsMapUpdated) {
+TEST_F(AppDeduplicationServiceTest, OnDuplicatedGroupListUpdated) {
   base::FilePath path;
   EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &path));
   path = path.AppendASCII("app_deduplication_service/binary_test_data.pb");
@@ -86,8 +86,8 @@
   std::string dedupe_pb;
   ASSERT_TRUE(base::ReadFileToString(path, &dedupe_pb));
 
-  proto::DuplicatedAppsMap duplicated_apps_map;
-  ASSERT_TRUE(duplicated_apps_map.ParseFromString(dedupe_pb));
+  proto::DuplicatedGroupList duplicated_group_list;
+  ASSERT_TRUE(duplicated_group_list.ParseFromString(dedupe_pb));
 
   TestingProfile::Builder profile_builder;
   auto profile = profile_builder.Build();
@@ -96,52 +96,52 @@
   auto* service = AppDeduplicationServiceFactory::GetForProfile(profile.get());
   EXPECT_NE(nullptr, service);
 
-  service->OnDuplicatedAppsMapUpdated(duplicated_apps_map);
+  service->OnDuplicatedGroupListUpdated(duplicated_group_list);
 
-  std::string skype_test_key = "Skype";
+  uint32_t skype_test_index = 1;
   std::string skype_arc_app_id = "com.skype.raider";
   auto it = service->entry_to_group_map_.find(
       EntryId(skype_arc_app_id, AppType::kArc));
   ASSERT_NE(it, service->entry_to_group_map_.end());
-  EXPECT_EQ(skype_test_key, it->second);
+  EXPECT_EQ(skype_test_index, it->second);
 
   std::string skype_web_app_id = "http://web.skype.com/";
   it = service->entry_to_group_map_.find(
       EntryId(skype_web_app_id, AppType::kWeb));
   ASSERT_NE(it, service->entry_to_group_map_.end());
-  EXPECT_EQ(skype_test_key, it->second);
+  EXPECT_EQ(skype_test_index, it->second);
 
   std::string skype_phonehub_app_id = "com.skype.raider";
   it = service->entry_to_group_map_.find(EntryId(skype_phonehub_app_id));
   ASSERT_NE(it, service->entry_to_group_map_.end());
-  EXPECT_EQ(skype_test_key, it->second);
+  EXPECT_EQ(skype_test_index, it->second);
 
-  auto map_it = service->duplication_map_.find(skype_test_key);
+  auto map_it = service->duplication_map_.find(skype_test_index);
   ASSERT_FALSE(map_it == service->duplication_map_.end());
   EXPECT_THAT(map_it->second.entries,
               ElementsAre(Entry(EntryId(skype_phonehub_app_id)),
                           Entry(EntryId(skype_arc_app_id, AppType::kArc)),
                           Entry(EntryId(skype_web_app_id, AppType::kWeb))));
 
-  std::string whatsapp_test_key = "WhatsApp";
+  uint32_t whatsapp_test_index = 2;
   std::string whatsapp_arc_app_id = "com.whatsapp";
   it = service->entry_to_group_map_.find(
       EntryId(whatsapp_arc_app_id, AppType::kArc));
   ASSERT_NE(it, service->entry_to_group_map_.end());
-  EXPECT_EQ(whatsapp_test_key, it->second);
+  EXPECT_EQ(whatsapp_test_index, it->second);
 
   std::string whatsapp_web_app_id = "http://web.whatsapp.com/";
   it = service->entry_to_group_map_.find(
       EntryId(whatsapp_web_app_id, AppType::kWeb));
   ASSERT_NE(it, service->entry_to_group_map_.end());
-  EXPECT_EQ(whatsapp_test_key, it->second);
+  EXPECT_EQ(whatsapp_test_index, it->second);
 
   std::string whatsapp_phonehub_app_id = "com.whatsapp";
   it = service->entry_to_group_map_.find(EntryId(whatsapp_phonehub_app_id));
   ASSERT_NE(it, service->entry_to_group_map_.end());
-  EXPECT_EQ(whatsapp_test_key, it->second);
+  EXPECT_EQ(whatsapp_test_index, it->second);
 
-  map_it = service->duplication_map_.find(whatsapp_test_key);
+  map_it = service->duplication_map_.find(whatsapp_test_index);
   ASSERT_FALSE(map_it == service->duplication_map_.end());
   EXPECT_THAT(map_it->second.entries,
               ElementsAre(Entry(EntryId(whatsapp_phonehub_app_id)),
@@ -157,8 +157,8 @@
   std::string dedupe_pb;
   ASSERT_TRUE(base::ReadFileToString(path, &dedupe_pb));
 
-  proto::DuplicatedAppsMap duplicated_apps_map;
-  ASSERT_TRUE(duplicated_apps_map.ParseFromString(dedupe_pb));
+  proto::DuplicatedGroupList duplicated_group_list;
+  ASSERT_TRUE(duplicated_group_list.ParseFromString(dedupe_pb));
 
   TestingProfile::Builder profile_builder;
   auto profile = profile_builder.Build();
@@ -167,7 +167,7 @@
   auto* service = AppDeduplicationServiceFactory::GetForProfile(profile.get());
   EXPECT_NE(nullptr, service);
 
-  service->OnDuplicatedAppsMapUpdated(duplicated_apps_map);
+  service->OnDuplicatedGroupListUpdated(duplicated_group_list);
 
   EntryId skype_arc_entry_id("com.skype.raider", apps::AppType::kArc);
   EntryId skype_web_entry_id("http://web.skype.com/", apps::AppType::kWeb);
diff --git a/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.cc b/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.cc
index 17dba0b..abb5a52 100644
--- a/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.cc
+++ b/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.cc
@@ -16,21 +16,21 @@
 namespace {
 // TODO(b/238394602): Use fake data for now. Update to generate from real data
 // when real data is ready.
-std::unique_ptr<proto::DuplicatedAppsMap> PopulateDuplicatedAppsMap() {
-  std::unique_ptr<proto::DuplicatedAppsMap> duplicated_apps_map =
-      std::make_unique<proto::DuplicatedAppsMap>();
-  auto* map = duplicated_apps_map->mutable_duplicated_apps_map();
+std::unique_ptr<proto::DuplicatedGroupList> PopulateDuplicatedGroupList() {
+  std::unique_ptr<proto::DuplicatedGroupList> duplicated_group_list =
+      std::make_unique<proto::DuplicatedGroupList>();
+  auto* add_group = duplicated_group_list->add_duplicate_group();
   proto::DuplicateGroup duplicate_group;
-  auto* arc_app = duplicate_group.add_apps();
+  auto* arc_app = duplicate_group.add_app();
   arc_app->set_app_id_for_platform("test_arc_app_id");
   arc_app->set_source_name("arc");
 
-  auto* web_app = duplicate_group.add_apps();
+  auto* web_app = duplicate_group.add_app();
   web_app->set_app_id_for_platform("test_web_app_id");
   web_app->set_source_name("web");
 
-  (*map)["test_key"] = duplicate_group;
-  return duplicated_apps_map;
+  *add_group = duplicate_group;
+  return duplicated_group_list;
 }
 
 std::unique_ptr<proto::AppWithLocaleList> PopulateAppWithLocaleList(
@@ -68,7 +68,7 @@
   // TODO(melzhang) : Add check that version of |app_with_locale_list| is newer.
   app_with_locale_list_ = PopulateAppWithLocaleList(binary_pb);
   if (base::FeatureList::IsEnabled(features::kAppDeduplicationService)) {
-    duplicated_apps_map_ = PopulateDuplicatedAppsMap();
+    duplicated_group_list_ = PopulateDuplicatedGroupList();
   }
   data_dir_ = install_dir;
   OnAppDataUpdated();
@@ -79,7 +79,7 @@
 }
 
 void AppProvisioningDataManager::OnAppDataUpdated() {
-  if (!app_with_locale_list_ && !duplicated_apps_map_) {
+  if (!app_with_locale_list_ && !duplicated_group_list_) {
     return;
   }
   for (auto& observer : observers_) {
@@ -89,7 +89,7 @@
 
 void AppProvisioningDataManager::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
-  if (app_with_locale_list_ || duplicated_apps_map_) {
+  if (app_with_locale_list_ || duplicated_group_list_) {
     NotifyObserver(*observer);
   }
 }
@@ -106,8 +106,8 @@
   }
   // TODO(b/238394602): Add version check so that only notify observer when new
   // version is available.
-  if (duplicated_apps_map_) {
-    observer.OnDuplicatedAppsMapUpdated(*duplicated_apps_map_.get());
+  if (duplicated_group_list_) {
+    observer.OnDuplicatedGroupListUpdated(*duplicated_group_list_.get());
   }
 }
 
diff --git a/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.h b/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.h
index 8b20240..0010529e 100644
--- a/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.h
+++ b/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.h
@@ -26,8 +26,8 @@
    public:
     virtual void OnAppWithLocaleListUpdated(
         const proto::AppWithLocaleList& app_with_locale_list) {}
-    virtual void OnDuplicatedAppsMapUpdated(
-        const proto::DuplicatedAppsMap& duplicated_apps_map) {}
+    virtual void OnDuplicatedGroupListUpdated(
+        const proto::DuplicatedGroupList& duplicated_group_list) {}
   };
 
   static AppProvisioningDataManager* Get();
@@ -64,7 +64,7 @@
 
   // The latest app data. Starts out as null.
   std::unique_ptr<proto::AppWithLocaleList> app_with_locale_list_;
-  std::unique_ptr<proto::DuplicatedAppsMap> duplicated_apps_map_;
+  std::unique_ptr<proto::DuplicatedGroupList> duplicated_group_list_;
 
   base::ObserverList<Observer> observers_;
 
diff --git a/chrome/browser/apps/app_provisioning_service/proto/app_data.proto b/chrome/browser/apps/app_provisioning_service/proto/app_data.proto
index 51c2aa8..6f908680 100644
--- a/chrome/browser/apps/app_provisioning_service/proto/app_data.proto
+++ b/chrome/browser/apps/app_provisioning_service/proto/app_data.proto
@@ -52,13 +52,12 @@
   optional bool is_masking_allowed = 2;
 }
 
-// A group of apps that considered as duplicated. This group will also include
-// meta data for duplication in the future, e.g. confidence, etc.
+// A group of apps that are considered to be duplicated.
 message DuplicateGroup {
-  repeated App apps = 1;
+  repeated App app = 1;
 }
 
-// A map for duplicate groups, each group is defined by a string key.
-message DuplicatedAppsMap {
-  map<string, DuplicateGroup> duplicated_apps_map = 1;
+// List of duplicated app groups.
+message DuplicatedGroupList {
+  repeated DuplicateGroup duplicate_group = 1;
 }
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics.cc b/chrome/browser/apps/app_service/metrics/website_metrics.cc
index ae22020..ae862836e 100644
--- a/chrome/browser/apps/app_service/metrics/website_metrics.cc
+++ b/chrome/browser/apps/app_service/metrics/website_metrics.cc
@@ -376,8 +376,12 @@
   // contents::WebContentsObserver::PrimaryPageChanged(), set the visible url as
   // default value for the ukm key url.
   webcontents_to_ukm_key_[web_contents] = web_contents->GetVisibleURL();
+  auto it = window_to_web_contents_.find(window);
+  bool is_activated = wm::IsActiveWindow(window) &&
+                      it != window_to_web_contents_.end() &&
+                      it->second == web_contents;
   AddUrlInfo(web_contents->GetVisibleURL(), base::TimeTicks::Now(),
-             UrlContent::kFullUrl, wm::IsActiveWindow(window),
+             UrlContent::kFullUrl, is_activated,
              /*promotable=*/false);
 }
 
@@ -409,8 +413,12 @@
   }
 
   DCHECK(!app_banner_manager->manifest().scope.is_empty());
+  auto window_it = window_to_web_contents_.find(window);
+  bool is_activated = wm::IsActiveWindow(window) &&
+                      window_it != window_to_web_contents_.end() &&
+                      window_it->second == web_contents;
   UpdateUrlInfo(it->second, app_banner_manager->manifest().scope,
-                UrlContent::kScope, wm::IsActiveWindow(window),
+                UrlContent::kScope, is_activated,
                 /*promotable=*/true);
   it->second = app_banner_manager->manifest().scope;
 }
@@ -507,9 +515,12 @@
       // the raw data collected in a 5 minutes slot.
       it.second.running_time_in_two_hours +=
           GetRandomNoise() * it.second.running_time_in_five_minutes;
-      dict.Set(it.first.spec(), it.second.ConvertToValue());
       it.second.running_time_in_five_minutes = base::TimeDelta();
     }
+    // Save all urls running time in the past two hours to the user pref.
+    if (!it.second.running_time_in_two_hours.is_zero()) {
+      dict.Set(it.first.spec(), it.second.ConvertToValue());
+    }
   }
 }
 
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics_browsertest.cc b/chrome/browser/apps/app_service/metrics/website_metrics_browsertest.cc
index 8427d7e..c1c1be9 100644
--- a/chrome/browser/apps/app_service/metrics/website_metrics_browsertest.cc
+++ b/chrome/browser/apps/app_service/metrics/website_metrics_browsertest.cc
@@ -149,6 +149,12 @@
                            WindowOpenDisposition::NEW_FOREGROUND_TAB);
   }
 
+  content::WebContents* InsertBackgroundTab(Browser* browser,
+                                            const std::string& url) {
+    return NavigateAndWait(browser, url,
+                           WindowOpenDisposition::NEW_BACKGROUND_TAB);
+  }
+
   web_app::AppId InstallWebApp(const std::string& start_url,
                                web_app::UserDisplayMode user_display_mode) {
     auto info = std::make_unique<WebAppInstallInfo>();
@@ -401,6 +407,7 @@
   VerifyUrlInfo(GURL("https://b.example.org"), UrlContent::kFullUrl,
                 /*is_activated=*/true, /*promotable=*/false);
 
+  website_metrics()->OnFiveMinutes();
   browser->tab_strip_model()->CloseAllTabs();
   EXPECT_TRUE(webcontents_to_observer_map().empty());
   EXPECT_TRUE(window_to_web_contents().empty());
@@ -409,7 +416,6 @@
                 /*is_activated=*/false, /*promotable=*/false);
   VerifyUrlInfo(GURL("https://b.example.org"), UrlContent::kFullUrl,
                 /*is_activated=*/false, /*promotable=*/false);
-  website_metrics()->OnFiveMinutes();
   VerifyUrlInfoInPref(GURL("https://a.example.org"), UrlContent::kFullUrl,
                       /*promotable=*/false);
   VerifyUrlInfoInPref(GURL("https://b.example.org"), UrlContent::kFullUrl,
@@ -424,6 +430,142 @@
   EXPECT_TRUE(url_infos().empty());
 }
 
+IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest, NavigateToBackgroundTab) {
+  auto website_metrics_ptr = std::make_unique<apps::TestWebsiteMetrics>(
+      ProfileManager::GetPrimaryUserProfile());
+  auto* metrics = website_metrics_ptr.get();
+  app_platform_metrics_service_->SetWebsiteMetricsForTesting(
+      std::move(website_metrics_ptr));
+
+  Browser* browser = CreateBrowser();
+  auto* window = browser->window()->GetNativeWindow();
+  EXPECT_EQ(1u, window_to_web_contents().size());
+  // Open a tab in foreground.
+  GURL url1 =
+      embedded_test_server()->GetURL("/banners/no_manifest_test_page.html");
+  auto* tab1 = InsertForegroundTab(browser, url1.spec());
+  EXPECT_EQ(1u, webcontents_to_observer_map().size());
+  EXPECT_TRUE(base::Contains(webcontents_to_observer_map(),
+                             window_to_web_contents()[window]));
+  EXPECT_EQ(window_to_web_contents()[window]->GetVisibleURL(), url1);
+  EXPECT_EQ(1u, webcontents_to_ukm_key().size());
+  EXPECT_EQ(webcontents_to_ukm_key()[tab1], url1);
+  VerifyUrlInfo(url1, UrlContent::kFullUrl,
+                /*is_activated=*/true, /*promotable=*/false);
+
+  // Navigate the background tab to a url with a manifest.
+  GURL url2 =
+      embedded_test_server()->GetURL("/banners/manifest_test_page.html");
+  auto ukm_key = url2.GetWithoutFilename();
+  auto* tab2 = InsertBackgroundTab(browser, url2.spec());
+  metrics->AwaitForInstallableWebAppCheck(ukm_key);
+  EXPECT_EQ(2u, webcontents_to_observer_map().size());
+  EXPECT_TRUE(base::Contains(webcontents_to_observer_map(), tab2));
+  EXPECT_EQ(1u, window_to_web_contents().size());
+  EXPECT_EQ(window_to_web_contents()[window]->GetVisibleURL(), url1);
+  EXPECT_EQ(2u, webcontents_to_ukm_key().size());
+  EXPECT_EQ(webcontents_to_ukm_key()[tab2], ukm_key);
+  VerifyUrlInfo(url1, UrlContent::kFullUrl,
+                /*is_activated=*/true, /*promotable=*/false);
+  VerifyUrlInfo(ukm_key, UrlContent::kScope,
+                /*is_activated=*/false, /*promotable=*/true);
+
+  website_metrics()->OnFiveMinutes();
+  browser->tab_strip_model()->CloseAllTabs();
+  EXPECT_TRUE(webcontents_to_observer_map().empty());
+  EXPECT_TRUE(window_to_web_contents().empty());
+  EXPECT_TRUE(webcontents_to_ukm_key().empty());
+  VerifyUrlInfo(url1, UrlContent::kFullUrl,
+                /*is_activated=*/false, /*promotable=*/false);
+  VerifyUrlInfo(ukm_key, UrlContent::kScope,
+                /*is_activated=*/false, /*promotable=*/true);
+  VerifyUrlInfoInPref(url1, UrlContent::kFullUrl,
+                      /*promotable=*/false);
+  VerifyNoUrlInfoInPref(ukm_key);
+
+  // Simulate recording the UKMs to clear the local usage time records.
+  website_metrics()->OnTwoHours();
+  VerifyUsageTimeUkm(url1, UrlContent::kFullUrl,
+                     /*promotable=*/false);
+  VerifyNoUsageTimeUkm(ukm_key);
+  EXPECT_TRUE(url_infos().empty());
+}
+
+IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest, ActiveBackgroundTab) {
+  auto website_metrics_ptr = std::make_unique<apps::TestWebsiteMetrics>(
+      ProfileManager::GetPrimaryUserProfile());
+  auto* metrics = website_metrics_ptr.get();
+  app_platform_metrics_service_->SetWebsiteMetricsForTesting(
+      std::move(website_metrics_ptr));
+
+  Browser* browser = CreateBrowser();
+  auto* window = browser->window()->GetNativeWindow();
+  EXPECT_EQ(1u, window_to_web_contents().size());
+  // Open a tab in foreground.
+  GURL url1 =
+      embedded_test_server()->GetURL("/banners/no_manifest_test_page.html");
+  auto* tab1 = InsertForegroundTab(browser, url1.spec());
+  EXPECT_EQ(1u, webcontents_to_observer_map().size());
+  EXPECT_TRUE(base::Contains(webcontents_to_observer_map(),
+                             window_to_web_contents()[window]));
+  EXPECT_EQ(window_to_web_contents()[window]->GetVisibleURL(), url1);
+  EXPECT_EQ(1u, webcontents_to_ukm_key().size());
+  EXPECT_EQ(webcontents_to_ukm_key()[tab1], url1);
+  VerifyUrlInfo(url1, UrlContent::kFullUrl,
+                /*is_activated=*/true, /*promotable=*/false);
+
+  // Navigate the background tab to a url with a manifest.
+  GURL url2 =
+      embedded_test_server()->GetURL("/banners/manifest_test_page.html");
+  auto ukm_key = url2.GetWithoutFilename();
+  auto* tab2 = InsertBackgroundTab(browser, url2.spec());
+  metrics->AwaitForInstallableWebAppCheck(ukm_key);
+  EXPECT_EQ(2u, webcontents_to_observer_map().size());
+  EXPECT_TRUE(base::Contains(webcontents_to_observer_map(), tab2));
+  EXPECT_EQ(1u, window_to_web_contents().size());
+  EXPECT_EQ(window_to_web_contents()[window]->GetVisibleURL(), url1);
+  EXPECT_EQ(2u, webcontents_to_ukm_key().size());
+  EXPECT_EQ(webcontents_to_ukm_key()[tab2], ukm_key);
+  VerifyUrlInfo(url1, UrlContent::kFullUrl,
+                /*is_activated=*/true, /*promotable=*/false);
+  VerifyUrlInfo(ukm_key, UrlContent::kScope,
+                /*is_activated=*/false, /*promotable=*/true);
+  website_metrics()->OnFiveMinutes();
+
+  browser->tab_strip_model()->ActivateTabAt(1);
+  EXPECT_EQ(2u, webcontents_to_observer_map().size());
+  EXPECT_EQ(1u, window_to_web_contents().size());
+  EXPECT_EQ(window_to_web_contents()[window]->GetVisibleURL(), url2);
+  EXPECT_EQ(2u, webcontents_to_ukm_key().size());
+  VerifyUrlInfo(url1, UrlContent::kFullUrl,
+                /*is_activated=*/false, /*promotable=*/false);
+  VerifyUrlInfo(ukm_key, UrlContent::kScope,
+                /*is_activated=*/true, /*promotable=*/true);
+  website_metrics()->OnFiveMinutes();
+
+  browser->tab_strip_model()->CloseAllTabs();
+  EXPECT_TRUE(webcontents_to_observer_map().empty());
+  EXPECT_TRUE(window_to_web_contents().empty());
+  EXPECT_TRUE(webcontents_to_ukm_key().empty());
+  VerifyUrlInfo(url1, UrlContent::kFullUrl,
+                /*is_activated=*/false, /*promotable=*/false);
+  VerifyUrlInfo(ukm_key, UrlContent::kScope,
+                /*is_activated=*/false, /*promotable=*/true);
+  website_metrics()->OnFiveMinutes();
+  VerifyUrlInfoInPref(url1, UrlContent::kFullUrl,
+                      /*promotable=*/false);
+  VerifyUrlInfoInPref(ukm_key, UrlContent::kScope,
+                      /*promotable=*/true);
+
+  // Simulate recording the UKMs to clear the local usage time records.
+  website_metrics()->OnTwoHours();
+  VerifyUsageTimeUkm(url1, UrlContent::kFullUrl,
+                     /*promotable=*/false);
+  VerifyUsageTimeUkm(ukm_key, UrlContent::kScope,
+                     /*promotable=*/true);
+  EXPECT_TRUE(url_infos().empty());
+}
+
 IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest, NavigateToUrlWithManifest) {
   auto website_metrics_ptr = std::make_unique<apps::TestWebsiteMetrics>(
       ProfileManager::GetPrimaryUserProfile());
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index 2b817c2..69fddc02 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -146,6 +146,8 @@
     "app_mode/web_app/web_kiosk_app_manager.h",
     "app_mode/web_app/web_kiosk_app_service_launcher.cc",
     "app_mode/web_app/web_kiosk_app_service_launcher.h",
+    "app_mode/web_app/web_kiosk_app_update_observer.cc",
+    "app_mode/web_app/web_kiosk_app_update_observer.h",
     "app_restore/app_launch_handler.cc",
     "app_restore/app_launch_handler.h",
     "app_restore/app_restore_arc_task_handler.cc",
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc
index 3bc2dad..6691309f 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc
@@ -22,10 +22,12 @@
 
 namespace ash {
 
+constexpr int kWebKioskIconSize = 128;  // size of the icon in px.
+
 namespace {
-constexpr int kIconSize = 128;  // size of the icon in px.
 // Maximum image size is 256x256..
-constexpr int kMaxIconFileSize = (2 * kIconSize) * (2 * kIconSize) * 4 + 1000;
+constexpr int kMaxIconFileSize =
+    (2 * kWebKioskIconSize) * (2 * kWebKioskIconSize) * 4 + 1000;
 
 const char kKeyLaunchUrl[] = "launch_url";
 const char kKeyLastIconUrl[] = "last_icon_url";
@@ -121,7 +123,7 @@
     }
 
     int size = decoded_image.width();
-    if (size == kIconSize) {
+    if (size == kWebKioskIconSize) {
       client_->OnDidDownloadIcon(decoded_image);
       return;
     }
@@ -130,7 +132,7 @@
         FROM_HERE,
         {base::TaskPriority::USER_VISIBLE,
          base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-        base::BindOnce(ResizeImageBlocking, decoded_image, kIconSize),
+        base::BindOnce(ResizeImageBlocking, decoded_image, kWebKioskIconSize),
         base::BindOnce(&WebKioskAppData::OnDidDownloadIcon, client_));
   }
 
@@ -213,13 +215,21 @@
 }
 
 void WebKioskAppData::UpdateFromWebAppInfo(const WebAppInstallInfo& app_info) {
-  name_ = base::UTF16ToUTF8(app_info.title);
+  UpdateAppInfo(base::UTF16ToUTF8(app_info.title), app_info.start_url,
+                app_info.icon_bitmaps);
+}
+
+void WebKioskAppData::UpdateAppInfo(const std::string& title,
+                                    const GURL& start_url,
+                                    const IconBitmaps& icon_bitmaps) {
+  name_ = title;
+
   base::FilePath cache_dir;
   if (delegate_)
     delegate_->GetKioskAppIconCacheDir(&cache_dir);
 
-  auto it = app_info.icon_bitmaps.any.find(kIconSize);
-  if (it != app_info.icon_bitmaps.any.end()) {
+  auto it = icon_bitmaps.any.find(kWebKioskIconSize);
+  if (it != icon_bitmaps.any.end()) {
     const SkBitmap& bitmap = it->second;
     icon_ = gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
     icon_.MakeThreadSafe();
@@ -230,7 +240,7 @@
   DictionaryPrefUpdate dict_update(local_state, dictionary_name());
   SaveToDictionary(dict_update);
 
-  launch_url_ = GURL(app_info.start_url);
+  launch_url_ = start_url;
   dict_update->FindDictKey(KioskAppDataBase::kKeyApps)
       ->FindDictKey(app_id())
       ->SetStringKey(kKeyLaunchUrl, launch_url_.spec());
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h
index 021c083..8e743fdd 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h
@@ -10,6 +10,7 @@
 
 #include "base/values.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_data_base.h"
+#include "chrome/browser/web_applications/web_app_install_info.h"
 #include "components/account_id/account_id.h"
 #include "ui/gfx/image/image_skia.h"
 #include "url/gurl.h"
@@ -20,6 +21,8 @@
 
 class KioskAppDataDelegate;
 
+extern const int kWebKioskIconSize;
+
 class WebKioskAppData : public KioskAppDataBase {
  public:
   enum class Status {
@@ -59,6 +62,10 @@
 
   void UpdateFromWebAppInfo(const WebAppInstallInfo& app_info);
 
+  void UpdateAppInfo(const std::string& title,
+                     const GURL& start_url,
+                     const IconBitmaps& icon_bitmaps);
+
   void SetOnLoadedCallbackForTesting(base::OnceClosure callback);
 
   Status status() const { return status_; }
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.cc
index 93a1fd4..0fa7a04 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.cc
@@ -5,17 +5,17 @@
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
 
 #include <map>
+#include <memory>
 
 #include "ash/components/settings/cros_settings_names.h"
-#include "base/bind.h"
 #include "chrome/browser/ash/app_mode/app_session_ash.h"
 #include "chrome/browser/ash/app_mode/kiosk_cryptohome_remover.h"
 #include "chrome/browser/ash/crosapi/browser_util.h"
 #include "chrome/browser/ash/policy/core/device_local_account.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "components/prefs/pref_registry_simple.h"
+#include "url/gurl.h"
 
 namespace ash {
 
@@ -103,6 +103,19 @@
   NOTREACHED();
 }
 
+void WebKioskAppManager::UpdateAppByAccountId(const AccountId& account_id,
+                                              const std::string& title,
+                                              const GURL& start_url,
+                                              const IconBitmaps& icon_bitmaps) {
+  for (auto& web_app : apps_) {
+    if (web_app->account_id() == account_id) {
+      web_app->UpdateAppInfo(title, start_url, icon_bitmaps);
+      return;
+    }
+  }
+  NOTREACHED();
+}
+
 void WebKioskAppManager::AddAppForTesting(const AccountId& account_id,
                                           const GURL& install_url) {
   const std::string app_id =
@@ -182,4 +195,10 @@
   NotifyKioskAppsChanged();
 }
 
+void WebKioskAppManager::StartObservingAppUpdate(Profile* profile,
+                                                 const AccountId& account_id) {
+  app_update_observer_ =
+      std::make_unique<WebKioskAppUpdateObserver>(profile, account_id);
+}
+
 }  // namespace ash
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h
index 4c37e113..a2ea0df3 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h
@@ -10,7 +10,10 @@
 
 #include "chrome/browser/ash/app_mode/kiosk_app_manager_base.h"
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h"
+#include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_update_observer.h"
+#include "chrome/browser/web_applications/web_app_install_info.h"
 #include "components/account_id/account_id.h"
+#include "url/gurl.h"
 
 class Browser;
 class PrefRegistrySimple;
@@ -56,12 +59,21 @@
   void UpdateAppByAccountId(const AccountId& account_id,
                             const WebAppInstallInfo& app_info);
 
+  // Updates app by title, start_url and icon_bitmaps.
+  void UpdateAppByAccountId(const AccountId& account_id,
+                            const std::string& title,
+                            const GURL& start_url,
+                            const IconBitmaps& icon_bitmaps);
+
   // Adds fake apps in tests.
   void AddAppForTesting(const AccountId& account_id, const GURL& install_url);
 
   // Initialize current app session with the browser that is running the app.
   void InitSession(Browser* browser, Profile* profile);
 
+  // Starts observing web app updates from App Service in a Kiosk session.
+  void StartObservingAppUpdate(Profile* profile, const AccountId& account_id);
+
  private:
   // KioskAppManagerBase:
   // Updates |apps_| based on CrosSettings.
@@ -69,6 +81,10 @@
 
   std::vector<std::unique_ptr<WebKioskAppData>> apps_;
   AccountId auto_launch_account_id_;
+
+  // Observes web Kiosk app updates. Persists through the whole web Kiosk
+  // session.
+  std::unique_ptr<WebKioskAppUpdateObserver> app_update_observer_;
 };
 
 }  // namespace ash
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher.cc
index c3ee54a..f6db24d 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher.cc
@@ -35,6 +35,10 @@
 void WebKioskAppServiceLauncher::Initialize() {
   DCHECK(!app_service_launcher_);
 
+  // Start observing app update from App Service early so that app updates being
+  // applied while launching can be handled.
+  WebKioskAppManager::Get()->StartObservingAppUpdate(profile_, account_id_);
+
   app_service_launcher_ = std::make_unique<KioskAppServiceLauncher>(profile_);
   app_service_launcher_->EnsureAppTypeInitialized(
       apps::AppType::kWeb,
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher_unittest.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher_unittest.cc
index d02bf46..a6c6c7d 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher_unittest.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher_unittest.cc
@@ -283,6 +283,9 @@
     launcher()->LaunchApp();
     loop.Run();
   }
+
+  EXPECT_EQ(app_data()->status(), WebKioskAppData::Status::kInstalled);
+  EXPECT_EQ(app_data()->launch_url(), kAppLaunchUrl);
 }
 
 TEST_F(WebKioskAppServiceLauncherTest, NormalFlowAlreadyInstalled) {
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_update_observer.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_update_observer.cc
new file mode 100644
index 0000000..800ba90
--- /dev/null
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_update_observer.cc
@@ -0,0 +1,95 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_update_observer.h"
+
+#include "base/syslog_logging.h"
+#include "chrome/browser/apps/app_service/app_icon/app_icon_factory.h"
+#include "chrome/browser/apps/app_service/app_service_proxy.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
+#include "chrome/browser/web_applications/web_app_install_info.h"
+#include "components/services/app_service/public/cpp/app_types.h"
+#include "components/services/app_service/public/cpp/app_update.h"
+
+namespace ash {
+
+WebKioskAppUpdateObserver::WebKioskAppUpdateObserver(
+    Profile* profile,
+    const AccountId& account_id)
+    : account_id_(account_id) {
+  app_service_ = apps::AppServiceProxyFactory::GetForProfile(profile);
+  DCHECK(app_service_);
+  app_registry_observation_.Observe(&app_service_->AppRegistryCache());
+}
+
+WebKioskAppUpdateObserver::~WebKioskAppUpdateObserver() = default;
+
+void WebKioskAppUpdateObserver::OnAppUpdate(const apps::AppUpdate& update) {
+  // There can be only one Kiosk-installed web app per Kiosk session. So that
+  // we treat any update coming from Kiosk-installed as the one configured in
+  // policy.
+  if (update.AppType() != apps::AppType::kWeb ||
+      update.InstallReason() != apps::InstallReason::kKiosk ||
+      update.Readiness() != apps::Readiness::kReady) {
+    return;
+  }
+
+  // If any of the following changes, we update the Kiosk Apps menu:
+  // Name: title of the app
+  // PublisherId: start URL of the app
+  // IconKey: icon of the app
+  if (update.NameChanged() || update.PublisherIdChanged() ||
+      update.IconKeyChanged()) {
+    SYSLOG(INFO) << "Kiosk web app update triggered";
+    UpdateWebAppFromAppService(update.AppId(), update.IconKeyChanged());
+  }
+}
+
+void WebKioskAppUpdateObserver::OnAppRegistryCacheWillBeDestroyed(
+    apps::AppRegistryCache* cache) {
+  app_registry_observation_.Reset();
+}
+
+void WebKioskAppUpdateObserver::UpdateWebAppFromAppService(
+    const std::string& app_id,
+    bool icon_updated) {
+  // |apps::AppUpdate| passed to |OnAppUpdate()| only contains updated info. To
+  // get all info we have to use |AppRegistryCache::ForOneApp()|.
+  app_service_->AppRegistryCache().ForOneApp(
+      app_id, [this, &icon_updated](const apps::AppUpdate& app_info) {
+        GURL start_url = GURL(app_info.PublisherId());
+
+        if (icon_updated && app_info.IconKey()) {
+          auto icon_key = app_info.IconKey().value();
+          // Remove web app icon effects for Kiosk apps menu.
+          icon_key.icon_effects = apps::IconEffects::kNone;
+          app_service_->LoadIconFromIconKey(
+              apps::AppType::kWeb, app_info.AppId(), icon_key,
+              apps::IconType::kUncompressed, kWebKioskIconSize,
+              /*allow_placeholder_icon=*/true,
+              base::BindOnce(&WebKioskAppUpdateObserver::OnAppServiceIconLoaded,
+                             weak_ptr_factory_.GetWeakPtr(), app_info.Name(),
+                             std::move(start_url)));
+          return;
+        }
+
+        WebKioskAppManager::Get()->UpdateAppByAccountId(
+            account_id_, app_info.Name(), start_url, IconBitmaps());
+      });
+}
+
+void WebKioskAppUpdateObserver::OnAppServiceIconLoaded(
+    std::string title,
+    GURL start_url,
+    apps::IconValuePtr icon) {
+  IconBitmaps icon_bitmaps;
+  if (icon->uncompressed.bitmap()) {
+    icon_bitmaps.any[kWebKioskIconSize] = *icon->uncompressed.bitmap();
+  }
+  WebKioskAppManager::Get()->UpdateAppByAccountId(account_id_, title, start_url,
+                                                  icon_bitmaps);
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_update_observer.h b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_update_observer.h
new file mode 100644
index 0000000..47185126
--- /dev/null
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_update_observer.h
@@ -0,0 +1,55 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_APP_MODE_WEB_APP_WEB_KIOSK_APP_UPDATE_OBSERVER_H_
+#define CHROME_BROWSER_ASH_APP_MODE_WEB_APP_WEB_KIOSK_APP_UPDATE_OBSERVER_H_
+
+#include <string>
+
+#include "base/scoped_observation.h"
+#include "chrome/browser/apps/app_service/app_service_proxy.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/services/app_service/public/cpp/app_registry_cache.h"
+
+namespace ash {
+
+// Observes web app update from App Service and updates information stored in
+// |WebKioskAppManager|. It persists through the whole Kiosk session so that app
+// updates during the session can also be handled.
+class WebKioskAppUpdateObserver : public apps::AppRegistryCache::Observer {
+ public:
+  WebKioskAppUpdateObserver(Profile* profile, const AccountId& account_id);
+
+  WebKioskAppUpdateObserver(const WebKioskAppUpdateObserver&) = delete;
+  WebKioskAppUpdateObserver& operator=(const WebKioskAppUpdateObserver&) =
+      delete;
+  ~WebKioskAppUpdateObserver() override;
+
+ private:
+  // apps::AppRegistryCache::Observer
+  void OnAppUpdate(const apps::AppUpdate& update) override;
+  void OnAppRegistryCacheWillBeDestroyed(
+      apps::AppRegistryCache* cache) override;
+
+  // Updates app info in |WebKioskAppManager|.
+  void UpdateWebAppFromAppService(const std::string& app_id, bool icon_updated);
+
+  void OnAppServiceIconLoaded(std::string title,
+                              GURL start_url,
+                              apps::IconValuePtr icon);
+
+  AccountId account_id_;
+
+  apps::AppServiceProxy* app_service_;
+
+  base::ScopedObservation<apps::AppRegistryCache,
+                          apps::AppRegistryCache::Observer>
+      app_registry_observation_{this};
+
+  base::WeakPtrFactory<WebKioskAppUpdateObserver> weak_ptr_factory_{this};
+};
+
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_ASH_APP_MODE_WEB_APP_WEB_KIOSK_APP_UPDATE_OBSERVER_H_
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_update_observer_unittest.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_update_observer_unittest.cc
new file mode 100644
index 0000000..ec2f9387
--- /dev/null
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_update_observer_unittest.cc
@@ -0,0 +1,253 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_update_observer.h"
+
+#include <sys/types.h>
+
+#include <memory>
+#include <vector>
+
+#include "base/run_loop.h"
+#include "chrome/browser/apps/app_service/app_service_proxy.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/apps/app_service/app_service_test.h"
+#include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h"
+#include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
+#include "chrome/browser/web_applications/test/web_app_icon_test_utils.h"
+#include "chrome/test/base/browser_with_test_window_test.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/services/app_service/public/cpp/app_types.h"
+#include "components/services/app_service/public/cpp/icon_types.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/image/image_skia.h"
+#include "url/gurl.h"
+
+namespace ash {
+
+namespace {
+
+const char kAppId[] = "testappid";
+const char kAppEmail[] = "test@example.com";
+const char kAppInstallUrl[] = "https://example.com";
+const char kAppLaunchUrl[] = "https://example.com/launch";
+const char kAppTitle[] = "app";
+const char kAppTitle2[] = "app2";
+
+class FakePublisher final : public apps::AppPublisher {
+ public:
+  FakePublisher(apps::AppServiceProxy* proxy, apps::AppType app_type)
+      : AppPublisher(proxy) {
+    RegisterPublisher(app_type);
+  }
+
+  MOCK_METHOD4(Launch,
+               void(const std::string& app_id,
+                    int32_t event_flags,
+                    apps::LaunchSource launch_source,
+                    apps::WindowInfoPtr window_info));
+
+  MOCK_METHOD2(LaunchAppWithParams,
+               void(apps::AppLaunchParams&& params,
+                    apps::LaunchCallback callback));
+
+  void LoadIcon(const std::string& app_id,
+                const apps::IconKey& icon_key,
+                apps::IconType icon_type,
+                int32_t size_hint_in_dip,
+                bool allow_placeholder_icon,
+                apps::LoadIconCallback callback) override {
+    auto icon = std::make_unique<apps::IconValue>();
+    icon->icon_type = apps::IconType::kUncompressed;
+    icon->uncompressed = gfx::ImageSkia::CreateFrom1xBitmap(
+        web_app::CreateSquareIcon(kWebKioskIconSize, SK_ColorWHITE));
+    icon->is_placeholder_icon = false;
+    std::move(callback).Run(std::move(icon));
+  }
+};
+
+}  // namespace
+
+class WebKioskAppUpdateObserverTest : public BrowserWithTestWindowTest {
+ public:
+  void SetUp() override {
+    BrowserWithTestWindowTest::SetUp();
+    account_id_ = AccountId::FromUserEmail(kAppEmail);
+
+    app_service_test_.UninstallAllApps(profile());
+    app_service_test_.SetUp(profile());
+    app_service_test_.WaitForAppService();
+    app_service_ = apps::AppServiceProxyFactory::GetForProfile(profile());
+
+    app_publisher_ =
+        std::make_unique<FakePublisher>(app_service_, apps::AppType::kWeb);
+
+    app_manager_ = std::make_unique<WebKioskAppManager>();
+
+    app_update_observer_ =
+        std::make_unique<WebKioskAppUpdateObserver>(profile(), account_id_);
+  }
+
+  void TearDown() override {
+    app_update_observer_.reset();
+    app_manager_.reset();
+    BrowserWithTestWindowTest::TearDown();
+  }
+
+ protected:
+  apps::AppPtr CreateTestApp() {
+    auto app = std::make_unique<apps::App>(apps::AppType::kWeb, kAppId);
+    app->app_id = kAppId;
+    app->app_type = apps::AppType::kWeb;
+    app->install_reason = apps::InstallReason::kKiosk;
+    app->readiness = apps::Readiness::kReady;
+    app->name = kAppTitle;
+    app->publisher_id = kAppLaunchUrl;
+    return app;
+  }
+
+  AccountId& account_id() { return account_id_; }
+
+  apps::AppServiceProxy* app_service() { return app_service_; }
+
+  apps::AppServiceTest& app_service_test() { return app_service_test_; }
+
+  WebKioskAppManager* app_manager() { return app_manager_.get(); }
+
+  const WebKioskAppData* app_data() {
+    return app_manager_->GetAppByAccountId(account_id_);
+  }
+
+  WebKioskAppUpdateObserver* app_update_observer() {
+    return app_update_observer_.get();
+  }
+
+ private:
+  AccountId account_id_;
+
+  apps::AppServiceTest app_service_test_;
+  apps::AppServiceProxy* app_service_ = nullptr;
+
+  std::unique_ptr<FakePublisher> app_publisher_;
+
+  std::unique_ptr<WebKioskAppManager> app_manager_;
+
+  std::unique_ptr<WebKioskAppUpdateObserver> app_update_observer_;
+};
+
+TEST_F(WebKioskAppUpdateObserverTest, ShouldUpdateAppInfoWithIconWhenReady) {
+  app_manager()->AddAppForTesting(account_id(), GURL(kAppInstallUrl));
+  EXPECT_EQ(app_data()->status(), WebKioskAppData::Status::kInit);
+  EXPECT_NE(app_data()->name(), kAppTitle);
+  EXPECT_NE(app_data()->launch_url(), kAppLaunchUrl);
+
+  // Initial app info without icon.
+  {
+    base::RunLoop loop;
+    std::vector<apps::AppPtr> apps;
+    apps.push_back(CreateTestApp());
+    app_service()->OnApps(std::move(apps), apps::AppType::kWeb,
+                          /*should_notify_initialized=*/true);
+    loop.RunUntilIdle();
+  }
+
+  EXPECT_EQ(app_data()->status(), WebKioskAppData::Status::kInstalled);
+  EXPECT_EQ(app_data()->name(), kAppTitle);
+  EXPECT_EQ(app_data()->launch_url(), kAppLaunchUrl);
+  EXPECT_TRUE(app_data()->icon().isNull());
+
+  // Update app info.
+  {
+    base::RunLoop loop;
+    std::vector<apps::AppPtr> apps;
+    apps.push_back(CreateTestApp());
+    apps[0]->name = kAppTitle2;
+    app_service()->OnApps(std::move(apps), apps::AppType::kWeb,
+                          /*should_notify_initialized=*/true);
+    loop.RunUntilIdle();
+  }
+
+  EXPECT_EQ(app_data()->name(), kAppTitle2);
+
+  // Update app icon.
+  {
+    base::RunLoop loop;
+    std::vector<apps::AppPtr> apps;
+    apps.push_back(CreateTestApp());
+    apps[0]->icon_key = apps::IconKey();
+    app_service()->OnApps(std::move(apps), apps::AppType::kWeb,
+                          /*should_notify_initialized=*/true);
+    loop.RunUntilIdle();
+  }
+
+  EXPECT_FALSE(app_data()->icon().isNull());
+  EXPECT_EQ(app_data()->icon().width(), kWebKioskIconSize);
+  EXPECT_EQ(app_data()->icon().height(), kWebKioskIconSize);
+}
+
+TEST_F(WebKioskAppUpdateObserverTest, ShouldNotUpdateAppInfoWhenNotReady) {
+  app_manager()->AddAppForTesting(account_id(), GURL(kAppInstallUrl));
+  EXPECT_EQ(app_data()->status(), WebKioskAppData::Status::kInit);
+  EXPECT_NE(app_data()->name(), kAppTitle);
+  EXPECT_NE(app_data()->launch_url(), kAppLaunchUrl);
+
+  {
+    base::RunLoop loop;
+    std::vector<apps::AppPtr> apps;
+    apps.push_back(CreateTestApp());
+    apps[0]->readiness = apps::Readiness::kUnknown;
+    app_service()->OnApps(std::move(apps), apps::AppType::kWeb,
+                          /*should_notify_initialized=*/true);
+    loop.RunUntilIdle();
+  }
+
+  EXPECT_EQ(app_data()->status(), WebKioskAppData::Status::kInit);
+  EXPECT_NE(app_data()->name(), kAppTitle);
+  EXPECT_NE(app_data()->launch_url(), kAppLaunchUrl);
+}
+
+TEST_F(WebKioskAppUpdateObserverTest, ShouldNotUpdateAppInfoForNonWebApps) {
+  app_manager()->AddAppForTesting(account_id(), GURL(kAppInstallUrl));
+  EXPECT_EQ(app_data()->status(), WebKioskAppData::Status::kInit);
+  EXPECT_NE(app_data()->name(), kAppTitle);
+  EXPECT_NE(app_data()->launch_url(), kAppLaunchUrl);
+
+  {
+    base::RunLoop loop;
+    std::vector<apps::AppPtr> apps;
+    apps.push_back(CreateTestApp());
+    apps[0]->app_type = apps::AppType::kChromeApp;
+    app_service()->OnApps(std::move(apps), apps::AppType::kChromeApp,
+                          /*should_notify_initialized=*/true);
+    loop.RunUntilIdle();
+  }
+
+  EXPECT_EQ(app_data()->status(), WebKioskAppData::Status::kInit);
+  EXPECT_NE(app_data()->name(), kAppTitle);
+  EXPECT_NE(app_data()->launch_url(), kAppLaunchUrl);
+}
+
+TEST_F(WebKioskAppUpdateObserverTest, ShouldNotUpdateAppInfoForNonKioskApps) {
+  app_manager()->AddAppForTesting(account_id(), GURL(kAppInstallUrl));
+  EXPECT_EQ(app_data()->status(), WebKioskAppData::Status::kInit);
+  EXPECT_NE(app_data()->name(), kAppTitle);
+  EXPECT_NE(app_data()->launch_url(), kAppLaunchUrl);
+
+  {
+    base::RunLoop loop;
+    std::vector<apps::AppPtr> apps;
+    apps.push_back(CreateTestApp());
+    apps[0]->install_reason = apps::InstallReason::kPolicy;
+    app_service()->OnApps(std::move(apps), apps::AppType::kWeb,
+                          /*should_notify_initialized=*/true);
+    loop.RunUntilIdle();
+  }
+
+  EXPECT_EQ(app_data()->status(), WebKioskAppData::Status::kInit);
+  EXPECT_NE(app_data()->name(), kAppTitle);
+  EXPECT_NE(app_data()->launch_url(), kAppLaunchUrl);
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ash/crosapi/test/file_manager_ash_browsertest.cc b/chrome/browser/ash/crosapi/test/file_manager_ash_browsertest.cc
index 75b95a5..1a3d709 100644
--- a/chrome/browser/ash/crosapi/test/file_manager_ash_browsertest.cc
+++ b/chrome/browser/ash/crosapi/test/file_manager_ash_browsertest.cc
@@ -3,12 +3,24 @@
 // found in the LICENSE file.
 
 #include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
 #include "base/run_loop.h"
+#include "base/test/bind.h"
+#include "chrome/browser/apps/app_service/app_service_proxy.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/apps/app_service/intent_util.h"
 #include "chrome/browser/ash/crosapi/crosapi_ash.h"
 #include "chrome/browser/ash/crosapi/crosapi_manager.h"
 #include "chrome/browser/ash/crosapi/file_manager_ash.h"
+#include "chrome/browser/ash/file_manager/path_util.h"
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/crosapi/mojom/file_manager.mojom.h"
+#include "components/services/app_service/public/cpp/app_types.h"
+#include "components/services/app_service/public/cpp/intent_filter.h"
 #include "content/public/test/browser_test.h"
 
 namespace crosapi {
@@ -17,10 +29,10 @@
 using FileManagerCrosapiTest = InProcessBrowserTest;
 
 IN_PROC_BROWSER_TEST_F(FileManagerCrosapiTest, ShowItemInFolder) {
-  // TODO(crbug.com/1351650): Add success cases in file manager crosapi test
-  base::FilePath bad_path("/does/not/exist");
+  const base::FilePath bad_path("/does/not/exist");
   base::RunLoop run_loop1;
 
+  // A non-existent path.
   CrosapiManager::Get()->crosapi_ash()->file_manager_ash()->ShowItemInFolder(
       bad_path,
       base::BindOnce(
@@ -31,25 +43,50 @@
           run_loop1.QuitClosure()));
   run_loop1.Run();
 
+  const base::FilePath folder_path =
+      file_manager::util::GetMyFilesFolderForProfile(browser()->profile());
   base::RunLoop run_loop2;
-  base::FilePath malformed_path("!@#$%");
 
+  // A valid folder.
   CrosapiManager::Get()->crosapi_ash()->file_manager_ash()->ShowItemInFolder(
-      malformed_path,
+      folder_path,
       base::BindOnce(
           [](base::RepeatingClosure quit_closure, mojom::OpenResult result) {
-            EXPECT_EQ(result, mojom::OpenResult::kFailedPathNotFound);
+            EXPECT_EQ(result, mojom::OpenResult::kSucceeded);
             quit_closure.Run();
           },
           run_loop2.QuitClosure()));
   run_loop2.Run();
+
+  const base::FilePath file_path = folder_path.Append("test_file.txt");
+  {
+    base::ScopedAllowBlockingForTesting scoped_allow_blocking;
+    EXPECT_TRUE(base::WriteFile(file_path, ""));
+  }
+  base::ScopedClosureRunner scoped_closure_runner(
+      base::BindLambdaForTesting([&]() {
+        base::ScopedAllowBlockingForTesting scoped_allow_blocking;
+        EXPECT_TRUE(base::DeleteFile(file_path));
+      }));
+  base::RunLoop run_loop3;
+
+  // A valid file.
+  CrosapiManager::Get()->crosapi_ash()->file_manager_ash()->ShowItemInFolder(
+      file_path,
+      base::BindOnce(
+          [](base::RepeatingClosure quit_closure, mojom::OpenResult result) {
+            EXPECT_EQ(result, mojom::OpenResult::kSucceeded);
+            quit_closure.Run();
+          },
+          run_loop3.QuitClosure()));
+  run_loop3.Run();
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerCrosapiTest, OpenFolder) {
-  // TODO(crbug.com/1351650): Add success cases in file manager crosapi test
-  base::FilePath bad_path("/does/not/exist");
-  base::RunLoop run_loop;
+  const base::FilePath bad_path("/does/not/exist");
+  base::RunLoop run_loop1;
 
+  // A non-existent path.
   CrosapiManager::Get()->crosapi_ash()->file_manager_ash()->OpenFolder(
       bad_path,
       base::BindOnce(
@@ -57,15 +94,54 @@
             EXPECT_EQ(result, mojom::OpenResult::kFailedPathNotFound);
             quit_closure.Run();
           },
-          run_loop.QuitClosure()));
-  run_loop.Run();
+          run_loop1.QuitClosure()));
+  run_loop1.Run();
+
+  const base::FilePath folder_path =
+      file_manager::util::GetMyFilesFolderForProfile(browser()->profile());
+  base::RunLoop run_loop2;
+
+  // A valid folder.
+  CrosapiManager::Get()->crosapi_ash()->file_manager_ash()->OpenFolder(
+      folder_path,
+      base::BindOnce(
+          [](base::RepeatingClosure quit_closure, mojom::OpenResult result) {
+            EXPECT_EQ(result, mojom::OpenResult::kSucceeded);
+            quit_closure.Run();
+          },
+          run_loop2.QuitClosure()));
+  run_loop2.Run();
+
+  const base::FilePath file_path = folder_path.Append("test_file.txt");
+  {
+    base::ScopedAllowBlockingForTesting scoped_allow_blocking;
+    EXPECT_TRUE(base::WriteFile(file_path, ""));
+  }
+  base::ScopedClosureRunner scoped_closure_runner(
+      base::BindLambdaForTesting([&]() {
+        base::ScopedAllowBlockingForTesting scoped_allow_blocking;
+        EXPECT_TRUE(base::DeleteFile(file_path));
+      }));
+
+  base::RunLoop run_loop3;
+
+  // A valid file but not a folder.
+  CrosapiManager::Get()->crosapi_ash()->file_manager_ash()->OpenFolder(
+      file_path,
+      base::BindOnce(
+          [](base::RepeatingClosure quit_closure, mojom::OpenResult result) {
+            EXPECT_EQ(result, mojom::OpenResult::kFailedInvalidType);
+            quit_closure.Run();
+          },
+          run_loop3.QuitClosure()));
+  run_loop3.Run();
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerCrosapiTest, OpenFile) {
-  // TODO(crbug.com/1351650): Add success cases in file manager crosapi test
-  base::FilePath bad_path("/does/not/exist");
-  base::RunLoop run_loop;
+  const base::FilePath bad_path("/does/not/exist");
+  base::RunLoop run_loop1;
 
+  // A non-existent path.
   CrosapiManager::Get()->crosapi_ash()->file_manager_ash()->OpenFile(
       bad_path,
       base::BindOnce(
@@ -73,8 +149,90 @@
             EXPECT_EQ(result, mojom::OpenResult::kFailedPathNotFound);
             quit_closure.Run();
           },
-          run_loop.QuitClosure()));
-  run_loop.Run();
+          run_loop1.QuitClosure()));
+  run_loop1.Run();
+
+  const base::FilePath folder_path =
+      file_manager::util::GetMyFilesFolderForProfile(browser()->profile());
+  base::RunLoop run_loop2;
+
+  // A valid folder but not a file.
+  CrosapiManager::Get()->crosapi_ash()->file_manager_ash()->OpenFile(
+      folder_path,
+      base::BindOnce(
+          [](base::RepeatingClosure quit_closure, mojom::OpenResult result) {
+            EXPECT_EQ(result, mojom::OpenResult::kFailedInvalidType);
+            quit_closure.Run();
+          },
+          run_loop2.QuitClosure()));
+  run_loop2.Run();
+
+  const base::FilePath txtfile_path = folder_path.Append("test_file.txt");
+  const base::FilePath pngfile_path = folder_path.Append("test_file.png");
+  {
+    base::ScopedAllowBlockingForTesting scoped_allow_blocking;
+    EXPECT_TRUE(base::WriteFile(txtfile_path, ""));
+    EXPECT_TRUE(base::WriteFile(pngfile_path, ""));
+  }
+  base::ScopedClosureRunner scoped_closure_runner(
+      base::BindLambdaForTesting([&]() {
+        base::ScopedAllowBlockingForTesting scoped_allow_blocking;
+        EXPECT_TRUE(base::DeleteFile(txtfile_path));
+        EXPECT_TRUE(base::DeleteFile(pngfile_path));
+      }));
+
+  base::RunLoop run_loop3;
+
+  // A valid file but there is no application to open txt file.
+  CrosapiManager::Get()->crosapi_ash()->file_manager_ash()->OpenFile(
+      txtfile_path,
+      base::BindOnce(
+          [](base::RepeatingClosure quit_closure, mojom::OpenResult result) {
+            EXPECT_EQ(result, mojom::OpenResult::kFailedNoHandlerForFileType);
+            quit_closure.Run();
+          },
+          run_loop3.QuitClosure()));
+  run_loop3.Run();
+
+  std::vector<apps::AppPtr> apps;
+  apps::AppPtr app =
+      std::make_unique<apps::App>(apps::AppType::kChromeApp, "fake-chrome-app");
+  app->handles_intents = true;
+  app->readiness = apps::Readiness::kReady;
+  apps::IntentFilters filters;
+  filters.push_back(apps_util::CreateFileFilter({"view"}, {}, {"txt"},
+                                                "fake-chrome-app", false));
+  app->intent_filters = std::move(filters);
+  apps.push_back(std::move(app));
+  apps::AppServiceProxyFactory::GetForProfile(browser()->profile())
+      ->AppRegistryCache()
+      .OnApps(std::move(apps), apps::AppType::kChromeApp, false);
+
+  base::RunLoop run_loop4;
+
+  // A valid txt file and the app which matches intent filters exists.
+  CrosapiManager::Get()->crosapi_ash()->file_manager_ash()->OpenFile(
+      txtfile_path,
+      base::BindOnce(
+          [](base::RepeatingClosure quit_closure, mojom::OpenResult result) {
+            EXPECT_EQ(result, mojom::OpenResult::kSucceeded);
+            quit_closure.Run();
+          },
+          run_loop4.QuitClosure()));
+  run_loop4.Run();
+
+  base::RunLoop run_loop5;
+
+  // A valid file but there is no application to open png file.
+  CrosapiManager::Get()->crosapi_ash()->file_manager_ash()->OpenFile(
+      pngfile_path,
+      base::BindOnce(
+          [](base::RepeatingClosure quit_closure, mojom::OpenResult result) {
+            EXPECT_EQ(result, mojom::OpenResult::kFailedNoHandlerForFileType);
+            quit_closure.Run();
+          },
+          run_loop5.QuitClosure()));
+  run_loop5.Run();
 }
 
 }  // namespace
diff --git a/chrome/browser/ash/crostini/crostini_manager.cc b/chrome/browser/ash/crostini/crostini_manager.cc
index d350a24..331218b 100644
--- a/chrome/browser/ash/crostini/crostini_manager.cc
+++ b/chrome/browser/ash/crostini/crostini_manager.cc
@@ -2230,16 +2230,6 @@
   crostini_container_properties_observers_.RemoveObserver(observer);
 }
 
-void CrostiniManager::AddContainerStartedObserver(
-    ContainerStartedObserver* observer) {
-  container_started_observers_.AddObserver(observer);
-}
-
-void CrostiniManager::RemoveContainerStartedObserver(
-    ContainerStartedObserver* observer) {
-  container_started_observers_.RemoveObserver(observer);
-}
-
 void CrostiniManager::AddContainerShutdownObserver(
     ContainerShutdownObserver* observer) {
   container_shutdown_observers_.AddObserver(observer);
@@ -2714,9 +2704,6 @@
             guest_os::GuestId(kCrostiniDefaultVmType, signal.vm_name(),
                               signal.container_name())));
   }
-  for (auto& observer : container_started_observers_) {
-    observer.OnContainerStarted(container_id);
-  }
 }
 
 void CrostiniManager::OnGuestFileCorruption(
diff --git a/chrome/browser/ash/crostini/crostini_manager.h b/chrome/browser/ash/crostini/crostini_manager.h
index 2e588cbc..9e818b3 100644
--- a/chrome/browser/ash/crostini/crostini_manager.h
+++ b/chrome/browser/ash/crostini/crostini_manager.h
@@ -129,12 +129,6 @@
       bool can_upgrade) = 0;
 };
 
-class ContainerStartedObserver : public base::CheckedObserver {
- public:
-  // Called when the container has started.
-  virtual void OnContainerStarted(const guest_os::GuestId& container_id) = 0;
-};
-
 class ContainerShutdownObserver : public base::CheckedObserver {
  public:
   // Called when the container has shutdown.
@@ -588,8 +582,6 @@
   void RemoveCrostiniContainerPropertiesObserver(
       CrostiniContainerPropertiesObserver* observer);
 
-  void AddContainerStartedObserver(ContainerStartedObserver* observer);
-  void RemoveContainerStartedObserver(ContainerStartedObserver* observer);
   void AddContainerShutdownObserver(ContainerShutdownObserver* observer);
   void RemoveContainerShutdownObserver(ContainerShutdownObserver* observer);
 
@@ -895,7 +887,6 @@
   base::ObserverList<CrostiniContainerPropertiesObserver>
       crostini_container_properties_observers_;
 
-  base::ObserverList<ContainerStartedObserver> container_started_observers_;
   base::ObserverList<ContainerShutdownObserver> container_shutdown_observers_;
 
   // Contains the types of crostini dialogs currently open. It is generally
diff --git a/chrome/browser/ash/file_manager/file_manager_string_util.cc b/chrome/browser/ash/file_manager/file_manager_string_util.cc
index 04e103d..ca67400 100644
--- a/chrome/browser/ash/file_manager/file_manager_string_util.cc
+++ b/chrome/browser/ash/file_manager/file_manager_string_util.cc
@@ -393,6 +393,7 @@
   SET_STRING("COPY_FILESYSTEM_ERROR", IDS_FILE_BROWSER_COPY_FILESYSTEM_ERROR);
   SET_STRING("EMPTY_TRASH_UNEXPECTED_ERROR",
              IDS_FILE_BROWSER_EMPTY_TRASH_UNEXPECTED_ERROR);
+  SET_STRING("TRASH_UNEXPECTED_ERROR", IDS_FILE_BROWSER_TRASH_UNEXPECTED_ERROR);
   SET_STRING("COPY_FILE_NAME", IDS_FILE_BROWSER_COPY_FILE_NAME);
   SET_STRING("COPY_ITEMS_REMAINING", IDS_FILE_BROWSER_COPY_ITEMS_REMAINING);
   SET_STRING("COPY_FILE_NAME_LONG", IDS_FILE_BROWSER_COPY_FILE_NAME_LONG);
diff --git a/chrome/browser/ash/guest_os/guest_os_session_tracker.cc b/chrome/browser/ash/guest_os/guest_os_session_tracker.cc
index 785dcf6..93887bb 100644
--- a/chrome/browser/ash/guest_os/guest_os_session_tracker.cc
+++ b/chrome/browser/ash/guest_os/guest_os_session_tracker.cc
@@ -204,6 +204,10 @@
   if (cb_list != container_start_callbacks_.end()) {
     cb_list->second->Notify(info);
   }
+  // Let the observers of ANY guest know too.
+  for (auto& observer : container_started_observers_) {
+    observer.OnContainerStarted(id);
+  }
 }
 
 void GuestOsSessionTracker::OnContainerShutdown(
@@ -252,4 +256,14 @@
   return cb_list->Add(std::move(callback));
 }
 
+void GuestOsSessionTracker::AddContainerStartedObserver(
+    ContainerStartedObserver* observer) {
+  container_started_observers_.AddObserver(observer);
+}
+
+void GuestOsSessionTracker::RemoveContainerStartedObserver(
+    ContainerStartedObserver* observer) {
+  container_started_observers_.RemoveObserver(observer);
+}
+
 }  // namespace guest_os
diff --git a/chrome/browser/ash/guest_os/guest_os_session_tracker.h b/chrome/browser/ash/guest_os/guest_os_session_tracker.h
index 8101277..b57223f 100644
--- a/chrome/browser/ash/guest_os/guest_os_session_tracker.h
+++ b/chrome/browser/ash/guest_os/guest_os_session_tracker.h
@@ -37,6 +37,12 @@
   uint32_t sftp_vsock_port;
 };
 
+class ContainerStartedObserver : public base::CheckedObserver {
+ public:
+  // Called when the container has started.
+  virtual void OnContainerStarted(const guest_os::GuestId& container_id) = 0;
+};
+
 class GuestOsSessionTracker : protected ash::ConciergeClient::VmObserver,
                               protected ash::CiceroneClient::Observer,
                               public KeyedService {
@@ -72,6 +78,9 @@
 
   void AddGuestForTesting(const GuestId& id, const GuestInfo& info);
 
+  void AddContainerStartedObserver(ContainerStartedObserver* observer);
+  void RemoveContainerStartedObserver(ContainerStartedObserver* observer);
+
  protected:
   // ash::ConciergeClient::VmObserver overrides.
   void OnVmStarted(const vm_tools::concierge::VmStartedSignal& signal) override;
@@ -109,6 +118,8 @@
   base::flat_map<GuestId, std::unique_ptr<base::OnceCallbackList<void()>>>
       container_shutdown_callbacks_;
 
+  base::ObserverList<ContainerStartedObserver> container_started_observers_;
+
   base::WeakPtrFactory<GuestOsSessionTracker> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/ash/input_method/autocorrect_manager.cc b/chrome/browser/ash/input_method/autocorrect_manager.cc
index 41d3b72..2947e51 100644
--- a/chrome/browser/ash/input_method/autocorrect_manager.cc
+++ b/chrome/browser/ash/input_method/autocorrect_manager.cc
@@ -62,6 +62,8 @@
     SuggestionHandlerInterface* suggestion_handler)
     : suggestion_handler_(suggestion_handler) {}
 
+AutocorrectManager::~AutocorrectManager() = default;
+
 void AutocorrectManager::HandleAutocorrect(const gfx::Range autocorrect_range,
                                            const std::u16string& original_text,
                                            const std::u16string& current_text) {
@@ -79,9 +81,7 @@
       diacritics_insensitive_string_comparator_.Equal(original_text,
                                                       current_text);
 
-  original_text_ = original_text;
-
-  if (autocorrect_pending_) {
+  if (pending_autocorrect_.has_value()) {
     AcceptOrClearPendingAutocorrect();
   }
 
@@ -91,12 +91,11 @@
     return;
   }
 
-  ResetStateVars(); // Ensure all state variables are reset.
-  autocorrect_pending_ = true;
+  pending_autocorrect_ = AutocorrectManager::PendingAutocorrectState(
+      /*original_text=*/original_text, /*start_time=*/base::TimeTicks::Now());
 
   LogAssistiveAutocorrectAction(AutocorrectActions::kUnderlined);
   RecordAssistiveCoverage(AssistiveType::kAutocorrectUnderlined);
-  autocorrect_time_ = base::TimeTicks::Now();
 }
 
 void AutocorrectManager::LogAssistiveAutocorrectAction(
@@ -126,7 +125,8 @@
 
 bool AutocorrectManager::OnKeyEvent(const ui::KeyEvent& event) {
   // OnKeyEvent is only used for interacting with the undo UI.
-  if (!autocorrect_pending_ || !window_visible_ ||
+  if (!pending_autocorrect_.has_value() ||
+      !pending_autocorrect_->undo_window_visible ||
       event.type() != ui::ET_KEY_PRESSED) {
     return false;
   }
@@ -135,7 +135,8 @@
     HighlightUndoButton();
     return true;
   }
-  if (event.code() == ui::DomCode::ENTER && button_highlighted_) {
+  if (event.code() == ui::DomCode::ENTER &&
+      pending_autocorrect_->undo_button_highlighted) {
     UndoAutocorrect();
     return true;
   }
@@ -146,7 +147,10 @@
 void AutocorrectManager::OnSurroundingTextChanged(const std::u16string& text,
                                                   const int cursor_pos,
                                                   const int anchor_pos) {
-  if (!autocorrect_pending_) {
+  if (error_on_hiding_undo_window_) {
+    HideUndoWindow();
+  }
+  if (!pending_autocorrect_.has_value()) {
     return;
   }
 
@@ -177,24 +181,26 @@
   // If it is the first call of the event after handling autocorrect range,
   // initialize the variables and do not process the empty range as it is
   // potentially stale.
-  if (num_inserted_chars_ < 0) {
-    num_inserted_chars_ = 0;
+  if (pending_autocorrect_->num_inserted_chars < 0) {
+    pending_autocorrect_->num_inserted_chars = 0;
   } else if (range.is_empty()) {
     // If it is not the first call and the range is empty, then it means the
     // user interaction has cleared the range.
     AcceptOrClearPendingAutocorrect();
     return;
-  } else if (text.length() > text_length_) {
+  } else if (text.length() > pending_autocorrect_->text_length) {
     // TODO(b/161490813): Fix double counting of emojis and some CJK chars.
 
     // Count characters added between two calls of the event.
-    num_inserted_chars_ += text.length() - text_length_;
+    pending_autocorrect_->num_inserted_chars += text.length() -
+        pending_autocorrect_->text_length;
   }
-  text_length_ = text.length();
+  pending_autocorrect_->text_length = text.length();
 
   // If the number of added characters after setting the pending range is above
   // the threshold, then accept the pending range.
-  if (num_inserted_chars_ >= kDistanceUntilUnderlineHides) {
+  if (pending_autocorrect_->num_inserted_chars >=
+      kDistanceUntilUnderlineHides) {
     AcceptOrClearPendingAutocorrect();
     return;
   }
@@ -218,16 +224,36 @@
                        base::Unretained(this)));
   }
 
-  if (autocorrect_pending_) {
-    // TODO(b/149796494): move this to onblur()
+  context_id_ = context_id;
+  ProcessTextFieldChange();
+}
+
+void AutocorrectManager::OnBlur() {
+  ProcessTextFieldChange();
+}
+
+void AutocorrectManager::ProcessTextFieldChange() {
+  ui::IMEInputContextHandlerInterface* input_context =
+    ui::IMEBridge::Get()->GetInputContextHandler();
+
+  // Clear autocorrect range if any.
+  if (input_context) {
+    HideUndoWindow();
+    input_context->SetAutocorrectRange(gfx::Range());
+  }
+
+  if (pending_autocorrect_.has_value()) {
     LogAssistiveAutocorrectAction(
         AutocorrectActions::kUserExitedTextFieldWithUnderline);
-    ResetStateVars(); // Unset pending state and related variables
+    pending_autocorrect_.reset();
   }
-  context_id_ = context_id;
 }
 
 void AutocorrectManager::UndoAutocorrect() {
+  if (!pending_autocorrect_.has_value()) {
+    return;
+  }
+
   HideUndoWindow();
 
   ui::IMEInputContextHandlerInterface* input_context =
@@ -238,7 +264,7 @@
     input_context->SetComposingRange(autocorrect_range.start(),
                                      autocorrect_range.end(), {});
     input_context->CommitText(
-        original_text_,
+        pending_autocorrect_->original_text,
         ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText);
   } else {
     // NOTE: GetSurroundingTextInfo() could return a stale cache that no longer
@@ -258,21 +284,23 @@
 
     // Replace with the original text.
     input_context->CommitText(
-        original_text_,
+        pending_autocorrect_->original_text,
         ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText);
   }
 
-  ResetStateVars(); // Unset pending state
-
   LogAssistiveAutocorrectAction(AutocorrectActions::kReverted);
   RecordAssistiveCoverage(AssistiveType::kAutocorrectReverted);
   RecordAssistiveSuccess(AssistiveType::kAutocorrectReverted);
-  LogAssistiveAutocorrectDelay(base::TimeTicks::Now() - autocorrect_time_);
+  LogAssistiveAutocorrectDelay(
+    base::TimeTicks::Now() - pending_autocorrect_->start_time);
+
+  pending_autocorrect_.reset();
 }
 
 void AutocorrectManager::ShowUndoWindow(
   gfx::Range range, const std::u16string& text) {
-  if (window_visible_) {
+  if (!pending_autocorrect_.has_value() ||
+      pending_autocorrect_->undo_window_visible) {
     return;
   }
 
@@ -283,19 +311,32 @@
   properties.type = ui::ime::AssistiveWindowType::kUndoWindow;
   properties.visible = true;
   properties.announce_string = l10n_util::GetStringFUTF16(
-      IDS_SUGGESTION_AUTOCORRECT_UNDO_WINDOW_SHOWN, original_text_,
+      IDS_SUGGESTION_AUTOCORRECT_UNDO_WINDOW_SHOWN,
+      pending_autocorrect_->original_text,
       autocorrected_text);
-  button_highlighted_ = false;
-  // TODO(b/161490813): Handle error.
   suggestion_handler_->SetAssistiveWindowProperties(context_id_, properties,
                                                     &error);
+
+  if (!error.empty()) {
+    LOG(ERROR) << "Failed to show autocorrect undo window.";
+    return;
+  }
+
+  // Showing a new undo window overrides the current shown undo window. So
+  // there is no need to first trying to hide the previous one.
+  error_on_hiding_undo_window_ = false;
+
   LogAssistiveAutocorrectAction(AutocorrectActions::kWindowShown);
   RecordAssistiveCoverage(AssistiveType::kAutocorrectWindowShown);
-  window_visible_ = true;
+
+  pending_autocorrect_->undo_button_highlighted = false;
+  pending_autocorrect_->undo_window_visible = true;
 }
 
 void AutocorrectManager::HideUndoWindow() {
-  if (!window_visible_) {
+  if (!error_on_hiding_undo_window_ &&
+      (!pending_autocorrect_.has_value() ||
+       !pending_autocorrect_->undo_window_visible)) {
     return;
   }
 
@@ -303,31 +344,50 @@
   AssistiveWindowProperties properties;
   properties.type = ui::ime::AssistiveWindowType::kUndoWindow;
   properties.visible = false;
-  button_highlighted_ = false;
-  // TODO(b/161490813): Handle error.
   suggestion_handler_->SetAssistiveWindowProperties(context_id_, properties,
                                                     &error);
-  window_visible_ = false;
+
+  if (!error.empty()) {
+    LOG(ERROR) << "Failed to hide autocorrect undo window.";
+    error_on_hiding_undo_window_ = true;
+    return;
+  }
+
+  error_on_hiding_undo_window_ = false;
+
+  if (pending_autocorrect_.has_value()) {
+    pending_autocorrect_->undo_button_highlighted = false;
+    pending_autocorrect_->undo_window_visible = false;
+  }
 }
 
 void AutocorrectManager::HighlightUndoButton() {
-  if (button_highlighted_) {
+  if (!pending_autocorrect_.has_value() ||
+      !pending_autocorrect_->undo_window_visible ||
+      pending_autocorrect_->undo_button_highlighted) {
     return;
   }
 
   std::string error;
-  auto button = ui::ime::AssistiveWindowButton();
+  ui::ime::AssistiveWindowButton button = ui::ime::AssistiveWindowButton();
   button.id = ui::ime::ButtonId::kUndo;
   button.window_type = ui::ime::AssistiveWindowType::kUndoWindow;
   button.announce_string = l10n_util::GetStringFUTF16(
-      IDS_SUGGESTION_AUTOCORRECT_UNDO_BUTTON, original_text_);
+      IDS_SUGGESTION_AUTOCORRECT_UNDO_BUTTON,
+      pending_autocorrect_->original_text);
   suggestion_handler_->SetButtonHighlighted(context_id_, button, true,
                                             &error);
-  button_highlighted_ = true;
+
+  if (!error.empty()) {
+    LOG(ERROR) << "Failed to highlight undo button.";
+    return;
+  }
+
+  pending_autocorrect_->undo_button_highlighted = true;
 }
 
 void AutocorrectManager::AcceptOrClearPendingAutocorrect() {
-  if (!autocorrect_pending_) {
+  if (!pending_autocorrect_.has_value()) {
     return;
   }
 
@@ -345,15 +405,8 @@
     LogAssistiveAutocorrectAction(
       AutocorrectActions::kUserActionClearedUnderline);
   }
-  ResetStateVars(); // Unset pending state
-}
-
-void AutocorrectManager::ResetStateVars() {
-  // Ensure undo window is hidden.
   HideUndoWindow();
-  autocorrect_pending_ = false;
-  num_inserted_chars_ = -1;
-  text_length_ = -1;
+  pending_autocorrect_.reset();
 }
 
 void AutocorrectManager::OnTextFieldContextualInfoChanged(
@@ -366,5 +419,13 @@
   return disabled_by_rule_;
 }
 
+AutocorrectManager::PendingAutocorrectState::PendingAutocorrectState(
+    const std::u16string& original_text,
+    const base::TimeTicks& start_time)
+    : original_text(original_text), start_time(start_time) {}
+
+AutocorrectManager::PendingAutocorrectState::~PendingAutocorrectState() =
+    default;
+
 }  // namespace input_method
 }  // namespace ash
diff --git a/chrome/browser/ash/input_method/autocorrect_manager.h b/chrome/browser/ash/input_method/autocorrect_manager.h
index 3ba769c..a070634 100644
--- a/chrome/browser/ash/input_method/autocorrect_manager.h
+++ b/chrome/browser/ash/input_method/autocorrect_manager.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/ash/input_method/input_method_engine.h"
 #include "chrome/browser/ash/input_method/suggestion_handler_interface.h"
 #include "chrome/browser/ash/input_method/text_field_contextual_info_fetcher.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace ash {
 namespace input_method {
@@ -38,6 +39,7 @@
   // `suggestion_handler_` must be alive for the duration of the lifetime of
   // this instance.
   explicit AutocorrectManager(SuggestionHandlerInterface* suggestion_handler);
+  ~AutocorrectManager();
 
   AutocorrectManager(const AutocorrectManager&) = delete;
   AutocorrectManager& operator=(const AutocorrectManager&) = delete;
@@ -60,6 +62,14 @@
   // Indicates a new text field is focused, used to save context ID.
   void OnFocus(int context_id);
 
+  // Handles OnBlur event and processes any pending autocorrect range.
+  void OnBlur();
+
+  // Processes the state where a user leaves or focuses a text field. At this
+  // stage any pending autocorrect range is cleared and relevant metrics are
+  // recorded.
+  void ProcessTextFieldChange();
+
   // To show the undo window when cursor is in an autocorrected word, this class
   // is notified of surrounding text changes.
   void OnSurroundingTextChanged(const std::u16string& text,
@@ -95,31 +105,48 @@
   // Highlights undo button of undo window if it is visible.
   void HighlightUndoButton();
 
-  // Resets all state variables to their default (no pending range) situation.
-  void ResetStateVars();
+  struct PendingAutocorrectState {
+    explicit PendingAutocorrectState(const std::u16string& original_text,
+                                     const base::TimeTicks& start_time);
+    PendingAutocorrectState(const PendingAutocorrectState& other) = default;
+    ~PendingAutocorrectState();
+
+    // Original text that is now corrected by autocorrect.
+    std::u16string original_text;
+
+    // Number of characters inserted anytime after setting the pending
+    // autocorrect range. Negative means no autocorrect range is pending or a
+    // range has just been set to pending with no OnSurroundingTextChanged
+    // called yet.
+    int num_inserted_chars = -1;
+
+    // Last known text length from OnSurroundingTextChanged after setting
+    // the pending autocorrect range. Negative means no autocorrect range is
+    // pending or a range has just been set to pending with no
+    // OnSurroundingTextChanged called yet.
+    int text_length = -1;
+
+    // Specifies if undo window is visible or not.
+    bool undo_window_visible = false;
+
+    // Specifies if undo button is highlighted or not.
+    bool undo_button_highlighted = false;
+
+    // The time of setting the pending range.
+    base::TimeTicks start_time;
+  };
+
+  // State variable for pending autocorrect, nullopt means no autocorrect
+  // suggestion is pending. The state is kept to avoid issue where
+  // InputContext returns stale autocorrect range.
+  absl::optional<PendingAutocorrectState> pending_autocorrect_;
+
+  // Specifies if the last try for hiding undo window failed. This means
+  // undo window is possibly visible while it must not be.
+  bool error_on_hiding_undo_window_ = false;
 
   SuggestionHandlerInterface* suggestion_handler_;
   int context_id_ = 0;
-  std::u16string original_text_;
-  bool window_visible_ = false;
-  bool button_highlighted_ = false;
-  base::TimeTicks autocorrect_time_;
-
-  // Stores the state where there is a pending/unprocessed autocorrect
-  // suggestion. The state is kept to avoid issue where InputContext returns
-  // stale autocorrect range.
-  bool autocorrect_pending_ = false;
-
-  // Number of characters inserted anytime after setting a pending autocorrect
-  // range. Negative means no autocorrect range is pending or a range has just
-  // been set to pending with no OnSurroundingTextChanged called yet.
-  int num_inserted_chars_ = -1;
-
-  // Last known text length from OnSurroundingTextChanged after setting
-  // a pending autocorrect range. Negative means no autocorrect range is
-  // pending or a range has just been set to pending with no
-  // OnSurroundingTextChanged called yet.
-  int text_length_ = -1;
 
   DiacriticsInsensitiveStringComparator
       diacritics_insensitive_string_comparator_;
diff --git a/chrome/browser/ash/input_method/autocorrect_manager_unittest.cc b/chrome/browser/ash/input_method/autocorrect_manager_unittest.cc
index e85ac67..487de0f5 100644
--- a/chrome/browser/ash/input_method/autocorrect_manager_unittest.cc
+++ b/chrome/browser/ash/input_method/autocorrect_manager_unittest.cc
@@ -25,6 +25,9 @@
 namespace {
 
 using ::testing::_;
+using ::testing::SetArgPointee;
+using ::testing::DoAll;
+using ::testing::Return;
 
 constexpr char kCoverageHistogramName[] = "InputMethod.Assistive.Coverage";
 constexpr char kSuccessHistogramName[] = "InputMethod.Assistive.Success";
@@ -44,7 +47,8 @@
                                  int underlined,
                                  int reverted,
                                  int accepted,
-                                 int cleared_underline) {
+                                 int cleared_underline,
+                                 int exited_text_field_with_underline=0) {
   // Window shown metrics.
   histogram_tester.ExpectBucketCount(kCoverageHistogramName,
                                      AssistiveType::kAutocorrectWindowShown,
@@ -99,8 +103,21 @@
       kAutocorrectActionHistogramName,
       AutocorrectActions::kUserActionClearedUnderline, cleared_underline);
 
+  // Exited text field with underline.
+  histogram_tester.ExpectBucketCount(
+      kAutocorrectActionHistogramName,
+      AutocorrectActions::kUserExitedTextFieldWithUnderline,
+      exited_text_field_with_underline);
+  if (visible_vk) {
+    histogram_tester.ExpectBucketCount(
+        kVKAutocorrectActionHistogramName,
+        AutocorrectActions::kUserExitedTextFieldWithUnderline,
+        exited_text_field_with_underline);
+  }
+
   const int total_actions =
-      window_shown + underlined + reverted + accepted + cleared_underline;
+      window_shown + underlined + reverted + accepted +
+      cleared_underline + exited_text_field_with_underline;
   const int total_coverage = window_shown + underlined + reverted;
 
   // Count total bucket to test side-effects and make the helper robust against
@@ -134,6 +151,17 @@
   return window_properties;
 }
 
+// A helper to create highlighted undo button in assistive window.
+ui::ime::AssistiveWindowButton CreateHighlightedUndoButton(
+    const std::u16string& original_text) {
+  ui::ime::AssistiveWindowButton button = ui::ime::AssistiveWindowButton();
+  button.id = ui::ime::ButtonId::kUndo;
+  button.window_type = ui::ime::AssistiveWindowType::kUndoWindow;
+  button.announce_string = l10n_util::GetStringFUTF16(
+      IDS_SUGGESTION_AUTOCORRECT_UNDO_BUTTON, original_text);
+  return button;
+}
+
 // A helper for creating key event.
 ui::KeyEvent CreateKeyEvent(ui::DomKey key, ui::DomCode code) {
   return ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN, code, ui::EF_NONE,
@@ -396,6 +424,24 @@
             gfx::Range());
 }
 
+TEST_F(AutocorrectManagerTest,
+       OnBlurClearsAutocorrectRange) {
+  manager_.HandleAutocorrect(gfx::Range(1, 4), u"teh", u"the");
+  manager_.OnBlur();
+
+  EXPECT_EQ(mock_ime_input_context_handler_.GetAutocorrectRange(),
+            gfx::Range());
+}
+
+TEST_F(AutocorrectManagerTest,
+       OnFocusClearsAutocorrectRange) {
+  manager_.HandleAutocorrect(gfx::Range(1, 4), u"teh", u"the");
+  manager_.OnFocus(1);
+
+  EXPECT_EQ(mock_ime_input_context_handler_.GetAutocorrectRange(),
+            gfx::Range());
+}
+
 TEST_F(AutocorrectManagerTest, MovingCursorInsideRangeShowsAssistiveWindow) {
   manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/4,
                                     /*anchor_pos=*/4);
@@ -435,6 +481,220 @@
                                     /*anchor_pos=*/4);
 }
 
+TEST_F(AutocorrectManagerTest,
+       MovingCursorRetriesPrevFailedUndoWindowHide) {
+  manager_.HandleAutocorrect(gfx::Range(0, 3), u"teh", u"the");
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/4,
+                                    /*anchor_pos=*/4);
+
+  // Show undo window.
+  AssistiveWindowProperties shown_properties =
+      CreateVisibleUndoWindowProperties(u"teh", u"the");
+  EXPECT_CALL(mock_suggestion_handler_,
+              SetAssistiveWindowProperties(_, shown_properties, _));
+  manager_.OnSurroundingTextChanged(u"the ", 1, 1);
+
+  // Accept autocorrect implicitly and make the request to hide the window
+  // fail.
+  AssistiveWindowProperties hidden_properties =
+      CreateHiddenUndoWindowProperties();
+  EXPECT_CALL(mock_suggestion_handler_,
+              SetAssistiveWindowProperties(_, hidden_properties, _))
+      .WillOnce(DoAll(SetArgPointee<2>("Error"), Return(false)))
+      .RetiresOnSaturation();
+  manager_.OnSurroundingTextChanged(u"the abcd", 8, 8);
+
+  // Now moving cursor should retry hiding autocorrect range.
+  EXPECT_CALL(mock_suggestion_handler_,
+              SetAssistiveWindowProperties(_, hidden_properties, _));
+  manager_.OnSurroundingTextChanged(u"the abcd", 7, 7);
+}
+
+TEST_F(AutocorrectManagerTest,
+       MovingCursorInsideRangeRetriesPrevFailedUndoWindowHide) {
+  manager_.HandleAutocorrect(gfx::Range(0, 3), u"teh", u"the");
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/4,
+                                    /*anchor_pos=*/4);
+
+  // Show undo window.
+  AssistiveWindowProperties shown_properties =
+      CreateVisibleUndoWindowProperties(u"teh", u"the");
+  EXPECT_CALL(mock_suggestion_handler_,
+              SetAssistiveWindowProperties(_, shown_properties, _));
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/1,
+                                    /*anchor_pos=*/1);
+
+  // Make first try to hide the window fail.
+  AssistiveWindowProperties hidden_properties =
+      CreateHiddenUndoWindowProperties();
+  EXPECT_CALL(mock_suggestion_handler_,
+              SetAssistiveWindowProperties(_, hidden_properties, _))
+      .WillOnce(DoAll(SetArgPointee<2>("Error"), Return(false)));
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/4,
+                                    /*anchor_pos=*/4);
+
+  {
+    ::testing::InSequence seq;
+
+    // Retries previously failed undo window hiding which now
+    // succeed.
+    EXPECT_CALL(mock_suggestion_handler_,
+                SetAssistiveWindowProperties(_, hidden_properties, _));
+
+    // Showing new undo window.
+    EXPECT_CALL(mock_suggestion_handler_,
+                SetAssistiveWindowProperties(_, shown_properties, _));
+  }
+
+  // Try hiding undo window before showing it again.
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/1,
+                                    /*anchor_pos=*/1);
+}
+
+TEST_F(AutocorrectManagerTest,
+       ShowingNewUndoWindowStopsRetryingPrevFailedUndoWindowHide) {
+  manager_.HandleAutocorrect(gfx::Range(0, 3), u"teh", u"the");
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/4,
+                                    /*anchor_pos=*/4);
+
+  // Show the undo window first time.
+  AssistiveWindowProperties shown_properties =
+      CreateVisibleUndoWindowProperties(u"teh", u"the");
+  EXPECT_CALL(mock_suggestion_handler_,
+              SetAssistiveWindowProperties(_, shown_properties, _));
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/1,
+                                    /*anchor_pos=*/1);
+
+  // Make first two call to hide undo window to fail.
+  AssistiveWindowProperties hidden_properties =
+      CreateHiddenUndoWindowProperties();
+  EXPECT_CALL(mock_suggestion_handler_,
+              SetAssistiveWindowProperties(_, hidden_properties, _))
+      .Times(2)
+      .WillRepeatedly(DoAll(SetArgPointee<2>("Error"), Return(false)))
+      .RetiresOnSaturation();
+
+  // Handle a new range to allow triggering an undo window override.
+  manager_.HandleAutocorrect(gfx::Range(0, 3), u"teh", u"the");
+
+  // Show a new undo window.
+  EXPECT_CALL(mock_suggestion_handler_,
+              SetAssistiveWindowProperties(_, shown_properties, _));
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/1,
+                                    /*anchor_pos=*/1);
+
+  // No retry should be applied to hide undo window as it is overridden.
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/2,
+                                    /*anchor_pos=*/2);
+}
+
+TEST_F(AutocorrectManagerTest, FocusChangeHidesUndoWindow) {
+  manager_.HandleAutocorrect(gfx::Range(0, 3), u"teh", u"the");
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/4,
+                                    /*anchor_pos=*/4);
+
+  // Show a window.
+  AssistiveWindowProperties shown_properties =
+      CreateVisibleUndoWindowProperties(u"teh", u"the");
+  EXPECT_CALL(mock_suggestion_handler_,
+              SetAssistiveWindowProperties(_, shown_properties, _));
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/1,
+                                    /*anchor_pos=*/1);
+
+  // OnFocus should try hiding the window.
+  AssistiveWindowProperties hidden_properties =
+      CreateHiddenUndoWindowProperties();
+  EXPECT_CALL(mock_suggestion_handler_,
+              SetAssistiveWindowProperties(_, hidden_properties, _));
+
+  manager_.OnFocus(1);
+}
+
+TEST_F(AutocorrectManagerTest, OnFocusRetriesHidingUndoWindow) {
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/4,
+                                    /*anchor_pos=*/4);
+  manager_.HandleAutocorrect(gfx::Range(0, 3), u"teh", u"the");
+
+  // Show undo window.
+  AssistiveWindowProperties shown_properties =
+      CreateVisibleUndoWindowProperties(u"teh", u"the");
+  EXPECT_CALL(mock_suggestion_handler_,
+              SetAssistiveWindowProperties(_, shown_properties, _));
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/1,
+                                    /*anchor_pos=*/1);
+
+  // Make it fail to hide window for OnBlur.
+  AssistiveWindowProperties hidden_properties =
+      CreateHiddenUndoWindowProperties();
+  EXPECT_CALL(mock_suggestion_handler_,
+              SetAssistiveWindowProperties(_, hidden_properties, _))
+      .WillOnce(DoAll(SetArgPointee<2>("Error"), Return(false)));
+  manager_.OnBlur();
+
+  // OnFocus must try to hide undo window.
+  EXPECT_CALL(mock_suggestion_handler_,
+              SetAssistiveWindowProperties(_, hidden_properties, _));
+  manager_.OnFocus(1);
+}
+
+TEST_F(AutocorrectManagerTest,
+       PressingUpArrowKeyHighlightsUndoButtonWhenUndoWindowIsVisible) {
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/4,
+                                    /*anchor_pos=*/4);
+  manager_.HandleAutocorrect(gfx::Range(0, 3), u"teh", u"the");
+
+  {
+    ::testing::InSequence seq;
+
+    AssistiveWindowProperties shown_properties =
+        CreateVisibleUndoWindowProperties(u"teh", u"the");
+
+    EXPECT_CALL(mock_suggestion_handler_,
+                SetAssistiveWindowProperties(_, shown_properties, _));
+
+    ui::ime::AssistiveWindowButton button =
+          CreateHighlightedUndoButton(u"teh");
+    EXPECT_CALL(mock_suggestion_handler_,
+                SetButtonHighlighted(_, button, true, _));
+  }
+
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/1,
+                                    /*anchor_pos=*/1);
+  manager_.OnKeyEvent(CreateKeyEvent(ui::DomKey::NONE, ui::DomCode::ARROW_UP));
+}
+
+TEST_F(AutocorrectManagerTest,
+       PressingEnterKeyHidesUndoWindowWhenButtonIsHighlighted) {
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/4,
+                                    /*anchor_pos=*/4);
+  manager_.HandleAutocorrect(gfx::Range(0, 3), u"teh", u"the");
+
+  {
+    ::testing::InSequence seq;
+
+    AssistiveWindowProperties shown_properties =
+        CreateVisibleUndoWindowProperties(u"teh", u"the");
+
+    EXPECT_CALL(mock_suggestion_handler_,
+                SetAssistiveWindowProperties(_, shown_properties, _));
+
+    ui::ime::AssistiveWindowButton button =
+        CreateHighlightedUndoButton(u"teh");
+    EXPECT_CALL(mock_suggestion_handler_,
+                SetButtonHighlighted(_, button, true, _));
+
+    AssistiveWindowProperties hidden_properties =
+        CreateHiddenUndoWindowProperties();
+    EXPECT_CALL(mock_suggestion_handler_,
+                SetAssistiveWindowProperties(_, hidden_properties, _));
+  }
+
+  manager_.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/1,
+                                    /*anchor_pos=*/1);
+  manager_.OnKeyEvent(CreateKeyEvent(ui::DomKey::NONE, ui::DomCode::ARROW_UP));
+  manager_.OnKeyEvent(CreateKeyEvent(ui::DomKey::NONE, ui::DomCode::ENTER));
+}
+
 TEST_F(AutocorrectManagerTest, UndoAutocorrectSingleWordInComposition) {
   ui::FakeTextInputClient fake_text_input_client(ui::TEXT_INPUT_TYPE_TEXT);
   ui::InputMethodAsh ime(nullptr);
@@ -736,6 +996,58 @@
                               /*cleared_underline=*/0);
 }
 
+TEST_F(AutocorrectManagerTest, OnBlurRecordsMetricsWhenClearingRange) {
+  manager_.HandleAutocorrect(gfx::Range(0, 3), u"teh", u"the");
+  manager_.OnBlur();
+  ExpectAutocorrectHistograms(histogram_tester_, /*visible_vk=*/false,
+                              /*window_shown=*/0, /*underlined=*/1,
+                              /*reverted=*/0, /*accepted=*/0,
+                              /*cleared_underline=*/0,
+                              /*exited_text_field_with_underline=*/1);
+}
+
+TEST_F(AutocorrectManagerTest,
+       OnBlurDoesNoRecordMetricsWhenNoPendingAutocorrectExists) {
+  manager_.OnBlur();
+  ExpectAutocorrectHistograms(histogram_tester_, /*visible_vk=*/false,
+                              /*window_shown=*/0, /*underlined=*/0,
+                              /*reverted=*/0, /*accepted=*/0,
+                              /*cleared_underline=*/0,
+                              /*exited_text_field_with_underline=*/0);
+}
+
+TEST_F(AutocorrectManagerTest,
+       OnBlurDoesNoRecordMetricsWhenInputContextIsNull) {
+  // Make Input context null.
+  ui::IMEBridge::Get()->SetInputContextHandler(nullptr);
+  manager_.OnBlur();
+  ExpectAutocorrectHistograms(histogram_tester_, /*visible_vk=*/false,
+                              /*window_shown=*/0, /*underlined=*/0,
+                              /*reverted=*/0, /*accepted=*/0,
+                              /*cleared_underline=*/0,
+                              /*exited_text_field_with_underline=*/0);
+}
+
+TEST_F(AutocorrectManagerTest, OnFocusRecordsMetricsWhenClearingRange) {
+  manager_.HandleAutocorrect(gfx::Range(0, 3), u"teh", u"the");
+  manager_.OnFocus(1);
+  ExpectAutocorrectHistograms(histogram_tester_, /*visible_vk=*/false,
+                              /*window_shown=*/0, /*underlined=*/1,
+                              /*reverted=*/0, /*accepted=*/0,
+                              /*cleared_underline=*/0,
+                              /*exited_text_field_with_underline=*/1);
+}
+
+TEST_F(AutocorrectManagerTest,
+       OnFocusDoesNoRecordMetricsWhenNoPendingAutocorrectExists) {
+  manager_.OnFocus(1);
+  ExpectAutocorrectHistograms(histogram_tester_, /*visible_vk=*/false,
+                              /*window_shown=*/0, /*underlined=*/0,
+                              /*reverted=*/0, /*accepted=*/0,
+                              /*cleared_underline=*/0,
+                              /*exited_text_field_with_underline=*/0);
+}
+
 TEST_F(AutocorrectManagerTest, HandleAutocorrectRecordsMetricsWhenVkIsVisible) {
   keyboard_client_->set_keyboard_visible_for_test(true);
   manager_.HandleAutocorrect(gfx::Range(0, 3), u"teh", u"the");
@@ -910,6 +1222,54 @@
                               /*cleared_underline=*/0);
 }
 
+TEST_F(AutocorrectManagerTest,
+       OnBlurDoesNotRecordMetricsForStaleAutocorrectRange) {
+  manager_.HandleAutocorrect(gfx::Range(0, 3), u"teh", u"the");
+
+  // Accept autocorrect implicitly.
+  manager_.OnSurroundingTextChanged(u"the abc", 7, 7);
+  ExpectAutocorrectHistograms(histogram_tester_, /*visible_vk=*/false,
+                              /*window_shown=*/0, /*underlined=*/1,
+                              /*reverted=*/0, /*accepted=*/1,
+                              /*cleared_underline=*/0,
+                              /*exited_text_field_with_underline=*/0);
+
+  // Set stale autocorrect range.
+  mock_ime_input_context_handler_.SetAutocorrectRange(gfx::Range(0, 3));
+
+  // Handle a new autocorrect and ensure the metric is not increase twice.
+  manager_.OnBlur();
+  ExpectAutocorrectHistograms(histogram_tester_, /*visible_vk=*/false,
+                              /*window_shown=*/0, /*underlined=*/1,
+                              /*reverted=*/0, /*accepted=*/1,
+                              /*cleared_underline=*/0,
+                              /*exited_text_field_with_underline=*/0);
+}
+
+TEST_F(AutocorrectManagerTest,
+       OnFocusDoesNotRecordMetricsForStaleAutocorrectRange) {
+  manager_.HandleAutocorrect(gfx::Range(0, 3), u"teh", u"the");
+
+  // Accept autocorrect implicitly.
+  manager_.OnBlur();
+  ExpectAutocorrectHistograms(histogram_tester_, /*visible_vk=*/false,
+                              /*window_shown=*/0, /*underlined=*/1,
+                              /*reverted=*/0, /*accepted=*/0,
+                              /*cleared_underline=*/0,
+                              /*exited_text_field_with_underline=*/1);
+
+  // Set stale autocorrect range.
+  mock_ime_input_context_handler_.SetAutocorrectRange(gfx::Range(0, 3));
+
+  // Handle a new autocorrect and ensure the metric is not increase twice.
+  manager_.OnFocus(1);
+  ExpectAutocorrectHistograms(histogram_tester_, /*visible_vk=*/false,
+                              /*window_shown=*/0, /*underlined=*/1,
+                              /*reverted=*/0, /*accepted=*/0,
+                              /*cleared_underline=*/0,
+                              /*exited_text_field_with_underline=*/1);
+}
+
 }  // namespace
 }  // namespace input_method
 }  // namespace ash
diff --git a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
index d126df3..1eee625 100644
--- a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
+++ b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
@@ -777,6 +777,7 @@
 
   if (assistive_suggester_->IsAssistiveFeatureEnabled())
     assistive_suggester_->OnBlur();
+  autocorrect_manager_->OnBlur();
 
   if (ShouldRouteToNativeMojoEngine(engine_id)) {
     if (IsInputMethodBound()) {
diff --git a/chrome/browser/ash/login/wizard_controller_browsertest.cc b/chrome/browser/ash/login/wizard_controller_browsertest.cc
index 0e390be..11131db 100644
--- a/chrome/browser/ash/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/ash/login/wizard_controller_browsertest.cc
@@ -3104,7 +3104,7 @@
     ASSERT_TRUE(chromeos::test_utils::GetTestDataPath(
         "oobe_configuration", "non_empty_configuration.json",
         &configuration_file));
-    command_line->AppendSwitchPath(switches::kFakeOobeConfiguration,
+    command_line->AppendSwitchPath(chromeos::switches::kFakeOobeConfiguration,
                                    configuration_file);
   }
 
@@ -3158,7 +3158,7 @@
     ASSERT_TRUE(chromeos::test_utils::GetTestDataPath(
         "oobe_configuration", "TestEnterpriseRollbackRecover.json",
         &configuration_file));
-    command_line->AppendSwitchPath(switches::kFakeOobeConfiguration,
+    command_line->AppendSwitchPath(chromeos::switches::kFakeOobeConfiguration,
                                    configuration_file);
   }
 
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler_unittest.cc
index a1e2b4d..e274523 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler_unittest.cc
@@ -186,7 +186,7 @@
   }
 
  protected:
-  base::test::SingleThreadTaskEnvironment task_environment_;
+  base::test::TaskEnvironment task_environment_;
 };
 
 class CrosHealthdMetricSamplerTbtTest
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 10999488..3df32c0 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
@@ -6,7 +6,6 @@
 
 #include "ash/components/settings/cros_settings_names.h"
 #include "base/location.h"
-#include "base/logging.h"
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/audio/audio_events_observer.h"
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/network/https_latency_sampler.h"
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/network/network_events_observer.h"
@@ -17,12 +16,9 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/reporting/metric_default_utils.h"
 #include "chrome/browser/chromeos/reporting/network/network_bandwidth_sampler.h"
-#include "components/reporting/client/report_queue.h"
 #include "components/reporting/client/report_queue_configuration.h"
-#include "components/reporting/client/report_queue_factory.h"
 #include "components/reporting/metrics/metric_data_collector.h"
 #include "components/reporting/metrics/metric_event_observer_manager.h"
-#include "components/reporting/metrics/metric_rate_controller.h"
 #include "components/reporting/metrics/metric_report_queue.h"
 #include "components/reporting/metrics/sampler.h"
 #include "components/user_manager/user.h"
@@ -31,134 +27,19 @@
 
 namespace reporting {
 
-bool MetricReportingManager::Delegate::IsAffiliated(Profile* profile) {
+bool MetricReportingManager::Delegate::IsAffiliated(Profile* profile) const {
   const user_manager::User* const user =
       ash::ProfileHelper::Get()->GetUserByProfile(profile);
   return user && user->IsAffiliated();
 }
 
-std::unique_ptr<::reporting::ReportQueue, base::OnTaskRunnerDeleter>
-MetricReportingManager::Delegate::CreateReportQueue(EventType event_type,
-                                                    Destination destination) {
-  return ReportQueueFactory::CreateSpeculativeReportQueue(event_type,
-                                                          destination);
-}
-
-bool MetricReportingManager::Delegate::IsDeprovisioned() {
+bool MetricReportingManager::Delegate::IsDeprovisioned() const {
   return ::ash::DeviceSettingsService::IsInitialized() &&
          ::ash::DeviceSettingsService::Get()->policy_data() &&
          ::ash::DeviceSettingsService::Get()->policy_data()->state() ==
              em::PolicyData::DEPROVISIONED;
 }
 
-std::unique_ptr<MetricReportQueue>
-MetricReportingManager::Delegate::CreateMetricReportQueue(
-    EventType event_type,
-    Destination destination,
-    Priority priority) {
-  std::unique_ptr<MetricReportQueue> metric_report_queue;
-  auto report_queue = CreateReportQueue(event_type, destination);
-  if (report_queue) {
-    metric_report_queue =
-        std::make_unique<MetricReportQueue>(std::move(report_queue), priority);
-  } else {
-    DVLOG(1) << "Cannot create metric report queue, report queue is null";
-  }
-  return metric_report_queue;
-}
-
-std::unique_ptr<MetricReportQueue>
-MetricReportingManager::Delegate::CreatePeriodicUploadReportQueue(
-    EventType event_type,
-    Destination destination,
-    Priority priority,
-    ReportingSettings* reporting_settings,
-    const std::string& rate_setting_path,
-    base::TimeDelta default_rate,
-    int rate_unit_to_ms) {
-  std::unique_ptr<MetricReportQueue> metric_report_queue;
-  auto report_queue = CreateReportQueue(event_type, destination);
-  if (report_queue) {
-    metric_report_queue = std::make_unique<MetricReportQueue>(
-        std::move(report_queue), priority, reporting_settings,
-        rate_setting_path, default_rate, rate_unit_to_ms);
-  } else {
-    DVLOG(1)
-        << "Cannot create periodic upload report queue, report queue is null";
-  }
-  return metric_report_queue;
-}
-
-std::unique_ptr<CollectorBase>
-MetricReportingManager::Delegate::CreateOneShotCollector(
-    Sampler* sampler,
-    MetricReportQueue* metric_report_queue,
-    ReportingSettings* reporting_settings,
-    const std::string& enable_setting_path,
-    bool setting_enabled_default_value) {
-  return std::make_unique<OneShotCollector>(
-      sampler, metric_report_queue, reporting_settings, enable_setting_path,
-      setting_enabled_default_value);
-}
-
-std::unique_ptr<CollectorBase>
-MetricReportingManager::Delegate::CreatePeriodicCollector(
-    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) {
-  return std::make_unique<PeriodicCollector>(
-      sampler, metric_report_queue, reporting_settings, enable_setting_path,
-      setting_enabled_default_value, rate_setting_path, default_rate,
-      rate_unit_to_ms);
-}
-
-std::unique_ptr<CollectorBase>
-MetricReportingManager::Delegate::CreatePeriodicEventCollector(
-    Sampler* sampler,
-    std::unique_ptr<EventDetector> event_detector,
-    std::vector<Sampler*> additional_samplers,
-    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) {
-  return std::make_unique<PeriodicEventCollector>(
-      sampler, std::move(event_detector), std::move(additional_samplers),
-      metric_report_queue, reporting_settings, enable_setting_path,
-      setting_enabled_default_value, rate_setting_path, default_rate,
-      rate_unit_to_ms);
-}
-
-std::unique_ptr<MetricEventObserverManager>
-MetricReportingManager::Delegate::CreateEventObserverManager(
-    std::unique_ptr<MetricEventObserver> event_observer,
-    MetricReportQueue* metric_report_queue,
-    ReportingSettings* reporting_settings,
-    const std::string& enable_setting_path,
-    bool setting_enabled_default_value,
-    std::vector<Sampler*> additional_samplers) {
-  return std::make_unique<MetricEventObserverManager>(
-      std::move(event_observer), metric_report_queue, reporting_settings,
-      enable_setting_path, setting_enabled_default_value,
-      std::move(additional_samplers));
-}
-
-base::TimeDelta MetricReportingManager::Delegate::GetInitDelay() const {
-  return metrics::kInitDelay;
-}
-
-base::TimeDelta MetricReportingManager::Delegate::GetInitialUploadDelay()
-    const {
-  return metrics::kInitialUploadDelay;
-}
-
 // static
 std::unique_ptr<MetricReportingManager> MetricReportingManager::Create(
     policy::ManagedSessionService* managed_session_service) {
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 7a8c26d..1b218c5 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
@@ -17,8 +17,8 @@
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/cros_reporting_settings.h"
 #include "chrome/browser/ash/policy/status_collector/managed_session_service.h"
 #include "chrome/browser/ash/settings/device_settings_service.h"
+#include "chrome/browser/chromeos/reporting/metric_reporting_manager_delegate_base.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "components/reporting/client/report_queue_configuration.h"
 #include "components/reporting/proto/synced/record_constants.pb.h"
 
@@ -29,7 +29,6 @@
 class MetricEventObserverManager;
 class MetricReportQueue;
 class CollectorBase;
-class ReportQueue;
 class Sampler;
 
 // Class to initialize and start info, event, and telemetry collection and
@@ -39,77 +38,18 @@
  public:
   // Delegate class for dependencies and behaviors that need to be overridden
   // for testing purposes.
-  class Delegate {
+  class Delegate : public metrics::MetricReportingManagerDelegateBase {
    public:
     Delegate() = default;
 
     Delegate(const Delegate& other) = delete;
     Delegate& operator=(const Delegate& other) = delete;
 
-    virtual ~Delegate() = default;
+    ~Delegate() override = default;
 
-    virtual bool IsAffiliated(Profile* profile);
+    bool IsAffiliated(Profile* profile) const override;
 
-    virtual std::unique_ptr<ReportQueue, base::OnTaskRunnerDeleter>
-    CreateReportQueue(EventType event_type, Destination destination);
-
-    virtual bool IsDeprovisioned();
-
-    virtual std::unique_ptr<MetricReportQueue> CreateMetricReportQueue(
-        EventType event_type,
-        Destination destination,
-        Priority priority);
-
-    virtual std::unique_ptr<MetricReportQueue> CreatePeriodicUploadReportQueue(
-        EventType event_type,
-        Destination destination,
-        Priority priority,
-        ReportingSettings* reporting_settings,
-        const std::string& rate_setting_path,
-        base::TimeDelta default_rate,
-        int rate_unit_to_ms = 1);
-
-    virtual std::unique_ptr<CollectorBase> CreateOneShotCollector(
-        Sampler* sampler,
-        MetricReportQueue* metric_report_queue,
-        ReportingSettings* reporting_settings,
-        const std::string& enable_setting_path,
-        bool setting_enabled_default_value);
-
-    virtual std::unique_ptr<CollectorBase> CreatePeriodicCollector(
-        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);
-
-    virtual std::unique_ptr<CollectorBase> CreatePeriodicEventCollector(
-        Sampler* sampler,
-        std::unique_ptr<EventDetector> event_detector,
-        std::vector<Sampler*> additional_samplers,
-        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);
-
-    virtual std::unique_ptr<MetricEventObserverManager>
-    CreateEventObserverManager(
-        std::unique_ptr<MetricEventObserver> event_observer,
-        MetricReportQueue* metric_report_queue,
-        ReportingSettings* reporting_settings,
-        const std::string& enable_setting_path,
-        bool setting_enabled_default_value,
-        std::vector<Sampler*> additional_samplers);
-
-    base::TimeDelta GetInitDelay() const;
-
-    base::TimeDelta GetInitialUploadDelay() const;
+    bool IsDeprovisioned() const override;
   };
 
   static std::unique_ptr<MetricReportingManager> Create(
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 1896982..5e3ac41 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
@@ -99,9 +99,9 @@
 
   ~MockDelegate() override = default;
 
-  MOCK_METHOD(bool, IsAffiliated, (Profile * profile), (override));
+  MOCK_METHOD(bool, IsAffiliated, (Profile * profile), (const, override));
 
-  MOCK_METHOD(bool, IsDeprovisioned, (), (override));
+  MOCK_METHOD(bool, IsDeprovisioned, (), (const, override));
 
   MOCK_METHOD(std::unique_ptr<MetricReportQueue>,
               CreateMetricReportQueue,
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/network/https_latency_sampler_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/network/https_latency_sampler_unittest.cc
index 3b09da5..3d615061 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/network/https_latency_sampler_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/network/https_latency_sampler_unittest.cc
@@ -133,7 +133,7 @@
 };
 
 TEST(HttpsLatencySamplerTest, NoProblem) {
-  base::test::SingleThreadTaskEnvironment task_environment;
+  base::test::TaskEnvironment task_environment;
 
   FakeNetworkDiagnostics diagnostics;
   int latency_ms = 100;
@@ -168,7 +168,7 @@
 }
 
 TEST(HttpsLatencySamplerTest, FailedRequests) {
-  base::test::SingleThreadTaskEnvironment task_environment;
+  base::test::TaskEnvironment task_environment;
 
   FakeNetworkDiagnostics diagnostics;
   diagnostics.SetResultProblem(HttpsLatencyProblemMojom::kFailedHttpsRequests);
@@ -202,7 +202,7 @@
 }
 
 TEST(HttpsLatencySamplerTest, OverlappingCalls) {
-  base::test::SingleThreadTaskEnvironment task_environment;
+  base::test::TaskEnvironment task_environment;
 
   FakeNetworkDiagnostics diagnostics;
   diagnostics.SetResultProblem(HttpsLatencyProblemMojom::kFailedDnsResolutions);
@@ -259,7 +259,7 @@
 }
 
 TEST(HttpsLatencySamplerTest, SuccessiveCalls) {
-  base::test::SingleThreadTaskEnvironment task_environment;
+  base::test::TaskEnvironment task_environment;
 
   FakeNetworkDiagnostics diagnostics;
   HttpsLatencySampler sampler(
@@ -363,7 +363,7 @@
     }
     base::RunLoop().RunUntilIdle();
   }
-  base::test::SingleThreadTaskEnvironment task_environment_;
+  base::test::TaskEnvironment task_environment_;
 
   ::ash::NetworkHandlerTestHelper network_handler_test_helper_;
 };
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler_unittest.cc
index 246f8ec..44a092b4 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler_unittest.cc
@@ -176,7 +176,7 @@
 
   std::unique_ptr<test::FakeSampler> https_latency_sampler_;
 
-  base::test::SingleThreadTaskEnvironment task_environment_;
+  base::test::TaskEnvironment task_environment_;
 
   ::ash::NetworkHandlerTestHelper network_handler_test_helper_;
 
diff --git a/chrome/browser/ash/policy/status_collector/device_status_collector.cc b/chrome/browser/ash/policy/status_collector/device_status_collector.cc
index e7c811720..2b96a9a 100644
--- a/chrome/browser/ash/policy/status_collector/device_status_collector.cc
+++ b/chrome/browser/ash/policy/status_collector/device_status_collector.cc
@@ -914,6 +914,10 @@
                   kUnknown:
                 LOG(ERROR) << "cros_healthd: Unknown storage vendor tag";
                 break;
+              case chromeos::cros_healthd::mojom::BlockDeviceVendor::Tag::
+                  kJedecManfid:
+                disk_info_out->set_jedec_manfid(vendor_id->get_jedec_manfid());
+                break;
             }
 
             // product_id
@@ -981,6 +985,11 @@
                   kUnknown:
                 LOG(ERROR) << "cros_healthd: Unknown storage firmware tag";
                 break;
+              case chromeos::cros_healthd::mojom::BlockDeviceFirmware::Tag::
+                  kUfsFwrev:
+                disk_info_out->set_ufs_firmware_rev(
+                    fw_version->get_ufs_fwrev());
+                break;
             }
 
             switch (storage->purpose) {
diff --git a/chrome/browser/ash/power/ml/OWNERS b/chrome/browser/ash/power/ml/OWNERS
index 0b16b90..f560ada4 100644
--- a/chrome/browser/ash/power/ml/OWNERS
+++ b/chrome/browser/ash/power/ml/OWNERS
@@ -1,3 +1,2 @@
 amoylan@chromium.org
-jiameng@chromium.org
 martis@chromium.org
diff --git a/chrome/browser/ash/system_web_apps/BUILD.gn b/chrome/browser/ash/system_web_apps/BUILD.gn
index 0fb1779c..547d1da 100644
--- a/chrome/browser/ash/system_web_apps/BUILD.gn
+++ b/chrome/browser/ash/system_web_apps/BUILD.gn
@@ -24,6 +24,7 @@
     "//ash/webui/camera_app_ui",
     "//ash/webui/connectivity_diagnostics",
     "//ash/webui/eche_app_ui",
+    "//ash/webui/face_ml_app_ui",
     "//ash/webui/file_manager:file_manager_ui",
     "//ash/webui/firmware_update_ui",
     "//ash/webui/help_app_ui",
@@ -47,7 +48,6 @@
   ]
 
   if (!is_official_build) {
-    deps += [ "//ash/webui/facial_ml_app_ui" ]
     deps += [ "//ash/webui/sample_system_web_app_ui" ]
   }
 }
diff --git a/chrome/browser/ash/system_web_apps/system_web_app_manager.cc b/chrome/browser/ash/system_web_apps/system_web_app_manager.cc
index 961a0bba..558db78 100644
--- a/chrome/browser/ash/system_web_apps/system_web_app_manager.cc
+++ b/chrome/browser/ash/system_web_apps/system_web_app_manager.cc
@@ -44,6 +44,7 @@
 #include "chrome/browser/ash/web_applications/crosh_system_web_app_info.h"
 #include "chrome/browser/ash/web_applications/diagnostics_system_web_app_info.h"
 #include "chrome/browser/ash/web_applications/eche_app_info.h"
+#include "chrome/browser/ash/web_applications/face_ml_system_web_app_info.h"
 #include "chrome/browser/ash/web_applications/file_manager_web_app_info.h"
 #include "chrome/browser/ash/web_applications/firmware_update_system_web_app_info.h"
 #include "chrome/browser/ash/web_applications/help_app/help_app_web_app_info.h"
@@ -96,7 +97,6 @@
 #include "url/origin.h"
 #if !defined(OFFICIAL_BUILD)
 #include "chrome/browser/ash/web_applications/demo_mode_web_app_info.h"
-#include "chrome/browser/ash/web_applications/facial_ml_system_web_app_info.h"
 #include "chrome/browser/ash/web_applications/sample_system_web_app_info.h"
 #endif  // !defined(OFFICIAL_BUILD)
 
@@ -139,10 +139,10 @@
   info_vec.push_back(
       std::make_unique<FirmwareUpdateSystemAppDelegate>(profile));
   info_vec.push_back(std::make_unique<OsFlagsSystemWebAppDelegate>(profile));
+  info_vec.push_back(std::make_unique<FaceMLSystemAppDelegate>(profile));
 
 #if !defined(OFFICIAL_BUILD)
   info_vec.push_back(std::make_unique<DemoModeSystemAppDelegate>(profile));
-  info_vec.push_back(std::make_unique<FacialMLSystemAppDelegate>(profile));
   info_vec.push_back(std::make_unique<SampleSystemAppDelegate>(profile));
 #endif  // !defined(OFFICIAL_BUILD)
 
diff --git a/chrome/browser/ash/system_web_apps/types/system_web_app_data.proto b/chrome/browser/ash/system_web_apps/types/system_web_app_data.proto
index fc828ac..2bd08f3 100644
--- a/chrome/browser/ash/system_web_apps/types/system_web_app_data.proto
+++ b/chrome/browser/ash/system_web_apps/types/system_web_app_data.proto
@@ -34,7 +34,7 @@
     OS_URL_HANDLER = 21;
     FIRMWARE_UPDATE = 22;
     OS_FLAGS = 23;
-    FACIAL_ML = 24;
+    FACE_ML = 24;
   };
 
   optional SystemWebAppType system_app_type = 1;
diff --git a/chrome/browser/ash/web_applications/facial_ml_system_web_app_info.cc b/chrome/browser/ash/web_applications/face_ml_system_web_app_info.cc
similarity index 63%
rename from chrome/browser/ash/web_applications/facial_ml_system_web_app_info.cc
rename to chrome/browser/ash/web_applications/face_ml_system_web_app_info.cc
index 4e321876..09d3369 100644
--- a/chrome/browser/ash/web_applications/facial_ml_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/face_ml_system_web_app_info.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/web_applications/facial_ml_system_web_app_info.h"
+#include "chrome/browser/ash/web_applications/face_ml_system_web_app_info.h"
 
 #include <memory>
 
 #include "ash/constants/ash_features.h"
-#include "ash/webui/facial_ml_app_ui/url_constants.h"
-#include "ash/webui/grit/ash_facial_ml_app_resources.h"
+#include "ash/webui/face_ml_app_ui/url_constants.h"
+#include "ash/webui/grit/ash_face_ml_app_resources.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/apps/app_service/app_launch_params.h"
 #include "chrome/browser/ash/web_applications/system_web_app_install_utils.h"
@@ -23,18 +23,18 @@
 constexpr gfx::Size DEFAULT_SIZE(800, 600);
 }  // namespace
 
-std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForFacialMLApp() {
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForFaceMLApp() {
   std::unique_ptr<WebAppInstallInfo> info =
       std::make_unique<WebAppInstallInfo>();
-  info->start_url = GURL(ash::kChromeUIFacialMLAppURL);
-  info->scope = GURL(ash::kChromeUIFacialMLAppURL);
+  info->start_url = GURL(ash::kChromeUIFaceMLAppURL);
+  info->scope = GURL(ash::kChromeUIFaceMLAppURL);
   // TODO(b/239374316): Convert the title to a localized string
-  info->title = u"Facial ML";
+  info->title = u"Face ML";
   web_app::CreateIconInfoForSystemWebApp(
       info->start_url,
       {
-          {"app_icon_192.png", 192, IDR_ASH_FACIAL_ML_APP_APP_ICON_192_PNG},
-          {"app_icon_512.png", 512, IDR_ASH_FACIAL_ML_APP_APP_ICON_512_PNG},
+          {"app_icon_192.png", 192, IDR_ASH_FACE_ML_APP_APP_ICON_192_PNG},
+          {"app_icon_512.png", 512, IDR_ASH_FACE_ML_APP_APP_ICON_512_PNG},
       },
       *info);
 
@@ -57,39 +57,39 @@
   return info;
 }
 
-FacialMLSystemAppDelegate::FacialMLSystemAppDelegate(Profile* profile)
+FaceMLSystemAppDelegate::FaceMLSystemAppDelegate(Profile* profile)
     : ash::SystemWebAppDelegate(
-          ash::SystemWebAppType::FACIAL_ML,
-          "FacialML",
-          GURL(ash::kChromeUIFacialMLAppURL),
+          ash::SystemWebAppType::FACE_ML,
+          "FaceML",
+          GURL(ash::kChromeUIFaceMLAppURL),
           profile,
-          ash::OriginTrialsMap({{ash::GetOrigin(ash::kChromeUIFacialMLAppURL),
+          ash::OriginTrialsMap({{ash::GetOrigin(ash::kChromeUIFaceMLAppURL),
                                  {"FileHandling"}}})) {}
 
-std::unique_ptr<WebAppInstallInfo> FacialMLSystemAppDelegate::GetWebAppInfo()
+std::unique_ptr<WebAppInstallInfo> FaceMLSystemAppDelegate::GetWebAppInfo()
     const {
-  return CreateWebAppInfoForFacialMLApp();
+  return CreateWebAppInfoForFaceMLApp();
 }
 
-gfx::Rect FacialMLSystemAppDelegate::GetDefaultBounds(Browser* browser) const {
+gfx::Rect FaceMLSystemAppDelegate::GetDefaultBounds(Browser* browser) const {
   gfx::Rect bounds =
       display::Screen::GetScreen()->GetDisplayForNewWindows().work_area();
   bounds.ClampToCenteredSize(DEFAULT_SIZE);
   return bounds;
 }
 
-bool FacialMLSystemAppDelegate::IsAppEnabled() const {
-  return base::FeatureList::IsEnabled(ash::features::kFaceMlApp);
+bool FaceMLSystemAppDelegate::IsAppEnabled() const {
+  return base::FeatureList::IsEnabled(ash::features::kFaceMLApp);
 }
 
-bool FacialMLSystemAppDelegate::ShouldCaptureNavigations() const {
+bool FaceMLSystemAppDelegate::ShouldCaptureNavigations() const {
   return true;
 }
 
-bool FacialMLSystemAppDelegate::ShouldShowNewWindowMenuOption() const {
+bool FaceMLSystemAppDelegate::ShouldShowNewWindowMenuOption() const {
   return false;
 }
 
-bool FacialMLSystemAppDelegate::ShouldReuseExistingWindow() const {
+bool FaceMLSystemAppDelegate::ShouldReuseExistingWindow() const {
   return true;
 }
diff --git a/chrome/browser/ash/web_applications/facial_ml_system_web_app_info.h b/chrome/browser/ash/web_applications/face_ml_system_web_app_info.h
similarity index 69%
rename from chrome/browser/ash/web_applications/facial_ml_system_web_app_info.h
rename to chrome/browser/ash/web_applications/face_ml_system_web_app_info.h
index 2fbc52b..130033a 100644
--- a/chrome/browser/ash/web_applications/facial_ml_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/face_ml_system_web_app_info.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_WEB_APPLICATIONS_FACIAL_ML_SYSTEM_WEB_APP_INFO_H_
-#define CHROME_BROWSER_ASH_WEB_APPLICATIONS_FACIAL_ML_SYSTEM_WEB_APP_INFO_H_
+#ifndef CHROME_BROWSER_ASH_WEB_APPLICATIONS_FACE_ML_SYSTEM_WEB_APP_INFO_H_
+#define CHROME_BROWSER_ASH_WEB_APPLICATIONS_FACE_ML_SYSTEM_WEB_APP_INFO_H_
 
 #include "chrome/browser/ash/system_web_apps/types/system_web_app_background_task_info.h"
 #include "chrome/browser/ash/system_web_apps/types/system_web_app_delegate.h"
@@ -13,9 +13,9 @@
 
 struct WebAppInstallInfo;
 
-class FacialMLSystemAppDelegate : public ash::SystemWebAppDelegate {
+class FaceMLSystemAppDelegate : public ash::SystemWebAppDelegate {
  public:
-  explicit FacialMLSystemAppDelegate(Profile* profile);
+  explicit FaceMLSystemAppDelegate(Profile* profile);
 
   // ash::SystemWebAppDelegate overrides:
   std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
@@ -27,6 +27,6 @@
 };
 
 // Return a WebAppInstallInfo used to install the app.
-std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForFacialMLApp();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForFaceMLApp();
 
-#endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_FACIAL_ML_SYSTEM_WEB_APP_INFO_H_
+#endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_FACE_ML_SYSTEM_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/wilco_dtc_supportd/fake_wilco_dtc_supportd_client.cc b/chrome/browser/ash/wilco_dtc_supportd/fake_wilco_dtc_supportd_client.cc
index 4c1fd53..e11d1d6 100644
--- a/chrome/browser/ash/wilco_dtc_supportd/fake_wilco_dtc_supportd_client.cc
+++ b/chrome/browser/ash/wilco_dtc_supportd/fake_wilco_dtc_supportd_client.cc
@@ -32,7 +32,7 @@
 
 void FakeWilcoDtcSupportdClient::BootstrapMojoConnection(
     base::ScopedFD fd,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   if (bootstrap_mojo_connection_result_) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
@@ -71,7 +71,7 @@
   bootstrap_mojo_connection_result_ = bootstrap_mojo_connection_result;
   if (!bootstrap_mojo_connection_result_)
     return;
-  std::vector<VoidDBusMethodCallback> callbacks;
+  std::vector<chromeos::VoidDBusMethodCallback> callbacks;
   callbacks.swap(pending_bootstrap_mojo_connection_callbacks_);
   for (auto& callback : callbacks)
     std::move(callback).Run(*bootstrap_mojo_connection_result_);
diff --git a/chrome/browser/ash/wilco_dtc_supportd/fake_wilco_dtc_supportd_client.h b/chrome/browser/ash/wilco_dtc_supportd/fake_wilco_dtc_supportd_client.h
index bed75c5..f712772e 100644
--- a/chrome/browser/ash/wilco_dtc_supportd/fake_wilco_dtc_supportd_client.h
+++ b/chrome/browser/ash/wilco_dtc_supportd/fake_wilco_dtc_supportd_client.h
@@ -30,8 +30,9 @@
   // WilcoDtcSupportdClient overrides:
   void WaitForServiceToBeAvailable(
       WaitForServiceToBeAvailableCallback callback) override;
-  void BootstrapMojoConnection(base::ScopedFD fd,
-                               VoidDBusMethodCallback callback) override;
+  void BootstrapMojoConnection(
+      base::ScopedFD fd,
+      chromeos::VoidDBusMethodCallback callback) override;
 
   // Whether there's a pending WaitForServiceToBeAvailable call.
   int wait_for_service_to_be_available_in_flight_call_count() const;
@@ -55,7 +56,7 @@
       pending_wait_for_service_to_be_available_callbacks_;
 
   absl::optional<bool> bootstrap_mojo_connection_result_;
-  std::vector<VoidDBusMethodCallback>
+  std::vector<chromeos::VoidDBusMethodCallback>
       pending_bootstrap_mojo_connection_callbacks_;
 };
 
diff --git a/chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_client.cc b/chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_client.cc
index 1ced412..db5a8db 100644
--- a/chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_client.cc
+++ b/chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_client.cc
@@ -21,7 +21,7 @@
 
 WilcoDtcSupportdClient* g_instance = nullptr;
 
-void OnVoidDBusMethod(VoidDBusMethodCallback callback,
+void OnVoidDBusMethod(chromeos::VoidDBusMethodCallback callback,
                       dbus::Response* response) {
   std::move(callback).Run(response != nullptr);
 }
@@ -40,8 +40,9 @@
   // WilcoDtcSupportdClient overrides:
   void WaitForServiceToBeAvailable(
       WaitForServiceToBeAvailableCallback callback) override;
-  void BootstrapMojoConnection(base::ScopedFD fd,
-                               VoidDBusMethodCallback callback) override;
+  void BootstrapMojoConnection(
+      base::ScopedFD fd,
+      chromeos::VoidDBusMethodCallback callback) override;
   void Init(dbus::Bus* bus) override;
 
  private:
@@ -61,7 +62,7 @@
 
 void WilcoDtcSupportdClientImpl::BootstrapMojoConnection(
     base::ScopedFD fd,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   dbus::MethodCall method_call(
       ::diagnostics::kWilcoDtcSupportdServiceInterface,
       ::diagnostics::kWilcoDtcSupportdBootstrapMojoConnectionMethod);
diff --git a/chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_client.h b/chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_client.h
index a13cbbfc..6c28b81 100644
--- a/chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_client.h
+++ b/chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_client.h
@@ -36,8 +36,9 @@
 
   // Bootstrap the Mojo connection between Chrome and the wilco_dtc_supportd
   // daemon. |fd| is the file descriptor with the child end of the Mojo pipe.
-  virtual void BootstrapMojoConnection(base::ScopedFD fd,
-                                       VoidDBusMethodCallback callback) = 0;
+  virtual void BootstrapMojoConnection(
+      base::ScopedFD fd,
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
  protected:
   // Create() should be used instead.
diff --git a/chrome/browser/chrome_navigation_browsertest.cc b/chrome/browser/chrome_navigation_browsertest.cc
index fa32e376..b58ebb86 100644
--- a/chrome/browser/chrome_navigation_browsertest.cc
+++ b/chrome/browser/chrome_navigation_browsertest.cc
@@ -1287,7 +1287,7 @@
 
 // Tests the behavior of navigating to a PDF when mobile emulation is enabled.
 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTestWithMobileEmulation,
-                       NavigateToPDFWithMobileEmulation) {
+                       DISABLED_NavigateToPDFWithMobileEmulation) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
   GURL initial_url = embedded_test_server()->GetURL("/title1.html");
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 7c7b05a..04c504a 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -142,6 +142,7 @@
     "//ash/webui/connectivity_diagnostics",
     "//ash/webui/diagnostics_ui",
     "//ash/webui/eche_app_ui",
+    "//ash/webui/face_ml_app_ui",
     "//ash/webui/file_manager:file_manager_ui",
     "//ash/webui/file_manager:file_manager_untrusted_ui",
     "//ash/webui/file_manager/resources:file_manager_swa_resources_grit",
@@ -165,6 +166,7 @@
     "//ash/webui/resources:connectivity_diagnostics_resources_grit",
     "//ash/webui/resources:diagnostics_app_resources_grit",
     "//ash/webui/resources:eche_bundle_resources_grit",
+    "//ash/webui/resources:face_ml_app_resources_grit",
     "//ash/webui/resources:firmware_update_app_resources_grit",
     "//ash/webui/resources:help_app_resources_grit",
     "//ash/webui/resources:media_app_bundle_resources_grit",
@@ -453,7 +455,6 @@
     "//components/reporting/util:status",
     "//components/reporting/util:status_proto",
     "//components/reporting/util:task_runner_context",
-    "//components/reporting/util:test_callbacks_support",
     "//components/rlz",
     "//components/safe_browsing/core/browser/db:metadata_proto",
     "//components/safe_browsing/core/common/proto:csd_proto",
@@ -1979,6 +1980,8 @@
     "../ash/web_applications/diagnostics_system_web_app_info.h",
     "../ash/web_applications/eche_app_info.cc",
     "../ash/web_applications/eche_app_info.h",
+    "../ash/web_applications/face_ml_system_web_app_info.cc",
+    "../ash/web_applications/face_ml_system_web_app_info.h",
     "../ash/web_applications/file_manager_web_app_info.cc",
     "../ash/web_applications/file_manager_web_app_info.h",
     "../ash/web_applications/firmware_update_system_web_app_info.cc",
@@ -2344,9 +2347,7 @@
   if (!is_official_build) {
     deps += [
       "//ash/webui/demo_mode_app_ui",
-      "//ash/webui/facial_ml_app_ui",
       "//ash/webui/resources:demo_mode_app_resources_grit",
-      "//ash/webui/resources:facial_ml_app_resources_grit",
       "//ash/webui/resources:sample_system_web_app_resources_grit",
       "//ash/webui/resources:sample_system_web_app_untrusted_resources_grit",
       "//ash/webui/sample_system_web_app_ui",
@@ -2354,8 +2355,6 @@
     sources += [
       "../ash/web_applications/demo_mode_web_app_info.cc",
       "../ash/web_applications/demo_mode_web_app_info.h",
-      "../ash/web_applications/facial_ml_system_web_app_info.cc",
-      "../ash/web_applications/facial_ml_system_web_app_info.h",
       "../ash/web_applications/sample_system_web_app_info.cc",
       "../ash/web_applications/sample_system_web_app_info.h",
     ]
@@ -2716,6 +2715,7 @@
     "../ash/app_mode/startup_app_launcher_unittest.cc",
     "../ash/app_mode/web_app/web_kiosk_app_launcher_unittest.cc",
     "../ash/app_mode/web_app/web_kiosk_app_service_launcher_unittest.cc",
+    "../ash/app_mode/web_app/web_kiosk_app_update_observer_unittest.cc",
     "../ash/app_restore/arc_ghost_window_view_unittest.cc",
     "../ash/app_restore/arc_window_utils_unittest.cc",
     "../ash/app_restore/full_restore_prefs_unittest.cc",
diff --git a/chrome/browser/chromeos/reporting/metric_reporting_manager_delegate_base.cc b/chrome/browser/chromeos/reporting/metric_reporting_manager_delegate_base.cc
new file mode 100644
index 0000000..aca89b9
--- /dev/null
+++ b/chrome/browser/chromeos/reporting/metric_reporting_manager_delegate_base.cc
@@ -0,0 +1,135 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/reporting/metric_reporting_manager_delegate_base.h"
+
+#include "chrome/browser/chromeos/reporting/metric_default_utils.h"
+#include "chrome/browser/enterprise/util/affiliation.h"
+#include "components/reporting/client/report_queue_factory.h"
+#include "components/reporting/metrics/metric_report_queue.h"
+
+namespace reporting::metrics {
+namespace {
+
+std::unique_ptr<::reporting::ReportQueue, base::OnTaskRunnerDeleter>
+CreateReportQueue(EventType event_type, Destination destination) {
+  return ReportQueueFactory::CreateSpeculativeReportQueue(event_type,
+                                                          destination);
+}
+
+}  // namespace
+
+std::unique_ptr<MetricReportQueue>
+MetricReportingManagerDelegateBase::CreateMetricReportQueue(
+    EventType event_type,
+    Destination destination,
+    Priority priority) {
+  std::unique_ptr<MetricReportQueue> metric_report_queue;
+  auto report_queue = CreateReportQueue(event_type, destination);
+  if (report_queue) {
+    metric_report_queue =
+        std::make_unique<MetricReportQueue>(std::move(report_queue), priority);
+  } else {
+    LOG(ERROR) << "Cannot create metric report queue, report queue is null";
+  }
+  return metric_report_queue;
+}
+
+std::unique_ptr<MetricReportQueue>
+MetricReportingManagerDelegateBase::CreatePeriodicUploadReportQueue(
+    EventType event_type,
+    Destination destination,
+    Priority priority,
+    ReportingSettings* reporting_settings,
+    const std::string& rate_setting_path,
+    base::TimeDelta default_rate,
+    int rate_unit_to_ms) {
+  std::unique_ptr<MetricReportQueue> metric_report_queue;
+  auto report_queue = CreateReportQueue(event_type, destination);
+  if (report_queue) {
+    metric_report_queue = std::make_unique<MetricReportQueue>(
+        std::move(report_queue), priority, reporting_settings,
+        rate_setting_path, default_rate, rate_unit_to_ms);
+  } else {
+    LOG(ERROR)
+        << "Cannot create periodic upload report queue, report queue is null";
+  }
+  return metric_report_queue;
+}
+
+std::unique_ptr<CollectorBase>
+MetricReportingManagerDelegateBase::CreatePeriodicCollector(
+    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) {
+  return std::make_unique<PeriodicCollector>(
+      sampler, metric_report_queue, reporting_settings, enable_setting_path,
+      setting_enabled_default_value, rate_setting_path, default_rate,
+      rate_unit_to_ms);
+}
+
+std::unique_ptr<CollectorBase>
+MetricReportingManagerDelegateBase::CreateOneShotCollector(
+    Sampler* sampler,
+    MetricReportQueue* metric_report_queue,
+    ReportingSettings* reporting_settings,
+    const std::string& enable_setting_path,
+    bool setting_enabled_default_value) {
+  return std::make_unique<OneShotCollector>(
+      sampler, metric_report_queue, reporting_settings, enable_setting_path,
+      setting_enabled_default_value);
+}
+
+std::unique_ptr<CollectorBase>
+MetricReportingManagerDelegateBase::CreatePeriodicEventCollector(
+    Sampler* sampler,
+    std::unique_ptr<EventDetector> event_detector,
+    std::vector<Sampler*> additional_samplers,
+    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) {
+  return std::make_unique<PeriodicEventCollector>(
+      sampler, std::move(event_detector), std::move(additional_samplers),
+      metric_report_queue, reporting_settings, enable_setting_path,
+      setting_enabled_default_value, rate_setting_path, default_rate,
+      rate_unit_to_ms);
+}
+
+std::unique_ptr<MetricEventObserverManager>
+MetricReportingManagerDelegateBase::CreateEventObserverManager(
+    std::unique_ptr<MetricEventObserver> event_observer,
+    MetricReportQueue* metric_report_queue,
+    ReportingSettings* reporting_settings,
+    const std::string& enable_setting_path,
+    bool setting_enabled_default_value,
+    std::vector<Sampler*> additional_samplers) {
+  return std::make_unique<MetricEventObserverManager>(
+      std::move(event_observer), metric_report_queue, reporting_settings,
+      enable_setting_path, setting_enabled_default_value,
+      std::move(additional_samplers));
+}
+
+bool MetricReportingManagerDelegateBase::IsAffiliated(Profile* profile) const {
+  return ::chrome::enterprise_util::IsProfileAffiliated(profile);
+}
+
+base::TimeDelta MetricReportingManagerDelegateBase::GetInitDelay() const {
+  return kInitDelay;
+}
+
+base::TimeDelta MetricReportingManagerDelegateBase::GetInitialUploadDelay()
+    const {
+  return kInitialUploadDelay;
+}
+
+}  // namespace reporting::metrics
diff --git a/chrome/browser/chromeos/reporting/metric_reporting_manager_delegate_base.h b/chrome/browser/chromeos/reporting/metric_reporting_manager_delegate_base.h
new file mode 100644
index 0000000..987a13d
--- /dev/null
+++ b/chrome/browser/chromeos/reporting/metric_reporting_manager_delegate_base.h
@@ -0,0 +1,115 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_REPORTING_METRIC_REPORTING_MANAGER_DELEGATE_BASE_H_
+#define CHROME_BROWSER_CHROMEOS_REPORTING_METRIC_REPORTING_MANAGER_DELEGATE_BASE_H_
+
+#include <memory>
+
+#include "chrome/browser/profiles/profile.h"
+#include "components/reporting/client/report_queue_configuration.h"
+#include "components/reporting/metrics/metric_data_collector.h"
+#include "components/reporting/metrics/metric_event_observer_manager.h"
+#include "components/reporting/metrics/metric_report_queue.h"
+
+namespace reporting::metrics {
+
+// Base class for the delegate used by the `MetricReportingManager` to
+// initialize metric related components.
+class MetricReportingManagerDelegateBase {
+ public:
+  MetricReportingManagerDelegateBase() = default;
+  MetricReportingManagerDelegateBase(
+      const MetricReportingManagerDelegateBase& other) = delete;
+  MetricReportingManagerDelegateBase& operator=(
+      const MetricReportingManagerDelegateBase& other) = delete;
+  virtual ~MetricReportingManagerDelegateBase() = default;
+
+  // Creates a new `MetricReportQueue` that can be used towards metrics
+  // reporting.
+  virtual std::unique_ptr<MetricReportQueue> CreateMetricReportQueue(
+      EventType event_type,
+      Destination destination,
+      Priority priority);
+
+  // Creates a new `MetricReportQueue` for periodic uploads. The rate is
+  // controlled by the specified setting and we fall back to the defaults
+  // specified if none set by policy.
+  virtual std::unique_ptr<MetricReportQueue> CreatePeriodicUploadReportQueue(
+      EventType event_type,
+      Destination destination,
+      Priority priority,
+      ReportingSettings* reporting_settings,
+      const std::string& rate_setting_path,
+      base::TimeDelta default_rate,
+      int rate_unit_to_ms = 1);
+
+  // Creates a new collector for periodic metric collection. The rate is
+  // controlled by the specified setting and we fall back to the defaults
+  // specified if none set by policy.
+  virtual std::unique_ptr<CollectorBase> CreatePeriodicCollector(
+      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);
+
+  // Creates a new collector for one shot metric collection. The rate is
+  // controlled by the specified setting and we fall back to the defaults
+  // specified if none set by policy.
+  virtual std::unique_ptr<CollectorBase> CreateOneShotCollector(
+      Sampler* sampler,
+      MetricReportQueue* metric_report_queue,
+      ReportingSettings* reporting_settings,
+      const std::string& enable_setting_path,
+      bool setting_enabled_default_value);
+
+  // Creates a new event collector for periodic event data collection. The rate
+  // is controlled by the specified setting and we fall back to the defaults
+  // specified if none set by policy.
+  virtual std::unique_ptr<CollectorBase> CreatePeriodicEventCollector(
+      Sampler* sampler,
+      std::unique_ptr<EventDetector> event_detector,
+      std::vector<Sampler*> additional_samplers,
+      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);
+
+  // Creates a new event observer manager to manage events reporting. The rate
+  // is controlled by the specified setting and we fall back to the defaults
+  // specified if none set by policy.
+  virtual std::unique_ptr<MetricEventObserverManager>
+  CreateEventObserverManager(
+      std::unique_ptr<MetricEventObserver> event_observer,
+      MetricReportQueue* metric_report_queue,
+      ReportingSettings* reporting_settings,
+      const std::string& enable_setting_path,
+      bool setting_enabled_default_value,
+      std::vector<Sampler*> additional_samplers);
+
+  // Checks for profile affiliation and returns true if affiliated. False
+  // otherwise.
+  virtual bool IsAffiliated(Profile* profile) const;
+
+  // Returns true if device is deprovisioned. False otherwise.
+  virtual bool IsDeprovisioned() const = 0;
+
+  // Returns the delay interval used with `MetricReportingManager`
+  // initialization.
+  base::TimeDelta GetInitDelay() const;
+
+  // Returns the delay interval used with initial record uploads.
+  base::TimeDelta GetInitialUploadDelay() const;
+};
+
+}  // namespace reporting::metrics
+
+#endif  // CHROME_BROWSER_CHROMEOS_REPORTING_METRIC_REPORTING_MANAGER_DELEGATE_BASE_H_
diff --git a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_browsertest.cc b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_browsertest.cc
index a9ad9597..6b758d1 100644
--- a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_browsertest.cc
+++ b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/test/with_feature_override.h"
 #include "build/build_config.h"
 #include "chrome/browser/extensions/component_loader.h"
+#include "chrome/browser/policy/policy_test_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
@@ -18,6 +19,8 @@
 #include "components/embedder_support/switches.h"
 #include "components/permissions/permission_request_manager.h"
 #include "components/permissions/test/permission_request_observer.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/policy_constants.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
@@ -410,12 +413,13 @@
 
 INSTANTIATE_FEATURE_OVERRIDE_TEST_SUITE(CryptotokenBrowserTest);
 
-// Test that `kLoadCryptoTokenExtension` controls loading of the component
-// extension.
-class CryptotokenLoadBrowserTest : public base::test::WithFeatureOverride,
-                                   public InProcessBrowserTest {
+// Test that the `kLoadCryptoTokenExtension` feature controls loading of the
+// component extension.
+class CryptotokenLoadFeatureBrowserTest
+    : public base::test::WithFeatureOverride,
+      public InProcessBrowserTest {
  protected:
-  CryptotokenLoadBrowserTest()
+  CryptotokenLoadFeatureBrowserTest()
       : base::test::WithFeatureOverride(
             extensions_features::kLoadCryptoTokenExtension) {}
 
@@ -425,14 +429,44 @@
   }
 };
 
-IN_PROC_BROWSER_TEST_P(CryptotokenLoadBrowserTest, IsLoaded) {
+IN_PROC_BROWSER_TEST_P(CryptotokenLoadFeatureBrowserTest, IsLoaded) {
   EXPECT_EQ(ExtensionRegistry::Get(browser()->profile())
                     ->GenerateInstalledExtensionsSet()
                     ->GetByID(kCryptoTokenExtensionId) != nullptr,
             IsParamFeatureEnabled());
 }
 
-INSTANTIATE_FEATURE_OVERRIDE_TEST_SUITE(CryptotokenLoadBrowserTest);
+INSTANTIATE_FEATURE_OVERRIDE_TEST_SUITE(CryptotokenLoadFeatureBrowserTest);
+
+// Test that `extensions_prefs::kLoadCryptoTokenExtension` also controls loading
+// of the component extension.
+class CryptotokenLoadPolicyBrowserTest : public policy::PolicyTest {
+ protected:
+  void SetUpInProcessBrowserTestFixture() override {
+    PolicyTest::SetUpInProcessBrowserTestFixture();
+
+    policy::PolicyMap policies;
+    policies.Set(policy::key::kLoadCryptoTokenExtension,
+                 policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+                 policy::POLICY_SOURCE_CLOUD, base::Value(true), nullptr);
+    UpdateProviderPolicy(policies);
+  }
+
+  void SetUp() override {
+    ComponentLoader::EnableBackgroundExtensionsForTesting();
+    policy::PolicyTest::SetUp();
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(CryptotokenLoadPolicyBrowserTest, IsLoaded) {
+  // The policy controls the extension even if the feature is disabled.
+  EXPECT_FALSE(base::FeatureList::IsEnabled(
+      extensions_features::kLoadCryptoTokenExtension));
+  EXPECT_NE(ExtensionRegistry::Get(browser()->profile())
+                ->GenerateInstalledExtensionsSet()
+                ->GetByID(kCryptoTokenExtensionId),
+            nullptr);
+}
 
 }  // namespace
 }  // namespace extensions
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc
index ce139e9..a51bef2 100644
--- a/chrome/browser/extensions/component_loader.cc
+++ b/chrome/browser/extensions/component_loader.cc
@@ -42,6 +42,7 @@
 #include "extensions/browser/extension_file_task_runner.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_system.h"
+#include "extensions/browser/pref_names.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_features.h"
@@ -436,7 +437,7 @@
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
 
   AddKeyboardApp();
-#else  // BUILDFLAG(IS_CHROMEOS_ASH)
+#else   // BUILDFLAG(IS_CHROMEOS_ASH)
   DCHECK(!skip_session_components);
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
@@ -551,7 +552,9 @@
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
 
   if (base::FeatureList::IsEnabled(
-          extensions_features::kLoadCryptoTokenExtension)) {
+          extensions_features::kLoadCryptoTokenExtension) ||
+      ExtensionPrefs::Get(profile_)->pref_service()->GetBoolean(
+          pref_names::kLoadCryptoTokenExtension)) {
     Add(IDR_CRYPTOTOKEN_MANIFEST,
         base::FilePath(FILE_PATH_LITERAL("cryptotoken")));
   }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 92c738f..058a3c4 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1566,7 +1566,7 @@
   {
     "name": "eche-swa-debug-mode",
     "owners": [ "dhnishi" ],
-    "expiry_milestone": 106
+    "expiry_milestone": 108
   },
   {
     "name": "edit-context",
@@ -5877,7 +5877,7 @@
   {
     "name": "show-metered-toggle",
     "owners": [ "stevenjb", "azeemarshad", "cros-connectivity@google.com" ],
-    "expiry_milestone": 106
+    "expiry_milestone": 122
   },
   {
     "name": "show-overdraw-feedback",
diff --git a/chrome/browser/metrics/structured/BUILD.gn b/chrome/browser/metrics/structured/BUILD.gn
index 8818379..4a529e93 100644
--- a/chrome/browser/metrics/structured/BUILD.gn
+++ b/chrome/browser/metrics/structured/BUILD.gn
@@ -11,6 +11,8 @@
   sources = [
     "chrome_structured_metrics_recorder.cc",
     "chrome_structured_metrics_recorder.h",
+    "cros_events_processor.cc",
+    "cros_events_processor.h",
   ]
 
   deps = [
@@ -19,6 +21,7 @@
     "//chromeos/crosapi/mojom",
     "//components/metrics/structured",
     "//components/metrics/structured:structured_events",
+    "//components/prefs",
   ]
 
   if (is_chromeos_ash) {
diff --git a/chrome/browser/metrics/structured/chrome_structured_metrics_recorder.cc b/chrome/browser/metrics/structured/chrome_structured_metrics_recorder.cc
index 4eec87f..424744f9 100644
--- a/chrome/browser/metrics/structured/chrome_structured_metrics_recorder.cc
+++ b/chrome/browser/metrics/structured/chrome_structured_metrics_recorder.cc
@@ -8,7 +8,9 @@
 
 #include "base/no_destructor.h"
 #include "build/chromeos_buildflags.h"
+#include "chrome/browser/metrics/structured/cros_events_processor.h"
 #include "components/metrics/structured/histogram_util.h"
+#include "components/metrics/structured/structured_metrics_features.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/metrics/structured/ash_structured_metrics_recorder.h"  // nogncheck
@@ -17,8 +19,8 @@
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "chrome/browser/metrics/structured/lacros_structured_metrics_recorder.h"  // nogncheck
 #endif
-namespace metrics {
-namespace structured {
+
+namespace metrics::structured {
 namespace {
 
 // Platforms for which the StructuredMetricsClient will be initialized for.
@@ -56,8 +58,25 @@
   return chrome_recorder.get();
 }
 
+// static
+void ChromeStructuredMetricsRecorder::RegisterLocalStatePrefs(
+    PrefRegistrySimple* registry) {
+  cros_event::CrOSEventsProcessor::RegisterLocalStatePrefs(registry);
+}
+
+// static
+void ChromeStructuredMetricsRecorder::RegisterUserProfilePrefs(
+    PrefRegistrySimple* registry) {
+  cros_event::CrOSEventsProcessor::RegisterUserProfilePrefs(registry);
+}
+
 void ChromeStructuredMetricsRecorder::Initialize() {
-// TODO(jongahn): Refactor this by making Initialize() part of the interface.
+  // Adds CrOSEvents processor if feature is enabled.
+  if (base::FeatureList::IsEnabled(kCrOSEvents)) {
+    StructuredMetricsClient::Get()->AddEventsProcessor(
+        std::make_unique<cros_event::CrOSEventsProcessor>());
+  }
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   auto* ash_recorder =
       static_cast<AshStructuredMetricsRecorder*>(delegate_.get());
@@ -85,5 +104,4 @@
   return delegate_->IsReadyToRecord();
 }
 
-}  // namespace structured
-}  // namespace metrics
+}  // namespace metrics::structured
diff --git a/chrome/browser/metrics/structured/chrome_structured_metrics_recorder.h b/chrome/browser/metrics/structured/chrome_structured_metrics_recorder.h
index 25ce0dd..ba4ec69e 100644
--- a/chrome/browser/metrics/structured/chrome_structured_metrics_recorder.h
+++ b/chrome/browser/metrics/structured/chrome_structured_metrics_recorder.h
@@ -11,6 +11,7 @@
 #include "components/metrics/structured/event.h"
 #include "components/metrics/structured/structured_events.h"
 #include "components/metrics/structured/structured_metrics_client.h"
+#include "components/prefs/pref_registry_simple.h"
 
 namespace metrics {
 namespace structured {
@@ -32,6 +33,10 @@
   // Pointer to singleton.
   static ChromeStructuredMetricsRecorder* Get();
 
+  // Registers prefs.
+  static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
+  static void RegisterUserProfilePrefs(PrefRegistrySimple* registry);
+
   ChromeStructuredMetricsRecorder(
       const ChromeStructuredMetricsRecorder& recorder) = delete;
   ChromeStructuredMetricsRecorder& operator=(
diff --git a/chrome/browser/metrics/structured/cros_events_processor.cc b/chrome/browser/metrics/structured/cros_events_processor.cc
new file mode 100644
index 0000000..05dc6834
--- /dev/null
+++ b/chrome/browser/metrics/structured/cros_events_processor.cc
@@ -0,0 +1,25 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/metrics/structured/cros_events_processor.h"
+
+namespace metrics::structured::cros_event {
+
+CrOSEventsProcessor::~CrOSEventsProcessor() = default;
+
+// static
+void CrOSEventsProcessor::RegisterLocalStatePrefs(
+    PrefRegistrySimple* registry) {}
+
+// static
+void CrOSEventsProcessor::RegisterUserProfilePrefs(
+    PrefRegistrySimple* registry) {}
+
+bool CrOSEventsProcessor::ShouldProcessOnEventRecord(const Event& event) {
+  return event.IsCrOSEvent();
+}
+
+void CrOSEventsProcessor::OnEventsRecord(Event* event) {}
+
+}  // namespace metrics::structured::cros_event
diff --git a/chrome/browser/metrics/structured/cros_events_processor.h b/chrome/browser/metrics/structured/cros_events_processor.h
new file mode 100644
index 0000000..e3e8eec
--- /dev/null
+++ b/chrome/browser/metrics/structured/cros_events_processor.h
@@ -0,0 +1,29 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_METRICS_STRUCTURED_CROS_EVENTS_PROCESSOR_H_
+#define CHROME_BROWSER_METRICS_STRUCTURED_CROS_EVENTS_PROCESSOR_H_
+
+#include "components/metrics/structured/events_processor_interface.h"
+#include "components/prefs/pref_registry_simple.h"
+
+namespace metrics::structured::cros_event {
+
+class CrOSEventsProcessor : public EventsProcessorInterface {
+ public:
+  ~CrOSEventsProcessor() override;
+
+  // Registers device-level prefs.
+  static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
+
+  // Registers user-level prefs.
+  static void RegisterUserProfilePrefs(PrefRegistrySimple* registry);
+
+  bool ShouldProcessOnEventRecord(const Event& event) override;
+  void OnEventsRecord(Event* event) override;
+};
+
+}  // namespace metrics::structured::cros_event
+
+#endif  // CHROME_BROWSER_METRICS_STRUCTURED_CROS_EVENTS_PROCESSOR_H_
diff --git a/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc
index ec7acda..98e870b 100644
--- a/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc
@@ -45,6 +45,16 @@
 }
 
 page_load_metrics::PageLoadMetricsObserver::ObservePolicy
+ProtocolPageLoadMetricsObserver::OnPrerenderStart(
+    content::NavigationHandle* navigation_handle,
+    const GURL& currently_committed_url) {
+  // This observer is interested in comparing performance among several
+  // protocols. Including prerendering cases can be another factor to
+  // differentiate performance, and it will be a noise for the original goal.
+  return STOP_OBSERVING;
+}
+
+page_load_metrics::PageLoadMetricsObserver::ObservePolicy
 ProtocolPageLoadMetricsObserver::OnCommit(
     content::NavigationHandle* navigation_handle) {
   protocol_ = page_load_metrics::GetNetworkProtocol(
diff --git a/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.h
index 3a10d7b..f0e74a0 100644
--- a/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.h
@@ -27,6 +27,8 @@
   ObservePolicy OnFencedFramesStart(
       content::NavigationHandle* navigation_handle,
       const GURL& currently_committed_url) override;
+  ObservePolicy OnPrerenderStart(content::NavigationHandle* navigation_handle,
+                                 const GURL& currently_committed_url) override;
   ObservePolicy OnCommit(content::NavigationHandle* navigation_handle) override;
   ObservePolicy OnHidden(
       const page_load_metrics::mojom::PageLoadTiming& timing) override;
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index e7ceef82..771e96c 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -570,6 +570,9 @@
   { key::kSecurityKeyPermitAttestation,
     prefs::kSecurityKeyPermitAttestation,
     base::Value::Type::LIST },
+  { key::kLoadCryptoTokenExtension,
+    extensions::pref_names::kLoadCryptoTokenExtension,
+    base::Value::Type::BOOLEAN },
 #endif // BUILDFLAG(ENABLE_EXTENSIONS)
   { key::kSerialAllowAllPortsForUrls,
     prefs::kManagedSerialAllowAllPortsForUrls,
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
index 8e6ca98..724774b03 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -1827,8 +1827,15 @@
   std::unique_ptr<ContextMenuNotificationObserver> menu_observer_;
 };
 
+#if BUILDFLAG(IS_CHROMEOS)
+#define MAYBE_LensRegionSearchWithValidRegionNewTab \
+  DISABLED_LensRegionSearchWithValidRegionNewTab
+#else
+#define MAYBE_LensRegionSearchWithValidRegionNewTab \
+  LensRegionSearchWithValidRegionNewTab
+#endif
 IN_PROC_BROWSER_TEST_F(SearchByRegionBrowserTest,
-                       LensRegionSearchWithValidRegionNewTab) {
+                       MAYBE_LensRegionSearchWithValidRegionNewTab) {
   SetupAndLoadPage("/empty.html");
   ui_test_utils::AllBrowserTabAddedWaiter add_tab;
 
@@ -1960,8 +1967,15 @@
   base::RepeatingClosure quit_closure_;
 };
 
+#if BUILDFLAG(IS_CHROMEOS)
+#define MAYBE_LensRegionSearchWithValidRegionSidePanel \
+  DISABLED_LensRegionSearchWithValidRegionSidePanel
+#else
+#define MAYBE_LensRegionSearchWithValidRegionSidePanel \
+  LensRegionSearchWithValidRegionSidePanel
+#endif
 IN_PROC_BROWSER_TEST_F(SearchByRegionWithSidePanelBrowserTest,
-                       LensRegionSearchWithValidRegionSidePanel) {
+                       MAYBE_LensRegionSearchWithValidRegionSidePanel) {
   SetupAndLoadPage("/empty.html");
   // We need a base::RunLoop to ensure that our test does not finish until the
   // side panel has opened and we have verified the URL.
diff --git a/chrome/browser/resources/bluetooth_internals/bluetooth_internals.css b/chrome/browser/resources/bluetooth_internals/bluetooth_internals.css
index ca8953b..a2535e6 100644
--- a/chrome/browser/resources/bluetooth_internals/bluetooth_internals.css
+++ b/chrome/browser/resources/bluetooth_internals/bluetooth_internals.css
@@ -160,6 +160,7 @@
   cursor: pointer;
   font: inherit;
   height: 40px;
+  overflow: hidden;
   padding-inline-start: var(--section-padding);
   text-align: start;
   width: 100%;
diff --git a/chrome/browser/resources/certificate_viewer/certificate_viewer.html b/chrome/browser/resources/certificate_viewer/certificate_viewer.html
index 1361ecc0..a0c8b8c7 100644
--- a/chrome/browser/resources/certificate_viewer/certificate_viewer.html
+++ b/chrome/browser/resources/certificate_viewer/certificate_viewer.html
@@ -107,7 +107,8 @@
                aria-readonly="true" aria-labelledby="cert-field-value-label"
                role="textbox"></div>
           <div>
-            <button id="export">$i18n{export}</button>
+            <button id="export"
+              aria-label="$i18n{exportA11yLabel}">$i18n{export}</button>
           </div>
         </div>
       </div>
diff --git a/chrome/browser/resources/chromeos/arc_support/icon/192.png b/chrome/browser/resources/chromeos/arc_support/icon/192.png
index 48e14885..6bd029cc 100644
--- a/chrome/browser/resources/chromeos/arc_support/icon/192.png
+++ b/chrome/browser/resources/chromeos/arc_support/icon/192.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/arc_support/icon/32.png b/chrome/browser/resources/chromeos/arc_support/icon/32.png
index b383a34..e7f31f6 100644
--- a/chrome/browser/resources/chromeos/arc_support/icon/32.png
+++ b/chrome/browser/resources/chromeos/arc_support/icon/32.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/arc_support/icon/playstore.svg b/chrome/browser/resources/chromeos/arc_support/icon/playstore.svg
index fa856db..f09b67d 100644
--- a/chrome/browser/resources/chromeos/arc_support/icon/playstore.svg
+++ b/chrome/browser/resources/chromeos/arc_support/icon/playstore.svg
@@ -1 +1 @@
-<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="91.497%" y1="4.965%" x2="-38.335%" y2="71.91%" id="a"><stop stop-color="#00A0FF" offset="0%"/><stop stop-color="#00A1FF" offset=".657%"/><stop stop-color="#00BEFF" offset="26.01%"/><stop stop-color="#00D2FF" offset="51.22%"/><stop stop-color="#00DFFF" offset="76.04%"/><stop stop-color="#00E3FF" offset="100%"/></linearGradient><linearGradient x1="107.589%" y1="49.995%" x2="-130.473%" y2="49.995%" id="b"><stop stop-color="#FFE000" offset="0%"/><stop stop-color="#FFBD00" offset="40.87%"/><stop stop-color="orange" offset="77.54%"/><stop stop-color="#FF9C00" offset="100%"/></linearGradient><linearGradient x1="86.244%" y1="17.846%" x2="-50.144%" y2="194.808%" id="c"><stop stop-color="#FF3A44" offset="0%"/><stop stop-color="#C31162" offset="100%"/></linearGradient><linearGradient x1="-18.809%" y1="-54.151%" x2="42.093%" y2="24.869%" id="d"><stop stop-color="#32A071" offset="0%"/><stop stop-color="#2DA771" offset="6.85%"/><stop stop-color="#15CF74" offset="47.62%"/><stop stop-color="#06E775" offset="80.09%"/><stop stop-color="#00F076" offset="100%"/></linearGradient></defs><g fill="none" fill-rule="evenodd"><path d="M.518.607C.193.952 0 1.484 0 2.177v24.711c0 .693.193 1.227.518 1.57l.083.08 13.842-13.841v-.327L.6.526.518.607Z" fill="url(#a)" transform="translate(3.097 1.548)"/><path d="m19.057 19.313-4.614-4.616v-.327l4.615-4.615.105.059 5.467 3.106c1.56.887 1.56 2.338 0 3.227l-5.467 3.105-.106.06Z" fill="url(#b)" transform="translate(3.097 1.548)"/><path d="m19.163 19.252-4.72-4.719L.518 28.46c.514.545 1.365.612 2.322.069l16.323-9.276" fill="url(#c)" transform="translate(3.097 1.548)"/><path d="M19.163 9.814 2.84.539C1.883-.005 1.032.062.518.607l13.925 13.926 4.72-4.719Z" fill="url(#d)" transform="translate(3.097 1.548)"/><g fill="#000"><path d="M22.155 20.698 5.936 29.913c-.907.516-1.717.481-2.238.011l-.084.083.084.08c.52.47 1.33.505 2.238-.011l16.323-9.275-.104-.103Z" opacity=".2"/><path d="M3.614 29.844c-.325-.344-.517-.878-.517-1.57v.164c0 .693.192 1.227.517 1.57l.084-.084-.084-.08Z" opacity=".12"/></g><path d="m27.727 17.532-5.572 3.166.104.105 5.468-3.106c.78-.445 1.17-1.03 1.17-1.614-.065.528-.463 1.047-1.17 1.449Z" fill="#000" opacity=".12"/><path d="m5.936 2.25 21.79 12.382c.71.401 1.106.92 1.171 1.45 0-.585-.39-1.17-1.17-1.614L5.937 2.088c-1.563-.887-2.84-.151-2.84 1.639v.163c0-1.79 1.277-2.526 2.84-1.64Z" fill="#FFF" opacity=".25"/></g></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 192 192" height="32px" viewBox="0 0 192 192" width="32px"><path d="M0 0h192v192H0V0z" fill="none"/><g><path d="M95.153 92.052 21.6 169.308v.1C23.898 177.804 31.593 184 40.788 184c3.698 0 7.096-.999 10.094-2.698l.2-.1 82.748-47.273c.099-.2-38.677-41.877-38.677-41.877z" fill="#EA4335"/><path d="m169.507 78.86-35.778-20.588-40.175 35.48 40.375 39.977 35.578-20.288c6.196-3.298 10.493-9.794 10.493-17.29-.1-7.497-4.297-13.993-10.493-17.291z" fill="#FBBC04"/><path d="M21.7 22.592c-.4 1.599-.7 3.298-.7 5.097v136.522c0 1.799.2 3.398.7 5.097l76.052-75.357L21.7 22.592z" fill="#4285F4"/><path d="m95.753 95.95 38.076-37.679-82.748-47.473C47.983 8.999 44.485 8 40.887 8 31.693 8 23.998 14.196 21.7 22.592L95.753 95.95z" fill="#34A853"/></g></svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/nearby_share/shared/BUILD.gn b/chrome/browser/resources/nearby_share/shared/BUILD.gn
index ba989d4..f60e7cd 100644
--- a/chrome/browser/resources/nearby_share/shared/BUILD.gn
+++ b/chrome/browser/resources/nearby_share/shared/BUILD.gn
@@ -123,12 +123,12 @@
     ":nearby_contact_manager",
     ":nearby_share_settings_behavior",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-    "//ui/webui/resources/cr_elements/cr_radio_button:cr_card_radio_button",
     "//ui/webui/resources/js:assert.m",
     "//ui/webui/resources/js:cr.m",
     "//ui/webui/resources/js:i18n_behavior.m",
     "//ui/webui/resources/js:load_time_data.m",
   ]
+  externs_list = [ "//ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_externs.js" ]
 }
 
 js_library("nearby_device_icon") {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn
index f57dae8..fb35713 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn
@@ -114,9 +114,10 @@
 js_library("multidevice_radio_button") {
   deps = [
     "//third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior-extracted",
-    "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button_behavior",
+    "//third_party/polymer/v3_0/components-chromium/paper-behaviors:paper-ripple-behavior",
     "//ui/webui/resources/cr_elements/policy:cr_policy_indicator.m",
   ]
+  externs_list = [ "//ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_externs.js" ]
 }
 
 js_library("multidevice_smartlock_subpage") {
@@ -132,10 +133,12 @@
     "..:route_observer_behavior",
     "../..:router",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-    "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button",
     "//ui/webui/resources/js:web_ui_listener_behavior.m",
   ]
-  externs_list = [ "$externs_path/quick_unlock_private.js" ]
+  externs_list = [
+    "$externs_path/quick_unlock_private.js",
+    "//ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_externs.js",
+  ]
 }
 
 js_library("multidevice_subpage") {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_radio_button.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_radio_button.js
index ef9f269..9b21ca8a 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_radio_button.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_radio_button.js
@@ -7,17 +7,31 @@
 import 'chrome://resources/polymer/v3_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.js';
 import '../../settings_shared.css.js';
 
-import {CrRadioButtonBehavior, CrRadioButtonBehaviorInterface} from 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button_behavior.js';
+import {CrRadioButtonMixin} from 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button_mixin.js';
+import {PaperRippleBehavior} from 'chrome://resources/polymer/v3_0/paper-behaviors/paper-ripple-behavior.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+class PaperRippleBehaviorInterface {
+  constructor() {
+    /**
+     * @type {?Element}
+     * @protected
+     */
+    this._rippleContainer;
+  }
+
+  /** @return {!HTMLElement} */
+  getRipple() {}
+}
 
 /**
  * @constructor
  * @extends {PolymerElement}
- * @implements {CrRadioButtonBehaviorInterface}
+ * @implements {CrRadioButtonMixinInterface}
+ * @implements {PaperRippleBehaviorInterface}
  */
 const MultideviceRadioButtonElementBase =
-    mixinBehaviors([CrRadioButtonBehavior], PolymerElement);
+    mixinBehaviors([PaperRippleBehavior], CrRadioButtonMixin(PolymerElement));
 
 /** @polymer */
 class MultideviceRadioButtonElement extends MultideviceRadioButtonElementBase {
@@ -58,6 +72,23 @@
     this.setAttribute('role', 'radio');
   }
 
+  // Overridden from CrRadioButtonMixin
+  /** @override */
+  getPaperRipple() {
+    return this.getRipple();
+  }
+
+  // Overridden from PaperRippleBehavior
+  /* eslint-disable-next-line @typescript-eslint/naming-convention */
+  _createRipple() {
+    this._rippleContainer = this.shadowRoot.querySelector('.disc-wrapper');
+    const ripple = super._createRipple();
+    ripple.id = 'ink';
+    ripple.setAttribute('recenters', '');
+    ripple.classList.add('circle', 'toggle-ink');
+    return ripple;
+  }
+
   getLabel_(label) {
     return label;
   }
diff --git a/chrome/browser/resources/settings/chromeos/nearby_share_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/nearby_share_page/BUILD.gn
index 4417553e..a7d01b8 100644
--- a/chrome/browser/resources/settings/chromeos/nearby_share_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/BUILD.gn
@@ -52,9 +52,9 @@
     "//chrome/browser/resources/nearby_share/shared:nearby_share_settings_behavior",
     "//ui/webui/resources/cr_elements/cr_button:cr_button",
     "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
-    "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button",
     "//ui/webui/resources/js:i18n_behavior.m",
   ]
+  externs_list = [ "//ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_externs.js" ]
 }
 
 js_library("nearby_share_device_name_dialog") {
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn
index 4c92818..bf4117f 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn
@@ -251,9 +251,9 @@
     ":supported_links_overlapping_apps_dialog",
     ":util",
     "../..:metrics_recorder",
-    "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button",
     "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
   ]
+  externs_list = [ "//ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_externs.js" ]
 }
 
 js_library("util") {
diff --git a/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.js b/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.js
index 9c36af20..00f51a2 100644
--- a/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.js
+++ b/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.js
@@ -7,12 +7,12 @@
  * Settings page for managing Parental Controls features.
  */
 
-import 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import 'chrome://resources/cr_elements/icons.m.js';
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
 import '../../settings_shared.css.js';
 
+import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/chrome/browser/resources/settings/controls/controlled_radio_button.ts b/chrome/browser/resources/settings/controls/controlled_radio_button.ts
index 4d184b23..ec07cf3 100644
--- a/chrome/browser/resources/settings/controls/controlled_radio_button.ts
+++ b/chrome/browser/resources/settings/controls/controlled_radio_button.ts
@@ -7,9 +7,10 @@
 import '//resources/polymer/v3_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.js';
 import '../settings_shared.css.js';
 
-import {CrRadioButtonBehavior} from '//resources/cr_elements/cr_radio_button/cr_radio_button_behavior.js';
+import {CrRadioButtonMixin, CrRadioButtonMixinInterface} from '//resources/cr_elements/cr_radio_button/cr_radio_button_mixin.js';
 import {assert} from '//resources/js/assert_ts.js';
 import {mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {PaperRippleBehavior} from 'chrome://resources/polymer/v3_0/paper-behaviors/paper-ripple-behavior.js';
 
 import {prefToString} from '../prefs/pref_util.js';
 
@@ -17,10 +18,11 @@
 import {PrefControlMixin, PrefControlMixinInterface} from './pref_control_mixin.js';
 
 const ControlledRadioButtonElementBase =
-    mixinBehaviors([CrRadioButtonBehavior], PrefControlMixin(PolymerElement)) as
-    {
-      new (): PolymerElement & CrRadioButtonBehavior &
-          PrefControlMixinInterface,
+    mixinBehaviors(
+        [PaperRippleBehavior],
+        CrRadioButtonMixin(PrefControlMixin(PolymerElement))) as {
+      new (): PolymerElement & CrRadioButtonMixinInterface &
+          PrefControlMixinInterface & PaperRippleBehavior,
     };
 
 export class ControlledRadioButtonElement extends
@@ -39,6 +41,22 @@
     ];
   }
 
+  // Overridden from CrRadioButtonMixin
+  override getPaperRipple() {
+    return this.getRipple();
+  }
+
+  // Overridden from PaperRippleBehavior
+  /* eslint-disable-next-line @typescript-eslint/naming-convention */
+  override _createRipple() {
+    this._rippleContainer = this.shadowRoot!.querySelector('.disc-wrapper');
+    const ripple = super._createRipple();
+    ripple.id = 'ink';
+    ripple.setAttribute('recenters', '');
+    ripple.classList.add('circle', 'toggle-ink');
+    return ripple;
+  }
+
   private updateDisabled_() {
     this.disabled =
         this.pref!.enforcement === chrome.settingsPrivate.Enforcement.ENFORCED;
diff --git a/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts b/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts
index f9b803a..a3168401 100644
--- a/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts
+++ b/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts
@@ -9,7 +9,8 @@
 import '../settings_shared.css.js';
 
 import {CrExpandButtonElement} from 'chrome://resources/cr_elements/cr_expand_button/cr_expand_button.js';
-import {CrRadioButtonBehavior} from 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button_behavior.js';
+import {CrRadioButtonMixin, CrRadioButtonMixinInterface} from 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button_mixin.js';
+import {PaperRippleBehavior} from 'chrome://resources/polymer/v3_0/paper-behaviors/paper-ripple-behavior.js';
 import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {getTemplate} from './collapse_radio_button.html.js';
@@ -20,8 +21,11 @@
   };
 }
 const SettingsCollapseRadioButtonElementBase =
-    mixinBehaviors([CrRadioButtonBehavior], PolymerElement) as
-    {new (): PolymerElement & CrRadioButtonBehavior};
+    mixinBehaviors([PaperRippleBehavior], CrRadioButtonMixin(PolymerElement)) as
+    {
+      new (): PolymerElement & CrRadioButtonMixinInterface &
+          PaperRippleBehavior,
+    };
 
 export class SettingsCollapseRadioButtonElement extends
     SettingsCollapseRadioButtonElementBase {
@@ -109,6 +113,22 @@
     this.pendingUpdateCollapsed_ = false;
   }
 
+  // Overridden from CrRadioButtonMixin
+  override getPaperRipple() {
+    return this.getRipple();
+  }
+
+  // Overridden from PaperRippleBehavior
+  /* eslint-disable-next-line @typescript-eslint/naming-convention */
+  override _createRipple() {
+    this._rippleContainer = this.shadowRoot!.querySelector('.disc-wrapper');
+    const ripple = super._createRipple();
+    ripple.id = 'ink';
+    ripple.setAttribute('recenters', '');
+    ripple.classList.add('circle', 'toggle-ink');
+    return ripple;
+  }
+
   /**
    * Updates the collapsed status of this radio button to reflect
    * the user selection actions.
diff --git a/chrome/browser/storage/shared_storage_browsertest.cc b/chrome/browser/storage/shared_storage_browsertest.cc
index 325d9152..329b2a7 100644
--- a/chrome/browser/storage/shared_storage_browsertest.cc
+++ b/chrome/browser/storage/shared_storage_browsertest.cc
@@ -12,6 +12,7 @@
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_run_loop_timeout.h"
 #include "base/test/task_environment.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
@@ -53,6 +54,36 @@
     "Storage.SharedStorage.AsyncIterator.ReceivedEntriesBenchmarks";
 constexpr char kIteratedEntriesBenchmarksHistogram[] =
     "Storage.SharedStorage.AsyncIterator.IteratedEntriesBenchmarks";
+constexpr char kTimingDocumentAddModuleHistogram[] =
+    "Storage.SharedStorage.Document.Timing.AddModule";
+constexpr char kTimingDocumentRunHistogram[] =
+    "Storage.SharedStorage.Document.Timing.Run";
+constexpr char kTimingDocumentSelectUrlHistogram[] =
+    "Storage.SharedStorage.Document.Timing.SelectURL";
+constexpr char kTimingDocumentAppendHistogram[] =
+    "Storage.SharedStorage.Document.Timing.Append";
+constexpr char kTimingDocumentSetHistogram[] =
+    "Storage.SharedStorage.Document.Timing.Set";
+constexpr char kTimingDocumentDeleteHistogram[] =
+    "Storage.SharedStorage.Document.Timing.Delete";
+constexpr char kTimingDocumentClearHistogram[] =
+    "Storage.SharedStorage.Document.Timing.Clear";
+constexpr char kTimingWorkletAppendHistogram[] =
+    "Storage.SharedStorage.Worklet.Timing.Append";
+constexpr char kTimingWorkletSetHistogram[] =
+    "Storage.SharedStorage.Worklet.Timing.Set";
+constexpr char kTimingWorkletGetHistogram[] =
+    "Storage.SharedStorage.Worklet.Timing.Get";
+constexpr char kTimingWorkletLengthHistogram[] =
+    "Storage.SharedStorage.Worklet.Timing.Length";
+constexpr char kTimingWorkletDeleteHistogram[] =
+    "Storage.SharedStorage.Worklet.Timing.Delete";
+constexpr char kTimingWorkletClearHistogram[] =
+    "Storage.SharedStorage.Worklet.Timing.Clear";
+constexpr char kTimingWorkletKeysHistogram[] =
+    "Storage.SharedStorage.Worklet.Timing.Keys.Next";
+constexpr char kTimingWorkletEntriesHistogram[] =
+    "Storage.SharedStorage.Worklet.Timing.Entries.Next";
 
 // With `WebContentsConsoleObserver`, we can only wait for the last message in a
 // group.
@@ -73,25 +104,33 @@
                        content::GetSharedStorageDisabledMessage(), "\"\n"});
 }
 
-void WaitForHistogram(const std::string& histogram_name) {
-  // Continue if histogram was already recorded.
-  if (base::StatisticsRecorder::FindHistogram(histogram_name))
-    return;
-
-  // Else, wait until the histogram is recorded.
+void DelayBy(base::TimeDelta delta) {
   base::RunLoop run_loop;
-  auto histogram_observer =
-      std::make_unique<base::StatisticsRecorder::ScopedHistogramSampleObserver>(
-          histogram_name,
-          base::BindLambdaForTesting(
-              [&](const char* histogram_name, uint64_t name_hash,
-                  base::HistogramBase::Sample sample) { run_loop.Quit(); }));
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE, run_loop.QuitClosure(), delta);
   run_loop.Run();
 }
 
-void WaitForHistograms(const std::vector<std::string>& histogram_names) {
-  for (const auto& name : histogram_names)
-    WaitForHistogram(name);
+// TODO(cammie): Find a way to ensure that istograms are available at the
+// necessary time without having to resort to sleeping/polling.
+void WaitForHistograms(std::vector<std::string> histogram_names) {
+  while (true) {
+    content::FetchHistogramsFromChildProcesses();
+    metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
+
+    std::vector<std::string> still_waiting;
+    for (const auto& name : histogram_names) {
+      if (!base::StatisticsRecorder::FindHistogram(name))
+        still_waiting.push_back(name);
+    }
+
+    histogram_names = std::move(still_waiting);
+
+    if (histogram_names.empty())
+      break;
+
+    DelayBy(base::Seconds(1));
+  }
 }
 
 }  // namespace
@@ -313,6 +352,9 @@
         "Finish executing customizable_module.js",
         base::UTF16ToUTF8(add_module_console_observer.messages()[0].message));
 
+    WaitForHistograms({kTimingDocumentAddModuleHistogram});
+    histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
+
     content::WebContentsConsoleObserver script_console_observer(
         GetActiveWebContents());
     script_console_observer.SetFilter(MakeFilter(
@@ -335,6 +377,9 @@
           base::UTF16ToUTF8(script_console_observer.messages()[0].message));
     }
 
+    WaitForHistograms({kTimingDocumentRunHistogram});
+    histogram_tester_.ExpectTotalCount(kTimingDocumentRunHistogram, 1);
+
     content::SetBypassIsSharedStorageAllowed(/*allow=*/false);
 
     return result.error.empty();
@@ -366,8 +411,6 @@
               result.error);
     EXPECT_EQ(0u, console_observer.messages().size());
 
-    content::FetchHistogramsFromChildProcesses();
-    metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
     WaitForHistograms({kErrorTypeHistogram});
 
     histogram_tester_.ExpectUniqueSample(
@@ -384,6 +427,10 @@
   EXPECT_EQ(1u, console_observer.messages().size());
   EXPECT_EQ("Finish executing simple_module.js",
             base::UTF16ToUTF8(console_observer.messages()[0].message));
+
+  WaitForHistograms({kTimingDocumentAddModuleHistogram});
+
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
 }
 
 IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, RunOperation) {
@@ -404,12 +451,13 @@
           'test-operation', {data: {'customKey': 'customValue'}});
     )");
 
+  WaitForHistograms({kTimingDocumentAddModuleHistogram});
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
+
   if (!SuccessExpected()) {
     // Shared Storage will be disabled.
     EXPECT_EQ(GetSharedStorageDisabledErrorMessage(), run_op_result.error);
 
-    content::FetchHistogramsFromChildProcesses();
-    metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
     WaitForHistograms({kErrorTypeHistogram});
 
     histogram_tester_.ExpectUniqueSample(
@@ -426,6 +474,11 @@
   EXPECT_EQ(1u, run_op_console_observer.messages().size());
   EXPECT_EQ("Finish executing \'test-operation\'",
             base::UTF16ToUTF8(run_op_console_observer.messages()[0].message));
+
+  WaitForHistograms(
+      {kTimingDocumentAddModuleHistogram, kTimingDocumentRunHistogram});
+
+  histogram_tester_.ExpectTotalCount(kTimingDocumentRunHistogram, 1);
 }
 
 IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, RunURLSelectionOperation) {
@@ -451,12 +504,13 @@
           {data: {'mockResult': 1}});
     )");
 
+  WaitForHistograms({kTimingDocumentAddModuleHistogram});
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
+
   if (!SuccessExpected()) {
     // Shared Storage will be disabled.
     EXPECT_EQ(GetSharedStorageDisabledErrorMessage(), run_url_op_result.error);
 
-    content::FetchHistogramsFromChildProcesses();
-    metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
     WaitForHistograms({kErrorTypeHistogram});
 
     histogram_tester_.ExpectUniqueSample(
@@ -476,6 +530,12 @@
   EXPECT_EQ(
       "Finish executing \'test-url-selection-operation\'",
       base::UTF16ToUTF8(run_url_op_console_observer.messages()[0].message));
+
+  WaitForHistograms(
+      {kTimingDocumentAddModuleHistogram, kTimingDocumentSelectUrlHistogram});
+
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
+  histogram_tester_.ExpectTotalCount(kTimingDocumentSelectUrlHistogram, 1);
 }
 
 IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, Set) {
@@ -484,8 +544,6 @@
       ui::PageTransition::PAGE_TRANSITION_LINK);
   ui_test_utils::NavigateToURL(&params);
 
-  AddSimpleModuleWithPermissionBypassed(GetActiveWebContents());
-
   content::EvalJsResult set_result = content::EvalJs(GetActiveWebContents(), R"(
       sharedStorage.set('customKey', 'customValue');
     )");
@@ -499,6 +557,9 @@
   // Privacy Sandox is enabled and 3P cookies are allowed, so Shared Storage
   // should be allowed.
   EXPECT_TRUE(set_result.error.empty());
+
+  WaitForHistograms({kTimingDocumentSetHistogram});
+  histogram_tester_.ExpectTotalCount(kTimingDocumentSetHistogram, 1);
 }
 
 IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, Append) {
@@ -507,8 +568,6 @@
       ui::PageTransition::PAGE_TRANSITION_LINK);
   ui_test_utils::NavigateToURL(&params);
 
-  AddSimpleModuleWithPermissionBypassed(GetActiveWebContents());
-
   content::EvalJsResult append_result =
       content::EvalJs(GetActiveWebContents(), R"(
       sharedStorage.append('customKey', 'customValue');
@@ -523,6 +582,9 @@
   // Privacy Sandox is enabled and 3P cookies are allowed, so Shared Storage
   // should be allowed.
   EXPECT_TRUE(append_result.error.empty());
+
+  WaitForHistograms({kTimingDocumentAppendHistogram});
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAppendHistogram, 1);
 }
 
 IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, Delete) {
@@ -531,8 +593,6 @@
       ui::PageTransition::PAGE_TRANSITION_LINK);
   ui_test_utils::NavigateToURL(&params);
 
-  AddSimpleModuleWithPermissionBypassed(GetActiveWebContents());
-
   content::EvalJsResult delete_result =
       content::EvalJs(GetActiveWebContents(), R"(
       sharedStorage.delete('customKey');
@@ -547,6 +607,9 @@
   // Privacy Sandox is enabled and 3P cookies are allowed, so Shared Storage
   // should be allowed.
   EXPECT_TRUE(delete_result.error.empty());
+
+  WaitForHistograms({kTimingDocumentDeleteHistogram});
+  histogram_tester_.ExpectTotalCount(kTimingDocumentDeleteHistogram, 1);
 }
 
 IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, Clear) {
@@ -555,8 +618,6 @@
       ui::PageTransition::PAGE_TRANSITION_LINK);
   ui_test_utils::NavigateToURL(&params);
 
-  AddSimpleModuleWithPermissionBypassed(GetActiveWebContents());
-
   content::EvalJsResult clear_result =
       content::EvalJs(GetActiveWebContents(), R"(
       sharedStorage.clear();
@@ -571,6 +632,9 @@
   // Privacy Sandox is enabled and 3P cookies are allowed, so Shared Storage
   // should be allowed.
   EXPECT_TRUE(clear_result.error.empty());
+
+  WaitForHistograms({kTimingDocumentClearHistogram});
+  histogram_tester_.ExpectTotalCount(kTimingDocumentClearHistogram, 1);
 }
 
 IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletSet) {
@@ -589,6 +653,11 @@
       console.log('Finished script');
     )",
       "Finished script"));
+
+  if (SuccessExpected()) {
+    WaitForHistograms({kTimingWorkletSetHistogram});
+    histogram_tester_.ExpectTotalCount(kTimingWorkletSetHistogram, 1);
+  }
 }
 
 IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletAppend) {
@@ -607,6 +676,11 @@
       console.log('Finished script');
     )",
       "Finished script"));
+
+  if (SuccessExpected()) {
+    WaitForHistograms({kTimingWorkletAppendHistogram});
+    histogram_tester_.ExpectTotalCount(kTimingWorkletAppendHistogram, 1);
+  }
 }
 
 IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletDelete) {
@@ -625,6 +699,11 @@
       console.log('Finished script');
     )",
       "Finished script"));
+
+  if (SuccessExpected()) {
+    WaitForHistograms({kTimingWorkletDeleteHistogram});
+    histogram_tester_.ExpectTotalCount(kTimingWorkletDeleteHistogram, 1);
+  }
 }
 
 IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletClear) {
@@ -643,6 +722,11 @@
       console.log('Finished script');
     )",
       "Finished script"));
+
+  if (SuccessExpected()) {
+    WaitForHistograms({kTimingWorkletClearHistogram});
+    histogram_tester_.ExpectTotalCount(kTimingWorkletClearHistogram, 1);
+  }
 }
 
 IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletGet) {
@@ -671,6 +755,12 @@
   // message since it is wrapped in a `console.log()` call.
   EXPECT_TRUE(ExecuteScriptInWorkletWithOuterPermissionsBypassed(
       GetActiveWebContents(), script, "Finished script"));
+
+  if (SuccessExpected()) {
+    WaitForHistograms({kTimingWorkletSetHistogram, kTimingWorkletGetHistogram});
+    histogram_tester_.ExpectTotalCount(kTimingWorkletSetHistogram, 1);
+    histogram_tester_.ExpectTotalCount(kTimingWorkletGetHistogram, 1);
+  }
 }
 
 IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletKeys) {
@@ -691,6 +781,11 @@
       console.log('Finished script');
     )",
       "Finished script"));
+
+  if (SuccessExpected()) {
+    WaitForHistograms({kTimingWorkletKeysHistogram});
+    histogram_tester_.ExpectTotalCount(kTimingWorkletKeysHistogram, 1);
+  }
 }
 
 IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletEntries) {
@@ -711,6 +806,11 @@
       console.log('Finished script');
     )",
       "Finished script"));
+
+  if (SuccessExpected()) {
+    WaitForHistograms({kTimingWorkletEntriesHistogram});
+    histogram_tester_.ExpectTotalCount(kTimingWorkletEntriesHistogram, 1);
+  }
 }
 
 IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletLength) {
@@ -729,6 +829,11 @@
       console.log('Finished script');
     )",
       "Finished script"));
+
+  if (SuccessExpected()) {
+    WaitForHistograms({kTimingWorkletLengthHistogram});
+    histogram_tester_.ExpectTotalCount(kTimingWorkletLengthHistogram, 1);
+  }
 }
 
 IN_PROC_BROWSER_TEST_F(SharedStorageChromeBrowserTest,
@@ -753,12 +858,16 @@
     )",
                                      "Finished script"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kEntriesQueuedCountHistogram,
-                     kReceivedEntriesBenchmarksHistogram,
-                     kIteratedEntriesBenchmarksHistogram});
+  WaitForHistograms(
+      {kTimingDocumentAddModuleHistogram, kTimingDocumentRunHistogram,
+       kTimingWorkletKeysHistogram, kTimingWorkletEntriesHistogram,
+       kEntriesQueuedCountHistogram, kReceivedEntriesBenchmarksHistogram,
+       kIteratedEntriesBenchmarksHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
+  histogram_tester_.ExpectTotalCount(kTimingDocumentRunHistogram, 1);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletKeysHistogram, 151);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletEntriesHistogram, 151);
   histogram_tester_.ExpectUniqueSample(kEntriesQueuedCountHistogram, 150, 2);
   histogram_tester_.ExpectBucketCount(kReceivedEntriesBenchmarksHistogram, 0,
                                       2);
@@ -842,12 +951,16 @@
     )",
                                      "Finished script"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kEntriesQueuedCountHistogram,
-                     kReceivedEntriesBenchmarksHistogram,
-                     kIteratedEntriesBenchmarksHistogram});
+  WaitForHistograms(
+      {kTimingDocumentAddModuleHistogram, kTimingDocumentRunHistogram,
+       kTimingWorkletKeysHistogram, kTimingWorkletEntriesHistogram,
+       kEntriesQueuedCountHistogram, kReceivedEntriesBenchmarksHistogram,
+       kIteratedEntriesBenchmarksHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
+  histogram_tester_.ExpectTotalCount(kTimingDocumentRunHistogram, 1);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletKeysHistogram, 150 + 243);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletEntriesHistogram, 101 + 299);
   histogram_tester_.ExpectUniqueSample(kEntriesQueuedCountHistogram, 300, 4);
   histogram_tester_.ExpectBucketCount(kReceivedEntriesBenchmarksHistogram, 0,
                                       4);
@@ -917,12 +1030,16 @@
     )",
                                      "Finished script"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kEntriesQueuedCountHistogram,
-                     kReceivedEntriesBenchmarksHistogram,
-                     kIteratedEntriesBenchmarksHistogram});
+  WaitForHistograms(
+      {kTimingDocumentAddModuleHistogram, kTimingDocumentRunHistogram,
+       kTimingWorkletKeysHistogram, kTimingWorkletEntriesHistogram,
+       kEntriesQueuedCountHistogram, kReceivedEntriesBenchmarksHistogram,
+       kIteratedEntriesBenchmarksHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
+  histogram_tester_.ExpectTotalCount(kTimingDocumentRunHistogram, 1);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletKeysHistogram, 6);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletEntriesHistogram, 6);
   histogram_tester_.ExpectUniqueSample(kEntriesQueuedCountHistogram, 5, 2);
   histogram_tester_.ExpectBucketCount(kReceivedEntriesBenchmarksHistogram, 0,
                                       2);
@@ -1006,12 +1123,16 @@
     )",
                                      "Finished script"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kEntriesQueuedCountHistogram,
-                     kReceivedEntriesBenchmarksHistogram,
-                     kIteratedEntriesBenchmarksHistogram});
+  WaitForHistograms(
+      {kTimingDocumentAddModuleHistogram, kTimingDocumentRunHistogram,
+       kTimingWorkletKeysHistogram, kTimingWorkletEntriesHistogram,
+       kEntriesQueuedCountHistogram, kReceivedEntriesBenchmarksHistogram,
+       kIteratedEntriesBenchmarksHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
+  histogram_tester_.ExpectTotalCount(kTimingDocumentRunHistogram, 1);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletKeysHistogram, 4 + 3);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletEntriesHistogram, 2 + 1);
   histogram_tester_.ExpectUniqueSample(kEntriesQueuedCountHistogram, 5, 4);
   histogram_tester_.ExpectBucketCount(kReceivedEntriesBenchmarksHistogram, 0,
                                       4);
@@ -1077,12 +1198,16 @@
     )",
                                      "Finished script"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kEntriesQueuedCountHistogram,
-                     kReceivedEntriesBenchmarksHistogram,
-                     kIteratedEntriesBenchmarksHistogram});
+  WaitForHistograms(
+      {kTimingDocumentAddModuleHistogram, kTimingDocumentRunHistogram,
+       kTimingWorkletKeysHistogram, kTimingWorkletEntriesHistogram,
+       kEntriesQueuedCountHistogram, kReceivedEntriesBenchmarksHistogram,
+       kIteratedEntriesBenchmarksHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
+  histogram_tester_.ExpectTotalCount(kTimingDocumentRunHistogram, 1);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletKeysHistogram, 1);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletEntriesHistogram, 1);
   histogram_tester_.ExpectUniqueSample(kEntriesQueuedCountHistogram, 0, 2);
   histogram_tester_.ExpectBucketCount(kReceivedEntriesBenchmarksHistogram, 0,
                                       2);
@@ -1132,8 +1257,6 @@
            "                               ^^^^^\n"}),
       result.error);
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
   WaitForHistograms({kErrorTypeHistogram});
 
   histogram_tester_.ExpectUniqueSample(
@@ -1163,8 +1286,6 @@
                     "\n                               ^^^^^\n"}),
       result.error);
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
   WaitForHistograms({kErrorTypeHistogram});
 
   histogram_tester_.ExpectUniqueSample(
@@ -1190,8 +1311,6 @@
                     script_url.spec(), " HTTP status = 404 Not Found.\"\n"}),
       result.error);
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
   WaitForHistograms({kErrorTypeHistogram});
 
   histogram_tester_.ExpectUniqueSample(
@@ -1217,8 +1336,6 @@
                     script_url.spec(), ".\"\n"}),
       result.error);
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
   WaitForHistograms({kErrorTypeHistogram});
 
   histogram_tester_.ExpectUniqueSample(
@@ -1244,8 +1361,6 @@
                           "undefinedVariable is not defined.\"\n"}),
             result.error);
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
   WaitForHistograms({kErrorTypeHistogram});
 
   histogram_tester_.ExpectUniqueSample(
@@ -1275,10 +1390,9 @@
                           "be invoked once per browsing context.\"\n"}),
             result.error);
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kErrorTypeHistogram});
+  WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
   histogram_tester_.ExpectUniqueSample(
       kErrorTypeHistogram,
       blink::SharedStorageWorkletErrorType::kAddModuleWebVisible, 1);
@@ -1296,8 +1410,6 @@
           'test-operation', {data: {}});
     )"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
   WaitForHistograms({kErrorTypeHistogram});
 
   histogram_tester_.ExpectUniqueSample(
@@ -1323,10 +1435,9 @@
           'test-operation-1', {data: {}});
     )"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kErrorTypeHistogram});
+  WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
   histogram_tester_.ExpectUniqueSample(
       kErrorTypeHistogram,
       blink::SharedStorageWorkletErrorType::kRunNonWebVisible, 1);
@@ -1350,10 +1461,9 @@
           'test-operation', {data: {}});
     )"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kErrorTypeHistogram});
+  WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
   histogram_tester_.ExpectUniqueSample(
       kErrorTypeHistogram,
       blink::SharedStorageWorkletErrorType::kRunNonWebVisible, 1);
@@ -1377,10 +1487,9 @@
           'test-operation', {data: {}});
     )"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kErrorTypeHistogram});
+  WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
   histogram_tester_.ExpectUniqueSample(
       kErrorTypeHistogram,
       blink::SharedStorageWorkletErrorType::kRunNonWebVisible, 1);
@@ -1404,10 +1513,9 @@
           'test-operation', {data: {}});
     )"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kErrorTypeHistogram});
+  WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
   histogram_tester_.ExpectUniqueSample(
       kErrorTypeHistogram,
       blink::SharedStorageWorkletErrorType::kRunNonWebVisible, 1);
@@ -1432,10 +1540,9 @@
           'test-operation', {data: {'customField': 'customValue123'}});
     )"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kErrorTypeHistogram});
+  WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
   histogram_tester_.ExpectUniqueSample(
       kErrorTypeHistogram,
       blink::SharedStorageWorkletErrorType::kRunNonWebVisible, 1);
@@ -1460,8 +1567,6 @@
                           "called before sharedStorage.selectURL().\"\n"}),
             result.error);
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
   WaitForHistograms({kErrorTypeHistogram});
 
   histogram_tester_.ExpectUniqueSample(
@@ -1489,10 +1594,9 @@
           [{url: "fenced_frames/title0.html"}], {data: {}});
     )"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kErrorTypeHistogram});
+  WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
   histogram_tester_.ExpectUniqueSample(
       kErrorTypeHistogram,
       blink::SharedStorageWorkletErrorType::kSelectURLNonWebVisible, 1);
@@ -1518,10 +1622,9 @@
           [{url: "fenced_frames/title0.html"}], {data: {}});
     )"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kErrorTypeHistogram});
+  WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
   histogram_tester_.ExpectUniqueSample(
       kErrorTypeHistogram,
       blink::SharedStorageWorkletErrorType::kSelectURLNonWebVisible, 1);
@@ -1547,10 +1650,9 @@
           [{url: "fenced_frames/title0.html"}], {data: {}});
     )"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kErrorTypeHistogram});
+  WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
   histogram_tester_.ExpectUniqueSample(
       kErrorTypeHistogram,
       blink::SharedStorageWorkletErrorType::kSelectURLNonWebVisible, 1);
@@ -1575,10 +1677,9 @@
           [{url: "fenced_frames/title0.html"}], {data: {}});
     )"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kErrorTypeHistogram});
+  WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
   histogram_tester_.ExpectUniqueSample(
       kErrorTypeHistogram,
       blink::SharedStorageWorkletErrorType::kSelectURLNonWebVisible, 1);
@@ -1605,10 +1706,9 @@
           {data: {'customField': 'customValue123'}});
     )"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kErrorTypeHistogram});
+  WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
   histogram_tester_.ExpectUniqueSample(
       kErrorTypeHistogram,
       blink::SharedStorageWorkletErrorType::kSelectURLNonWebVisible, 1);
@@ -1634,10 +1734,9 @@
           [{url: "fenced_frames/title0.html"}], {data: {}});
     )"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kErrorTypeHistogram});
+  WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
   histogram_tester_.ExpectUniqueSample(
       kErrorTypeHistogram,
       blink::SharedStorageWorkletErrorType::kSelectURLNonWebVisible, 1);
@@ -1663,13 +1762,104 @@
           [{url: "fenced_frames/title0.html"}], {data: {}});
     )"));
 
-  content::FetchHistogramsFromChildProcesses();
-  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  WaitForHistograms({kErrorTypeHistogram});
+  WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram});
 
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
   histogram_tester_.ExpectUniqueSample(
       kErrorTypeHistogram,
       blink::SharedStorageWorkletErrorType::kSelectURLNonWebVisible, 1);
 }
 
+IN_PROC_BROWSER_TEST_F(SharedStorageChromeBrowserTest, DocumentTiming) {
+  base::test::ScopedRunLoopTimeout timeout(FROM_HERE, base::Seconds(60));
+
+  NavigateParams params(
+      browser(), https_server()->GetURL(kSimpleTestHost, kSimplePagePath),
+      ui::PageTransition::PAGE_TRANSITION_LINK);
+  ui_test_utils::NavigateToURL(&params);
+
+  EXPECT_TRUE(content::ExecJs(GetActiveWebContents(),
+                              R"(
+      sharedStorage.set('key0', 'value0');
+
+      sharedStorage.set('key1', 'value1');
+      sharedStorage.set('key1', 'value111');
+
+      sharedStorage.set('key2', 'value2');
+      sharedStorage.set('key2', 'value222', {ignoreIfPresent: true});
+
+      sharedStorage.set('key3', 'value3');
+      sharedStorage.append('key3', 'value333');
+      sharedStorage.append('key2', 'value22');
+      sharedStorage.append('key4', 'value4');
+
+      sharedStorage.delete('key0');
+      sharedStorage.delete('key2');
+      sharedStorage.clear();
+    )"));
+
+  WaitForHistograms(
+      {kTimingDocumentSetHistogram, kTimingDocumentAppendHistogram,
+       kTimingDocumentDeleteHistogram, kTimingDocumentClearHistogram});
+
+  histogram_tester_.ExpectTotalCount(kTimingDocumentSetHistogram, 6);
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAppendHistogram, 3);
+  histogram_tester_.ExpectTotalCount(kTimingDocumentDeleteHistogram, 2);
+  histogram_tester_.ExpectTotalCount(kTimingDocumentClearHistogram, 1);
+}
+
+IN_PROC_BROWSER_TEST_F(SharedStorageChromeBrowserTest, WorkletTiming) {
+  base::test::ScopedRunLoopTimeout timeout(FROM_HERE, base::Seconds(60));
+
+  NavigateParams params(
+      browser(), https_server()->GetURL(kSimpleTestHost, kSimplePagePath),
+      ui::PageTransition::PAGE_TRANSITION_LINK);
+  ui_test_utils::NavigateToURL(&params);
+
+  EXPECT_TRUE(ExecuteScriptInWorklet(GetActiveWebContents(),
+                                     R"(
+      sharedStorage.set('key0', 'value0');
+
+      sharedStorage.set('key1', 'value1');
+      sharedStorage.set('key1', 'value111');
+
+      sharedStorage.set('key2', 'value2');
+      sharedStorage.set('key2', 'value222', {ignoreIfPresent: true});
+
+      sharedStorage.set('key3', 'value3');
+      sharedStorage.append('key3', 'value333');
+      sharedStorage.append('key2', 'value22');
+      sharedStorage.append('key4', 'value4');
+
+      console.log(await sharedStorage.get('key0'));
+      console.log(await sharedStorage.get('key1'));
+      console.log(await sharedStorage.get('key2'));
+      console.log(await sharedStorage.get('key3'));
+      console.log(await sharedStorage.get('key4'));
+      console.log(await sharedStorage.length());
+
+      sharedStorage.delete('key0');
+      sharedStorage.delete('key2');
+      sharedStorage.clear();
+
+      console.log('Finished script');
+    )",
+                                     "Finished script"));
+
+  WaitForHistograms(
+      {kTimingDocumentAddModuleHistogram, kTimingDocumentRunHistogram,
+       kTimingWorkletSetHistogram, kTimingWorkletAppendHistogram,
+       kTimingWorkletGetHistogram, kTimingWorkletLengthHistogram,
+       kTimingWorkletDeleteHistogram, kTimingWorkletClearHistogram});
+
+  histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1);
+  histogram_tester_.ExpectTotalCount(kTimingDocumentRunHistogram, 1);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletSetHistogram, 6);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletAppendHistogram, 3);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletGetHistogram, 5);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletLengthHistogram, 1);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletDeleteHistogram, 2);
+  histogram_tester_.ExpectTotalCount(kTimingWorkletClearHistogram, 1);
+}
+
 }  // namespace storage
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index 8461054..987fe4a4 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -775,7 +775,7 @@
   // aligned side panels.
   void RightAlignedSidePanelWasClosed();
 
-  bool ShouldShowWindowControlsOverlayToggle() const {
+  bool should_show_window_controls_overlay_toggle() const {
     return should_show_window_controls_overlay_toggle_;
   }
 
diff --git a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
index e8a3bcb..c4b0cac 100644
--- a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
+++ b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
@@ -9,9 +9,7 @@
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_pref_names.h"
 #include "ash/public/cpp/keyboard/keyboard_switches.h"
-#include "ash/public/cpp/style/color_provider.h"
 #include "ash/public/cpp/style/dark_light_mode_controller.h"
-#include "ash/public/cpp/style/scoped_light_mode_as_default.h"
 #include "ash/public/cpp/test/shell_test_api.h"
 #include "base/callback_helpers.h"
 #include "base/files/file_util.h"
@@ -667,7 +665,9 @@
   }
 };
 
-IN_PROC_BROWSER_TEST_P(SelectFileDialogExtensionFlagTest, DialogColoredTitle) {
+IN_PROC_BROWSER_TEST_P(SelectFileDialogExtensionFlagTest,
+                       DialogColoredTitle_Light) {
+  ash::DarkLightModeController::Get()->SetDarkModeEnabledForTest(false);
   gfx::NativeWindow owning_window = browser()->window()->GetNativeWindow();
   ASSERT_NE(nullptr, owning_window);
 
@@ -677,12 +677,34 @@
   content::RenderFrameHost* frame_host = dialog_->GetPrimaryMainFrame();
   aura::Window* dialog_window =
       frame_host->GetNativeView()->GetToplevelWindow();
-  auto* color_provider = ash::ColorProvider::Get();
-  ash::ScopedLightModeAsDefault scoped_light_mode_as_default;
+  // This is cros_tokens::kDialogTitleBarColorLight
+  SkColor dialog_title_bar_color = SkColorSetRGB(0xDF, 0xE0, 0xE1);
   EXPECT_EQ(dialog_window->GetProperty(chromeos::kFrameActiveColorKey),
-            color_provider->GetActiveDialogTitleBarColor());
+            dialog_title_bar_color);
   EXPECT_EQ(dialog_window->GetProperty(chromeos::kFrameInactiveColorKey),
-            color_provider->GetInactiveDialogTitleBarColor());
+            dialog_title_bar_color);
+
+  CloseDialog(DIALOG_BTN_CANCEL, owning_window);
+}
+
+IN_PROC_BROWSER_TEST_P(SelectFileDialogExtensionFlagTest,
+                       DialogColoredTitle_Dark) {
+  ash::DarkLightModeController::Get()->SetDarkModeEnabledForTest(true);
+  gfx::NativeWindow owning_window = browser()->window()->GetNativeWindow();
+  ASSERT_NE(nullptr, owning_window);
+
+  // Open the file dialog on the default path.
+  ASSERT_NO_FATAL_FAILURE(OpenDialog(ui::SelectFileDialog::SELECT_OPEN_FILE,
+                                     base::FilePath(), owning_window, ""));
+  content::RenderFrameHost* frame_host = dialog_->GetPrimaryMainFrame();
+  aura::Window* dialog_window =
+      frame_host->GetNativeView()->GetToplevelWindow();
+  // This is cros_tokens::kDialogTitleBarColorDark
+  SkColor dialog_title_bar_color = SkColorSetRGB(0x4D, 0x4D, 0x50);
+  EXPECT_EQ(dialog_window->GetProperty(chromeos::kFrameActiveColorKey),
+            dialog_title_bar_color);
+  EXPECT_EQ(dialog_window->GetProperty(chromeos::kFrameInactiveColorKey),
+            dialog_title_bar_color);
 
   CloseDialog(DIALOG_BTN_CANCEL, owning_window);
 }
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.cc
index e2bd2e6..139a0fc 100644
--- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.cc
+++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.cc
@@ -105,7 +105,7 @@
     ConfigureWebAppToolbarButton(window_controls_overlay_toggle_button_,
                                  toolbar_button_provider_);
     window_controls_overlay_toggle_button_->SetVisible(
-        browser_view_->ShouldShowWindowControlsOverlayToggle());
+        browser_view_->should_show_window_controls_overlay_toggle());
   }
 
   if (app_controller->HasTitlebarContentSettings()) {
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
index 379c5c2..1aa890f 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -2363,7 +2363,6 @@
     base::FilePath shortcut_dir,
     const std::string& app_name,
     const AppId& app_id) {
-  base::FilePath shortcut_path;
 #if BUILDFLAG(IS_WIN)
   std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
   base::FileEnumerator enumerator(shortcut_dir, false,
@@ -2372,33 +2371,35 @@
     std::wstring shortcut_filename = enumerator.GetInfo().GetName().value();
     if (re2::RE2::FullMatch(converter.to_bytes(shortcut_filename),
                             app_name + "(.*).lnk")) {
-      shortcut_path = shortcut_dir.Append(shortcut_filename);
+      base::FilePath shortcut_path = shortcut_dir.Append(shortcut_filename);
       if (GetShortcutProfile(shortcut_path) == profile()->GetBaseName())
         return shortcut_path;
     }
   }
 #elif BUILDFLAG(IS_MAC)
   std::string shortcut_filename = app_name + ".app";
-  shortcut_path = shortcut_dir.Append(shortcut_filename);
-  AppShimRegistry* registry = AppShimRegistry::Get();
+  base::FilePath shortcut_path = shortcut_dir.Append(shortcut_filename);
   // Exits early if the app id is empty because the verification won't work.
   // TODO(crbug.com/1289865): Figure a way to find the profile that has the app
   //                          installed without using app ID.
-  if (!app_id.empty()) {
-    std::set<base::FilePath> app_installed_profiles =
-        registry->GetInstalledProfilesForApp(app_id);
-    if (app_installed_profiles.find(profile()->GetPath()) !=
-        app_installed_profiles.end())
-      return shortcut_path;
+  if (app_id.empty())
+    return shortcut_path;
+
+  AppShimRegistry* registry = AppShimRegistry::Get();
+  std::set<base::FilePath> app_installed_profiles =
+      registry->GetInstalledProfilesForApp(app_id);
+  if (app_installed_profiles.find(profile()->GetPath()) !=
+      app_installed_profiles.end()) {
+    return shortcut_path;
   }
 #elif BUILDFLAG(IS_LINUX)
   std::string shortcut_filename =
       "chrome-" + app_id + "-" + profile()->GetBaseName().value() + ".desktop";
-  shortcut_path = shortcut_dir.Append(shortcut_filename);
+  base::FilePath shortcut_path = shortcut_dir.Append(shortcut_filename);
   if (base::PathExists(shortcut_path))
     return shortcut_path;
 #endif
-  return shortcut_path;
+  return base::FilePath();
 }
 
 void WebAppIntegrationTestDriver::InstallPolicyAppInternal(
diff --git a/chrome/browser/ui/webui/BUILD.gn b/chrome/browser/ui/webui/BUILD.gn
index d8d8de83..2661face 100644
--- a/chrome/browser/ui/webui/BUILD.gn
+++ b/chrome/browser/ui/webui/BUILD.gn
@@ -52,6 +52,7 @@
     deps += [
       "//ash/constants",
       "//ash/webui/eche_app_ui",
+      "//ash/webui/face_ml_app_ui",
       "//ash/webui/file_manager:file_manager_untrusted_ui",
       "//ash/webui/help_app_ui",
       "//ash/webui/os_feedback_ui",
@@ -61,7 +62,6 @@
     if (!is_official_build) {
       deps += [
         "//ash/webui/demo_mode_app_ui",
-        "//ash/webui/facial_ml_app_ui",
         "//ash/webui/sample_system_web_app_ui",
       ]
     }
diff --git a/chrome/browser/ui/webui/certificate_viewer_ui.cc b/chrome/browser/ui/webui/certificate_viewer_ui.cc
index c648644a..79b49b9 100644
--- a/chrome/browser/ui/webui/certificate_viewer_ui.cc
+++ b/chrome/browser/ui/webui/certificate_viewer_ui.cc
@@ -30,6 +30,7 @@
       {"details", IDS_CERT_INFO_DETAILS_TAB_LABEL},
       {"close", IDS_CLOSE},
       {"export", IDS_CERT_DETAILS_EXPORT_CERTIFICATE},
+      {"exportA11yLabel", IDS_CERT_DETAILS_EXPORT_CERTIFICATE_A11Y_LABEL},
       {"issuedTo", IDS_CERT_INFO_SUBJECT_GROUP},
       {"issuedBy", IDS_CERT_INFO_ISSUER_GROUP},
       {"cn", IDS_CERT_INFO_COMMON_NAME_LABEL},
diff --git a/chrome/browser/ui/webui/chrome_web_ui_configs_chromeos.cc b/chrome/browser/ui/webui/chrome_web_ui_configs_chromeos.cc
index f3155a4..500156a8 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_configs_chromeos.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_configs_chromeos.cc
@@ -8,10 +8,10 @@
 #include "content/public/browser/webui_config_map.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ash/webui/face_ml_app_ui/face_ml_app_ui.h"
 #include "ash/webui/shortcut_customization_ui/shortcut_customization_app_ui.h"
 #include "chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_ui.h"
 #if !defined(OFFICIAL_BUILD)
-#include "ash/webui/facial_ml_app_ui/facial_ml_app_ui.h"
 #include "ash/webui/sample_system_web_app_ui/sample_system_web_app_ui.h"
 #endif  // !defined(OFFICIAL_BUILD)
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
@@ -23,8 +23,8 @@
   auto& map = content::WebUIConfigMap::GetInstance();
   map.AddWebUIConfig(std::make_unique<ash::ShortcutCustomizationAppUIConfig>());
   map.AddWebUIConfig(std::make_unique<chromeos::NotificationTesterUIConfig>());
+  map.AddWebUIConfig(std::make_unique<ash::FaceMLAppUIConfig>());
 #if !defined(OFFICIAL_BUILD)
-  map.AddWebUIConfig(std::make_unique<ash::FacialMLAppUIConfig>());
   map.AddWebUIConfig(std::make_unique<ash::SampleSystemWebAppUIConfig>());
 #endif  // !defined(OFFICIAL_BUILD)
 }
diff --git a/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc b/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc
index 33491f6..7aeb5a2 100644
--- a/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc
@@ -187,10 +187,11 @@
   auto* crostini_manager = crostini::CrostiniManager::GetForProfile(profile_);
   crostini_manager->AddCrostiniDialogStatusObserver(this);
   crostini_manager->AddCrostiniContainerPropertiesObserver(this);
-  crostini_manager->AddContainerStartedObserver(this);
   crostini_manager->AddContainerShutdownObserver(this);
   crostini::CrostiniExportImport::GetForProfile(profile_)->AddObserver(this);
   crostini::CrostiniPortForwarder::GetForProfile(profile_)->AddObserver(this);
+  guest_os::GuestOsSessionTracker::GetForProfile(profile_)
+      ->AddContainerStartedObserver(this);
 
   // Observe ADB sideloading device policy and react to its changes
   adb_sideloading_device_policy_subscription_ =
@@ -218,11 +219,12 @@
   auto* crostini_manager = crostini::CrostiniManager::GetForProfile(profile_);
   crostini_manager->RemoveCrostiniDialogStatusObserver(this);
   crostini_manager->RemoveCrostiniContainerPropertiesObserver(this);
-  crostini_manager->RemoveContainerStartedObserver(this);
   crostini_manager->RemoveContainerShutdownObserver(this);
   crostini::CrostiniExportImport::GetForProfile(profile_)->RemoveObserver(this);
   crostini::CrostiniPortForwarder::GetForProfile(profile_)->RemoveObserver(
       this);
+  guest_os::GuestOsSessionTracker::GetForProfile(profile_)
+      ->RemoveContainerStartedObserver(this);
 
   adb_sideloading_device_policy_subscription_ = {};
   pref_change_registrar_.RemoveAll();
diff --git a/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h b/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h
index 4658b61..c21299b2 100644
--- a/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/ash/crostini/crostini_manager.h"
 #include "chrome/browser/ash/crostini/crostini_port_forwarder.h"
 #include "chrome/browser/ash/guest_os/guest_id.h"
+#include "chrome/browser/ash/guest_os/guest_os_session_tracker.h"
 #include "chrome/browser/ash/settings/cros_settings.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
@@ -34,7 +35,7 @@
                         public crostini::CrostiniExportImport::Observer,
                         public crostini::CrostiniContainerPropertiesObserver,
                         public crostini::CrostiniPortForwarder::Observer,
-                        public crostini::ContainerStartedObserver,
+                        public guest_os::ContainerStartedObserver,
                         public crostini::ContainerShutdownObserver {
  public:
   explicit CrostiniHandler(Profile* profile);
@@ -122,7 +123,7 @@
   void HandleGetCrostiniActivePorts(const base::Value::List& args);
   // Checks if Crostini is running.
   void HandleCheckCrostiniIsRunning(const base::Value::List& args);
-  // crostini::ContainerStartedObserver
+  // guest_os::ContainerStartedObserver
   void OnContainerStarted(const guest_os::GuestId& container_id) override;
   // crostini::ContainerShutdownObserver
   void OnContainerShutdown(const guest_os::GuestId& container_id) override;
diff --git a/chrome/browser/web_applications/web_app_icon_generator.cc b/chrome/browser/web_applications/web_app_icon_generator.cc
index 75cc082..e19ec5ef 100644
--- a/chrome/browser/web_applications/web_app_icon_generator.cc
+++ b/chrome/browser/web_applications/web_app_icon_generator.cc
@@ -19,7 +19,6 @@
 #include "skia/ext/image_operations.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/canvas.h"
-#include "ui/gfx/color_analysis.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/font.h"
 #include "ui/gfx/font_list.h"
@@ -38,11 +37,9 @@
 class GeneratedIconImageSource : public gfx::CanvasImageSource {
  public:
   explicit GeneratedIconImageSource(char32_t icon_letter,
-                                    SkColor color,
                                     SquareSizePx output_size)
       : gfx::CanvasImageSource(gfx::Size(output_size, output_size)),
         icon_letter_(icon_letter),
-        color_(color),
         output_size_(output_size) {}
   GeneratedIconImageSource(const GeneratedIconImageSource&) = delete;
   GeneratedIconImageSource& operator=(const GeneratedIconImageSource&) = delete;
@@ -67,10 +64,13 @@
     font_name = kChromeOSFontFamily;
 #endif
 
+    // Use a dark gray so it will stand out on the black shelf.
+    constexpr SkColor color = SK_ColorDKGRAY;
+
     // Draw a rounded rect of the given |color|.
     cc::PaintFlags background_flags;
     background_flags.setAntiAlias(true);
-    background_flags.setColor(color_);
+    background_flags.setColor(color);
 
     gfx::Rect icon_rect(icon_inset, icon_inset, icon_size, icon_size);
     canvas->DrawRoundRect(icon_rect, border_radius, background_flags);
@@ -80,43 +80,34 @@
     canvas->DrawStringRectWithFlags(
         IconLetterToString(icon_letter_),
         gfx::FontList(gfx::Font(font_name, font_size)),
-        color_utils::GetColorWithMaxContrast(color_), text_rect,
+        color_utils::GetColorWithMaxContrast(color), text_rect,
         gfx::Canvas::TEXT_ALIGN_CENTER);
   }
 
   char32_t icon_letter_;
 
-  SkColor color_;
-
   int output_size_;
 };
 
 // Adds a square container icon of |output_size| and 2 * |output_size| pixels
-// to |bitmaps| by drawing the given |icon_letter| into a rounded background of
-// |color|. For each size, if an icon of the requested size already exists in
-// |bitmaps|, nothing will happen.
+// to |bitmaps| by drawing the given |icon_letter| into a rounded background.
+// For each size, if an icon of the requested size already exists in |bitmaps|,
+// nothing will happen.
 void GenerateIcon(SizeToBitmap* bitmaps,
                   SquareSizePx output_size,
-                  SkColor color,
                   char32_t icon_letter) {
   // Do nothing if there is already an icon of |output_size|.
   if (bitmaps->count(output_size))
     return;
 
-  (*bitmaps)[output_size] = GenerateBitmap(output_size, color, icon_letter);
+  (*bitmaps)[output_size] = GenerateBitmap(output_size, icon_letter);
 }
 
 void GenerateIcons(const std::set<SquareSizePx>& generate_sizes,
                    char32_t icon_letter,
-                   SkColor generated_icon_color,
                    SizeToBitmap* bitmap_map) {
-  // If no color has been specified, use a dark gray so it will stand out on the
-  // black shelf.
-  if (generated_icon_color == SK_ColorTRANSPARENT)
-    generated_icon_color = SK_ColorDKGRAY;
-
   for (SquareSizePx size : generate_sizes)
-    GenerateIcon(bitmap_map, size, generated_icon_color, icon_letter);
+    GenerateIcon(bitmap_map, size, icon_letter);
 }
 
 // Gets the first code point of a string.
@@ -176,12 +167,10 @@
   return output_bitmaps;
 }
 
-SkBitmap GenerateBitmap(SquareSizePx output_size,
-                        SkColor color,
-                        char32_t icon_letter) {
-  gfx::ImageSkia icon_image(std::make_unique<GeneratedIconImageSource>(
-                                icon_letter, color, output_size),
-                            gfx::Size(output_size, output_size));
+SkBitmap GenerateBitmap(SquareSizePx output_size, char32_t icon_letter) {
+  gfx::ImageSkia icon_image(
+      std::make_unique<GeneratedIconImageSource>(icon_letter, output_size),
+      gfx::Size(output_size, output_size));
   SkBitmap dst;
   if (dst.tryAllocPixels(icon_image.bitmap()->info())) {
     icon_image.bitmap()->readPixels(dst.info(), dst.getPixels(), dst.rowBytes(),
@@ -225,9 +214,7 @@
     const std::vector<SkBitmap>& icons,
     const std::set<SquareSizePx>& sizes_to_generate,
     char32_t icon_letter,
-    SkColor* generated_icon_color,
     bool* is_generated_icon) {
-  DCHECK(generated_icon_color);
   DCHECK(is_generated_icon);
 
   // Resize provided icons to make sure we have versions for each size in
@@ -242,12 +229,6 @@
   }
 
   if (!resized_bitmaps.empty()) {
-    // Determine the color that will be used for the icon's background. For this
-    // the dominant color of the first icon found is used.
-    color_utils::GridSampler sampler;
-    *generated_icon_color = color_utils::CalculateKMeanColorOfBitmap(
-        resized_bitmaps.begin()->second);
-
     *is_generated_icon = false;
     // ConstrainBitmapsToSizes generates versions for each size in
     // |sizes_to_generate|, so we don't need to generate icons.
@@ -255,20 +236,18 @@
   }
 
   *is_generated_icon = true;
-  GenerateIcons(sizes_to_generate, icon_letter, *generated_icon_color,
-                &resized_bitmaps);
+  GenerateIcons(sizes_to_generate, icon_letter, &resized_bitmaps);
 
   return resized_bitmaps;
 }
 
-SizeToBitmap GenerateIcons(const std::string& app_name,
-                           SkColor background_icon_color) {
+SizeToBitmap GenerateIcons(const std::string& app_name) {
   const std::u16string app_name_utf16 = base::UTF8ToUTF16(app_name);
   const char32_t icon_letter = GenerateIconLetterFromAppName(app_name_utf16);
 
   SizeToBitmap icons;
   for (SquareSizePx size : SizesToGenerate()) {
-    icons[size] = GenerateBitmap(size, background_icon_color, icon_letter);
+    icons[size] = GenerateBitmap(size, icon_letter);
   }
   return icons;
 }
diff --git a/chrome/browser/web_applications/web_app_icon_generator.h b/chrome/browser/web_applications/web_app_icon_generator.h
index 0524eef..53c4a24 100644
--- a/chrome/browser/web_applications/web_app_icon_generator.h
+++ b/chrome/browser/web_applications/web_app_icon_generator.h
@@ -62,10 +62,8 @@
                                      const std::set<SquareSizePx>& sizes);
 
 // Generates a square container icon of |output_size| by drawing the given
-// |icon_letter| into a rounded background of |color|.
-SkBitmap GenerateBitmap(SquareSizePx output_size,
-                        SkColor color,
-                        char32_t icon_letter);
+// |icon_letter|.
+SkBitmap GenerateBitmap(SquareSizePx output_size, char32_t icon_letter);
 
 // Returns the first letter from |app_url| that will be painted on the generated
 // icon.
@@ -84,20 +82,16 @@
 // Resize icons to the accepted sizes, and generate any that are missing.
 // Note that |icon_letter| is the first letter of app name if available
 // otherwise the first letter of app url.
-// Output: |generated_icon_color| is the color to use if an icon needs to be
-// generated for the web app. |is_generated_icon| represents whether the icons
-// were generated.
+// Output: |is_generated_icon| represents whether the icons were generated.
 SizeToBitmap ResizeIconsAndGenerateMissing(
     const std::vector<SkBitmap>& icons,
     const std::set<SquareSizePx>& sizes_to_generate,
     char32_t icon_letter,
-    SkColor* generated_icon_color,
     bool* is_generated_icon);
 
 // Generate icons for default sizes, using the first letter of the application
-// name and some background color. |app_name| is encoded as UTF8.
-SizeToBitmap GenerateIcons(const std::string& app_name,
-                           SkColor background_icon_color);
+// name. |app_name| is encoded as UTF8.
+SizeToBitmap GenerateIcons(const std::string& app_name);
 
 // Converts any image with arbitrary RGB channels to a monochrome image
 // according to the spec.
diff --git a/chrome/browser/web_applications/web_app_icon_generator_unittest.cc b/chrome/browser/web_applications/web_app_icon_generator_unittest.cc
index 27b4d77..5520bf9 100644
--- a/chrome/browser/web_applications/web_app_icon_generator_unittest.cc
+++ b/chrome/browser/web_applications/web_app_icon_generator_unittest.cc
@@ -153,11 +153,10 @@
   downloaded.push_back(CreateSquareIcon(icon_size, SK_ColorRED));
 
   // Now run the resizing/generation and validation.
-  SkColor generated_icon_color = SK_ColorTRANSPARENT;
   bool is_generated_icon = true;
   auto size_map = ResizeIconsAndGenerateMissing(
       downloaded, TestSizesToGenerate(), GenerateIconLetterFromAppName(u"Test"),
-      &generated_icon_color, &is_generated_icon);
+      &is_generated_icon);
   EXPECT_FALSE(is_generated_icon);
 
   ValidateIconsGeneratedAndResizedCorrectly(
@@ -239,11 +238,10 @@
   const auto& sizes = TestSizesToGenerate();
 
   // Now run the resizing and generation into a new web icons info.
-  SkColor generated_icon_color = SK_ColorTRANSPARENT;
   bool is_generated_icon = true;
   SizeToBitmap size_map = ResizeIconsAndGenerateMissing(
       downloaded, sizes, GenerateIconLetterFromAppName(u"Test"),
-      &generated_icon_color, &is_generated_icon);
+      &is_generated_icon);
   EXPECT_EQ(sizes.size(), size_map.size());
   EXPECT_FALSE(is_generated_icon);
 
@@ -264,11 +262,10 @@
       CreateSquareIcon(kIconSizeLargeBetweenMediumAndLarge, color));
 
   // Now run the resizing and generation.
-  SkColor generated_icon_color = SK_ColorTRANSPARENT;
   bool is_generated_icon = true;
   SizeToBitmap size_map = ResizeIconsAndGenerateMissing(
       downloaded, TestSizesToGenerate(), GenerateIconLetterFromAppName(u"Test"),
-      &generated_icon_color, &is_generated_icon);
+      &is_generated_icon);
   EXPECT_FALSE(is_generated_icon);
 
   // No icons should be generated. The LARGE and MEDIUM sizes should be resized.
@@ -285,11 +282,10 @@
   downloaded.push_back(CreateSquareIcon(icon_size::k512, SK_ColorBLACK));
 
   // Now run the resizing and generation.
-  SkColor generated_icon_color = SK_ColorTRANSPARENT;
   bool is_generated_icon = true;
   SizeToBitmap size_map = ResizeIconsAndGenerateMissing(
       downloaded, TestSizesToGenerate(), GenerateIconLetterFromAppName(u"Test"),
-      &generated_icon_color, &is_generated_icon);
+      &is_generated_icon);
   EXPECT_FALSE(is_generated_icon);
 
   // Expect icon for MEDIUM and LARGE to be resized from the gigantor icon
@@ -303,11 +299,10 @@
   std::vector<SkBitmap> downloaded;
 
   // Now run the resizing and generation.
-  SkColor generated_icon_color = SK_ColorTRANSPARENT;
   bool is_generated_icon = false;
   SizeToBitmap size_map = ResizeIconsAndGenerateMissing(
       downloaded, TestSizesToGenerate(), GenerateIconLetterFromAppName(u"Test"),
-      &generated_icon_color, &is_generated_icon);
+      &is_generated_icon);
   EXPECT_TRUE(is_generated_icon);
 
   // Expect all icons to be generated.
@@ -323,11 +318,10 @@
   downloaded.push_back(CreateSquareIcon(icon_size::k48, SK_ColorBLUE));
 
   // Now run the resizing and generation.
-  SkColor generated_icon_color = SK_ColorTRANSPARENT;
   bool is_generated_icon = true;
   SizeToBitmap size_map = ResizeIconsAndGenerateMissing(
       downloaded, TestSizesToGenerate(), GenerateIconLetterFromAppName(u"Test"),
-      &generated_icon_color, &is_generated_icon);
+      &is_generated_icon);
   EXPECT_FALSE(is_generated_icon);
 
   // Expect no icons to be generated, but the LARGE and SMALL icons to be
@@ -408,12 +402,11 @@
 
 TEST_F(WebAppIconGeneratorTest, GenerateIcons) {
   std::set<int> sizes = SizesToGenerate();
-  const SkColor bg_color = SK_ColorCYAN;
+  constexpr SkColor bg_color = SK_ColorDKGRAY;
 
   // The |+| character guarantees that there is some letter_color area at the
   // center of the generated icon.
-  const std::map<SquareSizePx, SkBitmap> icon_bitmaps =
-      GenerateIcons("+", bg_color);
+  const std::map<SquareSizePx, SkBitmap> icon_bitmaps = GenerateIcons("+");
   EXPECT_EQ(sizes.size(), icon_bitmaps.size());
 
   for (const std::pair<const SquareSizePx, SkBitmap>& icon : icon_bitmaps) {
diff --git a/chrome/browser/web_applications/web_app_install_info.cc b/chrome/browser/web_applications/web_app_install_info.cc
index d653cc7..948a23b4 100644
--- a/chrome/browser/web_applications/web_app_install_info.cc
+++ b/chrome/browser/web_applications/web_app_install_info.cc
@@ -227,7 +227,6 @@
   create_shortcut_info.icon_bitmaps = other.icon_bitmaps;
   create_shortcut_info.other_icon_bitmaps = other.other_icon_bitmaps;
   create_shortcut_info.is_generated_icon = other.is_generated_icon;
-  create_shortcut_info.generated_icon_color = other.generated_icon_color;
   create_shortcut_info.theme_color = other.theme_color;
   create_shortcut_info.dark_mode_theme_color = other.dark_mode_theme_color;
   create_shortcut_info.background_color = other.background_color;
diff --git a/chrome/browser/web_applications/web_app_install_info.h b/chrome/browser/web_applications/web_app_install_info.h
index 3480054d..34e9be2 100644
--- a/chrome/browser/web_applications/web_app_install_info.h
+++ b/chrome/browser/web_applications/web_app_install_info.h
@@ -243,9 +243,6 @@
   // tag.
   MobileCapable mobile_capable = MOBILE_CAPABLE_UNSPECIFIED;
 
-  // The color to use if an icon needs to be generated for the web app.
-  SkColor generated_icon_color = SK_ColorTRANSPARENT;
-
   // The color to use for the web app frame.
   absl::optional<SkColor> theme_color;
 
diff --git a/chrome/browser/web_applications/web_app_install_utils.cc b/chrome/browser/web_applications/web_app_install_utils.cc
index f87788a..788d3c0 100644
--- a/chrome/browser/web_applications/web_app_install_utils.cc
+++ b/chrome/browser/web_applications/web_app_install_utils.cc
@@ -721,7 +721,6 @@
       web_app_info->title.empty()
           ? GenerateIconLetterFromUrl(web_app_info->start_url)
           : GenerateIconLetterFromAppName(web_app_info->title);
-  web_app_info->generated_icon_color = SK_ColorTRANSPARENT;
   // Ensure that all top-level icons that are in web_app_info with  Purpose::ANY
   // are present, by generating icons for any sizes that have failed to
   // download. This ensures that the created manifest for the web app does not
@@ -730,7 +729,7 @@
   // not necessary and would simplify this code path to remove.
   SizeToBitmap size_to_icons = ResizeIconsAndGenerateMissing(
       square_icons_any, SizesToGenerate(), icon_letter,
-      &web_app_info->generated_icon_color, &web_app_info->is_generated_icon);
+      &web_app_info->is_generated_icon);
 
   for (auto& item : size_to_icons) {
     // Retain any bitmaps provided as input to the installation.
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index dbcf8043..f4caed9a 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1661190988-cd26b70dd483a7fc544ebb08f3af0232e4a03671.profdata
+chrome-linux-main-1661212800-c3763b8584ba96c5d2782c77a96108aef28cefb4.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 55b90ef..bb8f55b 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1661190988-b67380cc09138484e6ed1514af28ccfd8cc91d91.profdata
+chrome-mac-arm-main-1661212800-cfe80023b221715da429cdd6ec927053d8a2c735.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 383476b..a5e0ada 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1661190988-9ac98bed8f99b0fcca5df0750480040f96fc654d.profdata
+chrome-mac-main-1661212800-ba20bcdfa6a109f25cb2b96da2d00a921cd66a34.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 30f4848..01eb044c 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1661190988-e5e5e66c3711faf6bfffbcc96601718f88bcce9f.profdata
+chrome-win32-main-1661212788-c15bed7d97c474419826f979eb3434fa44757fe5.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 05e52ed..94c5243 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1661201802-27e2a46364cdc7db87549b5feb2711214acc783e.profdata
+chrome-win64-main-1661223573-c415751e4cb183fb4e01a3c82b8d9be873afb94a.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni
index 2965af4b..1e0bae8 100644
--- a/chrome/chrome_paks.gni
+++ b/chrome/chrome_paks.gni
@@ -223,6 +223,7 @@
         "$root_gen_dir/ash/webui/ash_diagnostics_app_resources.pak",
         "$root_gen_dir/ash/webui/ash_eche_app_resources.pak",
         "$root_gen_dir/ash/webui/ash_eche_bundle_resources.pak",
+        "$root_gen_dir/ash/webui/ash_face_ml_app_resources.pak",
         "$root_gen_dir/ash/webui/ash_firmware_update_app_resources.pak",
         "$root_gen_dir/ash/webui/ash_guest_os_installer_resources.pak",
         "$root_gen_dir/ash/webui/ash_help_app_resources.pak",
@@ -283,6 +284,7 @@
         "//ash/webui/resources:diagnostics_app_resources",
         "//ash/webui/resources:eche_app_resources",
         "//ash/webui/resources:eche_bundle_resources",
+        "//ash/webui/resources:face_ml_app_resources",
         "//ash/webui/resources:firmware_update_app_resources",
         "//ash/webui/resources:guest_os_installer_resources",
         "//ash/webui/resources:help_app_bundle_resources",
@@ -332,13 +334,11 @@
       if (!is_official_build) {
         sources += [
           "$root_gen_dir/ash/webui/ash_demo_mode_app_resources.pak",
-          "$root_gen_dir/ash/webui/ash_facial_ml_app_resources.pak",
           "$root_gen_dir/ash/webui/ash_sample_system_web_app_resources.pak",
           "$root_gen_dir/ash/webui/ash_sample_system_web_app_untrusted_resources.pak",
         ]
         deps += [
           "//ash/webui/resources:demo_mode_app_resources",
-          "//ash/webui/resources:facial_ml_app_resources",
           "//ash/webui/resources:sample_system_web_app_resources",
           "//ash/webui/resources:sample_system_web_app_untrusted_resources",
         ]
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index d132b22..7215e033 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -10915,8 +10915,13 @@
       ":browser_tests_runner",
       ":test_support_ui",
       "//base",
+      "//base/test:test_support",
+      "//chrome/browser",
+      "//chrome/browser/ash",
       "//chrome/browser/ash/crosapi",
+      "//chrome/browser/ui",
       "//chromeos/crosapi/mojom",
+      "//components/services/app_service/public/cpp:app_types",
     ]
   }
 }
diff --git a/chrome/test/data/app_deduplication_service/binary_test_data.pb b/chrome/test/data/app_deduplication_service/binary_test_data.pb
index b5ee5267..cbb69b082 100644
--- a/chrome/test/data/app_deduplication_service/binary_test_data.pb
+++ b/chrome/test/data/app_deduplication_service/binary_test_data.pb
@@ -1,14 +1,12 @@
 
-^
-SkypeU
+U
 
 com.skype.raiderJphonehub
 
 com.skype.raiderJarc
 
 http://web.skype.com/Jweb
-\
-WhatsAppP
+P
 
 com.whatsappJphonehub
 
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index e905633a..6bc4f10 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -17930,6 +17930,41 @@
   "U2fSecurityKeyApiEnabled": {
     "reason_for_missing_test": "Policy was deprecated in M103"
   },
+  "LoadCryptoTokenExtension": {
+    "os": [
+      "win",
+      "linux",
+      "mac",
+      "chromeos_ash",
+      "chromeos_lacros"
+    ],
+    "policy_pref_mapping_tests": [
+      {
+        "policies": { "LoadCryptoTokenExtension": false },
+        "prefs": {
+          "extensions.load_cryptotoken_extension": {
+            "value": false
+          }
+        }
+      },
+      {
+        "policies": { "LoadCryptoTokenExtension": true },
+        "prefs": {
+          "extensions.load_cryptotoken_extension": {
+            "value": true
+          }
+        }
+      },
+      {
+        "policies": {},
+        "prefs": {
+          "extensions.load_cryptotoken_extension": {
+            "default_value": false
+          }
+        }
+      }
+    ]
+  },
   "DeviceLoginScreenPromptOnMultipleMatchingCertificates": {
     "os": ["chromeos_ash"],
     "policy_pref_mapping_tests": [
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 bddb4bf..2b6e645f 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
@@ -10,6 +10,7 @@
 import {FakeSystemDataProvider} from 'chrome://diagnostics/fake_system_data_provider.js';
 import {getSystemDataProvider, setSystemDataProviderForTesting} from 'chrome://diagnostics/mojo_interface_provider.js';
 import {mojoString16ToString} from 'chrome://diagnostics/mojo_utils.js';
+import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
 import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.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 a19f93f..e3ee736 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_test.js
@@ -12,6 +12,7 @@
 import {FakeSystemDataProvider} from 'chrome://diagnostics/fake_system_data_provider.js';
 import {FakeSystemRoutineController} from 'chrome://diagnostics/fake_system_routine_controller.js';
 import {setInputDataProviderForTesting, setNetworkHealthProviderForTesting, setSystemDataProviderForTesting, setSystemRoutineControllerForTesting} from 'chrome://diagnostics/mojo_interface_provider.js';
+import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
 import {assertFalse, assertTrue} from '../../chai_assert.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 7020c6bf..2396007fb 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_test_utils.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_test_utils.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
+
 import {assertEquals, assertTrue} from '../../chai_assert.js';
 import {isVisible} from '../../test_util.js';
 
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 c354d7422..e26046c 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/memory_card_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/memory_card_test.js
@@ -9,6 +9,7 @@
 import {fakeMemoryUsage, fakeMemoryUsageLowAvailableMemory} from 'chrome://diagnostics/fake_data.js';
 import {FakeSystemDataProvider} from 'chrome://diagnostics/fake_system_data_provider.js';
 import {setSystemDataProviderForTesting} from 'chrome://diagnostics/mojo_interface_provider.js';
+import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
 import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.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 cb035486..0abe3d6 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/routine_section_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/routine_section_test.js
@@ -13,6 +13,7 @@
 import {ExecutionProgress, TestSuiteStatus} from 'chrome://diagnostics/routine_list_executor.js';
 import {getRoutineType} from 'chrome://diagnostics/routine_result_entry.js';
 import {BadgeType} from 'chrome://diagnostics/text_badge.js';
+import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
 import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.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 dd58ea0c..e14eeb7 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/system_page_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/system_page_test.js
@@ -12,6 +12,7 @@
 import {FakeSystemRoutineController} from 'chrome://diagnostics/fake_system_routine_controller.js';
 import {setNetworkHealthProviderForTesting, setSystemDataProviderForTesting, setSystemRoutineControllerForTesting} from 'chrome://diagnostics/mojo_interface_provider.js';
 import {TestSuiteStatus} from 'chrome://diagnostics/routine_list_executor.js';
+import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
 import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
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 edf0c81..f82369c 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
@@ -10,6 +10,7 @@
 import {getUpdateProvider, setUpdateControllerForTesting, setUpdateProviderForTesting} from 'chrome://accessory-update/mojo_interface_provider.js';
 import {mojoString16ToString} from 'chrome://accessory-update/mojo_utils.js';
 import {UpdateCardElement} from 'chrome://accessory-update/update_card.js';
+import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
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 c282a524..fa0df87 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
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import {GaiaActionButtonsElement} from 'chrome://chrome-signin/gaia_action_buttons/gaia_action_buttons.js';
+import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.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 0b0acac5..2d4b295 100644
--- a/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js
@@ -4,6 +4,7 @@
 
 import 'chrome://scanning/scanning_app.js';
 
+import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js';
 import {setScanServiceForTesting} from 'chrome://scanning/mojo_interface_provider.js';
diff --git a/chromeos/ash/components/dbus/arc/arc_appfuse_provider_client.cc b/chromeos/ash/components/dbus/arc/arc_appfuse_provider_client.cc
index a8804921..10d0b6c 100644
--- a/chromeos/ash/components/dbus/arc/arc_appfuse_provider_client.cc
+++ b/chromeos/ash/components/dbus/arc/arc_appfuse_provider_client.cc
@@ -50,7 +50,7 @@
 
   void Unmount(uint32_t uid,
                int32_t mount_id,
-               VoidDBusMethodCallback callback) override {
+               chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(arc::appfuse::kArcAppfuseProviderInterface,
                                  arc::appfuse::kUnmountMethod);
     dbus::MessageWriter writer(&method_call);
@@ -90,7 +90,7 @@
 
  private:
   // Runs the callback with the method call result.
-  void OnVoidDBusMethod(VoidDBusMethodCallback callback,
+  void OnVoidDBusMethod(chromeos::VoidDBusMethodCallback callback,
                         dbus::Response* response) {
     std::move(callback).Run(response != nullptr);
   }
diff --git a/chromeos/ash/components/dbus/arc/arc_appfuse_provider_client.h b/chromeos/ash/components/dbus/arc/arc_appfuse_provider_client.h
index 53f4048e..485344b 100644
--- a/chromeos/ash/components/dbus/arc/arc_appfuse_provider_client.h
+++ b/chromeos/ash/components/dbus/arc/arc_appfuse_provider_client.h
@@ -42,7 +42,7 @@
   // Unmounts the specified appfuse file system.
   virtual void Unmount(uint32_t uid,
                        int32_t mount_id,
-                       VoidDBusMethodCallback callback) = 0;
+                       chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Opens a file under the specified appfuse file system.
   virtual void OpenFile(
diff --git a/chromeos/ash/components/dbus/arc/arc_camera_client.cc b/chromeos/ash/components/dbus/arc/arc_camera_client.cc
index a1ba522..4c2a7329 100644
--- a/chromeos/ash/components/dbus/arc/arc_camera_client.cc
+++ b/chromeos/ash/components/dbus/arc/arc_camera_client.cc
@@ -36,7 +36,7 @@
   // ArcCameraClient overrides:
   void StartService(int fd,
                     const std::string& token,
-                    VoidDBusMethodCallback callback) override {
+                    chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(arc_camera::kArcCameraServiceInterface,
                                  "StartService");
     dbus::MessageWriter writer(&method_call);
@@ -49,7 +49,8 @@
   }
 
  private:
-  void OnVoidMethod(VoidDBusMethodCallback callback, dbus::Response* response) {
+  void OnVoidMethod(chromeos::VoidDBusMethodCallback callback,
+                    dbus::Response* response) {
     std::move(callback).Run(response);
   }
 
diff --git a/chromeos/ash/components/dbus/arc/arc_camera_client.h b/chromeos/ash/components/dbus/arc/arc_camera_client.h
index 91ca2a7..b14a487 100644
--- a/chromeos/ash/components/dbus/arc/arc_camera_client.h
+++ b/chromeos/ash/components/dbus/arc/arc_camera_client.h
@@ -38,7 +38,7 @@
   // token and FD.
   virtual void StartService(int fd,
                             const std::string& token,
-                            VoidDBusMethodCallback callback) = 0;
+                            chromeos::VoidDBusMethodCallback callback) = 0;
 
  protected:
   // Initialize() should be used instead.
diff --git a/chromeos/ash/components/dbus/arc/arc_data_snapshotd_client.cc b/chromeos/ash/components/dbus/arc/arc_data_snapshotd_client.cc
index d81cad1..d6daec0 100644
--- a/chromeos/ash/components/dbus/arc/arc_data_snapshotd_client.cc
+++ b/chromeos/ash/components/dbus/arc/arc_data_snapshotd_client.cc
@@ -22,7 +22,7 @@
 
 ArcDataSnapshotdClient* g_instance = nullptr;
 
-void OnBoolMethodCallback(VoidDBusMethodCallback callback,
+void OnBoolMethodCallback(chromeos::VoidDBusMethodCallback callback,
                           dbus::Response* response) {
   if (!response) {
     std::move(callback).Run(false /* success */);
@@ -68,7 +68,7 @@
   ArcDataSnapshotdClientImpl& operator=(const ArcDataSnapshotdClientImpl&) =
       delete;
 
-  void GenerateKeyPair(VoidDBusMethodCallback callback) override {
+  void GenerateKeyPair(chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(
         arc::data_snapshotd::kArcDataSnapshotdServiceInterface,
         arc::data_snapshotd::kGenerateKeyPairMethod);
@@ -78,7 +78,8 @@
         base::BindOnce(&OnBoolMethodCallback, std::move(callback)));
   }
 
-  void ClearSnapshot(bool last, VoidDBusMethodCallback callback) override {
+  void ClearSnapshot(bool last,
+                     chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(
         arc::data_snapshotd::kArcDataSnapshotdServiceInterface,
         arc::data_snapshotd::kClearSnapshotMethod);
@@ -90,7 +91,7 @@
   }
 
   void TakeSnapshot(const std::string& account_id,
-                    VoidDBusMethodCallback callback) override {
+                    chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(
         arc::data_snapshotd::kArcDataSnapshotdServiceInterface,
         arc::data_snapshotd::kTakeSnapshotMethod);
@@ -113,7 +114,7 @@
         base::BindOnce(&OnLoadSnapshotMethodCallback, std::move(callback)));
   }
 
-  void Update(int percent, VoidDBusMethodCallback callback) override {
+  void Update(int percent, chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(
         arc::data_snapshotd::kArcDataSnapshotdServiceInterface,
         arc::data_snapshotd::kUpdateMethod);
diff --git a/chromeos/ash/components/dbus/arc/arc_data_snapshotd_client.h b/chromeos/ash/components/dbus/arc/arc_data_snapshotd_client.h
index 3a41a12..884b021 100644
--- a/chromeos/ash/components/dbus/arc/arc_data_snapshotd_client.h
+++ b/chromeos/ash/components/dbus/arc/arc_data_snapshotd_client.h
@@ -43,16 +43,17 @@
 
   // Generate key pair for an upcoming session.
   // Should be called before the user session started.
-  virtual void GenerateKeyPair(VoidDBusMethodCallback callback) = 0;
+  virtual void GenerateKeyPair(chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Remove a snapshot. If |last|, remove the last generated snapshot,
   // otherwise the previous one.
-  virtual void ClearSnapshot(bool last, VoidDBusMethodCallback callback) = 0;
+  virtual void ClearSnapshot(bool last,
+                             chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Take the ARC data/ snapshot of the current session.
   // MGS is a current active session with |account_id|.
   virtual void TakeSnapshot(const std::string& account_id,
-                            VoidDBusMethodCallback callback) = 0;
+                            chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Load the ARC data/ snapshot to the current active MGS with |account_id|.
   virtual void LoadSnapshot(const std::string& account_id,
@@ -60,7 +61,8 @@
 
   // Update a progress bar on a UI screen.
   // |percent| is a percentage of installed required ARC apps [0..100].
-  virtual void Update(int percent, VoidDBusMethodCallback callback) = 0;
+  virtual void Update(int percent,
+                      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Connects callbacks to D-Bus signal |UiCancelled| sent by
   // arc-data-snapshotd.
diff --git a/chromeos/ash/components/dbus/arc/arc_keymaster_client.cc b/chromeos/ash/components/dbus/arc/arc_keymaster_client.cc
index 04cc9e1..753748e 100644
--- a/chromeos/ash/components/dbus/arc/arc_keymaster_client.cc
+++ b/chromeos/ash/components/dbus/arc/arc_keymaster_client.cc
@@ -22,7 +22,7 @@
 
 ArcKeymasterClient* g_instance = nullptr;
 
-void OnVoidDBusMethod(VoidDBusMethodCallback callback,
+void OnVoidDBusMethod(chromeos::VoidDBusMethodCallback callback,
                       dbus::Response* response) {
   std::move(callback).Run(response != nullptr);
 }
@@ -36,8 +36,9 @@
 
   ~ArcKeymasterClientImpl() override = default;
 
-  void BootstrapMojoConnection(base::ScopedFD fd,
-                               VoidDBusMethodCallback callback) override {
+  void BootstrapMojoConnection(
+      base::ScopedFD fd,
+      chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(
         arc::keymaster::kArcKeymasterInterfaceName,
         arc::keymaster::kBootstrapMojoConnectionMethod);
diff --git a/chromeos/ash/components/dbus/arc/arc_keymaster_client.h b/chromeos/ash/components/dbus/arc/arc_keymaster_client.h
index ce35f16..288316cf 100644
--- a/chromeos/ash/components/dbus/arc/arc_keymaster_client.h
+++ b/chromeos/ash/components/dbus/arc/arc_keymaster_client.h
@@ -32,8 +32,9 @@
 
   // Bootstrap the Mojo connection between Chrome and the keymaster service.
   // Should pass in the child end of the Mojo pipe.
-  virtual void BootstrapMojoConnection(base::ScopedFD fd,
-                                       VoidDBusMethodCallback callback) = 0;
+  virtual void BootstrapMojoConnection(
+      base::ScopedFD fd,
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
  protected:
   // Initialize() should be used instead.
diff --git a/chromeos/ash/components/dbus/arc/arc_midis_client.cc b/chromeos/ash/components/dbus/arc/arc_midis_client.cc
index 5411e6b..c9e783c 100644
--- a/chromeos/ash/components/dbus/arc/arc_midis_client.cc
+++ b/chromeos/ash/components/dbus/arc/arc_midis_client.cc
@@ -34,8 +34,9 @@
 
   ~ArcMidisClientImpl() override = default;
 
-  void BootstrapMojoConnection(base::ScopedFD fd,
-                               VoidDBusMethodCallback callback) override {
+  void BootstrapMojoConnection(
+      base::ScopedFD fd,
+      chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(midis::kMidisInterfaceName,
                                  midis::kBootstrapMojoConnectionMethod);
     dbus::MessageWriter writer(&method_call);
@@ -53,7 +54,7 @@
   }
 
  private:
-  void OnVoidDBusMethod(VoidDBusMethodCallback callback,
+  void OnVoidDBusMethod(chromeos::VoidDBusMethodCallback callback,
                         dbus::Response* response) {
     std::move(callback).Run(response != nullptr);
   }
diff --git a/chromeos/ash/components/dbus/arc/arc_midis_client.h b/chromeos/ash/components/dbus/arc/arc_midis_client.h
index 8cb0a7d3..3aae66c16 100644
--- a/chromeos/ash/components/dbus/arc/arc_midis_client.h
+++ b/chromeos/ash/components/dbus/arc/arc_midis_client.h
@@ -34,8 +34,9 @@
 
   // Bootstrap the Mojo connection between Chrome and the MIDI service.
   // Should pass in the child end of the Mojo pipe.
-  virtual void BootstrapMojoConnection(base::ScopedFD fd,
-                                       VoidDBusMethodCallback callback) = 0;
+  virtual void BootstrapMojoConnection(
+      base::ScopedFD fd,
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
  protected:
   // Initialize() should be used instead.
diff --git a/chromeos/ash/components/dbus/arc/arc_obb_mounter_client.cc b/chromeos/ash/components/dbus/arc/arc_obb_mounter_client.cc
index 2ca76af5..5c7883c 100644
--- a/chromeos/ash/components/dbus/arc/arc_obb_mounter_client.cc
+++ b/chromeos/ash/components/dbus/arc/arc_obb_mounter_client.cc
@@ -34,7 +34,7 @@
   void MountObb(const std::string& obb_file,
                 const std::string& mount_path,
                 int32_t owner_gid,
-                VoidDBusMethodCallback callback) override {
+                chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(arc::obb_mounter::kArcObbMounterInterface,
                                  arc::obb_mounter::kMountObbMethod);
     dbus::MessageWriter writer(&method_call);
@@ -48,7 +48,7 @@
   }
 
   void UnmountObb(const std::string& mount_path,
-                  VoidDBusMethodCallback callback) override {
+                  chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(arc::obb_mounter::kArcObbMounterInterface,
                                  arc::obb_mounter::kUnmountObbMethod);
     dbus::MessageWriter writer(&method_call);
@@ -68,7 +68,7 @@
 
  private:
   // Runs the callback with the method call result.
-  void OnVoidDBusMethod(VoidDBusMethodCallback callback,
+  void OnVoidDBusMethod(chromeos::VoidDBusMethodCallback callback,
                         dbus::Response* response) {
     std::move(callback).Run(response != nullptr);
   }
diff --git a/chromeos/ash/components/dbus/arc/arc_obb_mounter_client.h b/chromeos/ash/components/dbus/arc/arc_obb_mounter_client.h
index 01ad4e0f..d0c5e4d0 100644
--- a/chromeos/ash/components/dbus/arc/arc_obb_mounter_client.h
+++ b/chromeos/ash/components/dbus/arc/arc_obb_mounter_client.h
@@ -38,11 +38,11 @@
   virtual void MountObb(const std::string& obb_file,
                         const std::string& mount_path,
                         int32_t owner_gid,
-                        VoidDBusMethodCallback callback) = 0;
+                        chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Unmounts the OBB mounted at the specified path.
   virtual void UnmountObb(const std::string& mount_path,
-                          VoidDBusMethodCallback callback) = 0;
+                          chromeos::VoidDBusMethodCallback callback) = 0;
 
  protected:
   // Initialize() should be used instead.
diff --git a/chromeos/ash/components/dbus/arc/arc_sensor_service_client.cc b/chromeos/ash/components/dbus/arc/arc_sensor_service_client.cc
index f403d905..4759e0a 100644
--- a/chromeos/ash/components/dbus/arc/arc_sensor_service_client.cc
+++ b/chromeos/ash/components/dbus/arc/arc_sensor_service_client.cc
@@ -35,9 +35,10 @@
       delete;
 
   // ArcSensorServiceClient overrides:
-  void BootstrapMojoConnection(int fd,
-                               const std::string& token,
-                               VoidDBusMethodCallback callback) override {
+  void BootstrapMojoConnection(
+      int fd,
+      const std::string& token,
+      chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(arc::sensor::kArcSensorServiceInterface,
                                  arc::sensor::kBootstrapMojoConnectionMethod);
     dbus::MessageWriter writer(&method_call);
@@ -50,7 +51,8 @@
   }
 
  private:
-  void OnVoidMethod(VoidDBusMethodCallback callback, dbus::Response* response) {
+  void OnVoidMethod(chromeos::VoidDBusMethodCallback callback,
+                    dbus::Response* response) {
     std::move(callback).Run(response);
   }
 
diff --git a/chromeos/ash/components/dbus/arc/arc_sensor_service_client.h b/chromeos/ash/components/dbus/arc/arc_sensor_service_client.h
index 03b1c85..bc2cc21 100644
--- a/chromeos/ash/components/dbus/arc/arc_sensor_service_client.h
+++ b/chromeos/ash/components/dbus/arc/arc_sensor_service_client.h
@@ -30,9 +30,10 @@
   static ArcSensorServiceClient* Get();
 
   // Bootstraps the Mojo connection between chrome and arc-sensor-service.
-  virtual void BootstrapMojoConnection(int fd,
-                                       const std::string& token,
-                                       VoidDBusMethodCallback callback) = 0;
+  virtual void BootstrapMojoConnection(
+      int fd,
+      const std::string& token,
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
  protected:
   // Initialize() should be used instead.
diff --git a/chromeos/ash/components/dbus/arc/fake_arc_appfuse_provider_client.cc b/chromeos/ash/components/dbus/arc/fake_arc_appfuse_provider_client.cc
index e0a62930..e040f14d 100644
--- a/chromeos/ash/components/dbus/arc/fake_arc_appfuse_provider_client.cc
+++ b/chromeos/ash/components/dbus/arc/fake_arc_appfuse_provider_client.cc
@@ -26,9 +26,10 @@
       FROM_HERE, base::BindOnce(std::move(callback), base::ScopedFD()));
 }
 
-void FakeArcAppfuseProviderClient::Unmount(uint32_t uid,
-                                           int32_t mount_id,
-                                           VoidDBusMethodCallback callback) {
+void FakeArcAppfuseProviderClient::Unmount(
+    uint32_t uid,
+    int32_t mount_id,
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), false));
 }
diff --git a/chromeos/ash/components/dbus/arc/fake_arc_appfuse_provider_client.h b/chromeos/ash/components/dbus/arc/fake_arc_appfuse_provider_client.h
index 59e6b41..fd1dcac 100644
--- a/chromeos/ash/components/dbus/arc/fake_arc_appfuse_provider_client.h
+++ b/chromeos/ash/components/dbus/arc/fake_arc_appfuse_provider_client.h
@@ -30,7 +30,7 @@
              chromeos::DBusMethodCallback<base::ScopedFD> callback) override;
   void Unmount(uint32_t uid,
                int32_t mount_id,
-               VoidDBusMethodCallback callback) override;
+               chromeos::VoidDBusMethodCallback callback) override;
   void OpenFile(uint32_t uid,
                 int32_t mount_id,
                 int32_t file_id,
diff --git a/chromeos/ash/components/dbus/arc/fake_arc_camera_client.cc b/chromeos/ash/components/dbus/arc/fake_arc_camera_client.cc
index 7c21cc10..a503ffa 100644
--- a/chromeos/ash/components/dbus/arc/fake_arc_camera_client.cc
+++ b/chromeos/ash/components/dbus/arc/fake_arc_camera_client.cc
@@ -34,9 +34,10 @@
   return g_instance;
 }
 
-void FakeArcCameraClient::StartService(int fd,
-                                       const std::string& token,
-                                       VoidDBusMethodCallback callback) {
+void FakeArcCameraClient::StartService(
+    int fd,
+    const std::string& token,
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
diff --git a/chromeos/ash/components/dbus/arc/fake_arc_camera_client.h b/chromeos/ash/components/dbus/arc/fake_arc_camera_client.h
index ffc2c48..cc4177a 100644
--- a/chromeos/ash/components/dbus/arc/fake_arc_camera_client.h
+++ b/chromeos/ash/components/dbus/arc/fake_arc_camera_client.h
@@ -22,7 +22,7 @@
   // ArcCameraClient override:
   void StartService(int fd,
                     const std::string& token,
-                    VoidDBusMethodCallback callback) override;
+                    chromeos::VoidDBusMethodCallback callback) override;
 
  protected:
   friend class ArcCameraClient;
diff --git a/chromeos/ash/components/dbus/arc/fake_arc_data_snapshotd_client.cc b/chromeos/ash/components/dbus/arc/fake_arc_data_snapshotd_client.cc
index c8e7a64..e527eaed 100644
--- a/chromeos/ash/components/dbus/arc/fake_arc_data_snapshotd_client.cc
+++ b/chromeos/ash/components/dbus/arc/fake_arc_data_snapshotd_client.cc
@@ -19,20 +19,21 @@
 void FakeArcDataSnapshotdClient::Init(dbus::Bus* bus) {}
 
 void FakeArcDataSnapshotdClient::GenerateKeyPair(
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
 
 void FakeArcDataSnapshotdClient::ClearSnapshot(
     bool last,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
 
-void FakeArcDataSnapshotdClient::TakeSnapshot(const std::string& account_id,
-                                              VoidDBusMethodCallback callback) {
+void FakeArcDataSnapshotdClient::TakeSnapshot(
+    const std::string& account_id,
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
@@ -44,8 +45,9 @@
       FROM_HERE, base::BindOnce(std::move(callback), true, true));
 }
 
-void FakeArcDataSnapshotdClient::Update(int percent,
-                                        VoidDBusMethodCallback callback) {
+void FakeArcDataSnapshotdClient::Update(
+    int percent,
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
diff --git a/chromeos/ash/components/dbus/arc/fake_arc_data_snapshotd_client.h b/chromeos/ash/components/dbus/arc/fake_arc_data_snapshotd_client.h
index f8ede92..ac422de 100644
--- a/chromeos/ash/components/dbus/arc/fake_arc_data_snapshotd_client.h
+++ b/chromeos/ash/components/dbus/arc/fake_arc_data_snapshotd_client.h
@@ -26,17 +26,18 @@
   void Init(dbus::Bus* bus) override;
 
   // ArcDataSnapshotdClient override:
-  void GenerateKeyPair(VoidDBusMethodCallback callback) override;
+  void GenerateKeyPair(chromeos::VoidDBusMethodCallback callback) override;
 
-  void ClearSnapshot(bool last, VoidDBusMethodCallback callback) override;
+  void ClearSnapshot(bool last,
+                     chromeos::VoidDBusMethodCallback callback) override;
 
   void TakeSnapshot(const std::string& account_id,
-                    VoidDBusMethodCallback callback) override;
+                    chromeos::VoidDBusMethodCallback callback) override;
 
   void LoadSnapshot(const std::string& account_id,
                     LoadSnapshotMethodCallback callback) override;
 
-  void Update(int percent, VoidDBusMethodCallback callback) override;
+  void Update(int percent, chromeos::VoidDBusMethodCallback callback) override;
 
   void ConnectToUiCancelledSignal(
       base::RepeatingClosure signal_callback,
diff --git a/chromeos/ash/components/dbus/arc/fake_arc_keymaster_client.cc b/chromeos/ash/components/dbus/arc/fake_arc_keymaster_client.cc
index f9bb8a25..cf78126 100644
--- a/chromeos/ash/components/dbus/arc/fake_arc_keymaster_client.cc
+++ b/chromeos/ash/components/dbus/arc/fake_arc_keymaster_client.cc
@@ -16,7 +16,7 @@
 
 void FakeArcKeymasterClient::BootstrapMojoConnection(
     base::ScopedFD fd,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), false));
 }
diff --git a/chromeos/ash/components/dbus/arc/fake_arc_keymaster_client.h b/chromeos/ash/components/dbus/arc/fake_arc_keymaster_client.h
index 8b46744..6eca9d73 100644
--- a/chromeos/ash/components/dbus/arc/fake_arc_keymaster_client.h
+++ b/chromeos/ash/components/dbus/arc/fake_arc_keymaster_client.h
@@ -24,8 +24,9 @@
   void Init(dbus::Bus* bus) override;
 
   // ArcKeymasterClient override:
-  void BootstrapMojoConnection(base::ScopedFD fd,
-                               VoidDBusMethodCallback callback) override;
+  void BootstrapMojoConnection(
+      base::ScopedFD fd,
+      chromeos::VoidDBusMethodCallback callback) override;
 };
 
 }  // namespace ash
diff --git a/chromeos/ash/components/dbus/arc/fake_arc_midis_client.cc b/chromeos/ash/components/dbus/arc/fake_arc_midis_client.cc
index 3c5b9ac..06117af 100644
--- a/chromeos/ash/components/dbus/arc/fake_arc_midis_client.cc
+++ b/chromeos/ash/components/dbus/arc/fake_arc_midis_client.cc
@@ -16,7 +16,7 @@
 
 void FakeArcMidisClient::BootstrapMojoConnection(
     base::ScopedFD fd,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), false));
 }
diff --git a/chromeos/ash/components/dbus/arc/fake_arc_midis_client.h b/chromeos/ash/components/dbus/arc/fake_arc_midis_client.h
index caef4a17..293cd20 100644
--- a/chromeos/ash/components/dbus/arc/fake_arc_midis_client.h
+++ b/chromeos/ash/components/dbus/arc/fake_arc_midis_client.h
@@ -24,8 +24,9 @@
   void Init(dbus::Bus* bus) override;
 
   // ArcMidisClient override:
-  void BootstrapMojoConnection(base::ScopedFD fd,
-                               VoidDBusMethodCallback callback) override;
+  void BootstrapMojoConnection(
+      base::ScopedFD fd,
+      chromeos::VoidDBusMethodCallback callback) override;
 };
 
 }  // namespace ash
diff --git a/chromeos/ash/components/dbus/arc/fake_arc_obb_mounter_client.cc b/chromeos/ash/components/dbus/arc/fake_arc_obb_mounter_client.cc
index d2aa782..89eaa0e 100644
--- a/chromeos/ash/components/dbus/arc/fake_arc_obb_mounter_client.cc
+++ b/chromeos/ash/components/dbus/arc/fake_arc_obb_mounter_client.cc
@@ -18,16 +18,18 @@
 
 void FakeArcObbMounterClient::Init(dbus::Bus* bus) {}
 
-void FakeArcObbMounterClient::MountObb(const std::string& obb_file,
-                                       const std::string& mount_path,
-                                       int32_t owner_gid,
-                                       VoidDBusMethodCallback callback) {
+void FakeArcObbMounterClient::MountObb(
+    const std::string& obb_file,
+    const std::string& mount_path,
+    int32_t owner_gid,
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), false));
 }
 
-void FakeArcObbMounterClient::UnmountObb(const std::string& mount_path,
-                                         VoidDBusMethodCallback callback) {
+void FakeArcObbMounterClient::UnmountObb(
+    const std::string& mount_path,
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), false));
 }
diff --git a/chromeos/ash/components/dbus/arc/fake_arc_obb_mounter_client.h b/chromeos/ash/components/dbus/arc/fake_arc_obb_mounter_client.h
index 0a1ee97..c9e329d6 100644
--- a/chromeos/ash/components/dbus/arc/fake_arc_obb_mounter_client.h
+++ b/chromeos/ash/components/dbus/arc/fake_arc_obb_mounter_client.h
@@ -29,9 +29,9 @@
   void MountObb(const std::string& obb_file,
                 const std::string& mount_path,
                 int32_t owner_gid,
-                VoidDBusMethodCallback callback) override;
+                chromeos::VoidDBusMethodCallback callback) override;
   void UnmountObb(const std::string& mount_path,
-                  VoidDBusMethodCallback callback) override;
+                  chromeos::VoidDBusMethodCallback callback) override;
 };
 
 }  // namespace ash
diff --git a/chromeos/ash/components/dbus/arc/fake_arc_sensor_service_client.cc b/chromeos/ash/components/dbus/arc/fake_arc_sensor_service_client.cc
index f0e17b07..030938f 100644
--- a/chromeos/ash/components/dbus/arc/fake_arc_sensor_service_client.cc
+++ b/chromeos/ash/components/dbus/arc/fake_arc_sensor_service_client.cc
@@ -37,7 +37,7 @@
 void FakeArcSensorServiceClient::BootstrapMojoConnection(
     int fd,
     const std::string& token,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
diff --git a/chromeos/ash/components/dbus/arc/fake_arc_sensor_service_client.h b/chromeos/ash/components/dbus/arc/fake_arc_sensor_service_client.h
index 464894f..332358c 100644
--- a/chromeos/ash/components/dbus/arc/fake_arc_sensor_service_client.h
+++ b/chromeos/ash/components/dbus/arc/fake_arc_sensor_service_client.h
@@ -17,9 +17,10 @@
   static FakeArcSensorServiceClient* Get();
 
   // ArcSensorServiceClient override:
-  void BootstrapMojoConnection(int fd,
-                               const std::string& token,
-                               VoidDBusMethodCallback callback) override;
+  void BootstrapMojoConnection(
+      int fd,
+      const std::string& token,
+      chromeos::VoidDBusMethodCallback callback) override;
 
  protected:
   friend class ArcSensorServiceClient;
diff --git a/chromeos/ash/components/dbus/audio/cras_audio_client.cc b/chromeos/ash/components/dbus/audio/cras_audio_client.cc
index dcdafcc8..c856b61 100644
--- a/chromeos/ash/components/dbus/audio/cras_audio_client.cc
+++ b/chromeos/ash/components/dbus/audio/cras_audio_client.cc
@@ -345,7 +345,7 @@
 
   void SetHotwordModel(uint64_t node_id,
                        const std::string& hotword_model,
-                       VoidDBusMethodCallback callback) override {
+                       chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(cras::kCrasControlInterface,
                                  cras::kSetHotwordModel);
     dbus::MessageWriter writer(&method_call);
@@ -984,7 +984,7 @@
     std::move(callback).Run(deprioritize_bt_wbs_mic);
   }
 
-  void OnSetHotwordModel(VoidDBusMethodCallback callback,
+  void OnSetHotwordModel(chromeos::VoidDBusMethodCallback callback,
                          dbus::Response* response) {
     if (!response) {
       LOG(ERROR) << "Failed to call SetHotwordModel.";
diff --git a/chromeos/ash/components/dbus/audio/cras_audio_client.h b/chromeos/ash/components/dbus/audio/cras_audio_client.h
index ff99c7b..c689049 100644
--- a/chromeos/ash/components/dbus/audio/cras_audio_client.h
+++ b/chromeos/ash/components/dbus/audio/cras_audio_client.h
@@ -173,7 +173,7 @@
   // successfully set.
   virtual void SetHotwordModel(uint64_t node_id,
                                const std::string& hotword_model,
-                               VoidDBusMethodCallback callback) = 0;
+                               chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Enables or disables the usage of fixed A2DP packet size in CRAS.
   virtual void SetFixA2dpPacketSize(bool enabled) = 0;
diff --git a/chromeos/ash/components/dbus/audio/fake_cras_audio_client.cc b/chromeos/ash/components/dbus/audio/fake_cras_audio_client.cc
index 9a9d975..7e1461a 100644
--- a/chromeos/ash/components/dbus/audio/fake_cras_audio_client.cc
+++ b/chromeos/ash/components/dbus/audio/fake_cras_audio_client.cc
@@ -251,9 +251,10 @@
     observer.ActiveInputNodeChanged(node_id);
 }
 
-void FakeCrasAudioClient::SetHotwordModel(uint64_t node_id,
-                                          const std::string& hotword_model,
-                                          VoidDBusMethodCallback callback) {}
+void FakeCrasAudioClient::SetHotwordModel(
+    uint64_t node_id,
+    const std::string& hotword_model,
+    chromeos::VoidDBusMethodCallback callback) {}
 
 void FakeCrasAudioClient::SetFixA2dpPacketSize(bool enabled) {}
 
diff --git a/chromeos/ash/components/dbus/audio/fake_cras_audio_client.h b/chromeos/ash/components/dbus/audio/fake_cras_audio_client.h
index 7f59ff83..b905411 100644
--- a/chromeos/ash/components/dbus/audio/fake_cras_audio_client.h
+++ b/chromeos/ash/components/dbus/audio/fake_cras_audio_client.h
@@ -67,7 +67,7 @@
   void SetActiveInputNode(uint64_t node_id) override;
   void SetHotwordModel(uint64_t node_id,
                        const std::string& hotword_model,
-                       VoidDBusMethodCallback callback) override;
+                       chromeos::VoidDBusMethodCallback callback) override;
   void SetFixA2dpPacketSize(bool enabled) override;
   void SetFlossEnabled(bool enabled) override;
   void AddActiveInputNode(uint64_t node_id) override;
diff --git a/chromeos/ash/components/dbus/biod/biod_client.cc b/chromeos/ash/components/dbus/biod/biod_client.cc
index 1ef20ce7..527b3e7 100644
--- a/chromeos/ash/components/dbus/biod/biod_client.cc
+++ b/chromeos/ash/components/dbus/biod/biod_client.cc
@@ -29,7 +29,8 @@
 BiodClient* g_instance = nullptr;
 
 // D-Bus response handler for methods that use void callbacks.
-void OnVoidResponse(VoidDBusMethodCallback callback, dbus::Response* response) {
+void OnVoidResponse(chromeos::VoidDBusMethodCallback callback,
+                    dbus::Response* response) {
   std::move(callback).Run(response != nullptr);
 }
 
@@ -96,7 +97,7 @@
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
-  void DestroyAllRecords(VoidDBusMethodCallback callback) override {
+  void DestroyAllRecords(chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(
         biod::kBiometricsManagerInterface,
         biod::kBiometricsManagerDestroyAllRecordsMethod);
@@ -138,7 +139,7 @@
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
-  void CancelEnrollSession(VoidDBusMethodCallback callback) override {
+  void CancelEnrollSession(chromeos::VoidDBusMethodCallback callback) override {
     if (!current_enroll_session_path_) {
       std::move(callback).Run(true);
       return;
@@ -154,7 +155,7 @@
     current_enroll_session_path_.reset();
   }
 
-  void EndAuthSession(VoidDBusMethodCallback callback) override {
+  void EndAuthSession(chromeos::VoidDBusMethodCallback callback) override {
     if (!current_auth_session_path_) {
       std::move(callback).Run(true);
       return;
@@ -172,7 +173,7 @@
 
   void SetRecordLabel(const dbus::ObjectPath& record_path,
                       const std::string& label,
-                      VoidDBusMethodCallback callback) override {
+                      chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(biod::kRecordInterface,
                                  biod::kRecordSetLabelMethod);
     dbus::MessageWriter writer(&method_call);
@@ -186,7 +187,7 @@
   }
 
   void RemoveRecord(const dbus::ObjectPath& record_path,
-                    VoidDBusMethodCallback callback) override {
+                    chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(biod::kRecordInterface,
                                  biod::kRecordRemoveMethod);
 
diff --git a/chromeos/ash/components/dbus/biod/biod_client.h b/chromeos/ash/components/dbus/biod/biod_client.h
index 7866417c..6168af0 100644
--- a/chromeos/ash/components/dbus/biod/biod_client.h
+++ b/chromeos/ash/components/dbus/biod/biod_client.h
@@ -115,7 +115,7 @@
 
   // Irreversibly destroys all records registered. |callback| is called
   // asynchronously with the result.
-  virtual void DestroyAllRecords(VoidDBusMethodCallback callback) = 0;
+  virtual void DestroyAllRecords(chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Starts the biometric auth session. |callback| is called with the object
   // path of the auth session after the method succeeds.
@@ -127,23 +127,24 @@
 
   // Cancels the enroll session.
   // |callback| is called asynchronously with the result.
-  virtual void CancelEnrollSession(VoidDBusMethodCallback callback) = 0;
+  virtual void CancelEnrollSession(
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Ends the auth session.
   // |callback| is called asynchronously with the result.
-  virtual void EndAuthSession(VoidDBusMethodCallback callback) = 0;
+  virtual void EndAuthSession(chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Changes the label of the record at |record_path| to |label|. |callback| is
   // called asynchronously with the result.
   virtual void SetRecordLabel(const dbus::ObjectPath& record_path,
                               const std::string& label,
-                              VoidDBusMethodCallback callback) = 0;
+                              chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Removes the record at |record_path|. This record will no longer be able to
   // used for authentication. |callback| is called asynchronously with the
   // result.
   virtual void RemoveRecord(const dbus::ObjectPath& record_path,
-                            VoidDBusMethodCallback callback) = 0;
+                            chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Requests the label of the record at |record_path|. |callback| is called
   // with the label of the record.
diff --git a/chromeos/ash/components/dbus/biod/fake_biod_client.cc b/chromeos/ash/components/dbus/biod/fake_biod_client.cc
index ff918ff..85a06fef7 100644
--- a/chromeos/ash/components/dbus/biod/fake_biod_client.cc
+++ b/chromeos/ash/components/dbus/biod/fake_biod_client.cc
@@ -175,7 +175,8 @@
       FROM_HERE, base::BindOnce(std::move(callback), records_object_paths));
 }
 
-void FakeBiodClient::DestroyAllRecords(VoidDBusMethodCallback callback) {
+void FakeBiodClient::DestroyAllRecords(
+    chromeos::VoidDBusMethodCallback callback) {
   records_.clear();
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -197,7 +198,8 @@
       base::BindOnce(std::move(callback), biod::BIOMETRIC_TYPE_FINGERPRINT));
 }
 
-void FakeBiodClient::CancelEnrollSession(VoidDBusMethodCallback callback) {
+void FakeBiodClient::CancelEnrollSession(
+    chromeos::VoidDBusMethodCallback callback) {
   DCHECK_EQ(current_session_, FingerprintSession::ENROLL);
 
   // Clean up the in progress enrollment.
@@ -209,7 +211,7 @@
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
 
-void FakeBiodClient::EndAuthSession(VoidDBusMethodCallback callback) {
+void FakeBiodClient::EndAuthSession(chromeos::VoidDBusMethodCallback callback) {
   current_session_ = FingerprintSession::NONE;
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
@@ -217,7 +219,7 @@
 
 void FakeBiodClient::SetRecordLabel(const dbus::ObjectPath& record_path,
                                     const std::string& label,
-                                    VoidDBusMethodCallback callback) {
+                                    chromeos::VoidDBusMethodCallback callback) {
   if (records_.find(record_path) != records_.end())
     records_[record_path]->label = label;
 
@@ -226,7 +228,7 @@
 }
 
 void FakeBiodClient::RemoveRecord(const dbus::ObjectPath& record_path,
-                                  VoidDBusMethodCallback callback) {
+                                  chromeos::VoidDBusMethodCallback callback) {
   records_.erase(record_path);
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chromeos/ash/components/dbus/biod/fake_biod_client.h b/chromeos/ash/components/dbus/biod/fake_biod_client.h
index 4996bad..5fb781e 100644
--- a/chromeos/ash/components/dbus/biod/fake_biod_client.h
+++ b/chromeos/ash/components/dbus/biod/fake_biod_client.h
@@ -67,16 +67,16 @@
                           ObjectPathCallback callback) override;
   void GetRecordsForUser(const std::string& user_id,
                          UserRecordsCallback callback) override;
-  void DestroyAllRecords(VoidDBusMethodCallback callback) override;
+  void DestroyAllRecords(chromeos::VoidDBusMethodCallback callback) override;
   void StartAuthSession(ObjectPathCallback callback) override;
   void RequestType(BiometricTypeCallback callback) override;
-  void CancelEnrollSession(VoidDBusMethodCallback callback) override;
-  void EndAuthSession(VoidDBusMethodCallback callback) override;
+  void CancelEnrollSession(chromeos::VoidDBusMethodCallback callback) override;
+  void EndAuthSession(chromeos::VoidDBusMethodCallback callback) override;
   void SetRecordLabel(const dbus::ObjectPath& record_path,
                       const std::string& label,
-                      VoidDBusMethodCallback callback) override;
+                      chromeos::VoidDBusMethodCallback callback) override;
   void RemoveRecord(const dbus::ObjectPath& record_path,
-                    VoidDBusMethodCallback callback) override;
+                    chromeos::VoidDBusMethodCallback callback) override;
   void RequestRecordLabel(const dbus::ObjectPath& record_path,
                           LabelCallback callback) override;
 
diff --git a/chromeos/ash/components/dbus/cros_disks/cros_disks_client.cc b/chromeos/ash/components/dbus/cros_disks/cros_disks_client.cc
index ab66802..06dacc9d 100644
--- a/chromeos/ash/components/dbus/cros_disks/cros_disks_client.cc
+++ b/chromeos/ash/components/dbus/cros_disks/cros_disks_client.cc
@@ -207,7 +207,7 @@
              const std::vector<std::string>& mount_options,
              MountAccessMode access_mode,
              RemountOption remount,
-             VoidDBusMethodCallback callback) override {
+             chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
                                  cros_disks::kMount);
     dbus::MessageWriter writer(&method_call);
@@ -265,7 +265,7 @@
   void Format(const std::string& device_path,
               const std::string& filesystem,
               const std::string& label,
-              VoidDBusMethodCallback callback) override {
+              chromeos::VoidDBusMethodCallback callback) override {
     format_start_time_[device_path] = base::TimeTicks::Now();
     dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
                                  cros_disks::kFormat);
@@ -300,7 +300,7 @@
 
   void Rename(const std::string& device_path,
               const std::string& volume_name,
-              VoidDBusMethodCallback callback) override {
+              chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
                                  cros_disks::kRename);
     dbus::MessageWriter writer(&method_call);
@@ -388,12 +388,13 @@
   };
 
   // Handles the result of D-Bus method call with no return value.
-  void OnVoidMethod(VoidDBusMethodCallback callback, dbus::Response* response) {
+  void OnVoidMethod(chromeos::VoidDBusMethodCallback callback,
+                    dbus::Response* response) {
     std::move(callback).Run(response);
   }
 
   // Handles the result of Mount and calls |callback|.
-  void OnMount(VoidDBusMethodCallback callback,
+  void OnMount(chromeos::VoidDBusMethodCallback callback,
                base::Time start_time,
                dbus::Response* response) {
     UMA_HISTOGRAM_MEDIUM_TIMES("CrosDisksClient.MountTime",
diff --git a/chromeos/ash/components/dbus/cros_disks/cros_disks_client.h b/chromeos/ash/components/dbus/cros_disks/cros_disks_client.h
index 9c0aa636..41b0f665 100644
--- a/chromeos/ash/components/dbus/cros_disks/cros_disks_client.h
+++ b/chromeos/ash/components/dbus/cros_disks/cros_disks_client.h
@@ -389,7 +389,7 @@
                      const std::vector<std::string>& mount_options,
                      MountAccessMode access_mode,
                      RemountOption remount,
-                     VoidDBusMethodCallback callback) = 0;
+                     chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Calls Unmount method.  On method call completion, |callback| is called
   // with the error code.
@@ -411,7 +411,7 @@
   virtual void Format(const std::string& device_path,
                       const std::string& filesystem,
                       const std::string& label,
-                      VoidDBusMethodCallback callback) = 0;
+                      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Calls SinglePartitionFormat async method. |callback| is called when
   // response received.
@@ -422,7 +422,7 @@
   // success, or with |false| otherwise.
   virtual void Rename(const std::string& device_path,
                       const std::string& volume_name,
-                      VoidDBusMethodCallback callback) = 0;
+                      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Calls GetDeviceProperties method.  |callback| is called after the method
   // call succeeds, otherwise, |error_callback| is called.
diff --git a/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.cc b/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.cc
index 21ed3df..035d8868 100644
--- a/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.cc
+++ b/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.cc
@@ -73,7 +73,7 @@
                                 const std::vector<std::string>& mount_options,
                                 MountAccessMode access_mode,
                                 RemountOption remount,
-                                VoidDBusMethodCallback callback) {
+                                chromeos::VoidDBusMethodCallback callback) {
   if (block_mount_) {
     return;
   }
@@ -124,7 +124,7 @@
 void FakeCrosDisksClient::DidMount(const std::string& source_path,
                                    MountType type,
                                    const base::FilePath& mounted_path,
-                                   VoidDBusMethodCallback callback,
+                                   chromeos::VoidDBusMethodCallback callback,
                                    MountError mount_error) {
   // Tell the caller of Mount() that the mount request was accepted.
   // Note that even if PerformFakeMount fails, this calls with |true| to
@@ -172,7 +172,7 @@
 void FakeCrosDisksClient::Format(const std::string& device_path,
                                  const std::string& filesystem,
                                  const std::string& label,
-                                 VoidDBusMethodCallback callback) {
+                                 chromeos::VoidDBusMethodCallback callback) {
   DCHECK(!callback.is_null());
 
   format_call_count_++;
@@ -195,7 +195,7 @@
 
 void FakeCrosDisksClient::Rename(const std::string& device_path,
                                  const std::string& volume_name,
-                                 VoidDBusMethodCallback callback) {
+                                 chromeos::VoidDBusMethodCallback callback) {
   DCHECK(!callback.is_null());
 
   rename_call_count_++;
diff --git a/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.h b/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.h
index a92cea0d4..0722ed8 100644
--- a/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.h
+++ b/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.h
@@ -46,7 +46,7 @@
              const std::vector<std::string>& mount_options,
              MountAccessMode access_mode,
              RemountOption remount,
-             VoidDBusMethodCallback callback) override;
+             chromeos::VoidDBusMethodCallback callback) override;
 
   // Deletes the directory created in Mount().
   void Unmount(const std::string& device_path,
@@ -58,12 +58,12 @@
   void Format(const std::string& device_path,
               const std::string& filesystem,
               const std::string& label,
-              VoidDBusMethodCallback callback) override;
+              chromeos::VoidDBusMethodCallback callback) override;
   void SinglePartitionFormat(const std::string& device_path,
                              PartitionCallback callback) override;
   void Rename(const std::string& device_path,
               const std::string& volume_name,
-              VoidDBusMethodCallback callback) override;
+              chromeos::VoidDBusMethodCallback callback) override;
   void GetDeviceProperties(const std::string& device_path,
                            GetDevicePropertiesCallback callback,
                            base::OnceClosure error_callback) override;
@@ -171,7 +171,7 @@
   void DidMount(const std::string& source_path,
                 MountType type,
                 const base::FilePath& mounted_path,
-                VoidDBusMethodCallback callback,
+                chromeos::VoidDBusMethodCallback callback,
                 MountError mount_error);
 
   base::ObserverList<Observer> observer_list_;
diff --git a/chromeos/ash/components/dbus/debug_daemon/debug_daemon_client.cc b/chromeos/ash/components/dbus/debug_daemon/debug_daemon_client.cc
index 2f66b3a..525fcfe5 100644
--- a/chromeos/ash/components/dbus/debug_daemon/debug_daemon_client.cc
+++ b/chromeos/ash/components/dbus/debug_daemon/debug_daemon_client.cc
@@ -149,7 +149,7 @@
   // DebugDaemonClient override.
   void DumpDebugLogs(bool is_compressed,
                      int file_descriptor,
-                     VoidDBusMethodCallback callback) override {
+                     chromeos::VoidDBusMethodCallback callback) override {
     // Issue the dbus request to get debug logs.
     dbus::MethodCall method_call(debugd::kDebugdInterface,
                                  debugd::kDumpDebugLogs);
@@ -163,7 +163,7 @@
   }
 
   void SetDebugMode(const std::string& subsystem,
-                    VoidDBusMethodCallback callback) override {
+                    chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(debugd::kDebugdInterface,
                                  debugd::kSetDebugMode);
     dbus::MessageWriter writer(&method_call);
@@ -241,7 +241,8 @@
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
-  void StopPerf(uint64_t session_id, VoidDBusMethodCallback callback) override {
+  void StopPerf(uint64_t session_id,
+                chromeos::VoidDBusMethodCallback callback) override {
     DCHECK(session_id);
     dbus::MethodCall method_call(debugd::kDebugdInterface, debugd::kStopPerf);
     dbus::MessageWriter writer(&method_call);
@@ -278,7 +279,7 @@
   }
 
   void BackupArcBugReport(const cryptohome::AccountIdentifier& id,
-                          VoidDBusMethodCallback callback) override {
+                          chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(debugd::kDebugdInterface,
                                  debugd::kBackupArcBugReport);
     dbus::MessageWriter writer(&method_call);
@@ -606,7 +607,7 @@
   }
 
   void SetU2fFlags(const std::set<std::string>& flags,
-                   VoidDBusMethodCallback callback) override {
+                   chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(debugd::kDebugdInterface,
                                  debugd::kSetU2fFlags);
     dbus::MessageWriter writer(&method_call);
@@ -826,7 +827,8 @@
 
   // Called when D-Bus method call which does not return the result is
   // completed or on its error.
-  void OnVoidMethod(VoidDBusMethodCallback callback, dbus::Response* response) {
+  void OnVoidMethod(chromeos::VoidDBusMethodCallback callback,
+                    dbus::Response* response) {
     std::move(callback).Run(response);
   }
 
diff --git a/chromeos/ash/components/dbus/debug_daemon/debug_daemon_client.h b/chromeos/ash/components/dbus/debug_daemon/debug_daemon_client.h
index 18cc982..13cd20b 100644
--- a/chromeos/ash/components/dbus/debug_daemon/debug_daemon_client.h
+++ b/chromeos/ash/components/dbus/debug_daemon/debug_daemon_client.h
@@ -85,13 +85,13 @@
   // waiting for the result.
   virtual void DumpDebugLogs(bool is_compressed,
                              int file_descriptor,
-                             VoidDBusMethodCallback callback) = 0;
+                             chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Requests to change debug mode to given |subsystem| and calls
   // |callback| when completed. |subsystem| should be one of the
   // following: "wifi", "ethernet", "cellular" or "none".
   virtual void SetDebugMode(const std::string& subsystem,
-                            VoidDBusMethodCallback callback) = 0;
+                            chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Gets information about routes.
   virtual void GetRoutes(
@@ -130,7 +130,7 @@
   // profiling data right away. If the profiler session as identified by
   // |session_id| has ended, this method will silently succeed.
   virtual void StopPerf(uint64_t session_id,
-                        VoidDBusMethodCallback callback) = 0;
+                        chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Callback type for GetAllLogs()
   using GetLogsCallback =
@@ -151,8 +151,9 @@
   // If backup operation fails, an error is logged.
   // |id|: Cryptohome Account identifier for the user to get
   // logs for.
-  virtual void BackupArcBugReport(const cryptohome::AccountIdentifier& id,
-                                  VoidDBusMethodCallback callback) = 0;
+  virtual void BackupArcBugReport(
+      const cryptohome::AccountIdentifier& id,
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Gets all logs collected by debugd.
   virtual void GetAllLogs(GetLogsCallback callback) = 0;
@@ -310,7 +311,7 @@
 
   // Set U2F flags.
   virtual void SetU2fFlags(const std::set<std::string>& flags,
-                           VoidDBusMethodCallback callback) = 0;
+                           chromeos::VoidDBusMethodCallback callback) = 0;
   // Get U2F flags.
   virtual void GetU2fFlags(
       chromeos::DBusMethodCallback<std::set<std::string>> callback) = 0;
diff --git a/chromeos/ash/components/dbus/debug_daemon/fake_debug_daemon_client.cc b/chromeos/ash/components/dbus/debug_daemon/fake_debug_daemon_client.cc
index b85796b..3767a32 100644
--- a/chromeos/ash/components/dbus/debug_daemon/fake_debug_daemon_client.cc
+++ b/chromeos/ash/components/dbus/debug_daemon/fake_debug_daemon_client.cc
@@ -40,14 +40,16 @@
 
 void FakeDebugDaemonClient::Init(dbus::Bus* bus) {}
 
-void FakeDebugDaemonClient::DumpDebugLogs(bool is_compressed,
-                                          int file_descriptor,
-                                          VoidDBusMethodCallback callback) {
+void FakeDebugDaemonClient::DumpDebugLogs(
+    bool is_compressed,
+    int file_descriptor,
+    chromeos::VoidDBusMethodCallback callback) {
   std::move(callback).Run(true);
 }
 
-void FakeDebugDaemonClient::SetDebugMode(const std::string& subsystem,
-                                         VoidDBusMethodCallback callback) {
+void FakeDebugDaemonClient::SetDebugMode(
+    const std::string& subsystem,
+    chromeos::VoidDBusMethodCallback callback) {
   std::move(callback).Run(false);
 }
 
@@ -147,8 +149,9 @@
     int file_descriptor,
     chromeos::DBusMethodCallback<uint64_t> error_callback) {}
 
-void FakeDebugDaemonClient::StopPerf(uint64_t session_id,
-                                     VoidDBusMethodCallback callback) {}
+void FakeDebugDaemonClient::StopPerf(
+    uint64_t session_id,
+    chromeos::VoidDBusMethodCallback callback) {}
 
 void FakeDebugDaemonClient::GetScrubbedBigLogs(
     const cryptohome::AccountIdentifier& id,
@@ -161,7 +164,7 @@
 
 void FakeDebugDaemonClient::BackupArcBugReport(
     const cryptohome::AccountIdentifier& id,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
@@ -319,8 +322,9 @@
       base::BindOnce(std::move(callback), true, /*num_cores_disabled=*/0));
 }
 
-void FakeDebugDaemonClient::SetU2fFlags(const std::set<std::string>& flags,
-                                        VoidDBusMethodCallback callback) {
+void FakeDebugDaemonClient::SetU2fFlags(
+    const std::set<std::string>& flags,
+    chromeos::VoidDBusMethodCallback callback) {
   u2f_flags_ = flags;
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
diff --git a/chromeos/ash/components/dbus/debug_daemon/fake_debug_daemon_client.h b/chromeos/ash/components/dbus/debug_daemon/fake_debug_daemon_client.h
index a79aa1429..f1299fd 100644
--- a/chromeos/ash/components/dbus/debug_daemon/fake_debug_daemon_client.h
+++ b/chromeos/ash/components/dbus/debug_daemon/fake_debug_daemon_client.h
@@ -35,9 +35,9 @@
   void Init(dbus::Bus* bus) override;
   void DumpDebugLogs(bool is_compressed,
                      int file_descriptor,
-                     VoidDBusMethodCallback callback) override;
+                     chromeos::VoidDBusMethodCallback callback) override;
   void SetDebugMode(const std::string& subsystem,
-                    VoidDBusMethodCallback callback) override;
+                    chromeos::VoidDBusMethodCallback callback) override;
   std::string GetTracingAgentName() override;
   std::string GetTraceEventLabel() override;
   void SetSwapParameter(
@@ -78,11 +78,12 @@
                      bool disable_cpu_idle,
                      int file_descriptor,
                      chromeos::DBusMethodCallback<uint64_t> callback) override;
-  void StopPerf(uint64_t session_id, VoidDBusMethodCallback callback) override;
+  void StopPerf(uint64_t session_id,
+                chromeos::VoidDBusMethodCallback callback) override;
   void GetScrubbedBigLogs(const cryptohome::AccountIdentifier& id,
                           GetLogsCallback callback) override;
   void BackupArcBugReport(const cryptohome::AccountIdentifier& id,
-                          VoidDBusMethodCallback callback) override;
+                          chromeos::VoidDBusMethodCallback callback) override;
   void GetAllLogs(GetLogsCallback callback) override;
   void GetLog(const std::string& log_name,
               chromeos::DBusMethodCallback<std::string> callback) override;
@@ -121,7 +122,7 @@
       bool lock_policy,
       SetSchedulerConfigurationV2Callback callback) override;
   void SetU2fFlags(const std::set<std::string>& flags,
-                   VoidDBusMethodCallback callback) override;
+                   chromeos::VoidDBusMethodCallback callback) override;
   void GetU2fFlags(
       chromeos::DBusMethodCallback<std::set<std::string>> callback) override;
 
diff --git a/chromeos/ash/components/dbus/hiberman/hiberman_client.cc b/chromeos/ash/components/dbus/hiberman/hiberman_client.cc
index 764d248b..711e16c1 100644
--- a/chromeos/ash/components/dbus/hiberman/hiberman_client.cc
+++ b/chromeos/ash/components/dbus/hiberman/hiberman_client.cc
@@ -86,7 +86,7 @@
   }
 
  private:
-  void HandleResponse(VoidDBusMethodCallback callback,
+  void HandleResponse(chromeos::VoidDBusMethodCallback callback,
                       dbus::Response* response) {
     std::move(callback).Run(response != nullptr);
   }
diff --git a/chromeos/ash/components/dbus/hiberman/hiberman_client.h b/chromeos/ash/components/dbus/hiberman/hiberman_client.h
index 4717890..0c277d1 100644
--- a/chromeos/ash/components/dbus/hiberman/hiberman_client.h
+++ b/chromeos/ash/components/dbus/hiberman/hiberman_client.h
@@ -21,7 +21,7 @@
 // thread (UI thread) which initializes the DBusThreadManager instance.
 class COMPONENT_EXPORT(HIBERMAN_CLIENT) HibermanClient {
  public:
-  using ResumeFromHibernateCallback = VoidDBusMethodCallback;
+  using ResumeFromHibernateCallback = chromeos::VoidDBusMethodCallback;
 
   // Not copyable or movable.
   HibermanClient(const HibermanClient&) = delete;
diff --git a/chromeos/ash/components/dbus/lorgnette_manager/fake_lorgnette_manager_client.cc b/chromeos/ash/components/dbus/lorgnette_manager/fake_lorgnette_manager_client.cc
index 8c27f1b..6747f77c 100644
--- a/chromeos/ash/components/dbus/lorgnette_manager/fake_lorgnette_manager_client.cc
+++ b/chromeos/ash/components/dbus/lorgnette_manager/fake_lorgnette_manager_client.cc
@@ -64,7 +64,7 @@
 }
 
 void FakeLorgnetteManagerClient::CancelScan(
-    VoidDBusMethodCallback completion_callback) {
+    chromeos::VoidDBusMethodCallback completion_callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(completion_callback), true));
 }
diff --git a/chromeos/ash/components/dbus/lorgnette_manager/fake_lorgnette_manager_client.h b/chromeos/ash/components/dbus/lorgnette_manager/fake_lorgnette_manager_client.h
index 3bfd4a9..59509888 100644
--- a/chromeos/ash/components/dbus/lorgnette_manager/fake_lorgnette_manager_client.h
+++ b/chromeos/ash/components/dbus/lorgnette_manager/fake_lorgnette_manager_client.h
@@ -41,7 +41,8 @@
       base::RepeatingCallback<void(std::string, uint32_t)> page_callback,
       base::RepeatingCallback<void(uint32_t, uint32_t)> progress_callback)
       override;
-  void CancelScan(VoidDBusMethodCallback completion_callback) override;
+  void CancelScan(
+      chromeos::VoidDBusMethodCallback completion_callback) override;
 
   // Sets the response returned by ListScanners().
   void SetListScannersResponse(
diff --git a/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client.cc b/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client.cc
index 7164efe..d6d7b1c7 100644
--- a/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client.cc
+++ b/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client.cc
@@ -102,7 +102,7 @@
                        weak_ptr_factory_.GetWeakPtr(), std::move(state)));
   }
 
-  void CancelScan(VoidDBusMethodCallback cancel_callback) override {
+  void CancelScan(chromeos::VoidDBusMethodCallback cancel_callback) override {
     // Post the task to the proper sequence (since it requires access to
     // scan_job_state_).
     base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -200,7 +200,7 @@
     base::OnceCallback<void(lorgnette::ScanFailureMode)> completion_callback;
     base::RepeatingCallback<void(uint32_t, uint32_t)> progress_callback;
     base::RepeatingCallback<void(std::string, uint32_t)> page_callback;
-    VoidDBusMethodCallback cancel_callback;
+    chromeos::VoidDBusMethodCallback cancel_callback;
     std::unique_ptr<ScanDataReader> scan_data_reader;
   };
 
@@ -241,7 +241,7 @@
   // Helper method to actually perform scan cancellation.
   // We use this method since the scan cancel logic requires that we are running
   // on the proper sequence.
-  void DoScanCancel(VoidDBusMethodCallback cancel_callback) {
+  void DoScanCancel(chromeos::VoidDBusMethodCallback cancel_callback) {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     if (scan_job_state_.size() == 0) {
       LOG(ERROR) << "No active scan job to cancel.";
diff --git a/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client.h b/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client.h
index 463b7cb4..304c8c1 100644
--- a/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client.h
+++ b/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client.h
@@ -81,7 +81,7 @@
   //
   // This function makes the assumption that LorgnetteManagerClient only has one
   // scan running at a time.
-  virtual void CancelScan(VoidDBusMethodCallback cancel_callback) = 0;
+  virtual void CancelScan(chromeos::VoidDBusMethodCallback cancel_callback) = 0;
 
  protected:
   friend class LorgnetteManagerClientTest;
diff --git a/chromeos/ash/components/dbus/media_analytics/fake_media_analytics_client.cc b/chromeos/ash/components/dbus/media_analytics/fake_media_analytics_client.cc
index 4dacbc9..e496838 100644
--- a/chromeos/ash/components/dbus/media_analytics/fake_media_analytics_client.cc
+++ b/chromeos/ash/components/dbus/media_analytics/fake_media_analytics_client.cc
@@ -120,7 +120,7 @@
 
 void FakeMediaAnalyticsClient::BootstrapMojoConnection(
     base::ScopedFD file_descriptor,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   // Fake that the mojo connection has been successfully established.
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
diff --git a/chromeos/ash/components/dbus/media_analytics/fake_media_analytics_client.h b/chromeos/ash/components/dbus/media_analytics/fake_media_analytics_client.h
index 984c9c1..2960a5d 100644
--- a/chromeos/ash/components/dbus/media_analytics/fake_media_analytics_client.h
+++ b/chromeos/ash/components/dbus/media_analytics/fake_media_analytics_client.h
@@ -38,8 +38,9 @@
                 chromeos::DBusMethodCallback<mri::State> callback) override;
   void GetDiagnostics(
       chromeos::DBusMethodCallback<mri::Diagnostics> callback) override;
-  void BootstrapMojoConnection(base::ScopedFD file_descriptor,
-                               VoidDBusMethodCallback callback) override;
+  void BootstrapMojoConnection(
+      base::ScopedFD file_descriptor,
+      chromeos::VoidDBusMethodCallback callback) override;
 
   // Fires a fake media perception event.
   bool FireMediaPerceptionEvent(const mri::MediaPerception& media_perception);
diff --git a/chromeos/ash/components/dbus/media_analytics/media_analytics_client.cc b/chromeos/ash/components/dbus/media_analytics/media_analytics_client.cc
index 7ac6e846..a111d35e 100644
--- a/chromeos/ash/components/dbus/media_analytics/media_analytics_client.cc
+++ b/chromeos/ash/components/dbus/media_analytics/media_analytics_client.cc
@@ -81,8 +81,9 @@
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
-  void BootstrapMojoConnection(base::ScopedFD file_descriptor,
-                               VoidDBusMethodCallback callback) override {
+  void BootstrapMojoConnection(
+      base::ScopedFD file_descriptor,
+      chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(media_perception::kMediaPerceptionServiceName,
                                  media_perception::kBootstrapMojoConnection);
     dbus::MessageWriter writer(&method_call);
@@ -111,8 +112,9 @@
   }
 
  private:
-  void OnBootstrapMojoConnectionCallback(VoidDBusMethodCallback callback,
-                                         dbus::Response* response) {
+  void OnBootstrapMojoConnectionCallback(
+      chromeos::VoidDBusMethodCallback callback,
+      dbus::Response* response) {
     std::move(callback).Run(response != nullptr);
   }
 
diff --git a/chromeos/ash/components/dbus/media_analytics/media_analytics_client.h b/chromeos/ash/components/dbus/media_analytics/media_analytics_client.h
index 0ba0aae..37552acf 100644
--- a/chromeos/ash/components/dbus/media_analytics/media_analytics_client.h
+++ b/chromeos/ash/components/dbus/media_analytics/media_analytics_client.h
@@ -66,8 +66,9 @@
   // Bootstrap the Mojo connection between Chrome and the media analytics
   // process. Should pass in the file descriptor for the child end of the Mojo
   // pipe.
-  virtual void BootstrapMojoConnection(base::ScopedFD file_descriptor,
-                                       VoidDBusMethodCallback callback) = 0;
+  virtual void BootstrapMojoConnection(
+      base::ScopedFD file_descriptor,
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Factory function, creates new instance and returns ownership.
   // For normal usage, access the singleton via DbusThreadManager::Get().
diff --git a/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc b/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc
index 6061b8c..fd69700 100644
--- a/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc
+++ b/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc
@@ -288,10 +288,11 @@
 
 void FakeSessionManagerClient::EmitAshInitialized() {}
 
-void FakeSessionManagerClient::RestartJob(int socket_fd,
-                                          const std::vector<std::string>& argv,
-                                          RestartJobReason reason,
-                                          VoidDBusMethodCallback callback) {
+void FakeSessionManagerClient::RestartJob(
+    int socket_fd,
+    const std::vector<std::string>& argv,
+    RestartJobReason reason,
+    chromeos::VoidDBusMethodCallback callback) {
   DCHECK(supports_browser_restart_);
 
   restart_job_argv_ = argv;
@@ -380,25 +381,25 @@
 }
 
 void FakeSessionManagerClient::ClearForcedReEnrollmentVpd(
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   clear_forced_re_enrollment_vpd_call_count_++;
   PostReply(FROM_HERE, std::move(callback), true);
 }
 
 void FakeSessionManagerClient::UnblockDevModeForEnrollment(
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   unblock_dev_mode_enrollment_call_count_++;
   PostReply(FROM_HERE, std::move(callback), true);
 }
 
 void FakeSessionManagerClient::UnblockDevModeForInitialStateDetermination(
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   unblock_dev_mode_init_state_call_count_++;
   PostReply(FROM_HERE, std::move(callback), true);
 }
 
 void FakeSessionManagerClient::UnblockDevModeForCarrierLock(
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   unblock_dev_mode_carrier_lock_call_count_++;
   PostReply(FROM_HERE, std::move(callback), true);
 }
@@ -535,7 +536,7 @@
 
 void FakeSessionManagerClient::StoreDevicePolicy(
     const std::string& policy_blob,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
       login_manager::ACCOUNT_TYPE_DEVICE, kEmptyAccountId);
   StorePolicy(descriptor, policy_blob, std::move(callback));
@@ -544,7 +545,7 @@
 void FakeSessionManagerClient::StorePolicyForUser(
     const cryptohome::AccountIdentifier& cryptohome_id,
     const std::string& policy_blob,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
       login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id());
   StorePolicy(descriptor, policy_blob, std::move(callback));
@@ -553,7 +554,7 @@
 void FakeSessionManagerClient::StoreDeviceLocalAccountPolicy(
     const std::string& account_id,
     const std::string& policy_blob,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
       login_manager::ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT, account_id);
   StorePolicy(descriptor, policy_blob, std::move(callback));
@@ -562,7 +563,7 @@
 void FakeSessionManagerClient::StorePolicy(
     const login_manager::PolicyDescriptor& descriptor,
     const std::string& policy_blob,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   // Decode the blob to get the new key.
   enterprise_management::PolicyFetchResponse response;
   if (!response.ParseFromString(policy_blob)) {
@@ -685,7 +686,7 @@
 
 void FakeSessionManagerClient::StartArcMiniContainer(
     const login_manager::StartArcMiniContainerRequest& request,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   last_start_arc_mini_container_request_ = request;
 
   if (!arc_available_) {
@@ -699,7 +700,7 @@
 
 void FakeSessionManagerClient::UpgradeArcContainer(
     const login_manager::UpgradeArcContainerRequest& request,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   last_upgrade_arc_request_ = request;
 
   PostReply(FROM_HERE, std::move(callback), !force_upgrade_failure_);
@@ -716,7 +717,7 @@
 void FakeSessionManagerClient::StopArcInstance(
     const std::string& account_id,
     bool should_backup_log,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   if (!arc_available_ || !container_running_) {
     PostReply(FROM_HERE, std::move(callback), false /* result */);
     return;
@@ -735,13 +736,13 @@
 
 void FakeSessionManagerClient::SetArcCpuRestriction(
     login_manager::ContainerCpuRestrictionState restriction_state,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   PostReply(FROM_HERE, std::move(callback), arc_available_);
 }
 
 void FakeSessionManagerClient::EmitArcBooted(
     const cryptohome::AccountIdentifier& cryptohome_id,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   PostReply(FROM_HERE, std::move(callback), arc_available_);
 }
 
diff --git a/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h b/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h
index 0271604..d548a44 100644
--- a/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h
+++ b/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h
@@ -75,7 +75,7 @@
   void RestartJob(int socket_fd,
                   const std::vector<std::string>& argv,
                   RestartJobReason reason,
-                  VoidDBusMethodCallback callback) override;
+                  chromeos::VoidDBusMethodCallback callback) override;
   void SaveLoginPassword(const std::string& password) override;
 
   void LoginScreenStorageStore(
@@ -98,11 +98,14 @@
   void StartDeviceWipe() override;
   void StartRemoteDeviceWipe(
       const enterprise_management::SignedData& signed_command) override;
-  void ClearForcedReEnrollmentVpd(VoidDBusMethodCallback callback) override;
-  void UnblockDevModeForEnrollment(VoidDBusMethodCallback callback) override;
+  void ClearForcedReEnrollmentVpd(
+      chromeos::VoidDBusMethodCallback callback) override;
+  void UnblockDevModeForEnrollment(
+      chromeos::VoidDBusMethodCallback callback) override;
   void UnblockDevModeForInitialStateDetermination(
-      VoidDBusMethodCallback callback) override;
-  void UnblockDevModeForCarrierLock(VoidDBusMethodCallback callback) override;
+      chromeos::VoidDBusMethodCallback callback) override;
+  void UnblockDevModeForCarrierLock(
+      chromeos::VoidDBusMethodCallback callback) override;
   void StartTPMFirmwareUpdate(const std::string& update_mode) override;
   void RequestLockScreen() override;
   void NotifyLockScreenShown() override;
@@ -131,16 +134,17 @@
       const login_manager::PolicyDescriptor& descriptor,
       std::string* policy_out) override;
   void StoreDevicePolicy(const std::string& policy_blob,
-                         VoidDBusMethodCallback callback) override;
+                         chromeos::VoidDBusMethodCallback callback) override;
   void StorePolicyForUser(const cryptohome::AccountIdentifier& cryptohome_id,
                           const std::string& policy_blob,
-                          VoidDBusMethodCallback callback) override;
-  void StoreDeviceLocalAccountPolicy(const std::string& account_id,
-                                     const std::string& policy_blob,
-                                     VoidDBusMethodCallback callback) override;
+                          chromeos::VoidDBusMethodCallback callback) override;
+  void StoreDeviceLocalAccountPolicy(
+      const std::string& account_id,
+      const std::string& policy_blob,
+      chromeos::VoidDBusMethodCallback callback) override;
   void StorePolicy(const login_manager::PolicyDescriptor& descriptor,
                    const std::string& policy_blob,
-                   VoidDBusMethodCallback callback) override;
+                   chromeos::VoidDBusMethodCallback callback) override;
   bool SupportsBrowserRestart() const override;
   void SetFlagsForUser(const cryptohome::AccountIdentifier& cryptohome_id,
                        const std::vector<std::string>& flags) override;
@@ -154,18 +158,18 @@
 
   void StartArcMiniContainer(
       const login_manager::StartArcMiniContainerRequest& request,
-      VoidDBusMethodCallback callback) override;
+      chromeos::VoidDBusMethodCallback callback) override;
   void UpgradeArcContainer(
       const login_manager::UpgradeArcContainerRequest& request,
-      VoidDBusMethodCallback callback) override;
+      chromeos::VoidDBusMethodCallback callback) override;
   void StopArcInstance(const std::string& account_id,
                        bool should_backup_log,
-                       VoidDBusMethodCallback callback) override;
+                       chromeos::VoidDBusMethodCallback callback) override;
   void SetArcCpuRestriction(
       login_manager::ContainerCpuRestrictionState restriction_state,
-      VoidDBusMethodCallback callback) override;
+      chromeos::VoidDBusMethodCallback callback) override;
   void EmitArcBooted(const cryptohome::AccountIdentifier& cryptohome_id,
-                     VoidDBusMethodCallback callback) override;
+                     chromeos::VoidDBusMethodCallback callback) override;
   void GetArcStartTime(
       chromeos::DBusMethodCallback<base::TimeTicks> callback) override;
   void EnableAdbSideload(EnableAdbSideloadCallback callback) override;
diff --git a/chromeos/ash/components/dbus/session_manager/session_manager_client.cc b/chromeos/ash/components/dbus/session_manager/session_manager_client.cc
index 0ba0d54..f3fcdb3 100644
--- a/chromeos/ash/components/dbus/session_manager/session_manager_client.cc
+++ b/chromeos/ash/components/dbus/session_manager/session_manager_client.cc
@@ -216,7 +216,7 @@
   void RestartJob(int socket_fd,
                   const std::vector<std::string>& argv,
                   RestartJobReason reason,
-                  VoidDBusMethodCallback callback) override {
+                  chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
                                  login_manager::kSessionManagerRestartJob);
     dbus::MessageWriter writer(&method_call);
@@ -367,7 +367,8 @@
                                        base::DoNothing());
   }
 
-  void ClearForcedReEnrollmentVpd(VoidDBusMethodCallback callback) override {
+  void ClearForcedReEnrollmentVpd(
+      chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(
         login_manager::kSessionManagerInterface,
         login_manager::kSessionManagerClearForcedReEnrollmentVpd);
@@ -378,7 +379,8 @@
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
-  void UnblockDevModeForEnrollment(VoidDBusMethodCallback callback) override {
+  void UnblockDevModeForEnrollment(
+      chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(
         login_manager::kSessionManagerInterface,
         login_manager::kSessionManagerUnblockDevModeForEnrollment);
@@ -389,7 +391,8 @@
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
-  void UnblockDevModeForCarrierLock(VoidDBusMethodCallback callback) override {
+  void UnblockDevModeForCarrierLock(
+      chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(
         login_manager::kSessionManagerInterface,
         login_manager::kSessionManagerUnblockDevModeForCarrierLock);
@@ -401,7 +404,7 @@
   }
 
   void UnblockDevModeForInitialStateDetermination(
-      VoidDBusMethodCallback callback) override {
+      chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(
         login_manager::kSessionManagerInterface,
         login_manager::
@@ -532,7 +535,7 @@
   }
 
   void StoreDevicePolicy(const std::string& policy_blob,
-                         VoidDBusMethodCallback callback) override {
+                         chromeos::VoidDBusMethodCallback callback) override {
     login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
         login_manager::ACCOUNT_TYPE_DEVICE, kEmptyAccountId);
     CallStorePolicy(descriptor, policy_blob, std::move(callback));
@@ -540,15 +543,16 @@
 
   void StorePolicyForUser(const cryptohome::AccountIdentifier& cryptohome_id,
                           const std::string& policy_blob,
-                          VoidDBusMethodCallback callback) override {
+                          chromeos::VoidDBusMethodCallback callback) override {
     login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
         login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id());
     CallStorePolicy(descriptor, policy_blob, std::move(callback));
   }
 
-  void StoreDeviceLocalAccountPolicy(const std::string& account_name,
-                                     const std::string& policy_blob,
-                                     VoidDBusMethodCallback callback) override {
+  void StoreDeviceLocalAccountPolicy(
+      const std::string& account_name,
+      const std::string& policy_blob,
+      chromeos::VoidDBusMethodCallback callback) override {
     login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
         login_manager::ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT, account_name);
     CallStorePolicy(descriptor, policy_blob, std::move(callback));
@@ -556,7 +560,7 @@
 
   void StorePolicy(const login_manager::PolicyDescriptor& descriptor,
                    const std::string& policy_blob,
-                   VoidDBusMethodCallback callback) override {
+                   chromeos::VoidDBusMethodCallback callback) override {
     CallStorePolicy(descriptor, policy_blob, std::move(callback));
   }
 
@@ -632,7 +636,7 @@
 
   void StartArcMiniContainer(
       const login_manager::StartArcMiniContainerRequest& request,
-      VoidDBusMethodCallback callback) override {
+      chromeos::VoidDBusMethodCallback callback) override {
     DCHECK(!callback.is_null());
     dbus::MethodCall method_call(
         login_manager::kSessionManagerInterface,
@@ -649,7 +653,7 @@
 
   void UpgradeArcContainer(
       const login_manager::UpgradeArcContainerRequest& request,
-      VoidDBusMethodCallback callback) override {
+      chromeos::VoidDBusMethodCallback callback) override {
     DCHECK(!callback.is_null());
     dbus::MethodCall method_call(
         login_manager::kSessionManagerInterface,
@@ -666,7 +670,7 @@
 
   void StopArcInstance(const std::string& account_id,
                        bool should_backup_log,
-                       VoidDBusMethodCallback callback) override {
+                       chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
                                  login_manager::kSessionManagerStopArcInstance);
 
@@ -682,7 +686,7 @@
 
   void SetArcCpuRestriction(
       login_manager::ContainerCpuRestrictionState restriction_state,
-      VoidDBusMethodCallback callback) override {
+      chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(
         login_manager::kSessionManagerInterface,
         login_manager::kSessionManagerSetArcCpuRestriction);
@@ -695,7 +699,7 @@
   }
 
   void EmitArcBooted(const cryptohome::AccountIdentifier& cryptohome_id,
-                     VoidDBusMethodCallback callback) override {
+                     chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
                                  login_manager::kSessionManagerEmitArcBooted);
     dbus::MessageWriter writer(&method_call);
@@ -799,7 +803,8 @@
   }
 
   // Called when the method call without result is completed.
-  void OnVoidMethod(VoidDBusMethodCallback callback, dbus::Response* response) {
+  void OnVoidMethod(chromeos::VoidDBusMethodCallback callback,
+                    dbus::Response* response) {
     std::move(callback).Run(response);
   }
 
@@ -854,7 +859,7 @@
 
   void CallStorePolicy(const login_manager::PolicyDescriptor& descriptor,
                        const std::string& policy_blob,
-                       VoidDBusMethodCallback callback) {
+                       chromeos::VoidDBusMethodCallback callback) {
     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
                                  login_manager::kSessionManagerStorePolicyEx);
     dbus::MessageWriter writer(&method_call);
diff --git a/chromeos/ash/components/dbus/session_manager/session_manager_client.h b/chromeos/ash/components/dbus/session_manager/session_manager_client.h
index 368dded5..5c3ca61 100644
--- a/chromeos/ash/components/dbus/session_manager/session_manager_client.h
+++ b/chromeos/ash/components/dbus/session_manager/session_manager_client.h
@@ -170,7 +170,7 @@
   virtual void RestartJob(int socket_fd,
                           const std::vector<std::string>& argv,
                           RestartJobReason reason,
-                          VoidDBusMethodCallback callback) = 0;
+                          chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Sends the user's password to the session manager.
   virtual void SaveLoginPassword(const std::string& password) = 0;
@@ -238,15 +238,17 @@
       const enterprise_management::SignedData& signed_command) = 0;
 
   // Set the block_demode and check_enrollment flags to 0 in the VPD.
-  virtual void ClearForcedReEnrollmentVpd(VoidDBusMethodCallback callback) = 0;
+  virtual void ClearForcedReEnrollmentVpd(
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
-  virtual void UnblockDevModeForEnrollment(VoidDBusMethodCallback callback) = 0;
+  virtual void UnblockDevModeForEnrollment(
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   virtual void UnblockDevModeForInitialStateDetermination(
-      VoidDBusMethodCallback callback) = 0;
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   virtual void UnblockDevModeForCarrierLock(
-      VoidDBusMethodCallback callback) = 0;
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Triggers a TPM firmware update.
   virtual void StartTPMFirmwareUpdate(const std::string& update_mode) = 0;
@@ -373,7 +375,7 @@
   // Attempts to asynchronously store |policy_blob| as device policy.  Upon
   // completion of the store attempt, we will call callback.
   virtual void StoreDevicePolicy(const std::string& policy_blob,
-                                 VoidDBusMethodCallback callback) = 0;
+                                 chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Attempts to asynchronously store |policy_blob| as user policy for the
   // given |cryptohome_id|. Upon completion of the store attempt, we will call
@@ -381,21 +383,21 @@
   virtual void StorePolicyForUser(
       const cryptohome::AccountIdentifier& cryptohome_id,
       const std::string& policy_blob,
-      VoidDBusMethodCallback callback) = 0;
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Sends a request to store a policy blob for the specified device-local
   // account. The result of the operation is reported through |callback|.
   virtual void StoreDeviceLocalAccountPolicy(
       const std::string& account_id,
       const std::string& policy_blob,
-      VoidDBusMethodCallback callback) = 0;
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Sends a request to store a |policy_blob| to Session Manager. The storage
   // location is determined by |descriptor|. The result of the operation is
   // reported through |callback|.
   virtual void StorePolicy(const login_manager::PolicyDescriptor& descriptor,
                            const std::string& policy_blob,
-                           VoidDBusMethodCallback callback) = 0;
+                           chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Returns whether session manager can be used to restart Chrome in order to
   // apply per-user session flags, or start guest session.
@@ -445,7 +447,7 @@
   // processes for Chrome OS login screen.
   virtual void StartArcMiniContainer(
       const login_manager::StartArcMiniContainerRequest& request,
-      VoidDBusMethodCallback callback) = 0;
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // UpgradeArcContainer upgrades a mini-container to a full ARC container. On
   // upgrade failure, the container will be shutdown. The container shutdown
@@ -454,7 +456,7 @@
   // ArcInstanceStopped signal is received first.
   virtual void UpgradeArcContainer(
       const login_manager::UpgradeArcContainerRequest& request,
-      VoidDBusMethodCallback callback) = 0;
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Asynchronously stops the ARC instance. When |should_backup_log| is set to
   // true it also initiates ARC log back up operation on debugd for the given
@@ -463,7 +465,7 @@
   // stop an instance or session manager can not be reached).
   virtual void StopArcInstance(const std::string& account_id,
                                bool should_backup_log,
-                               VoidDBusMethodCallback callback) = 0;
+                               chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Adjusts the amount of CPU the ARC instance is allowed to use. When
   // |restriction_state| is CONTAINER_CPU_RESTRICTION_FOREGROUND the limit is
@@ -474,11 +476,11 @@
   // supported, the function asynchronously runs the |callback| with false.
   virtual void SetArcCpuRestriction(
       login_manager::ContainerCpuRestrictionState restriction_state,
-      VoidDBusMethodCallback callback) = 0;
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Emits the "arc-booted" upstart signal.
   virtual void EmitArcBooted(const cryptohome::AccountIdentifier& cryptohome_id,
-                             VoidDBusMethodCallback callback) = 0;
+                             chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Asynchronously retrieves the timestamp which ARC instance is invoked.
   // Returns nullopt if there is no ARC instance or ARC is not available.
diff --git a/chromeos/ash/components/dbus/shill/fake_modem_messaging_client.cc b/chromeos/ash/components/dbus/shill/fake_modem_messaging_client.cc
index e944536..55c9c8f0 100644
--- a/chromeos/ash/components/dbus/shill/fake_modem_messaging_client.cc
+++ b/chromeos/ash/components/dbus/shill/fake_modem_messaging_client.cc
@@ -34,10 +34,11 @@
   sms_received_handlers_[object_path].Reset();
 }
 
-void FakeModemMessagingClient::Delete(const std::string& service_name,
-                                      const dbus::ObjectPath& object_path,
-                                      const dbus::ObjectPath& sms_path,
-                                      VoidDBusMethodCallback callback) {
+void FakeModemMessagingClient::Delete(
+    const std::string& service_name,
+    const dbus::ObjectPath& object_path,
+    const dbus::ObjectPath& sms_path,
+    chromeos::VoidDBusMethodCallback callback) {
   std::vector<dbus::ObjectPath> message_paths = message_paths_map_[object_path];
   auto iter = find(message_paths.begin(), message_paths.end(), sms_path);
   if (iter != message_paths.end())
diff --git a/chromeos/ash/components/dbus/shill/fake_modem_messaging_client.h b/chromeos/ash/components/dbus/shill/fake_modem_messaging_client.h
index 7d46901..d7b071a 100644
--- a/chromeos/ash/components/dbus/shill/fake_modem_messaging_client.h
+++ b/chromeos/ash/components/dbus/shill/fake_modem_messaging_client.h
@@ -34,7 +34,7 @@
   void Delete(const std::string& service_name,
               const dbus::ObjectPath& object_path,
               const dbus::ObjectPath& sms_path,
-              VoidDBusMethodCallback callback) override;
+              chromeos::VoidDBusMethodCallback callback) override;
   void List(const std::string& service_name,
             const dbus::ObjectPath& object_path,
             ListCallback callback) override;
diff --git a/chromeos/ash/components/dbus/shill/fake_shill_device_client.cc b/chromeos/ash/components/dbus/shill/fake_shill_device_client.cc
index 6257fc0..4110c475 100644
--- a/chromeos/ash/components/dbus/shill/fake_shill_device_client.cc
+++ b/chromeos/ash/components/dbus/shill/fake_shill_device_client.cc
@@ -150,9 +150,10 @@
   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
 }
 
-void FakeShillDeviceClient::ClearProperty(const dbus::ObjectPath& device_path,
-                                          const std::string& name,
-                                          VoidDBusMethodCallback callback) {
+void FakeShillDeviceClient::ClearProperty(
+    const dbus::ObjectPath& device_path,
+    const std::string& name,
+    chromeos::VoidDBusMethodCallback callback) {
   base::Value* device_properties =
       stub_devices_.FindDictKey(device_path.value());
   if (!device_properties) {
@@ -560,8 +561,9 @@
 }
 
 // Posts a task to run a void callback with status code |status|.
-void FakeShillDeviceClient::PostVoidCallback(VoidDBusMethodCallback callback,
-                                             bool result) {
+void FakeShillDeviceClient::PostVoidCallback(
+    chromeos::VoidDBusMethodCallback callback,
+    bool result) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), result));
 }
diff --git a/chromeos/ash/components/dbus/shill/fake_shill_device_client.h b/chromeos/ash/components/dbus/shill/fake_shill_device_client.h
index 12d640e..47657eb 100644
--- a/chromeos/ash/components/dbus/shill/fake_shill_device_client.h
+++ b/chromeos/ash/components/dbus/shill/fake_shill_device_client.h
@@ -48,7 +48,7 @@
                    ErrorCallback error_callback) override;
   void ClearProperty(const dbus::ObjectPath& device_path,
                      const std::string& name,
-                     VoidDBusMethodCallback callback) override;
+                     chromeos::VoidDBusMethodCallback callback) override;
   void RequirePin(const dbus::ObjectPath& device_path,
                   const std::string& pin,
                   bool require,
@@ -125,7 +125,7 @@
       chromeos::DBusMethodCallback<base::Value> callback) const;
 
   // Posts a task to run a void callback with status code |result|.
-  void PostVoidCallback(VoidDBusMethodCallback callback, bool result);
+  void PostVoidCallback(chromeos::VoidDBusMethodCallback callback, bool result);
 
   // If |notify_changed| is true, NotifyObserversPropertyChanged is called,
   // otherwise it is not (e.g. when setting up initial properties).
diff --git a/chromeos/ash/components/dbus/shill/fake_shill_ipconfig_client.cc b/chromeos/ash/components/dbus/shill/fake_shill_ipconfig_client.cc
index 3792a44..f0cce50 100644
--- a/chromeos/ash/components/dbus/shill/fake_shill_ipconfig_client.cc
+++ b/chromeos/ash/components/dbus/shill/fake_shill_ipconfig_client.cc
@@ -43,10 +43,11 @@
       FROM_HERE, base::BindOnce(std::move(callback), dict->Clone()));
 }
 
-void FakeShillIPConfigClient::SetProperty(const dbus::ObjectPath& ipconfig_path,
-                                          const std::string& name,
-                                          const base::Value& value,
-                                          VoidDBusMethodCallback callback) {
+void FakeShillIPConfigClient::SetProperty(
+    const dbus::ObjectPath& ipconfig_path,
+    const std::string& name,
+    const base::Value& value,
+    chromeos::VoidDBusMethodCallback callback) {
   base::Value* dict = ipconfigs_.FindDictKey(ipconfig_path.value());
   if (!dict) {
     dict = ipconfigs_.SetKey(ipconfig_path.value(),
@@ -62,13 +63,14 @@
 void FakeShillIPConfigClient::ClearProperty(
     const dbus::ObjectPath& ipconfig_path,
     const std::string& name,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
 
-void FakeShillIPConfigClient::Remove(const dbus::ObjectPath& ipconfig_path,
-                                     VoidDBusMethodCallback callback) {
+void FakeShillIPConfigClient::Remove(
+    const dbus::ObjectPath& ipconfig_path,
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
diff --git a/chromeos/ash/components/dbus/shill/fake_shill_ipconfig_client.h b/chromeos/ash/components/dbus/shill/fake_shill_ipconfig_client.h
index 42318a9..fbfd64c9 100644
--- a/chromeos/ash/components/dbus/shill/fake_shill_ipconfig_client.h
+++ b/chromeos/ash/components/dbus/shill/fake_shill_ipconfig_client.h
@@ -38,12 +38,12 @@
   void SetProperty(const dbus::ObjectPath& ipconfig_path,
                    const std::string& name,
                    const base::Value& value,
-                   VoidDBusMethodCallback callback) override;
+                   chromeos::VoidDBusMethodCallback callback) override;
   void ClearProperty(const dbus::ObjectPath& ipconfig_path,
                      const std::string& name,
-                     VoidDBusMethodCallback callback) override;
+                     chromeos::VoidDBusMethodCallback callback) override;
   void Remove(const dbus::ObjectPath& ipconfig_path,
-              VoidDBusMethodCallback callback) override;
+              chromeos::VoidDBusMethodCallback callback) override;
   ShillIPConfigClient::TestInterface* GetTestInterface() override;
 
   // ShillIPConfigClient::TestInterface overrides.
diff --git a/chromeos/ash/components/dbus/shill/modem_messaging_client.cc b/chromeos/ash/components/dbus/shill/modem_messaging_client.cc
index 8f272a8..14ff64b 100644
--- a/chromeos/ash/components/dbus/shill/modem_messaging_client.cc
+++ b/chromeos/ash/components/dbus/shill/modem_messaging_client.cc
@@ -61,7 +61,7 @@
 
   // Calls Delete method.
   void Delete(const dbus::ObjectPath& message_path,
-              VoidDBusMethodCallback callback) {
+              chromeos::VoidDBusMethodCallback callback) {
     dbus::MethodCall method_call(modemmanager::kModemManager1MessagingInterface,
                                  modemmanager::kSMSDeleteFunction);
     dbus::MessageWriter writer(&method_call);
@@ -98,7 +98,8 @@
   }
 
   // Handles responses of Delete method calls.
-  void OnDelete(VoidDBusMethodCallback callback, dbus::Response* response) {
+  void OnDelete(chromeos::VoidDBusMethodCallback callback,
+                dbus::Response* response) {
     std::move(callback).Run(response);
   }
 
@@ -159,7 +160,7 @@
   void Delete(const std::string& service_name,
               const dbus::ObjectPath& object_path,
               const dbus::ObjectPath& sms_path,
-              VoidDBusMethodCallback callback) override {
+              chromeos::VoidDBusMethodCallback callback) override {
     GetProxy(service_name, object_path)->Delete(sms_path, std::move(callback));
   }
 
diff --git a/chromeos/ash/components/dbus/shill/modem_messaging_client.h b/chromeos/ash/components/dbus/shill/modem_messaging_client.h
index 57287b4..b3f905a 100644
--- a/chromeos/ash/components/dbus/shill/modem_messaging_client.h
+++ b/chromeos/ash/components/dbus/shill/modem_messaging_client.h
@@ -68,7 +68,7 @@
   virtual void Delete(const std::string& service_name,
                       const dbus::ObjectPath& object_path,
                       const dbus::ObjectPath& sms_path,
-                      VoidDBusMethodCallback callback) = 0;
+                      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Calls List method.  |callback| is called on method completion.
   using ListCallback =
diff --git a/chromeos/ash/components/dbus/shill/shill_client_helper.cc b/chromeos/ash/components/dbus/shill/shill_client_helper.cc
index 819e6c9..f454a67 100644
--- a/chromeos/ash/components/dbus/shill/shill_client_helper.cc
+++ b/chromeos/ash/components/dbus/shill/shill_client_helper.cc
@@ -99,7 +99,7 @@
 
 // Handles responses for methods without results.
 void OnVoidMethod(ShillClientHelper::RefHolder* ref_holder,
-                  VoidDBusMethodCallback callback,
+                  chromeos::VoidDBusMethodCallback callback,
                   dbus::Response* response) {
   std::move(callback).Run(response != nullptr);
 }
@@ -267,8 +267,9 @@
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
-void ShillClientHelper::CallVoidMethod(dbus::MethodCall* method_call,
-                                       VoidDBusMethodCallback callback) {
+void ShillClientHelper::CallVoidMethod(
+    dbus::MethodCall* method_call,
+    chromeos::VoidDBusMethodCallback callback) {
   DCHECK(!callback.is_null());
   proxy_->CallMethod(
       method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
diff --git a/chromeos/ash/components/dbus/shill/shill_client_helper.h b/chromeos/ash/components/dbus/shill/shill_client_helper.h
index d5ac0c0..eece531 100644
--- a/chromeos/ash/components/dbus/shill/shill_client_helper.h
+++ b/chromeos/ash/components/dbus/shill/shill_client_helper.h
@@ -79,7 +79,7 @@
 
   // Calls a method without results.
   void CallVoidMethod(dbus::MethodCall* method_call,
-                      VoidDBusMethodCallback callback);
+                      chromeos::VoidDBusMethodCallback callback);
 
   // Calls a method with an object path result where there is an error callback.
   void CallObjectPathMethodWithErrorCallback(dbus::MethodCall* method_call,
diff --git a/chromeos/ash/components/dbus/shill/shill_device_client.cc b/chromeos/ash/components/dbus/shill/shill_device_client.cc
index 1508400..e3c00051 100644
--- a/chromeos/ash/components/dbus/shill/shill_device_client.cc
+++ b/chromeos/ash/components/dbus/shill/shill_device_client.cc
@@ -89,7 +89,7 @@
 
   void ClearProperty(const dbus::ObjectPath& device_path,
                      const std::string& name,
-                     VoidDBusMethodCallback callback) override {
+                     chromeos::VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
                                  shill::kClearPropertyFunction);
     dbus::MessageWriter writer(&method_call);
diff --git a/chromeos/ash/components/dbus/shill/shill_device_client.h b/chromeos/ash/components/dbus/shill/shill_device_client.h
index 34163f6..fe07d38 100644
--- a/chromeos/ash/components/dbus/shill/shill_device_client.h
+++ b/chromeos/ash/components/dbus/shill/shill_device_client.h
@@ -116,7 +116,7 @@
   // |callback| is called after the method call finishes.
   virtual void ClearProperty(const dbus::ObjectPath& device_path,
                              const std::string& name,
-                             VoidDBusMethodCallback callback) = 0;
+                             chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Calls the RequirePin method.
   // |callback| is called after the method call finishes.
diff --git a/chromeos/ash/components/dbus/shill/shill_ipconfig_client.cc b/chromeos/ash/components/dbus/shill/shill_ipconfig_client.cc
index a8d0947b..2102ad9 100644
--- a/chromeos/ash/components/dbus/shill/shill_ipconfig_client.cc
+++ b/chromeos/ash/components/dbus/shill/shill_ipconfig_client.cc
@@ -55,12 +55,12 @@
   void SetProperty(const dbus::ObjectPath& ipconfig_path,
                    const std::string& name,
                    const base::Value& value,
-                   VoidDBusMethodCallback callback) override;
+                   chromeos::VoidDBusMethodCallback callback) override;
   void ClearProperty(const dbus::ObjectPath& ipconfig_path,
                      const std::string& name,
-                     VoidDBusMethodCallback callback) override;
+                     chromeos::VoidDBusMethodCallback callback) override;
   void Remove(const dbus::ObjectPath& ipconfig_path,
-              VoidDBusMethodCallback callback) override;
+              chromeos::VoidDBusMethodCallback callback) override;
   ShillIPConfigClient::TestInterface* GetTestInterface() override;
 
  private:
@@ -98,10 +98,11 @@
                                        ipconfig_path, std::move(callback)));
 }
 
-void ShillIPConfigClientImpl::SetProperty(const dbus::ObjectPath& ipconfig_path,
-                                          const std::string& name,
-                                          const base::Value& value,
-                                          VoidDBusMethodCallback callback) {
+void ShillIPConfigClientImpl::SetProperty(
+    const dbus::ObjectPath& ipconfig_path,
+    const std::string& name,
+    const base::Value& value,
+    chromeos::VoidDBusMethodCallback callback) {
   dbus::MethodCall method_call(shill::kFlimflamIPConfigInterface,
                                shill::kSetPropertyFunction);
   dbus::MessageWriter writer(&method_call);
@@ -138,7 +139,7 @@
 void ShillIPConfigClientImpl::ClearProperty(
     const dbus::ObjectPath& ipconfig_path,
     const std::string& name,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   dbus::MethodCall method_call(shill::kFlimflamIPConfigInterface,
                                shill::kClearPropertyFunction);
   dbus::MessageWriter writer(&method_call);
@@ -146,8 +147,9 @@
   GetHelper(ipconfig_path)->CallVoidMethod(&method_call, std::move(callback));
 }
 
-void ShillIPConfigClientImpl::Remove(const dbus::ObjectPath& ipconfig_path,
-                                     VoidDBusMethodCallback callback) {
+void ShillIPConfigClientImpl::Remove(
+    const dbus::ObjectPath& ipconfig_path,
+    chromeos::VoidDBusMethodCallback callback) {
   dbus::MethodCall method_call(shill::kFlimflamIPConfigInterface,
                                shill::kRemoveConfigFunction);
   GetHelper(ipconfig_path)->CallVoidMethod(&method_call, std::move(callback));
diff --git a/chromeos/ash/components/dbus/shill/shill_ipconfig_client.h b/chromeos/ash/components/dbus/shill/shill_ipconfig_client.h
index cf5f6719..ce2ba04 100644
--- a/chromeos/ash/components/dbus/shill/shill_ipconfig_client.h
+++ b/chromeos/ash/components/dbus/shill/shill_ipconfig_client.h
@@ -76,18 +76,18 @@
   virtual void SetProperty(const dbus::ObjectPath& ipconfig_path,
                            const std::string& name,
                            const base::Value& value,
-                           VoidDBusMethodCallback callback) = 0;
+                           chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Calls ClearProperty method.
   // |callback| is called after the method call succeeds.
   virtual void ClearProperty(const dbus::ObjectPath& ipconfig_path,
                              const std::string& name,
-                             VoidDBusMethodCallback callback) = 0;
+                             chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Calls Remove method.
   // |callback| is called after the method call succeeds.
   virtual void Remove(const dbus::ObjectPath& ipconfig_path,
-                      VoidDBusMethodCallback callback) = 0;
+                      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Returns an interface for testing (stub only), or returns null.
   virtual ShillIPConfigClient::TestInterface* GetTestInterface() = 0;
diff --git a/chromeos/ash/components/dbus/upstart/fake_upstart_client.cc b/chromeos/ash/components/dbus/upstart/fake_upstart_client.cc
index 261f828..21de4799 100644
--- a/chromeos/ash/components/dbus/upstart/fake_upstart_client.cc
+++ b/chromeos/ash/components/dbus/upstart/fake_upstart_client.cc
@@ -36,7 +36,7 @@
 
 void FakeUpstartClient::StartJob(const std::string& job,
                                  const std::vector<std::string>& upstart_env,
-                                 VoidDBusMethodCallback callback) {
+                                 chromeos::VoidDBusMethodCallback callback) {
   const bool result =
       start_job_cb_ ? start_job_cb_.Run(job, upstart_env) : true;
   base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -56,7 +56,7 @@
 
 void FakeUpstartClient::StopJob(const std::string& job,
                                 const std::vector<std::string>& upstart_env,
-                                VoidDBusMethodCallback callback) {
+                                chromeos::VoidDBusMethodCallback callback) {
   const bool result = stop_job_cb_ ? stop_job_cb_.Run(job, upstart_env) : true;
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), result));
@@ -77,7 +77,7 @@
 
 void FakeUpstartClient::StartMediaAnalytics(
     const std::vector<std::string>& /* upstart_env */,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   DLOG_IF(WARNING, FakeMediaAnalyticsClient::Get()->process_running())
       << "Trying to start media analytics which is already started.";
   FakeMediaAnalyticsClient::Get()->set_process_running(true);
@@ -85,7 +85,8 @@
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
 
-void FakeUpstartClient::RestartMediaAnalytics(VoidDBusMethodCallback callback) {
+void FakeUpstartClient::RestartMediaAnalytics(
+    chromeos::VoidDBusMethodCallback callback) {
   FakeMediaAnalyticsClient::Get()->set_process_running(false);
   FakeMediaAnalyticsClient::Get()->set_process_running(true);
   FakeMediaAnalyticsClient::Get()->SetStateSuspended();
@@ -99,30 +100,34 @@
   FakeMediaAnalyticsClient::Get()->set_process_running(false);
 }
 
-void FakeUpstartClient::StopMediaAnalytics(VoidDBusMethodCallback callback) {
+void FakeUpstartClient::StopMediaAnalytics(
+    chromeos::VoidDBusMethodCallback callback) {
   FakeMediaAnalyticsClient::Get()->set_process_running(false);
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
 
-void FakeUpstartClient::StartWilcoDtcService(VoidDBusMethodCallback callback) {
+void FakeUpstartClient::StartWilcoDtcService(
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
 
-void FakeUpstartClient::StopWilcoDtcService(VoidDBusMethodCallback callback) {
+void FakeUpstartClient::StopWilcoDtcService(
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
 
 void FakeUpstartClient::StartArcDataSnapshotd(
     const std::vector<std::string>& upstart_env,
-    VoidDBusMethodCallback callback) {
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
 
-void FakeUpstartClient::StopArcDataSnapshotd(VoidDBusMethodCallback callback) {
+void FakeUpstartClient::StopArcDataSnapshotd(
+    chromeos::VoidDBusMethodCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
diff --git a/chromeos/ash/components/dbus/upstart/fake_upstart_client.h b/chromeos/ash/components/dbus/upstart/fake_upstart_client.h
index 18c977c..4a36c80 100644
--- a/chromeos/ash/components/dbus/upstart/fake_upstart_client.h
+++ b/chromeos/ash/components/dbus/upstart/fake_upstart_client.h
@@ -31,27 +31,29 @@
   // UpstartClient overrides:
   void StartJob(const std::string& job,
                 const std::vector<std::string>& upstart_env,
-                VoidDBusMethodCallback callback) override;
+                chromeos::VoidDBusMethodCallback callback) override;
   void StartJobWithErrorDetails(
       const std::string& job,
       const std::vector<std::string>& upstart_env,
       StartJobWithErrorDetailsCallback callback) override;
   void StopJob(const std::string& job,
                const std::vector<std::string>& upstart_env,
-               VoidDBusMethodCallback callback) override;
+               chromeos::VoidDBusMethodCallback callback) override;
   void StartAuthPolicyService() override;
   void RestartAuthPolicyService() override;
   void StartLacrosChrome(const std::vector<std::string>& upstart_env) override;
   void StartMediaAnalytics(const std::vector<std::string>& upstart_env,
-                           VoidDBusMethodCallback callback) override;
-  void RestartMediaAnalytics(VoidDBusMethodCallback callback) override;
+                           chromeos::VoidDBusMethodCallback callback) override;
+  void RestartMediaAnalytics(
+      chromeos::VoidDBusMethodCallback callback) override;
   void StopMediaAnalytics() override;
-  void StopMediaAnalytics(VoidDBusMethodCallback callback) override;
-  void StartWilcoDtcService(VoidDBusMethodCallback callback) override;
-  void StopWilcoDtcService(VoidDBusMethodCallback callback) override;
-  void StartArcDataSnapshotd(const std::vector<std::string>& upstart_env,
-                             VoidDBusMethodCallback callback) override;
-  void StopArcDataSnapshotd(VoidDBusMethodCallback callback) override;
+  void StopMediaAnalytics(chromeos::VoidDBusMethodCallback callback) override;
+  void StartWilcoDtcService(chromeos::VoidDBusMethodCallback callback) override;
+  void StopWilcoDtcService(chromeos::VoidDBusMethodCallback callback) override;
+  void StartArcDataSnapshotd(
+      const std::vector<std::string>& upstart_env,
+      chromeos::VoidDBusMethodCallback callback) override;
+  void StopArcDataSnapshotd(chromeos::VoidDBusMethodCallback callback) override;
 
   void set_start_job_cb(const StartStopJobCallback& cb) { start_job_cb_ = cb; }
   void set_stop_job_cb(const StartStopJobCallback& cb) { stop_job_cb_ = cb; }
diff --git a/chromeos/ash/components/dbus/upstart/upstart_client.cc b/chromeos/ash/components/dbus/upstart/upstart_client.cc
index 5a1677f..ce4541ee 100644
--- a/chromeos/ash/components/dbus/upstart/upstart_client.cc
+++ b/chromeos/ash/components/dbus/upstart/upstart_client.cc
@@ -52,7 +52,7 @@
   // UpstartClient overrides:
   void StartJob(const std::string& job,
                 const std::vector<std::string>& upstart_env,
-                VoidDBusMethodCallback callback) override {
+                chromeos::VoidDBusMethodCallback callback) override {
     CallJobMethod(job, kStartMethod, upstart_env,
                   base::BindOnce(&UpstartClientImpl::OnVoidMethod,
                                  weak_ptr_factory_.GetWeakPtr(), job, "start",
@@ -71,7 +71,7 @@
 
   void StopJob(const std::string& job,
                const std::vector<std::string>& upstart_env,
-               VoidDBusMethodCallback callback) override {
+               chromeos::VoidDBusMethodCallback callback) override {
     CallJobMethod(job, kStopMethod, upstart_env,
                   base::BindOnce(&UpstartClientImpl::OnVoidMethod,
                                  weak_ptr_factory_.GetWeakPtr(), job, "stop",
@@ -95,11 +95,12 @@
   }
 
   void StartMediaAnalytics(const std::vector<std::string>& upstart_env,
-                           VoidDBusMethodCallback callback) override {
+                           chromeos::VoidDBusMethodCallback callback) override {
     StartJob(kMediaAnalyticsJob, upstart_env, std::move(callback));
   }
 
-  void RestartMediaAnalytics(VoidDBusMethodCallback callback) override {
+  void RestartMediaAnalytics(
+      chromeos::VoidDBusMethodCallback callback) override {
     CallJobMethod(
         kMediaAnalyticsJob, kRestartMethod, {},
         base::BindOnce(&UpstartClientImpl::OnVoidMethod,
@@ -113,24 +114,27 @@
     StopJob(kMediaAnalyticsJob, {}, base::DoNothing());
   }
 
-  void StopMediaAnalytics(VoidDBusMethodCallback callback) override {
+  void StopMediaAnalytics(chromeos::VoidDBusMethodCallback callback) override {
     StopJob(kMediaAnalyticsJob, {}, std::move(callback));
   }
 
-  void StartWilcoDtcService(VoidDBusMethodCallback callback) override {
+  void StartWilcoDtcService(
+      chromeos::VoidDBusMethodCallback callback) override {
     StartJob(kWilcoDtcDispatcherJob, {}, std::move(callback));
   }
 
-  void StopWilcoDtcService(VoidDBusMethodCallback callback) override {
+  void StopWilcoDtcService(chromeos::VoidDBusMethodCallback callback) override {
     StopJob(kWilcoDtcDispatcherJob, {}, std::move(callback));
   }
 
-  void StartArcDataSnapshotd(const std::vector<std::string>& upstart_env,
-                             VoidDBusMethodCallback callback) override {
+  void StartArcDataSnapshotd(
+      const std::vector<std::string>& upstart_env,
+      chromeos::VoidDBusMethodCallback callback) override {
     StartJob(kArcDataSnapshotdJob, upstart_env, std::move(callback));
   }
 
-  void StopArcDataSnapshotd(VoidDBusMethodCallback callback) override {
+  void StopArcDataSnapshotd(
+      chromeos::VoidDBusMethodCallback callback) override {
     StopJob(kArcDataSnapshotdJob, {}, std::move(callback));
   }
 
@@ -152,7 +156,7 @@
 
   void OnVoidMethod(const std::string& job_for_logging,
                     const std::string& action_for_logging,
-                    VoidDBusMethodCallback callback,
+                    chromeos::VoidDBusMethodCallback callback,
                     dbus::Response* response,
                     dbus::ErrorResponse* error_response) {
     if (!response)
diff --git a/chromeos/ash/components/dbus/upstart/upstart_client.h b/chromeos/ash/components/dbus/upstart/upstart_client.h
index 2fe7e54..6818385 100644
--- a/chromeos/ash/components/dbus/upstart/upstart_client.h
+++ b/chromeos/ash/components/dbus/upstart/upstart_client.h
@@ -52,7 +52,7 @@
   // |callback|: Called with a response.
   virtual void StartJob(const std::string& job,
                         const std::vector<std::string>& upstart_env,
-                        VoidDBusMethodCallback callback) = 0;
+                        chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Does the same thing as StartJob(), but the callback is run with error
   // details on failures.
@@ -78,7 +78,7 @@
   // |callback|: Called with a response.
   virtual void StopJob(const std::string& job,
                        const std::vector<std::string>& upstart_env,
-                       VoidDBusMethodCallback callback) = 0;
+                       chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Starts authpolicyd.
   virtual void StartAuthPolicyService() = 0;
@@ -95,31 +95,37 @@
   // Starts the media analytics process.
   // |upstart_env|: List of upstart environment variables to be passed to the
   // upstart service.
-  virtual void StartMediaAnalytics(const std::vector<std::string>& upstart_env,
-                                   VoidDBusMethodCallback callback) = 0;
+  virtual void StartMediaAnalytics(
+      const std::vector<std::string>& upstart_env,
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Restarts the media analytics process.
-  virtual void RestartMediaAnalytics(VoidDBusMethodCallback callback) = 0;
+  virtual void RestartMediaAnalytics(
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Stops the media analytics process.
   virtual void StopMediaAnalytics() = 0;
 
   // Provides an interface for stopping the media analytics process.
-  virtual void StopMediaAnalytics(VoidDBusMethodCallback callback) = 0;
+  virtual void StopMediaAnalytics(
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Start wilco DTC services.
-  virtual void StartWilcoDtcService(VoidDBusMethodCallback callback) = 0;
+  virtual void StartWilcoDtcService(
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Stops wilco DTC services.
-  virtual void StopWilcoDtcService(VoidDBusMethodCallback callback) = 0;
+  virtual void StopWilcoDtcService(
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Starts arc-data-snapshotd daemon.
   virtual void StartArcDataSnapshotd(
       const std::vector<std::string>& upstart_env,
-      VoidDBusMethodCallback callback) = 0;
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
   // Stops arc-data-snapshotd daemon.
-  virtual void StopArcDataSnapshotd(VoidDBusMethodCallback callback) = 0;
+  virtual void StopArcDataSnapshotd(
+      chromeos::VoidDBusMethodCallback callback) = 0;
 
  protected:
   // Initialize() should be used instead.
diff --git a/chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.cc b/chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.cc
index 0a216976..f8bd055 100644
--- a/chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.cc
+++ b/chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.cc
@@ -34,8 +34,8 @@
   g_instance = this;
 
   base::FilePath cache_path;
-  locked_ = base::PathService::Get(dbus_paths::FILE_INSTALL_ATTRIBUTES,
-                                   &cache_path) &&
+  locked_ = base::PathService::Get(
+                chromeos::dbus_paths::FILE_INSTALL_ATTRIBUTES, &cache_path) &&
             base::PathExists(cache_path);
   if (locked_)
     LoadInstallAttributes();
@@ -118,7 +118,7 @@
   // browser is restarted. This is used for ease of development when device
   // enrollment is required.
   base::FilePath cache_path;
-  if (!base::PathService::Get(dbus_paths::FILE_INSTALL_ATTRIBUTES,
+  if (!base::PathService::Get(chromeos::dbus_paths::FILE_INSTALL_ATTRIBUTES,
                               &cache_path)) {
     reply.set_error(::user_data_auth::CryptohomeErrorCode::
                         CRYPTOHOME_ERROR_INSTALL_ATTRIBUTES_FINALIZE_FAILED);
@@ -200,7 +200,7 @@
 bool FakeInstallAttributesClient::LoadInstallAttributes() {
   base::FilePath cache_file;
   const bool file_exists =
-      base::PathService::Get(dbus_paths::FILE_INSTALL_ATTRIBUTES,
+      base::PathService::Get(chromeos::dbus_paths::FILE_INSTALL_ATTRIBUTES,
                              &cache_file) &&
       base::PathExists(cache_file);
   DCHECK(file_exists);
diff --git a/chromeos/ash/components/install_attributes/install_attributes.cc b/chromeos/ash/components/install_attributes/install_attributes.cc
index e011d4b..1e93f5f 100644
--- a/chromeos/ash/components/install_attributes/install_attributes.cc
+++ b/chromeos/ash/components/install_attributes/install_attributes.cc
@@ -73,8 +73,8 @@
 
   DCHECK(!g_install_attributes);
   g_install_attributes = new InstallAttributes(InstallAttributesClient::Get());
-  g_install_attributes->Init(
-      base::PathService::CheckedGet(dbus_paths::FILE_INSTALL_ATTRIBUTES));
+  g_install_attributes->Init(base::PathService::CheckedGet(
+      chromeos::dbus_paths::FILE_INSTALL_ATTRIBUTES));
 }
 
 // static
diff --git a/chromeos/ash/components/install_attributes/install_attributes_unittest.cc b/chromeos/ash/components/install_attributes/install_attributes_unittest.cc
index 7c12ddb..30b43de 100644
--- a/chromeos/ash/components/install_attributes/install_attributes_unittest.cc
+++ b/chromeos/ash/components/install_attributes/install_attributes_unittest.cc
@@ -49,7 +49,8 @@
   void SetUp() override {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     ASSERT_TRUE(base::PathService::OverrideAndCreateIfNeeded(
-        dbus_paths::FILE_INSTALL_ATTRIBUTES, GetTempPath(), true, false));
+        chromeos::dbus_paths::FILE_INSTALL_ATTRIBUTES, GetTempPath(), true,
+        false));
     InstallAttributesClient::InitializeFake();
     TpmManagerClient::InitializeFake();
     install_attributes_ =
diff --git a/chromeos/ash/components/network/managed_network_configuration_handler_impl.cc b/chromeos/ash/components/network/managed_network_configuration_handler_impl.cc
index 0e02af3..77cd25b 100644
--- a/chromeos/ash/components/network/managed_network_configuration_handler_impl.cc
+++ b/chromeos/ash/components/network/managed_network_configuration_handler_impl.cc
@@ -797,7 +797,7 @@
   network_state_handler_->UpdateBlockedCellularNetworks(
       AllowOnlyPolicyCellularNetworks());
 
-  if (features::IsSimLockPolicyEnabled())
+  if (features::IsSimLockPolicyEnabled() && network_device_handler_)
     network_device_handler_->SetAllowCellularSimLock(AllowCellularSimLock());
 
   if (device_policy_applied_ && user_policy_applied_) {
diff --git a/chromeos/ash/components/string_matching/BUILD.gn b/chromeos/ash/components/string_matching/BUILD.gn
index fb35373..56193b53 100644
--- a/chromeos/ash/components/string_matching/BUILD.gn
+++ b/chromeos/ash/components/string_matching/BUILD.gn
@@ -9,6 +9,8 @@
 
 source_set("string_matching") {
   sources = [
+    "diacritic_utils.cc",
+    "diacritic_utils.h",
     "fuzzy_tokenized_string_match.cc",
     "fuzzy_tokenized_string_match.h",
     "prefix_matcher.cc",
@@ -40,6 +42,7 @@
   testonly = true
 
   sources = [
+    "diacritic_utils_unittest.cc",
     "fuzzy_tokenized_string_match_unittest.cc",
     "prefix_matcher_unittest.cc",
     "sequence_matcher_unittest.cc",
diff --git a/chromeos/ash/components/string_matching/diacritic_utils.cc b/chromeos/ash/components/string_matching/diacritic_utils.cc
new file mode 100644
index 0000000..69b98861
--- /dev/null
+++ b/chromeos/ash/components/string_matching/diacritic_utils.cc
@@ -0,0 +1,50 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/ash/components/string_matching/diacritic_utils.h"
+
+#include <string>
+#include <vector>
+
+#include "base/containers/flat_map.h"
+
+namespace ash::string_matching {
+
+// Intentionally only covering Latin-script accented characters for our initial
+// implementation of diacritic-insensitive search.
+DiacriticUtils::DiacriticUtils() {
+  std::vector<std::pair<std::u16string, std::u16string>>
+      diacritics_to_stripped = {
+          {u"áàâäāå", u"a"}, {u"ÁÀÂÄĀÅ", u"A"}, {u"éèêëē", u"e"},
+          {u"ÉÈÊËĒ", u"E"},  {u"íìîïī", u"i"},  {u"óòôöōø", u"o"},
+          {u"úùûüū", u"u"},  {u"ÚÙÛÜŪ", u"U"},  {u"ýỳŷÿȳ", u"y"},
+          {u"ÝỲŶŸȲ", u"Y"},  {u"ç", u"c"},      {u"Ç", u"C"},
+          {u"ñ", u"n"},      {u"Ñ", u"N"},      {u"æ", u"ae"},
+          {u"Æ", u"AE"},     {u"œ", u"oe"},     {u"Œ", u"OE"},
+      };
+
+  for (const auto& mapping_pair : diacritics_to_stripped) {
+    for (const auto& diacritic : mapping_pair.first) {
+      conversion_map_[diacritic] = mapping_pair.second;
+    }
+  }
+};
+
+DiacriticUtils::~DiacriticUtils() = default;
+
+const std::u16string DiacriticUtils::RemoveDiacritics(
+    const std::u16string& str) {
+  std::u16string result;
+  for (auto letter : str) {
+    auto it = conversion_map_.find(letter);
+    if (it == conversion_map_.end()) {
+      result.push_back(letter);
+    } else {
+      result.append(it->second);
+    }
+  }
+  return result;
+};
+
+}  // namespace ash::string_matching
diff --git a/chromeos/ash/components/string_matching/diacritic_utils.h b/chromeos/ash/components/string_matching/diacritic_utils.h
new file mode 100644
index 0000000..3bfd955
--- /dev/null
+++ b/chromeos/ash/components/string_matching/diacritic_utils.h
@@ -0,0 +1,29 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_DIACRITIC_UTILS_H_
+#define CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_DIACRITIC_UTILS_H_
+
+#include <string>
+#include "base/containers/flat_map.h"
+
+namespace ash::string_matching {
+class DiacriticUtils {
+ public:
+  DiacriticUtils();
+  ~DiacriticUtils();
+
+  DiacriticUtils(const DiacriticUtils&) = delete;
+  DiacriticUtils& operator=(const DiacriticUtils&) = delete;
+
+  // Removes diacritics from 'str' and return the result. e.g.:
+  // RemoveDiacritics(hölzle) => holzle
+  const std::u16string RemoveDiacritics(const std::u16string& str);
+
+ private:
+  base::flat_map<char16_t, std::u16string> conversion_map_;
+};
+
+}  // namespace ash::string_matching
+#endif  // CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_DIACRITIC_UTILS_H_
diff --git a/chromeos/ash/components/string_matching/diacritic_utils_unittest.cc b/chromeos/ash/components/string_matching/diacritic_utils_unittest.cc
new file mode 100644
index 0000000..34e7c91
--- /dev/null
+++ b/chromeos/ash/components/string_matching/diacritic_utils_unittest.cc
@@ -0,0 +1,39 @@
+// Copyright (c) 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/ash/components/string_matching/diacritic_utils.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ash::string_matching {
+class DiacriticUtilsTest : public testing::Test {};
+
+TEST(DiacriticUtilsTest, TestEqual) {
+  DiacriticUtils util;
+  EXPECT_EQ(util.RemoveDiacritics(u"français"), u"francais");
+  EXPECT_EQ(util.RemoveDiacritics(u"déjà"), u"deja");
+  EXPECT_EQ(util.RemoveDiacritics(u"Español"), u"Espanol");
+  EXPECT_EQ(util.RemoveDiacritics(u"École"), u"Ecole");
+  EXPECT_EQ(util.RemoveDiacritics(u"cœur"), u"coeur");
+  EXPECT_EQ(util.RemoveDiacritics(u"København"), u"Kobenhavn");
+  EXPECT_EQ(util.RemoveDiacritics(u"ångström"), u"angstrom");
+  EXPECT_EQ(util.RemoveDiacritics(u"Neuchâtel"), u"Neuchatel");
+  EXPECT_EQ(util.RemoveDiacritics(u"jamón"), u"jamon");
+  EXPECT_EQ(util.RemoveDiacritics(u"NOËL"), u"NOEL");
+}
+
+TEST(DiacriticUtilsTest, TestNotEqual) {
+  DiacriticUtils util;
+  EXPECT_NE(util.RemoveDiacritics(u"français"), u"français");
+  EXPECT_NE(util.RemoveDiacritics(u"Déjà"), u"deja");
+  EXPECT_NE(util.RemoveDiacritics(u"español"), u"français");
+  EXPECT_NE(util.RemoveDiacritics(u"École"), u"ecole");
+  EXPECT_NE(util.RemoveDiacritics(u"œufs"), u"coeur");
+  EXPECT_NE(util.RemoveDiacritics(u"København"), u"Copenhagen");
+  EXPECT_NE(util.RemoveDiacritics(u"ångström"), u"angstroms");
+  EXPECT_NE(util.RemoveDiacritics(u"Neuchâtel"), u"Newcastle");
+  EXPECT_NE(util.RemoveDiacritics(u"jamón"), u"jambon");
+  EXPECT_NE(util.RemoveDiacritics(u"NOËL"), u"Christmas");
+}
+}  // namespace ash::string_matching
diff --git a/chromeos/ash/services/assistant/platform/audio_devices_unittest.cc b/chromeos/ash/services/assistant/platform/audio_devices_unittest.cc
index db02a10..38ad17f3 100644
--- a/chromeos/ash/services/assistant/platform/audio_devices_unittest.cc
+++ b/chromeos/ash/services/assistant/platform/audio_devices_unittest.cc
@@ -97,7 +97,7 @@
               SetHotwordModel,
               (uint64_t node_id,
                const std::string& hotword_model,
-               VoidDBusMethodCallback callback));
+               chromeos::VoidDBusMethodCallback callback));
 };
 
 class ScopedCrasAudioHandler {
@@ -393,7 +393,7 @@
   EXPECT_CALL(cras_audio_client_mock(),
               SetHotwordModel(_, "rejected_locale", _))
       .WillOnce([](uint64_t node_id, const std::string&,
-                   VoidDBusMethodCallback callback) {
+                   chromeos::VoidDBusMethodCallback callback) {
         // Report failure to change the locale
         std::move(callback).Run(/*success=*/false);
       });
@@ -418,7 +418,7 @@
   EXPECT_CALL(cras_audio_client_mock(),
               SetHotwordModel(_, "accepted_locale", _))
       .WillOnce([](uint64_t node_id, const std::string&,
-                   VoidDBusMethodCallback callback) {
+                   chromeos::VoidDBusMethodCallback callback) {
         // Accept the change to the locale.
         std::move(callback).Run(/*success=*/true);
       });
diff --git a/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom
index aee9496..516f7b2 100644
--- a/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom
+++ b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom
@@ -241,13 +241,14 @@
 
 // The manufacturer of the block device.
 //
-// NextMinVersion: 2, NextIndex: 4
+// NextMinVersion: 3, NextIndex: 5
 [Stable, Extensible]
 union BlockDeviceVendor {
   uint32 nvme_subsystem_vendor@0;
   uint16 emmc_oemid@1;
   uint16 other@2;
   [MinVersion=1, Default] uint64 unknown@3;
+  [MinVersion=2] uint16 jedec_manfid@4;
 };
 
 // The manufacturer-specific product identifier.
@@ -274,13 +275,14 @@
 
 // The revision of the device's firmware.
 //
-// NextMinVersion: 2, NextIndex: 4
+// NextMinVersion: 3, NextIndex: 5
 [Stable, Extensible]
 union BlockDeviceFirmware {
   uint64 nvme_firmware_rev@0;
   uint64 emmc_fwrev@1;
   uint16 other@2;
   [MinVersion=1, Default] uint64 unknown@3;
+  [MinVersion=2] uint64 ufs_fwrev@4;
 };
 
 // Purpose of the storage device.
diff --git a/chromeos/dbus/common/dbus_method_call_status.h b/chromeos/dbus/common/dbus_method_call_status.h
index 06fcc6c5..291cae6 100644
--- a/chromeos/dbus/common/dbus_method_call_status.h
+++ b/chromeos/dbus/common/dbus_method_call_status.h
@@ -48,7 +48,6 @@
 // TODO(https://crbug.com/1164001): remove when //chromeos/dbus moved to ash.
 namespace ash {
 using ::chromeos::ObjectPathCallback;
-using ::chromeos::VoidDBusMethodCallback;
 using ::chromeos::WaitForServiceToBeAvailableCallback;
 }  // namespace ash
 
diff --git a/chromeos/dbus/constants/dbus_paths.h b/chromeos/dbus/constants/dbus_paths.h
index fd249dbf..1295752 100644
--- a/chromeos/dbus/constants/dbus_paths.h
+++ b/chromeos/dbus/constants/dbus_paths.h
@@ -44,9 +44,4 @@
 }  // namespace dbus_paths
 }  // namespace chromeos
 
-// TODO(https://crbug.com/1164001): remove after the migration is finished.
-namespace ash::dbus_paths {
-using ::chromeos::dbus_paths::FILE_INSTALL_ATTRIBUTES;
-}
-
 #endif  // CHROMEOS_DBUS_CONSTANTS_DBUS_PATHS_H_
diff --git a/chromeos/dbus/constants/dbus_switches.h b/chromeos/dbus/constants/dbus_switches.h
index e0240c0..26ea914 100644
--- a/chromeos/dbus/constants/dbus_switches.h
+++ b/chromeos/dbus/constants/dbus_switches.h
@@ -34,11 +34,4 @@
 }  // namespace switches
 }  // namespace chromeos
 
-// TODO(https://crbug.com/1164001): remove after the migration is finished.
-namespace ash {
-namespace switches {
-using ::chromeos::switches::kFakeOobeConfiguration;
-}
-}  // namespace ash
-
 #endif  // CHROMEOS_DBUS_CONSTANTS_DBUS_SWITCHES_H_
diff --git a/chromeos/ui/frame/caption_buttons/frame_size_button.cc b/chromeos/ui/frame/caption_buttons/frame_size_button.cc
index 763fb2b..99a0d16 100644
--- a/chromeos/ui/frame/caption_buttons/frame_size_button.cc
+++ b/chromeos/ui/frame/caption_buttons/frame_size_button.cc
@@ -10,6 +10,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/metrics/user_metrics.h"
 #include "chromeos/ui/base/display_util.h"
+#include "chromeos/ui/base/tablet_state.h"
 #include "chromeos/ui/base/window_properties.h"
 #include "chromeos/ui/frame/caption_buttons/snap_controller.h"
 #include "chromeos/ui/wm/features.h"
@@ -19,6 +20,7 @@
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/display/screen.h"
+#include "ui/display/tablet_state.h"
 #include "ui/gfx/animation/animation_delegate.h"
 #include "ui/gfx/animation/slide_animation.h"
 #include "ui/gfx/canvas.h"
@@ -127,11 +129,9 @@
   ~PieAnimation() override = default;
 
   void Paint(gfx::Canvas* canvas) {
-    // Use the bounds of the inkdrop. Assert that the width and height matches
-    // so we get a nice round pie.
+    // Use the bounds of the inkdrop.
     gfx::Rect bounds = button_->GetLocalBounds();
     bounds.Inset(button_->GetInkdropInsets(bounds.size()));
-    DCHECK_EQ(bounds.width(), bounds.height());
 
     // The pie is a filled arc which starts at the top and sweeps around
     // clockwise.
@@ -225,11 +225,24 @@
                                 views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE,
                                 HTMAXBUTTON),
       delegate_(delegate),
-      set_buttons_to_snap_mode_delay_ms_(kSetButtonsToSnapModeDelayMs),
-      in_snap_mode_(false) {}
+      set_buttons_to_snap_mode_delay_ms_(kSetButtonsToSnapModeDelayMs) {
+  display_observer_.emplace(this);
+}
 
 FrameSizeButton::~FrameSizeButton() = default;
 
+void FrameSizeButton::ShowMultitaskMenu() {
+  // Show Multitask Menu if float is enabled. Note here float flag is also used
+  // to represent other relatable UI/UX changes.
+  if (chromeos::wm::features::IsFloatWindowEnabled()) {
+    // Owned by the bubble which contains this view. If there is an existing
+    // bubble, it will be deactivated and then close and destroy itself.
+    auto* multitask_menu = new MultitaskMenu(
+        /*anchor=*/this, GetWidget()->GetNativeWindow());
+    multitask_menu->ShowBubble();
+  }
+}
+
 bool FrameSizeButton::OnMousePressed(const ui::MouseEvent& event) {
   // Note that this triggers `StateChanged()`, and we want the changes to
   // `pie_animation_` below to come after `StateChanged()`.
@@ -336,7 +349,7 @@
   if (!chromeos::wm::features::IsFloatWindowEnabled())
     return;
 
-  if (GetState() == views::Button::STATE_HOVERED) {
+  if (GetState() == views::Button::STATE_HOVERED && GetWidget()->IsActive()) {
     base::OnceClosure cancel_animation = base::BindOnce(
         &FrameSizeButton::DestroyPieAnimation, base::Unretained(this));
     base::OnceClosure show_multitask_menu = base::BindOnce(
@@ -357,10 +370,11 @@
   views::FrameCaptionButton::PaintButtonContents(canvas);
 }
 
-const raw_ptr<MultitaskMenu> FrameSizeButton::GetMultitaskMenuForTesting() {
-  // Force creating Multitask Menu.
-  ShowMultitaskMenu();
-  return multitask_menu_;
+void FrameSizeButton::OnDisplayTabletStateChanged(display::TabletState state) {
+  if (state == display::TabletState::kEnteringTabletMode) {
+    pie_animation_.reset();
+    set_buttons_to_snap_mode_timer_.Stop();
+  }
 }
 
 void FrameSizeButton::StartSetButtonsToSnapModeTimer(
@@ -383,18 +397,6 @@
       GetWidget()->GetNativeWindow(), this);
 }
 
-void FrameSizeButton::ShowMultitaskMenu() {
-  // Show Multitask Menu if float is enabled. Note here float flag is also used
-  // to represent other relatable UI/UX changes.
-  // TODO(shidi) Move this when long hover trigger (crbug.com/1330016) is
-  // implemented.
-  if (chromeos::wm::features::IsFloatWindowEnabled()) {
-    multitask_menu_ = new MultitaskMenu(
-        /*anchor=*/this, GetWidget()->GetNativeWindow());
-    multitask_menu_->ShowBubble();
-  }
-}
-
 void FrameSizeButton::SetButtonsToSnapMode(
     FrameSizeButtonDelegate::Animate animate) {
   in_snap_mode_ = true;
diff --git a/chromeos/ui/frame/caption_buttons/frame_size_button.h b/chromeos/ui/frame/caption_buttons/frame_size_button.h
index 964c9c20..c2cf15e2 100644
--- a/chromeos/ui/frame/caption_buttons/frame_size_button.h
+++ b/chromeos/ui/frame/caption_buttons/frame_size_button.h
@@ -13,12 +13,11 @@
 #include "chromeos/ui/frame/caption_buttons/frame_size_button_delegate.h"
 #include "chromeos/ui/frame/multitask_menu/multitask_menu.h"
 #include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/display/display_observer.h"
 #include "ui/views/window/frame_caption_button.h"
 
 namespace chromeos {
 
-class MultitaskMenu;
-
 // The maximize/restore button.
 // When the mouse is pressed over the size button or the size button is touched:
 // - The minimize and close buttons are set to snap left and snap right
@@ -28,10 +27,14 @@
 // When the drag terminates, the action for the button underneath the mouse
 // is executed. For the sake of simplicity, the size button is the event
 // handler for a click starting on the size button and the entire drag.
+// When the mouse is long pressed or long hovered over the size button, the
+// multitask menu bubble shows up.
 class COMPONENT_EXPORT(CHROMEOS_UI_FRAME) FrameSizeButton
-    : public views::FrameCaptionButton {
+    : public views::FrameCaptionButton,
+      public display::DisplayObserver {
  public:
   METADATA_HEADER(FrameSizeButton);
+
   FrameSizeButton(PressedCallback callback, FrameSizeButtonDelegate* delegate);
 
   FrameSizeButton(const FrameSizeButton&) = delete;
@@ -39,6 +42,8 @@
 
   ~FrameSizeButton() override;
 
+  void ShowMultitaskMenu();
+
   // views::Button:
   bool OnMousePressed(const ui::MouseEvent& event) override;
   bool OnMouseDragged(const ui::MouseEvent& event) override;
@@ -49,12 +54,13 @@
   void StateChanged(views::Button::ButtonState old_state) override;
   void PaintButtonContents(gfx::Canvas* canvas) override;
 
-  // Cancel the snap opereation if we're currently in snap mode. The snap
+  // display::DisplayObserver:
+  void OnDisplayTabletStateChanged(display::TabletState state) override;
+
+  // Cancel the snap operation if we're currently in snap mode. The snap
   // preview will be deleted and the button will be set back to its normal mode.
   void CancelSnap();
 
-  const raw_ptr<MultitaskMenu> GetMultitaskMenuForTesting();
-
   void set_delay_to_set_buttons_to_snap_mode(int delay_ms) {
     set_buttons_to_snap_mode_delay_ms_ = delay_ms;
   }
@@ -70,7 +76,6 @@
   // Animates the buttons adjacent to the size button to snap left and right.
   void AnimateButtonsToSnapMode();
 
-  void ShowMultitaskMenu();
   // Sets the buttons adjacent to the size button to snap left and right.
   // Passing in ANIMATE_NO progresses the animation (if any) to the end.
   void SetButtonsToSnapMode(FrameSizeButtonDelegate::Animate animate);
@@ -114,15 +119,15 @@
 
   base::OneShotTimer set_buttons_to_snap_mode_timer_;
 
-  raw_ptr<MultitaskMenu> multitask_menu_;
-
   // Creates an animation to add indication to when long hover and long press to
   // show multitask menu and snap buttons will trigger.
   std::unique_ptr<PieAnimation> pie_animation_;
 
   // Whether the buttons adjacent to the size button snap the window left and
   // right.
-  bool in_snap_mode_;
+  bool in_snap_mode_ = false;
+
+  absl::optional<display::ScopedDisplayObserver> display_observer_;
 };
 
 }  // namespace chromeos
diff --git a/chromeos/ui/frame/multitask_menu/multitask_menu.cc b/chromeos/ui/frame/multitask_menu/multitask_menu.cc
index c69634d0..d58e0a8 100644
--- a/chromeos/ui/frame/multitask_menu/multitask_menu.cc
+++ b/chromeos/ui/frame/multitask_menu/multitask_menu.cc
@@ -10,11 +10,13 @@
 #include "chromeos/ui/frame/multitask_menu/float_controller_base.h"
 #include "chromeos/ui/frame/multitask_menu/multitask_menu_view.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/display/tablet_state.h"
 #include "ui/views/layout/table_layout.h"
 
 namespace chromeos {
 
 namespace {
+
 constexpr int kMultitaskMenuBubbleCornerRadius = 8;
 constexpr int kRowPadding = 16;
 constexpr int KMultitaskMenuWidth = 270;
@@ -24,15 +26,17 @@
 
 MultitaskMenu::MultitaskMenu(views::View* anchor, aura::Window* parent_window) {
   DCHECK(parent_window);
-  SetAnchorView(anchor);
-  SetPaintToLayer();
+
   set_corner_radius(kMultitaskMenuBubbleCornerRadius);
+  set_close_on_deactivate(true);
+  set_internal_name("MultitaskMenuBubbleWidget");
+  set_parent_window(parent_window);
+
+  SetAnchorView(anchor);
   // TODO(shidi): Confirm with UX/UI for additional arrow choices when parent
   // window has no space for `MultitaskMenu` to arrow at `TOP_CENTER`.
   SetArrow(views::BubbleBorder::Arrow::TOP_CENTER);
   SetButtons(ui::DIALOG_BUTTON_NONE);
-  set_parent_window(parent_window);
-  set_close_on_deactivate(true);
   SetPreferredSize(gfx::Size(KMultitaskMenuWidth, kMultitaskMenuHeight));
   SetUseDefaultFillLayout(true);
 
@@ -56,12 +60,12 @@
       .AddRows(1, views::TableLayout::kFixedSize, 0)
       .AddPaddingRow(views::TableLayout::kFixedSize, kRowPadding)
       .AddRows(1, views::TableLayout::kFixedSize, 0);
+
+  display_observer_.emplace(this);
 }
 
 MultitaskMenu::~MultitaskMenu() {
-  if (bubble_widget_)
-    HideBubble();
-  bubble_widget_ = nullptr;
+  HideBubble();
 }
 
 void MultitaskMenu::OnWidgetDestroying(views::Widget* widget) {
@@ -70,6 +74,11 @@
   bubble_widget_ = nullptr;
 }
 
+void MultitaskMenu::OnDisplayTabletStateChanged(display::TabletState state) {
+  if (state == display::TabletState::kEnteringTabletMode)
+    HideBubble();
+}
+
 void MultitaskMenu::ShowBubble() {
   DCHECK(parent_window());
   bubble_widget_ = views::BubbleDialogDelegateView::CreateBubble(this);
@@ -86,7 +95,6 @@
 }
 
 void MultitaskMenu::HideBubble() {
-  DCHECK(bubble_widget_);
   // This calls into OnWidgetDestroying() so `bubble_widget_` should have been
   // reset to nullptr.
   if (bubble_widget_ && !bubble_widget_->IsClosed())
diff --git a/chromeos/ui/frame/multitask_menu/multitask_menu.h b/chromeos/ui/frame/multitask_menu/multitask_menu.h
index 89860f2..f9157ce 100644
--- a/chromeos/ui/frame/multitask_menu/multitask_menu.h
+++ b/chromeos/ui/frame/multitask_menu/multitask_menu.h
@@ -9,6 +9,7 @@
 #include "chromeos/ui/frame/caption_buttons/snap_controller.h"
 #include "chromeos/ui/frame/multitask_menu/multitask_menu_view.h"
 #include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/display/display_observer.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
 
 namespace views {
@@ -22,7 +23,8 @@
 // size button.
 class COMPONENT_EXPORT(CHROMEOS_UI_FRAME) MultitaskMenu
     : public views::BubbleDialogDelegateView,
-      public views::WidgetObserver {
+      public views::WidgetObserver,
+      public display::DisplayObserver {
  public:
   METADATA_HEADER(MultitaskMenu);
 
@@ -33,17 +35,19 @@
 
   ~MultitaskMenu() override;
 
-  views::Widget* bubble_widget_for_testing() { return bubble_widget_.get(); }
-
   // views::WidgetObserver:
   void OnWidgetDestroying(views::Widget* widget) override;
 
+  // display::DisplayObserver:
+  void OnDisplayTabletStateChanged(display::TabletState state) override;
+
   // Displays the MultitaskMenu.
   void ShowBubble();
 
   // Hides the currently-showing MultitaskMenu.
   void HideBubble();
 
+  views::Widget* bubble_widget_for_testing() { return bubble_widget_.get(); }
   MultitaskMenuView* multitask_menu_view_for_testing() {
     return multitask_menu_view_.get();
   }
@@ -53,7 +57,9 @@
   base::ScopedObservation<views::Widget, views::WidgetObserver>
       bubble_widget_observer_{this};
 
-  raw_ptr<MultitaskMenuView> multitask_menu_view_;
+  raw_ptr<MultitaskMenuView> multitask_menu_view_ = nullptr;
+
+  absl::optional<display::ScopedDisplayObserver> display_observer_;
 };
 
 }  // namespace chromeos
diff --git a/components/bookmarks/browser/bookmark_codec.cc b/components/bookmarks/browser/bookmark_codec.cc
index 81911c5..e9ab5c3 100644
--- a/components/bookmarks/browser/bookmark_codec.cc
+++ b/components/bookmarks/browser/bookmark_codec.cc
@@ -14,6 +14,7 @@
 #include "base/containers/contains.h"
 #include "base/guid.h"
 #include "base/json/json_string_value_serializer.h"
+#include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -45,6 +46,7 @@
 const char BookmarkCodec::kDateModifiedKey[] = "date_modified";
 const char BookmarkCodec::kChildrenKey[] = "children";
 const char BookmarkCodec::kMetaInfo[] = "meta_info";
+const char BookmarkCodec::kUnsyncedMetaInfo[] = "unsynced_meta_info";
 const char BookmarkCodec::kTypeURL[] = "url";
 const char BookmarkCodec::kTypeFolder[] = "folder";
 const char BookmarkCodec::kSyncMetadata[] = "sync_metadata";
@@ -77,6 +79,7 @@
                                   std::string sync_metadata_str) {
   return Encode(model->bookmark_bar_node(), model->other_node(),
                 model->mobile_node(), model->root_node()->GetMetaInfoMap(),
+                model->root_node()->GetUnsyncedMetaInfoMap(),
                 std::move(sync_metadata_str));
 }
 
@@ -85,6 +88,7 @@
     const BookmarkNode* other_folder_node,
     const BookmarkNode* mobile_folder_node,
     const BookmarkNode::MetaInfoMap* model_meta_info_map,
+    const BookmarkNode::MetaInfoMap* model_unsynced_meta_info_map,
     std::string sync_metadata_str) {
   ids_reassigned_ = false;
   guids_reassigned_ = false;
@@ -107,6 +111,11 @@
   roots.SetKey(kMobileBookmarkFolderNameKey, EncodeNode(mobile_folder_node));
   if (model_meta_info_map)
     roots.SetKey(kMetaInfo, EncodeMetaInfo(*model_meta_info_map));
+  if (model_unsynced_meta_info_map) {
+    roots.SetKey(kUnsyncedMetaInfo,
+                 EncodeMetaInfo(*model_unsynced_meta_info_map));
+  }
+
   FinalizeChecksum();
   // We are going to store the computed checksum. So set stored checksum to be
   // the same as computed checksum.
@@ -180,6 +189,10 @@
   const BookmarkNode::MetaInfoMap* meta_info_map = node->GetMetaInfoMap();
   if (meta_info_map)
     value.SetKey(kMetaInfo, EncodeMetaInfo(*meta_info_map));
+  const BookmarkNode::MetaInfoMap* unsynced_meta_info_map =
+      node->GetUnsyncedMetaInfoMap();
+  if (unsynced_meta_info_map)
+    value.SetKey(kUnsyncedMetaInfo, EncodeMetaInfo(*unsynced_meta_info_map));
   return value;
 }
 
@@ -230,6 +243,8 @@
 
   if (!DecodeMetaInfo(*roots, &model_meta_info_map_))
     return false;
+  if (!DecodeUnsyncedMetaInfo(*roots, &model_unsynced_meta_info_map_))
+    return false;
 
   if (sync_metadata_str) {
     const std::string* sync_metadata_str_base64 =
@@ -412,6 +427,11 @@
     return false;
   node->SetMetaInfoMap(meta_info_map);
 
+  BookmarkNode::MetaInfoMap unsynced_meta_info_map;
+  if (!DecodeUnsyncedMetaInfo(value, &unsynced_meta_info_map))
+    return false;
+  node->SetUnsyncedMetaInfoMap(unsynced_meta_info_map);
+
   return true;
 }
 
@@ -447,6 +467,24 @@
   return true;
 }
 
+bool BookmarkCodec::DecodeUnsyncedMetaInfo(
+    const base::Value& value,
+    BookmarkNode::MetaInfoMap* meta_info_map) {
+  DCHECK(value.is_dict());
+  DCHECK(meta_info_map);
+  meta_info_map->clear();
+
+  const base::Value* meta_info = value.FindKey(kUnsyncedMetaInfo);
+  if (!meta_info)
+    return true;
+  if (!meta_info->is_dict())
+    return false;
+
+  DecodeMetaInfoHelper(*meta_info, std::string(), meta_info_map);
+
+  return true;
+}
+
 void BookmarkCodec::DecodeMetaInfoHelper(
     const base::Value& dict,
     const std::string& prefix,
diff --git a/components/bookmarks/browser/bookmark_codec.h b/components/bookmarks/browser/bookmark_codec.h
index 5511c604..9b32105 100644
--- a/components/bookmarks/browser/bookmark_codec.h
+++ b/components/bookmarks/browser/bookmark_codec.h
@@ -45,11 +45,13 @@
   base::Value Encode(BookmarkModel* model, std::string sync_metadata_str);
 
   // Encodes the bookmark bar and other folders returning the JSON value.
-  base::Value Encode(const BookmarkNode* bookmark_bar_node,
-                     const BookmarkNode* other_folder_node,
-                     const BookmarkNode* mobile_folder_node,
-                     const BookmarkNode::MetaInfoMap* model_meta_info_map,
-                     std::string sync_metadata_str);
+  base::Value Encode(
+      const BookmarkNode* bookmark_bar_node,
+      const BookmarkNode* other_folder_node,
+      const BookmarkNode* mobile_folder_node,
+      const BookmarkNode::MetaInfoMap* model_meta_info_map,
+      const BookmarkNode::MetaInfoMap* model_unsynced_meta_info_map,
+      std::string sync_metadata_str);
 
   // Decodes the previously encoded value to the specified nodes as well as
   // setting |max_node_id| to the greatest node id. Returns true on success,
@@ -78,6 +80,11 @@
     return model_meta_info_map_;
   }
 
+  // Return the unsynced meta info of bookmark model root.
+  const BookmarkNode::MetaInfoMap& model_unsynced_meta_info_map() const {
+    return model_unsynced_meta_info_map_;
+  }
+
   // Returns whether the IDs were reassigned during decoding. Always returns
   // false after encoding.
   bool ids_reassigned() const { return ids_reassigned_; }
@@ -102,6 +109,7 @@
   static const char kDateModifiedKey[];
   static const char kChildrenKey[];
   static const char kMetaInfo[];
+  static const char kUnsyncedMetaInfo[];
   // Allows the BookmarkClient to read and a write a string blob from the JSON
   // file. That string captures the bookmarks sync metadata.
   static const char kSyncMetadata[];
@@ -151,6 +159,11 @@
   bool DecodeMetaInfo(const base::Value& value,
                       BookmarkNode::MetaInfoMap* meta_info_map);
 
+  // Decodes the unsynced meta info from the supplied value. meta_info_map must
+  // not be nullptr.
+  bool DecodeUnsyncedMetaInfo(const base::Value& value,
+                              BookmarkNode::MetaInfoMap* meta_info_map);
+
   // Decodes the meta info from the supplied sub-node dictionary. The values
   // found will be inserted in meta_info_map with the given prefix added to the
   // start of their keys.
@@ -208,6 +221,9 @@
 
   // Meta info set on bookmark model root.
   BookmarkNode::MetaInfoMap model_meta_info_map_;
+
+  // Unsynced meta info set on bookmark model root.
+  BookmarkNode::MetaInfoMap model_unsynced_meta_info_map_;
 };
 
 }  // namespace bookmarks
diff --git a/components/bookmarks/browser/bookmark_codec_unittest.cc b/components/bookmarks/browser/bookmark_codec_unittest.cc
index 9376829..5c74bc8 100644
--- a/components/bookmarks/browser/bookmark_codec_unittest.cc
+++ b/components/bookmarks/browser/bookmark_codec_unittest.cc
@@ -172,6 +172,8 @@
                                 sync_metadata_str);
     model->set_next_node_id(max_id);
     AsMutable(model->root_node())->SetMetaInfoMap(codec->model_meta_info_map());
+    AsMutable(model->root_node())
+        ->SetUnsyncedMetaInfoMap(codec->model_unsynced_meta_info_map());
 
     return result;
   }
@@ -418,6 +420,34 @@
   EXPECT_FALSE(child->GetMetaInfo("other_key", &meta_value));
 }
 
+TEST_F(BookmarkCodecTest, EncodeAndDecodeUnsyncedMetaInfo) {
+  // Add meta info and encode.
+  std::unique_ptr<BookmarkModel> model(CreateTestModel1());
+  model->SetNodeUnsyncedMetaInfo(model->root_node(), "model_info", "value1");
+  model->SetNodeUnsyncedMetaInfo(
+      model->bookmark_bar_node()->children().front().get(), "node_info",
+      "value2");
+  std::string checksum;
+  base::Value value =
+      EncodeHelper(model.get(), /*sync_metadata_str=*/std::string(), &checksum);
+
+  // Decode and check for meta info.
+  model = DecodeHelper(value, checksum, &checksum, false,
+                       /*sync_metadata_str=*/nullptr);
+  std::string meta_value;
+  EXPECT_TRUE(
+      model->root_node()->GetUnsyncedMetaInfo("model_info", &meta_value));
+  EXPECT_EQ("value1", meta_value);
+  EXPECT_FALSE(
+      model->root_node()->GetUnsyncedMetaInfo("other_key", &meta_value));
+  const BookmarkNode* bbn = model->bookmark_bar_node();
+  ASSERT_EQ(1u, bbn->children().size());
+  const BookmarkNode* child = bbn->children().front().get();
+  EXPECT_TRUE(child->GetUnsyncedMetaInfo("node_info", &meta_value));
+  EXPECT_EQ("value2", meta_value);
+  EXPECT_FALSE(child->GetUnsyncedMetaInfo("other_key", &meta_value));
+}
+
 // Verifies that we can still decode the old codec format after changing the
 // way meta info is stored.
 TEST_F(BookmarkCodecTest, CanDecodeMetaInfoAsString) {
diff --git a/components/bookmarks/browser/bookmark_load_details.h b/components/bookmarks/browser/bookmark_load_details.h
index 830826e..9435c319 100644
--- a/components/bookmarks/browser/bookmark_load_details.h
+++ b/components/bookmarks/browser/bookmark_load_details.h
@@ -57,6 +57,13 @@
   void set_model_meta_info_map(const BookmarkNode::MetaInfoMap& meta_info_map) {
     model_meta_info_map_ = meta_info_map;
   }
+  const BookmarkNode::MetaInfoMap& model_unsynced_meta_info_map() const {
+    return model_unsynced_meta_info_map_;
+  }
+  void set_model_unsynced_meta_info_map(
+      const BookmarkNode::MetaInfoMap& model_unsynced_meta_info_map) {
+    model_unsynced_meta_info_map_ = model_unsynced_meta_info_map;
+  }
 
   // Max id of the nodes.
   void set_max_id(int64_t max_id) { max_id_ = max_id; }
@@ -106,6 +113,7 @@
   LoadManagedNodeCallback load_managed_node_callback_;
   std::unique_ptr<TitledUrlIndex> index_;
   BookmarkNode::MetaInfoMap model_meta_info_map_;
+  BookmarkNode::MetaInfoMap model_unsynced_meta_info_map_;
   int64_t max_id_ = 1;
   std::string computed_checksum_;
   std::string stored_checksum_;
diff --git a/components/bookmarks/browser/bookmark_model.cc b/components/bookmarks/browser/bookmark_model.cc
index 2d91c6d..b1763f4 100644
--- a/components/bookmarks/browser/bookmark_model.cc
+++ b/components/bookmarks/browser/bookmark_model.cc
@@ -527,6 +527,48 @@
     observer.BookmarkMetaInfoChanged(this, node);
 }
 
+void BookmarkModel::SetNodeUnsyncedMetaInfo(const BookmarkNode* node,
+                                            const std::string& key,
+                                            const std::string& value) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  std::string old_value;
+  if (node->GetUnsyncedMetaInfo(key, &old_value) && old_value == value)
+    return;
+
+  if (AsMutable(node)->SetUnsyncedMetaInfo(key, value) && store_.get())
+    store_->ScheduleSave();
+}
+
+void BookmarkModel::SetNodeUnsyncedMetaInfoMap(
+    const BookmarkNode* node,
+    const BookmarkNode::MetaInfoMap& meta_info_map) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  const BookmarkNode::MetaInfoMap* old_meta_info_map =
+      node->GetUnsyncedMetaInfoMap();
+  if ((!old_meta_info_map && meta_info_map.empty()) ||
+      (old_meta_info_map && meta_info_map == *old_meta_info_map))
+    return;
+
+  AsMutable(node)->SetUnsyncedMetaInfoMap(meta_info_map);
+  if (store_)
+    store_->ScheduleSave();
+}
+
+void BookmarkModel::DeleteUnsyncedNodeMetaInfo(const BookmarkNode* node,
+                                               const std::string& key) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  const BookmarkNode::MetaInfoMap* meta_info_map =
+      node->GetUnsyncedMetaInfoMap();
+  if (!meta_info_map || meta_info_map->find(key) == meta_info_map->end())
+    return;
+
+  if (AsMutable(node)->DeleteUnsyncedMetaInfo(key) && store_.get())
+    store_->ScheduleSave();
+}
+
 void BookmarkModel::AddNonClonedKey(const std::string& key) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   non_cloned_keys_.insert(key);
diff --git a/components/bookmarks/browser/bookmark_model.h b/components/bookmarks/browser/bookmark_model.h
index c74d4ee..3427ede2 100644
--- a/components/bookmarks/browser/bookmark_model.h
+++ b/components/bookmarks/browser/bookmark_model.h
@@ -307,6 +307,16 @@
   void DeleteNodeMetaInfo(const BookmarkNode* node,
                           const std::string& key);
 
+  // Sets/deletes local meta info of |node|.
+  void SetNodeUnsyncedMetaInfo(const BookmarkNode* node,
+                               const std::string& key,
+                               const std::string& value);
+  void SetNodeUnsyncedMetaInfoMap(
+      const BookmarkNode* node,
+      const BookmarkNode::MetaInfoMap& meta_info_map);
+  void DeleteUnsyncedNodeMetaInfo(const BookmarkNode* node,
+                                  const std::string& key);
+
   // Adds |key| to the set of meta info keys that are not copied when a node is
   // cloned.
   void AddNonClonedKey(const std::string& key);
diff --git a/components/bookmarks/browser/bookmark_node.cc b/components/bookmarks/browser/bookmark_node.cc
index ee34fb2..c4a00851 100644
--- a/components/bookmarks/browser/bookmark_node.cc
+++ b/components/bookmarks/browser/bookmark_node.cc
@@ -136,6 +136,56 @@
   return meta_info_map_.get();
 }
 
+bool BookmarkNode::GetUnsyncedMetaInfo(const std::string& key,
+                                       std::string* value) const {
+  if (!unsynced_meta_info_map_)
+    return false;
+
+  MetaInfoMap::const_iterator it = unsynced_meta_info_map_->find(key);
+  if (it == unsynced_meta_info_map_->end())
+    return false;
+
+  *value = it->second;
+  return true;
+}
+
+bool BookmarkNode::SetUnsyncedMetaInfo(const std::string& key,
+                                       const std::string& value) {
+  if (!unsynced_meta_info_map_)
+    unsynced_meta_info_map_ = std::make_unique<MetaInfoMap>();
+
+  auto it = unsynced_meta_info_map_->find(key);
+  if (it == unsynced_meta_info_map_->end()) {
+    (*unsynced_meta_info_map_)[key] = value;
+    return true;
+  }
+  // Key already in map, check if the value has changed.
+  if (it->second == value)
+    return false;
+  it->second = value;
+  return true;
+}
+
+bool BookmarkNode::DeleteUnsyncedMetaInfo(const std::string& key) {
+  if (!unsynced_meta_info_map_)
+    return false;
+  bool erased = unsynced_meta_info_map_->erase(key) != 0;
+  if (unsynced_meta_info_map_->empty())
+    unsynced_meta_info_map_.reset();
+  return erased;
+}
+
+void BookmarkNode::SetUnsyncedMetaInfoMap(const MetaInfoMap& meta_info_map) {
+  if (meta_info_map.empty())
+    unsynced_meta_info_map_.reset();
+  else
+    unsynced_meta_info_map_ = std::make_unique<MetaInfoMap>(meta_info_map);
+}
+
+const BookmarkNode::MetaInfoMap* BookmarkNode::GetUnsyncedMetaInfoMap() const {
+  return unsynced_meta_info_map_.get();
+}
+
 const std::u16string& BookmarkNode::GetTitledUrlNodeTitle() const {
   return GetTitle();
 }
diff --git a/components/bookmarks/browser/bookmark_node.h b/components/bookmarks/browser/bookmark_node.h
index f3332fb..af43d06 100644
--- a/components/bookmarks/browser/bookmark_node.h
+++ b/components/bookmarks/browser/bookmark_node.h
@@ -7,10 +7,10 @@
 
 #include <stdint.h>
 
-#include <map>
 #include <memory>
 #include <string>
 
+#include "base/containers/flat_map.h"
 #include "base/guid.h"
 #include "base/strings/string_piece.h"
 #include "base/task/cancelable_task_tracker.h"
@@ -44,7 +44,7 @@
     LOADED_FAVICON,
   };
 
-  typedef std::map<std::string, std::string> MetaInfoMap;
+  typedef base::flat_map<std::string, std::string> MetaInfoMap;
 
   // TODO(crbug.com/1026195): Make these constants of type base::GUID once there
   // exists a constexpr constructor.
@@ -123,7 +123,7 @@
   // representation but we may want to suppress some nodes.
   virtual bool IsVisible() const;
 
-  // Gets/sets/deletes value of |key| in the meta info represented by
+  // Gets/sets/deletes value of |key| in the synced meta info represented by
   // |meta_info_str_|. Return true if key is found in meta info for gets or
   // meta info is changed indeed for sets/deletes.
   bool GetMetaInfo(const std::string& key, std::string* value) const;
@@ -133,6 +133,16 @@
   // Returns NULL if there are no values in the map.
   const MetaInfoMap* GetMetaInfoMap() const;
 
+  // Gets/sets/deletes value of `key` in the local meta info represented by
+  // `meta_info_str_`. Return true if key is found in meta info for gets or
+  // meta info is changed indeed for sets/deletes.
+  bool GetUnsyncedMetaInfo(const std::string& key, std::string* value) const;
+  bool SetUnsyncedMetaInfo(const std::string& key, const std::string& value);
+  bool DeleteUnsyncedMetaInfo(const std::string& key);
+  void SetUnsyncedMetaInfoMap(const MetaInfoMap& meta_info_map);
+  // Returns NULL if there are no values in the map.
+  const MetaInfoMap* GetUnsyncedMetaInfoMap() const;
+
   // TitledUrlNode interface methods.
   const std::u16string& GetTitledUrlNodeTitle() const override;
   const GURL& GetTitledUrlNodeUrl() const override;
@@ -218,8 +228,12 @@
   base::CancelableTaskTracker::TaskId favicon_load_task_id_ =
       base::CancelableTaskTracker::kBadTaskId;
 
-  // A map that stores arbitrary meta information about the node.
+  // A map that stores arbitrary meta information about the node. This map is
+  // synced to other devices.
   std::unique_ptr<MetaInfoMap> meta_info_map_;
+  // A map that stores arbitrary meta information about the node. This map is
+  // local-only and won't be synced.
+  std::unique_ptr<MetaInfoMap> unsynced_meta_info_map_;
 
   const bool is_permanent_node_;
 
diff --git a/components/bookmarks/browser/model_loader.cc b/components/bookmarks/browser/model_loader.cc
index 74f3719..9d0d0a45 100644
--- a/components/bookmarks/browser/model_loader.cc
+++ b/components/bookmarks/browser/model_loader.cc
@@ -66,6 +66,8 @@
       details->set_ids_reassigned(codec.ids_reassigned());
       details->set_guids_reassigned(codec.guids_reassigned());
       details->set_model_meta_info_map(codec.model_meta_info_map());
+      details->set_model_unsynced_meta_info_map(
+          codec.model_unsynced_meta_info_map());
 
       load_index = true;
     }
diff --git a/components/history_clusters/core/config.cc b/components/history_clusters/core/config.cc
index 7ba3b8e..bc2730a 100644
--- a/components/history_clusters/core/config.cc
+++ b/components/history_clusters/core/config.cc
@@ -107,6 +107,18 @@
   omnibox_history_cluster_provider =
       base::FeatureList::IsEnabled(internal::kOmniboxHistoryClusterProvider);
 
+  omnibox_history_cluster_provider_score =
+      base::GetFieldTrialParamByFeatureAsInt(
+          internal::kOmniboxHistoryClusterProvider,
+          "omnibox_history_cluster_provider_score",
+          omnibox_history_cluster_provider_score);
+
+  omnibox_history_cluster_provider_shortcuts =
+      base::GetFieldTrialParamByFeatureAsBool(
+          internal::kOmniboxHistoryClusterProvider,
+          "omnibox_history_cluster_provider_shortcuts",
+          omnibox_history_cluster_provider_shortcuts);
+
   keyword_filter_on_entity_aliases = base::GetFieldTrialParamByFeatureAsBool(
       history_clusters::features::kOnDeviceClusteringKeywordFiltering,
       "keyword_filter_on_entity_aliases", keyword_filter_on_entity_aliases);
diff --git a/components/history_clusters/core/config.h b/components/history_clusters/core/config.h
index e8ec44a..5c8e015 100644
--- a/components/history_clusters/core/config.h
+++ b/components/history_clusters/core/config.h
@@ -119,6 +119,26 @@
   // only have 1 enabled.
   bool omnibox_history_cluster_provider = false;
 
+  // The score the `HistoryClusterProvider` will assign to journey suggestions.
+  // Meaningless if `omnibox_history_cluster_provider` is disabled. 900 seems to
+  // work well in local tests. It's high enough to outscore search suggestions
+  // and therefore not be crowded out, but low enough to only display when there
+  // aren't too many strong navigation matches.
+  int omnibox_history_cluster_provider_score = 900;
+
+  // Whether Journey suggestions from the `HistoryClusterProvider` can be
+  // surfaced from the shortcuts' provider. They will be scored according to the
+  // shortcuts' provider's scoring, which is more aggressive than the default
+  // 900 score the `HistoryClusterProvider` assigns. Journey suggestions will
+  // still be limited to 1, and will still be locked to the last suggestion
+  // slot. More aggressive scoring won't affect ranking, but visibility. If
+  // disabled, journey suggestions will still be added to the table, but
+  // filtered out when retrieving suggesting; this is so that users in an
+  // experiment group with `omnibox_history_cluster_provider_shortcuts` enabled
+  // don't have lingering effects when they leave the group. Meaningless if
+  // `omnibox_history_cluster_provider` is disabled.
+  bool omnibox_history_cluster_provider_shortcuts = false;
+
   // If enabled, adds the keywords of aliases for detected entity names to a
   // cluster.
   bool keyword_filter_on_entity_aliases = false;
@@ -309,8 +329,7 @@
 bool IsJourneysEnabledInOmnibox(HistoryClustersService* service,
                                 PrefService* prefs);
 
-// Gets the current configuration. OverrideWithFinch() must have been called
-// before GetConfig() is called.
+// Gets the current configuration.
 const Config& GetConfig();
 
 // Overrides the config returned by |GetConfig()|.
diff --git a/components/metrics/structured/event.cc b/components/metrics/structured/event.cc
index ef2010a..85163bb 100644
--- a/components/metrics/structured/event.cc
+++ b/components/metrics/structured/event.cc
@@ -8,11 +8,11 @@
 #include <memory>
 #include <string>
 
+#include "base/system/sys_info.h"
 #include "base/values.h"
 #include "components/metrics/structured/structured_metrics_client.h"
 
-namespace metrics {
-namespace structured {
+namespace metrics::structured {
 
 Event::MetricValue::MetricValue(MetricType type, base::Value value)
     : type(type), value(std::move(value)) {}
@@ -34,7 +34,8 @@
 
 Event::Event(Event&& other)
     : project_name_(std::move(other.project_name_)),
-      event_name_(std::move(other.event_name_)) {
+      event_name_(std::move(other.event_name_)),
+      recorded_time_since_boot_(std::move(other.recorded_time_since_boot_)) {
   metric_values_.insert(std::make_move_iterator(other.metric_values_.begin()),
                         std::make_move_iterator(other.metric_values_.end()));
 }
@@ -44,10 +45,16 @@
   event_name_ = std::move(other.event_name_);
   metric_values_.insert(std::make_move_iterator(other.metric_values_.begin()),
                         std::make_move_iterator(other.metric_values_.end()));
+  recorded_time_since_boot_ = std::move(other.recorded_time_since_boot_);
   return *this;
 }
 
+bool Event::IsCrOSEvent() const {
+  return false;
+}
+
 void Event::Record() {
+  recorded_time_since_boot_ = base::SysInfo::Uptime();
   StructuredMetricsClient::Get()->Record(std::move(*this));
 }
 
@@ -63,6 +70,10 @@
   return metric_values_;
 }
 
+base::TimeDelta Event::recorded_time_since_boot() const {
+  return recorded_time_since_boot_;
+}
+
 bool Event::AddMetric(const std::string& metric_name,
                       Event::MetricType type,
                       base::Value&& value) {
@@ -96,5 +107,4 @@
   return pair.second;
 }
 
-}  // namespace structured
-}  // namespace metrics
+}  // namespace metrics::structured
diff --git a/components/metrics/structured/event.h b/components/metrics/structured/event.h
index ca76dcc..995eaa5 100644
--- a/components/metrics/structured/event.h
+++ b/components/metrics/structured/event.h
@@ -9,17 +9,18 @@
 #include <memory>
 #include <string>
 
+#include "base/time/time.h"
 #include "base/values.h"
 
-// Builder classes for sending events are generated in the similarily-named
-// //components/metrics/structured/structured_events.h.
+// Builder classes for sending events are generated in
+// //components/metrics/structured/structured_events.h based on XML
+// configuration.
 //
-// Builder classes will generate subclasses of |Event| rather than |EventBase|
-// once the mojo implementation of structured metrics is complete. |EventBase|
-// will only be used by the central service to record events.
+// Note that |EventBase| is only be used by the central service to record
+// events. TODO(jongahn): Investigate whether it's even necessary to convert to
+// EventBase when persisting events.
 
-namespace metrics {
-namespace structured {
+namespace metrics::structured {
 
 // Event to be built and sent by StructuredMetrics clients. Builder
 // classes will be codegen'd from metrics definitions in structured.xml, but
@@ -61,6 +62,8 @@
 
   virtual ~Event();
 
+  virtual bool IsCrOSEvent() const;
+
   // Records |this|. Once this method is called, |this| will be unsafe to
   // access.
   void Record();
@@ -76,13 +79,17 @@
   const std::string& event_name() const;
   const std::map<std::string, MetricValue>& metric_values() const;
 
+  base::TimeDelta recorded_time_since_boot() const;
+
  private:
   std::string project_name_;
   std::string event_name_;
   std::map<std::string, MetricValue> metric_values_;
+
+  // System uptime for which the event was recorded.
+  base::TimeDelta recorded_time_since_boot_;
 };
 
-}  // namespace structured
-}  // namespace metrics
+}  // namespace metrics::structured
 
 #endif  // COMPONENTS_METRICS_STRUCTURED_EVENT_H_
diff --git a/components/metrics/structured/event_base.h b/components/metrics/structured/event_base.h
index b33cf703..e31c4ea 100644
--- a/components/metrics/structured/event_base.h
+++ b/components/metrics/structured/event_base.h
@@ -17,8 +17,11 @@
 namespace metrics {
 namespace structured {
 
-// A base class for generated structured metrics event objects. This class
-// should not be used directly.
+// All events must be converted to EventBase to be recorded and persisted to
+// disk.
+//
+// TODO(jongahn): Write directly from Event to disk without making this
+// conversion.
 class EventBase {
  public:
   EventBase(const EventBase& other);
diff --git a/components/metrics/structured/structured_metrics_features.cc b/components/metrics/structured/structured_metrics_features.cc
index b85090a..290929e6 100644
--- a/components/metrics/structured/structured_metrics_features.cc
+++ b/components/metrics/structured/structured_metrics_features.cc
@@ -12,6 +12,9 @@
 const base::Feature kStructuredMetrics{"EnableStructuredMetrics",
                                        base::FEATURE_ENABLED_BY_DEFAULT};
 
+const base::Feature kCrOSEvents{"EnableCrOSEvents",
+                                base::FEATURE_DISABLED_BY_DEFAULT};
+
 // TODO(b/181724341): Remove this experimental once the feature is rolled out.
 const base::Feature kBluetoothSessionizedMetrics{
     "BluetoothSessionizedMetrics", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/components/metrics/structured/structured_metrics_features.h b/components/metrics/structured/structured_metrics_features.h
index 17c08f0..2eed7f1 100644
--- a/components/metrics/structured/structured_metrics_features.h
+++ b/components/metrics/structured/structured_metrics_features.h
@@ -13,6 +13,9 @@
 // This can be used to disable structured metrics as a whole.
 extern const base::Feature kStructuredMetrics;
 
+// Controls whether CrOSEvents logging is enabled or not.
+extern const base::Feature kCrOSEvents;
+
 extern const base::Feature kBluetoothSessionizedMetrics;
 
 // Delays appending structured metrics events until HWID has been loaded.
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc
index 4f2b56c..0b5bba2 100644
--- a/components/omnibox/browser/autocomplete_controller.cc
+++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -933,8 +933,8 @@
     result_.AttachPedalsToMatches(input_, *provider_client_);
   }
 
-  // Need to validate before invoking CopyOldMatches as the old matches are not
-  // valid against the current input.
+  // Need to validate before invoking `TransferOldMatches()` as the old matches
+  // are not valid against the current input.
 #if DCHECK_IS_ON()
   result_.Validate();
 #endif  // DCHECK_IS_ON()
diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc
index af6d955..e33d102 100644
--- a/components/omnibox/browser/autocomplete_result.cc
+++ b/components/omnibox/browser/autocomplete_result.cc
@@ -15,6 +15,7 @@
 #include "base/containers/adapters.h"
 #include "base/containers/contains.h"
 #include "base/containers/cxx20_erase.h"
+#include "base/containers/cxx20_erase_vector.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/notreached.h"
@@ -317,6 +318,22 @@
       matches_[0].ComputeStrippedDestinationURL(input, template_url_service);
   }
 
+  // Limit history cluster suggestions to 1. This has to be done before limiting
+  // URL matches below so that a to-be-removed history cluster suggestion
+  // doesn't waste a URL slot.
+  bool history_cluster_included = false;
+  base::EraseIf(matches_, [&](const auto& match) {
+    // If not a history cluster match, don't erase it.
+    if (match.type != AutocompleteMatch::Type::HISTORY_CLUSTER)
+      return false;
+    // If not the 1st history cluster match, do erase it.
+    if (history_cluster_included)
+      return true;
+    // If the 1st history cluster match, don't erase it.
+    history_cluster_included = true;
+    return false;
+  });
+
   // Limit URL matches per OmniboxMaxURLMatches.
   size_t max_url_count = 0;
   bool is_zero_suggest = input.focus_type() != OmniboxFocusType::DEFAULT;
diff --git a/components/omnibox/browser/autocomplete_result_unittest.cc b/components/omnibox/browser/autocomplete_result_unittest.cc
index 372eea6b..dc0ef353 100644
--- a/components/omnibox/browser/autocomplete_result_unittest.cc
+++ b/components/omnibox/browser/autocomplete_result_unittest.cc
@@ -2178,6 +2178,28 @@
                       AutocompleteResult::GetMaxMatches());
 }
 
+TEST_F(AutocompleteResultTest, SortAndCullMaxHistoryClusterSuggestions) {
+  // Should limit history cluster suggestions to 1, even if there are no
+  // alternative suggestions to display.
+
+  ACMatches matches;
+  const AutocompleteMatchTestData data[] = {
+      {"url_1", AutocompleteMatchType::HISTORY_CLUSTER},
+      {"url_2", AutocompleteMatchType::HISTORY_CLUSTER},
+      {"url_3", AutocompleteMatchType::HISTORY_CLUSTER},
+  };
+  PopulateAutocompleteMatchesFromTestData(data, std::size(data), &matches);
+
+  AutocompleteInput input(u"a", metrics::OmniboxEventProto::OTHER,
+                          TestSchemeClassifier());
+  AutocompleteResult result;
+  result.AppendMatches(matches);
+  result.SortAndCull(input, template_url_service_.get());
+
+  ASSERT_EQ(result.size(), 1u);
+  EXPECT_EQ(result.match_at(0)->type, AutocompleteMatchType::HISTORY_CLUSTER);
+}
+
 TEST_F(AutocompleteResultTest, SortAndCullMaxURLMatches) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeaturesAndParameters(
diff --git a/components/omnibox/browser/history_cluster_provider.cc b/components/omnibox/browser/history_cluster_provider.cc
index bf64a940..0c0a9704 100644
--- a/components/omnibox/browser/history_cluster_provider.cc
+++ b/components/omnibox/browser/history_cluster_provider.cc
@@ -120,16 +120,13 @@
   match.provider = this;
   match.type = AutocompleteMatch::Type::HISTORY_CLUSTER;
 
-  // 900 seems to work well in local tests. It's high enough to
-  // outscore search suggestions and therefore not be crowded out, but low
-  // enough to only display when there aren't too many strong navigation
-  // matches.
   // TODO(manukh): Currently, history cluster suggestions only display when the
   //  `text` is an exact match of a cluster keyword, and all cluster keywords
   //  are treated equal. Therefore, we're limited to using a static value.
   //  Ideally, relevance would depend on how many keywords matched, how
   //  significant the keywords were, how significant their clusters were etc.
-  match.relevance = 900;
+  match.relevance =
+      history_clusters::GetConfig().omnibox_history_cluster_provider_score;
 
   match.fill_into_edit = base::UTF8ToUTF16(base::StringPrintf(
       "chrome://history/journeys?q=%s", base::UTF16ToUTF8(text).c_str()));
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc
index 80f8efa..9d3f7ba 100644
--- a/components/omnibox/browser/omnibox_edit_model.cc
+++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -2142,9 +2142,17 @@
 
       break;
     }
-    case OmniboxPopupSelection::KEYWORD_MODE:
-      additional_message_id = IDS_ACC_KEYWORD_MODE;
-      break;
+    case OmniboxPopupSelection::KEYWORD_MODE: {
+      // In keyword mode, the match we're interested in is actually the
+      // associated_keyword of the match we're on. Populate the a11y string
+      // with information from the keyword match, rather than the current match.
+      TemplateURL* turl = match.associated_keyword->GetTemplateURL(
+          client_->GetTemplateURLService(), false);
+      std::u16string replacement_string =
+          turl ? turl->short_name() : match.contents;
+      return l10n_util::GetStringFUTF16(IDS_ACC_KEYWORD_MODE,
+                                        replacement_string);
+    }
     case OmniboxPopupSelection::FOCUSED_BUTTON_TAB_SWITCH:
       additional_message_id = IDS_ACC_TAB_SWITCH_BUTTON_FOCUSED_PREFIX;
       break;
diff --git a/components/omnibox/browser/shortcuts_backend.cc b/components/omnibox/browser/shortcuts_backend.cc
index 4593627..f973423b 100644
--- a/components/omnibox/browser/shortcuts_backend.cc
+++ b/components/omnibox/browser/shortcuts_backend.cc
@@ -208,15 +208,6 @@
   match.Validate();
 #endif  // DCHECK_IS_ON()
 
-  // TODO(manukh): If we decide to launch history cluster suggestions, adding
-  //  them to the shortcuts provider would be useful to help users get to
-  //  repeat journeys but would require some logic to limit the joint history
-  //  cluster provider and shortcuts provider history cluster suggestions to
-  //  just 1. Until then, don't add history cluster suggestions to the shortcuts
-  //  DB to avoid showing more than 1 history cluster suggestion.
-  if (match.type == AutocompleteMatchType::HISTORY_CLUSTER)
-    return;
-
   // Trim `text` since `ExpandToFullWord()` trims the shortcut text; otherwise,
   // inputs with trailing whitespace wouldn't match a shortcut even if the user
   // previously used the input with a trailing whitespace.
diff --git a/components/omnibox/browser/shortcuts_provider.cc b/components/omnibox/browser/shortcuts_provider.cc
index ecb2451..c6c3547c 100644
--- a/components/omnibox/browser/shortcuts_provider.cc
+++ b/components/omnibox/browser/shortcuts_provider.cc
@@ -41,6 +41,10 @@
 #include "components/url_formatter/url_fixer.h"
 #include "third_party/metrics_proto/omnibox_input_type.pb.h"
 
+#if !BUILDFLAG(IS_IOS)
+#include "components/history_clusters/core/config.h"
+#endif  // !BUILDFLAG(IS_IOS)
+
 namespace {
 
 class DestinationURLEqualsURL {
@@ -267,6 +271,11 @@
   // Get the shortcuts from the database with keys that partially or completely
   // match the search term.
   std::vector<ShortcutMatch> shortcut_matches;
+  // Track history cluster shortcuts separately, so they don't consume
+  // `provider_max_matches_`.
+  std::vector<ShortcutMatch> history_cluster_shortcut_matches;
+  // The number of history cluster shortcuts added to `shortcut_matches`. This
+  // is used to bump the `provider_max_matches_`.
   if (base::FeatureList::IsEnabled(omnibox::kAggregateShortcuts)) {
     // If `kAggregateShortcuts` is enabled, group the matching shortcuts by
     // stripped `destination_url`, score them together, and create a single
@@ -278,11 +287,24 @@
          base::StartsWith(it->first, term_string, base::CompareCase::SENSITIVE);
          ++it) {
       const ShortcutsDatabase::Shortcut& shortcut = it->second;
+
+      // Allow `HISTORY_CLUSTER` suggestions only if the appropriate feature is
+      // enabled.
+#if !BUILDFLAG(IS_IOS)
+      if (!history_clusters::GetConfig()
+               .omnibox_history_cluster_provider_shortcuts &&
+          shortcut.match_core.type ==
+              AutocompleteMatch::Type::HISTORY_CLUSTER) {
+        continue;
+      }
+#endif  // !BUILDFLAG(IS_IOS)
+
       const GURL stripped_destination_url(AutocompleteMatch::GURLToStrippedGURL(
           shortcut.match_core.destination_url, input, template_url_service,
           shortcut.match_core.keyword));
       shortcuts_by_url[stripped_destination_url].push_back(&shortcut);
     }
+
     for (auto const& it : shortcuts_by_url) {
       int relevance =
           CalculateAggregateScore(term_string, it.second, max_relevance);
@@ -297,7 +319,14 @@
         // are prefixes of each other.
         const ShortcutsDatabase::Shortcut* shortcut =
             ShortestShortcutContent(it.second);
-        shortcut_matches.emplace_back(relevance, it.first, shortcut);
+
+        if (shortcut->match_core.type ==
+            AutocompleteMatch::Type::HISTORY_CLUSTER) {
+          history_cluster_shortcut_matches.emplace_back(relevance, it.first,
+                                                        shortcut);
+        } else {
+          shortcut_matches.emplace_back(relevance, it.first, shortcut);
+        }
       }
     }
 
@@ -309,10 +338,20 @@
          it != backend->shortcuts_map().end() &&
          base::StartsWith(it->first, term_string, base::CompareCase::SENSITIVE);
          ++it) {
+      const ShortcutsDatabase::Shortcut& shortcut = it->second;
+
+      // `kAggregateShortcuts` is launched. So rather than implement history
+      // cluster shortcuts logic, simply bypass history cluster suggestions when
+      // `kAggregateShortcuts` is disabled. This will prevent weird bugs if
+      // `kAggregateShortcuts` is unlaunched.
+      if (shortcut.match_core.type ==
+          AutocompleteMatch::Type::HISTORY_CLUSTER) {
+        continue;
+      }
+
       // Don't return shortcuts with zero relevance.
       int relevance = CalculateScore(term_string, it->second, max_relevance);
       if (relevance) {
-        const ShortcutsDatabase::Shortcut& shortcut = it->second;
         GURL stripped_destination_url(AutocompleteMatch::GURLToStrippedGURL(
             shortcut.match_core.destination_url, input, template_url_service,
             shortcut.match_core.keyword));
@@ -352,17 +391,38 @@
     shortcut_matches.erase(shortcut_matches.begin() + provider_max_matches_,
                            shortcut_matches.end());
   }
+
   // Create and initialize autocomplete matches from shortcut matches.
-  // Also guarantee that all relevance scores are decreasing (but do not assign
-  // any scores below 1).
-  matches_.reserve(shortcut_matches.size());
-  for (ShortcutMatch& match : shortcut_matches) {
-    max_relevance = std::min(max_relevance, match.relevance);
-    matches_.push_back(ShortcutToACMatch(*match.shortcut, max_relevance, input,
-                                         fixed_up_input, term_string));
-    if (max_relevance > 1)
-      --max_relevance;
-  }
+  matches_.reserve(shortcut_matches.size() +
+                   history_cluster_shortcut_matches.size());
+  base::ranges::transform(
+      shortcut_matches, std::back_inserter(matches_),
+      [&](const auto& shortcut_match) {
+        // Guarantee that all relevance scores are decreasing (but do not assign
+        // any scores below 1). Only do this for non-history cluster shortcuts.
+        max_relevance = std::min(max_relevance, shortcut_match.relevance);
+        int relevance = max_relevance;
+        if (max_relevance > 1)
+          --max_relevance;
+
+        return ShortcutToACMatch(*shortcut_match.shortcut, relevance, input,
+                                 fixed_up_input, term_string);
+      });
+  base::ranges::transform(
+      history_cluster_shortcut_matches, std::back_inserter(matches_),
+      [&](const auto& shortcut_match) {
+        auto match = ShortcutToACMatch(*shortcut_match.shortcut,
+                                       shortcut_match.relevance, input,
+                                       fixed_up_input, term_string);
+
+        // Set the `suggestion_group_id` to guarantee ordering last.
+        match.suggestion_group_id = SuggestionGroupId::kHistoryCluster;
+        // Insert a corresponding SuggestionGroup with default values in the
+        // suggestion groups map; otherwise the group ID will get dropped.
+        suggestion_groups_map_[SuggestionGroupId::kHistoryCluster];
+
+        return match;
+      });
 }
 
 AutocompleteMatch ShortcutsProvider::ShortcutToACMatch(
diff --git a/components/omnibox/browser/shortcuts_provider_unittest.cc b/components/omnibox/browser/shortcuts_provider_unittest.cc
index e3f40d2..e01d8941 100644
--- a/components/omnibox/browser/shortcuts_provider_unittest.cc
+++ b/components/omnibox/browser/shortcuts_provider_unittest.cc
@@ -22,6 +22,8 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "components/history/core/browser/url_database.h"
+#include "components/history_clusters/core/config.h"
+#include "components/history_clusters/core/features.h"
 #include "components/omnibox/browser/autocomplete_input.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/omnibox/browser/autocomplete_provider.h"
@@ -33,6 +35,7 @@
 #include "components/omnibox/common/omnibox_features.h"
 #include "components/search_engines/omnibox_focus_type.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/metrics_proto/omnibox_event.pb.h"
 
 using base::ASCIIToUTF16;
@@ -42,8 +45,8 @@
 
 // Returns up to 99,999 incrementing GUIDs of the format
 // "BD85DBA2-8C29-49F9-84AE-48E1E_____E0".
-int currentGuid = 0;
 std::string GetGuid() {
+  static int currentGuid = 0;
   currentGuid++;
   DCHECK_LE(currentGuid, 99999);
   return base::StringPrintf("BD85DBA2-8C29-49F9-84AE-48E1E%05dE0", currentGuid);
@@ -865,3 +868,72 @@
   auto score_b_frequent = CalculateAggregateScore("a", {&shortcut_b_frequent});
   EXPECT_GT(score_b_frequent, score_b);
 }
+
+#if !BUILDFLAG(IS_IOS)
+TEST_F(ShortcutsProviderTest, HistoryClusterSuggestions) {
+  history_clusters::Config config;
+  config.omnibox_history_cluster_provider_shortcuts = true;
+  history_clusters::SetConfigForTesting(config);
+
+  const auto create_test_data =
+      [](std::string text, bool is_history_cluster) -> TestShortcutData {
+    return {GetGuid(), text, "fill_into_edit",
+            // Use unique URLs to avoid deduping.
+            "http://www.destination_url.com/" + text,
+            AutocompleteMatch::DocumentType::NONE, "contents", "0,0",
+            "description", "0,0", ui::PAGE_TRANSITION_TYPED,
+            is_history_cluster ? AutocompleteMatchType::HISTORY_CLUSTER
+                               : AutocompleteMatchType::HISTORY_URL,
+            /*keyword=*/"",
+            /*days_from_now=*/1,
+            /*number_of_hits=*/1};
+  };
+  // `provider_max_matches_` is 3. Create more than 3 cluster and non-cluster
+  // shortcuts.
+  TestShortcutData test_data[] = {
+      create_test_data("text_history_0", false),
+      create_test_data("text_history_1", false),
+      create_test_data("text_history_2", false),
+      create_test_data("text_history_3", false),
+      create_test_data("text_cluster_0", true),
+      create_test_data("text_cluster_1", true),
+      create_test_data("text_cluster_2", true),
+      create_test_data("text_cluster_3", true),
+  };
+  PopulateShortcutsBackendWithTestData(client_->GetShortcutsBackend(),
+                                       test_data, std::size(test_data));
+
+  AutocompleteInput input(u"tex", metrics::OmniboxEventProto::OTHER,
+                          TestSchemeClassifier());
+  provider_->Start(input, false);
+  const auto& matches = provider_->matches();
+
+  // Expect 3 (i.e. `provider_max_matches_`) non-cluster matches, and all
+  // cluster matches.
+  ASSERT_EQ(matches.size(), 7u);
+  EXPECT_EQ(matches[0].type, AutocompleteMatchType::HISTORY_URL);
+  EXPECT_EQ(matches[1].type, AutocompleteMatchType::HISTORY_URL);
+  EXPECT_EQ(matches[2].type, AutocompleteMatchType::HISTORY_URL);
+  EXPECT_EQ(matches[3].type, AutocompleteMatchType::HISTORY_CLUSTER);
+  EXPECT_EQ(matches[4].type, AutocompleteMatchType::HISTORY_CLUSTER);
+  EXPECT_EQ(matches[5].type, AutocompleteMatchType::HISTORY_CLUSTER);
+  EXPECT_EQ(matches[6].type, AutocompleteMatchType::HISTORY_CLUSTER);
+
+  // Expect only non-cluster matches to have capped decrementing scores.
+  EXPECT_EQ(matches[1].relevance, matches[0].relevance - 1);
+  EXPECT_EQ(matches[2].relevance, matches[0].relevance - 2);
+  EXPECT_EQ(matches[3].relevance, matches[0].relevance);
+  EXPECT_EQ(matches[4].relevance, matches[0].relevance);
+  EXPECT_EQ(matches[5].relevance, matches[0].relevance);
+  EXPECT_EQ(matches[6].relevance, matches[0].relevance);
+
+  // Expect cluster matches to have grouping.
+  EXPECT_EQ(matches[0].suggestion_group_id, absl::nullopt);
+  EXPECT_EQ(matches[1].suggestion_group_id, absl::nullopt);
+  EXPECT_EQ(matches[2].suggestion_group_id, absl::nullopt);
+  EXPECT_EQ(matches[3].suggestion_group_id, SuggestionGroupId::kHistoryCluster);
+  EXPECT_EQ(matches[4].suggestion_group_id, SuggestionGroupId::kHistoryCluster);
+  EXPECT_EQ(matches[5].suggestion_group_id, SuggestionGroupId::kHistoryCluster);
+  EXPECT_EQ(matches[6].suggestion_group_id, SuggestionGroupId::kHistoryCluster);
+}
+#endif  // !BUILDFLAG(IS_IOS)
diff --git a/components/omnibox_strings.grdp b/components/omnibox_strings.grdp
index 71dd84a5..42c9eba 100644
--- a/components/omnibox_strings.grdp
+++ b/components/omnibox_strings.grdp
@@ -264,7 +264,7 @@
     <ph name="KEYWORD_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, press Tab then Enter to search
   </message>
   <message name="IDS_ACC_KEYWORD_MODE" desc="Announcement when entering keyword search mode.">
-    Search mode, type a query and press Enter to search with <ph name="KEYWORD_SUFFIX">$1<ex>Youtube</ex></ph>
+    Search <ph name="KEYWORD_SUFFIX">$1<ex>Youtube</ex>, type a query and press Enter to search</ph>
   </message>
 
   <!-- Accessibility suffix for suggestions when the remove button is focused. -->
diff --git a/components/omnibox_strings_grdp/IDS_ACC_KEYWORD_MODE.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_KEYWORD_MODE.png.sha1
index 372b718a..13fb736 100644
--- a/components/omnibox_strings_grdp/IDS_ACC_KEYWORD_MODE.png.sha1
+++ b/components/omnibox_strings_grdp/IDS_ACC_KEYWORD_MODE.png.sha1
@@ -1 +1 @@
-04f3209a14011a26a9c707ad26251373f5d5a2bf
\ No newline at end of file
+33b3bbdc87fa0a0356d9357055e0ab3bbfae0989
\ No newline at end of file
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto
index cdcc594b..e4c11134 100644
--- a/components/policy/proto/device_management_backend.proto
+++ b/components/policy/proto/device_management_backend.proto
@@ -1097,7 +1097,7 @@
 }
 
 // Status of the single storage device
-// Next id: 27
+// Next id: 29
 message DiskInfo {
   optional string serial = 1;
   optional string manufacturer = 2;
@@ -1130,6 +1130,7 @@
     // https://screenshot.googleplex.com/eZWNnV8qGnc
     uint32 emmc_oemid = 15;
     uint32 other_vendor = 16;
+    uint32 jedec_manfid = 27;
   }
 
   // The manufacturer-specific product identifier.
@@ -1151,6 +1152,7 @@
     uint64 nvme_firmware_rev = 23;
     uint64 emmc_firmware_rev = 24;
     uint32 other_firmware_rev = 25;
+    uint32 ufs_firmware_rev = 28;
   }
 
   // The purpose of the device on the system.
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 67d33b1..4595585 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -9949,6 +9949,34 @@
       URLs will only match as U2F appIDs. Domains only match as webauthn RP IDs. So to cover both U2F and webauthn APIs, list the appID URL and domain for a given site.''',
     },
     {
+      'name': 'LoadCryptoTokenExtension',
+      'owners': ['martinkr@google.com', 'rdcronin@google.com'],
+      'tags': [],
+      'type': 'main',
+      'schema': { 'type': 'boolean' },
+      'items': [
+        {
+          'value': True,
+          'caption': 'Load the extension',
+        },
+        {
+          'value': False,
+          'caption': 'Apply default behavior',
+        },
+      ],
+      'supported_on': ['chrome.*:106-107', 'chrome_os:106-107'],
+      'future_on': ['fuchsia'],
+      'features': {
+        'per_profile': True,
+        'dynamic_refresh': False,
+      },
+      'example_value': True,
+      'default': False,
+      'id': 1005,
+      'caption': '''Load the CryptoToken component extension at startup''',
+      'desc': '''If set to Enabled, the built-in CryptoToken component extension is loaded at startup. If set to Disabled or not set, CryptoToken is not loaded at browser startup. This policy is meant as a temporary workaround for sites broken by `chrome.runtime` being undefined as a side effect of the removal of CryptoToken in M106. Websites must not depend on `chrome.runtime` being defined unconditionally.''',
+    },
+    {
       'name': 'U2fSecurityKeyApiEnabled',
       'owners': ['martinkr@google.com', 'agl@chromium.org'],
       'tags': [],
@@ -33822,6 +33850,6 @@
   'placeholders': [],
   'deleted_policy_ids': [114, 115, 204, 205, 206, 341, 412, 438, 476, 544, 546, 562, 569, 578, 583, 585, 586, 587, 588, 589, 590, 591, 600, 668, 669, 872],
   'deleted_atomic_policy_group_ids': [19],
-  'highest_id_currently_used': 1004,
+  'highest_id_currently_used': 1005,
   'highest_atomic_group_id_currently_used': 43
 }
diff --git a/components/reporting/storage/storage.cc b/components/reporting/storage/storage.cc
index e5e10d2..2fe6541 100644
--- a/components/reporting/storage/storage.cc
+++ b/components/reporting/storage/storage.cc
@@ -24,15 +24,11 @@
 #include "base/task/task_runner.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "components/reporting/compression/compression_module.h"
 #include "components/reporting/encryption/encryption_module_interface.h"
 #include "components/reporting/encryption/primitives.h"
 #include "components/reporting/encryption/verification.h"
 #include "components/reporting/proto/synced/record.pb.h"
-#include "components/reporting/resources/disk_resource_impl.h"
-#include "components/reporting/resources/memory_resource_impl.h"
 #include "components/reporting/resources/resource_interface.h"
 #include "components/reporting/storage/storage_configuration.h"
 #include "components/reporting/storage/storage_queue.h"
diff --git a/components/reporting/util/BUILD.gn b/components/reporting/util/BUILD.gn
index e04ace8..f53c6629 100644
--- a/components/reporting/util/BUILD.gn
+++ b/components/reporting/util/BUILD.gn
@@ -58,12 +58,17 @@
 }
 
 source_set("test_callbacks_support") {
+  testonly = true
   sources = [
     "test_support_callbacks.cc",
     "test_support_callbacks.h",
   ]
 
-  deps = [ "//base" ]
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//testing/gtest",
+  ]
 }
 
 source_set("disconnectable_client") {
diff --git a/components/reporting/util/test_support_callbacks.cc b/components/reporting/util/test_support_callbacks.cc
index 332dfad..3806205dd 100644
--- a/components/reporting/util/test_support_callbacks.cc
+++ b/components/reporting/util/test_support_callbacks.cc
@@ -4,13 +4,16 @@
 
 #include "components/reporting/util/test_support_callbacks.h"
 
-#include "base/run_loop.h"
+#include "base/task/bind_post_task.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 
 namespace reporting {
 namespace test {
 
 TestCallbackWaiter::TestCallbackWaiter()
-    : run_loop_(base::RunLoop::Type::kNestableTasksAllowed) {}
+    : signaled_cb_(
+          base::BindPostTask(base::SequencedTaskRunnerHandle::Get(),
+                             base::test::TestFuture<bool>::GetCallback())) {}
 TestCallbackWaiter::~TestCallbackWaiter() = default;
 
 TestCallbackAutoWaiter::TestCallbackAutoWaiter() {
@@ -21,4 +24,4 @@
 }
 
 }  // namespace test
-}  // namespace reporting
\ No newline at end of file
+}  // namespace reporting
diff --git a/components/reporting/util/test_support_callbacks.h b/components/reporting/util/test_support_callbacks.h
index 160cc0cc..1372d85 100644
--- a/components/reporting/util/test_support_callbacks.h
+++ b/components/reporting/util/test_support_callbacks.h
@@ -13,9 +13,13 @@
 #include "base/callback_forward.h"
 #include "base/callback_helpers.h"
 #include "base/logging.h"
-#include "base/run_loop.h"
-#include "base/synchronization/lock.h"
+#include "base/task/bind_post_task.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/test/repeating_test_future.h"
+#include "base/test/test_future.h"
 #include "base/thread_annotations.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "testing/gtest/include/gtest/gtest.h"
 
 namespace reporting {
 namespace test {
@@ -33,16 +37,17 @@
 //   It can only be done in tests, never in production code.
 //
 template <typename ResType>
-class TestEvent {
+class TestEvent : base::test::RepeatingTestFuture<ResType> {
  public:
-  TestEvent() : run_loop_(base::RunLoop::Type::kNestableTasksAllowed) {}
+  TestEvent() = default;
   ~TestEvent() = default;
   TestEvent(const TestEvent& other) = delete;
   TestEvent& operator=(const TestEvent& other) = delete;
   ResType result() {
-    run_loop_.Run();
-    base::ReleasableAutoLock lock(&mutex_);
-    return std::forward<ResType>(result_);
+    auto res = base::test::RepeatingTestFuture<ResType>::Take();
+    EXPECT_TRUE(base::test::RepeatingTestFuture<ResType>::IsEmpty())
+        << "Event callback invoked more than once";
+    return res;
   }
 
   // Repeating callback to hand over to the processing method.
@@ -51,22 +56,10 @@
   // when the caller requires it.
   // If the caller expects OnceCallback, result will be converted automatically.
   base::RepeatingCallback<void(ResType res)> cb() {
-    return base::BindRepeating(&TestEvent<ResType>::Callback,
-                               base::Unretained(this));
+    return base::BindPostTask(
+        base::SequencedTaskRunnerHandle::Get(),
+        base::test::RepeatingTestFuture<ResType>::GetCallback());
   }
-
- private:
-  void Callback(ResType res) {
-    {
-      base::ReleasableAutoLock lock(&mutex_);
-      result_ = std::forward<ResType>(res);
-    }
-    run_loop_.Quit();
-  }
-
-  base::RunLoop run_loop_;
-  base::Lock mutex_;
-  ResType result_ GUARDED_BY(mutex_);
 };
 
 // Usage (in tests only):
@@ -82,36 +75,26 @@
 //   It can only be done in tests, never in production code.
 //
 template <typename... ResType>
-class TestMultiEvent {
+class TestMultiEvent : base::test::RepeatingTestFuture<ResType...> {
  public:
-  TestMultiEvent() : run_loop_(base::RunLoop::Type::kNestableTasksAllowed) {}
+  TestMultiEvent() = default;
   ~TestMultiEvent() = default;
   TestMultiEvent(const TestMultiEvent& other) = delete;
   TestMultiEvent& operator=(const TestMultiEvent& other) = delete;
   std::tuple<ResType...> result() {
-    run_loop_.Run();
-    base::ReleasableAutoLock lock(&mutex_);
-    return std::forward<std::tuple<ResType...>>(result_);
+    auto res = std::forward<std::tuple<ResType...>>(
+        base::test::RepeatingTestFuture<ResType...>::Take());
+    EXPECT_TRUE(base::test::RepeatingTestFuture<ResType...>::IsEmpty())
+        << "Event callback invoked more than once";
+    return res;
   }
 
   // Completion callback to hand over to the processing method.
   base::RepeatingCallback<void(ResType... res)> cb() {
-    return base::BindRepeating(&TestMultiEvent<ResType...>::Callback,
-                               base::Unretained(this));
+    return base::BindPostTask(
+        base::SequencedTaskRunnerHandle::Get(),
+        base::test::RepeatingTestFuture<ResType...>::GetCallback());
   }
-
- private:
-  void Callback(ResType... res) {
-    {
-      base::ReleasableAutoLock lock(&mutex_);
-      result_ = std::forward_as_tuple(res...);
-    }
-    run_loop_.Quit();
-  }
-
-  base::RunLoop run_loop_;
-  base::Lock mutex_;
-  std::tuple<ResType...> result_ GUARDED_BY(mutex_);
 };
 
 // Usage (in tests only):
@@ -129,7 +112,7 @@
 //
 //  And  in each of N actions: waiter.Signal(); when done
 
-class TestCallbackWaiter {
+class TestCallbackWaiter : public base::test::TestFuture<bool> {
  public:
   TestCallbackWaiter();
   ~TestCallbackWaiter();
@@ -147,17 +130,17 @@
       return;
     }
     // Dropping the last owner.
-    run_loop_.Quit();
+    std::move(signaled_cb_).Run(true);
   }
 
   void Wait() {
     Signal();  // Rid of the constructor's ownership.
-    run_loop_.Run();
+    ASSERT_TRUE(base::test::TestFuture<bool>::Get());
   }
 
  private:
   base::AtomicRefCount counter_{1};  // Owned by constructor.
-  base::RunLoop run_loop_;
+  base::OnceCallback<void(bool)> signaled_cb_;
 };
 
 // RAII wrapper for TestCallbackWaiter.
@@ -179,4 +162,4 @@
 }  // namespace test
 }  // namespace reporting
 
-#endif  // COMPONENTS_REPORTING_UTIL_TEST_SUPPORT_CALLBACKS_H_
\ No newline at end of file
+#endif  // COMPONENTS_REPORTING_UTIL_TEST_SUPPORT_CALLBACKS_H_
diff --git a/components/segmentation_platform/internal/segmentation_platform_service_impl.cc b/components/segmentation_platform/internal/segmentation_platform_service_impl.cc
index 9719f6c..881ed0b2 100644
--- a/components/segmentation_platform/internal/segmentation_platform_service_impl.cc
+++ b/components/segmentation_platform/internal/segmentation_platform_service_impl.cc
@@ -105,6 +105,7 @@
 
   proxy_ = std::make_unique<ServiceProxyImpl>(
       storage_service_->segment_info_database(),
+      storage_service_->default_model_manager(),
       storage_service_->signal_storage_config(), &configs_,
       &segment_selectors_);
   segment_score_provider_ =
diff --git a/components/segmentation_platform/internal/selection/segment_result_provider.cc b/components/segmentation_platform/internal/selection/segment_result_provider.cc
index f19981c4..7becb25e 100644
--- a/components/segmentation_platform/internal/selection/segment_result_provider.cc
+++ b/components/segmentation_platform/internal/selection/segment_result_provider.cc
@@ -270,13 +270,24 @@
   auto request = std::make_unique<ExecutionRequest>();
   // The pointer is kept alive by the `request_state`.
   request->segment_info = segment_info;
-  request->record_metrics_for_default = true;
+  request->record_metrics_for_default =
+      source == DefaultModelManager::SegmentSource::DEFAULT_MODEL;
   request->input_context = request_state->options->input_context;
-  request->callback =
-      base::BindOnce(&SegmentResultProviderImpl::OnModelExecuted,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(request_state),
-                     source, std::move(callback));
-  request->model_provider = provider;
+  // If the request needs to save result to database, ensure that the model is
+  // from database.
+  request->save_result_to_db =
+      (source == DefaultModelManager::SegmentSource::DATABASE &&
+       request_state->options->save_results_to_db);
+  if (request->save_result_to_db) {
+    // Drop `callback` on floor if saving results to database.
+    DCHECK(request_state->options->callback.is_null());
+  } else {
+    request->callback =
+        base::BindOnce(&SegmentResultProviderImpl::OnModelExecuted,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(request_state),
+                       source, std::move(callback));
+    request->model_provider = provider;
+  }
   execution_service_->RequestModelExecution(std::move(request));
 }
 
diff --git a/components/segmentation_platform/internal/selection/segment_result_provider.h b/components/segmentation_platform/internal/selection/segment_result_provider.h
index faebcc26..100ae83b 100644
--- a/components/segmentation_platform/internal/selection/segment_result_provider.h
+++ b/components/segmentation_platform/internal/selection/segment_result_provider.h
@@ -85,9 +85,16 @@
     //  * Execution of default model when score is missing.
     // When set to true, the result could be from following:
     //  * Execution of TFLite model.
-    //  * TODO(ssid): Support fallback to default when model is missing.
+    //  * Fallback to default when model is missing.
     bool ignore_db_scores = false;
 
+    // If `ignore_db_scores` is true and TFLite model is available, then write
+    // the results to database. Used when user wants to rerun the database
+    // model. `callback` should be null if set to true.
+    // TODO(ssid): Consider moving this option out as a different SaveRequest
+    // method in this class.
+    bool save_results_to_db = false;
+
     // Callback to return the segment result.
     SegmentResultCallback callback;
 
diff --git a/components/segmentation_platform/internal/service_proxy_impl.cc b/components/segmentation_platform/internal/service_proxy_impl.cc
index 551d922..ba9994a 100644
--- a/components/segmentation_platform/internal/service_proxy_impl.cc
+++ b/components/segmentation_platform/internal/service_proxy_impl.cc
@@ -5,20 +5,24 @@
 #include "components/segmentation_platform/internal/service_proxy_impl.h"
 
 #include <inttypes.h>
+#include <memory>
 #include <sstream>
 
+#include "base/callback_helpers.h"
 #include "base/observer_list.h"
-#include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
+#include "base/time/default_clock.h"
 #include "base/time/time.h"
+#include "components/segmentation_platform/internal/database/segment_info_database.h"
 #include "components/segmentation_platform/internal/database/signal_storage_config.h"
+#include "components/segmentation_platform/internal/database/storage_service.h"
+#include "components/segmentation_platform/internal/execution/default_model_manager.h"
 #include "components/segmentation_platform/internal/metadata/metadata_utils.h"
 #include "components/segmentation_platform/internal/scheduler/execution_service.h"
-#include "components/segmentation_platform/internal/segmentation_platform_service_impl.h"
+#include "components/segmentation_platform/internal/selection/segment_result_provider.h"
 #include "components/segmentation_platform/internal/selection/segment_selector_impl.h"
 #include "components/segmentation_platform/public/config.h"
 
-#include "base/logging.h"
 namespace segmentation_platform {
 
 namespace {
@@ -48,15 +52,29 @@
       prediction_result.has_result() ? prediction_result.result() : 0,
       time_string.str().c_str());
 }
+
+base::flat_set<proto::SegmentId> GetAllSegemntIds(
+    const std::vector<std::unique_ptr<Config>>& configs) {
+  base::flat_set<proto::SegmentId> all_segment_ids;
+  for (const auto& config : configs) {
+    for (const auto& segment : config->segments) {
+      all_segment_ids.insert(segment.first);
+    }
+  }
+  return all_segment_ids;
+}
+
 }  // namespace
 
 ServiceProxyImpl::ServiceProxyImpl(
     SegmentInfoDatabase* segment_db,
+    DefaultModelManager* default_manager,
     SignalStorageConfig* signal_storage_config,
     std::vector<std::unique_ptr<Config>>* configs,
     base::flat_map<std::string, std::unique_ptr<SegmentSelectorImpl>>*
         segment_selectors)
     : segment_db_(segment_db),
+      default_manager_(default_manager),
       signal_storage_config_(signal_storage_config),
       configs_(configs),
       segment_selectors_(segment_selectors) {}
@@ -89,10 +107,11 @@
       obs.OnServiceStatusChanged(is_service_initialized_, service_status_flag_);
   }
 
-  if (segment_db_ &&
+  if (default_manager_ &&
       (static_cast<int>(ServiceStatus::kSegmentationInfoDbInitialized) &
        service_status_flag_)) {
-    segment_db_->GetAllSegmentInfo(
+    default_manager_->GetAllSegmentInfoFromBothModels(
+        GetAllSegemntIds(*configs_), segment_db_,
         base::BindOnce(&ServiceProxyImpl::OnGetAllSegmentationInfo,
                        weak_ptr_factory_.GetWeakPtr()));
   }
@@ -100,7 +119,10 @@
 
 void ServiceProxyImpl::SetExecutionService(
     ExecutionService* model_execution_scheduler) {
-  execution_service = model_execution_scheduler;
+  execution_service_ = model_execution_scheduler;
+  segment_result_provider_ = SegmentResultProvider::Create(
+      segment_db_, signal_storage_config_, default_manager_, execution_service_,
+      base::DefaultClock::GetInstance(), /*force_refresh_results=*/true);
 }
 
 void ServiceProxyImpl::GetServiceStatus() {
@@ -108,36 +130,23 @@
 }
 
 void ServiceProxyImpl::ExecuteModel(SegmentId segment_id) {
-  if (!execution_service ||
+  if (!execution_service_ ||
       segment_id == SegmentId::OPTIMIZATION_TARGET_UNKNOWN) {
     return;
   }
-  segment_db_->GetSegmentInfo(
-      segment_id,
-      base::BindOnce(&ServiceProxyImpl::OnSegmentInfoFetchedForExecution,
-                     weak_ptr_factory_.GetWeakPtr()));
-}
-
-void ServiceProxyImpl::OnSegmentInfoFetchedForExecution(
-    absl::optional<proto::SegmentInfo> segment_info) {
-  if (!segment_info)
-    return;
-  auto request = std::make_unique<ExecutionRequest>();
-  request->record_metrics_for_default = false;
-  request->save_result_to_db = true;
-  request->segment_info = &segment_info.value();
-  execution_service->RequestModelExecution(std::move(request));
+  auto request = std::make_unique<SegmentResultProvider::GetResultOptions>();
+  request->save_results_to_db = true;
+  request->segment_id = segment_id;
+  request->ignore_db_scores = true;
+  segment_result_provider_->GetSegmentResult(std::move(request));
 }
 
 void ServiceProxyImpl::OverwriteResult(SegmentId segment_id, float result) {
-  if (!execution_service)
-    return;
-
-  if (result < 0 || result > 1)
+  if (!execution_service_)
     return;
 
   if (segment_id != SegmentId::OPTIMIZATION_TARGET_UNKNOWN) {
-    execution_service->OverwriteModelExecutionResult(
+    execution_service_->OverwriteModelExecutionResult(
         segment_id, std::make_pair(result, ModelExecutionStatus::kSuccess));
   }
 }
@@ -155,14 +164,26 @@
 }
 
 void ServiceProxyImpl::OnGetAllSegmentationInfo(
-    std::unique_ptr<SegmentInfoDatabase::SegmentInfoList> segment_info) {
+    DefaultModelManager::SegmentInfoList segment_info) {
   if (!configs_)
     return;
 
   // Convert the |segment_info| vector to a map for quick lookup.
   base::flat_map<SegmentId, proto::SegmentInfo> segment_ids;
-  for (const auto& info : *segment_info) {
-    segment_ids[info.first] = info.second;
+  for (const auto& info : segment_info) {
+    const SegmentId segment_id = info->segment_info.segment_id();
+    switch (info->segment_source) {
+      case DefaultModelManager::SegmentSource::DATABASE:
+        // If database info is available, then overwrite the existing entry.
+        segment_ids[segment_id] = std::move(info->segment_info);
+        break;
+      case DefaultModelManager::SegmentSource::DEFAULT_MODEL:
+        // If database info is not available then use default model info.
+        if (segment_ids.count(segment_id) == 0) {
+          segment_ids[segment_id] = std::move(info->segment_info);
+        }
+        break;
+    }
   }
 
   std::vector<ServiceProxy::ClientInfo> result;
diff --git a/components/segmentation_platform/internal/service_proxy_impl.h b/components/segmentation_platform/internal/service_proxy_impl.h
index 1d4ea7fc..289cc3f 100644
--- a/components/segmentation_platform/internal/service_proxy_impl.h
+++ b/components/segmentation_platform/internal/service_proxy_impl.h
@@ -11,8 +11,8 @@
 #include "base/containers/flat_map.h"
 #include "base/memory/raw_ptr.h"
 #include "base/observer_list.h"
-#include "components/leveldb_proto/public/proto_database.h"
 #include "components/segmentation_platform/internal/database/segment_info_database.h"
+#include "components/segmentation_platform/internal/execution/default_model_manager.h"
 #include "components/segmentation_platform/internal/scheduler/model_execution_scheduler.h"
 #include "components/segmentation_platform/public/proto/segmentation_platform.pb.h"
 #include "components/segmentation_platform/public/service_proxy.h"
@@ -21,9 +21,10 @@
 using proto::SegmentId;
 
 struct Config;
-class SignalStorageConfig;
 class ExecutionService;
 class SegmentSelectorImpl;
+class SegmentResultProvider;
+class SignalStorageConfig;
 
 // A helper class to expose internals of the segmentationss service to a logging
 // component and/or debug UI.
@@ -32,6 +33,7 @@
  public:
   ServiceProxyImpl(
       SegmentInfoDatabase* segment_db,
+      DefaultModelManager* default_manager,
       SignalStorageConfig* signal_storage_config,
       std::vector<std::unique_ptr<Config>>* configs,
       base::flat_map<std::string, std::unique_ptr<SegmentSelectorImpl>>*
@@ -67,20 +69,23 @@
 
   //  Called after retrieving all the segmentation info from the DB.
   void OnGetAllSegmentationInfo(
-      std::unique_ptr<SegmentInfoDatabase::SegmentInfoList> segment_info);
+      DefaultModelManager::SegmentInfoList segment_info);
 
   // ModelExecutionScheduler::Observer overrides.
   void OnModelExecutionCompleted(SegmentId segment_id) override;
 
   bool is_service_initialized_ = false;
   int service_status_flag_ = 0;
-  raw_ptr<SegmentInfoDatabase> segment_db_;
-  raw_ptr<SignalStorageConfig> signal_storage_config_;
-  raw_ptr<std::vector<std::unique_ptr<Config>>> configs_;
+  const raw_ptr<SegmentInfoDatabase> segment_db_;
+  const raw_ptr<DefaultModelManager> default_manager_;
+  const raw_ptr<SignalStorageConfig> signal_storage_config_;
+  const raw_ptr<std::vector<std::unique_ptr<Config>>> configs_;
   base::ObserverList<ServiceProxy::Observer> observers_;
-  raw_ptr<ExecutionService> execution_service{nullptr};
-  raw_ptr<base::flat_map<std::string, std::unique_ptr<SegmentSelectorImpl>>>
+  raw_ptr<ExecutionService> execution_service_{nullptr};
+  const raw_ptr<
+      base::flat_map<std::string, std::unique_ptr<SegmentSelectorImpl>>>
       segment_selectors_;
+  std::unique_ptr<SegmentResultProvider> segment_result_provider_;
 
   base::WeakPtrFactory<ServiceProxyImpl> weak_ptr_factory_{this};
 };
diff --git a/components/segmentation_platform/internal/service_proxy_impl_unittest.cc b/components/segmentation_platform/internal/service_proxy_impl_unittest.cc
index 7a130a6a..1415a193 100644
--- a/components/segmentation_platform/internal/service_proxy_impl_unittest.cc
+++ b/components/segmentation_platform/internal/service_proxy_impl_unittest.cc
@@ -3,17 +3,18 @@
 // found in the LICENSE file.
 
 #include "components/segmentation_platform/internal/service_proxy_impl.h"
+#include <memory>
 
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/test/task_environment.h"
-#include "components/leveldb_proto/public/proto_database.h"
 #include "components/leveldb_proto/testing/fake_db.h"
-#include "components/optimization_guide/core/model_util.h"
-#include "components/optimization_guide/core/optimization_guide_util.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/segmentation_platform/internal/constants.h"
+#include "components/segmentation_platform/internal/database/test_segment_info_database.h"
+#include "components/segmentation_platform/internal/execution/default_model_manager.h"
+#include "components/segmentation_platform/internal/execution/mock_model_provider.h"
 #include "components/segmentation_platform/internal/execution/model_executor.h"
 #include "components/segmentation_platform/internal/execution/processing/feature_list_query_processor.h"
 #include "components/segmentation_platform/internal/platform_options.h"
@@ -35,19 +36,26 @@
 constexpr char kTestSegmentationKey[] = "test_key";
 
 // Adds a segment info into a map, and return a copy of it.
-proto::SegmentInfo AddSegmentInfo(
-    std::map<std::string, proto::SegmentInfo>* db_entries,
-    Config* config,
-    SegmentId segment_id) {
-  proto::SegmentInfo info;
-  info.set_segment_id(segment_id);
-  db_entries->insert(
-      std::make_pair(base::NumberToString(static_cast<int>(segment_id)), info));
+proto::SegmentInfo* AddSegmentInfo(test::TestSegmentInfoDatabase* segment_db,
+                                   Config* config,
+                                   SegmentId segment_id) {
+  auto* info = segment_db->FindOrCreateSegment(segment_id);
+  info->mutable_model_metadata()->set_time_unit(proto::TimeUnit::DAY);
   config->segments.insert(
       {segment_id, std::make_unique<Config::SegmentMetadata>("UmaName")});
   return info;
 }
 
+base::flat_set<SegmentId> GetAllSegmentIds(
+    const std::vector<std::unique_ptr<Config>>& configs) {
+  base::flat_set<SegmentId> all_segment_ids;
+  for (const auto& config : configs) {
+    for (const auto& segment_id : config->segments)
+      all_segment_ids.insert(segment_id.first);
+  }
+  return all_segment_ids;
+}
+
 class MockModelExecutionScheduler : public ModelExecutionScheduler {
  public:
   MockModelExecutionScheduler() = default;
@@ -59,6 +67,11 @@
               (SegmentId, (const std::pair<float, ModelExecutionStatus>&)));
 };
 
+class MockModelExecutionManager : public ModelExecutionManager {
+ public:
+  MOCK_METHOD(ModelProvider*, GetProvider, (proto::SegmentId segment_id));
+};
+
 }  // namespace
 
 class FakeSegmentSelectorImpl : public SegmentSelectorImpl {
@@ -96,28 +109,23 @@
     config->segmentation_key = kTestSegmentationKey;
     configs_.emplace_back(std::move(config));
     pref_service_.registry()->RegisterDictionaryPref(kSegmentationResultPref);
+    segment_db_ = std::make_unique<test::TestSegmentInfoDatabase>();
   }
 
   void SetUpProxy() {
-    DCHECK(!db_);
-    DCHECK(!segment_db_);
-
-    auto db = std::make_unique<leveldb_proto::test::FakeDB<proto::SegmentInfo>>(
-        &db_entries_);
-    db_ = db.get();
-    segment_db_ = std::make_unique<SegmentInfoDatabase>(std::move(db));
-
     segment_selectors_[kTestSegmentationKey] =
         std::make_unique<FakeSegmentSelectorImpl>(&pref_service_,
                                                   configs_.at(0).get());
+    test_model_factory_ = std::make_unique<TestModelProviderFactory>(&data_);
+    default_manager_ = std::make_unique<DefaultModelManager>(
+        test_model_factory_.get(), GetAllSegmentIds(configs_));
     service_proxy_impl_ = std::make_unique<ServiceProxyImpl>(
-        segment_db_.get(), nullptr, &configs_, &segment_selectors_);
+        segment_db_.get(), default_manager_.get(), nullptr, &configs_,
+        &segment_selectors_);
     service_proxy_impl_->AddObserver(this);
   }
 
   void TearDown() override {
-    db_entries_.clear();
-    db_ = nullptr;
     segment_db_.reset();
     configs_.clear();
     client_info_.clear();
@@ -130,23 +138,35 @@
 
   void OnClientInfoAvailable(
       const std::vector<ServiceProxy::ClientInfo>& client_info) override {
+    if (wait_for_client_info_) {
+      wait_for_client_info_->QuitClosure().Run();
+    }
     client_info_ = client_info;
   }
 
+  void WaitForClientInfo() {
+    wait_for_client_info_ = std::make_unique<base::RunLoop>();
+    wait_for_client_info_->Run();
+    wait_for_client_info_.reset();
+  }
+
  protected:
   base::test::TaskEnvironment task_environment_;
   bool is_initialized_ = false;
   int status_flag_ = 0;
 
-  std::map<std::string, proto::SegmentInfo> db_entries_;
-  raw_ptr<leveldb_proto::test::FakeDB<proto::SegmentInfo>> db_{nullptr};
-  std::unique_ptr<SegmentInfoDatabase> segment_db_;
+  std::unique_ptr<test::TestSegmentInfoDatabase> segment_db_;
+  TestModelProviderFactory::Data data_;
+  std::unique_ptr<TestModelProviderFactory> test_model_factory_;
+  std::unique_ptr<DefaultModelManager> default_manager_;
   std::unique_ptr<ServiceProxyImpl> service_proxy_impl_;
   std::vector<ServiceProxy::ClientInfo> client_info_;
   std::vector<std::unique_ptr<Config>> configs_;
   base::flat_map<std::string, std::unique_ptr<SegmentSelectorImpl>>
       segment_selectors_;
   TestingPrefServiceSimple pref_service_;
+
+  std::unique_ptr<base::RunLoop> wait_for_client_info_;
 };
 
 TEST_F(ServiceProxyImplTest, GetServiceStatus) {
@@ -163,19 +183,32 @@
   ASSERT_EQ(is_initialized_, true);
   ASSERT_EQ(status_flag_, 7);
 
-  db_->LoadCallback(true);
+  WaitForClientInfo();
   ASSERT_FALSE(client_info_.empty());
   ASSERT_EQ(client_info_.size(), 1u);
 }
 
-TEST_F(ServiceProxyImplTest, GetSegmentationInfoFromDB) {
-  proto::SegmentInfo info =
-      AddSegmentInfo(&db_entries_, configs_.at(0).get(),
-                     SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB);
+TEST_F(ServiceProxyImplTest, GetSegmentationInfoFromDefaultModel) {
+  const SegmentId segment_id =
+      SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+  proto::SegmentationModelMetadata model_metadata;
+  model_metadata.set_time_unit(proto::TimeUnit::DAY);
+  data_.segments_supporting_default_model = {segment_id};
+  configs_.at(0)->segments.insert(
+      {segment_id, std::make_unique<Config::SegmentMetadata>("UmaName")});
+
   SetUpProxy();
 
+  ASSERT_TRUE(data_.default_model_providers[segment_id]);
+  EXPECT_CALL(*data_.default_model_providers[segment_id], InitAndFetchModel(_))
+      .WillOnce(Invoke([&](const ModelProvider::ModelUpdatedCallback&
+                               model_updated_callback) {
+        model_updated_callback.Run(segment_id, model_metadata, 1);
+      }));
+
   service_proxy_impl_->OnServiceStatusChanged(true, 7);
-  db_->LoadCallback(true);
+  WaitForClientInfo();
+
   ASSERT_EQ(client_info_.size(), 1u);
   ASSERT_EQ(client_info_.at(0).segmentation_key, kTestSegmentationKey);
   ASSERT_EQ(client_info_.at(0).segment_status.size(), 1u);
@@ -183,29 +216,59 @@
   ASSERT_EQ(status.segment_id,
             SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB);
   ASSERT_EQ(status.can_execute_segment, false);
-  ASSERT_TRUE(status.segment_metadata.empty());
+  ASSERT_EQ(status.segment_metadata, "model_metadata: { time_unit:DAY }");
+  ASSERT_TRUE(status.prediction_result.empty());
+}
+
+TEST_F(ServiceProxyImplTest, GetSegmentationInfoFromDB) {
+  const SegmentId segment_id =
+      SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+  data_.segments_supporting_default_model = {segment_id};
+  configs_.at(0)->segments.insert(
+      {segment_id, std::make_unique<Config::SegmentMetadata>("UmaName")});
+  auto* info =
+      AddSegmentInfo(segment_db_.get(), configs_.at(0).get(), segment_id);
+  SetUpProxy();
+
+  ASSERT_TRUE(data_.default_model_providers[segment_id]);
+  EXPECT_CALL(*data_.default_model_providers[segment_id], InitAndFetchModel(_))
+      .WillOnce(Invoke([&](const ModelProvider::ModelUpdatedCallback&
+                               model_updated_callback) {
+        model_updated_callback.Run(segment_id, info->model_metadata(), 1);
+      }));
+
+  service_proxy_impl_->OnServiceStatusChanged(true, 7);
+  WaitForClientInfo();
+
+  ASSERT_EQ(client_info_.size(), 1u);
+  ASSERT_EQ(client_info_.at(0).segmentation_key, kTestSegmentationKey);
+  ASSERT_EQ(client_info_.at(0).segment_status.size(), 1u);
+  ServiceProxy::SegmentStatus status = client_info_.at(0).segment_status.at(0);
+  ASSERT_EQ(status.segment_id,
+            SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB);
+  ASSERT_EQ(status.can_execute_segment, false);
+  ASSERT_EQ(status.segment_metadata, "model_metadata: { time_unit:DAY }");
   ASSERT_TRUE(status.prediction_result.empty());
 }
 
 TEST_F(ServiceProxyImplTest, ExecuteModel) {
-  proto::SegmentInfo info =
-      AddSegmentInfo(&db_entries_, configs_.at(0).get(),
+  auto* info =
+      AddSegmentInfo(segment_db_.get(), configs_.at(0).get(),
                      SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB);
   SetUpProxy();
 
   service_proxy_impl_->OnServiceStatusChanged(true, 7);
-  db_->LoadCallback(true);
 
   segment_db_->UpdateSegment(
-      SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB, info,
+      SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB, *info,
       base::DoNothing());
-  db_->UpdateCallback(true);
 
   auto scheduler_moved = std::make_unique<MockModelExecutionScheduler>();
   MockModelExecutionScheduler* scheduler = scheduler_moved.get();
+  auto model_manager = std::make_unique<MockModelExecutionManager>();
   ExecutionService execution;
   execution.InitForTesting(nullptr, nullptr, std::move(scheduler_moved),
-                           nullptr);
+                           std::move(model_manager));
 
   // Scheduler is not set, ExecuteModel() will do nothing.
   EXPECT_CALL(*scheduler, RequestModelExecution(_)).Times(0);
@@ -217,12 +280,11 @@
   EXPECT_CALL(*scheduler, RequestModelExecution(_))
       .WillOnce(Invoke(
           [&info, &wait_for_execution](const proto::SegmentInfo actual_info) {
-            EXPECT_EQ(info.segment_id(), actual_info.segment_id());
+            EXPECT_EQ(info->segment_id(), actual_info.segment_id());
             wait_for_execution.QuitClosure().Run();
           }));
   service_proxy_impl_->ExecuteModel(
       SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB);
-  db_->GetCallback(true);
   wait_for_execution.Run();
 
   EXPECT_CALL(*scheduler, RequestModelExecution(_)).Times(0);
@@ -230,13 +292,11 @@
 }
 
 TEST_F(ServiceProxyImplTest, OverwriteResult) {
-  proto::SegmentInfo info =
-      AddSegmentInfo(&db_entries_, configs_.at(0).get(),
-                     SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB);
+  AddSegmentInfo(segment_db_.get(), configs_.at(0).get(),
+                 SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB);
   SetUpProxy();
 
   service_proxy_impl_->OnServiceStatusChanged(true, 7);
-  db_->LoadCallback(true);
 
   auto scheduler_moved = std::make_unique<MockModelExecutionScheduler>();
   MockModelExecutionScheduler* scheduler = scheduler_moved.get();
@@ -249,13 +309,7 @@
   service_proxy_impl_->OverwriteResult(
       SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB, 0.7);
 
-  // Test with invalid values.
   service_proxy_impl_->SetExecutionService(&execution);
-  EXPECT_CALL(*scheduler, OnModelExecutionCompleted(_, _)).Times(0);
-  service_proxy_impl_->OverwriteResult(
-      SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB, 1.1);
-  service_proxy_impl_->OverwriteResult(
-      SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB, -0.1);
 
   EXPECT_CALL(*scheduler,
               OnModelExecutionCompleted(
@@ -270,13 +324,11 @@
 }
 
 TEST_F(ServiceProxyImplTest, SetSelectSegment) {
-  proto::SegmentInfo info =
-      AddSegmentInfo(&db_entries_, configs_.at(0).get(),
-                     SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB);
+  AddSegmentInfo(segment_db_.get(), configs_.at(0).get(),
+                 SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB);
   SetUpProxy();
 
   service_proxy_impl_->OnServiceStatusChanged(true, 7);
-  db_->LoadCallback(true);
 
   service_proxy_impl_->SetSelectedSegment(
       kTestSegmentationKey,
diff --git a/components/services/app_service/public/cpp/features.cc b/components/services/app_service/public/cpp/features.cc
index b68b645..056423c6 100644
--- a/components/services/app_service/public/cpp/features.cc
+++ b/components/services/app_service/public/cpp/features.cc
@@ -19,6 +19,6 @@
     "AppServiceUninstallWithoutMojom", base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kAppServiceWithoutMojom{"AppServiceWithoutMojom",
-                                            base::FEATURE_DISABLED_BY_DEFAULT};
+                                            base::FEATURE_ENABLED_BY_DEFAULT};
 
 }  // namespace apps
diff --git a/content/browser/accessibility/accessibility_tree_formatter_blink.cc b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
index f4b797cb..b3b6faac 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_blink.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
@@ -19,6 +19,7 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/platform/ax_platform_node_delegate.h"
 #include "ui/accessibility/platform/compute_attributes.h"
 #include "ui/gfx/geometry/rect_conversions.h"
@@ -423,7 +424,7 @@
   }
 
   //  Check for relevant rich text selection info in AXTreeData
-  ui::AXTree::Selection unignored_selection =
+  ui::AXSelection unignored_selection =
       node.manager()->ax_tree()->GetUnignoredSelection();
   int anchor_id = unignored_selection.anchor_object_id;
   if (id == anchor_id) {
@@ -573,8 +574,7 @@
   }
 
   //  Check for relevant rich text selection info in AXTreeData
-  ui::AXTree::Selection unignored_selection =
-      node.tree()->GetUnignoredSelection();
+  ui::AXSelection unignored_selection = node.tree()->GetUnignoredSelection();
   int anchor_id = unignored_selection.anchor_object_id;
   if (id == anchor_id) {
     int anchor_offset = unignored_selection.anchor_offset;
diff --git a/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc b/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc
index 936d0241..2c49ac9c 100644
--- a/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc
+++ b/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc
@@ -24,6 +24,7 @@
 #include "net/dns/mock_host_resolver.h"
 #include "ui/accessibility/accessibility_switches.h"
 #include "ui/accessibility/ax_node_position.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/ax_tree_id.h"
 
 using Microsoft::WRL::ComPtr;
@@ -3239,7 +3240,7 @@
   EXPECT_HRESULT_SUCCEEDED(text_range_provider->Select());
 
   ASSERT_TRUE(waiter.WaitForNotification());
-  ui::AXTree::Selection selection = node->GetUnignoredSelection();
+  ui::AXSelection selection = node->GetUnignoredSelection();
   EXPECT_EQ(selection.anchor_object_id, node->GetId());
   EXPECT_EQ(selection.anchor_offset, 0);
   EXPECT_EQ(selection.focus_object_id, node->GetId());
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index 9071554..28ba4b0 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -20,6 +20,7 @@
 #include "third_party/blink/public/strings/grit/blink_accessibility_strings.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/ax_tree_id.h"
 #include "ui/accessibility/platform/ax_unique_id.h"
 #include "ui/base/buildflags.h"
@@ -1196,8 +1197,7 @@
   return GetData().GetDescriptionFrom();
 }
 
-const ui::AXTree::Selection BrowserAccessibility::GetUnignoredSelection()
-    const {
+const ui::AXSelection BrowserAccessibility::GetUnignoredSelection() const {
   return node()->GetUnignoredSelection();
 }
 
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h
index 2de6304..7fb3146 100644
--- a/content/browser/accessibility/browser_accessibility.h
+++ b/content/browser/accessibility/browser_accessibility.h
@@ -439,7 +439,7 @@
   bool HasTextStyle(ax::mojom::TextStyle text_style) const override;
   ax::mojom::NameFrom GetNameFrom() const override;
   ax::mojom::DescriptionFrom GetDescriptionFrom() const override;
-  const ui::AXTree::Selection GetUnignoredSelection() const override;
+  const ui::AXSelection GetUnignoredSelection() const override;
   AXPosition CreatePositionAt(
       int offset,
       ax::mojom::TextAffinity affinity =
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc
index 80b54e8..b229f2a 100644
--- a/content/browser/accessibility/browser_accessibility_android.cc
+++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -22,6 +22,7 @@
 #include "ui/accessibility/ax_assistant_structure.h"
 #include "ui/accessibility/ax_node_position.h"
 #include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/platform/ax_android_constants.h"
 #include "ui/accessibility/platform/ax_unique_id.h"
 #include "ui/strings/grit/ax_strings.h"
@@ -1485,7 +1486,7 @@
       GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart, &sel_start)) {
     return sel_start;
   }
-  ui::AXTree::Selection unignored_selection =
+  ui::AXSelection unignored_selection =
       manager()->ax_tree()->GetUnignoredSelection();
   int32_t anchor_id = unignored_selection.anchor_object_id;
   BrowserAccessibility* anchor_object = manager()->GetFromID(anchor_id);
@@ -1508,7 +1509,7 @@
     return sel_end;
   }
 
-  ui::AXTree::Selection unignored_selection =
+  ui::AXSelection unignored_selection =
       manager()->ax_tree()->GetUnignoredSelection();
   int32_t focus_id = unignored_selection.focus_object_id;
   BrowserAccessibility* focus_object = manager()->GetFromID(focus_id);
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm
index c606df43..6bfbb5ce 100644
--- a/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -34,6 +34,7 @@
 #include "ui/accessibility/ax_enum_util.h"
 #include "ui/accessibility/ax_range.h"
 #include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/platform/ax_platform_node.h"
 #include "ui/accessibility/platform/ax_utils_mac.h"
 #include "ui/gfx/mac/coordinate_conversion.h"
@@ -239,7 +240,7 @@
   if (!manager)
     return {};
 
-  const ui::AXTree::Selection unignored_selection =
+  const ui::AXSelection unignored_selection =
       manager->ax_tree()->GetUnignoredSelection();
   int32_t anchor_id = unignored_selection.anchor_object_id;
   const BrowserAccessibility* anchor_object = manager->GetFromID(anchor_id);
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc
index d218beb0..38980dd 100644
--- a/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -11,6 +11,7 @@
 #include "content/browser/accessibility/web_contents_accessibility_android.h"
 #include "third_party/blink/public/mojom/render_accessibility.mojom.h"
 #include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_selection.h"
 
 namespace content {
 
diff --git a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
index 51b34e7c..f92917a1 100644
--- a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "content/browser/accessibility/browser_accessibility_auralinux.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/platform/ax_platform_node_auralinux.h"
 
 namespace content {
diff --git a/content/browser/client_hints/client_hints.cc b/content/browser/client_hints/client_hints.cc
index b9cbfdb..d0dd096 100644
--- a/content/browser/client_hints/client_hints.cc
+++ b/content/browser/client_hints/client_hints.cc
@@ -19,6 +19,7 @@
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "content/browser/devtools/devtools_instrumentation.h"
+#include "content/browser/preloading/prerender/prerender_host.h"
 #include "content/browser/renderer_host/frame_tree.h"
 #include "content/browser/renderer_host/frame_tree_node.h"
 #include "content/browser/renderer_host/navigator.h"
@@ -571,6 +572,17 @@
     delegate->GetAllowedClientHintsFromSource(outermost_main_frame_origin,
                                               &hints);
 
+    // If this is a prerender tree, also capture prerender local setting. The
+    // setting was given by navigation requests on the prerendering page, and
+    // has not been used as a global setting.
+    if (frame_tree_node && frame_tree_node->frame_tree()->is_prerendering()) {
+      // If prerender host is nullptr, it means prerender has been canceled and
+      // the host will be discarded soon, so we do not need to continue.
+      if (auto* host = PrerenderHost::GetPrerenderHostFromFrameTreeNode(
+              *frame_tree_node))
+        host->GetAllowedClientHintsOnPage(outermost_main_frame_origin, &hints);
+    }
+
     // If this is not a top-level frame, then check if any of the ancestors
     // in the path that led to this request have Sec-CH-UA-Reduced set.
     // TODO(crbug.com/1258063): Remove once the UserAgentReduction Origin Trial
@@ -1073,17 +1085,41 @@
 
   const std::vector<WebClientHintsType> persisted_hints =
       enabled_hints.GetEnabledHints();
-  PersistAcceptCH(origin, frame_tree_node->GetParentOrOuterDocument(), delegate,
-                  persisted_hints);
+  DCHECK(frame_tree_node);
+  PersistAcceptCH(origin, *frame_tree_node, delegate, persisted_hints);
   return persisted_hints;
 }
 
 void PersistAcceptCH(const url::Origin& origin,
-                     content::RenderFrameHost* parent_rfh,
+                     FrameTreeNode& frame_tree_node,
                      ClientHintsControllerDelegate* delegate,
                      const std::vector<WebClientHintsType>& hints) {
   DCHECK(delegate);
-  delegate->PersistClientHints(origin, parent_rfh, hints);
+
+  // TODO(https://crbug.com/1355279): Moving the if condition from the caller
+  // into this function after PrerenderHost becomes a FrameTreeDelegate. A
+  // clearer pattern should be to check whether it is in a prerendering tree
+  // and return a nullptr if it isn't. However, the current prerender
+  // implementation returns a nullptr in two cases: not prerendered or
+  // prerender is canceled, and the callers cannot distinguish between the two
+  // reasons and have to have another if condition.
+  if (frame_tree_node.frame_tree()->is_prerendering()) {
+    // For prerendering headers, it should not persist the client header until
+    // activation, considering user has not visited the page and allowed it to
+    // change content setting yet. The client hints should apply to navigations
+    // in the prerendering page, and propagate to the global setting upon user
+    // navigation.
+    // If host is nullptr, it means prerender has been canceled and will be
+    // deleted soon, so we do not need to persist anything.
+    if (auto* host =
+            PrerenderHost::GetPrerenderHostFromFrameTreeNode(frame_tree_node)) {
+      host->OnAcceptClientHintChanged(origin, hints);
+    }
+    return;
+  }
+
+  delegate->PersistClientHints(
+      origin, frame_tree_node.GetParentOrOuterDocument(), hints);
 }
 
 std::vector<WebClientHintsType> LookupAcceptCHForCommit(
diff --git a/content/browser/client_hints/client_hints.h b/content/browser/client_hints/client_hints.h
index 4f6603b..0ee016c 100644
--- a/content/browser/client_hints/client_hints.h
+++ b/content/browser/client_hints/client_hints.h
@@ -126,7 +126,7 @@
 // `delegate` cannot be nullptr.
 CONTENT_EXPORT void PersistAcceptCH(
     const url::Origin& origin,
-    content::RenderFrameHost* parent_rfh,
+    FrameTreeNode& frame_tree_node,
     ClientHintsControllerDelegate* delegate,
     const std::vector<network::mojom::WebClientHintsType>& hints);
 
diff --git a/content/browser/preloading/prerender/prerender_browsertest.cc b/content/browser/preloading/prerender/prerender_browsertest.cc
index bebec65..e4542e0 100644
--- a/content/browser/preloading/prerender/prerender_browsertest.cc
+++ b/content/browser/preloading/prerender/prerender_browsertest.cc
@@ -62,6 +62,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/mock_client_hints_controller_delegate.h"
 #include "content/public/test/mock_web_contents_observer.h"
 #include "content/public/test/navigation_handle_observer.h"
 #include "content/public/test/preloading_test_util.h"
@@ -71,6 +72,7 @@
 #include "content/public/test/test_utils.h"
 #include "content/public/test/theme_change_waiter.h"
 #include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_browser_context.h"
 #include "content/shell/browser/shell_content_browser_client.h"
 #include "content/test/content_browser_test_utils_internal.h"
 #include "content/test/mock_commit_deferring_condition.h"
@@ -6918,4 +6920,204 @@
   EXPECT_EQ(prerender_rfh->GetProcess(), current_frame_host()->GetProcess());
 }
 
+class PrerenderClientHintsBrowserTest : public PrerenderBrowserTest {
+ public:
+  PrerenderClientHintsBrowserTest() = default;
+  ~PrerenderClientHintsBrowserTest() override = default;
+
+  void SetUp() override {
+    ssl_server().RegisterRequestHandler(base::BindRepeating(&HandleRequest));
+    PrerenderBrowserTest::SetUp();
+  }
+
+  static std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
+      const net::test_server::HttpRequest& request) {
+    if (request.relative_url.find("acceptch") == std::string::npos)
+      return nullptr;
+
+    // Serve a response indicating clients to provide full version of UA.
+    auto response = std::make_unique<net::test_server::BasicHttpResponse>();
+    if (request.relative_url.find("full-version") != std::string::npos) {
+      response->AddCustomHeader("Accept-CH", "sec-ch-ua-full-version");
+    } else if (request.relative_url.find("bitness") != std::string::npos) {
+      response->AddCustomHeader("Accept-CH", "sec-ch-ua-bitness");
+    } else if (request.relative_url.find("no-value") != std::string::npos) {
+      response->AddCustomHeader("Accept-CH", "");
+    }
+    response->set_code(net::HTTP_OK);
+    if (request.relative_url.find("iframe") != std::string::npos) {
+      response->set_content(R"(
+        <html><head><title>iframe test</title></head>
+        <body>
+        <iframe src="title1.html" id="test"></iframe>
+        </body></html>
+      )");
+      response->set_content_type("text/html");
+    } else if (request.relative_url.find("image") != std::string::npos) {
+      response->set_content(R"(
+        <html>
+        <head></head>
+        <body>
+          <img src="./blank.jpg"/>
+          <p>This page has an image. Yay for images!
+        </body>
+        </html>
+      )");
+      response->set_content_type("text/html");
+
+    } else {
+      response->set_content("");
+      response->set_content_type("text/plain");
+    }
+    return response;
+  }
+
+ protected:
+  bool HasRequestHeader(const GURL& url, const std::string& key) {
+    net::test_server::HttpRequest::HeaderMap headers = GetRequestHeaders(url);
+    return headers.find(key) != headers.end();
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(PrerenderClientHintsBrowserTest,
+                       PrerenderResponseChangesClientHintsLocally) {
+  MockClientHintsControllerDelegate client_hints_controller_delegate(
+      content::GetShellUserAgentMetadata());
+  ShellContentBrowserClient::Get()
+      ->browser_context()
+      ->set_client_hints_controller_delegate(&client_hints_controller_delegate);
+
+  // Navigate to an initial page.
+  GURL url = GetUrl("/empty.html?acceptch-bitness");
+  ASSERT_TRUE(NavigateToURL(shell(), url));
+
+  // Start prerendering.
+  GURL prerender_url = GetUrl("/iframe.html?acceptch-full-version");
+  int host_id = AddPrerender(prerender_url);
+  WaitForPrerenderLoadCompleted(host_id);
+
+  // The main frame request does not contain sec-ch-ua-full-version, because it
+  // is using the global setting at this moment. sec-ch-ua-bitness should be
+  // contained as well, because it is a global setting and applies to all
+  // navigations.
+  EXPECT_TRUE(HasRequestHeader(prerender_url, "sec-ch-ua-bitness"));
+  EXPECT_FALSE(HasRequestHeader(prerender_url, "sec-ch-ua-full-version"));
+
+  // The subframe prerender navigation requests should contain
+  // sec-ch-ua-full-version, as the main frame navigation request changed the
+  // client hints setting.
+  GURL prerender_iframe_url = GetUrl("/title1.html");
+  WaitForRequest(prerender_iframe_url, 1);
+  EXPECT_TRUE(HasRequestHeader(prerender_iframe_url, "sec-ch-ua-full-version"));
+  EXPECT_TRUE(HasRequestHeader(prerender_iframe_url, "sec-ch-ua-bitness"));
+
+  content::test::PrerenderHostObserver prerender_observer(*web_contents_impl(),
+                                                          host_id);
+  NavigatePrimaryPage(prerender_url);
+
+  // The prerendered page should be activated successfully. The settings on the
+  // prerendered page should not apply to the primary navigation before
+  // activation, so at this point the navigation request is using the global
+  // setting, which is the same as the prerender initial navigation.
+  prerender_observer.WaitForActivation();
+
+  GURL real_navigate_url = GetUrl("/empty.html?real");
+  NavigatePrimaryPage(real_navigate_url);
+
+  // The request headers should contain sec-ch-ua-full-version, because the
+  // prerender local setting was propagated to the global setting. The final
+  // setting is the union set of global setting and local setting.
+  EXPECT_TRUE(HasRequestHeader(real_navigate_url, "sec-ch-ua-full-version"));
+  EXPECT_TRUE(HasRequestHeader(prerender_iframe_url, "sec-ch-ua-bitness"));
+}
+
+IN_PROC_BROWSER_TEST_F(PrerenderClientHintsBrowserTest,
+                       ChangesToClientHintsAreDiscardIfNoActivation) {
+  MockClientHintsControllerDelegate client_hints_controller_delegate(
+      content::GetShellUserAgentMetadata());
+  ShellContentBrowserClient::Get()
+      ->browser_context()
+      ->set_client_hints_controller_delegate(&client_hints_controller_delegate);
+
+  // Navigate to an initial page.
+  GURL url = GetUrl("/empty.html");
+  ASSERT_TRUE(NavigateToURL(shell(), url));
+
+  // Start prerendering.
+  GURL prerender_url = GetUrl("/empty.html?acceptch");
+  GURL real_navigate_url = GetUrl("/empty.html?real");
+
+  int host_id = AddPrerender(prerender_url);
+  content::test::PrerenderHostObserver prerender_observer(*web_contents_impl(),
+                                                          host_id);
+  WaitForPrerenderLoadCompleted(host_id);
+  NavigatePrimaryPage(real_navigate_url);
+
+  // The request headers should not contain sec-ch-ua-full-version, because no
+  // primary pages indicate to do so and the prerender local setting has been
+  // discarded.
+  EXPECT_FALSE(HasRequestHeader(real_navigate_url, "sec-ch-ua-full-version"));
+  GURL real_navigate_url_2 = GetUrl("/empty.html?real2");
+  NavigatePrimaryPage(real_navigate_url_2);
+
+  // The request headers should not contain sec-ch-ua-full-version, because no
+  // primary pages indicate to do so and the prerender local setting has been
+  // discarded.
+  EXPECT_FALSE(HasRequestHeader(real_navigate_url_2, "sec-ch-ua-full-version"));
+}
+
+IN_PROC_BROWSER_TEST_F(PrerenderClientHintsBrowserTest,
+                       PrimaryResponsesDoNotResetPrenderSettings) {
+  MockClientHintsControllerDelegate client_hints_controller_delegate(
+      content::GetShellUserAgentMetadata());
+  ShellContentBrowserClient::Get()
+      ->browser_context()
+      ->set_client_hints_controller_delegate(&client_hints_controller_delegate);
+
+  // Navigate to an initial page.
+  GURL url = GetUrl("/empty.html");
+  ASSERT_TRUE(NavigateToURL(shell(), url));
+
+  // Start prerendering.
+  GURL prerender_url = GetUrl("/iframe.html?acceptch-full-version");
+  int host_id = AddPrerender(prerender_url);
+  WaitForPrerenderLoadCompleted(host_id);
+
+  // The main frame request does not contain sec-ch-ua-full-version, because it
+  // is using the global setting at this moment.
+  EXPECT_FALSE(HasRequestHeader(prerender_url, "sec-ch-ua-full-version"));
+
+  // The subframe prerender navigation requests should contain
+  // sec-ch-ua-full-version, as the main frame navigation request changed the
+  // client hints setting.
+  GURL prerender_iframe_url = GetUrl("/title1.html");
+  WaitForRequest(prerender_iframe_url, 1);
+  EXPECT_TRUE(HasRequestHeader(prerender_iframe_url, "sec-ch-ua-full-version"));
+
+  // Open a new tab, and the new page clears all settings.
+  GURL new_tab_url = GetUrl("/image.html?acceptch-no-value");
+  OpenURLParams params(
+      new_tab_url, Referrer(), WindowOpenDisposition::NEW_BACKGROUND_TAB,
+      ui::PAGE_TRANSITION_LINK, /*is_renderer_initiated=*/false);
+  auto* new_web_contents = web_contents_impl()->OpenURL(params);
+  ASSERT_NE(nullptr, new_web_contents);
+  GURL new_tab_image_url = GetUrl("/blank.jpg");
+  WaitForRequest(new_tab_image_url, 1);
+  EXPECT_FALSE(HasRequestHeader(new_tab_url, "sec-ch-ua-full-version"));
+
+  content::test::PrerenderHostObserver prerender_observer(*web_contents_impl(),
+                                                          host_id);
+  NavigatePrimaryPage(prerender_url);
+
+  // The prerendered page should be activated successfully.
+  prerender_observer.WaitForActivation();
+
+  GURL real_navigate_url = GetUrl("/empty.html?real");
+  NavigatePrimaryPage(real_navigate_url);
+
+  // The request headers should contain sec-ch-ua-full-version, because the
+  // prerender local setting was propagated to the global setting.
+  EXPECT_TRUE(HasRequestHeader(real_navigate_url, "sec-ch-ua-full-version"));
+}
+
 }  // namespace content
diff --git a/content/browser/preloading/prerender/prerender_host.cc b/content/browser/preloading/prerender/prerender_host.cc
index 2f1668f..9fe41026 100644
--- a/content/browser/preloading/prerender/prerender_host.cc
+++ b/content/browser/preloading/prerender/prerender_host.cc
@@ -10,6 +10,7 @@
 #include "base/trace_event/common/trace_event_common.h"
 #include "base/trace_event/trace_conversion_helper.h"
 #include "base/trace_event/typed_macros.h"
+#include "content/browser/client_hints/client_hints.h"
 #include "content/browser/devtools/devtools_instrumentation.h"
 #include "content/browser/preloading/prerender/prerender_host_registry.h"
 #include "content/browser/preloading/prerender/prerender_metrics.h"
@@ -22,6 +23,7 @@
 #include "content/browser/site_info.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/back_forward_cache.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/prerender_trigger_type.h"
 #include "content/public/browser/web_contents.h"
@@ -30,8 +32,10 @@
 #include "content/public/common/referrer.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_request_headers.h"
+#include "third_party/blink/public/common/client_hints/enabled_client_hints.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/loader/referrer.mojom.h"
+#include "url/origin.h"
 
 namespace content {
 
@@ -71,6 +75,30 @@
 
 }  // namespace
 
+// static
+PrerenderHost* PrerenderHost::GetPrerenderHostFromFrameTreeNode(
+    FrameTreeNode& frame_tree_node) {
+  WebContentsImpl* web_contents =
+      static_cast<WebContentsImpl*>(WebContentsImpl::FromRenderFrameHost(
+          frame_tree_node.current_frame_host()));
+  DCHECK(web_contents);
+  PrerenderHostRegistry* prerender_registry =
+      web_contents->GetPrerenderHostRegistry();
+  int prerender_host_id =
+      frame_tree_node.frame_tree()->root()->frame_tree_node_id();
+
+  if (PrerenderHost* host =
+          prerender_registry->FindNonReservedHostById(prerender_host_id)) {
+    return host;
+  } else {
+    // TODO(https://crbug.com/1355279): This function can be called during
+    // prerender activation so we have to call FindReservedHostById here and
+    // give it another shot. Consider using delegate after PrerenderHost
+    // implements FrameTree::Delegate.
+    return prerender_registry->FindReservedHostById(prerender_host_id);
+  }
+}
+
 PrerenderHost::PrerenderHost(const PrerenderAttributes& attributes,
                              WebContents& web_contents,
                              base::WeakPtr<PreloadingAttempt> attempt)
@@ -259,11 +287,25 @@
   DCHECK(is_ready_for_activation_);
   is_ready_for_activation_ = false;
 
+  FrameTree& target_frame_tree = page_holder_->GetPrimaryFrameTree();
   std::unique_ptr<StoredPage> page = page_holder_->Activate(navigation_request);
 
   for (auto& observer : observers_)
     observer.OnActivated();
 
+  // The activated page is on the primary tree now. It can propagate the client
+  // hints to the global settings.
+  BrowserContext* browser_context =
+      target_frame_tree.controller().GetBrowserContext();
+  ClientHintsControllerDelegate* client_hints_delegate =
+      browser_context->GetClientHintsControllerDelegate();
+  if (client_hints_delegate) {
+    for (auto& [origin, client_hint] : client_hints_type_) {
+      PersistAcceptCH(origin, *(target_frame_tree.root()),
+                      client_hints_delegate, client_hint);
+    }
+  }
+
   // TODO(crbug.com/1299330): Replace
   // `navigation_request.GetNextPageUkmSourceId()` with prerendered page's UKM
   // source ID.
@@ -708,6 +750,22 @@
   return GetInitialUrl() == url;
 }
 
+void PrerenderHost::OnAcceptClientHintChanged(
+    const url::Origin& origin,
+    const std::vector<network::mojom::WebClientHintsType>& client_hints_type) {
+  client_hints_type_[origin] = client_hints_type;
+}
+
+void PrerenderHost::GetAllowedClientHintsOnPage(
+    const url::Origin& origin,
+    blink::EnabledClientHints* client_hints) const {
+  if (!client_hints_type_.contains(origin))
+    return;
+  for (const auto& hint : client_hints_type_.at(origin)) {
+    client_hints->SetIsEnabled(hint, true);
+  }
+}
+
 void PrerenderHost::Cancel(FinalStatus status) {
   TRACE_EVENT("navigation", "PrerenderHost::Cancel", "final_status", status);
   // Already cancelled.
diff --git a/content/browser/preloading/prerender/prerender_host.h b/content/browser/preloading/prerender/prerender_host.h
index c5828a9..2caf0a23 100644
--- a/content/browser/preloading/prerender/prerender_host.h
+++ b/content/browser/preloading/prerender/prerender_host.h
@@ -24,9 +24,22 @@
 #include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
 #include "url/gurl.h"
 
+namespace blink {
+class EnabledClientHints;
+}  // namespace blink
+
+namespace network::mojom {
+enum class WebClientHintsType;
+}  // namespace network::mojom
+
+namespace url {
+class Origin;
+}  // namespace url
+
 namespace content {
 
 class FrameTree;
+class FrameTreeNode;
 class PrerenderHostRegistry;
 class PrerenderPageHolder;
 class RenderFrameHostImpl;
@@ -134,6 +147,14 @@
     kMaxValue = kRequestDestination,
   };
 
+  // Returns the PrerenderHost that the given `frame_tree_node` is in, if it is
+  // being prerendered. Note that this function returns false if the prerender
+  // has been canceled.
+  // TODO(https://crbug.com/1355279): Always return a non-null ptr if the
+  // frame_tree_node is in a prerendering tree.
+  static PrerenderHost* GetPrerenderHostFromFrameTreeNode(
+      FrameTreeNode& frame_tree_node);
+
   PrerenderHost(const PrerenderAttributes& attributes,
                 WebContents& web_contents,
                 base::WeakPtr<PreloadingAttempt> attempt);
@@ -205,6 +226,18 @@
   // initial_url.
   bool IsUrlMatch(const GURL& url) const;
 
+  // Called when the prerender pages asks the client to change the Accept Client
+  // Hints. The instruction applies to the prerendering page before activation,
+  // and will be persisted to the global setting upon activation.
+  void OnAcceptClientHintChanged(
+      const url::Origin& origin,
+      const std::vector<network::mojom::WebClientHintsType>& client_hints_type);
+
+  // Updates the given `client_hints`.
+  void GetAllowedClientHintsOnPage(
+      const url::Origin& origin,
+      blink::EnabledClientHints* client_hints) const;
+
   // Returns absl::nullopt iff prerendering is initiated by the browser (not by
   // a renderer using Speculation Rules API).
   absl::optional<url::Origin> initiator_origin() const {
@@ -289,6 +322,10 @@
   blink::mojom::BeginNavigationParamsPtr begin_params_;
   blink::mojom::CommonNavigationParamsPtr common_params_;
 
+  // Stores the client hints type that applies to this page.
+  base::flat_map<url::Origin, std::vector<network::mojom::WebClientHintsType>>
+      client_hints_type_;
+
   // Holds the navigation ID for the main frame initial navigation.
   absl::optional<int64_t> initial_navigation_id_;
 };
diff --git a/content/browser/renderer_host/back_forward_cache_metrics.h b/content/browser/renderer_host/back_forward_cache_metrics.h
index 6f6f45b..a5da4fa 100644
--- a/content/browser/renderer_host/back_forward_cache_metrics.h
+++ b/content/browser/renderer_host/back_forward_cache_metrics.h
@@ -6,20 +6,21 @@
 #define CONTENT_BROWSER_RENDERER_HOST_BACK_FORWARD_CACHE_METRICS_H_
 
 #include <bitset>
-#include <set>
+#include <memory>
 
 #include "base/memory/raw_ptr.h"
 #include "base/memory/ref_counted.h"
-#include "base/strings/string_piece.h"
-#include "base/time/tick_clock.h"
 #include "base/time/time.h"
 #include "content/browser/renderer_host/should_swap_browsing_instance.h"
 #include "content/common/content_export.h"
-#include "content/common/navigation_client.mojom.h"
 #include "content/public/browser/back_forward_cache.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h"
-#include "third_party/blink/public/mojom/back_forward_cache_not_restored_reasons.mojom.h"
+#include "third_party/blink/public/mojom/back_forward_cache_not_restored_reasons.mojom-forward.h"
+
+namespace base {
+class TickClock;
+}
 
 namespace url {
 class Origin;
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 971a14a..6e26159 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -985,8 +985,8 @@
     }
   }
   if (need_update_storage) {
-    PersistAcceptCH(url::Origin::Create(url),
-                    frame_tree_node->GetParentOrOuterDocument(), delegate,
+    DCHECK(frame_tree_node);
+    PersistAcceptCH(url::Origin::Create(url), *frame_tree_node, delegate,
                     client_hints);
   }
 }
diff --git a/content/browser/webauth/authenticator_common.cc b/content/browser/webauth/authenticator_common.cc
index 7b577884..cae87b7 100644
--- a/content/browser/webauth/authenticator_common.cc
+++ b/content/browser/webauth/authenticator_common.cc
@@ -1661,12 +1661,8 @@
   auto common_info = blink::mojom::CommonCredentialInfo::New();
   common_info->client_data_json.assign(client_data_json_.begin(),
                                        client_data_json_.end());
-  common_info->authenticator_data = response_data.attestation_object()
-                                        .authenticator_data()
-                                        .SerializeToByteArray();
   common_info->raw_id = response_data.attestation_object().GetCredentialId();
   common_info->id = Base64UrlEncode(common_info->raw_id);
-  response->info = std::move(common_info);
 
   response->authenticator_attachment =
       response_data.transport_used()
@@ -1783,6 +1779,10 @@
   }
   response->attestation_object =
       response_data.GetCBOREncodedAttestationObject();
+  common_info->authenticator_data = response_data.attestation_object()
+                                        .authenticator_data()
+                                        .SerializeToByteArray();
+  response->info = std::move(common_info);
 
   const device::PublicKey* public_key = response_data.attestation_object()
                                             .authenticator_data()
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index 3b08529..6de138c8 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -4474,7 +4474,18 @@
     ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
     const auto& response = result.response;
     EXPECT_EQ(response->public_key_algo, static_cast<int32_t>(test.algo));
-    EXPECT_FALSE(response->info->authenticator_data.empty());
+
+    // The value of the parsed authenticator data should match what's in
+    // the attestation object.
+    absl::optional<Value> attestation_value =
+        Reader::Read(response->attestation_object);
+    CHECK(attestation_value);
+    const auto& attestation = attestation_value->GetMap();
+    const auto auth_data_it = attestation.find(Value(device::kAuthDataKey));
+    CHECK(auth_data_it != attestation.end());
+    const std::vector<uint8_t>& auth_data =
+        auth_data_it->second.GetBytestring();
+    EXPECT_EQ(auth_data, response->info->authenticator_data);
 
     ASSERT_EQ(test.evp_id.has_value(), response->public_key_der.has_value());
     if (!test.evp_id) {
diff --git a/content/services/shared_storage_worklet/shared_storage.cc b/content/services/shared_storage_worklet/shared_storage.cc
index 8b27110..20d8aef 100644
--- a/content/services/shared_storage_worklet/shared_storage.cc
+++ b/content/services/shared_storage_worklet/shared_storage.cc
@@ -5,6 +5,7 @@
 #include "content/services/shared_storage_worklet/shared_storage.h"
 
 #include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
 #include "content/services/shared_storage_worklet/shared_storage_iterator.h"
 #include "content/services/shared_storage_worklet/worklet_v8_helper.h"
 #include "gin/arguments.h"
@@ -34,6 +35,32 @@
   return gin::ConvertFromV8<std::u16string>(isolate, str, &out);
 }
 
+void LogTimingHistogramForVoidOperation(
+    blink::SharedStorageVoidOperation caller,
+    base::TimeTicks start_time) {
+  base::TimeDelta elapsed_time = base::TimeTicks::Now() - start_time;
+  switch (caller) {
+    case blink::SharedStorageVoidOperation::kSet:
+      base::UmaHistogramMediumTimes("Storage.SharedStorage.Worklet.Timing.Set",
+                                    elapsed_time);
+      break;
+    case blink::SharedStorageVoidOperation::kAppend:
+      base::UmaHistogramMediumTimes(
+          "Storage.SharedStorage.Worklet.Timing.Append", elapsed_time);
+      break;
+    case blink::SharedStorageVoidOperation::kDelete:
+      base::UmaHistogramMediumTimes(
+          "Storage.SharedStorage.Worklet.Timing.Delete", elapsed_time);
+      break;
+    case blink::SharedStorageVoidOperation::kClear:
+      base::UmaHistogramMediumTimes(
+          "Storage.SharedStorage.Worklet.Timing.Clear", elapsed_time);
+      break;
+    default:
+      NOTREACHED();
+  }
+}
+
 }  // namespace
 
 SharedStorage::SharedStorage(mojom::SharedStorageWorkletServiceClient* client)
@@ -61,6 +88,7 @@
 }
 
 v8::Local<v8::Promise> SharedStorage::Set(gin::Arguments* args) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
   v8::Isolate* isolate = args->isolate();
 
   v8::Local<v8::Promise::Resolver> resolver =
@@ -118,12 +146,14 @@
       arg0_key, arg1_value, ignore_if_present,
       base::BindOnce(&SharedStorage::OnVoidOperationFinished,
                      weak_ptr_factory_.GetWeakPtr(), isolate,
-                     v8::Global<v8::Promise::Resolver>(isolate, resolver)));
+                     v8::Global<v8::Promise::Resolver>(isolate, resolver),
+                     blink::SharedStorageVoidOperation::kSet, start_time));
 
   return promise;
 }
 
 v8::Local<v8::Promise> SharedStorage::Append(gin::Arguments* args) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
   v8::Isolate* isolate = args->isolate();
 
   v8::Local<v8::Promise::Resolver> resolver =
@@ -162,12 +192,14 @@
       arg0_key, arg1_value,
       base::BindOnce(&SharedStorage::OnVoidOperationFinished,
                      weak_ptr_factory_.GetWeakPtr(), isolate,
-                     v8::Global<v8::Promise::Resolver>(isolate, resolver)));
+                     v8::Global<v8::Promise::Resolver>(isolate, resolver),
+                     blink::SharedStorageVoidOperation::kAppend, start_time));
 
   return promise;
 }
 
 v8::Local<v8::Promise> SharedStorage::Delete(gin::Arguments* args) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
   v8::Isolate* isolate = args->isolate();
 
   v8::Local<v8::Promise::Resolver> resolver =
@@ -194,12 +226,14 @@
       arg0_key,
       base::BindOnce(&SharedStorage::OnVoidOperationFinished,
                      weak_ptr_factory_.GetWeakPtr(), isolate,
-                     v8::Global<v8::Promise::Resolver>(isolate, resolver)));
+                     v8::Global<v8::Promise::Resolver>(isolate, resolver),
+                     blink::SharedStorageVoidOperation::kDelete, start_time));
 
   return promise;
 }
 
 v8::Local<v8::Promise> SharedStorage::Clear(gin::Arguments* args) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
   v8::Isolate* isolate = args->isolate();
 
   v8::Local<v8::Promise::Resolver> resolver =
@@ -210,12 +244,14 @@
 
   client_->SharedStorageClear(base::BindOnce(
       &SharedStorage::OnVoidOperationFinished, weak_ptr_factory_.GetWeakPtr(),
-      isolate, v8::Global<v8::Promise::Resolver>(isolate, resolver)));
+      isolate, v8::Global<v8::Promise::Resolver>(isolate, resolver),
+      blink::SharedStorageVoidOperation::kClear, start_time));
 
   return promise;
 }
 
 v8::Local<v8::Promise> SharedStorage::Get(gin::Arguments* args) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
   v8::Isolate* isolate = args->isolate();
 
   v8::Local<v8::Promise::Resolver> resolver =
@@ -243,7 +279,8 @@
       arg0_key,
       base::BindOnce(&SharedStorage::OnStringRetrievalOperationFinished,
                      weak_ptr_factory_.GetWeakPtr(), isolate,
-                     v8::Global<v8::Promise::Resolver>(isolate, resolver)));
+                     v8::Global<v8::Promise::Resolver>(isolate, resolver),
+                     start_time));
   return promise;
 }
 
@@ -261,6 +298,7 @@
 }
 
 v8::Local<v8::Promise> SharedStorage::Length(gin::Arguments* args) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
   v8::Isolate* isolate = args->isolate();
 
   v8::Local<v8::Promise::Resolver> resolver =
@@ -271,7 +309,8 @@
 
   client_->SharedStorageLength(base::BindOnce(
       &SharedStorage::OnLengthOperationFinished, weak_ptr_factory_.GetWeakPtr(),
-      isolate, v8::Global<v8::Promise::Resolver>(isolate, resolver)));
+      isolate, v8::Global<v8::Promise::Resolver>(isolate, resolver),
+      start_time));
 
   return promise;
 }
@@ -279,6 +318,8 @@
 void SharedStorage::OnVoidOperationFinished(
     v8::Isolate* isolate,
     v8::Global<v8::Promise::Resolver> global_resolver,
+    blink::SharedStorageVoidOperation caller,
+    base::TimeTicks start_time,
     bool success,
     const std::string& error_message) {
   WorkletV8Helper::HandleScope scope(isolate);
@@ -287,6 +328,7 @@
 
   if (success) {
     resolver->Resolve(context, v8::Undefined(isolate)).ToChecked();
+    LogTimingHistogramForVoidOperation(caller, start_time);
     return;
   }
 
@@ -297,22 +339,28 @@
 void SharedStorage::OnStringRetrievalOperationFinished(
     v8::Isolate* isolate,
     v8::Global<v8::Promise::Resolver> global_resolver,
+    base::TimeTicks start_time,
     shared_storage_worklet::mojom::SharedStorageGetStatus status,
     const std::string& error_message,
     const std::u16string& result) {
   WorkletV8Helper::HandleScope scope(isolate);
   v8::Local<v8::Promise::Resolver> resolver = global_resolver.Get(isolate);
   v8::Local<v8::Context> context = resolver->GetCreationContextChecked();
+  base::TimeDelta elapsed_time = base::TimeTicks::Now() - start_time;
 
   if (status ==
       shared_storage_worklet::mojom::SharedStorageGetStatus::kSuccess) {
     resolver->Resolve(context, gin::ConvertToV8(isolate, result)).ToChecked();
+    base::UmaHistogramMediumTimes("Storage.SharedStorage.Worklet.Timing.Get",
+                                  elapsed_time);
     return;
   }
 
   if (status ==
       shared_storage_worklet::mojom::SharedStorageGetStatus::kNotFound) {
     resolver->Resolve(context, v8::Undefined(isolate)).ToChecked();
+    base::UmaHistogramMediumTimes("Storage.SharedStorage.Worklet.Timing.Get",
+                                  elapsed_time);
     return;
   }
 
@@ -323,6 +371,7 @@
 void SharedStorage::OnLengthOperationFinished(
     v8::Isolate* isolate,
     v8::Global<v8::Promise::Resolver> global_resolver,
+    base::TimeTicks start_time,
     bool success,
     const std::string& error_message,
     uint32_t length) {
@@ -333,6 +382,8 @@
   if (success) {
     resolver->Resolve(context, gin::Converter<uint32_t>::ToV8(isolate, length))
         .ToChecked();
+    base::UmaHistogramMediumTimes("Storage.SharedStorage.Worklet.Timing.Length",
+                                  base::TimeTicks::Now() - start_time);
     return;
   }
 
diff --git a/content/services/shared_storage_worklet/shared_storage.h b/content/services/shared_storage_worklet/shared_storage.h
index 84a8dc3..b0efea5 100644
--- a/content/services/shared_storage_worklet/shared_storage.h
+++ b/content/services/shared_storage_worklet/shared_storage.h
@@ -6,9 +6,11 @@
 #define CONTENT_SERVICES_SHARED_STORAGE_WORKLET_SHARED_STORAGE_H_
 
 #include "base/memory/raw_ptr.h"
+#include "base/time/time.h"
 #include "content/common/shared_storage_worklet_service.mojom.h"
 #include "gin/object_template_builder.h"
 #include "gin/wrappable.h"
+#include "third_party/blink/public/common/shared_storage/shared_storage_utils.h"
 
 namespace gin {
 class Arguments;
@@ -41,12 +43,15 @@
   void OnVoidOperationFinished(
       v8::Isolate* isolate,
       v8::Global<v8::Promise::Resolver> global_resolver,
+      blink::SharedStorageVoidOperation caller,
+      base::TimeTicks start_time,
       bool success,
       const std::string& error_message);
 
   void OnStringRetrievalOperationFinished(
       v8::Isolate* isolate,
       v8::Global<v8::Promise::Resolver> global_resolver,
+      base::TimeTicks start_time,
       shared_storage_worklet::mojom::SharedStorageGetStatus status,
       const std::string& error_message,
       const std::u16string& result);
@@ -54,6 +59,7 @@
   void OnLengthOperationFinished(
       v8::Isolate* isolate,
       v8::Global<v8::Promise::Resolver> global_resolver,
+      base::TimeTicks start_time,
       bool success,
       const std::string& error_message,
       uint32_t length);
diff --git a/content/services/shared_storage_worklet/shared_storage_iterator.cc b/content/services/shared_storage_worklet/shared_storage_iterator.cc
index c4b5f71..24309fb 100644
--- a/content/services/shared_storage_worklet/shared_storage_iterator.cc
+++ b/content/services/shared_storage_worklet/shared_storage_iterator.cc
@@ -59,6 +59,7 @@
 }
 
 v8::Local<v8::Promise> SharedStorageIterator::Next(gin::Arguments* args) {
+  next_start_times_.push(base::TimeTicks::Now());
   v8::Isolate* isolate = args->isolate();
   v8::Local<v8::Context> context = args->GetHolderCreationContext();
 
@@ -77,6 +78,11 @@
   if (has_error_) {
     resolver->Reject(context, gin::StringToV8(isolate, error_message_))
         .ToChecked();
+
+    // We only record timing histograms when there is no error. Discard the
+    // start time for this call.
+    DCHECK(!next_start_times_.empty());
+    next_start_times_.pop();
     return promise;
   }
 
@@ -99,6 +105,7 @@
       next_benchmark_for_iteration_ += kSharedStorageIteratorBenchmarkStep;
     }
 
+    LogElapsedTime();
     return promise;
   }
 
@@ -113,6 +120,7 @@
 
   DCHECK(pending_resolvers_.empty());
   resolver->Resolve(context, CreateIteratorResultDone(isolate)).ToChecked();
+  LogElapsedTime();
   return promise;
 }
 
@@ -221,4 +229,21 @@
   return (100 * value) / total_entries_queued_ >= benchmark;
 }
 
+void SharedStorageIterator::LogElapsedTime() {
+  DCHECK(!next_start_times_.empty());
+  base::TimeDelta elapsed_time =
+      base::TimeTicks::Now() - next_start_times_.front();
+  next_start_times_.pop();
+  switch (mode_) {
+    case SharedStorageIterator::Mode::kKey:
+      base::UmaHistogramMediumTimes(
+          "Storage.SharedStorage.Worklet.Timing.Keys.Next", elapsed_time);
+      break;
+    case SharedStorageIterator::Mode::kKeyValue:
+      base::UmaHistogramMediumTimes(
+          "Storage.SharedStorage.Worklet.Timing.Entries.Next", elapsed_time);
+      break;
+  }
+}
+
 }  // namespace shared_storage_worklet
diff --git a/content/services/shared_storage_worklet/shared_storage_iterator.h b/content/services/shared_storage_worklet/shared_storage_iterator.h
index 61e1ed6..dafa739 100644
--- a/content/services/shared_storage_worklet/shared_storage_iterator.h
+++ b/content/services/shared_storage_worklet/shared_storage_iterator.h
@@ -6,8 +6,10 @@
 #define CONTENT_SERVICES_SHARED_STORAGE_WORKLET_SHARED_STORAGE_ITERATOR_H_
 
 #include <deque>
+#include <queue>
 
 #include "base/memory/raw_ptr.h"
+#include "base/time/time.h"
 #include "components/services/storage/shared_storage/public/mojom/shared_storage.mojom.h"
 #include "content/common/shared_storage_worklet_service.mojom.h"
 #include "gin/object_template_builder.h"
@@ -68,6 +70,9 @@
   // logging.
   bool MeetsBenchmark(int value, int benchmark);
 
+  // Logs the elasped time for calls to `Next()` to a histogram.
+  void LogElapsedTime();
+
   Mode mode_;
 
   // The error state can only be set once, when the first error is encountered
@@ -111,6 +116,10 @@
   // has not been logged.
   int next_benchmark_for_iteration_ = kSharedStorageIteratorBenchmarkStep;
 
+  // Start times of each call to `Next()`, in order of the call. Used to record
+  // a timing histogram.
+  std::queue<base::TimeTicks> next_start_times_;
+
   mojo::Receiver<mojom::SharedStorageEntriesListener> receiver_{this};
 };
 
diff --git a/content/test/gpu/gpu_tests/context_lost_integration_test.py b/content/test/gpu/gpu_tests/context_lost_integration_test.py
index 35867bb..b9dd290 100644
--- a/content/test/gpu/gpu_tests/context_lost_integration_test.py
+++ b/content/test/gpu/gpu_tests/context_lost_integration_test.py
@@ -535,7 +535,7 @@
     # lost.
     if not self._IsDualGPUMacLaptop():
       logging.info('Skipping test because not running on dual-GPU Mac laptop')
-      return
+      self.skipTest('Not running on dual-GPU Mac laptop')
     # Start with a browser with clean GPU process state.
     self.RestartBrowserWithArgs([])
     # Wait a few seconds for the system to dispatch any GPU switched
@@ -556,7 +556,7 @@
     # renderbuffers via the WebGL 2.0 API, does not crash.
     if not self._IsDualGPUMacLaptop():
       logging.info('Skipping test because not running on dual-GPU Mac laptop')
-      return
+      self.skipTest('Not running on dual-GPU Mac laptop')
     # Start with a browser with clean GPU process state.
     self.RestartBrowserWithArgs([])
     # Wait a few seconds for the system to dispatch any GPU switched
@@ -577,7 +577,7 @@
     # the context to be lost.
     if not self._IsDualGPUMacLaptop():
       logging.info('Skipping test because not running on dual-GPU Mac laptop')
-      return
+      self.skipTest('Not running on dual-GPU Mac laptop')
     # Start with a browser with clean GPU process state.
     self.RestartBrowserWithArgs([])
     # Wait a few seconds for the system to dispatch any GPU switched
@@ -625,7 +625,7 @@
     # Currently the test only works on Mac dual GPU bots.
     if not self._IsDualGPUMacLaptop():
       logging.info('Skipping test because not running on dual-GPU Mac laptop')
-      return
+      self.skipTest('Not running on dual-GPU Mac laptop')
     self.RestartBrowserIfNecessaryWithArgs(
         [cba.DISABLE_DOMAIN_BLOCKING_FOR_3D_APIS])
     active_vendor_id = self._GetActiveVendorId(False)
diff --git a/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider_impl.cc b/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider_impl.cc
index dd4e643..4855fba 100644
--- a/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider_impl.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider_impl.cc
@@ -452,6 +452,12 @@
           ? device::BluetoothGattCharacteristic::NotificationType::kIndication
           : device::BluetoothGattCharacteristic::NotificationType::
                 kNotification);
+
+  // This is temporary fix to unblock b/191129417.
+  // TODO(b/191129417); Plumb the callback up to ARC++ and add unit test.
+  std::unique_ptr<dbus::Response> response =
+      dbus::Response::FromMethodCall(method_call);
+  std::move(response_sender).Run(std::move(response));
 }
 
 void BluetoothGattCharacteristicServiceProviderImpl::StopNotify(
@@ -471,6 +477,12 @@
 
   DCHECK(delegate_);
   delegate_->StopNotifications(device_path);
+
+  // This is temporary fix to unblock b/191129417.
+  // TODO(b/191129417); Plumb the callback up to ARC++ and add unit test.
+  std::unique_ptr<dbus::Response> response =
+      dbus::Response::FromMethodCall(method_call);
+  std::move(response_sender).Run(std::move(response));
 }
 
 void BluetoothGattCharacteristicServiceProviderImpl::OnExported(
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc
index 7168afc8..3a3d9f9 100644
--- a/extensions/browser/extension_prefs.cc
+++ b/extensions/browser/extension_prefs.cc
@@ -2286,6 +2286,7 @@
   registry->RegisterBooleanPref(pref_names::kChromeAppsEnabled, false);
 #endif
   registry->RegisterBooleanPref(pref_names::kU2fSecurityKeyApiEnabled, false);
+  registry->RegisterBooleanPref(pref_names::kLoadCryptoTokenExtension, false);
 
   registry->RegisterListPref(pref_names::kNativeMessagingBlocklist);
   registry->RegisterListPref(pref_names::kNativeMessagingAllowlist);
diff --git a/extensions/browser/pref_names.cc b/extensions/browser/pref_names.cc
index 2693cab..5df7519 100644
--- a/extensions/browser/pref_names.cc
+++ b/extensions/browser/pref_names.cc
@@ -53,6 +53,8 @@
 #endif
 const char kU2fSecurityKeyApiEnabled[] =
     "extensions.u2f_security_key_api_enabled";
+const char kLoadCryptoTokenExtension[] =
+    "extensions.load_cryptotoken_extension";
 
 const char kPrefPreferences[] = "preferences";
 const char kPrefIncognitoPreferences[] = "incognito_preferences";
diff --git a/extensions/browser/pref_names.h b/extensions/browser/pref_names.h
index c0c9121..b6d185d9 100644
--- a/extensions/browser/pref_names.h
+++ b/extensions/browser/pref_names.h
@@ -113,6 +113,12 @@
 // TODO(1224886): Delete together with CryptoToken code.
 extern const char kU2fSecurityKeyApiEnabled[];
 
+// A boolean indicating whether the CryptoToken component extension should be
+// loaded at startup.
+//
+// TODO(1224886): Delete together with CryptoToken code.
+extern const char kLoadCryptoTokenExtension[];
+
 // Properties in kExtensions dictionaries --------------------------------------
 
 // Extension-controlled preferences.
diff --git a/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc b/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc
index 16ec6ec..b8b6f439 100644
--- a/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc
+++ b/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc
@@ -13,6 +13,7 @@
 #include "extensions/renderer/api/automation/automation_internal_custom_bindings.h"
 #include "ui/accessibility/ax_language_detection.h"
 #include "ui/accessibility/ax_node_position.h"
+#include "ui/accessibility/ax_selection.h"
 
 namespace extensions {
 
@@ -250,7 +251,7 @@
   return found;
 }
 
-ui::AXTree::Selection AutomationAXTreeWrapper::GetUnignoredSelection() {
+ui::AXSelection AutomationAXTreeWrapper::GetUnignoredSelection() {
   return ax_tree_->GetUnignoredSelection();
 }
 
diff --git a/extensions/renderer/api/automation/automation_ax_tree_wrapper.h b/extensions/renderer/api/automation/automation_ax_tree_wrapper.h
index c2239817..46e5663 100644
--- a/extensions/renderer/api/automation/automation_ax_tree_wrapper.h
+++ b/extensions/renderer/api/automation/automation_ax_tree_wrapper.h
@@ -67,7 +67,7 @@
   // document.activeElement (within the DOM).
   bool IsInFocusChain(int32_t node_id);
 
-  ui::AXTree::Selection GetUnignoredSelection();
+  ui::AXSelection GetUnignoredSelection();
 
   // Returns an AXNode from the underlying tree if it both exists and is not
   // ignored.
diff --git a/extensions/renderer/api/automation/automation_internal_custom_bindings.cc b/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
index 6cd3124b..a4c2132 100644
--- a/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
+++ b/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
@@ -46,6 +46,7 @@
 #include "ui/accessibility/ax_node_position.h"
 #include "ui/accessibility/ax_range.h"
 #include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/ax_text_utils.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/geometry/rect_conversions.h"
@@ -754,7 +755,7 @@
       "GetSelectionStartObjectID",
       [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
          AutomationAXTreeWrapper* tree_wrapper) {
-        ui::AXTree::Selection unignored_selection =
+        ui::AXSelection unignored_selection =
             tree_wrapper->GetUnignoredSelection();
         int32_t start_object_id = unignored_selection.is_backward
                                       ? unignored_selection.focus_object_id
@@ -765,7 +766,7 @@
       "GetSelectionStartOffset",
       [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
          AutomationAXTreeWrapper* tree_wrapper) {
-        ui::AXTree::Selection unignored_selection =
+        ui::AXSelection unignored_selection =
             tree_wrapper->GetUnignoredSelection();
         int start_offset = unignored_selection.is_backward
                                ? unignored_selection.focus_offset
@@ -776,7 +777,7 @@
       "GetSelectionStartAffinity",
       [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
          AutomationAXTreeWrapper* tree_wrapper) {
-        ui::AXTree::Selection unignored_selection =
+        ui::AXSelection unignored_selection =
             tree_wrapper->GetUnignoredSelection();
         ax::mojom::TextAffinity start_affinity =
             unignored_selection.is_backward
@@ -788,7 +789,7 @@
       "GetSelectionEndObjectID",
       [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
          AutomationAXTreeWrapper* tree_wrapper) {
-        ui::AXTree::Selection unignored_selection =
+        ui::AXSelection unignored_selection =
             tree_wrapper->GetUnignoredSelection();
         int32_t end_object_id = unignored_selection.is_backward
                                     ? unignored_selection.anchor_object_id
@@ -799,7 +800,7 @@
       "GetSelectionEndOffset",
       [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
          AutomationAXTreeWrapper* tree_wrapper) {
-        ui::AXTree::Selection unignored_selection =
+        ui::AXSelection unignored_selection =
             tree_wrapper->GetUnignoredSelection();
         int end_offset = unignored_selection.is_backward
                              ? unignored_selection.anchor_offset
@@ -810,7 +811,7 @@
       "GetSelectionEndAffinity",
       [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
          AutomationAXTreeWrapper* tree_wrapper) {
-        ui::AXTree::Selection unignored_selection =
+        ui::AXSelection unignored_selection =
             tree_wrapper->GetUnignoredSelection();
         ax::mojom::TextAffinity end_affinity =
             unignored_selection.is_backward
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg
index 2f501fa..be4cf927 100644
--- a/infra/config/generated/luci/luci-milo.cfg
+++ b/infra/config/generated/luci/luci-milo.cfg
@@ -4264,11 +4264,6 @@
     short_name: "x86"
   }
   builders {
-    name: "buildbucket/luci.chromium.ci/android-pie-x86-fyi-rel-reviver"
-    category: "builder_tester|x86"
-    short_name: "P"
-  }
-  builders {
     name: "buildbucket/luci.chromium.ci/android-cronet-asan-x86-rel"
     category: "cronet|asan"
   }
@@ -4303,6 +4298,11 @@
     short_name: "M"
   }
   builders {
+    name: "buildbucket/luci.chromium.ci/android-pie-x86-fyi-rel-reviver"
+    category: "reviver"
+    short_name: "P"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/android-12-x64-dbg-tests"
     category: "tester|phone"
     short_name: "12"
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg
index 826e229..2b559e95 100644
--- a/infra/config/generated/luci/luci-scheduler.cfg
+++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -4724,6 +4724,17 @@
   }
 }
 job {
+  id: "android-pie-x86-fyi-rel-reviver"
+  realm: "ci"
+  schedule: "0 1,4,7,10,13 * * *"
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "ci"
+    builder: "android-pie-x86-fyi-rel-reviver"
+  }
+}
+job {
   id: "android-pie-x86-rel"
   realm: "ci"
   acl_sets: "ci"
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.fyi.star b/infra/config/subprojects/chromium/ci/chromium.android.fyi.star
index 6649873..a57d3c7 100644
--- a/infra/config/subprojects/chromium/ci/chromium.android.fyi.star
+++ b/infra/config/subprojects/chromium/ci/chromium.android.fyi.star
@@ -175,9 +175,11 @@
         build_gs_bucket = "chromium-android-archive",
     ),
     console_view_entry = consoles.console_view_entry(
-        category = "builder_tester|x86",
+        category = "reviver",
         short_name = "P",
     ),
+    # To avoid peak hours, we run it at 1 AM, 4 AM, 7 AM, 10AM, 1 PM UTC.
+    schedule = "0 1,4,7,10,13 * * *",
     # Set to an empty list to avoid chromium-gitiles-trigger triggering new
     # builds. Also we don't set any `schedule` since this builder is for
     # reference only and should not run any new builds.
diff --git a/ios/chrome/browser/discover_feed/discover_feed_service.h b/ios/chrome/browser/discover_feed/discover_feed_service.h
index 41c47d86..b35acfb 100644
--- a/ios/chrome/browser/discover_feed/discover_feed_service.h
+++ b/ios/chrome/browser/discover_feed/discover_feed_service.h
@@ -90,6 +90,9 @@
   // Informs the service that the Following content has been seen.
   virtual void SetFollowingFeedContentSeen() = 0;
 
+  // Informs the service that Browsing History data was cleread by the user.
+  virtual void BrowsingHistoryCleared();
+
   // Methods to register or remove observers.
   void AddObserver(DiscoverFeedObserver* observer);
   void RemoveObserver(DiscoverFeedObserver* observer);
diff --git a/ios/chrome/browser/discover_feed/discover_feed_service.mm b/ios/chrome/browser/discover_feed/discover_feed_service.mm
index 29da5a2..1bc4aac 100644
--- a/ios/chrome/browser/discover_feed/discover_feed_service.mm
+++ b/ios/chrome/browser/discover_feed/discover_feed_service.mm
@@ -30,3 +30,5 @@
     observer.OnDiscoverFeedModelRecreated();
   }
 }
+
+void DiscoverFeedService::BrowsingHistoryCleared() {}
diff --git a/ios/chrome/browser/promos_manager/BUILD.gn b/ios/chrome/browser/promos_manager/BUILD.gn
index fbaf2f3..50840df 100644
--- a/ios/chrome/browser/promos_manager/BUILD.gn
+++ b/ios/chrome/browser/promos_manager/BUILD.gn
@@ -16,6 +16,7 @@
     "//base",
     "//components/prefs",
     "//ios/chrome/browser:pref_names",
+    "//third_party/abseil-cpp:absl",
   ]
 }
 
@@ -83,5 +84,6 @@
     "//ios/chrome/browser:pref_names",
     "//testing/gmock",
     "//testing/gtest",
+    "//third_party/abseil-cpp:absl",
   ]
 }
diff --git a/ios/chrome/browser/promos_manager/promos_manager.h b/ios/chrome/browser/promos_manager/promos_manager.h
index de4e7bf..761168a 100644
--- a/ios/chrome/browser/promos_manager/promos_manager.h
+++ b/ios/chrome/browser/promos_manager/promos_manager.h
@@ -12,6 +12,7 @@
 #import "components/prefs/pref_service.h"
 #import "ios/chrome/browser/promos_manager/constants.h"
 #import "ios/chrome/browser/promos_manager/impression_limit.h"
+#import "third_party/abseil-cpp/absl/types/optional.h"
 
 class PromosManagerTest;
 
@@ -43,6 +44,19 @@
   NSArray<ImpressionLimit*>* PromoImpressionLimits(
       promos_manager::Promo promo) const;
 
+  // Returns the least recently shown promo given the set of currently active
+  // promo campaigns, `active_promos`. Assumes that `sorted_impressions` is
+  // sorted by day (most recent -> least recent).
+  //
+  // When `active_promos` is empty, returns absl::nullopt.
+  //
+  // When `sorted_impressions` is empty, no "least recently shown" promo
+  // exists—because no promo has ever been shown. In this case,
+  // return the first promo in `active_promos`.
+  absl::optional<promos_manager::Promo> LeastRecentlyShown(
+      const std::set<promos_manager::Promo>& active_promos,
+      const std::vector<promos_manager::Impression>& sorted_impressions) const;
+
   // Impression limits that count against all promos.
   NSArray<ImpressionLimit*>* GlobalImpressionLimits() const;
 
@@ -63,9 +77,6 @@
       promos_manager::Promo promo,
       std::vector<promos_manager::Impression>& sorted_impressions) const;
 
-  // Allow unit tests to access private methods.
-  friend class PromosManagerTest;
-
   // Returns true if any impression limit from `impression_limits` is triggered,
   // and false otherwise.
   //
@@ -139,6 +150,20 @@
                            DetectsNoImpressionLimitTriggered);
   FRIEND_TEST_ALL_PREFIXES(PromosManagerTest, DecidesCanShowPromo);
   FRIEND_TEST_ALL_PREFIXES(PromosManagerTest, DecidesCannotShowPromo);
+  FRIEND_TEST_ALL_PREFIXES(PromosManagerTest, ReturnsLeastRecentlyShown);
+  FRIEND_TEST_ALL_PREFIXES(PromosManagerTest,
+                           ReturnsLeastRecentlyShownWithSomeInactivePromos);
+  FRIEND_TEST_ALL_PREFIXES(PromosManagerTest,
+                           ReturnsLeastRecentlyShownBreakingTies);
+  FRIEND_TEST_ALL_PREFIXES(PromosManagerTest,
+                           ReturnsLeastRecentlyShownWithOnlyOnePromoActive);
+  FRIEND_TEST_ALL_PREFIXES(PromosManagerTest,
+                           ReturnsLeastRecentlyShownWithoutImpressionHistory);
+  FRIEND_TEST_ALL_PREFIXES(
+      PromosManagerTest,
+      ReturnsNulloptWhenLeastRecentlyShownHasNoActivePromoCampaigns);
+  FRIEND_TEST_ALL_PREFIXES(PromosManagerTest,
+                           ReturnsFirstUnshownPromoForLeastRecentlyShown);
 };
 
 #endif  // IOS_CHROME_BROWSER_PROMOS_MANAGER_PROMOS_MANAGER_H_
diff --git a/ios/chrome/browser/promos_manager/promos_manager.mm b/ios/chrome/browser/promos_manager/promos_manager.mm
index 02d9daa..7731cf1 100644
--- a/ios/chrome/browser/promos_manager/promos_manager.mm
+++ b/ios/chrome/browser/promos_manager/promos_manager.mm
@@ -10,6 +10,7 @@
 #import <iterator>
 #import <map>
 #import <numeric>
+#import <set>
 #import <vector>
 
 #import "base/time/time.h"
@@ -19,6 +20,7 @@
 #import "ios/chrome/browser/promos_manager/constants.h"
 #import "ios/chrome/browser/promos_manager/features.h"
 #import "ios/chrome/browser/promos_manager/impression_limit.h"
+#import "third_party/abseil-cpp/absl/types/optional.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -231,3 +233,43 @@
 
   return std::accumulate(counts.begin(), counts.end(), 0);
 }
+
+absl::optional<promos_manager::Promo> PromosManager::LeastRecentlyShown(
+    const std::set<promos_manager::Promo>& active_promos,
+    const std::vector<promos_manager::Impression>& sorted_impressions) const {
+  // If there are no active promos, return absl::nullopt.
+  // (This is seldom expected to happen, if ever, as Promos Manager will launch
+  // with promos_manager::Promo::DefaultBrowser continuously running.)
+  if (active_promos.empty())
+    return absl::nullopt;
+
+  // When the impression history is empty, no "least recently shown" promo
+  // exists—because no promo has ever been shown. In this case,
+  // return the first promo in `active_promos`.
+  if (sorted_impressions.empty())
+    return *active_promos.begin();
+
+  // Loop over the impression history, `sorted_impressions`, and remove promos
+  // from `shown` as they are found. Given `sorted_impressions` is sorted from
+  // most recent -> least recent, the most recently shown promos will be removed
+  // from `shown` first. When `shown` contains just one promo, it must be the
+  // least recently shown promo.
+  std::set<promos_manager::Promo> shown(active_promos);
+
+  for (promos_manager::Impression impression : sorted_impressions) {
+    if (shown.size() == 1)
+      return *shown.begin();
+
+    // Given `shown` only contains active promos, impression history for
+    // inactive promos will be ignored/skipped; impression history for
+    // inactive promos won't affect this method's execution or correctness.
+    shown.erase(impression.promo);
+  }
+
+  // At this point in method execution, there's been more than one promo that's
+  // never been shown. In this case, In this case, return the first unshown
+  // promo (a bit awkwardly, these unshown promos are still left in the variable
+  // `shown`.)
+  DCHECK(!shown.empty());
+  return *shown.begin();
+}
diff --git a/ios/chrome/browser/promos_manager/promos_manager_unittest.mm b/ios/chrome/browser/promos_manager/promos_manager_unittest.mm
index 419e186..01beb01a 100644
--- a/ios/chrome/browser/promos_manager/promos_manager_unittest.mm
+++ b/ios/chrome/browser/promos_manager/promos_manager_unittest.mm
@@ -16,6 +16,7 @@
 #import "ios/chrome/browser/promos_manager/promo.h"
 #import "ios/chrome/browser/promos_manager/promos_manager.h"
 #import "testing/platform_test.h"
+#import "third_party/abseil-cpp/absl/types/optional.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -314,3 +315,168 @@
           promos_manager::Promo::CredentialProviderExtension, impressions),
       false);
 }
+
+// Tests PromosManager::LeastRecentlyShown() correctly returns the least
+// recently shown promo given a list of impressions and set of active promos to
+// choose from.
+TEST_F(PromosManagerTest, ReturnsLeastRecentlyShown) {
+  const std::set<promos_manager::Promo> active_promos = {
+      promos_manager::Promo::Test,
+      promos_manager::Promo::CredentialProviderExtension,
+      promos_manager::Promo::AppStoreRating,
+      promos_manager::Promo::DefaultBrowser,
+  };
+
+  int today = TodaysDay();
+
+  const std::vector<promos_manager::Impression> impressions = {
+      promos_manager::Impression(promos_manager::Promo::Test, today),
+      promos_manager::Impression(promos_manager::Promo::DefaultBrowser,
+                                 today - 7),
+      promos_manager::Impression(promos_manager::Promo::AppStoreRating,
+                                 today - 14),
+      promos_manager::Impression(
+          promos_manager::Promo::CredentialProviderExtension, today - 180),
+  };
+
+  EXPECT_EQ(
+      promos_manager_->LeastRecentlyShown(active_promos, impressions).value(),
+      promos_manager::Promo::CredentialProviderExtension);
+}
+
+// Tests PromosManager::LeastRecentlyShown() correctly returns the least
+// recently shown promo given a list of impressions (with some impressions
+// belonging to inactive promo campaigns) and set of active promos to choose
+// from.
+TEST_F(PromosManagerTest, ReturnsLeastRecentlyShownWithSomeInactivePromos) {
+  const std::set<promos_manager::Promo> active_promos = {
+      promos_manager::Promo::Test,
+      promos_manager::Promo::AppStoreRating,
+  };
+
+  int today = TodaysDay();
+
+  const std::vector<promos_manager::Impression> impressions = {
+      promos_manager::Impression(promos_manager::Promo::Test, today),
+      promos_manager::Impression(promos_manager::Promo::DefaultBrowser,
+                                 today - 7),
+      promos_manager::Impression(promos_manager::Promo::AppStoreRating,
+                                 today - 14),
+      promos_manager::Impression(
+          promos_manager::Promo::CredentialProviderExtension, today - 180),
+  };
+
+  EXPECT_EQ(
+      promos_manager_->LeastRecentlyShown(active_promos, impressions).value(),
+      promos_manager::Promo::AppStoreRating);
+}
+
+// Tests PromosManager::LeastRecentlyShown() gracefully returns the first
+// impression in `active_promos` when no impression history exists (i.e. there's
+// no 'least recently shown' promo because empty impression history means no
+// promo has ever been shown.)
+TEST_F(PromosManagerTest, ReturnsLeastRecentlyShownWithoutImpressionHistory) {
+  const std::set<promos_manager::Promo> active_promos = {
+      promos_manager::Promo::CredentialProviderExtension,
+  };
+
+  const std::vector<promos_manager::Impression> impressions;
+
+  EXPECT_EQ(
+      promos_manager_->LeastRecentlyShown(active_promos, impressions).value(),
+      promos_manager::Promo::CredentialProviderExtension);
+}
+
+// Tests PromosManager::LeastRecentlyShown() gracefully returns a promo when
+// multiple promos are tied for least recently shown.
+TEST_F(PromosManagerTest, ReturnsLeastRecentlyShownBreakingTies) {
+  const std::set<promos_manager::Promo> active_promos = {
+      promos_manager::Promo::Test,
+      promos_manager::Promo::CredentialProviderExtension,
+      promos_manager::Promo::AppStoreRating,
+      promos_manager::Promo::DefaultBrowser,
+  };
+
+  int today = TodaysDay();
+
+  const std::vector<promos_manager::Impression> impressions = {
+      promos_manager::Impression(promos_manager::Promo::Test, today),
+      promos_manager::Impression(promos_manager::Promo::DefaultBrowser, today),
+      promos_manager::Impression(promos_manager::Promo::AppStoreRating, today),
+      promos_manager::Impression(
+          promos_manager::Promo::CredentialProviderExtension, today),
+  };
+
+  EXPECT_EQ(
+      promos_manager_->LeastRecentlyShown(active_promos, impressions).value(),
+      promos_manager::Promo::CredentialProviderExtension);
+}
+
+// Tests PromosManager::LeastRecentlyShown() gracefully returns a promo when the
+// impression history contains only one active promo campaign.
+TEST_F(PromosManagerTest, ReturnsLeastRecentlyShownWithOnlyOnePromoActive) {
+  const std::set<promos_manager::Promo> active_promos = {
+      promos_manager::Promo::Test,
+  };
+
+  int today = TodaysDay();
+
+  const std::vector<promos_manager::Impression> impressions = {
+      promos_manager::Impression(promos_manager::Promo::Test, today),
+      promos_manager::Impression(promos_manager::Promo::DefaultBrowser,
+                                 today - 7),
+      promos_manager::Impression(promos_manager::Promo::AppStoreRating,
+                                 today - 14),
+      promos_manager::Impression(
+          promos_manager::Promo::CredentialProviderExtension, today - 180),
+  };
+
+  EXPECT_EQ(
+      promos_manager_->LeastRecentlyShown(active_promos, impressions).value(),
+      promos_manager::Promo::Test);
+}
+
+// Tests PromosManager::LeastRecentlyShown() gracefully returns
+// promos_manager::Promo::Test when there are no active promo campaigns.
+TEST_F(PromosManagerTest,
+       ReturnsNulloptWhenLeastRecentlyShownHasNoActivePromoCampaigns) {
+  const std::set<promos_manager::Promo> active_promos;
+
+  int today = TodaysDay();
+
+  const std::vector<promos_manager::Impression> impressions = {
+      promos_manager::Impression(promos_manager::Promo::Test, today),
+      promos_manager::Impression(promos_manager::Promo::DefaultBrowser,
+                                 today - 7),
+      promos_manager::Impression(promos_manager::Promo::AppStoreRating,
+                                 today - 14),
+      promos_manager::Impression(
+          promos_manager::Promo::CredentialProviderExtension, today - 180),
+  };
+
+  EXPECT_EQ(promos_manager_->LeastRecentlyShown(active_promos, impressions),
+            absl::nullopt);
+}
+
+// Tests PromosManager::LeastRecentlyShown() gracefully returns
+// the first unshown promo when there are multiple active promo campaigns for
+// unshown promos.
+TEST_F(PromosManagerTest, ReturnsFirstUnshownPromoForLeastRecentlyShown) {
+  const std::set<promos_manager::Promo> active_promos = {
+      promos_manager::Promo::Test,
+      promos_manager::Promo::CredentialProviderExtension,
+      promos_manager::Promo::AppStoreRating,
+      promos_manager::Promo::DefaultBrowser,
+  };
+
+  int today = TodaysDay();
+
+  const std::vector<promos_manager::Impression> impressions = {
+      promos_manager::Impression(promos_manager::Promo::Test, today),
+      promos_manager::Impression(promos_manager::Promo::DefaultBrowser,
+                                 today - 7),
+  };
+
+  EXPECT_EQ(promos_manager_->LeastRecentlyShown(active_promos, impressions),
+            promos_manager::Promo::AppStoreRating);
+}
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_earl_grey_app_interface.mm b/ios/chrome/browser/ui/bookmarks/bookmark_earl_grey_app_interface.mm
index 8eba7d5..9d6d20f3 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_earl_grey_app_interface.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_earl_grey_app_interface.mm
@@ -253,7 +253,8 @@
   const bookmarks::BookmarkNode* bookmark =
       [self bookmarkModel] -> GetMostRecentlyAddedUserNodeForURL(
                                GURL(base::SysNSStringToUTF16(URL)));
-  if (bookmark->GetTitle().compare(base::SysNSStringToUTF16(name)) != 0) {
+  if (!bookmark ||
+      bookmark->GetTitle().compare(base::SysNSStringToUTF16(name)) != 0) {
     return testing::NSErrorWithLocalizedDescription(
         [NSString stringWithFormat:@"Could not find bookmark named %@ for %@",
                                    name, URL]);
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.mm
index da583375..6491e2a2 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.mm
@@ -645,19 +645,6 @@
   }];
 }
 
-- (void)bookmarkCurrentPage {
-  web::WebState* currentWebState =
-      _browser->GetWebStateList()->GetActiveWebState();
-
-  GURL URL = currentWebState->GetLastCommittedURL();
-  NSString* title = tab_util::GetTabTitle(currentWebState);
-  BookmarkAddCommand* command = [[BookmarkAddCommand alloc] initWithURL:URL
-                                                                  title:title
-                                                   presentFolderChooser:NO];
-
-  [self bookmark:command];
-}
-
 #pragma mark - Private
 
 // Presents `viewController` using the appropriate presentation and styling,
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
index 8148406..9eb83e7 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
@@ -6,6 +6,7 @@
 #import <XCTest/XCTest.h>
 
 #include "base/ios/ios_util.h"
+#import "base/strings/sys_string_conversions.h"
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/ui/bookmarks/bookmark_earl_grey.h"
 #import "ios/chrome/browser/ui/bookmarks/bookmark_earl_grey_ui.h"
@@ -842,6 +843,31 @@
   [BookmarkEarlGreyUI verifyEmptyState];
 }
 
+// Tests that bookmarking an incognito tab actually bookmarks the
+// expected URL. Regression test for https://crbug.com/1353114.
+- (void)testBookmarkFromIncognito {
+  GREYAssertTrue(self.testServer->Start(), @"Server did not start.");
+
+  const GURL firstURL = self.testServer->GetURL("/pony.html");
+  [ChromeEarlGrey openNewTab];
+  [ChromeEarlGrey loadURL:firstURL];
+
+  const GURL incognitoURL = self.testServer->GetURL("/destination.html");
+  [ChromeEarlGrey openNewIncognitoTab];
+  [ChromeEarlGrey loadURL:incognitoURL];
+
+  // Add the bookmark from the UI.
+  [BookmarkEarlGrey waitForBookmarkModelLoaded:YES];
+  NSString* bookmarkTitle = @"Test Page";
+  [BookmarkEarlGreyUI bookmarkCurrentTabWithTitle:@"Test Page"];
+
+  [BookmarkEarlGrey verifyExistenceOfBookmarkWithURL:base::SysUTF8ToNSString(
+                                                         incognitoURL.spec())
+                                                name:bookmarkTitle];
+  [BookmarkEarlGrey
+      verifyAbsenceOfBookmarkWithURL:base::SysUTF8ToNSString(firstURL.spec())];
+}
+
 // TODO(crbug.com/695749): Add egtests for:
 // 1. Spinner background.
 // 2. Reorder bookmarks. (make sure it won't clear the row selection on table)
diff --git a/ios/chrome/browser/ui/browser_view/key_commands_provider.mm b/ios/chrome/browser/ui/browser_view/key_commands_provider.mm
index be0ac16e..b4af01f 100644
--- a/ios/chrome/browser/ui/browser_view/key_commands_provider.mm
+++ b/ios/chrome/browser/ui/browser_view/key_commands_provider.mm
@@ -255,8 +255,19 @@
                            title:l10n_util::GetNSStringWithFixup(
                                      IDS_IOS_KEYBOARD_BOOKMARK_THIS_PAGE)
                           action:^{
-                            [weakSelf.bookmarksCommandsHandler
-                                    bookmarkCurrentPage];
+                            if (weakSelf.browser) {
+                              web::WebState* currentWebState =
+                                  weakSelf.browser->GetWebStateList()
+                                      ->GetActiveWebState();
+                              if (currentWebState) {
+                                BookmarkAddCommand* command =
+                                    [[BookmarkAddCommand alloc]
+                                            initWithWebState:currentWebState
+                                        presentFolderChooser:NO];
+                                [weakSelf.bookmarksCommandsHandler
+                                    bookmark:command];
+                              }
+                            }
                           }],
       [UIKeyCommand cr_keyCommandWithInput:@"r"
                              modifierFlags:UIKeyModifierCommand
diff --git a/ios/chrome/browser/ui/commands/BUILD.gn b/ios/chrome/browser/ui/commands/BUILD.gn
index 6b1f83723..327cb9f6 100644
--- a/ios/chrome/browser/ui/commands/BUILD.gn
+++ b/ios/chrome/browser/ui/commands/BUILD.gn
@@ -54,6 +54,7 @@
   ]
 
   deps = [
+    "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui/util:url_with_title",
     "//ios/public/provider/chrome/browser/user_feedback",
     "//ios/web",
diff --git a/ios/chrome/browser/ui/commands/bookmark_add_command.h b/ios/chrome/browser/ui/commands/bookmark_add_command.h
index 8017165..524f0160 100644
--- a/ios/chrome/browser/ui/commands/bookmark_add_command.h
+++ b/ios/chrome/browser/ui/commands/bookmark_add_command.h
@@ -9,6 +9,9 @@
 
 class GURL;
 @class URLWithTitle;
+namespace web {
+class WebState;
+}
 
 // An object of this class will contain the data needed to execute any bookmark
 // command for one or more pages.
@@ -24,6 +27,14 @@
        presentFolderChooser:(BOOL)presentFolderChooser
     NS_DESIGNATED_INITIALIZER;
 
+// Initializes a command object with the `webState`'s URL and title.
+// If `presentFolderChooser` is true, the user will be prompted to choose
+// a destination for the bookmarks first. If false, the item will be bookmarked
+// immediately and the displayed snackbar message will allow editing to change
+// the location if desired.
+- (instancetype)initWithWebState:(web::WebState*)webState
+            presentFolderChooser:(BOOL)presentFolderChooser;
+
 // Initializes a command object with multiple pages `UrlWithTitle`.
 // This implies `presentFolderChooser` is `true` and the user will need
 // to select a destination folder before the bookmarks are saved.
diff --git a/ios/chrome/browser/ui/commands/bookmark_add_command.mm b/ios/chrome/browser/ui/commands/bookmark_add_command.mm
index 51f7fed..9e76f88 100644
--- a/ios/chrome/browser/ui/commands/bookmark_add_command.mm
+++ b/ios/chrome/browser/ui/commands/bookmark_add_command.mm
@@ -4,7 +4,9 @@
 
 #import "ios/chrome/browser/ui/commands/bookmark_add_command.h"
 
+#import "ios/chrome/browser/tabs/tab_title_util.h"
 #import "ios/chrome/browser/ui/util/url_with_title.h"
+#import "ios/web/public/web_state.h"
 #import "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -33,6 +35,15 @@
   return self;
 }
 
+- (instancetype)initWithWebState:(web::WebState*)webState
+            presentFolderChooser:(BOOL)presentFolderChooser {
+  GURL URL = webState->GetLastCommittedURL();
+  NSString* title = tab_util::GetTabTitle(webState);
+  return [self initWithURL:URL
+                     title:title
+      presentFolderChooser:presentFolderChooser];
+}
+
 - (instancetype)initWithURLs:(NSArray<URLWithTitle*>*)URLs {
   if (self = [super init]) {
     _URLs = [URLs copy];
diff --git a/ios/chrome/browser/ui/commands/bookmarks_commands.h b/ios/chrome/browser/ui/commands/bookmarks_commands.h
index c2d45c8..dce45f3 100644
--- a/ios/chrome/browser/ui/commands/bookmarks_commands.h
+++ b/ios/chrome/browser/ui/commands/bookmarks_commands.h
@@ -23,10 +23,6 @@
 // - If it is not already bookmarked, it will be bookmarked automatically and an
 //   "Edit" button will be provided in the displayed snackbar message.
 - (void)bookmark:(BookmarkAddCommand*)command;
-
-// Adds bookmark for the current page.
-- (void)bookmarkCurrentPage;
-
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_COMMANDS_BOOKMARKS_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm
index fbce41d..6b1aa06d 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm
@@ -1369,9 +1369,18 @@
 // bookmark edit screen if the current page is bookmarked.
 - (void)addOrEditBookmark {
   RecordAction(UserMetricsAction("MobileMenuAddToBookmarks"));
+  // Dismissing the menu disconnects the mediator, so save anything cleaned up
+  // there.
+  web::WebState* currentWebState = self.webState;
   [self.popupMenuCommandsHandler dismissPopupMenuAnimated:YES];
   LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeAllTabs);
-  [self.bookmarksCommandsHandler bookmarkCurrentPage];
+  if (!currentWebState) {
+    return;
+  }
+  BookmarkAddCommand* command =
+      [[BookmarkAddCommand alloc] initWithWebState:currentWebState
+                              presentFolderChooser:NO];
+  [self.bookmarksCommandsHandler bookmark:command];
 }
 
 // Dismisses the menu and adds the current page to the reading list.
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm
index ed2697f..18d5e353 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm
@@ -30,6 +30,7 @@
 #import "ios/chrome/browser/ui/ui_feature_flags.h"
 #import "ios/chrome/browser/web/web_navigation_browser_agent.h"
 #import "ios/chrome/browser/window_activities/window_activity_helpers.h"
+#import "ios/web/public/web_state.h"
 #include "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -75,11 +76,19 @@
       RecordAction(UserMetricsAction("MobileMenuReadLater"));
       [self.delegate readPageLater];
       break;
-    case PopupMenuActionPageBookmark:
+    case PopupMenuActionPageBookmark: {
       RecordAction(UserMetricsAction("MobileMenuAddToBookmarks"));
       LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeAllTabs);
-      [self.bookmarksCommandsHandler bookmarkCurrentPage];
+      web::WebState* currentWebState = self.delegate.currentWebState;
+      if (!currentWebState) {
+        return;
+      }
+      BookmarkAddCommand* command =
+          [[BookmarkAddCommand alloc] initWithWebState:currentWebState
+                                  presentFolderChooser:NO];
+      [self.bookmarksCommandsHandler bookmark:command];
       break;
+    }
     case PopupMenuActionTranslate:
       base::RecordAction(UserMetricsAction("MobileMenuTranslate"));
       [self.browserCoordinatorCommandsHandler showTranslate];
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler_delegate.h b/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler_delegate.h
index 31808a9b..0d364836 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler_delegate.h
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler_delegate.h
@@ -9,6 +9,9 @@
 
 @protocol PopupMenuItem;
 @class TableViewItem;
+namespace web {
+class WebState;
+}
 
 // Delegate for the PopupMenuActionHandler.
 @protocol PopupMenuActionHandlerDelegate
@@ -26,6 +29,8 @@
 // menu option has been tapped. Follows or unfollows the website according to
 // the current follow status of the website.
 - (void)toggleFollowed;
+// The current web state.
+- (web::WebState*)currentWebState;
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_POPUP_MENU_POPUP_MENU_ACTION_HANDLER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
index 344001a..5c2e74b 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
@@ -673,6 +673,10 @@
   }
 }
 
+- (web::WebState*)currentWebState {
+  return self.webState;
+}
+
 #pragma mark - IOSLanguageDetectionTabHelperObserving
 
 - (void)iOSLanguageDetectionTabHelper:
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn b/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn
index 22ed395..fb0f778 100644
--- a/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn
@@ -39,6 +39,8 @@
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/browsing_data",
     "//ios/chrome/browser/browsing_data:feature_flags",
+    "//ios/chrome/browser/discover_feed",
+    "//ios/chrome/browser/discover_feed:discover_feed_factory",
     "//ios/chrome/browser/feature_engagement",
     "//ios/chrome/browser/history",
     "//ios/chrome/browser/main:public",
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm
index afcd9a2..929a961 100644
--- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm
@@ -17,6 +17,8 @@
 #include "ios/chrome/browser/browsing_data/browsing_data_features.h"
 #include "ios/chrome/browser/browsing_data/browsing_data_remove_mask.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
+#import "ios/chrome/browser/discover_feed/discover_feed_service.h"
+#import "ios/chrome/browser/discover_feed/discover_feed_service_factory.h"
 #import "ios/chrome/browser/main/browser.h"
 #import "ios/chrome/browser/net/crurl.h"
 #import "ios/chrome/browser/signin/identity_manager_factory.h"
@@ -424,6 +426,9 @@
     browserState->GetPrefs()->SetInt64(
         browsing_data::prefs::kLastClearBrowsingDataTime,
         base::Time::Now().ToTimeT());
+
+    DiscoverFeedServiceFactory::GetForBrowserState(browserState)
+        ->BrowsingHistoryCleared();
   }
 
   [self.dispatcher
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 0819c68..191bc889 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 @@
-a569341be5fcdc9586d02bde970a975c229ebb96
\ No newline at end of file
+43a172ff7f6d627928837be3ec8dec9295fd9bd9
\ 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 d367b58..cf5e51a0 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 @@
-8235617bc8255bde79cfb19d1d7739c26df23c18
\ No newline at end of file
+14993544629b1e66c26a85533e5b28d2123f4ede
\ 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 105950f..3b25c08 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 @@
-2af083fb9c2769146f04429ae8b802f6c17fe830
\ No newline at end of file
+31b682add9e082fd0f068ed005aa6d4eb546bb06
\ 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 f9edfd3..188fad0 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 @@
-f2e3c7d870b13a099b520709f778bd652b9bacda
\ No newline at end of file
+2a2dddc65d87a8596c9648087efb45b3bba26bb5
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
index 42a3ce2..a74576d2 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-80ee833128b7238c1fa0e91c32e7b18ec19f1723
\ No newline at end of file
+c6a8250c37ecbe70f07d69907a07967456eae976
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
index 7292e3fc..0d6a2b4 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-336d295b728eb4f04a8268eb4bba51192b9edfef
\ No newline at end of file
+5293eef2875e50b31e52b087f276f109478a5e5b
\ 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 f4288d2..8f379ec5 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 @@
-c947b7662a0459447c6ebc2c958ca69803587370
\ No newline at end of file
+fe52075e1a9c83d36c11cfb8231f9ca765c8ce94
\ 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 65757e1..36340ef 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 @@
-cb41feebae11dc201fa42b9e28db2ec3493e388f
\ No newline at end of file
+6662267f4c36adcf31d6847bdf2a5068cd58d67c
\ 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 653ebbf8..3ed2a45 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 @@
-13100cd70292cb30ec8182ba9cadf9e8cb3e5546
\ No newline at end of file
+7b9ae353e74bbca7626e9801397926b8b309f24c
\ 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 b93ac82a..d6deb2e 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 @@
-1ae806557c801bbd78558321ba4a3a80c29dc041
\ No newline at end of file
+c521c951ac20eca3f47c0e7fe93a77a357e16c7b
\ No newline at end of file
diff --git a/media/base/win/BUILD.gn b/media/base/win/BUILD.gn
index b6d9fcf..973ed76 100644
--- a/media/base/win/BUILD.gn
+++ b/media/base/win/BUILD.gn
@@ -18,6 +18,7 @@
   sources = [
     "dxgi_device_manager.cc",
     "dxgi_device_manager.h",
+    "hresults.h",
     "mf_helpers.cc",
     "mf_helpers.h",
     "mf_initializer.cc",
diff --git a/media/base/win/hresults.h b/media/base/win/hresults.h
new file mode 100644
index 0000000..c355052
--- /dev/null
+++ b/media/base/win/hresults.h
@@ -0,0 +1,27 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_WIN_HRESULTS_H_
+#define MEDIA_BASE_WIN_HRESULTS_H_
+
+#include <winerror.h>
+
+namespace media {
+
+// Custom error HRESULTs used by Chromium media code on Windows.
+// See https://docs.microsoft.com/en-us/windows/win32/com/codes-in-facility-itf
+// Chromium media code is reserving the range [0x8004FA00, 0x8004FBFF].
+// Reported to metrics, please never modify or reuse existing values.
+// For new values, please also add them to enums.xml.
+
+constexpr HRESULT kErrorInitializeMediaFoundation =
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xFA01);
+constexpr HRESULT kErrorInitializeVideoWindowClass =
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xFA02);
+constexpr HRESULT kErrorCdmProxyReceivedInInvalidState =
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xFA03);
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_WIN_HRESULTS_H_
diff --git a/media/renderers/win/media_foundation_renderer.cc b/media/renderers/win/media_foundation_renderer.cc
index bcd87b8..991186e5 100644
--- a/media/renderers/win/media_foundation_renderer.cc
+++ b/media/renderers/win/media_foundation_renderer.cc
@@ -30,6 +30,7 @@
 #include "media/base/media_switches.h"
 #include "media/base/timestamp_constants.h"
 #include "media/base/win/dxgi_device_manager.h"
+#include "media/base/win/hresults.h"
 #include "media/base/win/mf_helpers.h"
 #include "media/base/win/mf_initializer.h"
 
@@ -200,7 +201,7 @@
   DVLOG_FUNC(1);
 
   if (!InitializeMediaFoundation())
-    return E_FAIL;
+    return kErrorInitializeMediaFoundation;
 
   // Set `cdm_proxy_` early on so errors can be reported via the CDM for better
   // error aggregation. See `CdmDocumentServiceImpl::OnCdmEvent()`.
@@ -405,7 +406,7 @@
 
 HRESULT MediaFoundationRenderer::InitializeVirtualVideoWindow() {
   if (!InitializeVideoWindowClass())
-    return E_FAIL;
+    return kErrorInitializeVideoWindowClass;
 
   virtual_video_window_ =
       CreateWindowEx(WS_EX_NOPARENTNOTIFY | WS_EX_LAYERED | WS_EX_TRANSPARENT |
@@ -460,7 +461,8 @@
 
   if (!waiting_for_mf_cdm_ || !content_protection_manager_) {
     OnError(PIPELINE_ERROR_INVALID_STATE,
-            ErrorReason::kCdmProxyReceivedInInvalidState);
+            ErrorReason::kCdmProxyReceivedInInvalidState,
+            kErrorCdmProxyReceivedInInvalidState);
     return;
   }
 
@@ -928,11 +930,11 @@
 
 void MediaFoundationRenderer::OnError(PipelineStatus status,
                                       ErrorReason reason,
-                                      absl::optional<HRESULT> hresult,
+                                      HRESULT hresult,
                                       PipelineStatusCallback status_cb) {
   const std::string error =
-      "MediaFoundationRenderer error: " + GetErrorReasonString(reason) +
-      (hresult.has_value() ? (" (" + PrintHr(hresult.value()) + ")") : "");
+      "MediaFoundationRenderer error: " + GetErrorReasonString(reason) + " (" +
+      PrintHr(hresult) + ")";
 
   DLOG(ERROR) << error;
 
@@ -947,7 +949,7 @@
   // during OS sleep/resume, or moving video to different graphics adapters.
   // This is not an error, so special case it here.
   PipelineStatus new_status = status;
-  if (hresult.has_value() && hresult == static_cast<HRESULT>(0x8004CD12)) {
+  if (hresult == static_cast<HRESULT>(0x8004CD12)) {
     new_status = PIPELINE_ERROR_HARDWARE_CONTEXT_RESET;
     if (cdm_proxy_)
       cdm_proxy_->OnHardwareContextReset();
@@ -956,8 +958,7 @@
   }
 
   // Attach hresult to `new_status` for logging and metrics reporting.
-  if (hresult.has_value())
-    new_status.WithData("hresult", static_cast<uint32_t>(hresult.value()));
+  new_status.WithData("hresult", static_cast<uint32_t>(hresult));
 
   if (status_cb)
     std::move(status_cb).Run(new_status);
diff --git a/media/renderers/win/media_foundation_renderer.h b/media/renderers/win/media_foundation_renderer.h
index 400df430..3fbd9a9 100644
--- a/media/renderers/win/media_foundation_renderer.h
+++ b/media/renderers/win/media_foundation_renderer.h
@@ -153,7 +153,7 @@
   //   `renderer_client` via OnError().
   void OnError(PipelineStatus status,
                ErrorReason reason,
-               absl::optional<HRESULT> hresult = absl::nullopt,
+               HRESULT hresult,
                PipelineStatusCallback status_cb = base::NullCallback());
 
   // Renderer methods are running in the same sequence.
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 0c3426dd..31ea3ac 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5774,21 +5774,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5254.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "dimension_sets": [
@@ -5801,7 +5801,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       },
       {
         "isolate_profile_data": true,
@@ -5939,21 +5939,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 107.0.5254.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "dimension_sets": [
@@ -5965,7 +5965,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       },
       {
         "args": [
@@ -6085,21 +6085,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 107.0.5254.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "dimension_sets": [
@@ -6111,7 +6111,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       },
       {
         "isolate_profile_data": true,
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index e205cf8..29ef678 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -99221,21 +99221,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5254.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -99243,7 +99243,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       },
       {
         "isolate_profile_data": true,
@@ -99356,28 +99356,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 107.0.5254.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       },
       {
         "args": [
@@ -99477,28 +99477,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 107.0.5254.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       },
       {
         "isolate_profile_data": true,
@@ -100831,20 +100831,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5254.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "dimension_sets": [
@@ -100858,7 +100858,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       },
       {
         "merge": {
@@ -100996,20 +100996,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 107.0.5254.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "dimension_sets": [
@@ -101022,7 +101022,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       },
       {
         "args": [
@@ -101142,20 +101142,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 107.0.5254.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "dimension_sets": [
@@ -101168,7 +101168,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       },
       {
         "merge": {
@@ -102676,20 +102676,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5254.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "dimension_sets": [
@@ -102703,7 +102703,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       },
       {
         "merge": {
@@ -102841,20 +102841,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 107.0.5254.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "dimension_sets": [
@@ -102867,7 +102867,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       },
       {
         "args": [
@@ -102987,20 +102987,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 107.0.5254.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "dimension_sets": [
@@ -103013,7 +103013,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       },
       {
         "merge": {
@@ -103766,20 +103766,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5254.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "dimension_sets": [
@@ -103792,7 +103792,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       }
     ]
   },
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index f505cb4..a6a63a9 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -20863,21 +20863,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5254.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "dimension_sets": [
@@ -20890,7 +20890,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       },
       {
         "isolate_profile_data": true,
@@ -21028,21 +21028,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 107.0.5254.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "dimension_sets": [
@@ -21054,7 +21054,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       },
       {
         "args": [
@@ -21174,21 +21174,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 107.0.5254.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 107.0.5256.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v107.0.5254.0",
-              "revision": "version:107.0.5254.0"
+              "location": "lacros_version_skew_tests_v107.0.5256.0",
+              "revision": "version:107.0.5256.0"
             }
           ],
           "dimension_sets": [
@@ -21200,7 +21200,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5256.0"
       },
       {
         "isolate_profile_data": true,
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 99b5365..a444e8cb 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -22,15 +22,15 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5256.0/test_ash_chrome',
     ],
-    'identifier': 'Lacros version skew testing ash 107.0.5254.0',
+    'identifier': 'Lacros version skew testing ash 107.0.5256.0',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v107.0.5254.0',
-          'revision': 'version:107.0.5254.0',
+          'location': 'lacros_version_skew_tests_v107.0.5256.0',
+          'revision': 'version:107.0.5256.0',
         },
       ],
     },
diff --git a/testing/test.gni b/testing/test.gni
index 4e95eb5..328d02b 100644
--- a/testing/test.gni
+++ b/testing/test.gni
@@ -274,10 +274,12 @@
         "use_native_activity",
       ]
 
+      _add_unwind_tables_in_apk = defined(invoker.add_unwind_tables_in_apk) &&
+                                  invoker.add_unwind_tables_in_apk
+
       # Adds the unwind tables from unstripped binary as an asset file in the
       # apk, if |add_unwind_tables_in_apk| is specified by the test.
-      if (defined(invoker.add_unwind_tables_in_apk) &&
-          invoker.add_unwind_tables_in_apk) {
+      if (_add_unwind_tables_in_apk) {
         if (use_android_unwinder_v2) {
           _unwind_table_asset_v2_name = "${target_name}_v2_unwind_assets"
           unwind_table_asset_v2(_unwind_table_asset_v2_name) {
@@ -303,6 +305,13 @@
         configs = []  # Prevent list overwriting warning.
         configs = invoker.configs
 
+        if (_add_unwind_tables_in_apk) {
+          # Remove -gz if present, as dump_syms does not support it.
+          # Add and then remove because "-=" removes all, but errors if none are found.
+          configs += [ "//build/config:compress_debug_sections" ]
+          configs -= [ "//build/config:compress_debug_sections" ]
+        }
+
         # Use a crate name that avoids creating a warning due to double
         # underscore (ie. `__`).
         rs_crate_name = _library_crate_name
@@ -310,7 +319,10 @@
         forward_variables_from(
             invoker,
             "*",
-            [ "deps" ] + _apk_specific_vars + _wrapper_script_vars +
+            [
+                  "configs",
+                  "deps",
+                ] + _apk_specific_vars + _wrapper_script_vars +
                 TESTONLY_AND_VISIBILITY)
 
         # Native targets do not need to depend on java targets. Filter them out
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 89a58f7..32f559b8 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -2775,6 +2775,32 @@
             ]
         }
     ],
+    "ChromeOSZramWriteback": [
+        {
+            "platforms": [
+                "chromeos"
+            ],
+            "experiments": [
+                {
+                    "name": "EnabledGroupB_20220815",
+                    "params": {
+                        "CrOSZramWritebackWritebackBackoffTimeSec": "900",
+                        "ZramWritebackHuge": "false",
+                        "ZramWritebackHugeIdle": "true",
+                        "ZramWritebackIdle": "true",
+                        "ZramWritebackIdleMaxTimeSec": "86400",
+                        "ZramWritebackIdleMinTimeSec": "7200",
+                        "ZramWritebackMaxPages": "25600",
+                        "ZramWritebackMinPages": "1792",
+                        "ZramWritebackPeriodicTimeSec": "600"
+                    },
+                    "enable_features": [
+                        "ChromeOSZramWriteback"
+                    ]
+                }
+            ]
+        }
+    ],
     "ChromeStart": [
         {
             "platforms": [
@@ -6699,8 +6725,14 @@
                         "AndroidAuxiliarySearch",
                         "OmniboxDynamicMaxAutocomplete",
                         "OmniboxFocusTriggersSRPZeroSuggest",
+                        "OmniboxHeaderPaddingUpdate",
                         "OmniboxLocalZeroSuggestAgeThreshold",
                         "OmniboxMaxURLMatches",
+                        "OmniboxMostVisitedTilesDynamicSpacing",
+                        "OmniboxMostVisitedTilesFadingOnTablet",
+                        "OmniboxMostVisitedTilesOnSrp",
+                        "OmniboxRemoveSuggestionHeaderCapitalization",
+                        "OmniboxRemoveSuggestionHeaderChevron",
                         "OmniboxRetainSuggestionsWithHeaders",
                         "OmniboxUIExperimentMaxAutocompleteMatches"
                     ],
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 3212d6a..197ee1d 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -1523,7 +1523,8 @@
     delay_async_script_execution_delay_types[] = {
         {DelayAsyncScriptDelayType::kFinishedParsing, "finished_parsing"},
         {DelayAsyncScriptDelayType::kFirstPaintOrFinishedParsing,
-         "first_paint_or_finished_parsing"}};
+         "first_paint_or_finished_parsing"},
+        {DelayAsyncScriptDelayType::kEachLcpCandidate, "each_lcp_candidate"}};
 
 const base::FeatureParam<DelayAsyncScriptDelayType>
     kDelayAsyncScriptExecutionDelayParam{
@@ -1534,6 +1535,9 @@
 const base::FeatureParam<bool> kDelayAsyncScriptExecutionCrossSiteOnlyParam{
     &kDelayAsyncScriptExecution, "cross_site_only", false};
 
+const base::FeatureParam<base::TimeDelta> kDelayAsyncScriptExecutionLimitParam{
+    &kDelayAsyncScriptExecution, "limit", base::Seconds(1)};
+
 const base::Feature kLowPriorityAsyncScriptExecution{
     "LowPriorityAsyncScriptExecution", base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index ccf675f..2bf43421 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -759,11 +759,14 @@
 enum class DelayAsyncScriptDelayType {
   kFinishedParsing,
   kFirstPaintOrFinishedParsing,
+  kEachLcpCandidate,
 };
 BLINK_COMMON_EXPORT extern const base::FeatureParam<DelayAsyncScriptDelayType>
     kDelayAsyncScriptExecutionDelayParam;
 BLINK_COMMON_EXPORT extern const base::FeatureParam<bool>
     kDelayAsyncScriptExecutionCrossSiteOnlyParam;
+BLINK_COMMON_EXPORT extern const base::FeatureParam<base::TimeDelta>
+    kDelayAsyncScriptExecutionLimitParam;
 
 // If enabled, async scripts will be run on a lower priority task queue.
 // See https://crbug.com/1348467.
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py b/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
index 70e4ed14..286ded8 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
@@ -644,7 +644,7 @@
     # https://webidl.spec.whatwg.org/#BufferSource
     _BUFFER_SOURCE_TYPES = (
         ('ArrayBuffer', 'ArrayBufferView', 'DataView') + _TYPED_ARRAY_TYPES)
-    _MISC_TYPES = ('any', 'boolean', 'object', 'symbol', 'void')
+    _MISC_TYPES = ('any', 'boolean', 'object', 'symbol', 'undefined', 'void')
     _VALID_TYPES = set(_NUMERIC_TYPES + _STRING_TYPES + _BUFFER_SOURCE_TYPES +
                        _MISC_TYPES)
 
@@ -738,7 +738,7 @@
 
     @property
     def is_void(self):
-        return self._name == 'void'
+        return self._name == 'undefined' or self._name == 'void'
 
 
 class ReferenceType(IdlType, RefById):
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py b/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
index d391fa6..474da45 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
@@ -888,7 +888,7 @@
         def build_simple_type(node, extended_attributes):
             name = node.GetName()
             if name is None:
-                assert node.GetClass() == 'Any'
+                assert node.GetClass() in ('Any', 'Undefined')
                 name = node.GetClass().lower()
             if node.GetProperty('UNRESTRICTED'):
                 name = 'unrestricted {}'.format(name)
@@ -939,6 +939,7 @@
             'Sequence': build_sequence_type,
             'StringType': build_simple_type,
             'Typeref': build_reference_type,
+            'Undefined': build_simple_type,
             'UnionType': build_union_type,
         }
         return build_functions[body_node.GetClass()](
diff --git a/third_party/blink/renderer/core/css/media_query_set_test.cc b/third_party/blink/renderer/core/css/media_query_set_test.cc
index ef246b2..61be56a 100644
--- a/third_party/blink/renderer/core/css/media_query_set_test.cc
+++ b/third_party/blink/renderer/core/css/media_query_set_test.cc
@@ -185,6 +185,8 @@
       {"only and", "not all"},
       {"only only", "not all"},
       {"only or", "not all"},
+      {"layer", "not all"},
+      {"not layer", "not all"},
       {"not (orientation)", nullptr},
       {"only (orientation)", "not all"},
       {"(max-width: 800px()), (max-width: 800px)",
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_impl_test.cc b/third_party/blink/renderer/core/css/parser/css_parser_impl_test.cc
index a3890fd..93e969e 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_impl_test.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_impl_test.cc
@@ -519,7 +519,7 @@
     ASSERT_TRUE(parsed->IsLayered());
     ASSERT_EQ(1u, parsed->GetLayerName().size());
     EXPECT_EQ(g_empty_atom, parsed->GetLayerName()[0]);
-    EXPECT_EQ("layer", parsed->MediaQueries()->MediaText());
+    EXPECT_EQ("not all", parsed->MediaQueries()->MediaText());
   }
 
   {
@@ -539,7 +539,7 @@
     ASSERT_TRUE(parsed->IsLayered());
     ASSERT_EQ(1u, parsed->GetLayerName().size());
     EXPECT_EQ("bar", parsed->GetLayerName()[0]);
-    EXPECT_EQ("layer", parsed->MediaQueries()->MediaText());
+    EXPECT_EQ("not all", parsed->MediaQueries()->MediaText());
   }
 }
 
diff --git a/third_party/blink/renderer/core/css/parser/media_query_parser.cc b/third_party/blink/renderer/core/css/parser/media_query_parser.cc
index 632b7fc..6c70e2c7 100644
--- a/third_party/blink/renderer/core/css/parser/media_query_parser.cc
+++ b/third_party/blink/renderer/core/css/parser/media_query_parser.cc
@@ -157,7 +157,8 @@
   return EqualIgnoringASCIICase(token.Value(), "not") ||
          EqualIgnoringASCIICase(token.Value(), "and") ||
          EqualIgnoringASCIICase(token.Value(), "or") ||
-         EqualIgnoringASCIICase(token.Value(), "only");
+         EqualIgnoringASCIICase(token.Value(), "only") ||
+         EqualIgnoringASCIICase(token.Value(), "layer");
 }
 
 bool ConsumeUntilCommaInclusive(CSSParserTokenRange& range) {
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index a85a4a1..c117169 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -6891,7 +6891,10 @@
       // Notify the ScriptRunner if the first paint has been recorded and
       // we're delaying async scripts until first paint or finished parsing
       // (whichever comes first).
-      script_runner_delayer_->Deactivate();
+      if (milestone == MilestoneForDelayedAsyncScript::kFirstPaint ||
+          milestone == MilestoneForDelayedAsyncScript::kFinishedParsing) {
+        script_runner_delayer_->Deactivate();
+      }
       break;
     case features::DelayAsyncScriptDelayType::kFinishedParsing:
       // Notify the ScriptRunner if we're finished parsing and we're delaying
@@ -6899,6 +6902,17 @@
       if (milestone == MilestoneForDelayedAsyncScript::kFinishedParsing)
         script_runner_delayer_->Deactivate();
       break;
+    case features::DelayAsyncScriptDelayType::kEachLcpCandidate:
+      // Notify the ScriptRunner if a LCP candidate is reported.
+      if (milestone == MilestoneForDelayedAsyncScript::kLcpCandidate) {
+        // Flush all async scripts that are already prepared but forced to be
+        // delayed.
+        script_runner_delayer_->Deactivate();
+        // Delay async scripts until next LCP candidate occurs or reaches the
+        // time limit.
+        script_runner_delayer_->Activate();
+      }
+      break;
   }
 }
 
@@ -6906,6 +6920,11 @@
   MaybeExecuteDelayedAsyncScripts(MilestoneForDelayedAsyncScript::kFirstPaint);
 }
 
+void Document::OnLargestContentfulPaintUpdated() {
+  MaybeExecuteDelayedAsyncScripts(
+      MilestoneForDelayedAsyncScript::kLcpCandidate);
+}
+
 void Document::FinishedParsing() {
   DCHECK(!GetScriptableDocumentParser() || !parser_->IsParsing());
   DCHECK(!GetScriptableDocumentParser() || ready_state_ != kLoading);
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
index 4901b1f..b983673 100644
--- a/third_party/blink/renderer/core/dom/document.h
+++ b/third_party/blink/renderer/core/dom/document.h
@@ -1335,6 +1335,7 @@
   void ParseDNSPrefetchControlHeader(const String&);
 
   void MarkFirstPaint();
+  void OnLargestContentfulPaintUpdated();
   void FinishedParsing();
 
   void SetEncodingData(const DocumentEncodingData& new_data);
@@ -2035,7 +2036,11 @@
   void ExecuteScriptsWaitingForResources();
   void ExecuteJavaScriptUrls();
 
-  enum class MilestoneForDelayedAsyncScript { kFirstPaint, kFinishedParsing };
+  enum class MilestoneForDelayedAsyncScript {
+    kFirstPaint,
+    kFinishedParsing,
+    kLcpCandidate
+  };
   void MaybeExecuteDelayedAsyncScripts(MilestoneForDelayedAsyncScript);
 
   void LoadEventDelayTimerFired(TimerBase*);
diff --git a/third_party/blink/renderer/core/dom/void_function.idl b/third_party/blink/renderer/core/dom/void_function.idl
index 99efce95..769a3ec 100644
--- a/third_party/blink/renderer/core/dom/void_function.idl
+++ b/third_party/blink/renderer/core/dom/void_function.idl
@@ -3,4 +3,4 @@
 // found in the LICENSE file.
 
 // https://webidl.spec.whatwg.org/#VoidFunction
-callback VoidFunction = void ();
+callback VoidFunction = undefined ();
diff --git a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
index 39e835f..4862512 100644
--- a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
@@ -1039,7 +1039,12 @@
 std::unique_ptr<protocol::Array<protocol::CSS::CSSProperty>>
 InspectorStyle::LonghandProperties(
     const CSSPropertySourceData& property_entry) {
-  CSSTokenizer tokenizer(property_entry.value);
+  String property_value = property_entry.value;
+  if (property_entry.important) {
+    property_value = property_value.Substring(
+        0, property_value.length() - 10 /* length of "!important" */);
+  }
+  CSSTokenizer tokenizer(property_value);
   const auto tokens = tokenizer.TokenizeToEOF();
   CSSParserTokenRange range(tokens);
   CSSPropertyID property_id =
diff --git a/third_party/blink/renderer/core/layout/geometry/logical_rect.h b/third_party/blink/renderer/core/layout/geometry/logical_rect.h
index e7b10ad..e9eb9cb 100644
--- a/third_party/blink/renderer/core/layout/geometry/logical_rect.h
+++ b/third_party/blink/renderer/core/layout/geometry/logical_rect.h
@@ -66,8 +66,8 @@
     return other.offset == offset && other.size == size;
   }
 
-  LogicalRect operator+(const LogicalOffset& offset) const {
-    return {this->offset + offset, size};
+  LogicalRect operator+(const LogicalOffset& additional_offset) const {
+    return {offset + additional_offset, size};
   }
 
   void Unite(const LogicalRect&);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
index 96792fa..b1dec95d 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
@@ -56,7 +56,7 @@
       style_variant_(static_cast<unsigned>(inline_item.StyleVariant())),
       is_hidden_for_paint_(is_hidden_for_paint),
       text_direction_(static_cast<unsigned>(inline_item.Direction())),
-      ink_overflow_type_(NGInkOverflow::kNotSet),
+      ink_overflow_type_(static_cast<unsigned>(NGInkOverflow::Type::kNotSet)),
       is_dirty_(false),
       is_last_for_node_(true) {
 #if DCHECK_IS_ON()
@@ -87,7 +87,7 @@
       style_variant_(static_cast<unsigned>(style_variant)),
       is_hidden_for_paint_(is_hidden_for_paint),
       text_direction_(static_cast<unsigned>(direction)),
-      ink_overflow_type_(NGInkOverflow::kNotSet),
+      ink_overflow_type_(static_cast<unsigned>(NGInkOverflow::Type::kNotSet)),
       is_dirty_(false),
       is_last_for_node_(true) {
   DCHECK(layout_object_);
@@ -121,7 +121,7 @@
       style_variant_(static_cast<unsigned>(line.StyleVariant())),
       is_hidden_for_paint_(false),
       text_direction_(static_cast<unsigned>(line.BaseDirection())),
-      ink_overflow_type_(NGInkOverflow::kNotSet),
+      ink_overflow_type_(static_cast<unsigned>(NGInkOverflow::Type::kNotSet)),
       is_dirty_(false),
       is_last_for_node_(true) {
   DCHECK(!IsFormattingContextRoot());
@@ -137,7 +137,7 @@
       style_variant_(static_cast<unsigned>(box.StyleVariant())),
       is_hidden_for_paint_(box.IsHiddenForPaint()),
       text_direction_(static_cast<unsigned>(resolved_direction)),
-      ink_overflow_type_(NGInkOverflow::kNotSet),
+      ink_overflow_type_(static_cast<unsigned>(NGInkOverflow::Type::kNotSet)),
       is_dirty_(false),
       is_last_for_node_(true) {
   DCHECK_EQ(IsFormattingContextRoot(), box.IsFormattingContextRoot());
@@ -203,7 +203,7 @@
       style_variant_(source.style_variant_),
       is_hidden_for_paint_(source.is_hidden_for_paint_),
       text_direction_(source.text_direction_),
-      ink_overflow_type_(NGInkOverflow::kNotSet),
+      ink_overflow_type_(static_cast<unsigned>(NGInkOverflow::Type::kNotSet)),
       is_dirty_(source.is_dirty_),
       is_last_for_node_(source.is_last_for_node_) {
   switch (Type()) {
@@ -227,7 +227,7 @@
   }
 
   if (source.IsInkOverflowComputed()) {
-    ink_overflow_type_ = source.InkOverflowType();
+    ink_overflow_type_ = static_cast<unsigned>(source.InkOverflowType());
     new (&ink_overflow_)
         NGInkOverflow(source.InkOverflowType(), source.ink_overflow_);
   }
@@ -802,7 +802,8 @@
 }
 
 void NGFragmentItem::InvalidateInkOverflow() {
-  ink_overflow_type_ = ink_overflow_.Invalidate(InkOverflowType());
+  ink_overflow_type_ =
+      static_cast<unsigned>(ink_overflow_.Invalidate(InkOverflowType()));
 }
 
 PhysicalRect NGFragmentItem::RecalcInkOverflowForCursor(
@@ -860,24 +861,27 @@
     NGTextFragmentPaintInfo paint_info = TextPaintInfo(cursor.Items());
     if (paint_info.shape_result) {
       if (Type() == kSvgText) {
-        ink_overflow_type_ = ink_overflow_.SetSvgTextInkOverflow(
-            InkOverflowType(), paint_info, Style(), ScaledFont(),
-            SvgFragmentData()->rect, SvgScalingFactor(),
-            SvgFragmentData()->length_adjust_scale,
-            BuildSvgTransformForBoundingBox(), self_and_contents_rect_out);
+        ink_overflow_type_ =
+            static_cast<unsigned>(ink_overflow_.SetSvgTextInkOverflow(
+                InkOverflowType(), paint_info, Style(), ScaledFont(),
+                SvgFragmentData()->rect, SvgScalingFactor(),
+                SvgFragmentData()->length_adjust_scale,
+                BuildSvgTransformForBoundingBox(), self_and_contents_rect_out));
         return;
       }
       // Create |ScopedInlineItem| here because the decoration box is not
       // supported for SVG.
       NGInlinePaintContext::ScopedInlineItem scoped_inline_item(*this,
                                                                 inline_context);
-      ink_overflow_type_ = ink_overflow_.SetTextInkOverflow(
-          InkOverflowType(), paint_info, Style(), RectInContainerFragment(),
-          inline_context, self_and_contents_rect_out);
+      ink_overflow_type_ =
+          static_cast<unsigned>(ink_overflow_.SetTextInkOverflow(
+              InkOverflowType(), paint_info, Style(), RectInContainerFragment(),
+              inline_context, self_and_contents_rect_out));
       return;
     }
 
-    ink_overflow_type_ = ink_overflow_.Reset(InkOverflowType());
+    ink_overflow_type_ =
+        static_cast<unsigned>(ink_overflow_.Reset(InkOverflowType()));
     *self_and_contents_rect_out = LocalRect();
     return;
   }
@@ -922,8 +926,8 @@
       contents_rect = text_combine->AdjustRectForBoundingBox(contents_rect);
     // Line boxes don't have self overflow. Compute content overflow only.
     *self_and_contents_rect_out = UnionRect(LocalRect(), contents_rect);
-    ink_overflow_type_ =
-        ink_overflow_.SetContents(InkOverflowType(), contents_rect, Size());
+    ink_overflow_type_ = static_cast<unsigned>(
+        ink_overflow_.SetContents(InkOverflowType(), contents_rect, Size()));
     return;
   }
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
index 67d6fb4..f97d202e 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
@@ -552,11 +552,11 @@
     return static_cast<NGInkOverflow::Type>(ink_overflow_type_);
   }
   bool IsInkOverflowComputed() const {
-    return InkOverflowType() != NGInkOverflow::kNotSet &&
-           InkOverflowType() != NGInkOverflow::kInvalidated;
+    return InkOverflowType() != NGInkOverflow::Type::kNotSet &&
+           InkOverflowType() != NGInkOverflow::Type::kInvalidated;
   }
   bool HasInkOverflow() const {
-    return InkOverflowType() != NGInkOverflow::kNone;
+    return InkOverflowType() != NGInkOverflow::Type::kNone;
   }
   const LayoutBox* InkOverflowOwnerBox() const;
   LayoutBox* MutableInkOverflowOwnerBox();
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc
index 389a836..256217e4 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc
@@ -104,12 +104,13 @@
 
   // To test moving ink overflow, add an ink overflow to |move_of_line|.
   PhysicalRect not_small_ink_overflow_rect(0, 0, 5000, 100);
-  move_of_line.ink_overflow_type_ = move_of_line.ink_overflow_.SetContents(
-      move_of_line.InkOverflowType(), not_small_ink_overflow_rect,
-      line_item->Size());
-  EXPECT_EQ(move_of_line.InkOverflowType(), NGInkOverflow::kContents);
+  move_of_line.ink_overflow_type_ =
+      static_cast<int>(move_of_line.ink_overflow_.SetContents(
+          move_of_line.InkOverflowType(), not_small_ink_overflow_rect,
+          line_item->Size()));
+  EXPECT_EQ(move_of_line.InkOverflowType(), NGInkOverflow::Type::kContents);
   NGFragmentItem move_of_line2(std::move(move_of_line));
-  EXPECT_EQ(move_of_line2.InkOverflowType(), NGInkOverflow::kContents);
+  EXPECT_EQ(move_of_line2.InkOverflowType(), NGInkOverflow::Type::kContents);
   EXPECT_EQ(move_of_line2.InkOverflow(), not_small_ink_overflow_rect);
 
   // Test copying a text item.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc
index 4a88b06..1852545 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc
@@ -48,7 +48,9 @@
 NGInkOverflow::~NGInkOverflow() {
   // Because |Type| is kept outside of the instance, callers must call |Reset|
   // before destructing.
-  DCHECK(type_ == kNotSet || type_ == kNone || type_ == kInvalidated) << type_;
+  DCHECK(type_ == Type::kNotSet || type_ == Type::kNone ||
+         type_ == Type::kInvalidated)
+      << static_cast<int>(type_);
 }
 #endif
 
@@ -56,12 +58,12 @@
   source.CheckType(source_type);
   new (this) NGInkOverflow();
   switch (source_type) {
-    case kNotSet:
-    case kInvalidated:
-    case kNone:
+    case Type::kNotSet:
+    case Type::kInvalidated:
+    case Type::kNone:
       break;
-    case kSmallSelf:
-    case kSmallContents:
+    case Type::kSmallSelf:
+    case Type::kSmallContents:
       static_assert(sizeof(outsets_) == sizeof(single_),
                     "outsets should be the size of a pointer");
       single_ = source.single_;
@@ -70,11 +72,11 @@
         DCHECK_EQ(outsets_[i], source.outsets_[i]);
 #endif
       break;
-    case kSelf:
-    case kContents:
+    case Type::kSelf:
+    case Type::kContents:
       single_ = new NGSingleInkOverflow(*source.single_);
       break;
-    case kSelfAndContents:
+    case Type::kSelfAndContents:
       container_ = new NGContainerInkOverflow(*source.container_);
       break;
   }
@@ -85,12 +87,12 @@
   source.CheckType(source_type);
   new (this) NGInkOverflow();
   switch (source_type) {
-    case kNotSet:
-    case kInvalidated:
-    case kNone:
+    case Type::kNotSet:
+    case Type::kInvalidated:
+    case Type::kNone:
       break;
-    case kSmallSelf:
-    case kSmallContents:
+    case Type::kSmallSelf:
+    case Type::kSmallContents:
       static_assert(sizeof(outsets_) == sizeof(single_),
                     "outsets should be the size of a pointer");
       single_ = source.single_;
@@ -99,12 +101,12 @@
         DCHECK_EQ(outsets_[i], source.outsets_[i]);
 #endif
       break;
-    case kSelf:
-    case kContents:
+    case Type::kSelf:
+    case Type::kContents:
       single_ = source.single_;
       source.single_ = nullptr;
       break;
-    case kSelfAndContents:
+    case Type::kSelfAndContents:
       container_ = source.container_;
       source.container_ = nullptr;
       break;
@@ -114,19 +116,20 @@
 
 NGInkOverflow::Type NGInkOverflow::Reset(Type type, Type new_type) {
   CheckType(type);
-  DCHECK(new_type == kNotSet || new_type == kNone || new_type == kInvalidated);
+  DCHECK(new_type == Type::kNotSet || new_type == Type::kNone ||
+         new_type == Type::kInvalidated);
   switch (type) {
-    case kNotSet:
-    case kInvalidated:
-    case kNone:
-    case kSmallSelf:
-    case kSmallContents:
+    case Type::kNotSet:
+    case Type::kInvalidated:
+    case Type::kNone:
+    case Type::kSmallSelf:
+    case Type::kSmallContents:
       break;
-    case kSelf:
-    case kContents:
+    case Type::kSelf:
+    case Type::kContents:
       delete single_;
       break;
-    case kSelfAndContents:
+    case Type::kSelfAndContents:
       delete container_;
       break;
   }
@@ -144,21 +147,21 @@
 PhysicalRect NGInkOverflow::Self(Type type, const PhysicalSize& size) const {
   CheckType(type);
   switch (type) {
-    case kNotSet:
-    case kInvalidated:
+    case Type::kNotSet:
+    case Type::kInvalidated:
 #if defined(DISALLOW_READING_UNSET)
       if (!read_unset_as_none_)
         NOTREACHED();
       [[fallthrough]];
 #endif
-    case kNone:
-    case kSmallContents:
-    case kContents:
+    case Type::kNone:
+    case Type::kSmallContents:
+    case Type::kContents:
       return {PhysicalOffset(), size};
-    case kSmallSelf:
+    case Type::kSmallSelf:
       return FromOutsets(size);
-    case kSelf:
-    case kSelfAndContents:
+    case Type::kSelf:
+    case Type::kSelfAndContents:
       DCHECK(single_);
       return single_->ink_overflow;
   }
@@ -170,23 +173,23 @@
                                      const PhysicalSize& size) const {
   CheckType(type);
   switch (type) {
-    case kNotSet:
-    case kInvalidated:
+    case Type::kNotSet:
+    case Type::kInvalidated:
 #if defined(DISALLOW_READING_UNSET)
       if (!read_unset_as_none_)
         NOTREACHED();
       [[fallthrough]];
 #endif
-    case kNone:
-    case kSmallSelf:
-    case kSelf:
+    case Type::kNone:
+    case Type::kSmallSelf:
+    case Type::kSelf:
       return PhysicalRect();
-    case kSmallContents:
+    case Type::kSmallContents:
       return FromOutsets(size);
-    case kContents:
+    case Type::kContents:
       DCHECK(single_);
       return single_->ink_overflow;
-    case kSelfAndContents:
+    case Type::kSelfAndContents:
       DCHECK(container_);
       return container_->contents_ink_overflow;
   }
@@ -198,23 +201,23 @@
                                             const PhysicalSize& size) const {
   CheckType(type);
   switch (type) {
-    case kNotSet:
-    case kInvalidated:
+    case Type::kNotSet:
+    case Type::kInvalidated:
 #if defined(DISALLOW_READING_UNSET)
       if (!read_unset_as_none_)
         NOTREACHED();
       [[fallthrough]];
 #endif
-    case kNone:
+    case Type::kNone:
       return {PhysicalOffset(), size};
-    case kSmallSelf:
-    case kSmallContents:
+    case Type::kSmallSelf:
+    case Type::kSmallContents:
       return FromOutsets(size);
-    case kSelf:
-    case kContents:
+    case Type::kSelf:
+    case Type::kContents:
       DCHECK(single_);
       return single_->ink_overflow;
-    case kSelfAndContents:
+    case Type::kSelfAndContents:
       DCHECK(container_);
       return container_->SelfAndContentsInkOverflow();
   }
@@ -271,18 +274,18 @@
       top_outset + size.height + bottom_outset);
 
   switch (type) {
-    case kSelfAndContents:
+    case Type::kSelfAndContents:
       Reset(type);
       [[fallthrough]];
-    case kNotSet:
-    case kInvalidated:
-    case kNone:
-    case kSmallSelf:
-    case kSmallContents:
+    case Type::kNotSet:
+    case Type::kInvalidated:
+    case Type::kNone:
+    case Type::kSmallSelf:
+    case Type::kSmallContents:
       single_ = new NGSingleInkOverflow(adjusted_ink_overflow);
       return SetType(new_type);
-    case kSelf:
-    case kContents:
+    case Type::kSelf:
+    case Type::kContents:
       DCHECK(single_);
       single_->ink_overflow = adjusted_ink_overflow;
       return SetType(new_type);
@@ -296,7 +299,7 @@
   CheckType(type);
   if (!HasOverflow(ink_overflow, size))
     return Reset(type);
-  return SetSingle(type, ink_overflow, size, kSelf, kSmallSelf);
+  return SetSingle(type, ink_overflow, size, Type::kSelf, Type::kSmallSelf);
 }
 
 NGInkOverflow::Type NGInkOverflow::SetContents(Type type,
@@ -305,7 +308,8 @@
   CheckType(type);
   if (!HasOverflow(ink_overflow, size))
     return Reset(type);
-  return SetSingle(type, ink_overflow, size, kContents, kSmallContents);
+  return SetSingle(type, ink_overflow, size, Type::kContents,
+                   Type::kSmallContents);
 }
 
 NGInkOverflow::Type NGInkOverflow::Set(Type type,
@@ -317,28 +321,29 @@
   if (!HasOverflow(self, size)) {
     if (!HasOverflow(contents, size))
       return Reset(type);
-    return SetSingle(type, contents, size, kContents, kSmallContents);
+    return SetSingle(type, contents, size, Type::kContents,
+                     Type::kSmallContents);
   }
   if (!HasOverflow(contents, size))
-    return SetSingle(type, self, size, kSelf, kSmallSelf);
+    return SetSingle(type, self, size, Type::kSelf, Type::kSmallSelf);
 
   switch (type) {
-    case kSelf:
-    case kContents:
+    case Type::kSelf:
+    case Type::kContents:
       Reset(type);
       [[fallthrough]];
-    case kNotSet:
-    case kInvalidated:
-    case kNone:
-    case kSmallSelf:
-    case kSmallContents:
+    case Type::kNotSet:
+    case Type::kInvalidated:
+    case Type::kNone:
+    case Type::kSmallSelf:
+    case Type::kSmallContents:
       container_ = new NGContainerInkOverflow(self, contents);
-      return SetType(kSelfAndContents);
-    case kSelfAndContents:
+      return SetType(Type::kSelfAndContents);
+    case Type::kSelfAndContents:
       DCHECK(container_);
       container_->ink_overflow = self;
       container_->contents_ink_overflow = contents;
-      return kSelfAndContents;
+      return Type::kSelfAndContents;
   }
   NOTREACHED();
 }
@@ -351,7 +356,7 @@
     const NGInlinePaintContext* inline_context,
     PhysicalRect* ink_overflow_out) {
   CheckType(type);
-  DCHECK(type == kNotSet || type == kInvalidated);
+  DCHECK(type == Type::kNotSet || type == Type::kInvalidated);
   absl::optional<PhysicalRect> ink_overflow = ComputeTextInkOverflow(
       text_info, style, style.GetFont(), rect_in_container, inline_context);
   if (!ink_overflow) {
@@ -374,7 +379,7 @@
     const AffineTransform& transform,
     PhysicalRect* ink_overflow_out) {
   CheckType(type);
-  DCHECK(type == kNotSet || type == kInvalidated);
+  DCHECK(type == Type::kNotSet || type == Type::kInvalidated);
   // Unapply length_adjust_scale because the size argument is compared with
   // Font::TextInkBounds().
   PhysicalSize item_size =
diff --git a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h
index 57149671..ec9369f 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h
@@ -60,7 +60,7 @@
 // |Type|.
 class CORE_EXPORT NGInkOverflow {
  public:
-  enum Type {
+  enum class Type {
     kNotSet,
     kInvalidated,
     kNone,
@@ -93,9 +93,9 @@
   PhysicalRect SelfAndContents(Type type, const PhysicalSize& size) const;
 
   // Reset to |kNone|.
-  Type Reset(Type type) { return Reset(type, kNone); }
+  Type Reset(Type type) { return Reset(type, Type::kNone); }
   // Reset to |kInvalidated|.
-  Type Invalidate(Type type) { return Reset(type, kInvalidated); }
+  Type Invalidate(Type type) { return Reset(type, Type::kInvalidated); }
 
   // Set self ink overflow rect.
   // If |this| had contents ink overflow, it is cleared.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow_test.cc b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow_test.cc
index 2d00a74..444dd1a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow_test.cc
@@ -52,57 +52,57 @@
   NGInkOverflow::Type type;
 
   NGInkOverflow::Type ExpectedTypeForContents() const {
-    if (type == NGInkOverflow::kSelf)
-      return NGInkOverflow::kContents;
-    if (type == NGInkOverflow::kSmallSelf)
-      return NGInkOverflow::kSmallContents;
+    if (type == NGInkOverflow::Type::kSelf)
+      return NGInkOverflow::Type::kContents;
+    if (type == NGInkOverflow::Type::kSmallSelf)
+      return NGInkOverflow::Type::kSmallContents;
     return type;
   }
 } rect_data[] = {
-    {{20, 10}, {0, 0, 0, 0}, {0, 0, 20, 10}, NGInkOverflow::kNone},
-    {{20, 10}, {0, 0, 20, 10}, {0, 0, 20, 10}, NGInkOverflow::kNone},
+    {{20, 10}, {0, 0, 0, 0}, {0, 0, 20, 10}, NGInkOverflow::Type::kNone},
+    {{20, 10}, {0, 0, 20, 10}, {0, 0, 20, 10}, NGInkOverflow::Type::kNone},
 
     // 2: One of values is max small, all others are 0.
     {{20, 10},
      {0, 0, MAX_SMALL + 20, 10},
      {0, 0, MAX_SMALL + 20, 10},
-     NGInkOverflow::kSmallSelf},
+     NGInkOverflow::Type::kSmallSelf},
     {{20, 10},
      {0, 0, 20, MAX_SMALL + 10},
      {0, 0, 20, MAX_SMALL + 10},
-     NGInkOverflow::kSmallSelf},
+     NGInkOverflow::Type::kSmallSelf},
     {{20, 10},
      {-MAX_SMALL, 0, MAX_SMALL + 20, 10},
      {-MAX_SMALL, 0, MAX_SMALL + 20, 10},
-     NGInkOverflow::kSmallSelf},
+     NGInkOverflow::Type::kSmallSelf},
     {{20, 10},
      {0, -MAX_SMALL, 20, MAX_SMALL + 10},
      {0, -MAX_SMALL, 20, MAX_SMALL + 10},
-     NGInkOverflow::kSmallSelf},
+     NGInkOverflow::Type::kSmallSelf},
 
     // 6: One of values is large, all others are 0.
     {{20, 10},
      {0, 0, MIN_LARGE + 20, 10},
      {0, 0, MIN_LARGE + 20, 10},
-     NGInkOverflow::kSelf},
+     NGInkOverflow::Type::kSelf},
     {{20, 10},
      {0, 0, 20, MIN_LARGE + 10},
      {0, 0, 20, MIN_LARGE + 10},
-     NGInkOverflow::kSelf},
+     NGInkOverflow::Type::kSelf},
     {{20, 10},
      {-MIN_LARGE, 0, MIN_LARGE + 20, 10},
      {-MIN_LARGE, 0, MIN_LARGE + 20, 10},
-     NGInkOverflow::kSelf},
+     NGInkOverflow::Type::kSelf},
     {{20, 10},
      {0, -MIN_LARGE, 20, MIN_LARGE + 10},
      {0, -MIN_LARGE, 20, MIN_LARGE + 10},
-     NGInkOverflow::kSelf},
+     NGInkOverflow::Type::kSelf},
 
     // 10: All values are the max small values.
     {{20, 10},
      {-MAX_SMALL, -MAX_SMALL, MAX_SMALL * 2 + 20, MAX_SMALL * 2 + 10},
      {-MAX_SMALL, -MAX_SMALL, MAX_SMALL * 2 + 20, MAX_SMALL * 2 + 10},
-     NGInkOverflow::kSmallSelf},
+     NGInkOverflow::Type::kSmallSelf},
 };
 
 class RectDataTest : public NGInkOverflowTest,
@@ -116,7 +116,7 @@
   const RectData data = GetParam();
   NGInkOverflow ink_overflow;
   NGInkOverflow::Type type = ink_overflow.SetSelf(
-      NGInkOverflow::kNotSet, FromFloatRound(data.rect), data.size);
+      NGInkOverflow::Type::kNotSet, FromFloatRound(data.rect), data.size);
   EXPECT_EQ(type, data.type);
   PhysicalRect result = ink_overflow.Self(type, data.size);
   EXPECT_EQ(result, FromFloatRound(data.expect));
@@ -127,7 +127,7 @@
   const RectData data = GetParam();
   NGInkOverflow ink_overflow;
   NGInkOverflow::Type type = ink_overflow.Set(
-      NGInkOverflow::kNotSet, {}, FromFloatRound(data.rect), data.size);
+      NGInkOverflow::Type::kNotSet, {}, FromFloatRound(data.rect), data.size);
   EXPECT_EQ(type, data.ExpectedTypeForContents());
   PhysicalRect result = ink_overflow.SelfAndContents(type, data.size);
   EXPECT_EQ(result, FromFloatRound(data.expect));
@@ -138,7 +138,7 @@
   const RectData data = GetParam();
   NGInkOverflow original;
   NGInkOverflow::Type type = original.SetSelf(
-      NGInkOverflow::kNotSet, FromFloatRound(data.rect), data.size);
+      NGInkOverflow::Type::kNotSet, FromFloatRound(data.rect), data.size);
   NGInkOverflow copy(type, original);
   EXPECT_EQ(copy.Self(type, data.size), original.Self(type, data.size));
   original.Reset(type);
@@ -151,11 +151,11 @@
   PhysicalRect contents;
   NGInkOverflow::Type type;
 } self_and_contents_data[] = {
-    {{10, 10}, {0, 0, 10, 10}, {0, 0, 10, 10}, NGInkOverflow::kNone},
+    {{10, 10}, {0, 0, 10, 10}, {0, 0, 10, 10}, NGInkOverflow::Type::kNone},
     {{10, 10},
      {-1, -1, 12, 12},
      {0, 0, 20, 20},
-     NGInkOverflow::kSelfAndContents},
+     NGInkOverflow::Type::kSelfAndContents},
 };
 
 class SelfAndContentsDataTest
@@ -169,8 +169,8 @@
 TEST_P(SelfAndContentsDataTest, SelfAndContents) {
   const SelfAndContentsData data = GetParam();
   NGInkOverflow ink_overflow;
-  NGInkOverflow::Type type = ink_overflow.Set(NGInkOverflow::kNotSet, data.self,
-                                              data.contents, data.size);
+  NGInkOverflow::Type type = ink_overflow.Set(
+      NGInkOverflow::Type::kNotSet, data.self, data.contents, data.size);
   EXPECT_EQ(type, data.type);
   EXPECT_EQ(ink_overflow.Self(type, data.size), data.self);
   EXPECT_EQ(ink_overflow.SelfAndContents(type, data.size),
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
index 548e934c..f68621e 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -390,7 +390,7 @@
     *const_cast<PhysicalRect*>(ComputeLayoutOverflowAddress()) =
         layout_overflow;
   }
-  ink_overflow_type_ = NGInkOverflow::kNotSet;
+  SetInkOverflowType(NGInkOverflow::Type::kNotSet);
   has_borders_ = has_borders;
   if (has_borders_)
     *const_cast<NGPhysicalBoxStrut*>(ComputeBordersAddress()) = borders;
@@ -505,12 +505,12 @@
 NGPhysicalBoxFragment::~NGPhysicalBoxFragment() {
   // Note: This function may not always be called because the dtor of
   // NGPhysicalFragment is made non-virtual for memory efficiency.
-  ink_overflow_type_ = ink_overflow_.Reset(InkOverflowType());
+  SetInkOverflowType(ink_overflow_.Reset(InkOverflowType()));
 }
 
 void NGPhysicalBoxFragment::Dispose() {
   if (HasInkOverflow())
-    ink_overflow_type_ = ink_overflow_.Reset(InkOverflowType());
+    SetInkOverflowType(ink_overflow_.Reset(InkOverflowType()));
   if (const_has_fragment_items_)
     ComputeItemsAddress()->~NGFragmentItems();
   if (const_has_rare_data_)
@@ -1125,8 +1125,8 @@
 
 void NGPhysicalBoxFragment::SetInkOverflow(const PhysicalRect& self,
                                            const PhysicalRect& contents) {
-  ink_overflow_type_ =
-      ink_overflow_.Set(InkOverflowType(), self, contents, Size());
+  SetInkOverflowType(
+      ink_overflow_.Set(InkOverflowType(), self, contents, Size()));
 }
 
 void NGPhysicalBoxFragment::RecalcInkOverflow(const PhysicalRect& contents) {
@@ -1278,7 +1278,7 @@
 
 #if DCHECK_IS_ON()
 void NGPhysicalBoxFragment::InvalidateInkOverflow() {
-  ink_overflow_type_ = ink_overflow_.Invalidate(InkOverflowType());
+  SetInkOverflowType(ink_overflow_.Invalidate(InkOverflowType()));
 }
 #endif
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
index f28b316..acdb22d 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
@@ -299,11 +299,11 @@
     return static_cast<NGInkOverflow::Type>(ink_overflow_type_);
   }
   bool IsInkOverflowComputed() const {
-    return InkOverflowType() != NGInkOverflow::kNotSet &&
-           InkOverflowType() != NGInkOverflow::kInvalidated;
+    return InkOverflowType() != NGInkOverflow::Type::kNotSet &&
+           InkOverflowType() != NGInkOverflow::Type::kInvalidated;
   }
   bool HasInkOverflow() const {
-    return InkOverflowType() != NGInkOverflow::kNone;
+    return InkOverflowType() != NGInkOverflow::Type::kNone;
   }
 
   // 3 types of ink overflows:
@@ -567,6 +567,9 @@
   }
 
   void SetInkOverflow(const PhysicalRect& self, const PhysicalRect& contents);
+  void SetInkOverflowType(NGInkOverflow::Type type) {
+    ink_overflow_type_ = static_cast<unsigned>(type);
+  }
   PhysicalRect RecalcContentsInkOverflow();
   PhysicalRect ComputeSelfInkOverflow() const;
 
diff --git a/third_party/blink/renderer/core/paint/ng/ng_highlight_overlay.cc b/third_party/blink/renderer/core/paint/ng/ng_highlight_overlay.cc
index 820f296..5e0c101 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_highlight_overlay.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_highlight_overlay.cc
@@ -173,9 +173,9 @@
   result.Append(",");
   result.AppendNumber(to);
   result.Append(")");
-  for (const HighlightLayer& layer : decorations) {
+  for (const HighlightLayer& current_layer : decorations) {
     result.Append("+");
-    result.Append(layer.ToString());
+    result.Append(current_layer.ToString());
   }
   return result.ToString();
 }
@@ -202,9 +202,9 @@
   result.emplace_back(HighlightLayerType::kOriginating);
 
   for (const auto& marker : custom) {
-    auto* custom = To<CustomHighlightMarker>(marker.Get());
+    auto* custom_marker = To<CustomHighlightMarker>(marker.Get());
     HighlightLayer layer{HighlightLayerType::kCustom,
-                         custom->GetHighlightName()};
+                         custom_marker->GetHighlightName()};
     if (!result.Contains(layer))
       result.push_back(layer);
   }
@@ -275,7 +275,7 @@
     for (const auto& marker : custom) {
       if (marker->EndOffset() <= last_from || marker->StartOffset() >= first_to)
         continue;
-      auto* custom = To<CustomHighlightMarker>(marker.Get());
+      auto* custom_marker = To<CustomHighlightMarker>(marker.Get());
       unsigned content_start =
           GetTextContentOffset(*text_node, marker->StartOffset());
       unsigned content_end =
@@ -284,11 +284,11 @@
         continue;
       result.emplace_back(content_start,
                           HighlightLayer{HighlightLayerType::kCustom,
-                                         custom->GetHighlightName()},
+                                         custom_marker->GetHighlightName()},
                           HighlightEdgeType::kStart);
       result.emplace_back(content_end,
                           HighlightLayer{HighlightLayerType::kCustom,
-                                         custom->GetHighlightName()},
+                                         custom_marker->GetHighlightName()},
                           HighlightEdgeType::kEnd);
     }
 
diff --git a/third_party/blink/renderer/core/paint/paint_layer_test.cc b/third_party/blink/renderer/core/paint/paint_layer_test.cc
index da962bd..59159be7 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_test.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_test.cc
@@ -2356,10 +2356,12 @@
   )HTML");
 
   auto* view_layer = GetLayoutView().Layer();
-  bool is_fixed_to_view = false;
-  EXPECT_EQ(nullptr,
-            view_layer->ContainingScrollContainerLayer(&is_fixed_to_view));
-  EXPECT_TRUE(is_fixed_to_view);
+  {
+    bool is_fixed_to_view = false;
+    EXPECT_EQ(nullptr,
+              view_layer->ContainingScrollContainerLayer(&is_fixed_to_view));
+    EXPECT_TRUE(is_fixed_to_view);
+  }
 
   TEST_SCROLL_CONTAINER("sticky", view_layer, false);
   TEST_SCROLL_CONTAINER("absolute", view_layer, false);
diff --git a/third_party/blink/renderer/core/script/script_runner.cc b/third_party/blink/renderer/core/script/script_runner.cc
index 304363d..c047855b4 100644
--- a/third_party/blink/renderer/core/script/script_runner.cc
+++ b/third_party/blink/renderer/core/script/script_runner.cc
@@ -172,6 +172,24 @@
     return;
 
   if (it->value &= ~static_cast<DelayReasons>(delay_reason)) {
+    // The delay must be less than a few seconds because some scripts times out
+    // otherwise. This is only applied to milestone based delay.
+    if (delay_reason == DelayReason::kLoad &&
+        (it->value & static_cast<DelayReasons>(DelayReason::kMilestone))) {
+      // PostDelayedTask to limit the delay amount of DelayAsyncScriptExecution
+      // (see crbug/1340837). DelayReason::kMilestone is sent on
+      // loading-milestones such as LCP, first_paint, or finished_parsing.
+      // Once the script is completely loaded, even if the milestones delaying
+      // execution aren't removed, we eventually want to trigger
+      // script-execution anyway for compatibility reasons, since waiting too
+      // long for the milestones can cause compatibility issues.
+      task_runner_->PostDelayedTask(
+          FROM_HERE,
+          WTF::Bind(&ScriptRunner::RemoveDelayReasonFromScript,
+                    WrapWeakPersistent(this), WrapPersistent(pending_script),
+                    DelayReason::kMilestone),
+          features::kDelayAsyncScriptExecutionLimitParam.Get());
+    }
     // Still to be delayed.
     return;
   }
diff --git a/third_party/blink/renderer/core/timing/window_performance.cc b/third_party/blink/renderer/core/timing/window_performance.cc
index 0444f889..13c892a0 100644
--- a/third_party/blink/renderer/core/timing/window_performance.cc
+++ b/third_party/blink/renderer/core/timing/window_performance.cc
@@ -703,6 +703,9 @@
   if (HTMLImageElement* image_element = DynamicTo<HTMLImageElement>(element)) {
     image_element->SetIsLCPElement();
   }
+
+  if (element)
+    element->GetDocument().OnLargestContentfulPaintUpdated();
 }
 
 void WindowPerformance::OnPaintFinished() {
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_audio_element_capturer_source_unittest.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_audio_element_capturer_source_unittest.cc
index a1a082f9..b444214 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/html_audio_element_capturer_source_unittest.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_audio_element_capturer_source_unittest.cc
@@ -92,9 +92,11 @@
         String::FromUTF8("audio_track"), false /* remote */,
         std::move(capture_source));
     media_stream_component_ = MakeGarbageCollected<MediaStreamComponentImpl>(
-        media_stream_source_->Id(), media_stream_source_);
+        media_stream_source_->Id(), media_stream_source_,
+        std::make_unique<MediaStreamAudioTrack>(/*is_local=*/true));
 
-    ASSERT_TRUE(source()->ConnectToTrack(media_stream_component_.Get()));
+    ASSERT_TRUE(
+        source()->ConnectToInitializedTrack(media_stream_component_.Get()));
   }
 
   Persistent<MediaStreamSource> media_stream_source_;
diff --git a/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder_unittest.cc b/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder_unittest.cc
index c491c2a..0fe32e1 100644
--- a/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder_unittest.cc
+++ b/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder_unittest.cc
@@ -18,6 +18,7 @@
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/public/web/web_heap.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_component_impl.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
@@ -266,8 +267,9 @@
         String::FromUTF8("dummy_source_name"), false /* remote */,
         std::move(audio_source));
     media_stream_component_ = MakeGarbageCollected<MediaStreamComponentImpl>(
-        String::FromUTF8("audio_track"), source);
-    CHECK(MediaStreamAudioSource::From(source)->ConnectToTrack(
+        String::FromUTF8("audio_track"), source,
+        std::make_unique<MediaStreamAudioTrack>(/*is_local=*/true));
+    CHECK(MediaStreamAudioSource::From(source)->ConnectToInitializedTrack(
         media_stream_component_));
   }
 };
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_utils.cc b/third_party/blink/renderer/modules/mediastream/media_stream_utils.cc
index 75acc6cc..f7a3238 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_utils.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_utils.cc
@@ -21,48 +21,15 @@
 
 namespace blink {
 
-namespace {
-
-void CreateNativeVideoMediaStreamTrack(MediaStreamComponent* component) {
-  DCHECK(!component->GetPlatformTrack());
-  MediaStreamSource* source = component->Source();
-  DCHECK_EQ(source->GetType(), MediaStreamSource::kTypeVideo);
-  MediaStreamVideoSource* native_source =
-      MediaStreamVideoSource::GetVideoSource(source);
-  DCHECK(native_source);
-  component->SetPlatformTrack(std::make_unique<blink::MediaStreamVideoTrack>(
-      native_source, blink::MediaStreamVideoSource::ConstraintsOnceCallback(),
-      component->Enabled()));
-}
-
-}  // namespace
-
-void MediaStreamUtils::DidCreateMediaStreamTrack(
-    MediaStreamComponent* component) {
-  DCHECK(component);
-  DCHECK(!component->GetPlatformTrack());
-  DCHECK(component->Source());
-
-  switch (component->GetSourceType()) {
-    case MediaStreamSource::kTypeAudio:
-      MediaStreamAudioSource::From(component->Source())
-          ->ConnectToTrack(component);
-      break;
-    case MediaStreamSource::kTypeVideo:
-      CreateNativeVideoMediaStreamTrack(component);
-      break;
-  }
-}
-
 MediaStreamTrack* MediaStreamUtils::CreateLocalAudioTrack(
     ExecutionContext* execution_context,
     MediaStreamSource* source) {
   DCHECK_EQ(source->GetType(), MediaStreamSource::kTypeAudio);
   DCHECK(!source->Remote());
-  // TODO(crbug.com/1302689): Provide a local MediaStreamAudioTrack instance in
-  // the Component constructor.
-  auto* component = MakeGarbageCollected<MediaStreamComponentImpl>(source);
-  DidCreateMediaStreamTrack(component);
+  auto* component = MakeGarbageCollected<MediaStreamComponentImpl>(
+      source, std::make_unique<MediaStreamAudioTrack>(/*is_local=*/true));
+  MediaStreamAudioSource::From(component->Source())
+      ->ConnectToInitializedTrack(component);
   return MakeGarbageCollected<MediaStreamTrackImpl>(execution_context,
                                                     component);
 }
diff --git a/third_party/blink/renderer/modules/mediastream/processed_local_audio_source_test.cc b/third_party/blink/renderer/modules/mediastream/processed_local_audio_source_test.cc
index 90bfd53..b9315d2 100644
--- a/third_party/blink/renderer/modules/mediastream/processed_local_audio_source_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/processed_local_audio_source_test.cc
@@ -143,7 +143,8 @@
         String::FromUTF8("audio_label"), MediaStreamSource::kTypeAudio,
         String::FromUTF8("audio_track"), false /* remote */, std::move(source));
     audio_component_ = MakeGarbageCollected<MediaStreamComponentImpl>(
-        audio_source_->Id(), audio_source_);
+        audio_source_->Id(), audio_source_,
+        std::make_unique<MediaStreamAudioTrack>(/*is_local=*/true));
   }
 
   void CheckSourceFormatMatches(const media::AudioParameters& params) {
@@ -217,7 +218,7 @@
       .WillOnce(Invoke(
           capture_source_callback(),
           &media::AudioCapturerSource::CaptureCallback::OnCaptureStarted));
-  ASSERT_TRUE(audio_source()->ConnectToTrack(audio_track()));
+  ASSERT_TRUE(audio_source()->ConnectToInitializedTrack(audio_track()));
   CheckOutputFormatMatches(audio_source()->GetAudioParameters());
 
   // Connect a sink to the track.
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
index ae1538a2..ae841485 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
@@ -376,7 +376,8 @@
     HeapVector<Member<MediaStreamComponent>> audio_components(
         static_cast<size_t>(1));
     audio_components[0] = MakeGarbageCollected<MediaStreamComponentImpl>(
-        audio_source->Id(), audio_source);
+        audio_source->Id(), audio_source,
+        std::make_unique<MediaStreamAudioTrack>(/*is_local=*/true));
     EXPECT_CALL(
         *webrtc_audio_device_platform_support_->mock_audio_capturer_source(),
         Initialize(_, _));
@@ -389,7 +390,8 @@
     EXPECT_CALL(
         *webrtc_audio_device_platform_support_->mock_audio_capturer_source(),
         Stop());
-    CHECK(processed_audio_source_ptr->ConnectToTrack(audio_components[0]));
+    CHECK(processed_audio_source_ptr->ConnectToInitializedTrack(
+        audio_components[0]));
 
     HeapVector<Member<MediaStreamComponent>> video_components(
         static_cast<size_t>(1));
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl_test.cc
index 4478dff..567022f 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl_test.cc
@@ -22,6 +22,7 @@
 #include "third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_component_impl.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
 #include "third_party/blink/renderer/platform/peerconnection/rtc_stats.h"
@@ -75,9 +76,10 @@
         String::FromUTF8(id), MediaStreamSource::kTypeAudio,
         String::FromUTF8("local_audio_track"), false, std::move(audio_source));
 
-    auto* component =
-        MakeGarbageCollected<MediaStreamComponentImpl>(source->Id(), source);
-    audio_source_ptr->ConnectToTrack(component);
+    auto* component = MakeGarbageCollected<MediaStreamComponentImpl>(
+        source->Id(), source,
+        std::make_unique<MediaStreamAudioTrack>(/*is_local=*/true));
+    audio_source_ptr->ConnectToInitializedTrack(component);
     return component;
   }
 
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl_test.cc
index be2eaba..19ccd60 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl_test.cc
@@ -22,6 +22,7 @@
 #include "third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.h"
 #include "third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
 #include "third_party/blink/renderer/platform/peerconnection/webrtc_util.h"
 #include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
@@ -159,9 +160,10 @@
         String::FromUTF8(id), MediaStreamSource::kTypeAudio,
         String::FromUTF8("local_audio_track"), false, std::move(audio_source));
 
-    auto* component =
-        MakeGarbageCollected<MediaStreamComponentImpl>(source->Id(), source);
-    audio_source_ptr->ConnectToTrack(component);
+    auto* component = MakeGarbageCollected<MediaStreamComponentImpl>(
+        source->Id(), source,
+        std::make_unique<MediaStreamAudioTrack>(/*is_local=*/true));
+    audio_source_ptr->ConnectToInitializedTrack(component);
     return component;
   }
 
diff --git a/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer_test.cc b/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer_test.cc
index 97bf43b..7f9a041 100644
--- a/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer_test.cc
@@ -19,6 +19,7 @@
 #include "third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.h"
 #include "third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_component_impl.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
 #include "third_party/blink/renderer/platform/peerconnection/webrtc_util.h"
@@ -234,9 +235,10 @@
         String::FromUTF8(id), MediaStreamSource::kTypeAudio,
         String::FromUTF8("local_audio_track"), false, std::move(audio_source));
 
-    auto* component =
-        MakeGarbageCollected<MediaStreamComponentImpl>(source->Id(), source);
-    audio_source_ptr->ConnectToTrack(component);
+    auto* component = MakeGarbageCollected<MediaStreamComponentImpl>(
+        source->Id(), source,
+        std::make_unique<MediaStreamAudioTrack>(/*is_local=*/true));
+    audio_source_ptr->ConnectToInitializedTrack(component);
     return component;
   }
 
diff --git a/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map_test.cc b/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map_test.cc
index 4be5a42..878072a 100644
--- a/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map_test.cc
@@ -18,6 +18,7 @@
 #include "third_party/blink/public/web/web_heap.h"
 #include "third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_component_impl.h"
 #include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
 
@@ -47,9 +48,10 @@
         String::FromUTF8(id), MediaStreamSource::kTypeAudio,
         String::FromUTF8("local_audio_track"), false, std::move(audio_source));
 
-    auto* component =
-        MakeGarbageCollected<MediaStreamComponentImpl>(source->Id(), source);
-    audio_source_ptr->ConnectToTrack(component);
+    auto* component = MakeGarbageCollected<MediaStreamComponentImpl>(
+        source->Id(), source,
+        std::make_unique<MediaStreamAudioTrack>(/*is_local=*/true));
+    audio_source_ptr->ConnectToInitializedTrack(component);
     return component;
   }
 
diff --git a/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_test.cc b/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_test.cc
index 9c235bc..4b0e4035 100644
--- a/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_test.cc
@@ -20,6 +20,7 @@
 #include "third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h"
 #include "third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_component_impl.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
 #include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
@@ -52,9 +53,10 @@
         String::FromUTF8("local_audio_id"), MediaStreamSource::kTypeAudio,
         String::FromUTF8("local_audio_track"), false, std::move(audio_source));
 
-    auto* component =
-        MakeGarbageCollected<MediaStreamComponentImpl>(source->Id(), source);
-    audio_source_ptr->ConnectToTrack(component);
+    auto* component = MakeGarbageCollected<MediaStreamComponentImpl>(
+        source->Id(), source,
+        std::make_unique<MediaStreamAudioTrack>(/*is_local=*/true));
+    audio_source_ptr->ConnectToInitializedTrack(component);
     return component;
   }
 
diff --git a/third_party/blink/renderer/modules/peerconnection/webrtc_set_description_observer_test.cc b/third_party/blink/renderer/modules/peerconnection/webrtc_set_description_observer_test.cc
index a239e60..c300502 100644
--- a/third_party/blink/renderer/modules/peerconnection/webrtc_set_description_observer_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/webrtc_set_description_observer_test.cc
@@ -21,6 +21,7 @@
 #include "third_party/blink/renderer/modules/peerconnection/testing/mock_peer_connection_interface.h"
 #include "third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
 #include "third_party/blink/renderer/platform/peerconnection/webrtc_util.h"
 #include "third_party/webrtc/api/peer_connection_interface.h"
 #include "third_party/webrtc/media/base/fake_media_engine.h"
@@ -221,9 +222,10 @@
         String::FromUTF8(id), MediaStreamSource::kTypeAudio,
         String::FromUTF8("local_audio_track"), false, std::move(audio_source));
 
-    auto* component =
-        MakeGarbageCollected<MediaStreamComponentImpl>(source->Id(), source);
-    audio_source_ptr->ConnectToTrack(component);
+    auto* component = MakeGarbageCollected<MediaStreamComponentImpl>(
+        source->Id(), source,
+        std::make_unique<MediaStreamAudioTrack>(/*is_local=*/true));
+    audio_source_ptr->ConnectToInitializedTrack(component);
     return component;
   }
 
diff --git a/third_party/blink/renderer/modules/shared_storage/shared_storage.cc b/third_party/blink/renderer/modules/shared_storage/shared_storage.cc
index 0ff0ed3..6f646dc 100644
--- a/third_party/blink/renderer/modules/shared_storage/shared_storage.cc
+++ b/third_party/blink/renderer/modules/shared_storage/shared_storage.cc
@@ -8,8 +8,10 @@
 #include <tuple>
 #include <utility>
 
+#include "base/metrics/histogram_functions.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/common/features.h"
@@ -82,9 +84,40 @@
   return true;
 }
 
+void LogTimingHistogramForVoidOperation(
+    blink::SharedStorageVoidOperation caller,
+    base::TimeTicks start_time) {
+  base::TimeDelta elapsed_time = base::TimeTicks::Now() - start_time;
+  switch (caller) {
+    case blink::SharedStorageVoidOperation::kRun:
+      base::UmaHistogramMediumTimes("Storage.SharedStorage.Document.Timing.Run",
+                                    elapsed_time);
+      break;
+    case blink::SharedStorageVoidOperation::kSet:
+      base::UmaHistogramMediumTimes("Storage.SharedStorage.Document.Timing.Set",
+                                    elapsed_time);
+      break;
+    case blink::SharedStorageVoidOperation::kAppend:
+      base::UmaHistogramMediumTimes(
+          "Storage.SharedStorage.Document.Timing.Append", elapsed_time);
+      break;
+    case blink::SharedStorageVoidOperation::kDelete:
+      base::UmaHistogramMediumTimes(
+          "Storage.SharedStorage.Document.Timing.Delete", elapsed_time);
+      break;
+    case blink::SharedStorageVoidOperation::kClear:
+      base::UmaHistogramMediumTimes(
+          "Storage.SharedStorage.Document.Timing.Clear", elapsed_time);
+      break;
+    default:
+      NOTREACHED();
+  }
+}
+
 void OnVoidOperationFinished(ScriptPromiseResolver* resolver,
                              SharedStorage* shared_storage,
                              blink::SharedStorageVoidOperation caller,
+                             base::TimeTicks start_time,
                              bool success,
                              const String& error_message) {
   DCHECK(resolver);
@@ -102,6 +135,7 @@
     return;
   }
 
+  LogTimingHistogramForVoidOperation(caller, start_time);
   resolver->Resolve();
 }
 
@@ -153,6 +187,7 @@
                                  const String& value,
                                  const SharedStorageSetMethodOptions* options,
                                  ExceptionState& exception_state) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
   ExecutionContext* execution_context = ExecutionContext::From(script_state);
   CHECK(execution_context->IsWindow());
 
@@ -189,7 +224,7 @@
           key, value, ignore_if_present,
           WTF::Bind(&OnVoidOperationFinished, WrapPersistent(resolver),
                     WrapPersistent(this),
-                    blink::SharedStorageVoidOperation::kSet));
+                    blink::SharedStorageVoidOperation::kSet, start_time));
 
   return promise;
 }
@@ -198,6 +233,7 @@
                                     const String& key,
                                     const String& value,
                                     ExceptionState& exception_state) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
   ExecutionContext* execution_context = ExecutionContext::From(script_state);
   CHECK(execution_context->IsWindow());
 
@@ -232,7 +268,7 @@
           key, value,
           WTF::Bind(&OnVoidOperationFinished, WrapPersistent(resolver),
                     WrapPersistent(this),
-                    blink::SharedStorageVoidOperation::kAppend));
+                    blink::SharedStorageVoidOperation::kAppend, start_time));
 
   return promise;
 }
@@ -240,6 +276,7 @@
 ScriptPromise SharedStorage::Delete(ScriptState* script_state,
                                     const String& key,
                                     ExceptionState& exception_state) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
   ExecutionContext* execution_context = ExecutionContext::From(script_state);
   CHECK(execution_context->IsWindow());
 
@@ -264,15 +301,17 @@
 
   GetSharedStorageDocumentService(execution_context)
       ->SharedStorageDelete(
-          key, WTF::Bind(&OnVoidOperationFinished, WrapPersistent(resolver),
-                         WrapPersistent(this),
-                         blink::SharedStorageVoidOperation::kDelete));
+          key,
+          WTF::Bind(&OnVoidOperationFinished, WrapPersistent(resolver),
+                    WrapPersistent(this),
+                    blink::SharedStorageVoidOperation::kDelete, start_time));
 
   return promise;
 }
 
 ScriptPromise SharedStorage::clear(ScriptState* script_state,
                                    ExceptionState& exception_state) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
   ExecutionContext* execution_context = ExecutionContext::From(script_state);
   CHECK(execution_context->IsWindow());
 
@@ -289,9 +328,10 @@
   }
 
   GetSharedStorageDocumentService(execution_context)
-      ->SharedStorageClear(WTF::Bind(
-          &OnVoidOperationFinished, WrapPersistent(resolver),
-          WrapPersistent(this), blink::SharedStorageVoidOperation::kClear));
+      ->SharedStorageClear(
+          WTF::Bind(&OnVoidOperationFinished, WrapPersistent(resolver),
+                    WrapPersistent(this),
+                    blink::SharedStorageVoidOperation::kClear, start_time));
 
   return promise;
 }
@@ -312,6 +352,7 @@
     HeapVector<Member<SharedStorageUrlWithMetadata>> urls,
     const SharedStorageRunOperationMethodOptions* options,
     ExceptionState& exception_state) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
   ExecutionContext* execution_context = ExecutionContext::From(script_state);
   CHECK(execution_context->IsWindow());
 
@@ -471,8 +512,8 @@
           name, std::move(converted_urls), std::move(serialized_data),
           WTF::Bind(
               [](ScriptPromiseResolver* resolver, SharedStorage* shared_storage,
-                 bool success, const String& error_message,
-                 const KURL& opaque_url) {
+                 base::TimeTicks start_time, bool success,
+                 const String& error_message, const KURL& opaque_url) {
                 DCHECK(resolver);
                 ScriptState* script_state = resolver->GetScriptState();
 
@@ -486,9 +527,12 @@
                   return;
                 }
 
+                base::UmaHistogramMediumTimes(
+                    "Storage.SharedStorage.Document.Timing.SelectURL",
+                    base::TimeTicks::Now() - start_time);
                 resolver->Resolve(opaque_url);
               },
-              WrapPersistent(resolver), WrapPersistent(this)));
+              WrapPersistent(resolver), WrapPersistent(this), start_time));
 
   return promise;
 }
@@ -505,6 +549,7 @@
     const String& name,
     const SharedStorageRunOperationMethodOptions* options,
     ExceptionState& exception_state) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
   ExecutionContext* execution_context = ExecutionContext::From(script_state);
   CHECK(execution_context->IsWindow());
 
@@ -534,7 +579,7 @@
           name, std::move(serialized_data),
           WTF::Bind(&OnVoidOperationFinished, WrapPersistent(resolver),
                     WrapPersistent(this),
-                    blink::SharedStorageVoidOperation::kRun));
+                    blink::SharedStorageVoidOperation::kRun, start_time));
 
   return promise;
 }
diff --git a/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.cc b/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.cc
index 63a4fa9..3af1e8e 100644
--- a/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.cc
+++ b/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.cc
@@ -4,6 +4,8 @@
 
 #include "third_party/blink/renderer/modules/shared_storage/shared_storage_worklet.h"
 
+#include "base/metrics/histogram_functions.h"
+#include "base/time/time.h"
 #include "third_party/blink/public/common/shared_storage/shared_storage_utils.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
@@ -28,6 +30,7 @@
 ScriptPromise SharedStorageWorklet::addModule(ScriptState* script_state,
                                               const String& module_url,
                                               ExceptionState& exception_state) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
   ExecutionContext* execution_context = ExecutionContext::From(script_state);
   CHECK(execution_context->IsWindow());
 
@@ -76,7 +79,8 @@
           script_source_url,
           WTF::Bind(
               [](ScriptPromiseResolver* resolver,
-                 SharedStorageWorklet* shared_storage_worklet, bool success,
+                 SharedStorageWorklet* shared_storage_worklet,
+                 base::TimeTicks start_time, bool success,
                  const String& error_message) {
                 DCHECK(resolver);
                 ScriptState* script_state = resolver->GetScriptState();
@@ -91,9 +95,12 @@
                   return;
                 }
 
+                base::UmaHistogramMediumTimes(
+                    "Storage.SharedStorage.Document.Timing.AddModule",
+                    base::TimeTicks::Now() - start_time);
                 resolver->Resolve();
               },
-              WrapPersistent(resolver), WrapPersistent(this)));
+              WrapPersistent(resolver), WrapPersistent(this), start_time));
 
   return promise;
 }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc b/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc
index 43a368b..442f13f 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc
@@ -512,14 +512,15 @@
     status_ = Status::Destroyed;
 }
 
-void GPUExternalTexture::Destroy() {
+bool GPUExternalTexture::Destroy() {
   if (status_ == Status::Destroyed)
-    return;
+    return false;
 
   status_ = Status::Destroyed;
 
   DCHECK(mailbox_texture_);
   mailbox_texture_.reset();
+  return true;
 }
 
 void GPUExternalTexture::ListenToHTMLVideoElement(HTMLVideoElement* video) {
@@ -577,11 +578,9 @@
 }
 
 void GPUExternalTexture::ExpireExternalTexture() {
-  if (expired())
-    return;
-
-  device()->RemoveActiveExternalTexture(this);
-  Destroy();
+  if (Destroy()) {
+    device()->RemoveActiveExternalTexture(this);
+  }
 }
 
 void GPUExternalTexture::ListenToVideoFrame(VideoFrame* frame) {
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_external_texture.h b/third_party/blink/renderer/modules/webgpu/gpu_external_texture.h
index 9f35f2a..5b73e61 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_external_texture.h
+++ b/third_party/blink/renderer/modules/webgpu/gpu_external_texture.h
@@ -39,7 +39,10 @@
   GPUExternalTexture(const GPUExternalTexture&) = delete;
   GPUExternalTexture& operator=(const GPUExternalTexture&) = delete;
 
-  void Destroy();
+  // Destroy() returns false when the GPUExternalTexture has been destroyed
+  // already. It returns true when the GPUExternalTexture has been destroyed
+  // successfully.
+  bool Destroy();
 
   bool expired() const;
 
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.cc b/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.cc
index c28b2ae..bb0db8e 100644
--- a/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.cc
+++ b/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.cc
@@ -76,26 +76,6 @@
   return static_cast<MediaStreamAudioSource*>(source->GetPlatformSource());
 }
 
-bool MediaStreamAudioSource::ConnectToTrack(MediaStreamComponent* component) {
-  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
-  DCHECK(component);
-
-  // Sanity-check that there is not already a MediaStreamAudioTrack instance
-  // associated with |component|.
-  if (MediaStreamAudioTrack::From(component)) {
-    LOG(DFATAL) << "Attempting to connect another source to a "
-                   "WebMediaStreamTrack/MediaStreamComponent.";
-    return false;
-  }
-
-  // Create and initialize a new MediaStreamAudioTrack and pass ownership of it
-  // to the MediaStreamComponent.
-  component->SetPlatformTrack(
-      CreateMediaStreamAudioTrack(component->Id().Utf8()));
-
-  return ConnectToInitializedTrack(component);
-}
-
 bool MediaStreamAudioSource::ConnectToInitializedTrack(
     MediaStreamComponent* component) {
   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h b/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h
index 8889e5e..cf462fc 100644
--- a/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h
+++ b/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h
@@ -90,17 +90,6 @@
   // streamed-in from outside the application.
   bool is_local_source() const { return is_local_source_; }
 
-  // Connects this source to the given |component|, creating the appropriate
-  // implementation of the content::MediaStreamAudioTrack interface, which
-  // becomes associated with and owned by |component|. Returns true if the
-  // source was successfully started.
-  // TODO(https://crbug.com/1302689): Remove this once all callers have been
-  // moved to ConnectToInitializedTrack().
-  [
-      [deprecated("Use ConnectToInitializedTrack() with a component which "
-                  "already has an associated MediaStreamAudioTrack.")]] bool
-  ConnectToTrack(MediaStreamComponent* component);
-
   // Connects this source to the given |component|, which already has an
   // associated MediaStreamAudioTrack. Returns true if the source was
   // successfully started.
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_component.h b/third_party/blink/renderer/platform/mediastream/media_stream_component.h
index 9e1fa8d4..1b42063 100644
--- a/third_party/blink/renderer/platform/mediastream/media_stream_component.h
+++ b/third_party/blink/renderer/platform/mediastream/media_stream_component.h
@@ -78,11 +78,6 @@
 
   virtual MediaStreamTrackPlatform* GetPlatformTrack() const = 0;
 
-  // Deprecated - use the MediaStreamComponentImpl constructor which takes a
-  // MediaStreamTrackPlatform instead.
-  // TODO(crbug.com/1302689): Remove once all callers have been migrated.
-  [[deprecated]] virtual void SetPlatformTrack(
-      std::unique_ptr<MediaStreamTrackPlatform> platform_track) = 0;
   virtual void GetSettings(MediaStreamTrackPlatform::Settings&) = 0;
   virtual MediaStreamTrackPlatform::CaptureHandle GetCaptureHandle() = 0;
 
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_component_impl.cc b/third_party/blink/renderer/platform/mediastream/media_stream_component_impl.cc
index 645ca796a..eb76628 100644
--- a/third_party/blink/renderer/platform/mediastream/media_stream_component_impl.cc
+++ b/third_party/blink/renderer/platform/mediastream/media_stream_component_impl.cc
@@ -81,12 +81,8 @@
     MediaStreamSource* source,
     std::unique_ptr<MediaStreamTrackPlatform> platform_track)
     : MediaStreamComponentImpl(id, source) {
-  // TODO(https://crbug.com/1302689): Change to a DCHECK(platform_track) once
-  // all callers provide a platform_track here, rather than using
-  // SetPlatformTrack().
-  if (platform_track) {
-    CheckSourceAndTrackSameType(source, platform_track.get());
-  }
+  DCHECK(platform_track);
+  CheckSourceAndTrackSameType(source, platform_track.get());
   platform_track_ = std::move(platform_track);
 }
 
@@ -94,12 +90,8 @@
     MediaStreamSource* source,
     std::unique_ptr<MediaStreamTrackPlatform> platform_track)
     : MediaStreamComponentImpl(source) {
-  // TODO(https://crbug.com/1302689): Change to a DCHECK(platform_track) once
-  // all callers provide a platform_track here, rather than using
-  // SetPlatformTrack().
-  if (platform_track) {
-    CheckSourceAndTrackSameType(source, platform_track.get());
-  }
+  DCHECK(platform_track);
+  CheckSourceAndTrackSameType(source, platform_track.get());
   platform_track_ = std::move(platform_track);
 }
 
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_component_impl.h b/third_party/blink/renderer/platform/mediastream/media_stream_component_impl.h
index 0e679f9a..1dcee56c 100644
--- a/third_party/blink/renderer/platform/mediastream/media_stream_component_impl.h
+++ b/third_party/blink/renderer/platform/mediastream/media_stream_component_impl.h
@@ -100,10 +100,6 @@
     return platform_track_.get();
   }
 
-  [[deprecated]] void SetPlatformTrack(
-      std::unique_ptr<MediaStreamTrackPlatform> platform_track) override {
-    platform_track_ = std::move(platform_track);
-  }
   void GetSettings(MediaStreamTrackPlatform::Settings&) override;
   MediaStreamTrackPlatform::CaptureHandle GetCaptureHandle() override;
 
diff --git a/third_party/blink/renderer/platform/mediastream/transferred_media_stream_component.cc b/third_party/blink/renderer/platform/mediastream/transferred_media_stream_component.cc
index be53a83..9c175a5c 100644
--- a/third_party/blink/renderer/platform/mediastream/transferred_media_stream_component.cc
+++ b/third_party/blink/renderer/platform/mediastream/transferred_media_stream_component.cc
@@ -155,16 +155,6 @@
   return nullptr;
 }
 
-[[deprecated]] void TransferredMediaStreamComponent::SetPlatformTrack(
-    std::unique_ptr<MediaStreamTrackPlatform> platform_track) {
-  if (component_) {
-    component_->SetPlatformTrack(std::move(platform_track));
-    return;
-  }
-  // TODO(https://crbug.com/1288839): Save and forward to component_ once it's
-  // initialized.
-}
-
 void TransferredMediaStreamComponent::GetSettings(
     MediaStreamTrackPlatform::Settings& settings) {
   if (component_) {
diff --git a/third_party/blink/renderer/platform/mediastream/transferred_media_stream_component.h b/third_party/blink/renderer/platform/mediastream/transferred_media_stream_component.h
index 7175fea..efdd99c 100644
--- a/third_party/blink/renderer/platform/mediastream/transferred_media_stream_component.h
+++ b/third_party/blink/renderer/platform/mediastream/transferred_media_stream_component.h
@@ -57,8 +57,6 @@
 
   MediaStreamTrackPlatform* GetPlatformTrack() const override;
 
-  [[deprecated]] void SetPlatformTrack(
-      std::unique_ptr<MediaStreamTrackPlatform> platform_track) override;
   void GetSettings(MediaStreamTrackPlatform::Settings&) override;
   MediaStreamTrackPlatform::CaptureHandle GetCaptureHandle() override;
 
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 2a0d503..e434de9 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -463,7 +463,6 @@
 crbug.com/1002049 external/wpt/css/mediaqueries/aspect-ratio-006.html [ Failure ]
 crbug.com/962417 external/wpt/css/mediaqueries/mq-negative-range-001.html [ Failure ]
 crbug.com/1343368 external/wpt/css/mediaqueries/viewport-script-dynamic.html [ Failure ]
-crbug.com/1343366 external/wpt/css/mediaqueries/mq-invalid-media-type-layer-001.html [ Failure ]
 crbug.com/1345247 external/wpt/css/mediaqueries/prefers-color-scheme-svg-image.html [ Failure ]
 
 crbug.com/815111 external/wpt/css/css-fill-stroke/paint-order-001.tentative.html [ Failure ]
@@ -3269,6 +3268,8 @@
 crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/css/css-color-adjust/rendering/dark-color-scheme/color-scheme-iframe-preferred.html [ Failure ]
+crbug.com/626703 virtual/dark-color-scheme/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/color-scheme-iframe-preferred.html [ Failure ]
 crbug.com/626703 [ Mac10.15 ] external/wpt/service-workers/cache-storage/cross-partition.https.tentative.html [ Skip Timeout ]
 crbug.com/626703 external/wpt/custom-elements/form-associated/ElementInternals-target-element-is-held-strongly.html [ Timeout ]
 crbug.com/626703 external/wpt/custom-elements/throw-on-dynamic-markup-insertion-counter-construct-xml-parser.xhtml [ Crash ]
diff --git a/third_party/blink/web_tests/android/WebviewWPTExpectations b/third_party/blink/web_tests/android/WebviewWPTExpectations
index 228ffb3..3ec34c5b 100644
--- a/third_party/blink/web_tests/android/WebviewWPTExpectations
+++ b/third_party/blink/web_tests/android/WebviewWPTExpectations
@@ -2683,7 +2683,6 @@
 crbug.com/1050754 external/wpt/html/interaction/focus/the-autofocus-attribute/same-origin-autofocus.html [ Failure ]
 crbug.com/1050754 external/wpt/html/interaction/focus/the-autofocus-attribute/spin-by-blocking-style-sheet.html [ Timeout ]
 crbug.com/1050754 external/wpt/html/interaction/focus/the-autofocus-attribute/update-the-rendering.html [ Failure ]
-crbug.com/1050754 external/wpt/html/rendering/dimension-attributes.html [ Failure Pass ]
 crbug.com/1050754 external/wpt/html/rendering/non-replaced-elements/flow-content-0/dialog.html [ Failure ]
 crbug.com/1050754 external/wpt/html/rendering/non-replaced-elements/form-controls/button-style.html [ Failure Pass ]
 crbug.com/1050754 external/wpt/html/rendering/non-replaced-elements/form-controls/resets.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version
index 694375c..4fd1d26b 100644
--- a/third_party/blink/web_tests/external/Version
+++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@
-Version: ba9d74cbfd10ea809d5099a636043e257bc76a24
+Version: 1302ef132c68962352904012bd69a7dc9f2bbf4a
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index 068940c..30911c3 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -93046,6 +93046,19 @@
          {}
         ]
        ],
+       "color-scheme-iframe-preferred.html": [
+        "1c8814b112492a0efaee5b8f944db1234a341131",
+        [
+         null,
+         [
+          [
+           "/css/css-color-adjust/rendering/dark-color-scheme/color-scheme-iframe-preferred-ref.html",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ],
        "color-scheme-table-border-currentcolor-responsive.html": [
         "1d42a4fddabe8c3337ced4f9ad9b676b4b25c09b",
         [
@@ -240311,7 +240324,7 @@
        ]
       ],
       "popup-appearance.tentative.html": [
-       "84421317e5a1c092064df022f38d432fcfea2152",
+       "4acc276c16c362a76567b253992c064ed42c4f42",
        [
         null,
         [
@@ -240350,7 +240363,7 @@
        ]
       ],
       "popup-hidden-display.tentative.html": [
-       "69c82b24827eff766df75a651aef0d8e1a382212",
+       "45c1f91ed43d405fdc016098e30a9f344ee53df3",
        [
         null,
         [
@@ -266498,6 +266511,10 @@
         "8cc4618ede4af030adc8fe5f119deccf3c2e3882",
         []
        ],
+       "color-scheme-iframe-preferred-ref.html": [
+        "ff2683bbd31da32aecf5bb48c3cf417543438f9c",
+        []
+       ],
        "color-scheme-table-border-currentcolor-responsive-ref.html": [
         "613ef03229fefdd9b7e5e80b7e3a6c5e4f49f97a",
         []
@@ -266523,6 +266540,10 @@
          "11f88db4a0b3e94d620b5a92314c88040210cfae",
          []
         ],
+        "prefers-color-scheme-blue-purple.html": [
+         "99d687b47f4685e8ca0960fbcfd7aaa7bdafc19a",
+         []
+        ],
         "prefers-color-scheme.svg": [
          "3afcac70fe9b561280f32d53420404a3cf23e1cf",
          []
@@ -317126,7 +317147,7 @@
        []
       ],
       "popup-appearance-ref.tentative.html": [
-       "95f43dba293b466fdc6fb86db61050b1dc436b0c",
+       "b8ebba794d2ceb0c98f93236dd19aecd4b176754",
        []
       ],
       "popup-backdrop-appearance-ref.tentative.html": [
@@ -317138,7 +317159,7 @@
        []
       ],
       "popup-hidden-display-ref.tentative.html": [
-       "bb321b17ba8e0ff0bc5bbd2dfb3fa7651c99996e",
+       "adfcfbf204e21e541180370fc4d9043f0fbb8cca",
        []
       ],
       "popup-inside-display-none-ref.tentative.html": [
@@ -317159,7 +317180,7 @@
       ],
       "resources": {
        "popup-styles.css": [
-        "1a99019f060dfc5218eb42904893ebf3366b8ded",
+        "e1d3e43dccc251cbe172d5d4f78a93c139a160c2",
         []
        ],
        "popup-utils.js": [
@@ -472526,7 +472547,7 @@
     },
     "rendering": {
      "dimension-attributes.html": [
-      "00a5ff9a9673f1bc5bea22807e2e90a41c3348af",
+      "f3dc8f8171807c3940930a25dff56b1245adee7f",
       [
        null,
        {
@@ -481177,7 +481198,7 @@
        ]
       ],
       "popup-attribute-basic.tentative.html": [
-       "d6090486aa27653abdccae3423bcafe446bb13ca",
+       "1ff7f13c61d8427e85fc7c9ae4a4d82072469b99",
        [
         null,
         {}
@@ -481190,13 +481211,6 @@
         {}
        ]
       ],
-      "popup-css-properties.tentative.html": [
-       "ac5e9f7f2f4117d0667ce07b867be1e745aa4ef1",
-       [
-        null,
-        {}
-       ]
-      ],
       "popup-defaultopen-2.tentative.html": [
        "36b621f2cf0381272ab44d5e5f9a6c2cfd41de1f",
        [
@@ -481226,17 +481240,7 @@
        ]
       ],
       "popup-focus.tentative.html": [
-       "979cb0a8feab692e9aa4a3eaaa5d09b41d62c4ea",
-       [
-        null,
-        {
-         "testdriver": true,
-         "timeout": "long"
-        }
-       ]
-      ],
-      "popup-hover-hide.tentative.html": [
-       "16acd687aae657a7b24a5fda8150b926c337fb93",
+       "4290b7dda50c2e3d7b170d90f8e1e2da84eff7e0",
        [
         null,
         {
@@ -481281,16 +481285,6 @@
         }
        ]
       ],
-      "popup-popuphovertarget-attribute.tentative.html": [
-       "e845b0d49df5f4cd06b1a7c602d5a219f403605a",
-       [
-        null,
-        {
-         "testdriver": true,
-         "timeout": "long"
-        }
-       ]
-      ],
       "popup-removal-2.tentative.html": [
        "7cf0951e5b14bcca0a6af7d8846cb4f85e8b8995",
        [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/color-scheme-iframe-preferred-ref.html b/third_party/blink/web_tests/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/color-scheme-iframe-preferred-ref.html
new file mode 100644
index 0000000..ff2683bb
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/color-scheme-iframe-preferred-ref.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<style>
+  div {
+    width: 100px;
+    height: 100px;
+  }
+</style>
+<div style="background-color: purple"></div>
+<div style="background-color: blue"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/color-scheme-iframe-preferred.html b/third_party/blink/web_tests/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/color-scheme-iframe-preferred.html
new file mode 100644
index 0000000..1c8814b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/color-scheme-iframe-preferred.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>prefers-color-scheme propagation</title>
+<link rel="help" href="https://drafts.csswg.org/css-color-adjust/#color-scheme-effect">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/4772">
+<link rel="match" href="color-scheme-iframe-preferred-ref.html">
+<style>
+  iframe {
+    display: block;
+    border: none;
+    width: 100px;
+    height: 100px;
+  }
+</style>
+<iframe style="color-scheme: dark" src="support/prefers-color-scheme-blue-purple.html"></iframe>
+<iframe style="color-scheme: light" src="support/prefers-color-scheme-blue-purple.html"></iframe>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/support/prefers-color-scheme-blue-purple.html b/third_party/blink/web_tests/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/support/prefers-color-scheme-blue-purple.html
new file mode 100644
index 0000000..99d687b4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/support/prefers-color-scheme-blue-purple.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<style>
+:root { background-color: blue }
+@media (prefers-color-scheme: dark) {
+  :root { background-color: purple }
+}
+</style>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/dimension-attributes.html b/third_party/blink/web_tests/external/wpt/html/rendering/dimension-attributes.html
index 00a5ff9..f3dc8f81 100644
--- a/third_party/blink/web_tests/external/wpt/html/rendering/dimension-attributes.html
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/dimension-attributes.html
@@ -102,6 +102,14 @@
   }
 }
 
+function newImgSource() {
+  return () => {
+    var elem = newElem("source")();
+    elem.setAttribute("srcset", "/images/green-100x50.png");
+    return elem;
+  }
+}
+
 /*
  * Array of tests.  Each test consists of the following information:
  *
@@ -160,16 +168,19 @@
   [ newElem("marquee"), "hspace", "marginRight", true ],
   [ newElem("marquee"), "vspace", "marginTop", true ],
   [ newElem("marquee"), "vspace", "marginBottom", true ],
+  // <source width> is mapped to <img> width if both are in <picture>.
+  [ newImgSource(), "width", "width", true, newElem("img"), newElem("picture") ],
+  // <source height> is mapped to <img> height if both are in <picture>.
+  [ newImgSource(), "height", "height", true, newElem("img"), newElem("picture") ],
 ];
 
-
 function style(element) {
   return element.ownerDocument.defaultView.getComputedStyle(element);
 }
 
 const container = document.getElementById("container");
 
-for (let [ctor, attr, prop, zero_allowed] of tests) {
+for (let [ctor, attr, prop, zero_allowed, mappedElemCtor, containerCtor] of tests) {
   let valid, invalid;
   if (zero_allowed) {
     valid = valid_values_with_0;
@@ -178,31 +189,52 @@
     valid = valid_values;
     invalid = invalid_values_with_0;
   }
-  for (let [value, result] of valid) {
-    let elem = ctor();
-    test(function() {
-      this.add_cleanup(() => elem.remove());
-      elem.setAttribute(attr, value);
-      assert_equals(elem.getAttribute(attr), value);
-      container.appendChild(elem);
-      assert_equals(style(elem)[prop], result);
-    }, `<${elem.localName} ${attr}="${value}"> mapping to ${prop}`);
+
+  let elemContainer = null;
+  if (!!containerCtor) {
+    elemContainer = containerCtor();
+    container.appendChild(elemContainer);
+  } else {
+    elemContainer = container;
   }
 
-  let default_elem = ctor();
-  container.appendChild(default_elem);
+  let runTest = (value, expected) => {
+    let elem = ctor();
+    let mappedElem = !!mappedElemCtor ? mappedElemCtor() : elem;
+    test(function() {
+      this.add_cleanup(() => {
+        elem.remove();
+        if (!!mappedElemCtor) {
+          mappedElem.remove();
+        }
+      });
+      elem.setAttribute(attr, value);
+      assert_equals(elem.getAttribute(attr), value);
+      elemContainer.appendChild(elem);
+      if (!!mappedElemCtor) {
+        elemContainer.appendChild(mappedElem);
+      }
+      assert_equals(style(mappedElem)[prop], expected);
+      }, `<${elem.localName} ${attr}="${value}"> mapping to ` +
+         `<${mappedElem.localName}> ${prop} property`);
+  }
+
+  for (let [value, result] of valid) {
+    runTest(value, result);
+  }
+
+  let default_elem = !!mappedElemCtor ? mappedElemCtor() : ctor();
+  elemContainer.appendChild(default_elem);
   let defaultVal = style(default_elem)[prop];
   default_elem.remove();
   for (let value of invalid) {
-    let elem = ctor();
-    test(function() {
-      this.add_cleanup(() => elem.remove());
-      elem.setAttribute(attr, value);
-      assert_equals(elem.getAttribute(attr), value);
-      container.appendChild(elem);
-      assert_equals(style(elem)[prop], defaultVal);
-    }, `<${elem.localName} ${attr}="${value}"> mapping to ${prop}`);
+    runTest(value, defaultVal);
+  }
+
+  if (!!containerCtor) {
+    elemContainer.remove();
   }
 }
+
 </script>
 </body>
diff --git a/third_party/blink/web_tests/inspector-protocol/css/css-get-styles-for-node.js b/third_party/blink/web_tests/inspector-protocol/css/css-get-styles-for-node.js
index 35e3854..9ceb17e 100644
--- a/third_party/blink/web_tests/inspector-protocol/css/css-get-styles-for-node.js
+++ b/third_party/blink/web_tests/inspector-protocol/css/css-get-styles-for-node.js
@@ -5,7 +5,7 @@
           <div id='inspected' style='padding-top: 55px; margin-top: 33px !important;'></div>
           <div id='child-div'></div>
       </div>
-      <div id='shorthand-div' style='margin: 0; margin-top: 5px; padding: var(--x); border: 1px solid black;'></div>`,
+      <div id='shorthand-div' style='margin: 0; margin-top: 5px; padding: var(--x); border: 1px solid black; flex: 1 !important;'></div>`,
       'The test verifies functionality of protocol method CSS.getMatchedStylesForNode and CSS.getInlineStylesForNode.');
 
   await dp.DOM.enable();
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/css/mediaqueries/mq-invalid-media-type-layer-002-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/css/mediaqueries/mq-invalid-media-type-layer-002-expected.txt
deleted file mode 100644
index a2b6836..0000000
--- a/third_party/blink/web_tests/platform/generic/external/wpt/css/mediaqueries/mq-invalid-media-type-layer-002-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL 'layer' used as media types is a syntax error assert_equals: expected "not all" but got "not layer"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/html/rendering/dimension-attributes-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/html/rendering/dimension-attributes-expected.txt
index bf21fea..7a1df93 100644
--- a/third_party/blink/web_tests/platform/generic/external/wpt/html/rendering/dimension-attributes-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/external/wpt/html/rendering/dimension-attributes-expected.txt
@@ -1,1644 +1,1724 @@
 This is a testharness.js-based test.
-Found 1640 tests; 1624 PASS, 16 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS <hr width="200"> mapping to width
-PASS <hr width="1007"> mapping to width
-PASS <hr width="   00523   "> mapping to width
-PASS <hr width="200.25"> mapping to width
-PASS <hr width="200.7"> mapping to width
-PASS <hr width="200."> mapping to width
-PASS <hr width="200in"> mapping to width
-PASS <hr width="200.25in"> mapping to width
-PASS <hr width="200 %"> mapping to width
-PASS <hr width="200 abc"> mapping to width
-PASS <hr width="200%"> mapping to width
-PASS <hr width="200%abc"> mapping to width
-PASS <hr width="200.25%"> mapping to width
-PASS <hr width="200.%"> mapping to width
-PASS <hr width="20.25e2"> mapping to width
-PASS <hr width="20.25E2"> mapping to width
-FAIL <hr width="0"> mapping to width assert_equals: expected "0px" but got "1px"
-FAIL <hr width="0%"> mapping to width assert_equals: expected "0%" but got "1px"
-FAIL <hr width="0px"> mapping to width assert_equals: expected "0px" but got "1px"
-FAIL <hr width="-0"> mapping to width assert_equals: expected "auto" but got "1px"
-FAIL <hr width="-0%"> mapping to width assert_equals: expected "auto" but got "1px"
-PASS <hr width="-200"> mapping to width
-PASS <hr width="-200px"> mapping to width
-PASS <hr width="   -200"> mapping to width
-PASS <hr width="+-200"> mapping to width
-PASS <hr width="-+200"> mapping to width
-PASS <hr width="-200%"> mapping to width
-PASS <hr width="+200"> mapping to width
-PASS <hr width="   +200in    "> mapping to width
-PASS <hr width="   +200.25in    "> mapping to width
-PASS <hr width="+200%"> mapping to width
-PASS <hr width="   +200.25%    "> mapping to width
-PASS <hr width="   +200.25%abc"> mapping to width
-FAIL <hr width="+0"> mapping to width assert_equals: expected "auto" but got "1px"
-FAIL <hr width="+0%"> mapping to width assert_equals: expected "auto" but got "1px"
-PASS <hr width="."> mapping to width
-PASS <hr width=".%"> mapping to width
-PASS <hr width=".x"> mapping to width
-PASS <hr width=".5"> mapping to width
-PASS <hr width=".5%"> mapping to width
-PASS <iframe width="200"> mapping to width
-PASS <iframe width="1007"> mapping to width
-PASS <iframe width="   00523   "> mapping to width
-PASS <iframe width="200.25"> mapping to width
-PASS <iframe width="200.7"> mapping to width
-PASS <iframe width="200."> mapping to width
-PASS <iframe width="200in"> mapping to width
-PASS <iframe width="200.25in"> mapping to width
-PASS <iframe width="200 %"> mapping to width
-PASS <iframe width="200 abc"> mapping to width
-PASS <iframe width="200%"> mapping to width
-PASS <iframe width="200%abc"> mapping to width
-PASS <iframe width="200.25%"> mapping to width
-PASS <iframe width="200.%"> mapping to width
-PASS <iframe width="20.25e2"> mapping to width
-PASS <iframe width="20.25E2"> mapping to width
-PASS <iframe width="0"> mapping to width
-PASS <iframe width="0%"> mapping to width
-PASS <iframe width="0px"> mapping to width
-PASS <iframe width="-0"> mapping to width
-PASS <iframe width="-0%"> mapping to width
-PASS <iframe width="-200"> mapping to width
-PASS <iframe width="-200px"> mapping to width
-PASS <iframe width="   -200"> mapping to width
-PASS <iframe width="+-200"> mapping to width
-PASS <iframe width="-+200"> mapping to width
-PASS <iframe width="-200%"> mapping to width
-PASS <iframe width="+200"> mapping to width
-PASS <iframe width="   +200in    "> mapping to width
-PASS <iframe width="   +200.25in    "> mapping to width
-PASS <iframe width="+200%"> mapping to width
-PASS <iframe width="   +200.25%    "> mapping to width
-PASS <iframe width="   +200.25%abc"> mapping to width
-PASS <iframe width="+0"> mapping to width
-PASS <iframe width="+0%"> mapping to width
-PASS <iframe width="."> mapping to width
-PASS <iframe width=".%"> mapping to width
-PASS <iframe width=".x"> mapping to width
-PASS <iframe width=".5"> mapping to width
-PASS <iframe width=".5%"> mapping to width
-PASS <iframe height="200"> mapping to height
-PASS <iframe height="1007"> mapping to height
-PASS <iframe height="   00523   "> mapping to height
-PASS <iframe height="200.25"> mapping to height
-PASS <iframe height="200.7"> mapping to height
-PASS <iframe height="200."> mapping to height
-PASS <iframe height="200in"> mapping to height
-PASS <iframe height="200.25in"> mapping to height
-PASS <iframe height="200 %"> mapping to height
-PASS <iframe height="200 abc"> mapping to height
-PASS <iframe height="200%"> mapping to height
-PASS <iframe height="200%abc"> mapping to height
-PASS <iframe height="200.25%"> mapping to height
-PASS <iframe height="200.%"> mapping to height
-PASS <iframe height="20.25e2"> mapping to height
-PASS <iframe height="20.25E2"> mapping to height
-PASS <iframe height="0"> mapping to height
-PASS <iframe height="0%"> mapping to height
-PASS <iframe height="0px"> mapping to height
-PASS <iframe height="-0"> mapping to height
-PASS <iframe height="-0%"> mapping to height
-PASS <iframe height="-200"> mapping to height
-PASS <iframe height="-200px"> mapping to height
-PASS <iframe height="   -200"> mapping to height
-PASS <iframe height="+-200"> mapping to height
-PASS <iframe height="-+200"> mapping to height
-PASS <iframe height="-200%"> mapping to height
-PASS <iframe height="+200"> mapping to height
-PASS <iframe height="   +200in    "> mapping to height
-PASS <iframe height="   +200.25in    "> mapping to height
-PASS <iframe height="+200%"> mapping to height
-PASS <iframe height="   +200.25%    "> mapping to height
-PASS <iframe height="   +200.25%abc"> mapping to height
-PASS <iframe height="+0"> mapping to height
-PASS <iframe height="+0%"> mapping to height
-PASS <iframe height="."> mapping to height
-PASS <iframe height=".%"> mapping to height
-PASS <iframe height=".x"> mapping to height
-PASS <iframe height=".5"> mapping to height
-PASS <iframe height=".5%"> mapping to height
-PASS <input width="200"> mapping to width
-PASS <input width="1007"> mapping to width
-PASS <input width="   00523   "> mapping to width
-PASS <input width="200.25"> mapping to width
-PASS <input width="200.7"> mapping to width
-PASS <input width="200."> mapping to width
-PASS <input width="200in"> mapping to width
-PASS <input width="200.25in"> mapping to width
-PASS <input width="200 %"> mapping to width
-PASS <input width="200 abc"> mapping to width
-PASS <input width="200%"> mapping to width
-PASS <input width="200%abc"> mapping to width
-PASS <input width="200.25%"> mapping to width
-PASS <input width="200.%"> mapping to width
-PASS <input width="20.25e2"> mapping to width
-PASS <input width="20.25E2"> mapping to width
-PASS <input width="0"> mapping to width
-PASS <input width="0%"> mapping to width
-PASS <input width="0px"> mapping to width
-PASS <input width="-0"> mapping to width
-PASS <input width="-0%"> mapping to width
-PASS <input width="-200"> mapping to width
-PASS <input width="-200px"> mapping to width
-PASS <input width="   -200"> mapping to width
-PASS <input width="+-200"> mapping to width
-PASS <input width="-+200"> mapping to width
-PASS <input width="-200%"> mapping to width
-PASS <input width="+200"> mapping to width
-PASS <input width="   +200in    "> mapping to width
-PASS <input width="   +200.25in    "> mapping to width
-PASS <input width="+200%"> mapping to width
-PASS <input width="   +200.25%    "> mapping to width
-PASS <input width="   +200.25%abc"> mapping to width
-PASS <input width="+0"> mapping to width
-PASS <input width="+0%"> mapping to width
-PASS <input width="."> mapping to width
-PASS <input width=".%"> mapping to width
-PASS <input width=".x"> mapping to width
-PASS <input width=".5"> mapping to width
-PASS <input width=".5%"> mapping to width
-PASS <input height="200"> mapping to height
-PASS <input height="1007"> mapping to height
-PASS <input height="   00523   "> mapping to height
-PASS <input height="200.25"> mapping to height
-PASS <input height="200.7"> mapping to height
-PASS <input height="200."> mapping to height
-PASS <input height="200in"> mapping to height
-PASS <input height="200.25in"> mapping to height
-PASS <input height="200 %"> mapping to height
-PASS <input height="200 abc"> mapping to height
-PASS <input height="200%"> mapping to height
-PASS <input height="200%abc"> mapping to height
-PASS <input height="200.25%"> mapping to height
-PASS <input height="200.%"> mapping to height
-PASS <input height="20.25e2"> mapping to height
-PASS <input height="20.25E2"> mapping to height
-PASS <input height="0"> mapping to height
-PASS <input height="0%"> mapping to height
-PASS <input height="0px"> mapping to height
-PASS <input height="-0"> mapping to height
-PASS <input height="-0%"> mapping to height
-PASS <input height="-200"> mapping to height
-PASS <input height="-200px"> mapping to height
-PASS <input height="   -200"> mapping to height
-PASS <input height="+-200"> mapping to height
-PASS <input height="-+200"> mapping to height
-PASS <input height="-200%"> mapping to height
-PASS <input height="+200"> mapping to height
-PASS <input height="   +200in    "> mapping to height
-PASS <input height="   +200.25in    "> mapping to height
-PASS <input height="+200%"> mapping to height
-PASS <input height="   +200.25%    "> mapping to height
-PASS <input height="   +200.25%abc"> mapping to height
-PASS <input height="+0"> mapping to height
-PASS <input height="+0%"> mapping to height
-PASS <input height="."> mapping to height
-PASS <input height=".%"> mapping to height
-PASS <input height=".x"> mapping to height
-PASS <input height=".5"> mapping to height
-PASS <input height=".5%"> mapping to height
-PASS <marquee width="200"> mapping to width
-PASS <marquee width="1007"> mapping to width
-PASS <marquee width="   00523   "> mapping to width
-PASS <marquee width="200.25"> mapping to width
-PASS <marquee width="200.7"> mapping to width
-PASS <marquee width="200."> mapping to width
-PASS <marquee width="200in"> mapping to width
-PASS <marquee width="200.25in"> mapping to width
-PASS <marquee width="200 %"> mapping to width
-PASS <marquee width="200 abc"> mapping to width
-PASS <marquee width="200%"> mapping to width
-PASS <marquee width="200%abc"> mapping to width
-PASS <marquee width="200.25%"> mapping to width
-PASS <marquee width="200.%"> mapping to width
-PASS <marquee width="20.25e2"> mapping to width
-PASS <marquee width="20.25E2"> mapping to width
-PASS <marquee width="0"> mapping to width
-PASS <marquee width="0%"> mapping to width
-PASS <marquee width="0px"> mapping to width
-PASS <marquee width="-0"> mapping to width
-PASS <marquee width="-0%"> mapping to width
-PASS <marquee width="-200"> mapping to width
-PASS <marquee width="-200px"> mapping to width
-PASS <marquee width="   -200"> mapping to width
-PASS <marquee width="+-200"> mapping to width
-PASS <marquee width="-+200"> mapping to width
-PASS <marquee width="-200%"> mapping to width
-PASS <marquee width="+200"> mapping to width
-PASS <marquee width="   +200in    "> mapping to width
-PASS <marquee width="   +200.25in    "> mapping to width
-PASS <marquee width="+200%"> mapping to width
-PASS <marquee width="   +200.25%    "> mapping to width
-PASS <marquee width="   +200.25%abc"> mapping to width
-PASS <marquee width="+0"> mapping to width
-PASS <marquee width="+0%"> mapping to width
-PASS <marquee width="."> mapping to width
-PASS <marquee width=".%"> mapping to width
-PASS <marquee width=".x"> mapping to width
-PASS <marquee width=".5"> mapping to width
-PASS <marquee width=".5%"> mapping to width
-PASS <marquee height="200"> mapping to height
-PASS <marquee height="1007"> mapping to height
-PASS <marquee height="   00523   "> mapping to height
-PASS <marquee height="200.25"> mapping to height
-PASS <marquee height="200.7"> mapping to height
-PASS <marquee height="200."> mapping to height
-PASS <marquee height="200in"> mapping to height
-PASS <marquee height="200.25in"> mapping to height
-PASS <marquee height="200 %"> mapping to height
-PASS <marquee height="200 abc"> mapping to height
-PASS <marquee height="200%"> mapping to height
-PASS <marquee height="200%abc"> mapping to height
-PASS <marquee height="200.25%"> mapping to height
-PASS <marquee height="200.%"> mapping to height
-PASS <marquee height="20.25e2"> mapping to height
-PASS <marquee height="20.25E2"> mapping to height
-PASS <marquee height="0"> mapping to height
-PASS <marquee height="0%"> mapping to height
-PASS <marquee height="0px"> mapping to height
-PASS <marquee height="-0"> mapping to height
-PASS <marquee height="-0%"> mapping to height
-PASS <marquee height="-200"> mapping to height
-PASS <marquee height="-200px"> mapping to height
-PASS <marquee height="   -200"> mapping to height
-PASS <marquee height="+-200"> mapping to height
-PASS <marquee height="-+200"> mapping to height
-PASS <marquee height="-200%"> mapping to height
-PASS <marquee height="+200"> mapping to height
-PASS <marquee height="   +200in    "> mapping to height
-PASS <marquee height="   +200.25in    "> mapping to height
-PASS <marquee height="+200%"> mapping to height
-PASS <marquee height="   +200.25%    "> mapping to height
-PASS <marquee height="   +200.25%abc"> mapping to height
-PASS <marquee height="+0"> mapping to height
-PASS <marquee height="+0%"> mapping to height
-PASS <marquee height="."> mapping to height
-PASS <marquee height=".%"> mapping to height
-PASS <marquee height=".x"> mapping to height
-PASS <marquee height=".5"> mapping to height
-PASS <marquee height=".5%"> mapping to height
-PASS <video width="200"> mapping to width
-PASS <video width="1007"> mapping to width
-PASS <video width="   00523   "> mapping to width
-PASS <video width="200.25"> mapping to width
-PASS <video width="200.7"> mapping to width
-PASS <video width="200."> mapping to width
-PASS <video width="200in"> mapping to width
-PASS <video width="200.25in"> mapping to width
-PASS <video width="200 %"> mapping to width
-PASS <video width="200 abc"> mapping to width
-PASS <video width="200%"> mapping to width
-PASS <video width="200%abc"> mapping to width
-PASS <video width="200.25%"> mapping to width
-PASS <video width="200.%"> mapping to width
-PASS <video width="20.25e2"> mapping to width
-PASS <video width="20.25E2"> mapping to width
-PASS <video width="0"> mapping to width
-PASS <video width="0%"> mapping to width
-PASS <video width="0px"> mapping to width
-PASS <video width="-0"> mapping to width
-PASS <video width="-0%"> mapping to width
-PASS <video width="-200"> mapping to width
-PASS <video width="-200px"> mapping to width
-PASS <video width="   -200"> mapping to width
-PASS <video width="+-200"> mapping to width
-PASS <video width="-+200"> mapping to width
-PASS <video width="-200%"> mapping to width
-PASS <video width="+200"> mapping to width
-PASS <video width="   +200in    "> mapping to width
-PASS <video width="   +200.25in    "> mapping to width
-PASS <video width="+200%"> mapping to width
-PASS <video width="   +200.25%    "> mapping to width
-PASS <video width="   +200.25%abc"> mapping to width
-PASS <video width="+0"> mapping to width
-PASS <video width="+0%"> mapping to width
-PASS <video width="."> mapping to width
-PASS <video width=".%"> mapping to width
-PASS <video width=".x"> mapping to width
-PASS <video width=".5"> mapping to width
-PASS <video width=".5%"> mapping to width
-PASS <video height="200"> mapping to height
-PASS <video height="1007"> mapping to height
-PASS <video height="   00523   "> mapping to height
-PASS <video height="200.25"> mapping to height
-PASS <video height="200.7"> mapping to height
-PASS <video height="200."> mapping to height
-PASS <video height="200in"> mapping to height
-PASS <video height="200.25in"> mapping to height
-PASS <video height="200 %"> mapping to height
-PASS <video height="200 abc"> mapping to height
-PASS <video height="200%"> mapping to height
-PASS <video height="200%abc"> mapping to height
-PASS <video height="200.25%"> mapping to height
-PASS <video height="200.%"> mapping to height
-PASS <video height="20.25e2"> mapping to height
-PASS <video height="20.25E2"> mapping to height
-PASS <video height="0"> mapping to height
-PASS <video height="0%"> mapping to height
-PASS <video height="0px"> mapping to height
-PASS <video height="-0"> mapping to height
-PASS <video height="-0%"> mapping to height
-PASS <video height="-200"> mapping to height
-PASS <video height="-200px"> mapping to height
-PASS <video height="   -200"> mapping to height
-PASS <video height="+-200"> mapping to height
-PASS <video height="-+200"> mapping to height
-PASS <video height="-200%"> mapping to height
-PASS <video height="+200"> mapping to height
-PASS <video height="   +200in    "> mapping to height
-PASS <video height="   +200.25in    "> mapping to height
-PASS <video height="+200%"> mapping to height
-PASS <video height="   +200.25%    "> mapping to height
-PASS <video height="   +200.25%abc"> mapping to height
-PASS <video height="+0"> mapping to height
-PASS <video height="+0%"> mapping to height
-PASS <video height="."> mapping to height
-PASS <video height=".%"> mapping to height
-PASS <video height=".x"> mapping to height
-PASS <video height=".5"> mapping to height
-PASS <video height=".5%"> mapping to height
-PASS <object width="200"> mapping to width
-PASS <object width="1007"> mapping to width
-PASS <object width="   00523   "> mapping to width
-PASS <object width="200.25"> mapping to width
-PASS <object width="200.7"> mapping to width
-PASS <object width="200."> mapping to width
-PASS <object width="200in"> mapping to width
-PASS <object width="200.25in"> mapping to width
-PASS <object width="200 %"> mapping to width
-PASS <object width="200 abc"> mapping to width
-PASS <object width="200%"> mapping to width
-PASS <object width="200%abc"> mapping to width
-PASS <object width="200.25%"> mapping to width
-PASS <object width="200.%"> mapping to width
-PASS <object width="20.25e2"> mapping to width
-PASS <object width="20.25E2"> mapping to width
-PASS <object width="0"> mapping to width
-PASS <object width="0%"> mapping to width
-PASS <object width="0px"> mapping to width
-PASS <object width="-0"> mapping to width
-PASS <object width="-0%"> mapping to width
-PASS <object width="-200"> mapping to width
-PASS <object width="-200px"> mapping to width
-PASS <object width="   -200"> mapping to width
-PASS <object width="+-200"> mapping to width
-PASS <object width="-+200"> mapping to width
-PASS <object width="-200%"> mapping to width
-PASS <object width="+200"> mapping to width
-PASS <object width="   +200in    "> mapping to width
-PASS <object width="   +200.25in    "> mapping to width
-PASS <object width="+200%"> mapping to width
-PASS <object width="   +200.25%    "> mapping to width
-PASS <object width="   +200.25%abc"> mapping to width
-PASS <object width="+0"> mapping to width
-PASS <object width="+0%"> mapping to width
-PASS <object width="."> mapping to width
-PASS <object width=".%"> mapping to width
-PASS <object width=".x"> mapping to width
-PASS <object width=".5"> mapping to width
-PASS <object width=".5%"> mapping to width
-PASS <object height="200"> mapping to height
-PASS <object height="1007"> mapping to height
-PASS <object height="   00523   "> mapping to height
-PASS <object height="200.25"> mapping to height
-PASS <object height="200.7"> mapping to height
-PASS <object height="200."> mapping to height
-PASS <object height="200in"> mapping to height
-PASS <object height="200.25in"> mapping to height
-PASS <object height="200 %"> mapping to height
-PASS <object height="200 abc"> mapping to height
-PASS <object height="200%"> mapping to height
-PASS <object height="200%abc"> mapping to height
-PASS <object height="200.25%"> mapping to height
-PASS <object height="200.%"> mapping to height
-PASS <object height="20.25e2"> mapping to height
-PASS <object height="20.25E2"> mapping to height
-PASS <object height="0"> mapping to height
-PASS <object height="0%"> mapping to height
-PASS <object height="0px"> mapping to height
-PASS <object height="-0"> mapping to height
-PASS <object height="-0%"> mapping to height
-PASS <object height="-200"> mapping to height
-PASS <object height="-200px"> mapping to height
-PASS <object height="   -200"> mapping to height
-PASS <object height="+-200"> mapping to height
-PASS <object height="-+200"> mapping to height
-PASS <object height="-200%"> mapping to height
-PASS <object height="+200"> mapping to height
-PASS <object height="   +200in    "> mapping to height
-PASS <object height="   +200.25in    "> mapping to height
-PASS <object height="+200%"> mapping to height
-PASS <object height="   +200.25%    "> mapping to height
-PASS <object height="   +200.25%abc"> mapping to height
-PASS <object height="+0"> mapping to height
-PASS <object height="+0%"> mapping to height
-PASS <object height="."> mapping to height
-PASS <object height=".%"> mapping to height
-PASS <object height=".x"> mapping to height
-PASS <object height=".5"> mapping to height
-PASS <object height=".5%"> mapping to height
-PASS <embed width="200"> mapping to width
-PASS <embed width="1007"> mapping to width
-PASS <embed width="   00523   "> mapping to width
-PASS <embed width="200.25"> mapping to width
-PASS <embed width="200.7"> mapping to width
-PASS <embed width="200."> mapping to width
-PASS <embed width="200in"> mapping to width
-PASS <embed width="200.25in"> mapping to width
-PASS <embed width="200 %"> mapping to width
-PASS <embed width="200 abc"> mapping to width
-PASS <embed width="200%"> mapping to width
-PASS <embed width="200%abc"> mapping to width
-PASS <embed width="200.25%"> mapping to width
-PASS <embed width="200.%"> mapping to width
-PASS <embed width="20.25e2"> mapping to width
-PASS <embed width="20.25E2"> mapping to width
-PASS <embed width="0"> mapping to width
-PASS <embed width="0%"> mapping to width
-PASS <embed width="0px"> mapping to width
-PASS <embed width="-0"> mapping to width
-PASS <embed width="-0%"> mapping to width
-PASS <embed width="-200"> mapping to width
-PASS <embed width="-200px"> mapping to width
-PASS <embed width="   -200"> mapping to width
-PASS <embed width="+-200"> mapping to width
-PASS <embed width="-+200"> mapping to width
-PASS <embed width="-200%"> mapping to width
-PASS <embed width="+200"> mapping to width
-PASS <embed width="   +200in    "> mapping to width
-PASS <embed width="   +200.25in    "> mapping to width
-PASS <embed width="+200%"> mapping to width
-PASS <embed width="   +200.25%    "> mapping to width
-PASS <embed width="   +200.25%abc"> mapping to width
-PASS <embed width="+0"> mapping to width
-PASS <embed width="+0%"> mapping to width
-PASS <embed width="."> mapping to width
-PASS <embed width=".%"> mapping to width
-PASS <embed width=".x"> mapping to width
-PASS <embed width=".5"> mapping to width
-PASS <embed width=".5%"> mapping to width
-PASS <embed height="200"> mapping to height
-PASS <embed height="1007"> mapping to height
-PASS <embed height="   00523   "> mapping to height
-PASS <embed height="200.25"> mapping to height
-PASS <embed height="200.7"> mapping to height
-PASS <embed height="200."> mapping to height
-PASS <embed height="200in"> mapping to height
-PASS <embed height="200.25in"> mapping to height
-PASS <embed height="200 %"> mapping to height
-PASS <embed height="200 abc"> mapping to height
-PASS <embed height="200%"> mapping to height
-PASS <embed height="200%abc"> mapping to height
-PASS <embed height="200.25%"> mapping to height
-PASS <embed height="200.%"> mapping to height
-PASS <embed height="20.25e2"> mapping to height
-PASS <embed height="20.25E2"> mapping to height
-PASS <embed height="0"> mapping to height
-PASS <embed height="0%"> mapping to height
-PASS <embed height="0px"> mapping to height
-PASS <embed height="-0"> mapping to height
-PASS <embed height="-0%"> mapping to height
-PASS <embed height="-200"> mapping to height
-PASS <embed height="-200px"> mapping to height
-PASS <embed height="   -200"> mapping to height
-PASS <embed height="+-200"> mapping to height
-PASS <embed height="-+200"> mapping to height
-PASS <embed height="-200%"> mapping to height
-PASS <embed height="+200"> mapping to height
-PASS <embed height="   +200in    "> mapping to height
-PASS <embed height="   +200.25in    "> mapping to height
-PASS <embed height="+200%"> mapping to height
-PASS <embed height="   +200.25%    "> mapping to height
-PASS <embed height="   +200.25%abc"> mapping to height
-PASS <embed height="+0"> mapping to height
-PASS <embed height="+0%"> mapping to height
-PASS <embed height="."> mapping to height
-PASS <embed height=".%"> mapping to height
-PASS <embed height=".x"> mapping to height
-PASS <embed height=".5"> mapping to height
-PASS <embed height=".5%"> mapping to height
-PASS <img width="200"> mapping to width
-PASS <img width="1007"> mapping to width
-PASS <img width="   00523   "> mapping to width
-PASS <img width="200.25"> mapping to width
-PASS <img width="200.7"> mapping to width
-PASS <img width="200."> mapping to width
-PASS <img width="200in"> mapping to width
-PASS <img width="200.25in"> mapping to width
-PASS <img width="200 %"> mapping to width
-PASS <img width="200 abc"> mapping to width
-PASS <img width="200%"> mapping to width
-PASS <img width="200%abc"> mapping to width
-PASS <img width="200.25%"> mapping to width
-PASS <img width="200.%"> mapping to width
-PASS <img width="20.25e2"> mapping to width
-PASS <img width="20.25E2"> mapping to width
-PASS <img width="0"> mapping to width
-PASS <img width="0%"> mapping to width
-PASS <img width="0px"> mapping to width
-PASS <img width="-0"> mapping to width
-PASS <img width="-0%"> mapping to width
-PASS <img width="-200"> mapping to width
-PASS <img width="-200px"> mapping to width
-PASS <img width="   -200"> mapping to width
-PASS <img width="+-200"> mapping to width
-PASS <img width="-+200"> mapping to width
-PASS <img width="-200%"> mapping to width
-PASS <img width="+200"> mapping to width
-PASS <img width="   +200in    "> mapping to width
-PASS <img width="   +200.25in    "> mapping to width
-PASS <img width="+200%"> mapping to width
-PASS <img width="   +200.25%    "> mapping to width
-PASS <img width="   +200.25%abc"> mapping to width
-PASS <img width="+0"> mapping to width
-PASS <img width="+0%"> mapping to width
-PASS <img width="."> mapping to width
-PASS <img width=".%"> mapping to width
-PASS <img width=".x"> mapping to width
-PASS <img width=".5"> mapping to width
-PASS <img width=".5%"> mapping to width
-PASS <img height="200"> mapping to height
-PASS <img height="1007"> mapping to height
-PASS <img height="   00523   "> mapping to height
-PASS <img height="200.25"> mapping to height
-PASS <img height="200.7"> mapping to height
-PASS <img height="200."> mapping to height
-PASS <img height="200in"> mapping to height
-PASS <img height="200.25in"> mapping to height
-PASS <img height="200 %"> mapping to height
-PASS <img height="200 abc"> mapping to height
-PASS <img height="200%"> mapping to height
-PASS <img height="200%abc"> mapping to height
-PASS <img height="200.25%"> mapping to height
-PASS <img height="200.%"> mapping to height
-PASS <img height="20.25e2"> mapping to height
-PASS <img height="20.25E2"> mapping to height
-PASS <img height="0"> mapping to height
-PASS <img height="0%"> mapping to height
-PASS <img height="0px"> mapping to height
-PASS <img height="-0"> mapping to height
-PASS <img height="-0%"> mapping to height
-PASS <img height="-200"> mapping to height
-PASS <img height="-200px"> mapping to height
-PASS <img height="   -200"> mapping to height
-PASS <img height="+-200"> mapping to height
-PASS <img height="-+200"> mapping to height
-PASS <img height="-200%"> mapping to height
-PASS <img height="+200"> mapping to height
-PASS <img height="   +200in    "> mapping to height
-PASS <img height="   +200.25in    "> mapping to height
-PASS <img height="+200%"> mapping to height
-PASS <img height="   +200.25%    "> mapping to height
-PASS <img height="   +200.25%abc"> mapping to height
-PASS <img height="+0"> mapping to height
-PASS <img height="+0%"> mapping to height
-PASS <img height="."> mapping to height
-PASS <img height=".%"> mapping to height
-PASS <img height=".x"> mapping to height
-PASS <img height=".5"> mapping to height
-PASS <img height=".5%"> mapping to height
-PASS <td width="200"> mapping to width
-PASS <td width="1007"> mapping to width
-PASS <td width="   00523   "> mapping to width
-PASS <td width="200.25"> mapping to width
-PASS <td width="200.7"> mapping to width
-PASS <td width="200."> mapping to width
-PASS <td width="200in"> mapping to width
-PASS <td width="200.25in"> mapping to width
-PASS <td width="200 %"> mapping to width
-PASS <td width="200 abc"> mapping to width
-PASS <td width="200%"> mapping to width
-PASS <td width="200%abc"> mapping to width
-PASS <td width="200.25%"> mapping to width
-PASS <td width="200.%"> mapping to width
-PASS <td width="20.25e2"> mapping to width
-PASS <td width="20.25E2"> mapping to width
-PASS <td width="-0"> mapping to width
-PASS <td width="-0%"> mapping to width
-PASS <td width="-200"> mapping to width
-PASS <td width="-200px"> mapping to width
-PASS <td width="   -200"> mapping to width
-PASS <td width="+-200"> mapping to width
-PASS <td width="-+200"> mapping to width
-PASS <td width="-200%"> mapping to width
-PASS <td width="+200"> mapping to width
-PASS <td width="   +200in    "> mapping to width
-PASS <td width="   +200.25in    "> mapping to width
-PASS <td width="+200%"> mapping to width
-PASS <td width="   +200.25%    "> mapping to width
-PASS <td width="   +200.25%abc"> mapping to width
-PASS <td width="+0"> mapping to width
-PASS <td width="+0%"> mapping to width
-PASS <td width="."> mapping to width
-PASS <td width=".%"> mapping to width
-PASS <td width=".x"> mapping to width
-PASS <td width=".5"> mapping to width
-PASS <td width=".5%"> mapping to width
-PASS <td width="0"> mapping to width
-PASS <td width="0%"> mapping to width
-PASS <td width="0px"> mapping to width
-PASS <td height="200"> mapping to height
-PASS <td height="1007"> mapping to height
-PASS <td height="   00523   "> mapping to height
-PASS <td height="200.25"> mapping to height
-PASS <td height="200.7"> mapping to height
-PASS <td height="200."> mapping to height
-PASS <td height="200in"> mapping to height
-PASS <td height="200.25in"> mapping to height
-PASS <td height="200 %"> mapping to height
-PASS <td height="200 abc"> mapping to height
-PASS <td height="200%"> mapping to height
-PASS <td height="200%abc"> mapping to height
-PASS <td height="200.25%"> mapping to height
-PASS <td height="200.%"> mapping to height
-PASS <td height="20.25e2"> mapping to height
-PASS <td height="20.25E2"> mapping to height
-PASS <td height="-0"> mapping to height
-PASS <td height="-0%"> mapping to height
-PASS <td height="-200"> mapping to height
-PASS <td height="-200px"> mapping to height
-PASS <td height="   -200"> mapping to height
-PASS <td height="+-200"> mapping to height
-PASS <td height="-+200"> mapping to height
-PASS <td height="-200%"> mapping to height
-PASS <td height="+200"> mapping to height
-PASS <td height="   +200in    "> mapping to height
-PASS <td height="   +200.25in    "> mapping to height
-PASS <td height="+200%"> mapping to height
-PASS <td height="   +200.25%    "> mapping to height
-PASS <td height="   +200.25%abc"> mapping to height
-PASS <td height="+0"> mapping to height
-PASS <td height="+0%"> mapping to height
-PASS <td height="."> mapping to height
-PASS <td height=".%"> mapping to height
-PASS <td height=".x"> mapping to height
-PASS <td height=".5"> mapping to height
-PASS <td height=".5%"> mapping to height
-PASS <td height="0"> mapping to height
-PASS <td height="0%"> mapping to height
-PASS <td height="0px"> mapping to height
-PASS <table width="200"> mapping to width
-PASS <table width="1007"> mapping to width
-PASS <table width="   00523   "> mapping to width
-PASS <table width="200.25"> mapping to width
-PASS <table width="200.7"> mapping to width
-PASS <table width="200."> mapping to width
-PASS <table width="200in"> mapping to width
-PASS <table width="200.25in"> mapping to width
-PASS <table width="200 %"> mapping to width
-PASS <table width="200 abc"> mapping to width
-PASS <table width="200%"> mapping to width
-PASS <table width="200%abc"> mapping to width
-PASS <table width="200.25%"> mapping to width
-PASS <table width="200.%"> mapping to width
-PASS <table width="20.25e2"> mapping to width
-PASS <table width="20.25E2"> mapping to width
-PASS <table width="-0"> mapping to width
-PASS <table width="-0%"> mapping to width
-PASS <table width="-200"> mapping to width
-PASS <table width="-200px"> mapping to width
-PASS <table width="   -200"> mapping to width
-PASS <table width="+-200"> mapping to width
-PASS <table width="-+200"> mapping to width
-PASS <table width="-200%"> mapping to width
-PASS <table width="+200"> mapping to width
-PASS <table width="   +200in    "> mapping to width
-PASS <table width="   +200.25in    "> mapping to width
-PASS <table width="+200%"> mapping to width
-PASS <table width="   +200.25%    "> mapping to width
-PASS <table width="   +200.25%abc"> mapping to width
-PASS <table width="+0"> mapping to width
-PASS <table width="+0%"> mapping to width
-PASS <table width="."> mapping to width
-PASS <table width=".%"> mapping to width
-PASS <table width=".x"> mapping to width
-PASS <table width=".5"> mapping to width
-PASS <table width=".5%"> mapping to width
-PASS <table width="0"> mapping to width
-PASS <table width="0%"> mapping to width
-PASS <table width="0px"> mapping to width
-PASS <table height="200"> mapping to height
-PASS <table height="1007"> mapping to height
-PASS <table height="   00523   "> mapping to height
-PASS <table height="200.25"> mapping to height
-PASS <table height="200.7"> mapping to height
-PASS <table height="200."> mapping to height
-PASS <table height="200in"> mapping to height
-PASS <table height="200.25in"> mapping to height
-PASS <table height="200 %"> mapping to height
-PASS <table height="200 abc"> mapping to height
-PASS <table height="200%"> mapping to height
-PASS <table height="200%abc"> mapping to height
-PASS <table height="200.25%"> mapping to height
-PASS <table height="200.%"> mapping to height
-PASS <table height="20.25e2"> mapping to height
-PASS <table height="20.25E2"> mapping to height
-PASS <table height="-0"> mapping to height
-PASS <table height="-0%"> mapping to height
-PASS <table height="-200"> mapping to height
-PASS <table height="-200px"> mapping to height
-PASS <table height="   -200"> mapping to height
-PASS <table height="+-200"> mapping to height
-PASS <table height="-+200"> mapping to height
-PASS <table height="-200%"> mapping to height
-PASS <table height="+200"> mapping to height
-PASS <table height="   +200in    "> mapping to height
-PASS <table height="   +200.25in    "> mapping to height
-PASS <table height="+200%"> mapping to height
-PASS <table height="   +200.25%    "> mapping to height
-PASS <table height="   +200.25%abc"> mapping to height
-PASS <table height="+0"> mapping to height
-PASS <table height="+0%"> mapping to height
-PASS <table height="."> mapping to height
-PASS <table height=".%"> mapping to height
-PASS <table height=".x"> mapping to height
-PASS <table height=".5"> mapping to height
-PASS <table height=".5%"> mapping to height
-FAIL <table height="0"> mapping to height assert_equals: expected "auto" but got "0px"
-FAIL <table height="0%"> mapping to height assert_equals: expected "auto" but got "0%"
-FAIL <table height="0px"> mapping to height assert_equals: expected "auto" but got "0px"
-PASS <tr height="200"> mapping to height
-PASS <tr height="1007"> mapping to height
-PASS <tr height="   00523   "> mapping to height
-PASS <tr height="200.25"> mapping to height
-PASS <tr height="200.7"> mapping to height
-PASS <tr height="200."> mapping to height
-PASS <tr height="200in"> mapping to height
-PASS <tr height="200.25in"> mapping to height
-PASS <tr height="200 %"> mapping to height
-PASS <tr height="200 abc"> mapping to height
-PASS <tr height="200%"> mapping to height
-PASS <tr height="200%abc"> mapping to height
-PASS <tr height="200.25%"> mapping to height
-PASS <tr height="200.%"> mapping to height
-PASS <tr height="20.25e2"> mapping to height
-PASS <tr height="20.25E2"> mapping to height
-PASS <tr height="-0"> mapping to height
-PASS <tr height="-0%"> mapping to height
-PASS <tr height="-200"> mapping to height
-PASS <tr height="-200px"> mapping to height
-PASS <tr height="   -200"> mapping to height
-PASS <tr height="+-200"> mapping to height
-PASS <tr height="-+200"> mapping to height
-PASS <tr height="-200%"> mapping to height
-PASS <tr height="+200"> mapping to height
-PASS <tr height="   +200in    "> mapping to height
-PASS <tr height="   +200.25in    "> mapping to height
-PASS <tr height="+200%"> mapping to height
-PASS <tr height="   +200.25%    "> mapping to height
-PASS <tr height="   +200.25%abc"> mapping to height
-PASS <tr height="+0"> mapping to height
-PASS <tr height="+0%"> mapping to height
-PASS <tr height="."> mapping to height
-PASS <tr height=".%"> mapping to height
-PASS <tr height=".x"> mapping to height
-PASS <tr height=".5"> mapping to height
-PASS <tr height=".5%"> mapping to height
-FAIL <tr height="0"> mapping to height assert_equals: expected "auto" but got "0px"
-FAIL <tr height="0%"> mapping to height assert_equals: expected "auto" but got "0%"
-FAIL <tr height="0px"> mapping to height assert_equals: expected "auto" but got "0px"
-PASS <col width="200"> mapping to width
-PASS <col width="1007"> mapping to width
-PASS <col width="   00523   "> mapping to width
-PASS <col width="200.25"> mapping to width
-PASS <col width="200.7"> mapping to width
-PASS <col width="200."> mapping to width
-PASS <col width="200in"> mapping to width
-PASS <col width="200.25in"> mapping to width
-PASS <col width="200 %"> mapping to width
-PASS <col width="200 abc"> mapping to width
-PASS <col width="200%"> mapping to width
-PASS <col width="200%abc"> mapping to width
-PASS <col width="200.25%"> mapping to width
-PASS <col width="200.%"> mapping to width
-PASS <col width="20.25e2"> mapping to width
-PASS <col width="20.25E2"> mapping to width
-PASS <col width="-0"> mapping to width
-PASS <col width="-0%"> mapping to width
-PASS <col width="-200"> mapping to width
-PASS <col width="-200px"> mapping to width
-PASS <col width="   -200"> mapping to width
-PASS <col width="+-200"> mapping to width
-PASS <col width="-+200"> mapping to width
-PASS <col width="-200%"> mapping to width
-PASS <col width="+200"> mapping to width
-PASS <col width="   +200in    "> mapping to width
-PASS <col width="   +200.25in    "> mapping to width
-PASS <col width="+200%"> mapping to width
-PASS <col width="   +200.25%    "> mapping to width
-PASS <col width="   +200.25%abc"> mapping to width
-PASS <col width="+0"> mapping to width
-PASS <col width="+0%"> mapping to width
-PASS <col width="."> mapping to width
-PASS <col width=".%"> mapping to width
-PASS <col width=".x"> mapping to width
-PASS <col width=".5"> mapping to width
-PASS <col width=".5%"> mapping to width
-FAIL <col width="0"> mapping to width assert_equals: expected "auto" but got "0px"
-FAIL <col width="0%"> mapping to width assert_equals: expected "auto" but got "0%"
-FAIL <col width="0px"> mapping to width assert_equals: expected "auto" but got "0px"
-PASS <embed hspace="200"> mapping to marginLeft
-PASS <embed hspace="1007"> mapping to marginLeft
-PASS <embed hspace="   00523   "> mapping to marginLeft
-PASS <embed hspace="200.25"> mapping to marginLeft
-PASS <embed hspace="200.7"> mapping to marginLeft
-PASS <embed hspace="200."> mapping to marginLeft
-PASS <embed hspace="200in"> mapping to marginLeft
-PASS <embed hspace="200.25in"> mapping to marginLeft
-PASS <embed hspace="200 %"> mapping to marginLeft
-PASS <embed hspace="200 abc"> mapping to marginLeft
-PASS <embed hspace="200%"> mapping to marginLeft
-PASS <embed hspace="200%abc"> mapping to marginLeft
-PASS <embed hspace="200.25%"> mapping to marginLeft
-PASS <embed hspace="200.%"> mapping to marginLeft
-PASS <embed hspace="20.25e2"> mapping to marginLeft
-PASS <embed hspace="20.25E2"> mapping to marginLeft
-PASS <embed hspace="0"> mapping to marginLeft
-PASS <embed hspace="0%"> mapping to marginLeft
-PASS <embed hspace="0px"> mapping to marginLeft
-PASS <embed hspace="-0"> mapping to marginLeft
-PASS <embed hspace="-0%"> mapping to marginLeft
-PASS <embed hspace="-200"> mapping to marginLeft
-PASS <embed hspace="-200px"> mapping to marginLeft
-PASS <embed hspace="   -200"> mapping to marginLeft
-PASS <embed hspace="+-200"> mapping to marginLeft
-PASS <embed hspace="-+200"> mapping to marginLeft
-PASS <embed hspace="-200%"> mapping to marginLeft
-PASS <embed hspace="+200"> mapping to marginLeft
-PASS <embed hspace="   +200in    "> mapping to marginLeft
-PASS <embed hspace="   +200.25in    "> mapping to marginLeft
-PASS <embed hspace="+200%"> mapping to marginLeft
-PASS <embed hspace="   +200.25%    "> mapping to marginLeft
-PASS <embed hspace="   +200.25%abc"> mapping to marginLeft
-PASS <embed hspace="+0"> mapping to marginLeft
-PASS <embed hspace="+0%"> mapping to marginLeft
-PASS <embed hspace="."> mapping to marginLeft
-PASS <embed hspace=".%"> mapping to marginLeft
-PASS <embed hspace=".x"> mapping to marginLeft
-PASS <embed hspace=".5"> mapping to marginLeft
-PASS <embed hspace=".5%"> mapping to marginLeft
-PASS <embed hspace="200"> mapping to marginRight
-PASS <embed hspace="1007"> mapping to marginRight
-PASS <embed hspace="   00523   "> mapping to marginRight
-PASS <embed hspace="200.25"> mapping to marginRight
-PASS <embed hspace="200.7"> mapping to marginRight
-PASS <embed hspace="200."> mapping to marginRight
-PASS <embed hspace="200in"> mapping to marginRight
-PASS <embed hspace="200.25in"> mapping to marginRight
-PASS <embed hspace="200 %"> mapping to marginRight
-PASS <embed hspace="200 abc"> mapping to marginRight
-PASS <embed hspace="200%"> mapping to marginRight
-PASS <embed hspace="200%abc"> mapping to marginRight
-PASS <embed hspace="200.25%"> mapping to marginRight
-PASS <embed hspace="200.%"> mapping to marginRight
-PASS <embed hspace="20.25e2"> mapping to marginRight
-PASS <embed hspace="20.25E2"> mapping to marginRight
-PASS <embed hspace="0"> mapping to marginRight
-PASS <embed hspace="0%"> mapping to marginRight
-PASS <embed hspace="0px"> mapping to marginRight
-PASS <embed hspace="-0"> mapping to marginRight
-PASS <embed hspace="-0%"> mapping to marginRight
-PASS <embed hspace="-200"> mapping to marginRight
-PASS <embed hspace="-200px"> mapping to marginRight
-PASS <embed hspace="   -200"> mapping to marginRight
-PASS <embed hspace="+-200"> mapping to marginRight
-PASS <embed hspace="-+200"> mapping to marginRight
-PASS <embed hspace="-200%"> mapping to marginRight
-PASS <embed hspace="+200"> mapping to marginRight
-PASS <embed hspace="   +200in    "> mapping to marginRight
-PASS <embed hspace="   +200.25in    "> mapping to marginRight
-PASS <embed hspace="+200%"> mapping to marginRight
-PASS <embed hspace="   +200.25%    "> mapping to marginRight
-PASS <embed hspace="   +200.25%abc"> mapping to marginRight
-PASS <embed hspace="+0"> mapping to marginRight
-PASS <embed hspace="+0%"> mapping to marginRight
-PASS <embed hspace="."> mapping to marginRight
-PASS <embed hspace=".%"> mapping to marginRight
-PASS <embed hspace=".x"> mapping to marginRight
-PASS <embed hspace=".5"> mapping to marginRight
-PASS <embed hspace=".5%"> mapping to marginRight
-PASS <embed vspace="200"> mapping to marginTop
-PASS <embed vspace="1007"> mapping to marginTop
-PASS <embed vspace="   00523   "> mapping to marginTop
-PASS <embed vspace="200.25"> mapping to marginTop
-PASS <embed vspace="200.7"> mapping to marginTop
-PASS <embed vspace="200."> mapping to marginTop
-PASS <embed vspace="200in"> mapping to marginTop
-PASS <embed vspace="200.25in"> mapping to marginTop
-PASS <embed vspace="200 %"> mapping to marginTop
-PASS <embed vspace="200 abc"> mapping to marginTop
-PASS <embed vspace="200%"> mapping to marginTop
-PASS <embed vspace="200%abc"> mapping to marginTop
-PASS <embed vspace="200.25%"> mapping to marginTop
-PASS <embed vspace="200.%"> mapping to marginTop
-PASS <embed vspace="20.25e2"> mapping to marginTop
-PASS <embed vspace="20.25E2"> mapping to marginTop
-PASS <embed vspace="0"> mapping to marginTop
-PASS <embed vspace="0%"> mapping to marginTop
-PASS <embed vspace="0px"> mapping to marginTop
-PASS <embed vspace="-0"> mapping to marginTop
-PASS <embed vspace="-0%"> mapping to marginTop
-PASS <embed vspace="-200"> mapping to marginTop
-PASS <embed vspace="-200px"> mapping to marginTop
-PASS <embed vspace="   -200"> mapping to marginTop
-PASS <embed vspace="+-200"> mapping to marginTop
-PASS <embed vspace="-+200"> mapping to marginTop
-PASS <embed vspace="-200%"> mapping to marginTop
-PASS <embed vspace="+200"> mapping to marginTop
-PASS <embed vspace="   +200in    "> mapping to marginTop
-PASS <embed vspace="   +200.25in    "> mapping to marginTop
-PASS <embed vspace="+200%"> mapping to marginTop
-PASS <embed vspace="   +200.25%    "> mapping to marginTop
-PASS <embed vspace="   +200.25%abc"> mapping to marginTop
-PASS <embed vspace="+0"> mapping to marginTop
-PASS <embed vspace="+0%"> mapping to marginTop
-PASS <embed vspace="."> mapping to marginTop
-PASS <embed vspace=".%"> mapping to marginTop
-PASS <embed vspace=".x"> mapping to marginTop
-PASS <embed vspace=".5"> mapping to marginTop
-PASS <embed vspace=".5%"> mapping to marginTop
-PASS <embed vspace="200"> mapping to marginBottom
-PASS <embed vspace="1007"> mapping to marginBottom
-PASS <embed vspace="   00523   "> mapping to marginBottom
-PASS <embed vspace="200.25"> mapping to marginBottom
-PASS <embed vspace="200.7"> mapping to marginBottom
-PASS <embed vspace="200."> mapping to marginBottom
-PASS <embed vspace="200in"> mapping to marginBottom
-PASS <embed vspace="200.25in"> mapping to marginBottom
-PASS <embed vspace="200 %"> mapping to marginBottom
-PASS <embed vspace="200 abc"> mapping to marginBottom
-PASS <embed vspace="200%"> mapping to marginBottom
-PASS <embed vspace="200%abc"> mapping to marginBottom
-PASS <embed vspace="200.25%"> mapping to marginBottom
-PASS <embed vspace="200.%"> mapping to marginBottom
-PASS <embed vspace="20.25e2"> mapping to marginBottom
-PASS <embed vspace="20.25E2"> mapping to marginBottom
-PASS <embed vspace="0"> mapping to marginBottom
-PASS <embed vspace="0%"> mapping to marginBottom
-PASS <embed vspace="0px"> mapping to marginBottom
-PASS <embed vspace="-0"> mapping to marginBottom
-PASS <embed vspace="-0%"> mapping to marginBottom
-PASS <embed vspace="-200"> mapping to marginBottom
-PASS <embed vspace="-200px"> mapping to marginBottom
-PASS <embed vspace="   -200"> mapping to marginBottom
-PASS <embed vspace="+-200"> mapping to marginBottom
-PASS <embed vspace="-+200"> mapping to marginBottom
-PASS <embed vspace="-200%"> mapping to marginBottom
-PASS <embed vspace="+200"> mapping to marginBottom
-PASS <embed vspace="   +200in    "> mapping to marginBottom
-PASS <embed vspace="   +200.25in    "> mapping to marginBottom
-PASS <embed vspace="+200%"> mapping to marginBottom
-PASS <embed vspace="   +200.25%    "> mapping to marginBottom
-PASS <embed vspace="   +200.25%abc"> mapping to marginBottom
-PASS <embed vspace="+0"> mapping to marginBottom
-PASS <embed vspace="+0%"> mapping to marginBottom
-PASS <embed vspace="."> mapping to marginBottom
-PASS <embed vspace=".%"> mapping to marginBottom
-PASS <embed vspace=".x"> mapping to marginBottom
-PASS <embed vspace=".5"> mapping to marginBottom
-PASS <embed vspace=".5%"> mapping to marginBottom
-PASS <img hspace="200"> mapping to marginLeft
-PASS <img hspace="1007"> mapping to marginLeft
-PASS <img hspace="   00523   "> mapping to marginLeft
-PASS <img hspace="200.25"> mapping to marginLeft
-PASS <img hspace="200.7"> mapping to marginLeft
-PASS <img hspace="200."> mapping to marginLeft
-PASS <img hspace="200in"> mapping to marginLeft
-PASS <img hspace="200.25in"> mapping to marginLeft
-PASS <img hspace="200 %"> mapping to marginLeft
-PASS <img hspace="200 abc"> mapping to marginLeft
-PASS <img hspace="200%"> mapping to marginLeft
-PASS <img hspace="200%abc"> mapping to marginLeft
-PASS <img hspace="200.25%"> mapping to marginLeft
-PASS <img hspace="200.%"> mapping to marginLeft
-PASS <img hspace="20.25e2"> mapping to marginLeft
-PASS <img hspace="20.25E2"> mapping to marginLeft
-PASS <img hspace="0"> mapping to marginLeft
-PASS <img hspace="0%"> mapping to marginLeft
-PASS <img hspace="0px"> mapping to marginLeft
-PASS <img hspace="-0"> mapping to marginLeft
-PASS <img hspace="-0%"> mapping to marginLeft
-PASS <img hspace="-200"> mapping to marginLeft
-PASS <img hspace="-200px"> mapping to marginLeft
-PASS <img hspace="   -200"> mapping to marginLeft
-PASS <img hspace="+-200"> mapping to marginLeft
-PASS <img hspace="-+200"> mapping to marginLeft
-PASS <img hspace="-200%"> mapping to marginLeft
-PASS <img hspace="+200"> mapping to marginLeft
-PASS <img hspace="   +200in    "> mapping to marginLeft
-PASS <img hspace="   +200.25in    "> mapping to marginLeft
-PASS <img hspace="+200%"> mapping to marginLeft
-PASS <img hspace="   +200.25%    "> mapping to marginLeft
-PASS <img hspace="   +200.25%abc"> mapping to marginLeft
-PASS <img hspace="+0"> mapping to marginLeft
-PASS <img hspace="+0%"> mapping to marginLeft
-PASS <img hspace="."> mapping to marginLeft
-PASS <img hspace=".%"> mapping to marginLeft
-PASS <img hspace=".x"> mapping to marginLeft
-PASS <img hspace=".5"> mapping to marginLeft
-PASS <img hspace=".5%"> mapping to marginLeft
-PASS <img hspace="200"> mapping to marginRight
-PASS <img hspace="1007"> mapping to marginRight
-PASS <img hspace="   00523   "> mapping to marginRight
-PASS <img hspace="200.25"> mapping to marginRight
-PASS <img hspace="200.7"> mapping to marginRight
-PASS <img hspace="200."> mapping to marginRight
-PASS <img hspace="200in"> mapping to marginRight
-PASS <img hspace="200.25in"> mapping to marginRight
-PASS <img hspace="200 %"> mapping to marginRight
-PASS <img hspace="200 abc"> mapping to marginRight
-PASS <img hspace="200%"> mapping to marginRight
-PASS <img hspace="200%abc"> mapping to marginRight
-PASS <img hspace="200.25%"> mapping to marginRight
-PASS <img hspace="200.%"> mapping to marginRight
-PASS <img hspace="20.25e2"> mapping to marginRight
-PASS <img hspace="20.25E2"> mapping to marginRight
-PASS <img hspace="0"> mapping to marginRight
-PASS <img hspace="0%"> mapping to marginRight
-PASS <img hspace="0px"> mapping to marginRight
-PASS <img hspace="-0"> mapping to marginRight
-PASS <img hspace="-0%"> mapping to marginRight
-PASS <img hspace="-200"> mapping to marginRight
-PASS <img hspace="-200px"> mapping to marginRight
-PASS <img hspace="   -200"> mapping to marginRight
-PASS <img hspace="+-200"> mapping to marginRight
-PASS <img hspace="-+200"> mapping to marginRight
-PASS <img hspace="-200%"> mapping to marginRight
-PASS <img hspace="+200"> mapping to marginRight
-PASS <img hspace="   +200in    "> mapping to marginRight
-PASS <img hspace="   +200.25in    "> mapping to marginRight
-PASS <img hspace="+200%"> mapping to marginRight
-PASS <img hspace="   +200.25%    "> mapping to marginRight
-PASS <img hspace="   +200.25%abc"> mapping to marginRight
-PASS <img hspace="+0"> mapping to marginRight
-PASS <img hspace="+0%"> mapping to marginRight
-PASS <img hspace="."> mapping to marginRight
-PASS <img hspace=".%"> mapping to marginRight
-PASS <img hspace=".x"> mapping to marginRight
-PASS <img hspace=".5"> mapping to marginRight
-PASS <img hspace=".5%"> mapping to marginRight
-PASS <img vspace="200"> mapping to marginTop
-PASS <img vspace="1007"> mapping to marginTop
-PASS <img vspace="   00523   "> mapping to marginTop
-PASS <img vspace="200.25"> mapping to marginTop
-PASS <img vspace="200.7"> mapping to marginTop
-PASS <img vspace="200."> mapping to marginTop
-PASS <img vspace="200in"> mapping to marginTop
-PASS <img vspace="200.25in"> mapping to marginTop
-PASS <img vspace="200 %"> mapping to marginTop
-PASS <img vspace="200 abc"> mapping to marginTop
-PASS <img vspace="200%"> mapping to marginTop
-PASS <img vspace="200%abc"> mapping to marginTop
-PASS <img vspace="200.25%"> mapping to marginTop
-PASS <img vspace="200.%"> mapping to marginTop
-PASS <img vspace="20.25e2"> mapping to marginTop
-PASS <img vspace="20.25E2"> mapping to marginTop
-PASS <img vspace="0"> mapping to marginTop
-PASS <img vspace="0%"> mapping to marginTop
-PASS <img vspace="0px"> mapping to marginTop
-PASS <img vspace="-0"> mapping to marginTop
-PASS <img vspace="-0%"> mapping to marginTop
-PASS <img vspace="-200"> mapping to marginTop
-PASS <img vspace="-200px"> mapping to marginTop
-PASS <img vspace="   -200"> mapping to marginTop
-PASS <img vspace="+-200"> mapping to marginTop
-PASS <img vspace="-+200"> mapping to marginTop
-PASS <img vspace="-200%"> mapping to marginTop
-PASS <img vspace="+200"> mapping to marginTop
-PASS <img vspace="   +200in    "> mapping to marginTop
-PASS <img vspace="   +200.25in    "> mapping to marginTop
-PASS <img vspace="+200%"> mapping to marginTop
-PASS <img vspace="   +200.25%    "> mapping to marginTop
-PASS <img vspace="   +200.25%abc"> mapping to marginTop
-PASS <img vspace="+0"> mapping to marginTop
-PASS <img vspace="+0%"> mapping to marginTop
-PASS <img vspace="."> mapping to marginTop
-PASS <img vspace=".%"> mapping to marginTop
-PASS <img vspace=".x"> mapping to marginTop
-PASS <img vspace=".5"> mapping to marginTop
-PASS <img vspace=".5%"> mapping to marginTop
-PASS <img vspace="200"> mapping to marginBottom
-PASS <img vspace="1007"> mapping to marginBottom
-PASS <img vspace="   00523   "> mapping to marginBottom
-PASS <img vspace="200.25"> mapping to marginBottom
-PASS <img vspace="200.7"> mapping to marginBottom
-PASS <img vspace="200."> mapping to marginBottom
-PASS <img vspace="200in"> mapping to marginBottom
-PASS <img vspace="200.25in"> mapping to marginBottom
-PASS <img vspace="200 %"> mapping to marginBottom
-PASS <img vspace="200 abc"> mapping to marginBottom
-PASS <img vspace="200%"> mapping to marginBottom
-PASS <img vspace="200%abc"> mapping to marginBottom
-PASS <img vspace="200.25%"> mapping to marginBottom
-PASS <img vspace="200.%"> mapping to marginBottom
-PASS <img vspace="20.25e2"> mapping to marginBottom
-PASS <img vspace="20.25E2"> mapping to marginBottom
-PASS <img vspace="0"> mapping to marginBottom
-PASS <img vspace="0%"> mapping to marginBottom
-PASS <img vspace="0px"> mapping to marginBottom
-PASS <img vspace="-0"> mapping to marginBottom
-PASS <img vspace="-0%"> mapping to marginBottom
-PASS <img vspace="-200"> mapping to marginBottom
-PASS <img vspace="-200px"> mapping to marginBottom
-PASS <img vspace="   -200"> mapping to marginBottom
-PASS <img vspace="+-200"> mapping to marginBottom
-PASS <img vspace="-+200"> mapping to marginBottom
-PASS <img vspace="-200%"> mapping to marginBottom
-PASS <img vspace="+200"> mapping to marginBottom
-PASS <img vspace="   +200in    "> mapping to marginBottom
-PASS <img vspace="   +200.25in    "> mapping to marginBottom
-PASS <img vspace="+200%"> mapping to marginBottom
-PASS <img vspace="   +200.25%    "> mapping to marginBottom
-PASS <img vspace="   +200.25%abc"> mapping to marginBottom
-PASS <img vspace="+0"> mapping to marginBottom
-PASS <img vspace="+0%"> mapping to marginBottom
-PASS <img vspace="."> mapping to marginBottom
-PASS <img vspace=".%"> mapping to marginBottom
-PASS <img vspace=".x"> mapping to marginBottom
-PASS <img vspace=".5"> mapping to marginBottom
-PASS <img vspace=".5%"> mapping to marginBottom
-PASS <object hspace="200"> mapping to marginLeft
-PASS <object hspace="1007"> mapping to marginLeft
-PASS <object hspace="   00523   "> mapping to marginLeft
-PASS <object hspace="200.25"> mapping to marginLeft
-PASS <object hspace="200.7"> mapping to marginLeft
-PASS <object hspace="200."> mapping to marginLeft
-PASS <object hspace="200in"> mapping to marginLeft
-PASS <object hspace="200.25in"> mapping to marginLeft
-PASS <object hspace="200 %"> mapping to marginLeft
-PASS <object hspace="200 abc"> mapping to marginLeft
-PASS <object hspace="200%"> mapping to marginLeft
-PASS <object hspace="200%abc"> mapping to marginLeft
-PASS <object hspace="200.25%"> mapping to marginLeft
-PASS <object hspace="200.%"> mapping to marginLeft
-PASS <object hspace="20.25e2"> mapping to marginLeft
-PASS <object hspace="20.25E2"> mapping to marginLeft
-PASS <object hspace="0"> mapping to marginLeft
-PASS <object hspace="0%"> mapping to marginLeft
-PASS <object hspace="0px"> mapping to marginLeft
-PASS <object hspace="-0"> mapping to marginLeft
-PASS <object hspace="-0%"> mapping to marginLeft
-PASS <object hspace="-200"> mapping to marginLeft
-PASS <object hspace="-200px"> mapping to marginLeft
-PASS <object hspace="   -200"> mapping to marginLeft
-PASS <object hspace="+-200"> mapping to marginLeft
-PASS <object hspace="-+200"> mapping to marginLeft
-PASS <object hspace="-200%"> mapping to marginLeft
-PASS <object hspace="+200"> mapping to marginLeft
-PASS <object hspace="   +200in    "> mapping to marginLeft
-PASS <object hspace="   +200.25in    "> mapping to marginLeft
-PASS <object hspace="+200%"> mapping to marginLeft
-PASS <object hspace="   +200.25%    "> mapping to marginLeft
-PASS <object hspace="   +200.25%abc"> mapping to marginLeft
-PASS <object hspace="+0"> mapping to marginLeft
-PASS <object hspace="+0%"> mapping to marginLeft
-PASS <object hspace="."> mapping to marginLeft
-PASS <object hspace=".%"> mapping to marginLeft
-PASS <object hspace=".x"> mapping to marginLeft
-PASS <object hspace=".5"> mapping to marginLeft
-PASS <object hspace=".5%"> mapping to marginLeft
-PASS <object hspace="200"> mapping to marginRight
-PASS <object hspace="1007"> mapping to marginRight
-PASS <object hspace="   00523   "> mapping to marginRight
-PASS <object hspace="200.25"> mapping to marginRight
-PASS <object hspace="200.7"> mapping to marginRight
-PASS <object hspace="200."> mapping to marginRight
-PASS <object hspace="200in"> mapping to marginRight
-PASS <object hspace="200.25in"> mapping to marginRight
-PASS <object hspace="200 %"> mapping to marginRight
-PASS <object hspace="200 abc"> mapping to marginRight
-PASS <object hspace="200%"> mapping to marginRight
-PASS <object hspace="200%abc"> mapping to marginRight
-PASS <object hspace="200.25%"> mapping to marginRight
-PASS <object hspace="200.%"> mapping to marginRight
-PASS <object hspace="20.25e2"> mapping to marginRight
-PASS <object hspace="20.25E2"> mapping to marginRight
-PASS <object hspace="0"> mapping to marginRight
-PASS <object hspace="0%"> mapping to marginRight
-PASS <object hspace="0px"> mapping to marginRight
-PASS <object hspace="-0"> mapping to marginRight
-PASS <object hspace="-0%"> mapping to marginRight
-PASS <object hspace="-200"> mapping to marginRight
-PASS <object hspace="-200px"> mapping to marginRight
-PASS <object hspace="   -200"> mapping to marginRight
-PASS <object hspace="+-200"> mapping to marginRight
-PASS <object hspace="-+200"> mapping to marginRight
-PASS <object hspace="-200%"> mapping to marginRight
-PASS <object hspace="+200"> mapping to marginRight
-PASS <object hspace="   +200in    "> mapping to marginRight
-PASS <object hspace="   +200.25in    "> mapping to marginRight
-PASS <object hspace="+200%"> mapping to marginRight
-PASS <object hspace="   +200.25%    "> mapping to marginRight
-PASS <object hspace="   +200.25%abc"> mapping to marginRight
-PASS <object hspace="+0"> mapping to marginRight
-PASS <object hspace="+0%"> mapping to marginRight
-PASS <object hspace="."> mapping to marginRight
-PASS <object hspace=".%"> mapping to marginRight
-PASS <object hspace=".x"> mapping to marginRight
-PASS <object hspace=".5"> mapping to marginRight
-PASS <object hspace=".5%"> mapping to marginRight
-PASS <object vspace="200"> mapping to marginTop
-PASS <object vspace="1007"> mapping to marginTop
-PASS <object vspace="   00523   "> mapping to marginTop
-PASS <object vspace="200.25"> mapping to marginTop
-PASS <object vspace="200.7"> mapping to marginTop
-PASS <object vspace="200."> mapping to marginTop
-PASS <object vspace="200in"> mapping to marginTop
-PASS <object vspace="200.25in"> mapping to marginTop
-PASS <object vspace="200 %"> mapping to marginTop
-PASS <object vspace="200 abc"> mapping to marginTop
-PASS <object vspace="200%"> mapping to marginTop
-PASS <object vspace="200%abc"> mapping to marginTop
-PASS <object vspace="200.25%"> mapping to marginTop
-PASS <object vspace="200.%"> mapping to marginTop
-PASS <object vspace="20.25e2"> mapping to marginTop
-PASS <object vspace="20.25E2"> mapping to marginTop
-PASS <object vspace="0"> mapping to marginTop
-PASS <object vspace="0%"> mapping to marginTop
-PASS <object vspace="0px"> mapping to marginTop
-PASS <object vspace="-0"> mapping to marginTop
-PASS <object vspace="-0%"> mapping to marginTop
-PASS <object vspace="-200"> mapping to marginTop
-PASS <object vspace="-200px"> mapping to marginTop
-PASS <object vspace="   -200"> mapping to marginTop
-PASS <object vspace="+-200"> mapping to marginTop
-PASS <object vspace="-+200"> mapping to marginTop
-PASS <object vspace="-200%"> mapping to marginTop
-PASS <object vspace="+200"> mapping to marginTop
-PASS <object vspace="   +200in    "> mapping to marginTop
-PASS <object vspace="   +200.25in    "> mapping to marginTop
-PASS <object vspace="+200%"> mapping to marginTop
-PASS <object vspace="   +200.25%    "> mapping to marginTop
-PASS <object vspace="   +200.25%abc"> mapping to marginTop
-PASS <object vspace="+0"> mapping to marginTop
-PASS <object vspace="+0%"> mapping to marginTop
-PASS <object vspace="."> mapping to marginTop
-PASS <object vspace=".%"> mapping to marginTop
-PASS <object vspace=".x"> mapping to marginTop
-PASS <object vspace=".5"> mapping to marginTop
-PASS <object vspace=".5%"> mapping to marginTop
-PASS <object vspace="200"> mapping to marginBottom
-PASS <object vspace="1007"> mapping to marginBottom
-PASS <object vspace="   00523   "> mapping to marginBottom
-PASS <object vspace="200.25"> mapping to marginBottom
-PASS <object vspace="200.7"> mapping to marginBottom
-PASS <object vspace="200."> mapping to marginBottom
-PASS <object vspace="200in"> mapping to marginBottom
-PASS <object vspace="200.25in"> mapping to marginBottom
-PASS <object vspace="200 %"> mapping to marginBottom
-PASS <object vspace="200 abc"> mapping to marginBottom
-PASS <object vspace="200%"> mapping to marginBottom
-PASS <object vspace="200%abc"> mapping to marginBottom
-PASS <object vspace="200.25%"> mapping to marginBottom
-PASS <object vspace="200.%"> mapping to marginBottom
-PASS <object vspace="20.25e2"> mapping to marginBottom
-PASS <object vspace="20.25E2"> mapping to marginBottom
-PASS <object vspace="0"> mapping to marginBottom
-PASS <object vspace="0%"> mapping to marginBottom
-PASS <object vspace="0px"> mapping to marginBottom
-PASS <object vspace="-0"> mapping to marginBottom
-PASS <object vspace="-0%"> mapping to marginBottom
-PASS <object vspace="-200"> mapping to marginBottom
-PASS <object vspace="-200px"> mapping to marginBottom
-PASS <object vspace="   -200"> mapping to marginBottom
-PASS <object vspace="+-200"> mapping to marginBottom
-PASS <object vspace="-+200"> mapping to marginBottom
-PASS <object vspace="-200%"> mapping to marginBottom
-PASS <object vspace="+200"> mapping to marginBottom
-PASS <object vspace="   +200in    "> mapping to marginBottom
-PASS <object vspace="   +200.25in    "> mapping to marginBottom
-PASS <object vspace="+200%"> mapping to marginBottom
-PASS <object vspace="   +200.25%    "> mapping to marginBottom
-PASS <object vspace="   +200.25%abc"> mapping to marginBottom
-PASS <object vspace="+0"> mapping to marginBottom
-PASS <object vspace="+0%"> mapping to marginBottom
-PASS <object vspace="."> mapping to marginBottom
-PASS <object vspace=".%"> mapping to marginBottom
-PASS <object vspace=".x"> mapping to marginBottom
-PASS <object vspace=".5"> mapping to marginBottom
-PASS <object vspace=".5%"> mapping to marginBottom
-PASS <input hspace="200"> mapping to marginLeft
-PASS <input hspace="1007"> mapping to marginLeft
-PASS <input hspace="   00523   "> mapping to marginLeft
-PASS <input hspace="200.25"> mapping to marginLeft
-PASS <input hspace="200.7"> mapping to marginLeft
-PASS <input hspace="200."> mapping to marginLeft
-PASS <input hspace="200in"> mapping to marginLeft
-PASS <input hspace="200.25in"> mapping to marginLeft
-PASS <input hspace="200 %"> mapping to marginLeft
-PASS <input hspace="200 abc"> mapping to marginLeft
-PASS <input hspace="200%"> mapping to marginLeft
-PASS <input hspace="200%abc"> mapping to marginLeft
-PASS <input hspace="200.25%"> mapping to marginLeft
-PASS <input hspace="200.%"> mapping to marginLeft
-PASS <input hspace="20.25e2"> mapping to marginLeft
-PASS <input hspace="20.25E2"> mapping to marginLeft
-PASS <input hspace="0"> mapping to marginLeft
-PASS <input hspace="0%"> mapping to marginLeft
-PASS <input hspace="0px"> mapping to marginLeft
-PASS <input hspace="-0"> mapping to marginLeft
-PASS <input hspace="-0%"> mapping to marginLeft
-PASS <input hspace="-200"> mapping to marginLeft
-PASS <input hspace="-200px"> mapping to marginLeft
-PASS <input hspace="   -200"> mapping to marginLeft
-PASS <input hspace="+-200"> mapping to marginLeft
-PASS <input hspace="-+200"> mapping to marginLeft
-PASS <input hspace="-200%"> mapping to marginLeft
-PASS <input hspace="+200"> mapping to marginLeft
-PASS <input hspace="   +200in    "> mapping to marginLeft
-PASS <input hspace="   +200.25in    "> mapping to marginLeft
-PASS <input hspace="+200%"> mapping to marginLeft
-PASS <input hspace="   +200.25%    "> mapping to marginLeft
-PASS <input hspace="   +200.25%abc"> mapping to marginLeft
-PASS <input hspace="+0"> mapping to marginLeft
-PASS <input hspace="+0%"> mapping to marginLeft
-PASS <input hspace="."> mapping to marginLeft
-PASS <input hspace=".%"> mapping to marginLeft
-PASS <input hspace=".x"> mapping to marginLeft
-PASS <input hspace=".5"> mapping to marginLeft
-PASS <input hspace=".5%"> mapping to marginLeft
-PASS <input hspace="200"> mapping to marginRight
-PASS <input hspace="1007"> mapping to marginRight
-PASS <input hspace="   00523   "> mapping to marginRight
-PASS <input hspace="200.25"> mapping to marginRight
-PASS <input hspace="200.7"> mapping to marginRight
-PASS <input hspace="200."> mapping to marginRight
-PASS <input hspace="200in"> mapping to marginRight
-PASS <input hspace="200.25in"> mapping to marginRight
-PASS <input hspace="200 %"> mapping to marginRight
-PASS <input hspace="200 abc"> mapping to marginRight
-PASS <input hspace="200%"> mapping to marginRight
-PASS <input hspace="200%abc"> mapping to marginRight
-PASS <input hspace="200.25%"> mapping to marginRight
-PASS <input hspace="200.%"> mapping to marginRight
-PASS <input hspace="20.25e2"> mapping to marginRight
-PASS <input hspace="20.25E2"> mapping to marginRight
-PASS <input hspace="0"> mapping to marginRight
-PASS <input hspace="0%"> mapping to marginRight
-PASS <input hspace="0px"> mapping to marginRight
-PASS <input hspace="-0"> mapping to marginRight
-PASS <input hspace="-0%"> mapping to marginRight
-PASS <input hspace="-200"> mapping to marginRight
-PASS <input hspace="-200px"> mapping to marginRight
-PASS <input hspace="   -200"> mapping to marginRight
-PASS <input hspace="+-200"> mapping to marginRight
-PASS <input hspace="-+200"> mapping to marginRight
-PASS <input hspace="-200%"> mapping to marginRight
-PASS <input hspace="+200"> mapping to marginRight
-PASS <input hspace="   +200in    "> mapping to marginRight
-PASS <input hspace="   +200.25in    "> mapping to marginRight
-PASS <input hspace="+200%"> mapping to marginRight
-PASS <input hspace="   +200.25%    "> mapping to marginRight
-PASS <input hspace="   +200.25%abc"> mapping to marginRight
-PASS <input hspace="+0"> mapping to marginRight
-PASS <input hspace="+0%"> mapping to marginRight
-PASS <input hspace="."> mapping to marginRight
-PASS <input hspace=".%"> mapping to marginRight
-PASS <input hspace=".x"> mapping to marginRight
-PASS <input hspace=".5"> mapping to marginRight
-PASS <input hspace=".5%"> mapping to marginRight
-PASS <input vspace="200"> mapping to marginTop
-PASS <input vspace="1007"> mapping to marginTop
-PASS <input vspace="   00523   "> mapping to marginTop
-PASS <input vspace="200.25"> mapping to marginTop
-PASS <input vspace="200.7"> mapping to marginTop
-PASS <input vspace="200."> mapping to marginTop
-PASS <input vspace="200in"> mapping to marginTop
-PASS <input vspace="200.25in"> mapping to marginTop
-PASS <input vspace="200 %"> mapping to marginTop
-PASS <input vspace="200 abc"> mapping to marginTop
-PASS <input vspace="200%"> mapping to marginTop
-PASS <input vspace="200%abc"> mapping to marginTop
-PASS <input vspace="200.25%"> mapping to marginTop
-PASS <input vspace="200.%"> mapping to marginTop
-PASS <input vspace="20.25e2"> mapping to marginTop
-PASS <input vspace="20.25E2"> mapping to marginTop
-PASS <input vspace="0"> mapping to marginTop
-PASS <input vspace="0%"> mapping to marginTop
-PASS <input vspace="0px"> mapping to marginTop
-PASS <input vspace="-0"> mapping to marginTop
-PASS <input vspace="-0%"> mapping to marginTop
-PASS <input vspace="-200"> mapping to marginTop
-PASS <input vspace="-200px"> mapping to marginTop
-PASS <input vspace="   -200"> mapping to marginTop
-PASS <input vspace="+-200"> mapping to marginTop
-PASS <input vspace="-+200"> mapping to marginTop
-PASS <input vspace="-200%"> mapping to marginTop
-PASS <input vspace="+200"> mapping to marginTop
-PASS <input vspace="   +200in    "> mapping to marginTop
-PASS <input vspace="   +200.25in    "> mapping to marginTop
-PASS <input vspace="+200%"> mapping to marginTop
-PASS <input vspace="   +200.25%    "> mapping to marginTop
-PASS <input vspace="   +200.25%abc"> mapping to marginTop
-PASS <input vspace="+0"> mapping to marginTop
-PASS <input vspace="+0%"> mapping to marginTop
-PASS <input vspace="."> mapping to marginTop
-PASS <input vspace=".%"> mapping to marginTop
-PASS <input vspace=".x"> mapping to marginTop
-PASS <input vspace=".5"> mapping to marginTop
-PASS <input vspace=".5%"> mapping to marginTop
-PASS <input vspace="200"> mapping to marginBottom
-PASS <input vspace="1007"> mapping to marginBottom
-PASS <input vspace="   00523   "> mapping to marginBottom
-PASS <input vspace="200.25"> mapping to marginBottom
-PASS <input vspace="200.7"> mapping to marginBottom
-PASS <input vspace="200."> mapping to marginBottom
-PASS <input vspace="200in"> mapping to marginBottom
-PASS <input vspace="200.25in"> mapping to marginBottom
-PASS <input vspace="200 %"> mapping to marginBottom
-PASS <input vspace="200 abc"> mapping to marginBottom
-PASS <input vspace="200%"> mapping to marginBottom
-PASS <input vspace="200%abc"> mapping to marginBottom
-PASS <input vspace="200.25%"> mapping to marginBottom
-PASS <input vspace="200.%"> mapping to marginBottom
-PASS <input vspace="20.25e2"> mapping to marginBottom
-PASS <input vspace="20.25E2"> mapping to marginBottom
-PASS <input vspace="0"> mapping to marginBottom
-PASS <input vspace="0%"> mapping to marginBottom
-PASS <input vspace="0px"> mapping to marginBottom
-PASS <input vspace="-0"> mapping to marginBottom
-PASS <input vspace="-0%"> mapping to marginBottom
-PASS <input vspace="-200"> mapping to marginBottom
-PASS <input vspace="-200px"> mapping to marginBottom
-PASS <input vspace="   -200"> mapping to marginBottom
-PASS <input vspace="+-200"> mapping to marginBottom
-PASS <input vspace="-+200"> mapping to marginBottom
-PASS <input vspace="-200%"> mapping to marginBottom
-PASS <input vspace="+200"> mapping to marginBottom
-PASS <input vspace="   +200in    "> mapping to marginBottom
-PASS <input vspace="   +200.25in    "> mapping to marginBottom
-PASS <input vspace="+200%"> mapping to marginBottom
-PASS <input vspace="   +200.25%    "> mapping to marginBottom
-PASS <input vspace="   +200.25%abc"> mapping to marginBottom
-PASS <input vspace="+0"> mapping to marginBottom
-PASS <input vspace="+0%"> mapping to marginBottom
-PASS <input vspace="."> mapping to marginBottom
-PASS <input vspace=".%"> mapping to marginBottom
-PASS <input vspace=".x"> mapping to marginBottom
-PASS <input vspace=".5"> mapping to marginBottom
-PASS <input vspace=".5%"> mapping to marginBottom
-PASS <marquee hspace="200"> mapping to marginLeft
-PASS <marquee hspace="1007"> mapping to marginLeft
-PASS <marquee hspace="   00523   "> mapping to marginLeft
-PASS <marquee hspace="200.25"> mapping to marginLeft
-PASS <marquee hspace="200.7"> mapping to marginLeft
-PASS <marquee hspace="200."> mapping to marginLeft
-PASS <marquee hspace="200in"> mapping to marginLeft
-PASS <marquee hspace="200.25in"> mapping to marginLeft
-PASS <marquee hspace="200 %"> mapping to marginLeft
-PASS <marquee hspace="200 abc"> mapping to marginLeft
-PASS <marquee hspace="200%"> mapping to marginLeft
-PASS <marquee hspace="200%abc"> mapping to marginLeft
-PASS <marquee hspace="200.25%"> mapping to marginLeft
-PASS <marquee hspace="200.%"> mapping to marginLeft
-PASS <marquee hspace="20.25e2"> mapping to marginLeft
-PASS <marquee hspace="20.25E2"> mapping to marginLeft
-PASS <marquee hspace="0"> mapping to marginLeft
-PASS <marquee hspace="0%"> mapping to marginLeft
-PASS <marquee hspace="0px"> mapping to marginLeft
-PASS <marquee hspace="-0"> mapping to marginLeft
-PASS <marquee hspace="-0%"> mapping to marginLeft
-PASS <marquee hspace="-200"> mapping to marginLeft
-PASS <marquee hspace="-200px"> mapping to marginLeft
-PASS <marquee hspace="   -200"> mapping to marginLeft
-PASS <marquee hspace="+-200"> mapping to marginLeft
-PASS <marquee hspace="-+200"> mapping to marginLeft
-PASS <marquee hspace="-200%"> mapping to marginLeft
-PASS <marquee hspace="+200"> mapping to marginLeft
-PASS <marquee hspace="   +200in    "> mapping to marginLeft
-PASS <marquee hspace="   +200.25in    "> mapping to marginLeft
-PASS <marquee hspace="+200%"> mapping to marginLeft
-PASS <marquee hspace="   +200.25%    "> mapping to marginLeft
-PASS <marquee hspace="   +200.25%abc"> mapping to marginLeft
-PASS <marquee hspace="+0"> mapping to marginLeft
-PASS <marquee hspace="+0%"> mapping to marginLeft
-PASS <marquee hspace="."> mapping to marginLeft
-PASS <marquee hspace=".%"> mapping to marginLeft
-PASS <marquee hspace=".x"> mapping to marginLeft
-PASS <marquee hspace=".5"> mapping to marginLeft
-PASS <marquee hspace=".5%"> mapping to marginLeft
-PASS <marquee hspace="200"> mapping to marginRight
-PASS <marquee hspace="1007"> mapping to marginRight
-PASS <marquee hspace="   00523   "> mapping to marginRight
-PASS <marquee hspace="200.25"> mapping to marginRight
-PASS <marquee hspace="200.7"> mapping to marginRight
-PASS <marquee hspace="200."> mapping to marginRight
-PASS <marquee hspace="200in"> mapping to marginRight
-PASS <marquee hspace="200.25in"> mapping to marginRight
-PASS <marquee hspace="200 %"> mapping to marginRight
-PASS <marquee hspace="200 abc"> mapping to marginRight
-PASS <marquee hspace="200%"> mapping to marginRight
-PASS <marquee hspace="200%abc"> mapping to marginRight
-PASS <marquee hspace="200.25%"> mapping to marginRight
-PASS <marquee hspace="200.%"> mapping to marginRight
-PASS <marquee hspace="20.25e2"> mapping to marginRight
-PASS <marquee hspace="20.25E2"> mapping to marginRight
-PASS <marquee hspace="0"> mapping to marginRight
-PASS <marquee hspace="0%"> mapping to marginRight
-PASS <marquee hspace="0px"> mapping to marginRight
-PASS <marquee hspace="-0"> mapping to marginRight
-PASS <marquee hspace="-0%"> mapping to marginRight
-PASS <marquee hspace="-200"> mapping to marginRight
-PASS <marquee hspace="-200px"> mapping to marginRight
-PASS <marquee hspace="   -200"> mapping to marginRight
-PASS <marquee hspace="+-200"> mapping to marginRight
-PASS <marquee hspace="-+200"> mapping to marginRight
-PASS <marquee hspace="-200%"> mapping to marginRight
-PASS <marquee hspace="+200"> mapping to marginRight
-PASS <marquee hspace="   +200in    "> mapping to marginRight
-PASS <marquee hspace="   +200.25in    "> mapping to marginRight
-PASS <marquee hspace="+200%"> mapping to marginRight
-PASS <marquee hspace="   +200.25%    "> mapping to marginRight
-PASS <marquee hspace="   +200.25%abc"> mapping to marginRight
-PASS <marquee hspace="+0"> mapping to marginRight
-PASS <marquee hspace="+0%"> mapping to marginRight
-PASS <marquee hspace="."> mapping to marginRight
-PASS <marquee hspace=".%"> mapping to marginRight
-PASS <marquee hspace=".x"> mapping to marginRight
-PASS <marquee hspace=".5"> mapping to marginRight
-PASS <marquee hspace=".5%"> mapping to marginRight
-PASS <marquee vspace="200"> mapping to marginTop
-PASS <marquee vspace="1007"> mapping to marginTop
-PASS <marquee vspace="   00523   "> mapping to marginTop
-PASS <marquee vspace="200.25"> mapping to marginTop
-PASS <marquee vspace="200.7"> mapping to marginTop
-PASS <marquee vspace="200."> mapping to marginTop
-PASS <marquee vspace="200in"> mapping to marginTop
-PASS <marquee vspace="200.25in"> mapping to marginTop
-PASS <marquee vspace="200 %"> mapping to marginTop
-PASS <marquee vspace="200 abc"> mapping to marginTop
-PASS <marquee vspace="200%"> mapping to marginTop
-PASS <marquee vspace="200%abc"> mapping to marginTop
-PASS <marquee vspace="200.25%"> mapping to marginTop
-PASS <marquee vspace="200.%"> mapping to marginTop
-PASS <marquee vspace="20.25e2"> mapping to marginTop
-PASS <marquee vspace="20.25E2"> mapping to marginTop
-PASS <marquee vspace="0"> mapping to marginTop
-PASS <marquee vspace="0%"> mapping to marginTop
-PASS <marquee vspace="0px"> mapping to marginTop
-PASS <marquee vspace="-0"> mapping to marginTop
-PASS <marquee vspace="-0%"> mapping to marginTop
-PASS <marquee vspace="-200"> mapping to marginTop
-PASS <marquee vspace="-200px"> mapping to marginTop
-PASS <marquee vspace="   -200"> mapping to marginTop
-PASS <marquee vspace="+-200"> mapping to marginTop
-PASS <marquee vspace="-+200"> mapping to marginTop
-PASS <marquee vspace="-200%"> mapping to marginTop
-PASS <marquee vspace="+200"> mapping to marginTop
-PASS <marquee vspace="   +200in    "> mapping to marginTop
-PASS <marquee vspace="   +200.25in    "> mapping to marginTop
-PASS <marquee vspace="+200%"> mapping to marginTop
-PASS <marquee vspace="   +200.25%    "> mapping to marginTop
-PASS <marquee vspace="   +200.25%abc"> mapping to marginTop
-PASS <marquee vspace="+0"> mapping to marginTop
-PASS <marquee vspace="+0%"> mapping to marginTop
-PASS <marquee vspace="."> mapping to marginTop
-PASS <marquee vspace=".%"> mapping to marginTop
-PASS <marquee vspace=".x"> mapping to marginTop
-PASS <marquee vspace=".5"> mapping to marginTop
-PASS <marquee vspace=".5%"> mapping to marginTop
-PASS <marquee vspace="200"> mapping to marginBottom
-PASS <marquee vspace="1007"> mapping to marginBottom
-PASS <marquee vspace="   00523   "> mapping to marginBottom
-PASS <marquee vspace="200.25"> mapping to marginBottom
-PASS <marquee vspace="200.7"> mapping to marginBottom
-PASS <marquee vspace="200."> mapping to marginBottom
-PASS <marquee vspace="200in"> mapping to marginBottom
-PASS <marquee vspace="200.25in"> mapping to marginBottom
-PASS <marquee vspace="200 %"> mapping to marginBottom
-PASS <marquee vspace="200 abc"> mapping to marginBottom
-PASS <marquee vspace="200%"> mapping to marginBottom
-PASS <marquee vspace="200%abc"> mapping to marginBottom
-PASS <marquee vspace="200.25%"> mapping to marginBottom
-PASS <marquee vspace="200.%"> mapping to marginBottom
-PASS <marquee vspace="20.25e2"> mapping to marginBottom
-PASS <marquee vspace="20.25E2"> mapping to marginBottom
-PASS <marquee vspace="0"> mapping to marginBottom
-PASS <marquee vspace="0%"> mapping to marginBottom
-PASS <marquee vspace="0px"> mapping to marginBottom
-PASS <marquee vspace="-0"> mapping to marginBottom
-PASS <marquee vspace="-0%"> mapping to marginBottom
-PASS <marquee vspace="-200"> mapping to marginBottom
-PASS <marquee vspace="-200px"> mapping to marginBottom
-PASS <marquee vspace="   -200"> mapping to marginBottom
-PASS <marquee vspace="+-200"> mapping to marginBottom
-PASS <marquee vspace="-+200"> mapping to marginBottom
-PASS <marquee vspace="-200%"> mapping to marginBottom
-PASS <marquee vspace="+200"> mapping to marginBottom
-PASS <marquee vspace="   +200in    "> mapping to marginBottom
-PASS <marquee vspace="   +200.25in    "> mapping to marginBottom
-PASS <marquee vspace="+200%"> mapping to marginBottom
-PASS <marquee vspace="   +200.25%    "> mapping to marginBottom
-PASS <marquee vspace="   +200.25%abc"> mapping to marginBottom
-PASS <marquee vspace="+0"> mapping to marginBottom
-PASS <marquee vspace="+0%"> mapping to marginBottom
-PASS <marquee vspace="."> mapping to marginBottom
-PASS <marquee vspace=".%"> mapping to marginBottom
-PASS <marquee vspace=".x"> mapping to marginBottom
-PASS <marquee vspace=".5"> mapping to marginBottom
-PASS <marquee vspace=".5%"> mapping to marginBottom
+Found 1720 tests; 1704 PASS, 16 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS <hr width="200"> mapping to <hr> width property
+PASS <hr width="1007"> mapping to <hr> width property
+PASS <hr width="   00523   "> mapping to <hr> width property
+PASS <hr width="200.25"> mapping to <hr> width property
+PASS <hr width="200.7"> mapping to <hr> width property
+PASS <hr width="200."> mapping to <hr> width property
+PASS <hr width="200in"> mapping to <hr> width property
+PASS <hr width="200.25in"> mapping to <hr> width property
+PASS <hr width="200 %"> mapping to <hr> width property
+PASS <hr width="200 abc"> mapping to <hr> width property
+PASS <hr width="200%"> mapping to <hr> width property
+PASS <hr width="200%abc"> mapping to <hr> width property
+PASS <hr width="200.25%"> mapping to <hr> width property
+PASS <hr width="200.%"> mapping to <hr> width property
+PASS <hr width="20.25e2"> mapping to <hr> width property
+PASS <hr width="20.25E2"> mapping to <hr> width property
+FAIL <hr width="0"> mapping to <hr> width property assert_equals: expected "0px" but got "1px"
+FAIL <hr width="0%"> mapping to <hr> width property assert_equals: expected "0%" but got "1px"
+FAIL <hr width="0px"> mapping to <hr> width property assert_equals: expected "0px" but got "1px"
+FAIL <hr width="-0"> mapping to <hr> width property assert_equals: expected "auto" but got "1px"
+FAIL <hr width="-0%"> mapping to <hr> width property assert_equals: expected "auto" but got "1px"
+PASS <hr width="-200"> mapping to <hr> width property
+PASS <hr width="-200px"> mapping to <hr> width property
+PASS <hr width="   -200"> mapping to <hr> width property
+PASS <hr width="+-200"> mapping to <hr> width property
+PASS <hr width="-+200"> mapping to <hr> width property
+PASS <hr width="-200%"> mapping to <hr> width property
+PASS <hr width="+200"> mapping to <hr> width property
+PASS <hr width="   +200in    "> mapping to <hr> width property
+PASS <hr width="   +200.25in    "> mapping to <hr> width property
+PASS <hr width="+200%"> mapping to <hr> width property
+PASS <hr width="   +200.25%    "> mapping to <hr> width property
+PASS <hr width="   +200.25%abc"> mapping to <hr> width property
+FAIL <hr width="+0"> mapping to <hr> width property assert_equals: expected "auto" but got "1px"
+FAIL <hr width="+0%"> mapping to <hr> width property assert_equals: expected "auto" but got "1px"
+PASS <hr width="."> mapping to <hr> width property
+PASS <hr width=".%"> mapping to <hr> width property
+PASS <hr width=".x"> mapping to <hr> width property
+PASS <hr width=".5"> mapping to <hr> width property
+PASS <hr width=".5%"> mapping to <hr> width property
+PASS <iframe width="200"> mapping to <iframe> width property
+PASS <iframe width="1007"> mapping to <iframe> width property
+PASS <iframe width="   00523   "> mapping to <iframe> width property
+PASS <iframe width="200.25"> mapping to <iframe> width property
+PASS <iframe width="200.7"> mapping to <iframe> width property
+PASS <iframe width="200."> mapping to <iframe> width property
+PASS <iframe width="200in"> mapping to <iframe> width property
+PASS <iframe width="200.25in"> mapping to <iframe> width property
+PASS <iframe width="200 %"> mapping to <iframe> width property
+PASS <iframe width="200 abc"> mapping to <iframe> width property
+PASS <iframe width="200%"> mapping to <iframe> width property
+PASS <iframe width="200%abc"> mapping to <iframe> width property
+PASS <iframe width="200.25%"> mapping to <iframe> width property
+PASS <iframe width="200.%"> mapping to <iframe> width property
+PASS <iframe width="20.25e2"> mapping to <iframe> width property
+PASS <iframe width="20.25E2"> mapping to <iframe> width property
+PASS <iframe width="0"> mapping to <iframe> width property
+PASS <iframe width="0%"> mapping to <iframe> width property
+PASS <iframe width="0px"> mapping to <iframe> width property
+PASS <iframe width="-0"> mapping to <iframe> width property
+PASS <iframe width="-0%"> mapping to <iframe> width property
+PASS <iframe width="-200"> mapping to <iframe> width property
+PASS <iframe width="-200px"> mapping to <iframe> width property
+PASS <iframe width="   -200"> mapping to <iframe> width property
+PASS <iframe width="+-200"> mapping to <iframe> width property
+PASS <iframe width="-+200"> mapping to <iframe> width property
+PASS <iframe width="-200%"> mapping to <iframe> width property
+PASS <iframe width="+200"> mapping to <iframe> width property
+PASS <iframe width="   +200in    "> mapping to <iframe> width property
+PASS <iframe width="   +200.25in    "> mapping to <iframe> width property
+PASS <iframe width="+200%"> mapping to <iframe> width property
+PASS <iframe width="   +200.25%    "> mapping to <iframe> width property
+PASS <iframe width="   +200.25%abc"> mapping to <iframe> width property
+PASS <iframe width="+0"> mapping to <iframe> width property
+PASS <iframe width="+0%"> mapping to <iframe> width property
+PASS <iframe width="."> mapping to <iframe> width property
+PASS <iframe width=".%"> mapping to <iframe> width property
+PASS <iframe width=".x"> mapping to <iframe> width property
+PASS <iframe width=".5"> mapping to <iframe> width property
+PASS <iframe width=".5%"> mapping to <iframe> width property
+PASS <iframe height="200"> mapping to <iframe> height property
+PASS <iframe height="1007"> mapping to <iframe> height property
+PASS <iframe height="   00523   "> mapping to <iframe> height property
+PASS <iframe height="200.25"> mapping to <iframe> height property
+PASS <iframe height="200.7"> mapping to <iframe> height property
+PASS <iframe height="200."> mapping to <iframe> height property
+PASS <iframe height="200in"> mapping to <iframe> height property
+PASS <iframe height="200.25in"> mapping to <iframe> height property
+PASS <iframe height="200 %"> mapping to <iframe> height property
+PASS <iframe height="200 abc"> mapping to <iframe> height property
+PASS <iframe height="200%"> mapping to <iframe> height property
+PASS <iframe height="200%abc"> mapping to <iframe> height property
+PASS <iframe height="200.25%"> mapping to <iframe> height property
+PASS <iframe height="200.%"> mapping to <iframe> height property
+PASS <iframe height="20.25e2"> mapping to <iframe> height property
+PASS <iframe height="20.25E2"> mapping to <iframe> height property
+PASS <iframe height="0"> mapping to <iframe> height property
+PASS <iframe height="0%"> mapping to <iframe> height property
+PASS <iframe height="0px"> mapping to <iframe> height property
+PASS <iframe height="-0"> mapping to <iframe> height property
+PASS <iframe height="-0%"> mapping to <iframe> height property
+PASS <iframe height="-200"> mapping to <iframe> height property
+PASS <iframe height="-200px"> mapping to <iframe> height property
+PASS <iframe height="   -200"> mapping to <iframe> height property
+PASS <iframe height="+-200"> mapping to <iframe> height property
+PASS <iframe height="-+200"> mapping to <iframe> height property
+PASS <iframe height="-200%"> mapping to <iframe> height property
+PASS <iframe height="+200"> mapping to <iframe> height property
+PASS <iframe height="   +200in    "> mapping to <iframe> height property
+PASS <iframe height="   +200.25in    "> mapping to <iframe> height property
+PASS <iframe height="+200%"> mapping to <iframe> height property
+PASS <iframe height="   +200.25%    "> mapping to <iframe> height property
+PASS <iframe height="   +200.25%abc"> mapping to <iframe> height property
+PASS <iframe height="+0"> mapping to <iframe> height property
+PASS <iframe height="+0%"> mapping to <iframe> height property
+PASS <iframe height="."> mapping to <iframe> height property
+PASS <iframe height=".%"> mapping to <iframe> height property
+PASS <iframe height=".x"> mapping to <iframe> height property
+PASS <iframe height=".5"> mapping to <iframe> height property
+PASS <iframe height=".5%"> mapping to <iframe> height property
+PASS <input width="200"> mapping to <input> width property
+PASS <input width="1007"> mapping to <input> width property
+PASS <input width="   00523   "> mapping to <input> width property
+PASS <input width="200.25"> mapping to <input> width property
+PASS <input width="200.7"> mapping to <input> width property
+PASS <input width="200."> mapping to <input> width property
+PASS <input width="200in"> mapping to <input> width property
+PASS <input width="200.25in"> mapping to <input> width property
+PASS <input width="200 %"> mapping to <input> width property
+PASS <input width="200 abc"> mapping to <input> width property
+PASS <input width="200%"> mapping to <input> width property
+PASS <input width="200%abc"> mapping to <input> width property
+PASS <input width="200.25%"> mapping to <input> width property
+PASS <input width="200.%"> mapping to <input> width property
+PASS <input width="20.25e2"> mapping to <input> width property
+PASS <input width="20.25E2"> mapping to <input> width property
+PASS <input width="0"> mapping to <input> width property
+PASS <input width="0%"> mapping to <input> width property
+PASS <input width="0px"> mapping to <input> width property
+PASS <input width="-0"> mapping to <input> width property
+PASS <input width="-0%"> mapping to <input> width property
+PASS <input width="-200"> mapping to <input> width property
+PASS <input width="-200px"> mapping to <input> width property
+PASS <input width="   -200"> mapping to <input> width property
+PASS <input width="+-200"> mapping to <input> width property
+PASS <input width="-+200"> mapping to <input> width property
+PASS <input width="-200%"> mapping to <input> width property
+PASS <input width="+200"> mapping to <input> width property
+PASS <input width="   +200in    "> mapping to <input> width property
+PASS <input width="   +200.25in    "> mapping to <input> width property
+PASS <input width="+200%"> mapping to <input> width property
+PASS <input width="   +200.25%    "> mapping to <input> width property
+PASS <input width="   +200.25%abc"> mapping to <input> width property
+PASS <input width="+0"> mapping to <input> width property
+PASS <input width="+0%"> mapping to <input> width property
+PASS <input width="."> mapping to <input> width property
+PASS <input width=".%"> mapping to <input> width property
+PASS <input width=".x"> mapping to <input> width property
+PASS <input width=".5"> mapping to <input> width property
+PASS <input width=".5%"> mapping to <input> width property
+PASS <input height="200"> mapping to <input> height property
+PASS <input height="1007"> mapping to <input> height property
+PASS <input height="   00523   "> mapping to <input> height property
+PASS <input height="200.25"> mapping to <input> height property
+PASS <input height="200.7"> mapping to <input> height property
+PASS <input height="200."> mapping to <input> height property
+PASS <input height="200in"> mapping to <input> height property
+PASS <input height="200.25in"> mapping to <input> height property
+PASS <input height="200 %"> mapping to <input> height property
+PASS <input height="200 abc"> mapping to <input> height property
+PASS <input height="200%"> mapping to <input> height property
+PASS <input height="200%abc"> mapping to <input> height property
+PASS <input height="200.25%"> mapping to <input> height property
+PASS <input height="200.%"> mapping to <input> height property
+PASS <input height="20.25e2"> mapping to <input> height property
+PASS <input height="20.25E2"> mapping to <input> height property
+PASS <input height="0"> mapping to <input> height property
+PASS <input height="0%"> mapping to <input> height property
+PASS <input height="0px"> mapping to <input> height property
+PASS <input height="-0"> mapping to <input> height property
+PASS <input height="-0%"> mapping to <input> height property
+PASS <input height="-200"> mapping to <input> height property
+PASS <input height="-200px"> mapping to <input> height property
+PASS <input height="   -200"> mapping to <input> height property
+PASS <input height="+-200"> mapping to <input> height property
+PASS <input height="-+200"> mapping to <input> height property
+PASS <input height="-200%"> mapping to <input> height property
+PASS <input height="+200"> mapping to <input> height property
+PASS <input height="   +200in    "> mapping to <input> height property
+PASS <input height="   +200.25in    "> mapping to <input> height property
+PASS <input height="+200%"> mapping to <input> height property
+PASS <input height="   +200.25%    "> mapping to <input> height property
+PASS <input height="   +200.25%abc"> mapping to <input> height property
+PASS <input height="+0"> mapping to <input> height property
+PASS <input height="+0%"> mapping to <input> height property
+PASS <input height="."> mapping to <input> height property
+PASS <input height=".%"> mapping to <input> height property
+PASS <input height=".x"> mapping to <input> height property
+PASS <input height=".5"> mapping to <input> height property
+PASS <input height=".5%"> mapping to <input> height property
+PASS <marquee width="200"> mapping to <marquee> width property
+PASS <marquee width="1007"> mapping to <marquee> width property
+PASS <marquee width="   00523   "> mapping to <marquee> width property
+PASS <marquee width="200.25"> mapping to <marquee> width property
+PASS <marquee width="200.7"> mapping to <marquee> width property
+PASS <marquee width="200."> mapping to <marquee> width property
+PASS <marquee width="200in"> mapping to <marquee> width property
+PASS <marquee width="200.25in"> mapping to <marquee> width property
+PASS <marquee width="200 %"> mapping to <marquee> width property
+PASS <marquee width="200 abc"> mapping to <marquee> width property
+PASS <marquee width="200%"> mapping to <marquee> width property
+PASS <marquee width="200%abc"> mapping to <marquee> width property
+PASS <marquee width="200.25%"> mapping to <marquee> width property
+PASS <marquee width="200.%"> mapping to <marquee> width property
+PASS <marquee width="20.25e2"> mapping to <marquee> width property
+PASS <marquee width="20.25E2"> mapping to <marquee> width property
+PASS <marquee width="0"> mapping to <marquee> width property
+PASS <marquee width="0%"> mapping to <marquee> width property
+PASS <marquee width="0px"> mapping to <marquee> width property
+PASS <marquee width="-0"> mapping to <marquee> width property
+PASS <marquee width="-0%"> mapping to <marquee> width property
+PASS <marquee width="-200"> mapping to <marquee> width property
+PASS <marquee width="-200px"> mapping to <marquee> width property
+PASS <marquee width="   -200"> mapping to <marquee> width property
+PASS <marquee width="+-200"> mapping to <marquee> width property
+PASS <marquee width="-+200"> mapping to <marquee> width property
+PASS <marquee width="-200%"> mapping to <marquee> width property
+PASS <marquee width="+200"> mapping to <marquee> width property
+PASS <marquee width="   +200in    "> mapping to <marquee> width property
+PASS <marquee width="   +200.25in    "> mapping to <marquee> width property
+PASS <marquee width="+200%"> mapping to <marquee> width property
+PASS <marquee width="   +200.25%    "> mapping to <marquee> width property
+PASS <marquee width="   +200.25%abc"> mapping to <marquee> width property
+PASS <marquee width="+0"> mapping to <marquee> width property
+PASS <marquee width="+0%"> mapping to <marquee> width property
+PASS <marquee width="."> mapping to <marquee> width property
+PASS <marquee width=".%"> mapping to <marquee> width property
+PASS <marquee width=".x"> mapping to <marquee> width property
+PASS <marquee width=".5"> mapping to <marquee> width property
+PASS <marquee width=".5%"> mapping to <marquee> width property
+PASS <marquee height="200"> mapping to <marquee> height property
+PASS <marquee height="1007"> mapping to <marquee> height property
+PASS <marquee height="   00523   "> mapping to <marquee> height property
+PASS <marquee height="200.25"> mapping to <marquee> height property
+PASS <marquee height="200.7"> mapping to <marquee> height property
+PASS <marquee height="200."> mapping to <marquee> height property
+PASS <marquee height="200in"> mapping to <marquee> height property
+PASS <marquee height="200.25in"> mapping to <marquee> height property
+PASS <marquee height="200 %"> mapping to <marquee> height property
+PASS <marquee height="200 abc"> mapping to <marquee> height property
+PASS <marquee height="200%"> mapping to <marquee> height property
+PASS <marquee height="200%abc"> mapping to <marquee> height property
+PASS <marquee height="200.25%"> mapping to <marquee> height property
+PASS <marquee height="200.%"> mapping to <marquee> height property
+PASS <marquee height="20.25e2"> mapping to <marquee> height property
+PASS <marquee height="20.25E2"> mapping to <marquee> height property
+PASS <marquee height="0"> mapping to <marquee> height property
+PASS <marquee height="0%"> mapping to <marquee> height property
+PASS <marquee height="0px"> mapping to <marquee> height property
+PASS <marquee height="-0"> mapping to <marquee> height property
+PASS <marquee height="-0%"> mapping to <marquee> height property
+PASS <marquee height="-200"> mapping to <marquee> height property
+PASS <marquee height="-200px"> mapping to <marquee> height property
+PASS <marquee height="   -200"> mapping to <marquee> height property
+PASS <marquee height="+-200"> mapping to <marquee> height property
+PASS <marquee height="-+200"> mapping to <marquee> height property
+PASS <marquee height="-200%"> mapping to <marquee> height property
+PASS <marquee height="+200"> mapping to <marquee> height property
+PASS <marquee height="   +200in    "> mapping to <marquee> height property
+PASS <marquee height="   +200.25in    "> mapping to <marquee> height property
+PASS <marquee height="+200%"> mapping to <marquee> height property
+PASS <marquee height="   +200.25%    "> mapping to <marquee> height property
+PASS <marquee height="   +200.25%abc"> mapping to <marquee> height property
+PASS <marquee height="+0"> mapping to <marquee> height property
+PASS <marquee height="+0%"> mapping to <marquee> height property
+PASS <marquee height="."> mapping to <marquee> height property
+PASS <marquee height=".%"> mapping to <marquee> height property
+PASS <marquee height=".x"> mapping to <marquee> height property
+PASS <marquee height=".5"> mapping to <marquee> height property
+PASS <marquee height=".5%"> mapping to <marquee> height property
+PASS <video width="200"> mapping to <video> width property
+PASS <video width="1007"> mapping to <video> width property
+PASS <video width="   00523   "> mapping to <video> width property
+PASS <video width="200.25"> mapping to <video> width property
+PASS <video width="200.7"> mapping to <video> width property
+PASS <video width="200."> mapping to <video> width property
+PASS <video width="200in"> mapping to <video> width property
+PASS <video width="200.25in"> mapping to <video> width property
+PASS <video width="200 %"> mapping to <video> width property
+PASS <video width="200 abc"> mapping to <video> width property
+PASS <video width="200%"> mapping to <video> width property
+PASS <video width="200%abc"> mapping to <video> width property
+PASS <video width="200.25%"> mapping to <video> width property
+PASS <video width="200.%"> mapping to <video> width property
+PASS <video width="20.25e2"> mapping to <video> width property
+PASS <video width="20.25E2"> mapping to <video> width property
+PASS <video width="0"> mapping to <video> width property
+PASS <video width="0%"> mapping to <video> width property
+PASS <video width="0px"> mapping to <video> width property
+PASS <video width="-0"> mapping to <video> width property
+PASS <video width="-0%"> mapping to <video> width property
+PASS <video width="-200"> mapping to <video> width property
+PASS <video width="-200px"> mapping to <video> width property
+PASS <video width="   -200"> mapping to <video> width property
+PASS <video width="+-200"> mapping to <video> width property
+PASS <video width="-+200"> mapping to <video> width property
+PASS <video width="-200%"> mapping to <video> width property
+PASS <video width="+200"> mapping to <video> width property
+PASS <video width="   +200in    "> mapping to <video> width property
+PASS <video width="   +200.25in    "> mapping to <video> width property
+PASS <video width="+200%"> mapping to <video> width property
+PASS <video width="   +200.25%    "> mapping to <video> width property
+PASS <video width="   +200.25%abc"> mapping to <video> width property
+PASS <video width="+0"> mapping to <video> width property
+PASS <video width="+0%"> mapping to <video> width property
+PASS <video width="."> mapping to <video> width property
+PASS <video width=".%"> mapping to <video> width property
+PASS <video width=".x"> mapping to <video> width property
+PASS <video width=".5"> mapping to <video> width property
+PASS <video width=".5%"> mapping to <video> width property
+PASS <video height="200"> mapping to <video> height property
+PASS <video height="1007"> mapping to <video> height property
+PASS <video height="   00523   "> mapping to <video> height property
+PASS <video height="200.25"> mapping to <video> height property
+PASS <video height="200.7"> mapping to <video> height property
+PASS <video height="200."> mapping to <video> height property
+PASS <video height="200in"> mapping to <video> height property
+PASS <video height="200.25in"> mapping to <video> height property
+PASS <video height="200 %"> mapping to <video> height property
+PASS <video height="200 abc"> mapping to <video> height property
+PASS <video height="200%"> mapping to <video> height property
+PASS <video height="200%abc"> mapping to <video> height property
+PASS <video height="200.25%"> mapping to <video> height property
+PASS <video height="200.%"> mapping to <video> height property
+PASS <video height="20.25e2"> mapping to <video> height property
+PASS <video height="20.25E2"> mapping to <video> height property
+PASS <video height="0"> mapping to <video> height property
+PASS <video height="0%"> mapping to <video> height property
+PASS <video height="0px"> mapping to <video> height property
+PASS <video height="-0"> mapping to <video> height property
+PASS <video height="-0%"> mapping to <video> height property
+PASS <video height="-200"> mapping to <video> height property
+PASS <video height="-200px"> mapping to <video> height property
+PASS <video height="   -200"> mapping to <video> height property
+PASS <video height="+-200"> mapping to <video> height property
+PASS <video height="-+200"> mapping to <video> height property
+PASS <video height="-200%"> mapping to <video> height property
+PASS <video height="+200"> mapping to <video> height property
+PASS <video height="   +200in    "> mapping to <video> height property
+PASS <video height="   +200.25in    "> mapping to <video> height property
+PASS <video height="+200%"> mapping to <video> height property
+PASS <video height="   +200.25%    "> mapping to <video> height property
+PASS <video height="   +200.25%abc"> mapping to <video> height property
+PASS <video height="+0"> mapping to <video> height property
+PASS <video height="+0%"> mapping to <video> height property
+PASS <video height="."> mapping to <video> height property
+PASS <video height=".%"> mapping to <video> height property
+PASS <video height=".x"> mapping to <video> height property
+PASS <video height=".5"> mapping to <video> height property
+PASS <video height=".5%"> mapping to <video> height property
+PASS <object width="200"> mapping to <object> width property
+PASS <object width="1007"> mapping to <object> width property
+PASS <object width="   00523   "> mapping to <object> width property
+PASS <object width="200.25"> mapping to <object> width property
+PASS <object width="200.7"> mapping to <object> width property
+PASS <object width="200."> mapping to <object> width property
+PASS <object width="200in"> mapping to <object> width property
+PASS <object width="200.25in"> mapping to <object> width property
+PASS <object width="200 %"> mapping to <object> width property
+PASS <object width="200 abc"> mapping to <object> width property
+PASS <object width="200%"> mapping to <object> width property
+PASS <object width="200%abc"> mapping to <object> width property
+PASS <object width="200.25%"> mapping to <object> width property
+PASS <object width="200.%"> mapping to <object> width property
+PASS <object width="20.25e2"> mapping to <object> width property
+PASS <object width="20.25E2"> mapping to <object> width property
+PASS <object width="0"> mapping to <object> width property
+PASS <object width="0%"> mapping to <object> width property
+PASS <object width="0px"> mapping to <object> width property
+PASS <object width="-0"> mapping to <object> width property
+PASS <object width="-0%"> mapping to <object> width property
+PASS <object width="-200"> mapping to <object> width property
+PASS <object width="-200px"> mapping to <object> width property
+PASS <object width="   -200"> mapping to <object> width property
+PASS <object width="+-200"> mapping to <object> width property
+PASS <object width="-+200"> mapping to <object> width property
+PASS <object width="-200%"> mapping to <object> width property
+PASS <object width="+200"> mapping to <object> width property
+PASS <object width="   +200in    "> mapping to <object> width property
+PASS <object width="   +200.25in    "> mapping to <object> width property
+PASS <object width="+200%"> mapping to <object> width property
+PASS <object width="   +200.25%    "> mapping to <object> width property
+PASS <object width="   +200.25%abc"> mapping to <object> width property
+PASS <object width="+0"> mapping to <object> width property
+PASS <object width="+0%"> mapping to <object> width property
+PASS <object width="."> mapping to <object> width property
+PASS <object width=".%"> mapping to <object> width property
+PASS <object width=".x"> mapping to <object> width property
+PASS <object width=".5"> mapping to <object> width property
+PASS <object width=".5%"> mapping to <object> width property
+PASS <object height="200"> mapping to <object> height property
+PASS <object height="1007"> mapping to <object> height property
+PASS <object height="   00523   "> mapping to <object> height property
+PASS <object height="200.25"> mapping to <object> height property
+PASS <object height="200.7"> mapping to <object> height property
+PASS <object height="200."> mapping to <object> height property
+PASS <object height="200in"> mapping to <object> height property
+PASS <object height="200.25in"> mapping to <object> height property
+PASS <object height="200 %"> mapping to <object> height property
+PASS <object height="200 abc"> mapping to <object> height property
+PASS <object height="200%"> mapping to <object> height property
+PASS <object height="200%abc"> mapping to <object> height property
+PASS <object height="200.25%"> mapping to <object> height property
+PASS <object height="200.%"> mapping to <object> height property
+PASS <object height="20.25e2"> mapping to <object> height property
+PASS <object height="20.25E2"> mapping to <object> height property
+PASS <object height="0"> mapping to <object> height property
+PASS <object height="0%"> mapping to <object> height property
+PASS <object height="0px"> mapping to <object> height property
+PASS <object height="-0"> mapping to <object> height property
+PASS <object height="-0%"> mapping to <object> height property
+PASS <object height="-200"> mapping to <object> height property
+PASS <object height="-200px"> mapping to <object> height property
+PASS <object height="   -200"> mapping to <object> height property
+PASS <object height="+-200"> mapping to <object> height property
+PASS <object height="-+200"> mapping to <object> height property
+PASS <object height="-200%"> mapping to <object> height property
+PASS <object height="+200"> mapping to <object> height property
+PASS <object height="   +200in    "> mapping to <object> height property
+PASS <object height="   +200.25in    "> mapping to <object> height property
+PASS <object height="+200%"> mapping to <object> height property
+PASS <object height="   +200.25%    "> mapping to <object> height property
+PASS <object height="   +200.25%abc"> mapping to <object> height property
+PASS <object height="+0"> mapping to <object> height property
+PASS <object height="+0%"> mapping to <object> height property
+PASS <object height="."> mapping to <object> height property
+PASS <object height=".%"> mapping to <object> height property
+PASS <object height=".x"> mapping to <object> height property
+PASS <object height=".5"> mapping to <object> height property
+PASS <object height=".5%"> mapping to <object> height property
+PASS <embed width="200"> mapping to <embed> width property
+PASS <embed width="1007"> mapping to <embed> width property
+PASS <embed width="   00523   "> mapping to <embed> width property
+PASS <embed width="200.25"> mapping to <embed> width property
+PASS <embed width="200.7"> mapping to <embed> width property
+PASS <embed width="200."> mapping to <embed> width property
+PASS <embed width="200in"> mapping to <embed> width property
+PASS <embed width="200.25in"> mapping to <embed> width property
+PASS <embed width="200 %"> mapping to <embed> width property
+PASS <embed width="200 abc"> mapping to <embed> width property
+PASS <embed width="200%"> mapping to <embed> width property
+PASS <embed width="200%abc"> mapping to <embed> width property
+PASS <embed width="200.25%"> mapping to <embed> width property
+PASS <embed width="200.%"> mapping to <embed> width property
+PASS <embed width="20.25e2"> mapping to <embed> width property
+PASS <embed width="20.25E2"> mapping to <embed> width property
+PASS <embed width="0"> mapping to <embed> width property
+PASS <embed width="0%"> mapping to <embed> width property
+PASS <embed width="0px"> mapping to <embed> width property
+PASS <embed width="-0"> mapping to <embed> width property
+PASS <embed width="-0%"> mapping to <embed> width property
+PASS <embed width="-200"> mapping to <embed> width property
+PASS <embed width="-200px"> mapping to <embed> width property
+PASS <embed width="   -200"> mapping to <embed> width property
+PASS <embed width="+-200"> mapping to <embed> width property
+PASS <embed width="-+200"> mapping to <embed> width property
+PASS <embed width="-200%"> mapping to <embed> width property
+PASS <embed width="+200"> mapping to <embed> width property
+PASS <embed width="   +200in    "> mapping to <embed> width property
+PASS <embed width="   +200.25in    "> mapping to <embed> width property
+PASS <embed width="+200%"> mapping to <embed> width property
+PASS <embed width="   +200.25%    "> mapping to <embed> width property
+PASS <embed width="   +200.25%abc"> mapping to <embed> width property
+PASS <embed width="+0"> mapping to <embed> width property
+PASS <embed width="+0%"> mapping to <embed> width property
+PASS <embed width="."> mapping to <embed> width property
+PASS <embed width=".%"> mapping to <embed> width property
+PASS <embed width=".x"> mapping to <embed> width property
+PASS <embed width=".5"> mapping to <embed> width property
+PASS <embed width=".5%"> mapping to <embed> width property
+PASS <embed height="200"> mapping to <embed> height property
+PASS <embed height="1007"> mapping to <embed> height property
+PASS <embed height="   00523   "> mapping to <embed> height property
+PASS <embed height="200.25"> mapping to <embed> height property
+PASS <embed height="200.7"> mapping to <embed> height property
+PASS <embed height="200."> mapping to <embed> height property
+PASS <embed height="200in"> mapping to <embed> height property
+PASS <embed height="200.25in"> mapping to <embed> height property
+PASS <embed height="200 %"> mapping to <embed> height property
+PASS <embed height="200 abc"> mapping to <embed> height property
+PASS <embed height="200%"> mapping to <embed> height property
+PASS <embed height="200%abc"> mapping to <embed> height property
+PASS <embed height="200.25%"> mapping to <embed> height property
+PASS <embed height="200.%"> mapping to <embed> height property
+PASS <embed height="20.25e2"> mapping to <embed> height property
+PASS <embed height="20.25E2"> mapping to <embed> height property
+PASS <embed height="0"> mapping to <embed> height property
+PASS <embed height="0%"> mapping to <embed> height property
+PASS <embed height="0px"> mapping to <embed> height property
+PASS <embed height="-0"> mapping to <embed> height property
+PASS <embed height="-0%"> mapping to <embed> height property
+PASS <embed height="-200"> mapping to <embed> height property
+PASS <embed height="-200px"> mapping to <embed> height property
+PASS <embed height="   -200"> mapping to <embed> height property
+PASS <embed height="+-200"> mapping to <embed> height property
+PASS <embed height="-+200"> mapping to <embed> height property
+PASS <embed height="-200%"> mapping to <embed> height property
+PASS <embed height="+200"> mapping to <embed> height property
+PASS <embed height="   +200in    "> mapping to <embed> height property
+PASS <embed height="   +200.25in    "> mapping to <embed> height property
+PASS <embed height="+200%"> mapping to <embed> height property
+PASS <embed height="   +200.25%    "> mapping to <embed> height property
+PASS <embed height="   +200.25%abc"> mapping to <embed> height property
+PASS <embed height="+0"> mapping to <embed> height property
+PASS <embed height="+0%"> mapping to <embed> height property
+PASS <embed height="."> mapping to <embed> height property
+PASS <embed height=".%"> mapping to <embed> height property
+PASS <embed height=".x"> mapping to <embed> height property
+PASS <embed height=".5"> mapping to <embed> height property
+PASS <embed height=".5%"> mapping to <embed> height property
+PASS <img width="200"> mapping to <img> width property
+PASS <img width="1007"> mapping to <img> width property
+PASS <img width="   00523   "> mapping to <img> width property
+PASS <img width="200.25"> mapping to <img> width property
+PASS <img width="200.7"> mapping to <img> width property
+PASS <img width="200."> mapping to <img> width property
+PASS <img width="200in"> mapping to <img> width property
+PASS <img width="200.25in"> mapping to <img> width property
+PASS <img width="200 %"> mapping to <img> width property
+PASS <img width="200 abc"> mapping to <img> width property
+PASS <img width="200%"> mapping to <img> width property
+PASS <img width="200%abc"> mapping to <img> width property
+PASS <img width="200.25%"> mapping to <img> width property
+PASS <img width="200.%"> mapping to <img> width property
+PASS <img width="20.25e2"> mapping to <img> width property
+PASS <img width="20.25E2"> mapping to <img> width property
+PASS <img width="0"> mapping to <img> width property
+PASS <img width="0%"> mapping to <img> width property
+PASS <img width="0px"> mapping to <img> width property
+PASS <img width="-0"> mapping to <img> width property
+PASS <img width="-0%"> mapping to <img> width property
+PASS <img width="-200"> mapping to <img> width property
+PASS <img width="-200px"> mapping to <img> width property
+PASS <img width="   -200"> mapping to <img> width property
+PASS <img width="+-200"> mapping to <img> width property
+PASS <img width="-+200"> mapping to <img> width property
+PASS <img width="-200%"> mapping to <img> width property
+PASS <img width="+200"> mapping to <img> width property
+PASS <img width="   +200in    "> mapping to <img> width property
+PASS <img width="   +200.25in    "> mapping to <img> width property
+PASS <img width="+200%"> mapping to <img> width property
+PASS <img width="   +200.25%    "> mapping to <img> width property
+PASS <img width="   +200.25%abc"> mapping to <img> width property
+PASS <img width="+0"> mapping to <img> width property
+PASS <img width="+0%"> mapping to <img> width property
+PASS <img width="."> mapping to <img> width property
+PASS <img width=".%"> mapping to <img> width property
+PASS <img width=".x"> mapping to <img> width property
+PASS <img width=".5"> mapping to <img> width property
+PASS <img width=".5%"> mapping to <img> width property
+PASS <img height="200"> mapping to <img> height property
+PASS <img height="1007"> mapping to <img> height property
+PASS <img height="   00523   "> mapping to <img> height property
+PASS <img height="200.25"> mapping to <img> height property
+PASS <img height="200.7"> mapping to <img> height property
+PASS <img height="200."> mapping to <img> height property
+PASS <img height="200in"> mapping to <img> height property
+PASS <img height="200.25in"> mapping to <img> height property
+PASS <img height="200 %"> mapping to <img> height property
+PASS <img height="200 abc"> mapping to <img> height property
+PASS <img height="200%"> mapping to <img> height property
+PASS <img height="200%abc"> mapping to <img> height property
+PASS <img height="200.25%"> mapping to <img> height property
+PASS <img height="200.%"> mapping to <img> height property
+PASS <img height="20.25e2"> mapping to <img> height property
+PASS <img height="20.25E2"> mapping to <img> height property
+PASS <img height="0"> mapping to <img> height property
+PASS <img height="0%"> mapping to <img> height property
+PASS <img height="0px"> mapping to <img> height property
+PASS <img height="-0"> mapping to <img> height property
+PASS <img height="-0%"> mapping to <img> height property
+PASS <img height="-200"> mapping to <img> height property
+PASS <img height="-200px"> mapping to <img> height property
+PASS <img height="   -200"> mapping to <img> height property
+PASS <img height="+-200"> mapping to <img> height property
+PASS <img height="-+200"> mapping to <img> height property
+PASS <img height="-200%"> mapping to <img> height property
+PASS <img height="+200"> mapping to <img> height property
+PASS <img height="   +200in    "> mapping to <img> height property
+PASS <img height="   +200.25in    "> mapping to <img> height property
+PASS <img height="+200%"> mapping to <img> height property
+PASS <img height="   +200.25%    "> mapping to <img> height property
+PASS <img height="   +200.25%abc"> mapping to <img> height property
+PASS <img height="+0"> mapping to <img> height property
+PASS <img height="+0%"> mapping to <img> height property
+PASS <img height="."> mapping to <img> height property
+PASS <img height=".%"> mapping to <img> height property
+PASS <img height=".x"> mapping to <img> height property
+PASS <img height=".5"> mapping to <img> height property
+PASS <img height=".5%"> mapping to <img> height property
+PASS <td width="200"> mapping to <td> width property
+PASS <td width="1007"> mapping to <td> width property
+PASS <td width="   00523   "> mapping to <td> width property
+PASS <td width="200.25"> mapping to <td> width property
+PASS <td width="200.7"> mapping to <td> width property
+PASS <td width="200."> mapping to <td> width property
+PASS <td width="200in"> mapping to <td> width property
+PASS <td width="200.25in"> mapping to <td> width property
+PASS <td width="200 %"> mapping to <td> width property
+PASS <td width="200 abc"> mapping to <td> width property
+PASS <td width="200%"> mapping to <td> width property
+PASS <td width="200%abc"> mapping to <td> width property
+PASS <td width="200.25%"> mapping to <td> width property
+PASS <td width="200.%"> mapping to <td> width property
+PASS <td width="20.25e2"> mapping to <td> width property
+PASS <td width="20.25E2"> mapping to <td> width property
+PASS <td width="-0"> mapping to <td> width property
+PASS <td width="-0%"> mapping to <td> width property
+PASS <td width="-200"> mapping to <td> width property
+PASS <td width="-200px"> mapping to <td> width property
+PASS <td width="   -200"> mapping to <td> width property
+PASS <td width="+-200"> mapping to <td> width property
+PASS <td width="-+200"> mapping to <td> width property
+PASS <td width="-200%"> mapping to <td> width property
+PASS <td width="+200"> mapping to <td> width property
+PASS <td width="   +200in    "> mapping to <td> width property
+PASS <td width="   +200.25in    "> mapping to <td> width property
+PASS <td width="+200%"> mapping to <td> width property
+PASS <td width="   +200.25%    "> mapping to <td> width property
+PASS <td width="   +200.25%abc"> mapping to <td> width property
+PASS <td width="+0"> mapping to <td> width property
+PASS <td width="+0%"> mapping to <td> width property
+PASS <td width="."> mapping to <td> width property
+PASS <td width=".%"> mapping to <td> width property
+PASS <td width=".x"> mapping to <td> width property
+PASS <td width=".5"> mapping to <td> width property
+PASS <td width=".5%"> mapping to <td> width property
+PASS <td width="0"> mapping to <td> width property
+PASS <td width="0%"> mapping to <td> width property
+PASS <td width="0px"> mapping to <td> width property
+PASS <td height="200"> mapping to <td> height property
+PASS <td height="1007"> mapping to <td> height property
+PASS <td height="   00523   "> mapping to <td> height property
+PASS <td height="200.25"> mapping to <td> height property
+PASS <td height="200.7"> mapping to <td> height property
+PASS <td height="200."> mapping to <td> height property
+PASS <td height="200in"> mapping to <td> height property
+PASS <td height="200.25in"> mapping to <td> height property
+PASS <td height="200 %"> mapping to <td> height property
+PASS <td height="200 abc"> mapping to <td> height property
+PASS <td height="200%"> mapping to <td> height property
+PASS <td height="200%abc"> mapping to <td> height property
+PASS <td height="200.25%"> mapping to <td> height property
+PASS <td height="200.%"> mapping to <td> height property
+PASS <td height="20.25e2"> mapping to <td> height property
+PASS <td height="20.25E2"> mapping to <td> height property
+PASS <td height="-0"> mapping to <td> height property
+PASS <td height="-0%"> mapping to <td> height property
+PASS <td height="-200"> mapping to <td> height property
+PASS <td height="-200px"> mapping to <td> height property
+PASS <td height="   -200"> mapping to <td> height property
+PASS <td height="+-200"> mapping to <td> height property
+PASS <td height="-+200"> mapping to <td> height property
+PASS <td height="-200%"> mapping to <td> height property
+PASS <td height="+200"> mapping to <td> height property
+PASS <td height="   +200in    "> mapping to <td> height property
+PASS <td height="   +200.25in    "> mapping to <td> height property
+PASS <td height="+200%"> mapping to <td> height property
+PASS <td height="   +200.25%    "> mapping to <td> height property
+PASS <td height="   +200.25%abc"> mapping to <td> height property
+PASS <td height="+0"> mapping to <td> height property
+PASS <td height="+0%"> mapping to <td> height property
+PASS <td height="."> mapping to <td> height property
+PASS <td height=".%"> mapping to <td> height property
+PASS <td height=".x"> mapping to <td> height property
+PASS <td height=".5"> mapping to <td> height property
+PASS <td height=".5%"> mapping to <td> height property
+PASS <td height="0"> mapping to <td> height property
+PASS <td height="0%"> mapping to <td> height property
+PASS <td height="0px"> mapping to <td> height property
+PASS <table width="200"> mapping to <table> width property
+PASS <table width="1007"> mapping to <table> width property
+PASS <table width="   00523   "> mapping to <table> width property
+PASS <table width="200.25"> mapping to <table> width property
+PASS <table width="200.7"> mapping to <table> width property
+PASS <table width="200."> mapping to <table> width property
+PASS <table width="200in"> mapping to <table> width property
+PASS <table width="200.25in"> mapping to <table> width property
+PASS <table width="200 %"> mapping to <table> width property
+PASS <table width="200 abc"> mapping to <table> width property
+PASS <table width="200%"> mapping to <table> width property
+PASS <table width="200%abc"> mapping to <table> width property
+PASS <table width="200.25%"> mapping to <table> width property
+PASS <table width="200.%"> mapping to <table> width property
+PASS <table width="20.25e2"> mapping to <table> width property
+PASS <table width="20.25E2"> mapping to <table> width property
+PASS <table width="-0"> mapping to <table> width property
+PASS <table width="-0%"> mapping to <table> width property
+PASS <table width="-200"> mapping to <table> width property
+PASS <table width="-200px"> mapping to <table> width property
+PASS <table width="   -200"> mapping to <table> width property
+PASS <table width="+-200"> mapping to <table> width property
+PASS <table width="-+200"> mapping to <table> width property
+PASS <table width="-200%"> mapping to <table> width property
+PASS <table width="+200"> mapping to <table> width property
+PASS <table width="   +200in    "> mapping to <table> width property
+PASS <table width="   +200.25in    "> mapping to <table> width property
+PASS <table width="+200%"> mapping to <table> width property
+PASS <table width="   +200.25%    "> mapping to <table> width property
+PASS <table width="   +200.25%abc"> mapping to <table> width property
+PASS <table width="+0"> mapping to <table> width property
+PASS <table width="+0%"> mapping to <table> width property
+PASS <table width="."> mapping to <table> width property
+PASS <table width=".%"> mapping to <table> width property
+PASS <table width=".x"> mapping to <table> width property
+PASS <table width=".5"> mapping to <table> width property
+PASS <table width=".5%"> mapping to <table> width property
+PASS <table width="0"> mapping to <table> width property
+PASS <table width="0%"> mapping to <table> width property
+PASS <table width="0px"> mapping to <table> width property
+PASS <table height="200"> mapping to <table> height property
+PASS <table height="1007"> mapping to <table> height property
+PASS <table height="   00523   "> mapping to <table> height property
+PASS <table height="200.25"> mapping to <table> height property
+PASS <table height="200.7"> mapping to <table> height property
+PASS <table height="200."> mapping to <table> height property
+PASS <table height="200in"> mapping to <table> height property
+PASS <table height="200.25in"> mapping to <table> height property
+PASS <table height="200 %"> mapping to <table> height property
+PASS <table height="200 abc"> mapping to <table> height property
+PASS <table height="200%"> mapping to <table> height property
+PASS <table height="200%abc"> mapping to <table> height property
+PASS <table height="200.25%"> mapping to <table> height property
+PASS <table height="200.%"> mapping to <table> height property
+PASS <table height="20.25e2"> mapping to <table> height property
+PASS <table height="20.25E2"> mapping to <table> height property
+PASS <table height="-0"> mapping to <table> height property
+PASS <table height="-0%"> mapping to <table> height property
+PASS <table height="-200"> mapping to <table> height property
+PASS <table height="-200px"> mapping to <table> height property
+PASS <table height="   -200"> mapping to <table> height property
+PASS <table height="+-200"> mapping to <table> height property
+PASS <table height="-+200"> mapping to <table> height property
+PASS <table height="-200%"> mapping to <table> height property
+PASS <table height="+200"> mapping to <table> height property
+PASS <table height="   +200in    "> mapping to <table> height property
+PASS <table height="   +200.25in    "> mapping to <table> height property
+PASS <table height="+200%"> mapping to <table> height property
+PASS <table height="   +200.25%    "> mapping to <table> height property
+PASS <table height="   +200.25%abc"> mapping to <table> height property
+PASS <table height="+0"> mapping to <table> height property
+PASS <table height="+0%"> mapping to <table> height property
+PASS <table height="."> mapping to <table> height property
+PASS <table height=".%"> mapping to <table> height property
+PASS <table height=".x"> mapping to <table> height property
+PASS <table height=".5"> mapping to <table> height property
+PASS <table height=".5%"> mapping to <table> height property
+FAIL <table height="0"> mapping to <table> height property assert_equals: expected "auto" but got "0px"
+FAIL <table height="0%"> mapping to <table> height property assert_equals: expected "auto" but got "0%"
+FAIL <table height="0px"> mapping to <table> height property assert_equals: expected "auto" but got "0px"
+PASS <tr height="200"> mapping to <tr> height property
+PASS <tr height="1007"> mapping to <tr> height property
+PASS <tr height="   00523   "> mapping to <tr> height property
+PASS <tr height="200.25"> mapping to <tr> height property
+PASS <tr height="200.7"> mapping to <tr> height property
+PASS <tr height="200."> mapping to <tr> height property
+PASS <tr height="200in"> mapping to <tr> height property
+PASS <tr height="200.25in"> mapping to <tr> height property
+PASS <tr height="200 %"> mapping to <tr> height property
+PASS <tr height="200 abc"> mapping to <tr> height property
+PASS <tr height="200%"> mapping to <tr> height property
+PASS <tr height="200%abc"> mapping to <tr> height property
+PASS <tr height="200.25%"> mapping to <tr> height property
+PASS <tr height="200.%"> mapping to <tr> height property
+PASS <tr height="20.25e2"> mapping to <tr> height property
+PASS <tr height="20.25E2"> mapping to <tr> height property
+PASS <tr height="-0"> mapping to <tr> height property
+PASS <tr height="-0%"> mapping to <tr> height property
+PASS <tr height="-200"> mapping to <tr> height property
+PASS <tr height="-200px"> mapping to <tr> height property
+PASS <tr height="   -200"> mapping to <tr> height property
+PASS <tr height="+-200"> mapping to <tr> height property
+PASS <tr height="-+200"> mapping to <tr> height property
+PASS <tr height="-200%"> mapping to <tr> height property
+PASS <tr height="+200"> mapping to <tr> height property
+PASS <tr height="   +200in    "> mapping to <tr> height property
+PASS <tr height="   +200.25in    "> mapping to <tr> height property
+PASS <tr height="+200%"> mapping to <tr> height property
+PASS <tr height="   +200.25%    "> mapping to <tr> height property
+PASS <tr height="   +200.25%abc"> mapping to <tr> height property
+PASS <tr height="+0"> mapping to <tr> height property
+PASS <tr height="+0%"> mapping to <tr> height property
+PASS <tr height="."> mapping to <tr> height property
+PASS <tr height=".%"> mapping to <tr> height property
+PASS <tr height=".x"> mapping to <tr> height property
+PASS <tr height=".5"> mapping to <tr> height property
+PASS <tr height=".5%"> mapping to <tr> height property
+FAIL <tr height="0"> mapping to <tr> height property assert_equals: expected "auto" but got "0px"
+FAIL <tr height="0%"> mapping to <tr> height property assert_equals: expected "auto" but got "0%"
+FAIL <tr height="0px"> mapping to <tr> height property assert_equals: expected "auto" but got "0px"
+PASS <col width="200"> mapping to <col> width property
+PASS <col width="1007"> mapping to <col> width property
+PASS <col width="   00523   "> mapping to <col> width property
+PASS <col width="200.25"> mapping to <col> width property
+PASS <col width="200.7"> mapping to <col> width property
+PASS <col width="200."> mapping to <col> width property
+PASS <col width="200in"> mapping to <col> width property
+PASS <col width="200.25in"> mapping to <col> width property
+PASS <col width="200 %"> mapping to <col> width property
+PASS <col width="200 abc"> mapping to <col> width property
+PASS <col width="200%"> mapping to <col> width property
+PASS <col width="200%abc"> mapping to <col> width property
+PASS <col width="200.25%"> mapping to <col> width property
+PASS <col width="200.%"> mapping to <col> width property
+PASS <col width="20.25e2"> mapping to <col> width property
+PASS <col width="20.25E2"> mapping to <col> width property
+PASS <col width="-0"> mapping to <col> width property
+PASS <col width="-0%"> mapping to <col> width property
+PASS <col width="-200"> mapping to <col> width property
+PASS <col width="-200px"> mapping to <col> width property
+PASS <col width="   -200"> mapping to <col> width property
+PASS <col width="+-200"> mapping to <col> width property
+PASS <col width="-+200"> mapping to <col> width property
+PASS <col width="-200%"> mapping to <col> width property
+PASS <col width="+200"> mapping to <col> width property
+PASS <col width="   +200in    "> mapping to <col> width property
+PASS <col width="   +200.25in    "> mapping to <col> width property
+PASS <col width="+200%"> mapping to <col> width property
+PASS <col width="   +200.25%    "> mapping to <col> width property
+PASS <col width="   +200.25%abc"> mapping to <col> width property
+PASS <col width="+0"> mapping to <col> width property
+PASS <col width="+0%"> mapping to <col> width property
+PASS <col width="."> mapping to <col> width property
+PASS <col width=".%"> mapping to <col> width property
+PASS <col width=".x"> mapping to <col> width property
+PASS <col width=".5"> mapping to <col> width property
+PASS <col width=".5%"> mapping to <col> width property
+FAIL <col width="0"> mapping to <col> width property assert_equals: expected "auto" but got "0px"
+FAIL <col width="0%"> mapping to <col> width property assert_equals: expected "auto" but got "0%"
+FAIL <col width="0px"> mapping to <col> width property assert_equals: expected "auto" but got "0px"
+PASS <embed hspace="200"> mapping to <embed> marginLeft property
+PASS <embed hspace="1007"> mapping to <embed> marginLeft property
+PASS <embed hspace="   00523   "> mapping to <embed> marginLeft property
+PASS <embed hspace="200.25"> mapping to <embed> marginLeft property
+PASS <embed hspace="200.7"> mapping to <embed> marginLeft property
+PASS <embed hspace="200."> mapping to <embed> marginLeft property
+PASS <embed hspace="200in"> mapping to <embed> marginLeft property
+PASS <embed hspace="200.25in"> mapping to <embed> marginLeft property
+PASS <embed hspace="200 %"> mapping to <embed> marginLeft property
+PASS <embed hspace="200 abc"> mapping to <embed> marginLeft property
+PASS <embed hspace="200%"> mapping to <embed> marginLeft property
+PASS <embed hspace="200%abc"> mapping to <embed> marginLeft property
+PASS <embed hspace="200.25%"> mapping to <embed> marginLeft property
+PASS <embed hspace="200.%"> mapping to <embed> marginLeft property
+PASS <embed hspace="20.25e2"> mapping to <embed> marginLeft property
+PASS <embed hspace="20.25E2"> mapping to <embed> marginLeft property
+PASS <embed hspace="0"> mapping to <embed> marginLeft property
+PASS <embed hspace="0%"> mapping to <embed> marginLeft property
+PASS <embed hspace="0px"> mapping to <embed> marginLeft property
+PASS <embed hspace="-0"> mapping to <embed> marginLeft property
+PASS <embed hspace="-0%"> mapping to <embed> marginLeft property
+PASS <embed hspace="-200"> mapping to <embed> marginLeft property
+PASS <embed hspace="-200px"> mapping to <embed> marginLeft property
+PASS <embed hspace="   -200"> mapping to <embed> marginLeft property
+PASS <embed hspace="+-200"> mapping to <embed> marginLeft property
+PASS <embed hspace="-+200"> mapping to <embed> marginLeft property
+PASS <embed hspace="-200%"> mapping to <embed> marginLeft property
+PASS <embed hspace="+200"> mapping to <embed> marginLeft property
+PASS <embed hspace="   +200in    "> mapping to <embed> marginLeft property
+PASS <embed hspace="   +200.25in    "> mapping to <embed> marginLeft property
+PASS <embed hspace="+200%"> mapping to <embed> marginLeft property
+PASS <embed hspace="   +200.25%    "> mapping to <embed> marginLeft property
+PASS <embed hspace="   +200.25%abc"> mapping to <embed> marginLeft property
+PASS <embed hspace="+0"> mapping to <embed> marginLeft property
+PASS <embed hspace="+0%"> mapping to <embed> marginLeft property
+PASS <embed hspace="."> mapping to <embed> marginLeft property
+PASS <embed hspace=".%"> mapping to <embed> marginLeft property
+PASS <embed hspace=".x"> mapping to <embed> marginLeft property
+PASS <embed hspace=".5"> mapping to <embed> marginLeft property
+PASS <embed hspace=".5%"> mapping to <embed> marginLeft property
+PASS <embed hspace="200"> mapping to <embed> marginRight property
+PASS <embed hspace="1007"> mapping to <embed> marginRight property
+PASS <embed hspace="   00523   "> mapping to <embed> marginRight property
+PASS <embed hspace="200.25"> mapping to <embed> marginRight property
+PASS <embed hspace="200.7"> mapping to <embed> marginRight property
+PASS <embed hspace="200."> mapping to <embed> marginRight property
+PASS <embed hspace="200in"> mapping to <embed> marginRight property
+PASS <embed hspace="200.25in"> mapping to <embed> marginRight property
+PASS <embed hspace="200 %"> mapping to <embed> marginRight property
+PASS <embed hspace="200 abc"> mapping to <embed> marginRight property
+PASS <embed hspace="200%"> mapping to <embed> marginRight property
+PASS <embed hspace="200%abc"> mapping to <embed> marginRight property
+PASS <embed hspace="200.25%"> mapping to <embed> marginRight property
+PASS <embed hspace="200.%"> mapping to <embed> marginRight property
+PASS <embed hspace="20.25e2"> mapping to <embed> marginRight property
+PASS <embed hspace="20.25E2"> mapping to <embed> marginRight property
+PASS <embed hspace="0"> mapping to <embed> marginRight property
+PASS <embed hspace="0%"> mapping to <embed> marginRight property
+PASS <embed hspace="0px"> mapping to <embed> marginRight property
+PASS <embed hspace="-0"> mapping to <embed> marginRight property
+PASS <embed hspace="-0%"> mapping to <embed> marginRight property
+PASS <embed hspace="-200"> mapping to <embed> marginRight property
+PASS <embed hspace="-200px"> mapping to <embed> marginRight property
+PASS <embed hspace="   -200"> mapping to <embed> marginRight property
+PASS <embed hspace="+-200"> mapping to <embed> marginRight property
+PASS <embed hspace="-+200"> mapping to <embed> marginRight property
+PASS <embed hspace="-200%"> mapping to <embed> marginRight property
+PASS <embed hspace="+200"> mapping to <embed> marginRight property
+PASS <embed hspace="   +200in    "> mapping to <embed> marginRight property
+PASS <embed hspace="   +200.25in    "> mapping to <embed> marginRight property
+PASS <embed hspace="+200%"> mapping to <embed> marginRight property
+PASS <embed hspace="   +200.25%    "> mapping to <embed> marginRight property
+PASS <embed hspace="   +200.25%abc"> mapping to <embed> marginRight property
+PASS <embed hspace="+0"> mapping to <embed> marginRight property
+PASS <embed hspace="+0%"> mapping to <embed> marginRight property
+PASS <embed hspace="."> mapping to <embed> marginRight property
+PASS <embed hspace=".%"> mapping to <embed> marginRight property
+PASS <embed hspace=".x"> mapping to <embed> marginRight property
+PASS <embed hspace=".5"> mapping to <embed> marginRight property
+PASS <embed hspace=".5%"> mapping to <embed> marginRight property
+PASS <embed vspace="200"> mapping to <embed> marginTop property
+PASS <embed vspace="1007"> mapping to <embed> marginTop property
+PASS <embed vspace="   00523   "> mapping to <embed> marginTop property
+PASS <embed vspace="200.25"> mapping to <embed> marginTop property
+PASS <embed vspace="200.7"> mapping to <embed> marginTop property
+PASS <embed vspace="200."> mapping to <embed> marginTop property
+PASS <embed vspace="200in"> mapping to <embed> marginTop property
+PASS <embed vspace="200.25in"> mapping to <embed> marginTop property
+PASS <embed vspace="200 %"> mapping to <embed> marginTop property
+PASS <embed vspace="200 abc"> mapping to <embed> marginTop property
+PASS <embed vspace="200%"> mapping to <embed> marginTop property
+PASS <embed vspace="200%abc"> mapping to <embed> marginTop property
+PASS <embed vspace="200.25%"> mapping to <embed> marginTop property
+PASS <embed vspace="200.%"> mapping to <embed> marginTop property
+PASS <embed vspace="20.25e2"> mapping to <embed> marginTop property
+PASS <embed vspace="20.25E2"> mapping to <embed> marginTop property
+PASS <embed vspace="0"> mapping to <embed> marginTop property
+PASS <embed vspace="0%"> mapping to <embed> marginTop property
+PASS <embed vspace="0px"> mapping to <embed> marginTop property
+PASS <embed vspace="-0"> mapping to <embed> marginTop property
+PASS <embed vspace="-0%"> mapping to <embed> marginTop property
+PASS <embed vspace="-200"> mapping to <embed> marginTop property
+PASS <embed vspace="-200px"> mapping to <embed> marginTop property
+PASS <embed vspace="   -200"> mapping to <embed> marginTop property
+PASS <embed vspace="+-200"> mapping to <embed> marginTop property
+PASS <embed vspace="-+200"> mapping to <embed> marginTop property
+PASS <embed vspace="-200%"> mapping to <embed> marginTop property
+PASS <embed vspace="+200"> mapping to <embed> marginTop property
+PASS <embed vspace="   +200in    "> mapping to <embed> marginTop property
+PASS <embed vspace="   +200.25in    "> mapping to <embed> marginTop property
+PASS <embed vspace="+200%"> mapping to <embed> marginTop property
+PASS <embed vspace="   +200.25%    "> mapping to <embed> marginTop property
+PASS <embed vspace="   +200.25%abc"> mapping to <embed> marginTop property
+PASS <embed vspace="+0"> mapping to <embed> marginTop property
+PASS <embed vspace="+0%"> mapping to <embed> marginTop property
+PASS <embed vspace="."> mapping to <embed> marginTop property
+PASS <embed vspace=".%"> mapping to <embed> marginTop property
+PASS <embed vspace=".x"> mapping to <embed> marginTop property
+PASS <embed vspace=".5"> mapping to <embed> marginTop property
+PASS <embed vspace=".5%"> mapping to <embed> marginTop property
+PASS <embed vspace="200"> mapping to <embed> marginBottom property
+PASS <embed vspace="1007"> mapping to <embed> marginBottom property
+PASS <embed vspace="   00523   "> mapping to <embed> marginBottom property
+PASS <embed vspace="200.25"> mapping to <embed> marginBottom property
+PASS <embed vspace="200.7"> mapping to <embed> marginBottom property
+PASS <embed vspace="200."> mapping to <embed> marginBottom property
+PASS <embed vspace="200in"> mapping to <embed> marginBottom property
+PASS <embed vspace="200.25in"> mapping to <embed> marginBottom property
+PASS <embed vspace="200 %"> mapping to <embed> marginBottom property
+PASS <embed vspace="200 abc"> mapping to <embed> marginBottom property
+PASS <embed vspace="200%"> mapping to <embed> marginBottom property
+PASS <embed vspace="200%abc"> mapping to <embed> marginBottom property
+PASS <embed vspace="200.25%"> mapping to <embed> marginBottom property
+PASS <embed vspace="200.%"> mapping to <embed> marginBottom property
+PASS <embed vspace="20.25e2"> mapping to <embed> marginBottom property
+PASS <embed vspace="20.25E2"> mapping to <embed> marginBottom property
+PASS <embed vspace="0"> mapping to <embed> marginBottom property
+PASS <embed vspace="0%"> mapping to <embed> marginBottom property
+PASS <embed vspace="0px"> mapping to <embed> marginBottom property
+PASS <embed vspace="-0"> mapping to <embed> marginBottom property
+PASS <embed vspace="-0%"> mapping to <embed> marginBottom property
+PASS <embed vspace="-200"> mapping to <embed> marginBottom property
+PASS <embed vspace="-200px"> mapping to <embed> marginBottom property
+PASS <embed vspace="   -200"> mapping to <embed> marginBottom property
+PASS <embed vspace="+-200"> mapping to <embed> marginBottom property
+PASS <embed vspace="-+200"> mapping to <embed> marginBottom property
+PASS <embed vspace="-200%"> mapping to <embed> marginBottom property
+PASS <embed vspace="+200"> mapping to <embed> marginBottom property
+PASS <embed vspace="   +200in    "> mapping to <embed> marginBottom property
+PASS <embed vspace="   +200.25in    "> mapping to <embed> marginBottom property
+PASS <embed vspace="+200%"> mapping to <embed> marginBottom property
+PASS <embed vspace="   +200.25%    "> mapping to <embed> marginBottom property
+PASS <embed vspace="   +200.25%abc"> mapping to <embed> marginBottom property
+PASS <embed vspace="+0"> mapping to <embed> marginBottom property
+PASS <embed vspace="+0%"> mapping to <embed> marginBottom property
+PASS <embed vspace="."> mapping to <embed> marginBottom property
+PASS <embed vspace=".%"> mapping to <embed> marginBottom property
+PASS <embed vspace=".x"> mapping to <embed> marginBottom property
+PASS <embed vspace=".5"> mapping to <embed> marginBottom property
+PASS <embed vspace=".5%"> mapping to <embed> marginBottom property
+PASS <img hspace="200"> mapping to <img> marginLeft property
+PASS <img hspace="1007"> mapping to <img> marginLeft property
+PASS <img hspace="   00523   "> mapping to <img> marginLeft property
+PASS <img hspace="200.25"> mapping to <img> marginLeft property
+PASS <img hspace="200.7"> mapping to <img> marginLeft property
+PASS <img hspace="200."> mapping to <img> marginLeft property
+PASS <img hspace="200in"> mapping to <img> marginLeft property
+PASS <img hspace="200.25in"> mapping to <img> marginLeft property
+PASS <img hspace="200 %"> mapping to <img> marginLeft property
+PASS <img hspace="200 abc"> mapping to <img> marginLeft property
+PASS <img hspace="200%"> mapping to <img> marginLeft property
+PASS <img hspace="200%abc"> mapping to <img> marginLeft property
+PASS <img hspace="200.25%"> mapping to <img> marginLeft property
+PASS <img hspace="200.%"> mapping to <img> marginLeft property
+PASS <img hspace="20.25e2"> mapping to <img> marginLeft property
+PASS <img hspace="20.25E2"> mapping to <img> marginLeft property
+PASS <img hspace="0"> mapping to <img> marginLeft property
+PASS <img hspace="0%"> mapping to <img> marginLeft property
+PASS <img hspace="0px"> mapping to <img> marginLeft property
+PASS <img hspace="-0"> mapping to <img> marginLeft property
+PASS <img hspace="-0%"> mapping to <img> marginLeft property
+PASS <img hspace="-200"> mapping to <img> marginLeft property
+PASS <img hspace="-200px"> mapping to <img> marginLeft property
+PASS <img hspace="   -200"> mapping to <img> marginLeft property
+PASS <img hspace="+-200"> mapping to <img> marginLeft property
+PASS <img hspace="-+200"> mapping to <img> marginLeft property
+PASS <img hspace="-200%"> mapping to <img> marginLeft property
+PASS <img hspace="+200"> mapping to <img> marginLeft property
+PASS <img hspace="   +200in    "> mapping to <img> marginLeft property
+PASS <img hspace="   +200.25in    "> mapping to <img> marginLeft property
+PASS <img hspace="+200%"> mapping to <img> marginLeft property
+PASS <img hspace="   +200.25%    "> mapping to <img> marginLeft property
+PASS <img hspace="   +200.25%abc"> mapping to <img> marginLeft property
+PASS <img hspace="+0"> mapping to <img> marginLeft property
+PASS <img hspace="+0%"> mapping to <img> marginLeft property
+PASS <img hspace="."> mapping to <img> marginLeft property
+PASS <img hspace=".%"> mapping to <img> marginLeft property
+PASS <img hspace=".x"> mapping to <img> marginLeft property
+PASS <img hspace=".5"> mapping to <img> marginLeft property
+PASS <img hspace=".5%"> mapping to <img> marginLeft property
+PASS <img hspace="200"> mapping to <img> marginRight property
+PASS <img hspace="1007"> mapping to <img> marginRight property
+PASS <img hspace="   00523   "> mapping to <img> marginRight property
+PASS <img hspace="200.25"> mapping to <img> marginRight property
+PASS <img hspace="200.7"> mapping to <img> marginRight property
+PASS <img hspace="200."> mapping to <img> marginRight property
+PASS <img hspace="200in"> mapping to <img> marginRight property
+PASS <img hspace="200.25in"> mapping to <img> marginRight property
+PASS <img hspace="200 %"> mapping to <img> marginRight property
+PASS <img hspace="200 abc"> mapping to <img> marginRight property
+PASS <img hspace="200%"> mapping to <img> marginRight property
+PASS <img hspace="200%abc"> mapping to <img> marginRight property
+PASS <img hspace="200.25%"> mapping to <img> marginRight property
+PASS <img hspace="200.%"> mapping to <img> marginRight property
+PASS <img hspace="20.25e2"> mapping to <img> marginRight property
+PASS <img hspace="20.25E2"> mapping to <img> marginRight property
+PASS <img hspace="0"> mapping to <img> marginRight property
+PASS <img hspace="0%"> mapping to <img> marginRight property
+PASS <img hspace="0px"> mapping to <img> marginRight property
+PASS <img hspace="-0"> mapping to <img> marginRight property
+PASS <img hspace="-0%"> mapping to <img> marginRight property
+PASS <img hspace="-200"> mapping to <img> marginRight property
+PASS <img hspace="-200px"> mapping to <img> marginRight property
+PASS <img hspace="   -200"> mapping to <img> marginRight property
+PASS <img hspace="+-200"> mapping to <img> marginRight property
+PASS <img hspace="-+200"> mapping to <img> marginRight property
+PASS <img hspace="-200%"> mapping to <img> marginRight property
+PASS <img hspace="+200"> mapping to <img> marginRight property
+PASS <img hspace="   +200in    "> mapping to <img> marginRight property
+PASS <img hspace="   +200.25in    "> mapping to <img> marginRight property
+PASS <img hspace="+200%"> mapping to <img> marginRight property
+PASS <img hspace="   +200.25%    "> mapping to <img> marginRight property
+PASS <img hspace="   +200.25%abc"> mapping to <img> marginRight property
+PASS <img hspace="+0"> mapping to <img> marginRight property
+PASS <img hspace="+0%"> mapping to <img> marginRight property
+PASS <img hspace="."> mapping to <img> marginRight property
+PASS <img hspace=".%"> mapping to <img> marginRight property
+PASS <img hspace=".x"> mapping to <img> marginRight property
+PASS <img hspace=".5"> mapping to <img> marginRight property
+PASS <img hspace=".5%"> mapping to <img> marginRight property
+PASS <img vspace="200"> mapping to <img> marginTop property
+PASS <img vspace="1007"> mapping to <img> marginTop property
+PASS <img vspace="   00523   "> mapping to <img> marginTop property
+PASS <img vspace="200.25"> mapping to <img> marginTop property
+PASS <img vspace="200.7"> mapping to <img> marginTop property
+PASS <img vspace="200."> mapping to <img> marginTop property
+PASS <img vspace="200in"> mapping to <img> marginTop property
+PASS <img vspace="200.25in"> mapping to <img> marginTop property
+PASS <img vspace="200 %"> mapping to <img> marginTop property
+PASS <img vspace="200 abc"> mapping to <img> marginTop property
+PASS <img vspace="200%"> mapping to <img> marginTop property
+PASS <img vspace="200%abc"> mapping to <img> marginTop property
+PASS <img vspace="200.25%"> mapping to <img> marginTop property
+PASS <img vspace="200.%"> mapping to <img> marginTop property
+PASS <img vspace="20.25e2"> mapping to <img> marginTop property
+PASS <img vspace="20.25E2"> mapping to <img> marginTop property
+PASS <img vspace="0"> mapping to <img> marginTop property
+PASS <img vspace="0%"> mapping to <img> marginTop property
+PASS <img vspace="0px"> mapping to <img> marginTop property
+PASS <img vspace="-0"> mapping to <img> marginTop property
+PASS <img vspace="-0%"> mapping to <img> marginTop property
+PASS <img vspace="-200"> mapping to <img> marginTop property
+PASS <img vspace="-200px"> mapping to <img> marginTop property
+PASS <img vspace="   -200"> mapping to <img> marginTop property
+PASS <img vspace="+-200"> mapping to <img> marginTop property
+PASS <img vspace="-+200"> mapping to <img> marginTop property
+PASS <img vspace="-200%"> mapping to <img> marginTop property
+PASS <img vspace="+200"> mapping to <img> marginTop property
+PASS <img vspace="   +200in    "> mapping to <img> marginTop property
+PASS <img vspace="   +200.25in    "> mapping to <img> marginTop property
+PASS <img vspace="+200%"> mapping to <img> marginTop property
+PASS <img vspace="   +200.25%    "> mapping to <img> marginTop property
+PASS <img vspace="   +200.25%abc"> mapping to <img> marginTop property
+PASS <img vspace="+0"> mapping to <img> marginTop property
+PASS <img vspace="+0%"> mapping to <img> marginTop property
+PASS <img vspace="."> mapping to <img> marginTop property
+PASS <img vspace=".%"> mapping to <img> marginTop property
+PASS <img vspace=".x"> mapping to <img> marginTop property
+PASS <img vspace=".5"> mapping to <img> marginTop property
+PASS <img vspace=".5%"> mapping to <img> marginTop property
+PASS <img vspace="200"> mapping to <img> marginBottom property
+PASS <img vspace="1007"> mapping to <img> marginBottom property
+PASS <img vspace="   00523   "> mapping to <img> marginBottom property
+PASS <img vspace="200.25"> mapping to <img> marginBottom property
+PASS <img vspace="200.7"> mapping to <img> marginBottom property
+PASS <img vspace="200."> mapping to <img> marginBottom property
+PASS <img vspace="200in"> mapping to <img> marginBottom property
+PASS <img vspace="200.25in"> mapping to <img> marginBottom property
+PASS <img vspace="200 %"> mapping to <img> marginBottom property
+PASS <img vspace="200 abc"> mapping to <img> marginBottom property
+PASS <img vspace="200%"> mapping to <img> marginBottom property
+PASS <img vspace="200%abc"> mapping to <img> marginBottom property
+PASS <img vspace="200.25%"> mapping to <img> marginBottom property
+PASS <img vspace="200.%"> mapping to <img> marginBottom property
+PASS <img vspace="20.25e2"> mapping to <img> marginBottom property
+PASS <img vspace="20.25E2"> mapping to <img> marginBottom property
+PASS <img vspace="0"> mapping to <img> marginBottom property
+PASS <img vspace="0%"> mapping to <img> marginBottom property
+PASS <img vspace="0px"> mapping to <img> marginBottom property
+PASS <img vspace="-0"> mapping to <img> marginBottom property
+PASS <img vspace="-0%"> mapping to <img> marginBottom property
+PASS <img vspace="-200"> mapping to <img> marginBottom property
+PASS <img vspace="-200px"> mapping to <img> marginBottom property
+PASS <img vspace="   -200"> mapping to <img> marginBottom property
+PASS <img vspace="+-200"> mapping to <img> marginBottom property
+PASS <img vspace="-+200"> mapping to <img> marginBottom property
+PASS <img vspace="-200%"> mapping to <img> marginBottom property
+PASS <img vspace="+200"> mapping to <img> marginBottom property
+PASS <img vspace="   +200in    "> mapping to <img> marginBottom property
+PASS <img vspace="   +200.25in    "> mapping to <img> marginBottom property
+PASS <img vspace="+200%"> mapping to <img> marginBottom property
+PASS <img vspace="   +200.25%    "> mapping to <img> marginBottom property
+PASS <img vspace="   +200.25%abc"> mapping to <img> marginBottom property
+PASS <img vspace="+0"> mapping to <img> marginBottom property
+PASS <img vspace="+0%"> mapping to <img> marginBottom property
+PASS <img vspace="."> mapping to <img> marginBottom property
+PASS <img vspace=".%"> mapping to <img> marginBottom property
+PASS <img vspace=".x"> mapping to <img> marginBottom property
+PASS <img vspace=".5"> mapping to <img> marginBottom property
+PASS <img vspace=".5%"> mapping to <img> marginBottom property
+PASS <object hspace="200"> mapping to <object> marginLeft property
+PASS <object hspace="1007"> mapping to <object> marginLeft property
+PASS <object hspace="   00523   "> mapping to <object> marginLeft property
+PASS <object hspace="200.25"> mapping to <object> marginLeft property
+PASS <object hspace="200.7"> mapping to <object> marginLeft property
+PASS <object hspace="200."> mapping to <object> marginLeft property
+PASS <object hspace="200in"> mapping to <object> marginLeft property
+PASS <object hspace="200.25in"> mapping to <object> marginLeft property
+PASS <object hspace="200 %"> mapping to <object> marginLeft property
+PASS <object hspace="200 abc"> mapping to <object> marginLeft property
+PASS <object hspace="200%"> mapping to <object> marginLeft property
+PASS <object hspace="200%abc"> mapping to <object> marginLeft property
+PASS <object hspace="200.25%"> mapping to <object> marginLeft property
+PASS <object hspace="200.%"> mapping to <object> marginLeft property
+PASS <object hspace="20.25e2"> mapping to <object> marginLeft property
+PASS <object hspace="20.25E2"> mapping to <object> marginLeft property
+PASS <object hspace="0"> mapping to <object> marginLeft property
+PASS <object hspace="0%"> mapping to <object> marginLeft property
+PASS <object hspace="0px"> mapping to <object> marginLeft property
+PASS <object hspace="-0"> mapping to <object> marginLeft property
+PASS <object hspace="-0%"> mapping to <object> marginLeft property
+PASS <object hspace="-200"> mapping to <object> marginLeft property
+PASS <object hspace="-200px"> mapping to <object> marginLeft property
+PASS <object hspace="   -200"> mapping to <object> marginLeft property
+PASS <object hspace="+-200"> mapping to <object> marginLeft property
+PASS <object hspace="-+200"> mapping to <object> marginLeft property
+PASS <object hspace="-200%"> mapping to <object> marginLeft property
+PASS <object hspace="+200"> mapping to <object> marginLeft property
+PASS <object hspace="   +200in    "> mapping to <object> marginLeft property
+PASS <object hspace="   +200.25in    "> mapping to <object> marginLeft property
+PASS <object hspace="+200%"> mapping to <object> marginLeft property
+PASS <object hspace="   +200.25%    "> mapping to <object> marginLeft property
+PASS <object hspace="   +200.25%abc"> mapping to <object> marginLeft property
+PASS <object hspace="+0"> mapping to <object> marginLeft property
+PASS <object hspace="+0%"> mapping to <object> marginLeft property
+PASS <object hspace="."> mapping to <object> marginLeft property
+PASS <object hspace=".%"> mapping to <object> marginLeft property
+PASS <object hspace=".x"> mapping to <object> marginLeft property
+PASS <object hspace=".5"> mapping to <object> marginLeft property
+PASS <object hspace=".5%"> mapping to <object> marginLeft property
+PASS <object hspace="200"> mapping to <object> marginRight property
+PASS <object hspace="1007"> mapping to <object> marginRight property
+PASS <object hspace="   00523   "> mapping to <object> marginRight property
+PASS <object hspace="200.25"> mapping to <object> marginRight property
+PASS <object hspace="200.7"> mapping to <object> marginRight property
+PASS <object hspace="200."> mapping to <object> marginRight property
+PASS <object hspace="200in"> mapping to <object> marginRight property
+PASS <object hspace="200.25in"> mapping to <object> marginRight property
+PASS <object hspace="200 %"> mapping to <object> marginRight property
+PASS <object hspace="200 abc"> mapping to <object> marginRight property
+PASS <object hspace="200%"> mapping to <object> marginRight property
+PASS <object hspace="200%abc"> mapping to <object> marginRight property
+PASS <object hspace="200.25%"> mapping to <object> marginRight property
+PASS <object hspace="200.%"> mapping to <object> marginRight property
+PASS <object hspace="20.25e2"> mapping to <object> marginRight property
+PASS <object hspace="20.25E2"> mapping to <object> marginRight property
+PASS <object hspace="0"> mapping to <object> marginRight property
+PASS <object hspace="0%"> mapping to <object> marginRight property
+PASS <object hspace="0px"> mapping to <object> marginRight property
+PASS <object hspace="-0"> mapping to <object> marginRight property
+PASS <object hspace="-0%"> mapping to <object> marginRight property
+PASS <object hspace="-200"> mapping to <object> marginRight property
+PASS <object hspace="-200px"> mapping to <object> marginRight property
+PASS <object hspace="   -200"> mapping to <object> marginRight property
+PASS <object hspace="+-200"> mapping to <object> marginRight property
+PASS <object hspace="-+200"> mapping to <object> marginRight property
+PASS <object hspace="-200%"> mapping to <object> marginRight property
+PASS <object hspace="+200"> mapping to <object> marginRight property
+PASS <object hspace="   +200in    "> mapping to <object> marginRight property
+PASS <object hspace="   +200.25in    "> mapping to <object> marginRight property
+PASS <object hspace="+200%"> mapping to <object> marginRight property
+PASS <object hspace="   +200.25%    "> mapping to <object> marginRight property
+PASS <object hspace="   +200.25%abc"> mapping to <object> marginRight property
+PASS <object hspace="+0"> mapping to <object> marginRight property
+PASS <object hspace="+0%"> mapping to <object> marginRight property
+PASS <object hspace="."> mapping to <object> marginRight property
+PASS <object hspace=".%"> mapping to <object> marginRight property
+PASS <object hspace=".x"> mapping to <object> marginRight property
+PASS <object hspace=".5"> mapping to <object> marginRight property
+PASS <object hspace=".5%"> mapping to <object> marginRight property
+PASS <object vspace="200"> mapping to <object> marginTop property
+PASS <object vspace="1007"> mapping to <object> marginTop property
+PASS <object vspace="   00523   "> mapping to <object> marginTop property
+PASS <object vspace="200.25"> mapping to <object> marginTop property
+PASS <object vspace="200.7"> mapping to <object> marginTop property
+PASS <object vspace="200."> mapping to <object> marginTop property
+PASS <object vspace="200in"> mapping to <object> marginTop property
+PASS <object vspace="200.25in"> mapping to <object> marginTop property
+PASS <object vspace="200 %"> mapping to <object> marginTop property
+PASS <object vspace="200 abc"> mapping to <object> marginTop property
+PASS <object vspace="200%"> mapping to <object> marginTop property
+PASS <object vspace="200%abc"> mapping to <object> marginTop property
+PASS <object vspace="200.25%"> mapping to <object> marginTop property
+PASS <object vspace="200.%"> mapping to <object> marginTop property
+PASS <object vspace="20.25e2"> mapping to <object> marginTop property
+PASS <object vspace="20.25E2"> mapping to <object> marginTop property
+PASS <object vspace="0"> mapping to <object> marginTop property
+PASS <object vspace="0%"> mapping to <object> marginTop property
+PASS <object vspace="0px"> mapping to <object> marginTop property
+PASS <object vspace="-0"> mapping to <object> marginTop property
+PASS <object vspace="-0%"> mapping to <object> marginTop property
+PASS <object vspace="-200"> mapping to <object> marginTop property
+PASS <object vspace="-200px"> mapping to <object> marginTop property
+PASS <object vspace="   -200"> mapping to <object> marginTop property
+PASS <object vspace="+-200"> mapping to <object> marginTop property
+PASS <object vspace="-+200"> mapping to <object> marginTop property
+PASS <object vspace="-200%"> mapping to <object> marginTop property
+PASS <object vspace="+200"> mapping to <object> marginTop property
+PASS <object vspace="   +200in    "> mapping to <object> marginTop property
+PASS <object vspace="   +200.25in    "> mapping to <object> marginTop property
+PASS <object vspace="+200%"> mapping to <object> marginTop property
+PASS <object vspace="   +200.25%    "> mapping to <object> marginTop property
+PASS <object vspace="   +200.25%abc"> mapping to <object> marginTop property
+PASS <object vspace="+0"> mapping to <object> marginTop property
+PASS <object vspace="+0%"> mapping to <object> marginTop property
+PASS <object vspace="."> mapping to <object> marginTop property
+PASS <object vspace=".%"> mapping to <object> marginTop property
+PASS <object vspace=".x"> mapping to <object> marginTop property
+PASS <object vspace=".5"> mapping to <object> marginTop property
+PASS <object vspace=".5%"> mapping to <object> marginTop property
+PASS <object vspace="200"> mapping to <object> marginBottom property
+PASS <object vspace="1007"> mapping to <object> marginBottom property
+PASS <object vspace="   00523   "> mapping to <object> marginBottom property
+PASS <object vspace="200.25"> mapping to <object> marginBottom property
+PASS <object vspace="200.7"> mapping to <object> marginBottom property
+PASS <object vspace="200."> mapping to <object> marginBottom property
+PASS <object vspace="200in"> mapping to <object> marginBottom property
+PASS <object vspace="200.25in"> mapping to <object> marginBottom property
+PASS <object vspace="200 %"> mapping to <object> marginBottom property
+PASS <object vspace="200 abc"> mapping to <object> marginBottom property
+PASS <object vspace="200%"> mapping to <object> marginBottom property
+PASS <object vspace="200%abc"> mapping to <object> marginBottom property
+PASS <object vspace="200.25%"> mapping to <object> marginBottom property
+PASS <object vspace="200.%"> mapping to <object> marginBottom property
+PASS <object vspace="20.25e2"> mapping to <object> marginBottom property
+PASS <object vspace="20.25E2"> mapping to <object> marginBottom property
+PASS <object vspace="0"> mapping to <object> marginBottom property
+PASS <object vspace="0%"> mapping to <object> marginBottom property
+PASS <object vspace="0px"> mapping to <object> marginBottom property
+PASS <object vspace="-0"> mapping to <object> marginBottom property
+PASS <object vspace="-0%"> mapping to <object> marginBottom property
+PASS <object vspace="-200"> mapping to <object> marginBottom property
+PASS <object vspace="-200px"> mapping to <object> marginBottom property
+PASS <object vspace="   -200"> mapping to <object> marginBottom property
+PASS <object vspace="+-200"> mapping to <object> marginBottom property
+PASS <object vspace="-+200"> mapping to <object> marginBottom property
+PASS <object vspace="-200%"> mapping to <object> marginBottom property
+PASS <object vspace="+200"> mapping to <object> marginBottom property
+PASS <object vspace="   +200in    "> mapping to <object> marginBottom property
+PASS <object vspace="   +200.25in    "> mapping to <object> marginBottom property
+PASS <object vspace="+200%"> mapping to <object> marginBottom property
+PASS <object vspace="   +200.25%    "> mapping to <object> marginBottom property
+PASS <object vspace="   +200.25%abc"> mapping to <object> marginBottom property
+PASS <object vspace="+0"> mapping to <object> marginBottom property
+PASS <object vspace="+0%"> mapping to <object> marginBottom property
+PASS <object vspace="."> mapping to <object> marginBottom property
+PASS <object vspace=".%"> mapping to <object> marginBottom property
+PASS <object vspace=".x"> mapping to <object> marginBottom property
+PASS <object vspace=".5"> mapping to <object> marginBottom property
+PASS <object vspace=".5%"> mapping to <object> marginBottom property
+PASS <input hspace="200"> mapping to <input> marginLeft property
+PASS <input hspace="1007"> mapping to <input> marginLeft property
+PASS <input hspace="   00523   "> mapping to <input> marginLeft property
+PASS <input hspace="200.25"> mapping to <input> marginLeft property
+PASS <input hspace="200.7"> mapping to <input> marginLeft property
+PASS <input hspace="200."> mapping to <input> marginLeft property
+PASS <input hspace="200in"> mapping to <input> marginLeft property
+PASS <input hspace="200.25in"> mapping to <input> marginLeft property
+PASS <input hspace="200 %"> mapping to <input> marginLeft property
+PASS <input hspace="200 abc"> mapping to <input> marginLeft property
+PASS <input hspace="200%"> mapping to <input> marginLeft property
+PASS <input hspace="200%abc"> mapping to <input> marginLeft property
+PASS <input hspace="200.25%"> mapping to <input> marginLeft property
+PASS <input hspace="200.%"> mapping to <input> marginLeft property
+PASS <input hspace="20.25e2"> mapping to <input> marginLeft property
+PASS <input hspace="20.25E2"> mapping to <input> marginLeft property
+PASS <input hspace="0"> mapping to <input> marginLeft property
+PASS <input hspace="0%"> mapping to <input> marginLeft property
+PASS <input hspace="0px"> mapping to <input> marginLeft property
+PASS <input hspace="-0"> mapping to <input> marginLeft property
+PASS <input hspace="-0%"> mapping to <input> marginLeft property
+PASS <input hspace="-200"> mapping to <input> marginLeft property
+PASS <input hspace="-200px"> mapping to <input> marginLeft property
+PASS <input hspace="   -200"> mapping to <input> marginLeft property
+PASS <input hspace="+-200"> mapping to <input> marginLeft property
+PASS <input hspace="-+200"> mapping to <input> marginLeft property
+PASS <input hspace="-200%"> mapping to <input> marginLeft property
+PASS <input hspace="+200"> mapping to <input> marginLeft property
+PASS <input hspace="   +200in    "> mapping to <input> marginLeft property
+PASS <input hspace="   +200.25in    "> mapping to <input> marginLeft property
+PASS <input hspace="+200%"> mapping to <input> marginLeft property
+PASS <input hspace="   +200.25%    "> mapping to <input> marginLeft property
+PASS <input hspace="   +200.25%abc"> mapping to <input> marginLeft property
+PASS <input hspace="+0"> mapping to <input> marginLeft property
+PASS <input hspace="+0%"> mapping to <input> marginLeft property
+PASS <input hspace="."> mapping to <input> marginLeft property
+PASS <input hspace=".%"> mapping to <input> marginLeft property
+PASS <input hspace=".x"> mapping to <input> marginLeft property
+PASS <input hspace=".5"> mapping to <input> marginLeft property
+PASS <input hspace=".5%"> mapping to <input> marginLeft property
+PASS <input hspace="200"> mapping to <input> marginRight property
+PASS <input hspace="1007"> mapping to <input> marginRight property
+PASS <input hspace="   00523   "> mapping to <input> marginRight property
+PASS <input hspace="200.25"> mapping to <input> marginRight property
+PASS <input hspace="200.7"> mapping to <input> marginRight property
+PASS <input hspace="200."> mapping to <input> marginRight property
+PASS <input hspace="200in"> mapping to <input> marginRight property
+PASS <input hspace="200.25in"> mapping to <input> marginRight property
+PASS <input hspace="200 %"> mapping to <input> marginRight property
+PASS <input hspace="200 abc"> mapping to <input> marginRight property
+PASS <input hspace="200%"> mapping to <input> marginRight property
+PASS <input hspace="200%abc"> mapping to <input> marginRight property
+PASS <input hspace="200.25%"> mapping to <input> marginRight property
+PASS <input hspace="200.%"> mapping to <input> marginRight property
+PASS <input hspace="20.25e2"> mapping to <input> marginRight property
+PASS <input hspace="20.25E2"> mapping to <input> marginRight property
+PASS <input hspace="0"> mapping to <input> marginRight property
+PASS <input hspace="0%"> mapping to <input> marginRight property
+PASS <input hspace="0px"> mapping to <input> marginRight property
+PASS <input hspace="-0"> mapping to <input> marginRight property
+PASS <input hspace="-0%"> mapping to <input> marginRight property
+PASS <input hspace="-200"> mapping to <input> marginRight property
+PASS <input hspace="-200px"> mapping to <input> marginRight property
+PASS <input hspace="   -200"> mapping to <input> marginRight property
+PASS <input hspace="+-200"> mapping to <input> marginRight property
+PASS <input hspace="-+200"> mapping to <input> marginRight property
+PASS <input hspace="-200%"> mapping to <input> marginRight property
+PASS <input hspace="+200"> mapping to <input> marginRight property
+PASS <input hspace="   +200in    "> mapping to <input> marginRight property
+PASS <input hspace="   +200.25in    "> mapping to <input> marginRight property
+PASS <input hspace="+200%"> mapping to <input> marginRight property
+PASS <input hspace="   +200.25%    "> mapping to <input> marginRight property
+PASS <input hspace="   +200.25%abc"> mapping to <input> marginRight property
+PASS <input hspace="+0"> mapping to <input> marginRight property
+PASS <input hspace="+0%"> mapping to <input> marginRight property
+PASS <input hspace="."> mapping to <input> marginRight property
+PASS <input hspace=".%"> mapping to <input> marginRight property
+PASS <input hspace=".x"> mapping to <input> marginRight property
+PASS <input hspace=".5"> mapping to <input> marginRight property
+PASS <input hspace=".5%"> mapping to <input> marginRight property
+PASS <input vspace="200"> mapping to <input> marginTop property
+PASS <input vspace="1007"> mapping to <input> marginTop property
+PASS <input vspace="   00523   "> mapping to <input> marginTop property
+PASS <input vspace="200.25"> mapping to <input> marginTop property
+PASS <input vspace="200.7"> mapping to <input> marginTop property
+PASS <input vspace="200."> mapping to <input> marginTop property
+PASS <input vspace="200in"> mapping to <input> marginTop property
+PASS <input vspace="200.25in"> mapping to <input> marginTop property
+PASS <input vspace="200 %"> mapping to <input> marginTop property
+PASS <input vspace="200 abc"> mapping to <input> marginTop property
+PASS <input vspace="200%"> mapping to <input> marginTop property
+PASS <input vspace="200%abc"> mapping to <input> marginTop property
+PASS <input vspace="200.25%"> mapping to <input> marginTop property
+PASS <input vspace="200.%"> mapping to <input> marginTop property
+PASS <input vspace="20.25e2"> mapping to <input> marginTop property
+PASS <input vspace="20.25E2"> mapping to <input> marginTop property
+PASS <input vspace="0"> mapping to <input> marginTop property
+PASS <input vspace="0%"> mapping to <input> marginTop property
+PASS <input vspace="0px"> mapping to <input> marginTop property
+PASS <input vspace="-0"> mapping to <input> marginTop property
+PASS <input vspace="-0%"> mapping to <input> marginTop property
+PASS <input vspace="-200"> mapping to <input> marginTop property
+PASS <input vspace="-200px"> mapping to <input> marginTop property
+PASS <input vspace="   -200"> mapping to <input> marginTop property
+PASS <input vspace="+-200"> mapping to <input> marginTop property
+PASS <input vspace="-+200"> mapping to <input> marginTop property
+PASS <input vspace="-200%"> mapping to <input> marginTop property
+PASS <input vspace="+200"> mapping to <input> marginTop property
+PASS <input vspace="   +200in    "> mapping to <input> marginTop property
+PASS <input vspace="   +200.25in    "> mapping to <input> marginTop property
+PASS <input vspace="+200%"> mapping to <input> marginTop property
+PASS <input vspace="   +200.25%    "> mapping to <input> marginTop property
+PASS <input vspace="   +200.25%abc"> mapping to <input> marginTop property
+PASS <input vspace="+0"> mapping to <input> marginTop property
+PASS <input vspace="+0%"> mapping to <input> marginTop property
+PASS <input vspace="."> mapping to <input> marginTop property
+PASS <input vspace=".%"> mapping to <input> marginTop property
+PASS <input vspace=".x"> mapping to <input> marginTop property
+PASS <input vspace=".5"> mapping to <input> marginTop property
+PASS <input vspace=".5%"> mapping to <input> marginTop property
+PASS <input vspace="200"> mapping to <input> marginBottom property
+PASS <input vspace="1007"> mapping to <input> marginBottom property
+PASS <input vspace="   00523   "> mapping to <input> marginBottom property
+PASS <input vspace="200.25"> mapping to <input> marginBottom property
+PASS <input vspace="200.7"> mapping to <input> marginBottom property
+PASS <input vspace="200."> mapping to <input> marginBottom property
+PASS <input vspace="200in"> mapping to <input> marginBottom property
+PASS <input vspace="200.25in"> mapping to <input> marginBottom property
+PASS <input vspace="200 %"> mapping to <input> marginBottom property
+PASS <input vspace="200 abc"> mapping to <input> marginBottom property
+PASS <input vspace="200%"> mapping to <input> marginBottom property
+PASS <input vspace="200%abc"> mapping to <input> marginBottom property
+PASS <input vspace="200.25%"> mapping to <input> marginBottom property
+PASS <input vspace="200.%"> mapping to <input> marginBottom property
+PASS <input vspace="20.25e2"> mapping to <input> marginBottom property
+PASS <input vspace="20.25E2"> mapping to <input> marginBottom property
+PASS <input vspace="0"> mapping to <input> marginBottom property
+PASS <input vspace="0%"> mapping to <input> marginBottom property
+PASS <input vspace="0px"> mapping to <input> marginBottom property
+PASS <input vspace="-0"> mapping to <input> marginBottom property
+PASS <input vspace="-0%"> mapping to <input> marginBottom property
+PASS <input vspace="-200"> mapping to <input> marginBottom property
+PASS <input vspace="-200px"> mapping to <input> marginBottom property
+PASS <input vspace="   -200"> mapping to <input> marginBottom property
+PASS <input vspace="+-200"> mapping to <input> marginBottom property
+PASS <input vspace="-+200"> mapping to <input> marginBottom property
+PASS <input vspace="-200%"> mapping to <input> marginBottom property
+PASS <input vspace="+200"> mapping to <input> marginBottom property
+PASS <input vspace="   +200in    "> mapping to <input> marginBottom property
+PASS <input vspace="   +200.25in    "> mapping to <input> marginBottom property
+PASS <input vspace="+200%"> mapping to <input> marginBottom property
+PASS <input vspace="   +200.25%    "> mapping to <input> marginBottom property
+PASS <input vspace="   +200.25%abc"> mapping to <input> marginBottom property
+PASS <input vspace="+0"> mapping to <input> marginBottom property
+PASS <input vspace="+0%"> mapping to <input> marginBottom property
+PASS <input vspace="."> mapping to <input> marginBottom property
+PASS <input vspace=".%"> mapping to <input> marginBottom property
+PASS <input vspace=".x"> mapping to <input> marginBottom property
+PASS <input vspace=".5"> mapping to <input> marginBottom property
+PASS <input vspace=".5%"> mapping to <input> marginBottom property
+PASS <marquee hspace="200"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="1007"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="   00523   "> mapping to <marquee> marginLeft property
+PASS <marquee hspace="200.25"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="200.7"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="200."> mapping to <marquee> marginLeft property
+PASS <marquee hspace="200in"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="200.25in"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="200 %"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="200 abc"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="200%"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="200%abc"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="200.25%"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="200.%"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="20.25e2"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="20.25E2"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="0"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="0%"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="0px"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="-0"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="-0%"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="-200"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="-200px"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="   -200"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="+-200"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="-+200"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="-200%"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="+200"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="   +200in    "> mapping to <marquee> marginLeft property
+PASS <marquee hspace="   +200.25in    "> mapping to <marquee> marginLeft property
+PASS <marquee hspace="+200%"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="   +200.25%    "> mapping to <marquee> marginLeft property
+PASS <marquee hspace="   +200.25%abc"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="+0"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="+0%"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="."> mapping to <marquee> marginLeft property
+PASS <marquee hspace=".%"> mapping to <marquee> marginLeft property
+PASS <marquee hspace=".x"> mapping to <marquee> marginLeft property
+PASS <marquee hspace=".5"> mapping to <marquee> marginLeft property
+PASS <marquee hspace=".5%"> mapping to <marquee> marginLeft property
+PASS <marquee hspace="200"> mapping to <marquee> marginRight property
+PASS <marquee hspace="1007"> mapping to <marquee> marginRight property
+PASS <marquee hspace="   00523   "> mapping to <marquee> marginRight property
+PASS <marquee hspace="200.25"> mapping to <marquee> marginRight property
+PASS <marquee hspace="200.7"> mapping to <marquee> marginRight property
+PASS <marquee hspace="200."> mapping to <marquee> marginRight property
+PASS <marquee hspace="200in"> mapping to <marquee> marginRight property
+PASS <marquee hspace="200.25in"> mapping to <marquee> marginRight property
+PASS <marquee hspace="200 %"> mapping to <marquee> marginRight property
+PASS <marquee hspace="200 abc"> mapping to <marquee> marginRight property
+PASS <marquee hspace="200%"> mapping to <marquee> marginRight property
+PASS <marquee hspace="200%abc"> mapping to <marquee> marginRight property
+PASS <marquee hspace="200.25%"> mapping to <marquee> marginRight property
+PASS <marquee hspace="200.%"> mapping to <marquee> marginRight property
+PASS <marquee hspace="20.25e2"> mapping to <marquee> marginRight property
+PASS <marquee hspace="20.25E2"> mapping to <marquee> marginRight property
+PASS <marquee hspace="0"> mapping to <marquee> marginRight property
+PASS <marquee hspace="0%"> mapping to <marquee> marginRight property
+PASS <marquee hspace="0px"> mapping to <marquee> marginRight property
+PASS <marquee hspace="-0"> mapping to <marquee> marginRight property
+PASS <marquee hspace="-0%"> mapping to <marquee> marginRight property
+PASS <marquee hspace="-200"> mapping to <marquee> marginRight property
+PASS <marquee hspace="-200px"> mapping to <marquee> marginRight property
+PASS <marquee hspace="   -200"> mapping to <marquee> marginRight property
+PASS <marquee hspace="+-200"> mapping to <marquee> marginRight property
+PASS <marquee hspace="-+200"> mapping to <marquee> marginRight property
+PASS <marquee hspace="-200%"> mapping to <marquee> marginRight property
+PASS <marquee hspace="+200"> mapping to <marquee> marginRight property
+PASS <marquee hspace="   +200in    "> mapping to <marquee> marginRight property
+PASS <marquee hspace="   +200.25in    "> mapping to <marquee> marginRight property
+PASS <marquee hspace="+200%"> mapping to <marquee> marginRight property
+PASS <marquee hspace="   +200.25%    "> mapping to <marquee> marginRight property
+PASS <marquee hspace="   +200.25%abc"> mapping to <marquee> marginRight property
+PASS <marquee hspace="+0"> mapping to <marquee> marginRight property
+PASS <marquee hspace="+0%"> mapping to <marquee> marginRight property
+PASS <marquee hspace="."> mapping to <marquee> marginRight property
+PASS <marquee hspace=".%"> mapping to <marquee> marginRight property
+PASS <marquee hspace=".x"> mapping to <marquee> marginRight property
+PASS <marquee hspace=".5"> mapping to <marquee> marginRight property
+PASS <marquee hspace=".5%"> mapping to <marquee> marginRight property
+PASS <marquee vspace="200"> mapping to <marquee> marginTop property
+PASS <marquee vspace="1007"> mapping to <marquee> marginTop property
+PASS <marquee vspace="   00523   "> mapping to <marquee> marginTop property
+PASS <marquee vspace="200.25"> mapping to <marquee> marginTop property
+PASS <marquee vspace="200.7"> mapping to <marquee> marginTop property
+PASS <marquee vspace="200."> mapping to <marquee> marginTop property
+PASS <marquee vspace="200in"> mapping to <marquee> marginTop property
+PASS <marquee vspace="200.25in"> mapping to <marquee> marginTop property
+PASS <marquee vspace="200 %"> mapping to <marquee> marginTop property
+PASS <marquee vspace="200 abc"> mapping to <marquee> marginTop property
+PASS <marquee vspace="200%"> mapping to <marquee> marginTop property
+PASS <marquee vspace="200%abc"> mapping to <marquee> marginTop property
+PASS <marquee vspace="200.25%"> mapping to <marquee> marginTop property
+PASS <marquee vspace="200.%"> mapping to <marquee> marginTop property
+PASS <marquee vspace="20.25e2"> mapping to <marquee> marginTop property
+PASS <marquee vspace="20.25E2"> mapping to <marquee> marginTop property
+PASS <marquee vspace="0"> mapping to <marquee> marginTop property
+PASS <marquee vspace="0%"> mapping to <marquee> marginTop property
+PASS <marquee vspace="0px"> mapping to <marquee> marginTop property
+PASS <marquee vspace="-0"> mapping to <marquee> marginTop property
+PASS <marquee vspace="-0%"> mapping to <marquee> marginTop property
+PASS <marquee vspace="-200"> mapping to <marquee> marginTop property
+PASS <marquee vspace="-200px"> mapping to <marquee> marginTop property
+PASS <marquee vspace="   -200"> mapping to <marquee> marginTop property
+PASS <marquee vspace="+-200"> mapping to <marquee> marginTop property
+PASS <marquee vspace="-+200"> mapping to <marquee> marginTop property
+PASS <marquee vspace="-200%"> mapping to <marquee> marginTop property
+PASS <marquee vspace="+200"> mapping to <marquee> marginTop property
+PASS <marquee vspace="   +200in    "> mapping to <marquee> marginTop property
+PASS <marquee vspace="   +200.25in    "> mapping to <marquee> marginTop property
+PASS <marquee vspace="+200%"> mapping to <marquee> marginTop property
+PASS <marquee vspace="   +200.25%    "> mapping to <marquee> marginTop property
+PASS <marquee vspace="   +200.25%abc"> mapping to <marquee> marginTop property
+PASS <marquee vspace="+0"> mapping to <marquee> marginTop property
+PASS <marquee vspace="+0%"> mapping to <marquee> marginTop property
+PASS <marquee vspace="."> mapping to <marquee> marginTop property
+PASS <marquee vspace=".%"> mapping to <marquee> marginTop property
+PASS <marquee vspace=".x"> mapping to <marquee> marginTop property
+PASS <marquee vspace=".5"> mapping to <marquee> marginTop property
+PASS <marquee vspace=".5%"> mapping to <marquee> marginTop property
+PASS <marquee vspace="200"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="1007"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="   00523   "> mapping to <marquee> marginBottom property
+PASS <marquee vspace="200.25"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="200.7"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="200."> mapping to <marquee> marginBottom property
+PASS <marquee vspace="200in"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="200.25in"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="200 %"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="200 abc"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="200%"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="200%abc"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="200.25%"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="200.%"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="20.25e2"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="20.25E2"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="0"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="0%"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="0px"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="-0"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="-0%"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="-200"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="-200px"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="   -200"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="+-200"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="-+200"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="-200%"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="+200"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="   +200in    "> mapping to <marquee> marginBottom property
+PASS <marquee vspace="   +200.25in    "> mapping to <marquee> marginBottom property
+PASS <marquee vspace="+200%"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="   +200.25%    "> mapping to <marquee> marginBottom property
+PASS <marquee vspace="   +200.25%abc"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="+0"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="+0%"> mapping to <marquee> marginBottom property
+PASS <marquee vspace="."> mapping to <marquee> marginBottom property
+PASS <marquee vspace=".%"> mapping to <marquee> marginBottom property
+PASS <marquee vspace=".x"> mapping to <marquee> marginBottom property
+PASS <marquee vspace=".5"> mapping to <marquee> marginBottom property
+PASS <marquee vspace=".5%"> mapping to <marquee> marginBottom property
+PASS <source width="200"> mapping to <img> width property
+PASS <source width="1007"> mapping to <img> width property
+PASS <source width="   00523   "> mapping to <img> width property
+PASS <source width="200.25"> mapping to <img> width property
+PASS <source width="200.7"> mapping to <img> width property
+PASS <source width="200."> mapping to <img> width property
+PASS <source width="200in"> mapping to <img> width property
+PASS <source width="200.25in"> mapping to <img> width property
+PASS <source width="200 %"> mapping to <img> width property
+PASS <source width="200 abc"> mapping to <img> width property
+PASS <source width="200%"> mapping to <img> width property
+PASS <source width="200%abc"> mapping to <img> width property
+PASS <source width="200.25%"> mapping to <img> width property
+PASS <source width="200.%"> mapping to <img> width property
+PASS <source width="20.25e2"> mapping to <img> width property
+PASS <source width="20.25E2"> mapping to <img> width property
+PASS <source width="0"> mapping to <img> width property
+PASS <source width="0%"> mapping to <img> width property
+PASS <source width="0px"> mapping to <img> width property
+PASS <source width="-0"> mapping to <img> width property
+PASS <source width="-0%"> mapping to <img> width property
+PASS <source width="-200"> mapping to <img> width property
+PASS <source width="-200px"> mapping to <img> width property
+PASS <source width="   -200"> mapping to <img> width property
+PASS <source width="+-200"> mapping to <img> width property
+PASS <source width="-+200"> mapping to <img> width property
+PASS <source width="-200%"> mapping to <img> width property
+PASS <source width="+200"> mapping to <img> width property
+PASS <source width="   +200in    "> mapping to <img> width property
+PASS <source width="   +200.25in    "> mapping to <img> width property
+PASS <source width="+200%"> mapping to <img> width property
+PASS <source width="   +200.25%    "> mapping to <img> width property
+PASS <source width="   +200.25%abc"> mapping to <img> width property
+PASS <source width="+0"> mapping to <img> width property
+PASS <source width="+0%"> mapping to <img> width property
+PASS <source width="."> mapping to <img> width property
+PASS <source width=".%"> mapping to <img> width property
+PASS <source width=".x"> mapping to <img> width property
+PASS <source width=".5"> mapping to <img> width property
+PASS <source width=".5%"> mapping to <img> width property
+PASS <source height="200"> mapping to <img> height property
+PASS <source height="1007"> mapping to <img> height property
+PASS <source height="   00523   "> mapping to <img> height property
+PASS <source height="200.25"> mapping to <img> height property
+PASS <source height="200.7"> mapping to <img> height property
+PASS <source height="200."> mapping to <img> height property
+PASS <source height="200in"> mapping to <img> height property
+PASS <source height="200.25in"> mapping to <img> height property
+PASS <source height="200 %"> mapping to <img> height property
+PASS <source height="200 abc"> mapping to <img> height property
+PASS <source height="200%"> mapping to <img> height property
+PASS <source height="200%abc"> mapping to <img> height property
+PASS <source height="200.25%"> mapping to <img> height property
+PASS <source height="200.%"> mapping to <img> height property
+PASS <source height="20.25e2"> mapping to <img> height property
+PASS <source height="20.25E2"> mapping to <img> height property
+PASS <source height="0"> mapping to <img> height property
+PASS <source height="0%"> mapping to <img> height property
+PASS <source height="0px"> mapping to <img> height property
+PASS <source height="-0"> mapping to <img> height property
+PASS <source height="-0%"> mapping to <img> height property
+PASS <source height="-200"> mapping to <img> height property
+PASS <source height="-200px"> mapping to <img> height property
+PASS <source height="   -200"> mapping to <img> height property
+PASS <source height="+-200"> mapping to <img> height property
+PASS <source height="-+200"> mapping to <img> height property
+PASS <source height="-200%"> mapping to <img> height property
+PASS <source height="+200"> mapping to <img> height property
+PASS <source height="   +200in    "> mapping to <img> height property
+PASS <source height="   +200.25in    "> mapping to <img> height property
+PASS <source height="+200%"> mapping to <img> height property
+PASS <source height="   +200.25%    "> mapping to <img> height property
+PASS <source height="   +200.25%abc"> mapping to <img> height property
+PASS <source height="+0"> mapping to <img> height property
+PASS <source height="+0%"> mapping to <img> height property
+PASS <source height="."> mapping to <img> height property
+PASS <source height=".%"> mapping to <img> height property
+PASS <source height=".x"> mapping to <img> height property
+PASS <source height=".5"> mapping to <img> height property
+PASS <source height=".5%"> mapping to <img> height property
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/generic/inspector-protocol/css/css-get-styles-for-node-expected.txt b/third_party/blink/web_tests/platform/generic/inspector-protocol/css/css-get-styles-for-node-expected.txt
index dd19a63..d63ad3552 100644
--- a/third_party/blink/web_tests/platform/generic/inspector-protocol/css/css-get-styles-for-node-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/inspector-protocol/css/css-get-styles-for-node-expected.txt
@@ -173,4 +173,18 @@
         value : initial
     }
 ]
+[
+    [0] : {
+        name : flex-grow
+        value : 1
+    }
+    [1] : {
+        name : flex-shrink
+        value : 1
+    }
+    [2] : {
+        name : flex-basis
+        value : 0%
+    }
+]
 
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium
index 9011d4f..a939545 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: 5b7bb37d41f45635fcb848841524cb18664336dd
+Version: 9dc4b83ca039bd24ac3d0655dd455e47ed4e8644
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/tools/binary_size/libsupersize/viewer/static/main.css b/tools/binary_size/libsupersize/viewer/static/main.css
index e441a16..2442031 100644
--- a/tools/binary_size/libsupersize/viewer/static/main.css
+++ b/tools/binary_size/libsupersize/viewer/static/main.css
@@ -166,7 +166,6 @@
   width: 0;
   height: 0;
 }
-
 [aria-expanded]>.node::before {
   /** Draw a 5x10 triangle */
   margin: 5px 7px 5px 8px;
@@ -179,6 +178,14 @@
   transform: rotate(90deg);
 }
 
+/** Tree leaves */
+:not([aria-expanded])>.node:focus {
+  background: #eef;
+}
+:not([aria-expanded])>.node:hover:focus {
+  background: #ddf;
+}
+
 /** Tree node sub items */
 .symbol-name {
   font-weight: 500;
diff --git a/tools/binary_size/libsupersize/viewer/static/tree-ui.js b/tools/binary_size/libsupersize/viewer/static/tree-ui.js
index 20107c6..f562704 100644
--- a/tools/binary_size/libsupersize/viewer/static/tree-ui.js
+++ b/tools/binary_size/libsupersize/viewer/static/tree-ui.js
@@ -131,6 +131,16 @@
   }
 
   /**
+   * Decides whether a given element is a leaf UI node in the tree view.
+   * @param {!HTMLElement} elt
+   * @return {boolean}
+   */
+  function _isLeafNode(elt) {
+    return elt.classList.contains('node') &&
+        elt.getAttribute('aria-expanded') === null;
+  }
+
+  /**
    * Tree view keydown event handler to move focus for the given element.
    * @param {KeyboardEvent} event Event passed from keydown event listener.
    */
@@ -310,6 +320,44 @@
   }
 
   /**
+   * Mousedown handler for an already-focused leaf node, to toggle it off.
+   * @param {!Event} event
+   */
+  function _handleRefocus(event) {
+    // Prevent click that would cause another focus event.
+    event.preventDefault();
+    const node = /** @type {!HTMLElement} */ (event.currentTarget);
+    node.blur();  // focusout handler will handle cleanup.
+  }
+
+  /**
+   * Focusin handler for a node.
+   * @param {!Event} event
+   */
+  function _handleFocusIn(event) {
+    const node = /** @type {!HTMLElement} */ (event.target);
+    if (_isLeafNode(node)) {
+      node.addEventListener('mousedown', _handleRefocus);
+    }
+    displayInfocard(_uiNodeData.get(node));
+    /** @type {HTMLElement} */ (event.currentTarget)
+        .parentElement.classList.add('focused');
+  }
+
+  /**
+   * Focusout handler for a node.
+   * @param {!Event} event
+   */
+  function _handleFocusOut(event) {
+    const node = /** @type {!HTMLElement} */ (event.target);
+    if (_isLeafNode(node)) {
+      node.removeEventListener('mousedown', _handleRefocus);
+    }
+    /** @type {HTMLElement} */ (event.currentTarget)
+        .parentElement.classList.remove('focused');
+  }
+
+  /**
    * Inflates a template to create an element that represents one tree node.
    * The element will represent a tree or a leaf, depending on if the tree node
    * object has any children. Trees use a slightly different template and have
@@ -367,15 +415,9 @@
       .addEventListener('change', _handleDynamicInputChange('.size', _setSize));
 
   _symbolTree.addEventListener('keydown', _handleKeyNavigation);
-  _symbolTree.addEventListener('focusin', event => {
-    displayInfocard(_uiNodeData.get(
-        /** @type {HTMLElement} */ (event.target)));
-    /** @type {HTMLElement} */ (event.currentTarget).parentElement
-        .classList.add('focused');
-  });
-  _symbolTree.addEventListener('focusout', event =>
-    /** @type {HTMLElement} */ (event.currentTarget).parentElement
-        .classList.remove('focused'));
+  _symbolTree.addEventListener('focusin', _handleFocusIn);
+  _symbolTree.addEventListener('focusout', _handleFocusOut);
+
   window.addEventListener('keydown', event => {
     if (event.key === '?' &&
         /** @type {HTMLElement} */ (event.target).tagName !== 'INPUT') {
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec
index d9ae1794..ac3ffe5 100644
--- a/tools/gritsettings/resource_ids.spec
+++ b/tools/gritsettings/resource_ids.spec
@@ -641,7 +641,7 @@
   "ash/webui/projector_app/resources/mock/projector_app_bundle_mock_resources.grd": {
     "includes": [3420],
   },
-  "<(SHARED_INTERMEDIATE_DIR)/ash/webui/facial_ml_app_ui/resources/trusted/ash_facial_ml_app_resources.grd": {
+  "<(SHARED_INTERMEDIATE_DIR)/ash/webui/face_ml_app_ui/resources/trusted/ash_face_ml_app_resources.grd": {
     "META": {"join": 2, "sizes": {"includes": [50],}},
     "includes": [3440],
   },
diff --git a/tools/idl_parser/idl_lexer.py b/tools/idl_parser/idl_lexer.py
index 61de1e9..670830a 100755
--- a/tools/idl_parser/idl_lexer.py
+++ b/tools/idl_parser/idl_lexer.py
@@ -100,6 +100,7 @@
       'stringifier': 'STRINGIFIER',
       'true': 'TRUE',
       'typedef': 'TYPEDEF',
+      'undefined': 'UNDEFINED',
       'unrestricted': 'UNRESTRICTED',
       'unsigned': 'UNSIGNED',
       'USVString': 'USVSTRING',
diff --git a/tools/idl_parser/idl_parser.py b/tools/idl_parser/idl_parser.py
index 1ec7054..b467fb85 100755
--- a/tools/idl_parser/idl_parser.py
+++ b/tools/idl_parser/idl_parser.py
@@ -917,9 +917,12 @@
                            | SEQUENCE '<' TypeWithExtendedAttributes '>' Null
                            | FROZENARRAY '<' TypeWithExtendedAttributes '>' Null
                            | OBSERVABLEARRAY '<' TypeWithExtendedAttributes '>' Null
-                           | RecordType Null"""
+                           | RecordType Null
+                           | UNDEFINED Null"""
     if len(p) == 3:
-      if type(p[1]) == str:
+      if p[1] == 'undefined':
+        typeref = self.BuildProduction('Undefined', p, 1)
+      elif type(p[1]) == str:
         typeref = self.BuildNamed('Typeref', p, 1)
       else:
         typeref = p[1]
diff --git a/tools/idl_parser/test_parser/typedef_web.idl b/tools/idl_parser/test_parser/typedef_web.idl
index df82cbb4..110b87b 100644
--- a/tools/idl_parser/test_parser/typedef_web.idl
+++ b/tools/idl_parser/test_parser/typedef_web.idl
@@ -190,3 +190,10 @@
  *        StringType(DOMString)
  */
 typedef sequence<DOMString>? StringSequenceOrNull;
+
+/** TREE
+ *Typedef(MyUndefined)
+ *  Type()
+ *    Undefined()
+ */
+typedef undefined MyUndefined;
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index ede10c30..dfcc387 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -32267,6 +32267,7 @@
   <int value="1002" label="PersistentQuotaEnabled"/>
   <int value="1003" label="DeviceContextAwareAccessSignalsAllowlist"/>
   <int value="1004" label="PrefixedStorageInfoEnabled"/>
+  <int value="1005" label="LoadCryptoTokenExtension"/>
 </enum>
 
 <enum name="EnterprisePoliciesSources">
@@ -48662,6 +48663,9 @@
   <int value="-2147167228" label="DRM_E_XB_UNKNOWN_ELEMENT_TYPE"/>
   <int value="-2147164882" label="DRM_E_* - OEM Specific (8004DD2E)"/>
   <int value="-2147164862" label="DRM_E_* - OEM Specific (8004DD42)"/>
+  <int value="-2147157503" label="media::kErrorInitializeMediaFoundation"/>
+  <int value="-2147157502" label="media::kErrorInitializeVideoWindowClass"/>
+  <int value="-2147157501" label="media::kErrorCdmProxyReceivedInInvalidState"/>
   <int value="-2147024894" label="ERROR_FILE_NOT_FOUND"/>
   <int value="-2147024893" label="ERROR_PATH_NOT_FOUND"/>
   <int value="-2147024891" label="E_ACCESSDENIED"/>
diff --git a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
index 92aea6d..b475360 100644
--- a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
+++ b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
@@ -6718,16 +6718,6 @@
       name="PageLoad.Clients.ServiceWorker2.ParseTiming.NavigationToParseStart"/>
 </histogram_suffixes>
 
-<!-- TODO(crbug.com/1353689): rewrite with the new way. -->
-<histogram_suffixes name="PageLoadMetricsSkippableFetchHandler" separator=".">
-  <suffix name="SkippableFetchHandler"
-    label="The fetch handler is recognized as skippable."/>
-  <suffix name="NonSkippableFetchHandler"
-    label="The fetch handler is recognized as not skippable."/>
-  <affected-histogram name="PageLoad.Clients.ServiceWorker2.PaintTiming.NavigationToFirstContentfulPaint"/>
-  <affected-histogram name="PageLoad.Clients.ServiceWorker2.PaintTiming.NavigationToLargestContentfulPaint2"/>
-</histogram_suffixes>
-
 <histogram_suffixes name="PageLoadMetricsClientsTabRestore" separator="."
     ordering="prefix">
   <suffix name="Clients.TabRestore"
@@ -10376,7 +10366,7 @@
   <suffix name="DemoMode" label="DemoMode"/>
   <suffix name="Diagnostics" label="Diagnostics"/>
   <suffix name="Eche" label="Eche"/>
-  <suffix name="FacialML" label="Facial ML"/>
+  <suffix name="FaceML" label="Face ML"/>
   <suffix name="FirmwareUpdate" label="FirmwareUpdate"/>
   <suffix name="Help" label="Help"/>
   <suffix name="Media" label="Media"/>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml
index 58ed8e4..c98ac3c 100644
--- a/tools/metrics/histograms/metadata/page/histograms.xml
+++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -1053,6 +1053,30 @@
 </histogram>
 
 <histogram
+    name="PageLoad.Clients.ServiceWorker2.PaintTiming.{Timing}.{HandlerType}"
+    units="ms" expires_after="2023-06-30">
+  <owner>yyanagisawa@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
+  <summary>
+    The {Timing} time of pages with the Service Worker fetch handlers. Metrics
+    won't be recorded if pages are not controlled by service workers. The
+    metrics are broken down by {HandlerType}. {HandlerType} only explains the
+    page's handler type, and it does not mean the fetch handler is actually
+    skipped or not.
+  </summary>
+  <token key="Timing">
+    <variant name="NavigationToFirstContentfulPaint"/>
+    <variant name="NavigationToLargestContentfulPaint2"/>
+  </token>
+  <token key="HandlerType">
+    <variant name="NonSkippableFetchHandler"
+        summary="The fetch handler is recognized as not skippable."/>
+    <variant name="SkippableFetchHandler"
+        summary="The fetch handler is recognized as skippable."/>
+  </token>
+</histogram>
+
+<histogram
     name="PageLoad.Clients.SideSearch.SidePanel.Experimental.PaintTiming.NavigationToFirstMeaningfulPaint"
     units="ms" expires_after="2022-09-11">
   <owner>tluk@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/storage/histograms.xml b/tools/metrics/histograms/metadata/storage/histograms.xml
index bd7d627..c4702cd 100644
--- a/tools/metrics/histograms/metadata/storage/histograms.xml
+++ b/tools/metrics/histograms/metadata/storage/histograms.xml
@@ -555,6 +555,104 @@
   </summary>
 </histogram>
 
+<histogram name="Storage.SharedStorage.Document.Timing.AddModule" units="ms"
+    expires_after="2023-07-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Measures the time from start of the call to
+    `blink::SharedStorageWorklet::AddModule()` to when the callback has
+    successfully completed. Does not measure the timing of calls that end in an
+    error. Recorded in the lambda function callback for
+    `blink::SharedStorageWorklet::AddModule()`.
+  </summary>
+</histogram>
+
+<histogram name="Storage.SharedStorage.Document.Timing.Append" units="ms"
+    expires_after="2023-07-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Measures the time from start of the call to `blink::SharedStorage::Append()`
+    to when the callback has successfully completed. Does not measure the timing
+    of calls that end in an error. Recorded in
+    `blink::SharedStorage::OnVoidOperationFinished()` via
+    `LogTimingHistogramForVoidOperation()`.
+  </summary>
+</histogram>
+
+<histogram name="Storage.SharedStorage.Document.Timing.Clear" units="ms"
+    expires_after="2023-07-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Measures the time from start of the call to `blink::SharedStorage::Clear()`
+    to when the callback has successfully completed. Does not measure the timing
+    of calls that end in an error. Recorded in
+    `blink::SharedStorage::OnVoidOperationFinished()` via
+    `LogTimingHistogramForVoidOperation()`.
+  </summary>
+</histogram>
+
+<histogram name="Storage.SharedStorage.Document.Timing.Delete" units="ms"
+    expires_after="2023-07-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Measures the time from start of the call to `blink::SharedStorage::Delete()`
+    to when the callback has successfully completed. Does not measure the timing
+    of calls that end in an error. Recorded in
+    `blink::SharedStorage::OnVoidOperationFinished()` via
+    `LogTimingHistogramForVoidOperation()`.
+  </summary>
+</histogram>
+
+<histogram name="Storage.SharedStorage.Document.Timing.Run" units="ms"
+    expires_after="2023-07-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Measures the time from start of the call to `blink::SharedStorage::Run()` to
+    when the callback has successfully completed. Does not measure the timing of
+    calls that end in an error. Recorded in
+    `blink::SharedStorage::OnVoidOperationFinished()` via
+    `LogTimingHistogramForVoidOperation()`.
+  </summary>
+</histogram>
+
+<histogram name="Storage.SharedStorage.Document.Timing.SelectURL" units="ms"
+    expires_after="2023-07-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Measures the time from start of the call to
+    `blink::SharedStorage::SelectURL()` to when the callback has successfully
+    completed. Does not measure the timing of calls that end in an error.
+    Recorded in the lambda function callback for
+    `blink::SharedStorage::SelectURL()`.
+  </summary>
+</histogram>
+
+<histogram name="Storage.SharedStorage.Document.Timing.Set" units="ms"
+    expires_after="2023-07-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Measures the time from start of the call to `blink::SharedStorage::Set()` to
+    when the callback has successfully completed. Does not measure the timing of
+    calls that end in an error. Recorded in
+    `blink::SharedStorage::OnVoidOperationFinished()` via
+    `LogTimingHistogramForVoidOperation()`.
+  </summary>
+</histogram>
+
 <histogram name="Storage.SharedStorage.OnShutdown.NumSqlErrors" units="Errors"
     expires_after="2023-01-31">
   <owner>cammie@chromium.org</owner>
@@ -621,6 +719,80 @@
   </summary>
 </histogram>
 
+<histogram name="Storage.SharedStorage.Worklet.Timing.Append" units="ms"
+    expires_after="2023-07-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Measures the time from start of the call to
+    `shared_storage_worklet::SharedStorage::Append()` to when the callback has
+    successfully completed. Does not measure the timing of calls that end in an
+    error. Recorded in
+    `shared_storage_worklet::SharedStorage::OnVoidOperationFinished()` via
+    `LogTimingHistogramForVoidOperation()`.
+  </summary>
+</histogram>
+
+<histogram name="Storage.SharedStorage.Worklet.Timing.Clear" units="ms"
+    expires_after="2023-07-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Measures the time from start of the call to
+    `shared_storage_worklet::SharedStorage::Clear()` to when the callback has
+    successfully completed. Does not measure the timing of calls that end in an
+    error. Recorded in
+    `shared_storage_worklet::SharedStorage::OnVoidOperationFinished()` via
+    `LogTimingHistogramForVoidOperation()`.
+  </summary>
+</histogram>
+
+<histogram name="Storage.SharedStorage.Worklet.Timing.Delete" units="ms"
+    expires_after="2023-07-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Measures the time from start of the call to
+    `shared_storage_worklet::SharedStorage::Delete()` to when the callback has
+    successfully completed. Does not measure the timing of calls that end in an
+    error. Recorded in
+    `shared_storage_worklet::SharedStorage::OnVoidOperationFinished()` via
+    `LogTimingHistogramForVoidOperation()`.
+  </summary>
+</histogram>
+
+<histogram name="Storage.SharedStorage.Worklet.Timing.Entries.Next" units="ms"
+    expires_after="2023-07-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Measures the time from the start of the call to
+    `shared_storage_worklet::SharedStorageiterator::Next()` to just before the
+    promise is returned, for the iterator in `Mode::kKeyValue`. Includes only
+    calls where `has_error_` is false. Recorded in
+    `shared_storage_worklet::SharedStorageIterator::NextHelper()` via
+    `LogElapsedTime()`.
+  </summary>
+</histogram>
+
+<histogram name="Storage.SharedStorage.Worklet.Timing.Get" units="ms"
+    expires_after="2023-07-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Measures the time from start of the call to
+    `shared_storage_worklet::SharedStorage::Get()` to when the callback has
+    successfully completed. Does not measure the timing of calls that end in an
+    error. Recorded in
+    `shared_storage_worklet::SharedStorage::OnStringRetrievalOperationFinished()`.
+  </summary>
+</histogram>
+
 <histogram
     name="Storage.SharedStorage.Worklet.Timing.KeepAliveEndedDueToOperationsFinished.KeepAliveDuration"
     units="ms" expires_after="2023-07-31">
@@ -635,6 +807,50 @@
   </summary>
 </histogram>
 
+<histogram name="Storage.SharedStorage.Worklet.Timing.Keys.Next" units="ms"
+    expires_after="2023-07-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Measures the time from the start of the call to
+    `shared_storage_worklet::SharedStorageiterator::Next()` to just before the
+    promise is returned, for the iterator in `Mode::kKey`. Includes only calls
+    where `has_error_` is false. Recorded in
+    `shared_storage_worklet::SharedStorageIterator::NextHelper()` via
+    `LogElapsedTime()`.
+  </summary>
+</histogram>
+
+<histogram name="Storage.SharedStorage.Worklet.Timing.Length" units="ms"
+    expires_after="2023-07-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Measures the time from start of the call to
+    `shared_storage_worklet::SharedStorage::Length()` to when the callback has
+    successfully completed. Does not measure the timing of calls that end in an
+    error. Recorded in
+    `shared_storage_worklet::SharedStorage::OnLengthOperationFinished()`.
+  </summary>
+</histogram>
+
+<histogram name="Storage.SharedStorage.Worklet.Timing.Set" units="ms"
+    expires_after="2023-07-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Measures the time from start of the call to
+    `shared_storage_worklet::SharedStorage::Set()` to when the callback has
+    successfully completed. Does not measure the timing of calls that end in an
+    error. Recorded in
+    `shared_storage_worklet::SharedStorage::OnVoidOperationFinished()` via
+    `LogTimingHistogramForVoidOperation()`.
+  </summary>
+</histogram>
+
 <histogram name="Storage.StoragePressure.Bubble"
     enum="StoragePressureBubbleUserAction" expires_after="2023-03-09">
   <owner>ayui@chromium.org</owner>
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn
index 16e5316..cdb54b27 100644
--- a/ui/accessibility/BUILD.gn
+++ b/ui/accessibility/BUILD.gn
@@ -145,6 +145,7 @@
     "ax_offscreen_result.h",
     "ax_position.h",
     "ax_range.h",
+    "ax_selection.h",
     "ax_serializable_tree.cc",
     "ax_serializable_tree.h",
     "ax_table_info.cc",
diff --git a/ui/accessibility/ax_assistant_structure.cc b/ui/accessibility/ax_assistant_structure.cc
index de2bdce..9af405a 100644
--- a/ui/accessibility/ax_assistant_structure.cc
+++ b/ui/accessibility/ax_assistant_structure.cc
@@ -13,6 +13,7 @@
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node.h"
 #include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/ax_serializable_tree.h"
 #include "ui/accessibility/platform/ax_android_constants.h"
 #include "ui/gfx/geometry/rect_conversions.h"
@@ -276,7 +277,7 @@
   if (IsLeaf(node) && update.has_tree_data) {
     int start_selection = 0;
     int end_selection = 0;
-    AXTree::Selection unignored_selection = tree->GetUnignoredSelection();
+    AXSelection unignored_selection = tree->GetUnignoredSelection();
     if (unignored_selection.anchor_object_id == node->id()) {
       start_selection = unignored_selection.anchor_offset;
       config->should_select_leaf = true;
diff --git a/ui/accessibility/ax_node.cc b/ui/accessibility/ax_node.cc
index 452b390..42039ec 100644
--- a/ui/accessibility/ax_node.cc
+++ b/ui/accessibility/ax_node.cc
@@ -17,6 +17,7 @@
 #include "ui/accessibility/ax_hypertext.h"
 #include "ui/accessibility/ax_language_detection.h"
 #include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/ax_table_info.h"
 #include "ui/accessibility/ax_tree.h"
 #include "ui/accessibility/ax_tree_manager.h"
@@ -770,7 +771,7 @@
 }
 
 bool AXNode::HasVisibleCaretOrSelection() const {
-  const OwnerTree::Selection selection = GetSelection();
+  const AXSelection selection = GetSelection();
   const AXNode* focus = tree()->GetFromId(selection.focus_object_id);
   if (!focus || !focus->IsDescendantOf(this))
     return false;
@@ -786,18 +787,18 @@
   return !selection.IsCollapsed();
 }
 
-AXNode::OwnerTree::Selection AXNode::GetSelection() const {
+AXSelection AXNode::GetSelection() const {
   DCHECK(tree()) << "Cannot retrieve the current selection if the node is not "
                     "attached to an accessibility tree.\n"
                  << *this;
   return tree()->GetSelection();
 }
 
-AXNode::OwnerTree::Selection AXNode::GetUnignoredSelection() const {
+AXSelection AXNode::GetUnignoredSelection() const {
   DCHECK(tree()) << "Cannot retrieve the current selection if the node is not "
                     "attached to an accessibility tree.\n"
                  << *this;
-  OwnerTree::Selection selection = tree()->GetUnignoredSelection();
+  AXSelection selection = tree()->GetUnignoredSelection();
 
   // "selection.anchor_offset" and "selection.focus_ofset" might need to be
   // adjusted if the anchor or the focus nodes include ignored children.
diff --git a/ui/accessibility/ax_node.h b/ui/accessibility/ax_node.h
index 2a98042..deeb6213 100644
--- a/ui/accessibility/ax_node.h
+++ b/ui/accessibility/ax_node.h
@@ -29,6 +29,7 @@
 namespace ui {
 
 class AXComputedNodeData;
+class AXSelection;
 class AXTableInfo;
 class AXTreeManager;
 
@@ -61,30 +62,6 @@
   // be necessary.
   class OwnerTree {
    public:
-    // A data structure that can store either the selected range of nodes in the
-    // accessibility tree, or the location of the caret in the case of a
-    // "collapsed" selection.
-    //
-    // TODO(nektar): Move this struct into its own file called "AXSelection",
-    // turn it into a class and make it compute the unignored selection given
-    // the `AXTreeData`.
-    struct Selection final {
-      // Returns true if this instance represents the position of the caret.
-      constexpr bool IsCollapsed() const {
-        return focus_object_id != kInvalidAXNodeID &&
-               anchor_object_id == focus_object_id &&
-               anchor_offset == focus_offset;
-      }
-
-      bool is_backward = false;
-      AXNodeID anchor_object_id = kInvalidAXNodeID;
-      int anchor_offset = -1;
-      ax::mojom::TextAffinity anchor_affinity;
-      AXNodeID focus_object_id = kInvalidAXNodeID;
-      int focus_offset = -1;
-      ax::mojom::TextAffinity focus_affinity;
-    };
-
     // See AXTree::GetAXTreeID.
     virtual const AXTreeID& GetAXTreeID() const = 0;
     // See `AXTree::GetTableInfo`.
@@ -98,9 +75,9 @@
     virtual absl::optional<int> GetSetSize(const AXNode& node) = 0;
 
     // See `AXTree::GetSelection`.
-    virtual Selection GetSelection() const = 0;
+    virtual AXSelection GetSelection() const = 0;
     // See `AXTree::GetUnignoredSelection`.
-    virtual Selection GetUnignoredSelection() const = 0;
+    virtual AXSelection GetUnignoredSelection() const = 0;
     // See `AXTree::GetTreeUpdateInProgressState`.
     virtual bool GetTreeUpdateInProgressState() const = 0;
     // See `AXTree::HasPaginationSupport`.
@@ -341,12 +318,12 @@
   bool HasVisibleCaretOrSelection() const;
 
   // Gets the current selection from the accessibility tree.
-  OwnerTree::Selection GetSelection() const;
+  AXSelection GetSelection() const;
 
   // Gets the unignored selection from the accessibility tree, meaning the
   // selection whose endpoints are on unignored nodes. (An "ignored" node is a
   // node that is not exposed to platform APIs: See `IsIgnored`.)
-  OwnerTree::Selection GetUnignoredSelection() const;
+  AXSelection GetUnignoredSelection() const;
 
   //
   // Methods for accessing accessibility attributes including attributes that
diff --git a/ui/accessibility/ax_node_position_unittest.cc b/ui/accessibility/ax_node_position_unittest.cc
index c63083f..0e5e561 100644
--- a/ui/accessibility/ax_node_position_unittest.cc
+++ b/ui/accessibility/ax_node_position_unittest.cc
@@ -20,6 +20,7 @@
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/accessibility/ax_node_position.h"
 #include "ui/accessibility/ax_range.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/ax_tree.h"
 #include "ui/accessibility/ax_tree_data.h"
 #include "ui/accessibility/ax_tree_id.h"
@@ -12385,7 +12386,7 @@
     tree->UpdateDataForTesting(data);
 
     // Should not crash.
-    AXNode::OwnerTree::Selection s = tree->GetUnignoredSelection();
+    AXSelection s = tree->GetUnignoredSelection();
     EXPECT_EQ(valid->anchor_id(), s.anchor_object_id);
     EXPECT_EQ(valid->child_index(), s.anchor_offset);
     EXPECT_EQ(valid->anchor_id(), s.focus_object_id);
diff --git a/ui/accessibility/ax_selection.h b/ui/accessibility/ax_selection.h
new file mode 100644
index 0000000..9c6f2ce
--- /dev/null
+++ b/ui/accessibility/ax_selection.h
@@ -0,0 +1,32 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ACCESSIBILITY_AX_SELECTION_H_
+#define UI_ACCESSIBILITY_AX_SELECTION_H_
+
+namespace ui {
+
+// A data structure that can store either the selected range of nodes in the
+// accessibility tree, or the location of the caret in the case of a
+// "collapsed" selection.
+class AX_EXPORT AXSelection final {
+ public:
+  // Returns true if this instance represents the position of the caret.
+  constexpr bool IsCollapsed() const {
+    return focus_object_id != kInvalidAXNodeID &&
+           anchor_object_id == focus_object_id && anchor_offset == focus_offset;
+  }
+
+  bool is_backward = false;
+  AXNodeID anchor_object_id = kInvalidAXNodeID;
+  int anchor_offset = -1;
+  ax::mojom::TextAffinity anchor_affinity;
+  AXNodeID focus_object_id = kInvalidAXNodeID;
+  int focus_offset = -1;
+  ax::mojom::TextAffinity focus_affinity;
+};
+
+}  // namespace ui
+
+#endif  // UI_ACCESSIBILITY_AX_SELECTION_H_
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc
index 9e716fc9..02c4d7d3 100644
--- a/ui/accessibility/ax_tree.cc
+++ b/ui/accessibility/ax_tree.cc
@@ -30,6 +30,7 @@
 #include "ui/accessibility/ax_node.h"
 #include "ui/accessibility/ax_node_position.h"
 #include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/ax_table_info.h"
 #include "ui/accessibility/ax_tree_observer.h"
 #include "ui/gfx/geometry/transform.h"
@@ -2684,15 +2685,15 @@
 
 }  // namespace
 
-AXTree::Selection AXTree::GetSelection() const {
+AXSelection AXTree::GetSelection() const {
   return {data().sel_is_backward,     data().sel_anchor_object_id,
           data().sel_anchor_offset,   data().sel_anchor_affinity,
           data().sel_focus_object_id, data().sel_focus_offset,
           data().sel_focus_affinity};
 }
 
-AXTree::Selection AXTree::GetUnignoredSelection() const {
-  Selection unignored_selection = GetSelection();
+AXSelection AXTree::GetUnignoredSelection() const {
+  AXSelection unignored_selection = GetSelection();
 
   // If one of the selection endpoints is invalid, then the other endpoint
   // should also be unset.
diff --git a/ui/accessibility/ax_tree.h b/ui/accessibility/ax_tree.h
index 554c202..f0d791e 100644
--- a/ui/accessibility/ax_tree.h
+++ b/ui/accessibility/ax_tree.h
@@ -33,6 +33,7 @@
 class AXTreeObserver;
 struct AXTreeUpdateState;
 class AXLanguageDetectionManager;
+class AXSelection;
 
 // These values are persisted to logs. Entries should not be renumbered and
 // numeric values should never be reused.
@@ -217,13 +218,13 @@
 
   // Returns the part of the current selection that falls within this
   // accessibility tree, if any.
-  Selection GetSelection() const override;
+  AXSelection GetSelection() const override;
 
   // Returns the part of the current selection that falls within this
   // accessibility tree, if any, adjusting its endpoints to be within unignored
   // nodes. (An "ignored" node is a node that is not exposed to platform APIs:
   // See `AXNode::IsIgnored`.)
-  Selection GetUnignoredSelection() const override;
+  AXSelection GetUnignoredSelection() const override;
 
   bool GetTreeUpdateInProgressState() const override;
 
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc
index 97dbe0a..bb75f11a 100644
--- a/ui/accessibility/ax_tree_unittest.cc
+++ b/ui/accessibility/ax_tree_unittest.cc
@@ -19,6 +19,7 @@
 #include "ui/accessibility/ax_enum_util.h"
 #include "ui/accessibility/ax_node.h"
 #include "ui/accessibility/ax_node_position.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/ax_serializable_tree.h"
 #include "ui/accessibility/ax_tree_data.h"
 #include "ui/accessibility/ax_tree_id.h"
@@ -37,7 +38,7 @@
     tree_update.tree_data.sel_focus_object_id = input.focus_id;    \
     tree_update.tree_data.sel_focus_offset = input.focus_offset;   \
     EXPECT_TRUE(tree->Unserialize(tree_update));                   \
-    AXTree::Selection actual = tree->GetUnignoredSelection();      \
+    AXSelection actual = tree->GetUnignoredSelection();            \
     EXPECT_EQ(expected.anchor_id, actual.anchor_object_id);        \
     EXPECT_EQ(expected.anchor_offset, actual.anchor_offset);       \
     EXPECT_EQ(expected.focus_id, actual.focus_object_id);          \
@@ -3057,7 +3058,7 @@
   tree_update.nodes[15].SetName("text");
 
   TestAXTreeManager test_ax_tree_manager(std::make_unique<AXTree>(tree_update));
-  AXTree::Selection unignored_selection =
+  AXSelection unignored_selection =
       test_ax_tree_manager.GetTree()->GetUnignoredSelection();
 
   EXPECT_EQ(kInvalidAXNodeID, unignored_selection.anchor_object_id);
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc
index 9650287f..d27062d 100644
--- a/ui/accessibility/platform/ax_platform_node_auralinux.cc
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -32,6 +32,7 @@
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/platform/atk_util_auralinux.h"
 #include "ui/accessibility/platform/ax_platform_atk_hyperlink.h"
 #include "ui/accessibility/platform/ax_platform_node_delegate.h"
@@ -3833,7 +3834,7 @@
     return;
   }
 
-  AXTree::Selection selection = GetDelegate()->GetUnignoredSelection();
+  AXSelection selection = GetDelegate()->GetUnignoredSelection();
   *anchor_node_id = selection.anchor_object_id;
   *anchor_offset = selection.anchor_offset;
   *focus_node_id = selection.focus_object_id;
@@ -5199,8 +5200,7 @@
   // no longer part of the visual selection.
   std::pair<int, int> selection;
   if (GetDelegate()->IsWebContent()) {
-    AXTree::Selection unignored_selection =
-        GetDelegate()->GetUnignoredSelection();
+    AXSelection unignored_selection = GetDelegate()->GetUnignoredSelection();
     GetSelectionOffsetsFromTree(&unignored_selection, &selection.first,
                                 &selection.second);
   } else {
diff --git a/ui/accessibility/platform/ax_platform_node_base.cc b/ui/accessibility/platform/ax_platform_node_base.cc
index 0bf97a3..26a0a2c 100644
--- a/ui/accessibility/platform/ax_platform_node_base.cc
+++ b/ui/accessibility/platform/ax_platform_node_base.cc
@@ -23,6 +23,7 @@
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/ax_tree_data.h"
 #include "ui/accessibility/platform/ax_platform_node_delegate.h"
 #include "ui/accessibility/platform/compute_attributes.h"
@@ -1929,7 +1930,7 @@
   return AXNodePosition::CreateNullPosition();
 }
 
-int AXPlatformNodeBase::GetSelectionAnchor(const AXTree::Selection* selection) {
+int AXPlatformNodeBase::GetSelectionAnchor(const AXSelection* selection) {
   DCHECK(selection);
   AXNodeID anchor_id = selection->anchor_object_id;
   AXPlatformNodeBase* anchor_object =
@@ -1941,7 +1942,7 @@
                                         selection->anchor_offset);
 }
 
-int AXPlatformNodeBase::GetSelectionFocus(const AXTree::Selection* selection) {
+int AXPlatformNodeBase::GetSelectionFocus(const AXSelection* selection) {
   DCHECK(selection);
   AXNodeID focus_id = selection->focus_object_id;
   AXPlatformNodeBase* focus_object =
@@ -1957,7 +1958,7 @@
   GetSelectionOffsets(nullptr, selection_start, selection_end);
 }
 
-void AXPlatformNodeBase::GetSelectionOffsets(const AXTree::Selection* selection,
+void AXPlatformNodeBase::GetSelectionOffsets(const AXSelection* selection,
                                              int* selection_start,
                                              int* selection_end) {
   DCHECK(selection_start && selection_end);
@@ -1970,7 +1971,7 @@
   }
 
   // If the unignored selection has not been computed yet, compute it now.
-  AXTree::Selection unignored_selection;
+  AXSelection unignored_selection;
   if (!selection) {
     unignored_selection = delegate_->GetUnignoredSelection();
     selection = &unignored_selection;
@@ -1980,7 +1981,7 @@
 }
 
 void AXPlatformNodeBase::GetSelectionOffsetsFromTree(
-    const AXTree::Selection* selection,
+    const AXSelection* selection,
     int* selection_start,
     int* selection_end) {
   DCHECK(selection_start && selection_end);
diff --git a/ui/accessibility/platform/ax_platform_node_base.h b/ui/accessibility/platform/ax_platform_node_base.h
index 9a78c92e..5a85eea3 100644
--- a/ui/accessibility/platform/ax_platform_node_base.h
+++ b/ui/accessibility/platform/ax_platform_node_base.h
@@ -513,8 +513,8 @@
   // First they check for a local selection found on the current control, e.g.
   // when querying the selection on a textarea.
   // If not found they retrieve the global selection found on the current frame.
-  int GetSelectionAnchor(const AXTree::Selection* selection);
-  int GetSelectionFocus(const AXTree::Selection* selection);
+  int GetSelectionAnchor(const AXSelection* selection);
+  int GetSelectionFocus(const AXSelection* selection);
 
   // Retrieves the selection offsets in the way required by the IA2 APIs.
   // selection_start and selection_end are -1 when there is no selection active
@@ -522,10 +522,10 @@
   // The greatest of the two offsets is one past the last character of the
   // selection.)
   void GetSelectionOffsets(int* selection_start, int* selection_end);
-  void GetSelectionOffsets(const AXTree::Selection* selection,
+  void GetSelectionOffsets(const AXSelection* selection,
                            int* selection_start,
                            int* selection_end);
-  void GetSelectionOffsetsFromTree(const AXTree::Selection* selection,
+  void GetSelectionOffsetsFromTree(const AXSelection* selection,
                                    int* selection_start,
                                    int* selection_end);
 
diff --git a/ui/accessibility/platform/ax_platform_node_delegate.h b/ui/accessibility/platform/ax_platform_node_delegate.h
index 4e4b7cb..5a8d433 100644
--- a/ui/accessibility/platform/ax_platform_node_delegate.h
+++ b/ui/accessibility/platform/ax_platform_node_delegate.h
@@ -190,7 +190,7 @@
   virtual std::u16string GetValueForControl() const = 0;
 
   // See `AXNode::GetUnignoredSelection`.
-  virtual const AXTree::Selection GetUnignoredSelection() const = 0;
+  virtual const AXSelection GetUnignoredSelection() const = 0;
 
   // Creates a text position rooted at this object if it's a leaf node, or a
   // tree position otherwise.
diff --git a/ui/accessibility/platform/ax_platform_node_delegate_base.cc b/ui/accessibility/platform/ax_platform_node_delegate_base.cc
index 58414cdb..e36d343b 100644
--- a/ui/accessibility/platform/ax_platform_node_delegate_base.cc
+++ b/ui/accessibility/platform/ax_platform_node_delegate_base.cc
@@ -11,6 +11,7 @@
 #include "ui/accessibility/ax_constants.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/ax_tree_data.h"
 #include "ui/accessibility/platform/ax_platform_node.h"
 #include "ui/accessibility/platform/ax_platform_node_base.h"
@@ -265,10 +266,9 @@
   return value;
 }
 
-const AXTree::Selection AXPlatformNodeDelegateBase::GetUnignoredSelection()
-    const {
+const AXSelection AXPlatformNodeDelegateBase::GetUnignoredSelection() const {
   NOTIMPLEMENTED();
-  return AXTree::Selection{false, -1, -1, ax::mojom::TextAffinity::kDownstream};
+  return AXSelection{false, -1, -1, ax::mojom::TextAffinity::kDownstream};
 }
 
 AXNodePosition::AXPositionInstance AXPlatformNodeDelegateBase::CreatePositionAt(
diff --git a/ui/accessibility/platform/ax_platform_node_delegate_base.h b/ui/accessibility/platform/ax_platform_node_delegate_base.h
index 3113e71..b14d99f6 100644
--- a/ui/accessibility/platform/ax_platform_node_delegate_base.h
+++ b/ui/accessibility/platform/ax_platform_node_delegate_base.h
@@ -99,7 +99,7 @@
   ax::mojom::DescriptionFrom GetDescriptionFrom() const override;
   std::u16string GetTextContentUTF16() const override;
   std::u16string GetValueForControl() const override;
-  const AXTree::Selection GetUnignoredSelection() const override;
+  const AXSelection GetUnignoredSelection() const override;
 
   AXNodePosition::AXPositionInstance CreatePositionAt(
       int offset,
diff --git a/ui/accessibility/platform/ax_platform_node_textprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textprovider_win.cc
index 9cf0bfa..faecaf7 100644
--- a/ui/accessibility/platform/ax_platform_node_textprovider_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_textprovider_win.cc
@@ -8,6 +8,7 @@
 
 #include "base/win/scoped_safearray.h"
 #include "ui/accessibility/ax_node_position.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/platform/ax_platform_node_base.h"
 #include "ui/accessibility/platform/ax_platform_node_delegate.h"
 #include "ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h"
@@ -64,7 +65,7 @@
   *selection = nullptr;
 
   AXPlatformNodeDelegate* delegate = owner()->GetDelegate();
-  ui::AXTree::Selection unignored_selection = delegate->GetUnignoredSelection();
+  AXSelection unignored_selection = delegate->GetUnignoredSelection();
 
   AXPlatformNode* anchor_object =
       delegate->GetFromNodeID(unignored_selection.anchor_object_id);
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
index ad2a2d7e..8a74aa9 100644
--- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
@@ -15,6 +15,7 @@
 #include "base/win/scoped_variant.h"
 #include "base/win/variant_vector.h"
 #include "ui/accessibility/ax_action_data.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/platform/ax_platform_node_delegate.h"
 #include "ui/accessibility/platform/ax_platform_tree_manager.h"
 
@@ -1314,7 +1315,7 @@
   // first snap them both to be unignored positions.
   NormalizeAsUnignoredTextRange(start, end);
 
-  // When a text range or one end of AXTree::Selection is inside the atomic text
+  // When a text range or one end of AXSelection is inside the atomic text
   // field, the precise state of the TextPattern must be preserved so that the
   // UIA client can handle scenarios such as determining which characters were
   // deleted. So normalization must be bypassed.
@@ -1405,7 +1406,7 @@
 
 AXNode* AXPlatformNodeTextRangeProviderWin::GetSelectionCommonAnchor() {
   AXPlatformNodeDelegate* delegate = GetOwner()->GetDelegate();
-  ui::AXTree::Selection unignored_selection = delegate->GetUnignoredSelection();
+  AXSelection unignored_selection = delegate->GetUnignoredSelection();
   AXPlatformNode* anchor_object =
       delegate->GetFromNodeID(unignored_selection.anchor_object_id);
   AXPlatformNode* focus_object =
@@ -1510,7 +1511,7 @@
 
   // Return true when both ends of a text range are inside the atomic
   // text field (e.g. a caret perceived by the AT), or when either endpoint of
-  // the AXTree::Selection is inside the atomic text field.
+  // the AXSelection is inside the atomic text field.
   return (is_start_in_text_field && is_end_in_text_field) ||
          (is_start_in_text_field && start_delegate &&
           start_delegate->HasVisibleCaretOrSelection()) ||
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
index 8ff0bf0..8f19676 100644
--- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
+++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/win/scoped_bstr.h"
 #include "base/win/scoped_safearray.h"
 #include "base/win/scoped_variant.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/platform/ax_fragment_root_win.h"
 #include "ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h"
 using Microsoft::WRL::ComPtr;
@@ -5006,7 +5007,7 @@
     text_range_provider->Select();
 
     // Verify selection.
-    AXTree::Selection unignored_selection = delegate->GetUnignoredSelection();
+    AXSelection unignored_selection = delegate->GetUnignoredSelection();
     EXPECT_EQ(3, unignored_selection.anchor_object_id);
     EXPECT_EQ(3, unignored_selection.focus_object_id);
     EXPECT_EQ(0, unignored_selection.anchor_offset);
@@ -5035,7 +5036,7 @@
     more_text_range_provider->Select();
 
     // Verify selection
-    AXTree::Selection unignored_selection = delegate->GetUnignoredSelection();
+    AXSelection unignored_selection = delegate->GetUnignoredSelection();
     EXPECT_EQ(5, unignored_selection.anchor_object_id);
     EXPECT_EQ(5, unignored_selection.focus_object_id);
     EXPECT_EQ(0, unignored_selection.anchor_offset);
@@ -5064,7 +5065,7 @@
     document_text_range_provider->Select();
 
     // Verify selection.
-    AXTree::Selection unignored_selection = delegate->GetUnignoredSelection();
+    AXSelection unignored_selection = delegate->GetUnignoredSelection();
     EXPECT_EQ(3, unignored_selection.anchor_object_id);
     EXPECT_EQ(5, unignored_selection.focus_object_id);
     EXPECT_EQ(0, unignored_selection.anchor_offset);
@@ -5096,7 +5097,7 @@
     text_range_provider->Select();
 
     // Verify selection.
-    AXTree::Selection unignored_selection = delegate->GetUnignoredSelection();
+    AXSelection unignored_selection = delegate->GetUnignoredSelection();
     EXPECT_EQ(3, unignored_selection.anchor_object_id);
     EXPECT_EQ(3, unignored_selection.focus_object_id);
     EXPECT_EQ(9, unignored_selection.anchor_offset);
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index 36f633b..00959865 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -46,6 +46,7 @@
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/accessibility/ax_node_position.h"
 #include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/ax_tree_data.h"
 #include "ui/accessibility/platform/ax_fragment_root_win.h"
 #include "ui/accessibility/platform/ax_platform_node_delegate.h"
@@ -2309,8 +2310,7 @@
                                                       LONG* nRanges) {
   COM_OBJECT_VALIDATE_2_ARGS(ranges, nRanges);
   AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
-  AXTree::Selection unignored_selection =
-      GetDelegate()->GetUnignoredSelection();
+  AXSelection unignored_selection = GetDelegate()->GetUnignoredSelection();
 
   AXNodeID anchor_id = unignored_selection.anchor_object_id;
   auto* anchor_node =
@@ -4467,8 +4467,7 @@
 
   COM_OBJECT_VALIDATE_2_ARGS(selections, nSelections);
 
-  AXTree::Selection unignored_selection =
-      GetDelegate()->GetUnignoredSelection();
+  AXSelection unignored_selection = GetDelegate()->GetUnignoredSelection();
 
   AXNodeID anchor_id = unignored_selection.anchor_object_id;
   AXPlatformNodeWin* anchor_node =
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.cc b/ui/accessibility/platform/test_ax_node_wrapper.cc
index ca3cdb6..5f5d855 100644
--- a/ui/accessibility/platform/test_ax_node_wrapper.cc
+++ b/ui/accessibility/platform/test_ax_node_wrapper.cc
@@ -13,6 +13,7 @@
 #include "build/build_config.h"
 #include "ui/accessibility/ax_action_data.h"
 #include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_selection.h"
 #include "ui/accessibility/ax_table_info.h"
 #include "ui/accessibility/ax_tree_observer.h"
 #include "ui/gfx/geometry/rect_conversions.h"
@@ -145,7 +146,7 @@
   return tree_->data();
 }
 
-const AXTree::Selection TestAXNodeWrapper::GetUnignoredSelection() const {
+const AXSelection TestAXNodeWrapper::GetUnignoredSelection() const {
   return tree_->GetUnignoredSelection();
 }
 
@@ -867,7 +868,7 @@
 }
 
 bool TestAXNodeWrapper::HasVisibleCaretOrSelection() const {
-  ui::AXTree::Selection unignored_selection = GetUnignoredSelection();
+  AXSelection unignored_selection = GetUnignoredSelection();
   int32_t focus_id = unignored_selection.focus_object_id;
   AXNode* focus_object = tree_->GetFromId(focus_id);
   if (!focus_object)
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.h b/ui/accessibility/platform/test_ax_node_wrapper.h
index 36d9e0ae..01611eb3 100644
--- a/ui/accessibility/platform/test_ax_node_wrapper.h
+++ b/ui/accessibility/platform/test_ax_node_wrapper.h
@@ -71,7 +71,7 @@
   // AXPlatformNodeDelegate.
   const AXNodeData& GetData() const override;
   const AXTreeData& GetTreeData() const override;
-  const AXTree::Selection GetUnignoredSelection() const override;
+  const AXSelection GetUnignoredSelection() const override;
   AXNodePosition::AXPositionInstance CreatePositionAt(
       int offset,
       ax::mojom::TextAffinity affinity =
diff --git a/ui/chromeos/file_manager_strings.grdp b/ui/chromeos/file_manager_strings.grdp
index b9fcba3f..2938c58 100644
--- a/ui/chromeos/file_manager_strings.grdp
+++ b/ui/chromeos/file_manager_strings.grdp
@@ -813,6 +813,9 @@
   <message name="IDS_FILE_BROWSER_RESTORE_FROM_TRASH_ERROR" desc="Message informing about error while restoring an item or items from the trash / recycle bin.">
     An error occurred. Some items may not have been restored.
   </message>
+  <message name="IDS_FILE_BROWSER_TRASH_UNEXPECTED_ERROR" desc="Message informing about error while sending an item to the trash / recycle bin.">
+    An error occurred. Some items may not have been trashed.
+  </message>
   <message name="IDS_FILE_BROWSER_OPEN_TRASHED_FILES_ERROR" desc="Message informing users they can't open files from the Trash folder">
     Cannot open trashed files. Please restore the files before opening.
   </message>
diff --git a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_TRASH_UNEXPECTED_ERROR.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_TRASH_UNEXPECTED_ERROR.png.sha1
new file mode 100644
index 0000000..4c23773d
--- /dev/null
+++ b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_TRASH_UNEXPECTED_ERROR.png.sha1
@@ -0,0 +1 @@
+37fdd801cd7ef168b1cfaec686adfa42d37e0ae4
\ No newline at end of file
diff --git a/ui/file_manager/file_manager/background/js/file_operation_handler.js b/ui/file_manager/file_manager/background/js/file_operation_handler.js
index bacb4b3..3964dbd 100644
--- a/ui/file_manager/file_manager/background/js/file_operation_handler.js
+++ b/ui/file_manager/file_manager/background/js/file_operation_handler.js
@@ -544,6 +544,8 @@
         return str('DELETE_ERROR');
       case chrome.fileManagerPrivate.IOTaskType.RESTORE:
         return str('RESTORE_FROM_TRASH_ERROR');
+      case chrome.fileManagerPrivate.IOTaskType.TRASH:
+        return str('TRASH_UNEXPECTED_ERROR');
       default:
         console.warn(`Unexpected operation type: ${event.type}`);
         return strf('FILE_ERROR_GENERIC');
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 0fe4467..e67df06 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
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import 'chrome://resources/cr_elements/cr_input/cr_input.js';
 
+import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
 import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn
index 0fa34b6fc..b1f3b94d 100644
--- a/ui/webui/resources/BUILD.gn
+++ b/ui/webui/resources/BUILD.gn
@@ -169,9 +169,6 @@
   "cr_elements/cr_icon_button/cr_icon_button.d.ts",
   "cr_elements/cr_input/cr_input.d.ts",
   "cr_elements/cr_lottie/cr_lottie.m.d.ts",
-  "cr_elements/cr_radio_button/cr_card_radio_button.d.ts",
-  "cr_elements/cr_radio_button/cr_radio_button_behavior.d.ts",
-  "cr_elements/cr_radio_button/cr_radio_button.d.ts",
   "cr_elements/cr_scrollable_behavior.m.d.ts",
   "cr_elements/find_shortcut_behavior.d.ts",
   "cr_elements/policy/cr_policy_indicator_behavior.m.d.ts",
diff --git a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_base_page.js b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_base_page.js
index 0f3744d..16f5a6a8 100644
--- a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_base_page.js
+++ b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_base_page.js
@@ -7,13 +7,13 @@
  * Base template with elements common to all Bluetooth UI sub-pages.
  */
 
-import 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/paper-progress/paper-progress.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from '//resources/js/i18n_behavior.m.js';
 import {afterNextRender, html, mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 
 import {assertNotReached} from '../../../js/assert.m.js';
 import {focusWithoutInk} from '../../../js/cr/ui/focus_without_ink.m.js';
diff --git a/ui/webui/resources/cr_components/chromeos/network/BUILD.gn b/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
index 82b9dbc..86dee1e 100644
--- a/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
+++ b/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
@@ -491,10 +491,10 @@
     "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout-classes",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/cr_elements/cr_input:cr_input",
-    "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button",
     "//ui/webui/resources/cr_elements/policy:cr_policy_indicator.m",
     "//ui/webui/resources/js:i18n_behavior.m",
   ]
+  externs_list = [ "//ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_externs.js" ]
   extra_deps = [ ":network_nameservers_module" ]
 }
 
@@ -850,7 +850,7 @@
   js_file = "network_siminfo.js"
   html_file = "network_siminfo.html"
   html_type = "dom-module"
-  auto_imports = cr_components_chromeos_auto_imports
+  auto_imports = cr_components_chromeos_auto_imports + [ "ui/webui/resources/cr_elements/cr_button/cr_button.html|CrButtonElement" ]
   migrated_imports = cr_components_migrated_imports
   namespace_rewrites = cr_components_chromeos_namespace_rewrites
 }
diff --git a/ui/webui/resources/cr_elements/BUILD.gn b/ui/webui/resources/cr_elements/BUILD.gn
index 53ad55c..12fe533 100644
--- a/ui/webui/resources/cr_elements/BUILD.gn
+++ b/ui/webui/resources/cr_elements/BUILD.gn
@@ -17,7 +17,6 @@
 preprocess_folder = "$root_gen_dir/ui/webui/resources/preprocessed/cr_elements"
 if (include_polymer) {
   preprocess_gen_manifest = "preprocessed_gen_manifest.json"
-  preprocess_src_manifest = "preprocessed_src_manifest.json"
 }
 
 if (is_chromeos_ash) {
@@ -29,10 +28,7 @@
     grd_prefix = "cr_elements"
     out_grd = "$target_gen_dir/${grd_prefix}_resources.grdp"
     public_deps = [ ":preprocess" ]
-    manifest_files = [
-      "$target_gen_dir/$preprocess_gen_manifest",
-      "$target_gen_dir/$preprocess_src_manifest",
-    ]
+    manifest_files = [ "$target_gen_dir/$preprocess_gen_manifest" ]
 
     if (is_chromeos_ash) {
       manifest_files += [
@@ -55,7 +51,6 @@
       ":css_wrapper_files",
       ":html_wrapper_files",
       ":preprocess_generated",
-      ":preprocess_src",
     ]
   }
 
@@ -115,13 +110,6 @@
 }
 
 if (include_polymer) {
-  preprocess_if_expr("preprocess_src") {
-    in_folder = "."
-    out_folder = preprocess_folder
-    out_manifest = "$target_gen_dir/$preprocess_src_manifest"
-    in_files = [ "cr_radio_button/cr_radio_button_behavior.js" ]
-  }
-
   preprocess_if_expr("preprocess_generated") {
     deps = [ ":custom_elements" ]
     in_folder = target_gen_dir
@@ -136,8 +124,6 @@
       "cr_icons_css.m.js",
       "cr_input/cr_input.js",
       "cr_lottie/cr_lottie.m.js",
-      "cr_radio_button/cr_card_radio_button.js",
-      "cr_radio_button/cr_radio_button.js",
       "cr_scrollable_behavior.m.js",
       "hidden_style_css.m.js",
       "icons.m.js",
@@ -173,7 +159,6 @@
       "cr_icon_button:closure_compile_module",
       "cr_input:closure_compile_module",
       "cr_lottie:closure_compile_module",
-      "cr_radio_button:closure_compile_module",
       "policy:closure_compile_module",
     ]
   }
@@ -271,7 +256,6 @@
       "cr_icon_button:web_components",
       "cr_input:web_components",
       "cr_lottie:cr_lottie_module",
-      "cr_radio_button:web_components",
       "policy:polymer3_elements",
     ]
 
diff --git a/ui/webui/resources/cr_elements/cr_button/cr_button.d.ts b/ui/webui/resources/cr_elements/cr_button/cr_button.d.ts
index 951f8b4..b2fd849 100644
--- a/ui/webui/resources/cr_elements/cr_button/cr_button.d.ts
+++ b/ui/webui/resources/cr_elements/cr_button/cr_button.d.ts
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js';
+import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-interface CrButtonElement extends LegacyElementMixin, HTMLElement {
+interface CrButtonElement extends PolymerElement {
   disabled: boolean;
   customTabIndex: number|null|undefined;
   hostAttributes: object|null;
diff --git a/ui/webui/resources/cr_elements/cr_button/cr_button.js b/ui/webui/resources/cr_elements/cr_button/cr_button.js
index efa6f6b..bebeafec 100644
--- a/ui/webui/resources/cr_elements/cr_button/cr_button.js
+++ b/ui/webui/resources/cr_elements/cr_button/cr_button.js
@@ -12,84 +12,115 @@
 import '../shared_vars_css.m.js';
 
 import {PaperRippleBehavior} from '//resources/polymer/v3_0/paper-behaviors/paper-ripple-behavior.js';
-import {html, Polymer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {html, mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {FocusOutlineManager} from '../../js/cr/ui/focus_outline_manager.m.js';
 
-Polymer({
-  is: 'cr-button',
+/** @interface */
+class PaperRippleBehaviorInterface {
+  /** @return {Element} */
+  getRipple() {}
 
-  _template: html`{__html_template__}`,
+  ensureRipple() {}
+}
 
-  behaviors: [
-    PaperRippleBehavior,
-  ],
+/**
+ * @constructor
+ * @extends {PolymerElement}
+ * @implements {PaperRippleBehaviorInterface}
+ */
+const CrButtonElementBase =
+    mixinBehaviors([PaperRippleBehavior], PolymerElement);
 
-  properties: {
-    disabled: {
-      type: Boolean,
-      value: false,
-      reflectToAttribute: true,
-      observer: 'disabledChanged_',
-    },
+/** @polymer */
+export class CrButtonElement extends CrButtonElementBase {
+  static get is() {
+    return 'cr-button';
+  }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
+
+  static get properties() {
+    return {
+      disabled: {
+        type: Boolean,
+        value: false,
+        reflectToAttribute: true,
+        observer: 'disabledChanged_',
+      },
+
+      /**
+       * Use this property in order to configure the "tabindex" attribute.
+       */
+      customTabIndex: {
+        type: Number,
+        observer: 'applyTabIndex_',
+      },
+
+      /**
+       * Flag used for formatting ripples on circle shaped cr-buttons.
+       * @private
+       */
+      circleRipple: {
+        type: Boolean,
+        value: false,
+      },
+    };
+  }
+
+  constructor() {
+    super();
 
     /**
-     * Use this property in order to configure the "tabindex" attribute.
+     * It is possible to activate a tab when the space key is pressed down. When
+     * this element has focus, the keyup event for the space key should not
+     * perform a 'click'. |spaceKeyDown_| tracks when a space pressed and
+     * handled by this element. Space keyup will only result in a 'click' when
+     * |spaceKeyDown_| is true. |spaceKeyDown_| is set to false when element
+     * loses focus.
+     * @private {boolean}
      */
-    customTabIndex: {
-      type: Number,
-      observer: 'applyTabIndex_',
-    },
+    this.spaceKeyDown_ = false;
 
-    /**
-     * Flag used for formatting ripples on circle shaped cr-buttons.
-     * @private
-     */
-    circleRipple: {
-      type: Boolean,
-      value: false,
-    },
-  },
+    /** @private {Set<number>} */
+    this.timeoutIds_ = null;
 
-  hostAttributes: {
-    'aria-disabled': 'false',
-    role: 'button',
-    tabindex: 0,
-  },
-
-  listeners: {
-    blur: 'onBlur_',
-    click: 'onClick_',
-    keydown: 'onKeyDown_',
-    keyup: 'onKeyUp_',
-    pointerdown: 'onPointerDown_',
-  },
-
-  /**
-   * It is possible to activate a tab when the space key is pressed down. When
-   * this element has focus, the keyup event for the space key should not
-   * perform a 'click'. |spaceKeyDown_| tracks when a space pressed and handled
-   * by this element. Space keyup will only result in a 'click' when
-   * |spaceKeyDown_| is true. |spaceKeyDown_| is set to false when element loses
-   * focus.
-   * @private {boolean}
-   */
-  spaceKeyDown_: false,
-
-  /** @private {Set<number>} */
-  timeoutIds_: null,
+    this.addEventListener('blur', this.onBlur_.bind(this));
+    // Must be added in constructor so that stopImmediatePropagation() works as
+    // expected.
+    this.addEventListener('click', this.onClick_.bind(this));
+    this.addEventListener(
+        'keydown', e => this.onKeyDown_(/** @type {!KeyboardEvent} */ (e)));
+    this.addEventListener(
+        'keyup', e => this.onKeyUp_(/** @type {!KeyboardEvent} */ (e)));
+    this.addEventListener('pointerdown', this.onPointerDown_.bind(this));
+  }
 
   /** @override */
   ready() {
+    super.ready();
+    if (!this.hasAttribute('role')) {
+      this.setAttribute('role', 'button');
+    }
+    if (!this.hasAttribute('tabindex')) {
+      this.setAttribute('tabindex', '0');
+    }
+    if (!this.hasAttribute('aria-disabled')) {
+      this.setAttribute('aria-disabled', 'false');
+    }
+
     FocusOutlineManager.forDocument(document);
     this.timeoutIds_ = new Set();
-  },
+  }
 
   /** @override */
-  detached() {
+  disconnectedCallback() {
+    super.disconnectedCallback();
     this.timeoutIds_.forEach(clearTimeout);
     this.timeoutIds_.clear();
-  },
+  }
 
   /**
    * @param {!Function} fn
@@ -105,7 +136,7 @@
       fn();
     }, delay);
     this.timeoutIds_.add(id);
-  },
+  }
 
   /**
    * @param {boolean} newValue
@@ -119,9 +150,9 @@
     if (this.disabled) {
       this.blur();
     }
-    this.setAttribute('aria-disabled', Boolean(this.disabled));
+    this.setAttribute('aria-disabled', this.disabled ? 'true' : 'false');
     this.applyTabIndex_();
-  },
+  }
 
   /**
    * Updates the tabindex HTML attribute to the actual value.
@@ -132,13 +163,13 @@
     if (value === undefined) {
       value = this.disabled ? -1 : 0;
     }
-    this.setAttribute('tabindex', value);
-  },
+    this.setAttribute('tabindex', value.toString());
+  }
 
   /** @private */
   onBlur_() {
     this.spaceKeyDown_ = false;
-  },
+  }
 
   /**
    * @param {!Event} e
@@ -148,7 +179,7 @@
     if (this.disabled) {
       e.stopImmediatePropagation();
     }
-  },
+  }
 
   /**
    * @param {!KeyboardEvent} e
@@ -163,7 +194,6 @@
     e.stopPropagation();
 
     if (e.repeat) {
-      this.lastKeyDownKey_ = null;
       return;
     }
 
@@ -176,7 +206,7 @@
     } else if (e.key === ' ') {
       this.spaceKeyDown_ = true;
     }
-  },
+  }
 
   /**
    * @param {!KeyboardEvent} e
@@ -195,12 +225,12 @@
       this.click();
       this.getRipple().uiUpAction();
     }
-  },
+  }
 
   /** @private */
   onPointerDown_() {
     this.ensureRipple();
-  },
+  }
 
   /**
    * Customize the element's ripple. Overriding the '_createRipple' function
@@ -208,7 +238,7 @@
    * @return {PaperRippleElement}
    */
   _createRipple() {
-    const ripple = PaperRippleBehavior._createRipple();
+    const ripple = super._createRipple();
 
     if (this.circleRipple) {
       ripple.setAttribute('center', '');
@@ -216,5 +246,7 @@
     }
 
     return ripple;
-  },
-});
+  }
+}
+
+customElements.define(CrButtonElement.is, CrButtonElement);
diff --git a/ui/webui/resources/cr_elements/cr_elements.gni b/ui/webui/resources/cr_elements/cr_elements.gni
index 4c3b17f..0604a0e 100644
--- a/ui/webui/resources/cr_elements/cr_elements.gni
+++ b/ui/webui/resources/cr_elements/cr_elements.gni
@@ -38,6 +38,8 @@
     "cr_link_row/cr_link_row.ts",
     "cr_profile_avatar_selector/cr_profile_avatar_selector_grid.ts",
     "cr_profile_avatar_selector/cr_profile_avatar_selector.ts",
+    "cr_radio_button/cr_card_radio_button.ts",
+    "cr_radio_button/cr_radio_button.ts",
     "cr_radio_group/cr_radio_group.ts",
     "cr_search_field/cr_search_field.ts",
     "cr_slider/cr_slider.ts",
@@ -87,6 +89,7 @@
     "cr_auto_img/cr_auto_img.ts",
     "cr_container_shadow_mixin.ts",
     "cr_menu_selector/cr_menu_selector.ts",
+    "cr_radio_button/cr_radio_button_mixin.ts",
     "cr_search_field/cr_search_field_mixin.ts",
     "find_shortcut_mixin.ts",
     "mouse_hoverable_mixin.ts",
diff --git a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js
index 436c998..460c64dd 100644
--- a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js
+++ b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js
@@ -98,6 +98,13 @@
      * @private {boolean}
      */
     this.spaceKeyDown_ = false;
+
+    this.addEventListener('blur', this.onBlur_.bind(this));
+    this.addEventListener('click', this.onClick_.bind(this));
+    this.addEventListener(
+        'keydown', e => this.onKeyDown_(/** @type {!KeyboardEvent} */ (e)));
+    this.addEventListener(
+        'keyup', e => this.onKeyUp_(/** @type {!KeyboardEvent} */ (e)));
   }
 
   /** @override */
@@ -110,13 +117,6 @@
     if (!this.hasAttribute('tabindex')) {
       this.setAttribute('tabindex', '0');
     }
-
-    this.addEventListener('blur', this.onBlur_.bind(this));
-    this.addEventListener('click', this.onClick_.bind(this));
-    this.addEventListener(
-        'keydown', e => this.onKeyDown_(/** @type {!KeyboardEvent} */ (e)));
-    this.addEventListener(
-        'keyup', e => this.onKeyUp_(/** @type {!KeyboardEvent} */ (e)));
   }
 
   /** @param {string} className */
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/BUILD.gn b/ui/webui/resources/cr_elements/cr_radio_button/BUILD.gn
deleted file mode 100644
index 2a2d6df..0000000
--- a/ui/webui/resources/cr_elements/cr_radio_button/BUILD.gn
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-import("//tools/polymer/html_to_js.gni")
-
-html_to_js("web_components") {
-  js_files = [
-    "cr_radio_button.js",
-    "cr_card_radio_button.js",
-  ]
-}
-
-js_type_check("closure_compile_module") {
-  is_polymer3 = true
-  deps = [
-    ":cr_card_radio_button",
-    ":cr_radio_button",
-    ":cr_radio_button_behavior",
-  ]
-}
-
-js_library("cr_radio_button") {
-  deps = [
-    ":cr_radio_button_behavior",
-    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-  ]
-}
-
-js_library("cr_card_radio_button") {
-  deps = [
-    ":cr_radio_button_behavior",
-    "//third_party/polymer/v3_0/components-chromium/iron-icon",
-    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-  ]
-}
-
-js_library("cr_radio_button_behavior") {
-  deps = [ "//third_party/polymer/v3_0/components-chromium/paper-behaviors:paper-ripple-behavior" ]
-}
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.d.ts b/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.d.ts
deleted file mode 100644
index a056728..0000000
--- a/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.d.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-import {CrRadioButtonBehavior} from './cr_radio_button_behavior.js';
-
-interface CrCardRadioButtonElement extends CrRadioButtonBehavior,
-                                           PolymerElement {
-  $: {
-    button: HTMLElement,
-  };
-}
-
-export {CrCardRadioButtonElement};
-
-declare global {
-  interface HTMLElementTagNameMap {
-    'cr-card-radio-button': CrCardRadioButtonElement;
-  }
-}
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.js b/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.js
deleted file mode 100644
index 5ff8f04..0000000
--- a/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.js
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview
- * 'cr-card-radio-button' is a radio button in the style of a card. A checkmark
- * is displayed in the upper right hand corner if the radio button is selected.
- */
-import '//resources/polymer/v3_0/iron-icon/iron-icon.js';
-import './cr_radio_button_style.css.js';
-import '../icons.m.js';
-import '../shared_vars_css.m.js';
-
-import {html, mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-import {CrRadioButtonBehavior, CrRadioButtonBehaviorInterface} from './cr_radio_button_behavior.js';
-
-/**
- * @constructor
- * @extends {PolymerElement}
- * @implements {CrRadioButtonBehaviorInterface}
- */
-const CrCardRadioButtonElementBase =
-    mixinBehaviors([CrRadioButtonBehavior], PolymerElement);
-
-/** @polymer */
-export class CrCardRadioButtonElement extends CrCardRadioButtonElementBase {
-  static get is() {
-    return 'cr-card-radio-button';
-  }
-
-  static get template() {
-    return html`{__html_template__}`;
-  }
-}
-
-customElements.define(CrCardRadioButtonElement.is, CrCardRadioButtonElement);
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.ts b/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.ts
new file mode 100644
index 0000000..02131ae
--- /dev/null
+++ b/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.ts
@@ -0,0 +1,66 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ * 'cr-card-radio-button' is a radio button in the style of a card. A checkmark
+ * is displayed in the upper right hand corner if the radio button is selected.
+ */
+import '//resources/polymer/v3_0/iron-icon/iron-icon.js';
+import './cr_radio_button_style.css.js';
+import '../icons.m.js';
+import '../shared_vars_css.m.js';
+
+import {mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {PaperRippleBehavior} from 'chrome://resources/polymer/v3_0/paper-behaviors/paper-ripple-behavior.js';
+
+import {getTemplate} from './cr_card_radio_button.html.js';
+import {CrRadioButtonMixin, CrRadioButtonMixinInterface} from './cr_radio_button_mixin.js';
+
+const CrCardRadioButtonElementBase =
+    mixinBehaviors([PaperRippleBehavior], CrRadioButtonMixin(PolymerElement)) as
+    {
+      new (): PolymerElement & CrRadioButtonMixinInterface &
+          PaperRippleBehavior,
+    };
+
+export interface CrCardRadioButtonElement {
+  $: {
+    button: HTMLElement,
+  };
+}
+
+export class CrCardRadioButtonElement extends CrCardRadioButtonElementBase {
+  static get is() {
+    return 'cr-card-radio-button';
+  }
+
+  static get template() {
+    return getTemplate();
+  }
+
+  // Overridden from CrRadioButtonMixin
+  override getPaperRipple() {
+    return this.getRipple();
+  }
+
+  // Overridden from PaperRippleBehavior
+  /* eslint-disable-next-line @typescript-eslint/naming-convention */
+  override _createRipple() {
+    this._rippleContainer = this.shadowRoot!.querySelector('.disc-wrapper');
+    const ripple = super._createRipple();
+    ripple.id = 'ink';
+    ripple.setAttribute('recenters', '');
+    ripple.classList.add('circle', 'toggle-ink');
+    return ripple;
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'cr-card-radio-button': CrCardRadioButtonElement;
+  }
+}
+
+customElements.define(CrCardRadioButtonElement.is, CrCardRadioButtonElement);
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.d.ts b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.d.ts
deleted file mode 100644
index 2515f43..0000000
--- a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.d.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-import {CrRadioButtonBehavior} from './cr_radio_button_behavior.js';
-
-interface CrRadioButtonElement extends CrRadioButtonBehavior, PolymerElement {
-  $: {
-    button: HTMLElement,
-  };
-}
-
-export {CrRadioButtonElement};
-
-declare global {
-  interface HTMLElementTagNameMap {
-    'cr-radio-button': CrRadioButtonElement;
-  }
-}
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.js b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.js
deleted file mode 100644
index 960a676..0000000
--- a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.js
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import '//resources/polymer/v3_0/paper-styles/color.js';
-import '../hidden_style_css.m.js';
-import '../shared_vars_css.m.js';
-import './cr_radio_button_style.css.js';
-
-import {html, mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-import {CrRadioButtonBehavior, CrRadioButtonBehaviorInterface} from './cr_radio_button_behavior.js';
-
-/**
- * @constructor
- * @extends {PolymerElement}
- * @implements {CrRadioButtonBehaviorInterface}
- */
-const CrRadioButtonElementBase =
-    mixinBehaviors([CrRadioButtonBehavior], PolymerElement);
-
-/** @polymer */
-export class CrRadioButtonElement extends CrRadioButtonElementBase {
-  static get is() {
-    return 'cr-radio-button';
-  }
-
-  static get template() {
-    return html`{__html_template__}`;
-  }
-}
-
-customElements.define(CrRadioButtonElement.is, CrRadioButtonElement);
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.ts b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.ts
new file mode 100644
index 0000000..9a67e44
--- /dev/null
+++ b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.ts
@@ -0,0 +1,60 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import '//resources/polymer/v3_0/paper-styles/color.js';
+import '../hidden_style_css.m.js';
+import '../shared_vars_css.m.js';
+import './cr_radio_button_style.css.js';
+
+import {mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {PaperRippleBehavior} from 'chrome://resources/polymer/v3_0/paper-behaviors/paper-ripple-behavior.js';
+
+import {getTemplate} from './cr_radio_button.html.js';
+import {CrRadioButtonMixin, CrRadioButtonMixinInterface} from './cr_radio_button_mixin.js';
+
+const CrRadioButtonElementBase = mixinBehaviors(
+                                     [PaperRippleBehavior],
+                                     CrRadioButtonMixin(PolymerElement)) as {
+  new (): PolymerElement & CrRadioButtonMixinInterface & PaperRippleBehavior,
+};
+
+export interface CrRadioButtonElement {
+  $: {
+    button: HTMLElement,
+  };
+}
+
+export class CrRadioButtonElement extends CrRadioButtonElementBase {
+  static get is() {
+    return 'cr-radio-button';
+  }
+
+  static get template() {
+    return getTemplate();
+  }
+
+  // Overridden from CrRadioButtonMixin
+  override getPaperRipple() {
+    return this.getRipple();
+  }
+
+  // Overridden from PaperRippleBehavior
+  /* eslint-disable-next-line @typescript-eslint/naming-convention */
+  override _createRipple() {
+    this._rippleContainer = this.shadowRoot!.querySelector('.disc-wrapper');
+    const ripple = super._createRipple();
+    ripple.id = 'ink';
+    ripple.setAttribute('recenters', '');
+    ripple.classList.add('circle', 'toggle-ink');
+    return ripple;
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'cr-radio-button': CrRadioButtonElement;
+  }
+}
+
+customElements.define(CrRadioButtonElement.is, CrRadioButtonElement);
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.d.ts b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.d.ts
deleted file mode 100644
index 850f2e10..0000000
--- a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.d.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {PaperRippleBehavior} from 'chrome://resources/polymer/v3_0/paper-behaviors/paper-ripple-behavior.js';
-
-export interface CrRadioButtonBehavior extends PaperRippleBehavior {
-  checked: boolean;
-  disabled: boolean;
-  focusable: boolean;
-  label: string;
-  name: string;
-}
-
-declare const CrRadioButtonBehavior: object;
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.html b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.html
deleted file mode 100644
index 2e54cc3..0000000
--- a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-behaviors/paper-ripple-behavior.html">
-<script src="cr_radio_button_behavior.js"></script>
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.js b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.js
deleted file mode 100644
index 20105f01..0000000
--- a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.js
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview Behavior for cr-radio-button-like elements.
- */
-
-// clang-format off
-import {PaperRippleBehavior} from 'chrome://resources/polymer/v3_0/paper-behaviors/paper-ripple-behavior.js';
-// clang-format on
-
-/** @polymerBehavior */
-const CrRadioButtonBehaviorImpl = {
-  properties: {
-    checked: {
-      type: Boolean,
-      value: false,
-      reflectToAttribute: true,
-    },
-
-    disabled: {
-      type: Boolean,
-      value: false,
-      reflectToAttribute: true,
-      notify: true,
-    },
-
-    /**
-     * Whether the radio button should be focusable or not. Toggling this
-     * property sets the corresponding tabindex of the button itself as well
-     * as any links in the button description.
-     */
-    focusable: {
-      type: Boolean,
-      value: false,
-      observer: 'onFocusableChanged_',
-    },
-
-    label: {
-      type: String,
-      value: '',  // Allows the hidden$= binding to run without being set.
-    },
-
-    name: {
-      type: String,
-      notify: true,
-      reflectToAttribute: true,
-    },
-
-    /**
-     * Holds the tabIndex for the radio button.
-     * @private {number}
-     */
-    buttonTabIndex_: {
-      type: Number,
-      computed: 'getTabIndex_(focusable)',
-    },
-  },
-
-  listeners: {
-    blur: 'hideRipple_',
-    focus: 'onFocus_',
-    up: 'hideRipple_',
-  },
-
-  focus() {
-    this.$.button.focus();
-  },
-
-  /** @private */
-  onFocusableChanged_() {
-    const links = this.querySelectorAll('a');
-    links.forEach((link) => {
-      // Remove the tab stop on any links when the row is unchecked. Since the
-      // row is not tabbable, any links within the row should not be either.
-      link.tabIndex = this.checked ? 0 : -1;
-    });
-  },
-
-  /** @private */
-  onFocus_() {
-    this.getRipple().showAndHoldDown();
-  },
-
-  /** @private */
-  hideRipple_() {
-    this.getRipple().clear();
-  },
-
-  /**
-   * @return {string}
-   * @private
-   */
-  getAriaChecked_() {
-    return this.checked ? 'true' : 'false';
-  },
-
-  /**
-   * @return {string}
-   * @private
-   */
-  getAriaDisabled_() {
-    return this.disabled ? 'true' : 'false';
-  },
-
-  /**
-   * @return {number}
-   * @private
-   */
-  getTabIndex_() {
-    return this.focusable ? 0 : -1;
-  },
-
-  /**
-   * When shift-tab is pressed, first bring the focus to the host element.
-   * This accomplishes 2 things:
-   * 1) Host doesn't get focused when the browser moves the focus backward.
-   * 2) focus now escaped the shadow-dom of this element, so that it'll
-   *    correctly obey non-zero tabindex ordering of the containing document.
-   * @param {!Event} e
-   * @private
-   */
-  onInputKeydown_(e) {
-    if (e.shiftKey && e.key === 'Tab') {
-      this.focus();
-    }
-  },
-
-  // customize the element's ripple
-  _createRipple() {
-    this._rippleContainer = this.$$('.disc-wrapper');
-    const ripple = PaperRippleBehavior._createRipple();
-    ripple.id = 'ink';
-    ripple.setAttribute('recenters', '');
-    ripple.classList.add('circle', 'toggle-ink');
-    return ripple;
-  },
-};
-
-
-/** @polymerBehavior */
-export const CrRadioButtonBehavior = [
-  PaperRippleBehavior,
-  CrRadioButtonBehaviorImpl,
-];
-
-/** @interface */
-export class CrRadioButtonBehaviorInterface {
-  constructor() {
-    /** @type {boolean} */
-    this.checked;
-
-    /** @type {boolean} */
-    this.disabled;
-  }
-
-  /** @return  {!PaperRippleElement} */
-  getRipple() {}
-}
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_externs.js b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_externs.js
new file mode 100644
index 0000000..920bc701
--- /dev/null
+++ b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_externs.js
@@ -0,0 +1,42 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/* Minimal externs file provided for places in the code that
+ * still use JavaScript instead of TypeScript.
+ * @externs
+ */
+
+/** @interface */
+class CrRadioButtonMixinInterface {
+  constructor() {
+    /** @type {boolean} */
+    this.checked;
+
+    /** @type {boolean} */
+    this.disabled;
+
+    /** @type {boolean} */
+    this.focusabled;
+
+    /** @type {string} */
+    this.name;
+  }
+
+  /** @return {HTMLElement} */
+  getPaperRipple() {}
+}
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @implements {CrRadioButtonMixinInterface}
+ */
+function CrRadioButtonElement() {}
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @implements {CrRadioButtonMixinInterface}
+ */
+function CrCardRadioButtonElement() {}
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_mixin.ts b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_mixin.ts
new file mode 100644
index 0000000..b09bd8c
--- /dev/null
+++ b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_mixin.ts
@@ -0,0 +1,154 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Mixin for cr-radio-button-like elements.
+ */
+
+// clang-format off
+import {dedupingMixin, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {assert, assertNotReached} from '../../js/assert_ts.js';
+
+interface PaperRippleElement {
+  clear(): void;
+  showAndHoldDown(): void;
+}
+
+type Constructor<T> = new (...args: any[]) => T;
+
+export const CrRadioButtonMixin = dedupingMixin(
+    <T extends Constructor<PolymerElement>>(superClass: T): T&
+    Constructor<CrRadioButtonMixinInterface> => {
+      class CrRadioButtonMixin extends superClass implements
+          CrRadioButtonMixinInterface {
+        static get properties() {
+          return {
+            checked: {
+              type: Boolean,
+              value: false,
+              reflectToAttribute: true,
+            },
+
+            disabled: {
+              type: Boolean,
+              value: false,
+              reflectToAttribute: true,
+              notify: true,
+            },
+
+            /**
+             * Whether the radio button should be focusable or not. Toggling
+             * this property sets the corresponding tabindex of the button
+             * itself as well as any links in the button description.
+             */
+            focusable: {
+              type: Boolean,
+              value: false,
+              observer: 'onFocusableChanged_',
+            },
+
+            label: {
+              type: String,
+              value: '',  // Allows hidden$= binding to run without being set.
+            },
+
+            name: {
+              type: String,
+              notify: true,
+              reflectToAttribute: true,
+            },
+
+            /**
+             * Holds the tabIndex for the radio button.
+             */
+            buttonTabIndex_: {
+              type: Number,
+              computed: 'getTabIndex_(focusable)',
+            },
+          };
+        }
+
+        checked: boolean;
+        disabled: boolean;
+        focusable: boolean;
+        label: string;
+        name: string;
+        private buttonTabIndex_: number;
+
+        override connectedCallback() {
+          super.connectedCallback();
+          this.addEventListener('blur', this.hideRipple_.bind(this));
+          this.addEventListener('focus', this.onFocus_.bind(this));
+          this.addEventListener('up', this.hideRipple_.bind(this));
+        }
+
+        override focus() {
+          const button = this.shadowRoot!.querySelector<HTMLElement>('#button');
+          assert(button);
+          button.focus();
+        }
+
+        getPaperRipple(): PaperRippleElement {
+          assertNotReached();
+        }
+
+        private onFocus_() {
+          this.getPaperRipple().showAndHoldDown();
+        }
+
+        private hideRipple_() {
+          this.getPaperRipple().clear();
+        }
+
+        private onFocusableChanged_() {
+          const links = this.querySelectorAll('a');
+          links.forEach((link) => {
+            // Remove the tab stop on any links when the row is unchecked.
+            // Since the row is not tabbable, any links within the row
+            // should not be either.
+            link.tabIndex = this.checked ? 0 : -1;
+          });
+        }
+
+        private getAriaChecked_(): string {
+          return this.checked ? 'true' : 'false';
+        }
+
+        private getAriaDisabled_(): string {
+          return this.disabled ? 'true' : 'false';
+        }
+
+        private getTabIndex_(): number {
+          return this.focusable ? 0 : -1;
+        }
+
+        /**
+         * When shift-tab is pressed, first bring the focus to the host
+         * element. This accomplishes 2 things:
+         * 1) Host doesn't get focused when the browser moves the focus
+         *    backward.
+         * 2) focus now escaped the shadow-dom of this element, so that
+         *    it'll correctly obey non-zero tabindex ordering of the
+         *    containing document.
+         */
+        private onInputKeydown_(e: KeyboardEvent) {
+          if (e.shiftKey && e.key === 'Tab') {
+            this.focus();
+          }
+        }
+      }
+
+      return CrRadioButtonMixin;
+    });
+
+export interface CrRadioButtonMixinInterface {
+  checked: boolean;
+  disabled: boolean;
+  focusable: boolean;
+  label: string;
+  name: string;
+
+  getPaperRipple(): PaperRippleElement;
+}
diff --git a/ui/webui/resources/roboto/OWNERS b/ui/webui/resources/roboto/OWNERS
deleted file mode 100644
index 07a31a62..0000000
--- a/ui/webui/resources/roboto/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-mathp@chromium.org