diff --git a/DEPS b/DEPS
index 0df12657..abf09a15 100644
--- a/DEPS
+++ b/DEPS
@@ -285,15 +285,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': '2594f990d87beb02837a22a78ec4810f95b25bc9',
+  'skia_revision': 'a02244254b13b14171e9386600d28c4faf171a8c',
   # 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': '18894416c9de759907fc9bf7dbb2b6747edd3db3',
+  'v8_revision': 'e6824b24fd32987d810cbfb3c7e8756808f7de32',
   # 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': '735fb48079650cec97ea286e5775f277d90a2cc0',
+  'angle_revision': '28edde6f2b7b306f37ce85527f90586f1ddd5015',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -301,7 +301,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'ca3e52a5e4cba5e557ca390f1f1b1496a621b752',
+  'pdfium_revision': 'd127a657b7b60d08258a84abdde07f6dc6177885',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -312,7 +312,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
-  'fuchsia_version': 'version:12.20230413.2.1',
+  'fuchsia_version': 'version:12.20230414.0.1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -356,7 +356,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '53cc27b20f1bd1d5118ad1e066af46565e943013',
+  'catapult_revision': 'ac30cc4bc7d30e574625e1f6a77fba5df0719ed6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling CrossBench
   # 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': 'a49353d4cd62655ecb72f4cbdb4dce7e370013ec',
+  'dawn_revision': '34d52ffa4c3a4767b1f3ef38cb9c1f5a7a0bdfb7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -476,7 +476,7 @@
 
   # If you change this, also update the libc++ revision in
   # //buildtools/deps_revisions.gni.
-  'libcxx_revision':       'a112d60e2f99bce2892f6aa75b7a6999cdcf8961',
+  'libcxx_revision':       '5488b5c294dd4b9640adbef628f2dcd6f85a6c09',
 
   # GN CIPD package version.
   'gn_version': 'git_revision:ffeea1b1fd070cb6a8d47154a03f8523486b50a7',
@@ -771,7 +771,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    'b65b833c6bbfe6b9eeb583162a968d4b31ceaf4f',
+    '30ac3a862baa8684f6f5aa049f16090213c9eb16',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -960,7 +960,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'pY61Naw_tF_wdhH7RNSoEoedMS5fPOzV1TdWCMRd_kUC',
+          'version': 'lFc_klEJZUxS7DOOp7ntguh9s_BntjOYTGFeDi9HIwQC',
       },
     ],
     'condition': 'checkout_android',
@@ -1201,7 +1201,7 @@
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '0f7452c2ee63313e10790f31f5a094baf47fa444',
+      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '38bffe7c5f59e937ea6cc13ab01436eb9e2ab0fa',
     'condition': 'checkout_src_internal',
   },
 
@@ -1676,7 +1676,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'd4f6e083e11e78c7370e0ce938be04c5d556cb0f',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '73a3aa98dc279a67a513bfd62aadad0872f715ad',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1861,7 +1861,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '3171daccdd89ae5c693399bc0c18db4c381527a1',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '242ca2b5d198d983c756cf49a12df0cd2b366c19',
+    Var('webrtc_git') + '/src.git' + '@' + 'fa6da49db39d759f141c528deaf6b1cdc80fc30f',
 
   # Wuffs' canonical repository is at github.com/google/wuffs, but we use
   # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
@@ -1951,7 +1951,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': Var('chrome_git') + '/chrome/src-internal.git@726354df5b77533ca4391ab983468febb0982a9b',
+    'url': Var('chrome_git') + '/chrome/src-internal.git@d1fea3f706ce8594b8b15ff492b7f3a850f3870a',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/gfx/aw_vulkan_context_provider.h b/android_webview/browser/gfx/aw_vulkan_context_provider.h
index 6414902..691a53b 100644
--- a/android_webview/browser/gfx/aw_vulkan_context_provider.h
+++ b/android_webview/browser/gfx/aw_vulkan_context_provider.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/memory/raw_ptr_exclusion.h"
 #include "components/viz/common/gpu/vulkan_context_provider.h"
 #include "gpu/vulkan/vulkan_device_queue.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -41,7 +42,9 @@
     ~ScopedSecondaryCBDraw() { provider_->SecondaryCMBDrawSubmitted(); }
 
    private:
-    AwVulkanContextProvider* const provider_;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #union
+    RAW_PTR_EXCLUSION AwVulkanContextProvider* const provider_;
   };
 
   AwVulkanContextProvider(const AwVulkanContextProvider&) = delete;
diff --git a/android_webview/browser/gfx/overlay_processor_webview.h b/android_webview/browser/gfx/overlay_processor_webview.h
index 6d649a8..d53fbba 100644
--- a/android_webview/browser/gfx/overlay_processor_webview.h
+++ b/android_webview/browser/gfx/overlay_processor_webview.h
@@ -7,6 +7,7 @@
 
 #include "android_webview/browser/gfx/display_scheduler_webview.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/weak_ptr.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread_checker.h"
@@ -37,7 +38,9 @@
     ~ScopedSurfaceControlAvailable();
 
    private:
-    OverlayProcessorWebView* processor_;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #union
+    RAW_PTR_EXCLUSION OverlayProcessorWebView* processor_;
   };
 
   OverlayProcessorWebView(
diff --git a/android_webview/browser/gfx/scoped_app_gl_state_restore_impl.h b/android_webview/browser/gfx/scoped_app_gl_state_restore_impl.h
index c9fd1b3..2933b71 100644
--- a/android_webview/browser/gfx/scoped_app_gl_state_restore_impl.h
+++ b/android_webview/browser/gfx/scoped_app_gl_state_restore_impl.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "android_webview/browser/gfx/scoped_app_gl_state_restore.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "ui/gl/gl_bindings.h"
 
 namespace android_webview {
@@ -41,7 +42,9 @@
     GLint type;
     GLint normalized;
     GLint stride;
-    GLvoid* pointer;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #addr-of
+    RAW_PTR_EXCLUSION GLvoid* pointer;
     GLint vertex_attrib_array_buffer_binding;
     GLfloat current_vertex_attrib[4];
   };
diff --git a/android_webview/browser/gfx/vulkan_gl_interop.h b/android_webview/browser/gfx/vulkan_gl_interop.h
index f650480..70f1533 100644
--- a/android_webview/browser/gfx/vulkan_gl_interop.h
+++ b/android_webview/browser/gfx/vulkan_gl_interop.h
@@ -12,6 +12,7 @@
 #include "base/android/scoped_hardware_buffer_handle.h"
 #include "base/containers/queue.h"
 #include "base/files/scoped_file.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/scoped_refptr.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/gpu/vk/GrVkTypes.h"
@@ -75,8 +76,12 @@
     raw_ptr<AwVulkanContextProvider> vk_context_provider;
   };
 
-  RenderThreadManager* const render_thread_manager_;
-  AwVulkanContextProvider* const vulkan_context_provider_;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #union
+  RAW_PTR_EXCLUSION RenderThreadManager* const render_thread_manager_;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #union
+  RAW_PTR_EXCLUSION AwVulkanContextProvider* const vulkan_context_provider_;
 
   // GL context used to draw via GL in Vk interop path.
   scoped_refptr<GLNonOwnedCompatibilityContext> gl_context_;
diff --git a/android_webview/js_sandbox/service/js_sandbox_isolate.h b/android_webview/js_sandbox/service/js_sandbox_isolate.h
index c90ad64..2c9ab2e 100644
--- a/android_webview/js_sandbox/service/js_sandbox_isolate.h
+++ b/android_webview/js_sandbox/service/js_sandbox_isolate.h
@@ -13,6 +13,7 @@
 #include "base/compiler_specific.h"
 #include "base/files/scoped_file.h"
 #include "base/functional/callback_forward.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/synchronization/lock.h"
 #include "base/thread_annotations.h"
@@ -174,7 +175,9 @@
   // of an evaluation is a JS promise which is pending resolution/rejection.
   //
   // This pointer must only be accessed from the isolate thread.
-  JsSandboxIsolateCallback* current_callback_;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #addr-of
+  RAW_PTR_EXCLUSION JsSandboxIsolateCallback* current_callback_;
 
   bool console_enabled_;
 
diff --git a/ash/clipboard/clipboard_history_controller_unittest.cc b/ash/clipboard/clipboard_history_controller_unittest.cc
index 5aa782c..23ff510 100644
--- a/ash/clipboard/clipboard_history_controller_unittest.cc
+++ b/ash/clipboard/clipboard_history_controller_unittest.cc
@@ -24,6 +24,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/test_future.h"
 #include "base/unguessable_token.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/clipboard/clipboard_buffer.h"
@@ -603,8 +604,13 @@
       public testing::WithParamInterface</*refresh_enabled=*/bool> {
  public:
   ClipboardHistoryControllerRefreshTest() {
-    scoped_feature_list_.InitWithFeatureState(
-        features::kClipboardHistoryRefresh, IsClipboardHistoryRefreshEnabled());
+    std::vector<base::test::FeatureRef> refresh_features = {
+        features::kClipboardHistoryRefresh, chromeos::features::kJelly};
+    std::vector<base::test::FeatureRef> enabled_features;
+    std::vector<base::test::FeatureRef> disabled_features;
+    (IsClipboardHistoryRefreshEnabled() ? enabled_features : disabled_features)
+        .swap(refresh_features);
+    scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
   }
 
   bool IsClipboardHistoryRefreshEnabled() const { return GetParam(); }
diff --git a/ash/components/arc/session/arc_session_impl.cc b/ash/components/arc/session/arc_session_impl.cc
index 4f5140a..3e11252e5 100644
--- a/ash/components/arc/session/arc_session_impl.cc
+++ b/ash/components/arc/session/arc_session_impl.cc
@@ -464,8 +464,8 @@
           arc::kKeyboardShortcutHelperIntegrationFeature);
   params.lcd_density = lcd_density_;
   params.num_cores_disabled = num_cores_disabled;
-  params.enable_notifications_refresh =
-      ash::features::IsNotificationsRefreshEnabled();
+  // TODO(b/278121256): Remove pre-NotificationsRefresh code from ARC.
+  params.enable_notifications_refresh = true;
   params.enable_tts_caching = true;
   params.enable_consumer_auto_update_toggle = base::FeatureList::IsEnabled(
       ash::features::kConsumerAutoUpdateToggleAllowed);
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 4b8f9ce0..897da2e 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -346,7 +346,7 @@
              base::FEATURE_DISABLED_BY_DEFAULT);
 
 // Enables updated UI for the clipboard history menu and new system behavior
-// related to clipboard history.
+// related to clipboard history. Requires jelly-colors flag to also be enabled.
 BASE_FEATURE(kClipboardHistoryRefresh,
              "ClipboardHistoryRefresh",
              base::FEATURE_DISABLED_BY_DEFAULT);
@@ -1521,11 +1521,6 @@
              "NotificationsInContextMenu",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-// Enables new notifications UI and grouped notifications.
-BASE_FEATURE(kNotificationsRefresh,
-             "NotificationsRefresh",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 // Controls whether to enable on-device grammar check service.
 BASE_FEATURE(kOnDeviceGrammarCheck,
              "OnDeviceGrammarCheck",
@@ -2538,7 +2533,8 @@
 }
 
 bool IsClipboardHistoryRefreshEnabled() {
-  return base::FeatureList::IsEnabled(kClipboardHistoryRefresh);
+  return chromeos::features::IsJellyEnabled() &&
+         base::FeatureList::IsEnabled(kClipboardHistoryRefresh);
 }
 
 bool IsClipboardHistoryReorderEnabled() {
@@ -3047,10 +3043,6 @@
   return base::FeatureList::IsEnabled(kNotificationsInContextMenu);
 }
 
-bool IsNotificationsRefreshEnabled() {
-  return base::FeatureList::IsEnabled(kNotificationsRefresh);
-}
-
 bool IsOobeChromeVoxHintEnabled() {
   return base::FeatureList::IsEnabled(kEnableOobeChromeVoxHint);
 }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index a22c82e1..9418c24 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -442,7 +442,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kNotificationScrollBar);
 COMPONENT_EXPORT(ASH_CONSTANTS)
 BASE_DECLARE_FEATURE(kNotificationsInContextMenu);
-COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kNotificationsRefresh);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kOnDeviceGrammarCheck);
 COMPONENT_EXPORT(ASH_CONSTANTS)
 BASE_DECLARE_FEATURE(kOnDeviceSpeechRecognition);
@@ -819,7 +818,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsNotificationImageDragEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsNotificationScrollBarEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsNotificationsInContextMenuEnabled();
-COMPONENT_EXPORT(ASH_CONSTANTS) bool IsNotificationsRefreshEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOAuthIppEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeChoobeEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeDriveOfflineEnabled();
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc b/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc
index 808aa35..8ee7067a 100644
--- a/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc
+++ b/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc
@@ -260,9 +260,7 @@
 
 // static
 int ArcNotificationContentView::GetNotificationContentViewWidth() {
-  return features::IsNotificationsRefreshEnabled()
-             ? kNotificationInMessageCenterWidth
-             : message_center::kNotificationWidth;
+  return kNotificationInMessageCenterWidth;
 }
 
 ArcNotificationContentView::ArcNotificationContentView(
@@ -274,17 +272,14 @@
       event_forwarder_(std::make_unique<EventForwarder>(this)),
       mouse_enter_exit_handler_(std::make_unique<MouseEnterExitHandler>(this)),
       message_view_(message_view),
-      control_buttons_view_(message_view),
-      notification_width_(GetNotificationContentViewWidth()) {
+      control_buttons_view_(message_view) {
   DCHECK(message_view);
   control_buttons_view_.SetNotificationControlButtonFactory(
       std::make_unique<AshNotificationControlButtonFactory>());
 
-  // |notification_width_| must be 360 (or 344 for refreshed notifications),
-  // since this value is separately defined in ArcNotificationWrapperView class
-  // in Android side.
-  DCHECK_EQ(features::IsNotificationsRefreshEnabled() ? 344 : 360,
-            notification_width_);
+  // `kNotificationInMessageCenterWidth` must be 344 since this value is
+  // separately defined in `ArcNotificationWrapperView` class in Android side.
+  static_assert(kNotificationInMessageCenterWidth == 344);
 
   SetFocusBehavior(FocusBehavior::ALWAYS);
   SetNotifyEnterExitOnChild(true);
@@ -491,14 +486,9 @@
     }
   }
 
-  // Maybe this if-branch is not needed but if the refresh flag is disabled we
-  // don't have to call |SchedulePaint()| because the notification background is
-  // opaque. Let's keep this if-branch not to break any existing behavior.
-  if (ash::features::IsNotificationsRefreshEnabled()) {
-    // Setting/resetting |surface_| changes the visibility of the snapshot so we
-    // here request to paint.
-    SchedulePaint();
-  }
+  // Setting/resetting |surface_| changes the visibility of the snapshot so we
+  // here request to paint.
+  SchedulePaint();
 }
 
 void ArcNotificationContentView::UpdatePreferredSize() {
@@ -511,10 +501,10 @@
   if (preferred_size.IsEmpty())
     return;
 
-  if (preferred_size.width() != notification_width_) {
-    const float scale =
-        static_cast<float>(notification_width_) / preferred_size.width();
-    preferred_size.SetSize(notification_width_,
+  if (preferred_size.width() != kNotificationInMessageCenterWidth) {
+    const float scale = static_cast<float>(kNotificationInMessageCenterWidth) /
+                        preferred_size.width();
+    preferred_size.SetSize(kNotificationInMessageCenterWidth,
                            preferred_size.height() * scale);
   }
 
@@ -675,7 +665,8 @@
     const gfx::Size surface_size = surface_->GetSize();
     if (!surface_size.IsEmpty()) {
       const float factor =
-          static_cast<float>(notification_width_) / surface_size.width();
+          static_cast<float>(kNotificationInMessageCenterWidth) /
+          surface_size.width();
       transform.Scale(factor, factor);
     }
 
@@ -726,14 +717,12 @@
         item_->GetSnapshot().height(), contents_bounds.x(), contents_bounds.y(),
         contents_bounds.width(), contents_bounds.height(), true /* filter */);
   } else {
-    // Draw a white background otherwise. The height of the view/ surface and
+    // Draw a clear background otherwise. The height of the view/ surface and
     // animation buffer size are not exactly synced and user may see the blank
     // area out of the surface.
     // TODO: This can be removed once both ARC and Chrome notifications have
     // smooth expansion animations.
-    canvas->DrawColor(ash::features::IsNotificationsRefreshEnabled()
-                          ? SK_ColorTRANSPARENT
-                          : SK_ColorWHITE);
+    canvas->DrawColor(SK_ColorTRANSPARENT);
   }
 }
 
@@ -775,12 +764,10 @@
   if (GetWidget() && GetNativeViewContainer())
     UpdateMask(true);
 
-  if (ash::features::IsNotificationsRefreshEnabled()) {
-    // Adjust control button color.
-    control_buttons_view_.SetButtonIconColors(
-        AshColorProvider::Get()->GetContentLayerColor(
-            AshColorProvider::ContentLayerType::kIconColorPrimary));
-  }
+  // Adjust control button color.
+  control_buttons_view_.SetButtonIconColors(
+      AshColorProvider::Get()->GetContentLayerColor(
+          AshColorProvider::ContentLayerType::kIconColorPrimary));
 }
 
 void ArcNotificationContentView::OnRemoteInputActivationChanged(
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_content_view.h b/ash/public/cpp/external_arc/message_center/arc_notification_content_view.h
index 7e396f5..a09d02a 100644
--- a/ash/public/cpp/external_arc/message_center/arc_notification_content_view.h
+++ b/ash/public/cpp/external_arc/message_center/arc_notification_content_view.h
@@ -67,8 +67,6 @@
 
   bool slide_in_progress() const { return slide_in_progress_; }
 
-  int notification_width() const { return notification_width_; }
-
  private:
   friend class ArcNotificationViewTest;
   friend class ArcNotificationContentViewTest;
@@ -208,8 +206,6 @@
   absl::optional<gfx::Insets> mask_insets_;
 
   std::unique_ptr<ui::LayerTreeOwner> surface_copy_;
-
-  const int notification_width_;
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_view.cc b/ash/public/cpp/external_arc/message_center/arc_notification_view.cc
index d1fcd46..729848a 100644
--- a/ash/public/cpp/external_arc/message_center/arc_notification_view.cc
+++ b/ash/public/cpp/external_arc/message_center/arc_notification_view.cc
@@ -6,7 +6,6 @@
 
 #include <algorithm>
 
-#include "ash/constants/ash_features.h"
 #include "ash/public/cpp/external_arc/message_center/arc_notification_content_view.h"
 #include "ash/public/cpp/external_arc/message_center/arc_notification_item.h"
 #include "ash/public/cpp/message_center/arc_notification_constants.h"
@@ -69,17 +68,12 @@
   AddChildView(content_view_);
 
   if (content_view_->background()) {
-    if (ash::features::IsNotificationsRefreshEnabled()) {
-      background()->SetNativeControlColor(
-          AshColorProvider::Get()->GetBaseLayerColor(
-              AshColorProvider::BaseLayerType::kTransparent80));
-    } else {
-      background()->SetNativeControlColor(
-          content_view_->background()->get_color());
-    }
+    background()->SetNativeControlColor(
+        AshColorProvider::Get()->GetBaseLayerColor(
+            AshColorProvider::BaseLayerType::kTransparent80));
   }
 
-  if (features::IsNotificationsRefreshEnabled() && shown_in_popup) {
+  if (shown_in_popup) {
     layer()->SetBackgroundBlur(ColorProvider::kBackgroundBlurSigma);
     layer()->SetBackdropFilterQuality(ColorProvider::kBackgroundBlurQuality);
     layer()->SetRoundedCornerRadius(
@@ -125,16 +119,12 @@
 }
 
 void ArcNotificationView::UpdateBackgroundPainter() {
-  if (features::IsNotificationsRefreshEnabled()) {
-    SetBackground(views::CreateSolidBackground(
-        shown_in_popup_ ? AshColorProvider::Get()->GetBaseLayerColor(
-                              AshColorProvider::BaseLayerType::kTransparent80)
-                        : AshColorProvider::Get()->GetControlsLayerColor(
-                              AshColorProvider::ControlsLayerType::
-                                  kControlBackgroundColorInactive)));
-  } else {
-    MessageView::UpdateBackgroundPainter();
-  }
+  SetBackground(views::CreateSolidBackground(
+      shown_in_popup_ ? AshColorProvider::Get()->GetBaseLayerColor(
+                            AshColorProvider::BaseLayerType::kTransparent80)
+                      : AshColorProvider::Get()->GetControlsLayerColor(
+                            AshColorProvider::ControlsLayerType::
+                                kControlBackgroundColorInactive)));
 }
 
 void ArcNotificationView::UpdateControlButtonsVisibility() {
@@ -206,15 +196,9 @@
   message_center::MessageView::OnThemeChanged();
 
   // TODO(yhanada): Migrate to views::FocusRing to support rounded-corner ring.
-  if (ash::features::IsNotificationsRefreshEnabled()) {
-    focus_painter_ = views::Painter::CreateSolidFocusPainter(
-        GetColorProvider()->GetColor(ui::kColorFocusableBorderFocused), 2,
-        gfx::InsetsF(3));
-  } else {
-    focus_painter_ = views::Painter::CreateSolidFocusPainter(
-        GetColorProvider()->GetColor(ui::kColorFocusableBorderFocused),
-        gfx::Insets::TLBR(0, 1, 3, 2));
-  }
+  focus_painter_ = views::Painter::CreateSolidFocusPainter(
+      GetColorProvider()->GetColor(ui::kColorFocusableBorderFocused), 2,
+      gfx::InsetsF(3));
 }
 
 void ArcNotificationView::OnContainerAnimationEnded() {
@@ -233,7 +217,7 @@
 
 gfx::Size ArcNotificationView::CalculatePreferredSize() const {
   const gfx::Insets insets = GetInsets();
-  const int contents_width = content_view_->notification_width();
+  const int contents_width = kNotificationInMessageCenterWidth;
   const int contents_height = content_view_->GetHeightForWidth(contents_width);
   return gfx::Size(contents_width + insets.width(),
                    contents_height + insets.height());
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_view_unittest.cc b/ash/public/cpp/external_arc/message_center/arc_notification_view_unittest.cc
index 791b2d6..4ba1261 100644
--- a/ash/public/cpp/external_arc/message_center/arc_notification_view_unittest.cc
+++ b/ash/public/cpp/external_arc/message_center/arc_notification_view_unittest.cc
@@ -4,7 +4,6 @@
 
 #include <memory>
 
-#include "ash/constants/ash_features.h"
 #include "ash/public/cpp/external_arc/message_center/arc_notification_content_view.h"
 #include "ash/public/cpp/external_arc/message_center/arc_notification_item.h"
 #include "ash/public/cpp/external_arc/message_center/arc_notification_surface.h"
@@ -20,7 +19,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
-#include "chromeos/constants/chromeos_features.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/ime/dummy_text_input_client.h"
 #include "ui/base/ime/input_method.h"
@@ -61,8 +59,7 @@
 
 }  // namespace
 
-class ArcNotificationViewTest : public AshTestBase,
-                                public testing::WithParamInterface<bool> {
+class ArcNotificationViewTest : public AshTestBase {
  public:
   ArcNotificationViewTest() = default;
 
@@ -73,19 +70,6 @@
 
   // views::ViewsTestBase
   void SetUp() override {
-    scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
-    if (IsNotificationsRefreshEnabled()) {
-      scoped_feature_list_->InitWithFeatures(
-          /*enabled_features=*/{features::kNotificationsRefresh,
-                                chromeos::features::kDarkLightMode},
-          /*disabled_features=*/{});
-    } else {
-      scoped_feature_list_->InitWithFeatures(
-          /*enabled_features=*/{},
-          /*disabled_features=*/{features::kNotificationsRefresh,
-                                 chromeos::features::kDarkLightMode});
-    }
-
     AshTestBase::SetUp();
 
     item_ = std::make_unique<MockArcNotificationItem>(kDefaultNotificationKey);
@@ -125,8 +109,6 @@
     EXPECT_EQ(widget, notification_view_->GetWidget());
   }
 
-  bool IsNotificationsRefreshEnabled() const { return GetParam(); }
-
   std::unique_ptr<Notification> CreateSimpleNotification() {
     std::unique_ptr<Notification> notification = std::make_unique<Notification>(
         message_center::NOTIFICATION_TYPE_CUSTOM, kDefaultNotificationId,
@@ -231,11 +213,7 @@
   std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
 };
 
-INSTANTIATE_TEST_SUITE_P(All,
-                         ArcNotificationViewTest,
-                         testing::Bool() /* IsNotificationsRefreshEnabled() */);
-
-TEST_P(ArcNotificationViewTest, Events) {
+TEST_F(ArcNotificationViewTest, Events) {
   widget()->Show();
 
   gfx::Point cursor_location(1, 1);
@@ -251,7 +229,7 @@
                 ->FindTargetForEvent(widget()->GetRootView(), &key_event));
 }
 
-TEST_P(ArcNotificationViewTest, SlideOut) {
+TEST_F(ArcNotificationViewTest, SlideOut) {
   ui::ScopedAnimationDurationScaleMode zero_duration_scope(
       ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
 
@@ -281,7 +259,7 @@
 #else
 #define MAYBE_SlideOutNested SlideOutNested
 #endif
-TEST_P(ArcNotificationViewTest, MAYBE_SlideOutNested) {
+TEST_F(ArcNotificationViewTest, MAYBE_SlideOutNested) {
   ui::ScopedAnimationDurationScaleMode zero_duration_scope(
       ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
 
@@ -306,7 +284,7 @@
   EXPECT_TRUE(IsRemovedAfterIdle(notification_id));
 }
 
-TEST_P(ArcNotificationViewTest, SlideOutPinned) {
+TEST_F(ArcNotificationViewTest, SlideOutPinned) {
   ui::ScopedAnimationDurationScaleMode zero_duration_scope(
       ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
 
@@ -326,7 +304,7 @@
   EXPECT_FALSE(IsRemovedAfterIdle(notification_id));
 }
 
-TEST_P(ArcNotificationViewTest, SnoozeButton) {
+TEST_F(ArcNotificationViewTest, SnoozeButton) {
   ui::ScopedAnimationDurationScaleMode zero_duration_scope(
       ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
 
@@ -347,7 +325,7 @@
             notification_view()->GetControlButtonsView()->snooze_button());
 }
 
-TEST_P(ArcNotificationViewTest, PressBackspaceKey) {
+TEST_F(ArcNotificationViewTest, PressBackspaceKey) {
   std::string notification_id(kDefaultNotificationId);
   content_view()->RequestFocus();
 
@@ -364,7 +342,7 @@
   input_method->SetFocusedTextInputClient(nullptr);
 }
 
-TEST_P(ArcNotificationViewTest, PressBackspaceKeyOnEditBox) {
+TEST_F(ArcNotificationViewTest, PressBackspaceKeyOnEditBox) {
   std::string notification_id(kDefaultNotificationId);
   content_view()->RequestFocus();
 
@@ -383,26 +361,23 @@
   input_method->SetFocusedTextInputClient(nullptr);
 }
 
-TEST_P(ArcNotificationViewTest, ChangeContentHeight) {
+TEST_F(ArcNotificationViewTest, ChangeContentHeight) {
   // Default size.
   gfx::Size size = notification_view()->GetPreferredSize();
   size.Enlarge(0, -notification_view()->GetInsets().height());
-  EXPECT_EQ(IsNotificationsRefreshEnabled() ? "344x100" : "360x100",
-            size.ToString());
+  EXPECT_EQ("344x100", size.ToString());
 
   // Allow small notifications.
   content_view()->SetPreferredSize(gfx::Size(10, 10));
   size = notification_view()->GetPreferredSize();
   size.Enlarge(0, -notification_view()->GetInsets().height());
-  EXPECT_EQ(IsNotificationsRefreshEnabled() ? "344x10" : "360x10",
-            size.ToString());
+  EXPECT_EQ("344x10", size.ToString());
 
   // The long notification.
   content_view()->SetPreferredSize(gfx::Size(1000, 1000));
   size = notification_view()->GetPreferredSize();
   size.Enlarge(0, -notification_view()->GetInsets().height());
-  EXPECT_EQ(IsNotificationsRefreshEnabled() ? "344x1000" : "360x1000",
-            size.ToString());
+  EXPECT_EQ("344x1000", size.ToString());
 }
 
 }  // namespace ash
diff --git a/ash/webui/camera_app_ui/resources/BUILD.gn b/ash/webui/camera_app_ui/resources/BUILD.gn
index 956fd0e7..241358a4 100644
--- a/ash/webui/camera_app_ui/resources/BUILD.gn
+++ b/ash/webui/camera_app_ui/resources/BUILD.gn
@@ -18,7 +18,7 @@
   }
 
   outputs = [ "$target_gen_dir/js/preload_images.js" ]
-  response_file_contents = inputs
+  response_file_contents = rebase_path(inputs)
   args = [
     "--output_file",
     rebase_path(outputs[0], root_build_dir),
@@ -66,7 +66,11 @@
 }
 
 ts_library("build_ts") {
-  deps = [ "//ui/webui/resources/mojo:build_ts" ]
+  deps = [
+    "//third_party/material_web_components:bundle_lit_ts",
+    "//third_party/material_web_components:library",
+    "//ui/webui/resources/mojo:build_ts",
+  ]
 
   tsconfig_base = "tsconfig_base.json"
   root_dir = target_gen_dir
diff --git a/ash/webui/camera_app_ui/resources/css/main.css b/ash/webui/camera_app_ui/resources/css/main.css
index 94c651c..76183fb 100644
--- a/ash/webui/camera_app_ui/resources/css/main.css
+++ b/ash/webui/camera_app_ui/resources/css/main.css
@@ -675,10 +675,6 @@
   background-image: url(/images/camera_button_mic_off.svg);
 }
 
-#open-settings {
-  background-image: url(/images/camera_button_settings.svg);
-}
-
 body.should-handle-intent-result #open-settings {
   display: none;
 }
@@ -1559,3 +1555,7 @@
   height: 20px;
   width: 20px;
 }
+
+#open-settings {
+  --color: white;
+}
diff --git a/ash/webui/camera_app_ui/resources/images/camera_button_settings.svg b/ash/webui/camera_app_ui/resources/images/camera_button_settings.svg
index 1957c1de..23fcc25 100644
--- a/ash/webui/camera_app_ui/resources/images/camera_button_settings.svg
+++ b/ash/webui/camera_app_ui/resources/images/camera_button_settings.svg
@@ -1,25 +1,3 @@
-<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-    <defs>
-        <filter x="-52.5%" y="-52.5%" width="205.0%" height="205.0%" filterUnits="objectBoundingBox" id="filter-1">
-            <feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
-            <feGaussianBlur stdDeviation="1.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
-            <feColorMatrix values="0 0 0 0 0.125490196   0 0 0 0 0.129411765   0 0 0 0 0.141176471  0 0 0 0.3 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
-            <feMerge>
-                <feMergeNode in="shadowMatrixOuter1"></feMergeNode>
-                <feMergeNode in="SourceGraphic"></feMergeNode>
-            </feMerge>
-        </filter>
-        <path d="M11.6628542,19 L8.33386438,19 C7.66806642,19 7.11023569,18.5256223 7.02926026,17.8843338 L6.78633397,16.2240117 C6.54340769,16.1010249 6.30947867,15.9692533 6.07554965,15.8199122 L4.45604108,16.4524158 C3.82623219,16.6808199 3.13344241,16.4260615 2.82753524,15.8814056 L1.18103486,13.0966325 C0.866130414,12.5168375 1.00108946,11.8316252 1.50493657,11.4450952 L2.88151886,10.3997072 C2.87252159,10.2679356 2.86352432,10.136164 2.86352432,9.99560761 C2.86352432,9.86383602 2.87252159,9.72327965 2.88151886,9.59150805 L1.51393384,8.54612006 C0.983094922,8.15080527 0.848135875,7.43923865 1.18103486,6.89458272 L2.84552978,4.09224012 C3.15143695,3.54758419 3.84422673,3.30161054 4.45604108,3.53879941 L6.08454692,4.18008785 C6.31847594,4.03074671 6.55240496,3.89897511 6.78633397,3.77598829 L7.02926026,2.09809663 C7.11023569,1.48316252 7.66806642,1 8.32486711,1 L11.653857,1 C12.3196549,1 12.8774857,1.47437775 12.9584611,2.11566618 L13.2013874,3.77598829 C13.4443137,3.89897511 13.6782427,4.03074671 13.9121717,4.18008785 L15.5316803,3.54758419 C16.1704864,3.31918009 16.8632762,3.57393851 17.1691834,4.11859444 L18.824681,6.91215227 C19.1485827,7.49194729 19.0046264,8.17715959 18.5007793,8.5636896 L17.1331943,9.6090776 C17.1421916,9.74084919 17.1511888,9.87262079 17.1511888,10.0131772 C17.1511888,10.1537335 17.1421916,10.2855051 17.1331943,10.4172767 L18.5007793,11.4626647 C19.0046264,11.8579795 19.1485827,12.5431918 18.8336783,13.0966325 L17.1601861,15.9253294 C16.8542789,16.4699854 16.1614891,16.715959 15.5406775,16.4787701 L13.921169,15.8462665 C13.6872399,15.9956076 13.4533109,16.1273792 13.2193819,16.250366 L12.9764556,17.9282577 C12.8864829,18.5256223 12.3286522,19 11.6628542,19 Z M11.1859989,17.6559297 L11.1859989,17.6734993 L11.1859989,17.6559297 Z M8.81071969,17.6383602 L8.81071969,17.6559297 C8.81971696,17.6559297 8.81971696,17.6471449 8.81071969,17.6383602 Z M8.75673607,17.2430454 L11.2399825,17.2430454 L11.5728815,15.0029283 L12.0497368,14.8096633 C12.4456167,14.6515373 12.8414966,14.4231332 13.255371,14.124451 L13.6602481,13.8257687 L15.8015984,14.6691069 L17.0432216,12.5607613 L15.2167758,11.1727672 L15.2797567,10.6808199 C15.3067485,10.4524158 15.3337403,10.2327965 15.3337403,9.99560761 C15.3337403,9.75841874 15.3067485,9.53001464 15.2797567,9.31039531 L15.2167758,8.81844802 L17.0432216,7.43045388 L15.7926011,5.32210835 L13.6422536,6.16544656 L13.2373764,5.8579795 C12.8594911,5.57686676 12.454614,5.34846266 12.0407396,5.18155198 L11.5728815,4.98828697 L11.2399825,2.74816984 L8.75673607,2.74816984 L8.42383708,4.98828697 L7.94698178,5.1727672 C7.55110191,5.33967789 7.15522203,5.55929722 6.74134762,5.86676428 L6.33647048,6.15666179 L4.19512026,5.32210835 L2.94449975,7.42166911 L4.77094553,8.80966325 L4.70796464,9.30161054 C4.68097283,9.53001464 4.65398102,9.76720351 4.65398102,9.99560761 C4.65398102,10.2240117 4.67197556,10.4612006 4.70796464,10.6808199 L4.77094553,11.1727672 L2.94449975,12.5607613 L4.18612299,14.6691069 L6.33647048,13.8257687 L6.74134762,14.1332357 C7.12823023,14.4231332 7.51511283,14.6427526 7.93798451,14.8096633 L8.41483981,15.0029283 L8.75673607,17.2430454 Z M15.5946611,15.0204978 C15.5946611,15.0292826 15.5856639,15.0380673 15.5856639,15.0468521 L15.5946611,15.0204978 Z M4.39306019,15.011713 L4.40205746,15.0292826 C4.40205746,15.0204978 4.39306019,15.011713 4.39306019,15.011713 Z M15.5946611,4.96193265 C15.5946611,4.97071742 15.6036584,4.9795022 15.6036584,4.9795022 L15.5946611,4.96193265 Z M4.41105473,4.9443631 L4.40205746,4.96193265 C4.40205746,4.96193265 4.41105473,4.95314788 4.41105473,4.9443631 Z M11.1770017,2.33528551 L11.1770017,2.35285505 L11.1770017,2.33528551 Z M9.99835931,6.92093704 C8.87331407,6.92093702 7.83372939,7.50696591 7.27120676,8.45827231 C6.70868414,9.4095787 6.70868414,10.5816365 7.27120676,11.5329429 C7.83372939,12.4842493 8.87331407,13.0702782 9.99835931,13.0702782 C11.7375285,13.0702782 13.1474038,11.6937013 13.1474038,9.99560761 C13.1474038,8.29751395 11.7375285,6.92093704 9.99835931,6.92093704 Z" id="path-2"></path>
-    </defs>
-    <g id="Mocks" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
-        <g id="camera_grid_3:3" transform="translate(2.000000, 2.000000)">
-            <g id="ic_settings" filter="url(#filter-1)">
-                <polygon id="Shape" points="0 0 20 0 20 20 0 20"></polygon>
-                <mask id="mask-3" fill="white">
-                    <use xlink:href="#path-2"></use>
-                </mask>
-                <use id="ic_settings_24px" fill="#FFFFFF" fill-rule="nonzero" xlink:href="#path-2"></use>
-            </g>
-        </g>
-    </g>
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M11.4781 18H8.51899C7.92717 18 7.43132 17.5783 7.35934 17.0083L7.14341 15.5325C6.92747 15.4231 6.71954 15.306 6.5116 15.1733L5.07204 15.7355C4.51221 15.9385 3.89639 15.7121 3.62448 15.2279L2.16092 12.7526C1.881 12.2372 2.00097 11.6281 2.44883 11.2845L3.67246 10.3553C3.66446 10.2382 3.65647 10.121 3.65647 9.9961C3.65647 9.87897 3.66446 9.75403 3.67246 9.6369L2.45683 8.70766C1.98497 8.35627 1.86501 7.72377 2.16092 7.23963L3.64047 4.74866C3.91239 4.26452 4.5282 4.04588 5.07204 4.25671L6.5196 4.82674C6.72753 4.694 6.93547 4.57687 7.14341 4.46755L7.35934 2.97609C7.43132 2.42948 7.92717 2 8.51099 2H11.4701C12.0619 2 12.5578 2.42167 12.6297 2.9917L12.8457 4.46755C13.0616 4.57687 13.2695 4.694 13.4775 4.82674L14.917 4.26452C15.4849 4.06149 16.1007 4.28795 16.3726 4.77208L17.8442 7.25525C18.1321 7.77062 18.0041 8.3797 17.5562 8.72328L16.3406 9.65251C16.3486 9.76964 16.3566 9.88677 16.3566 10.0117C16.3566 10.1367 16.3486 10.2538 16.3406 10.3709L17.5562 11.3001C18.0041 11.6515 18.1321 12.2606 17.8522 12.7526L16.3646 15.267C16.0927 15.7511 15.4769 15.9697 14.925 15.7589L13.4855 15.1967C13.2775 15.3294 13.0696 15.4466 12.8617 15.5559L12.6457 17.0473C12.5658 17.5783 12.0699 18 11.4781 18ZM8.94703 16H11.0606L11.344 14.1455L11.7498 13.9855C12.0868 13.8545 12.4237 13.6655 12.776 13.4182L13.1206 13.1709L14.9432 13.8691L16 12.1236L14.4454 10.9745L14.499 10.5673C14.522 10.3782 14.545 10.1964 14.545 10C14.545 9.80364 14.522 9.61455 14.499 9.43273L14.4454 9.02545L16 7.87636L14.9355 6.13091L13.1053 6.82909L12.7607 6.57455C12.4391 6.34182 12.0944 6.15273 11.7422 6.01455L11.344 5.85455L11.0606 4H8.94703L8.66369 5.85455L8.25782 6.00727C7.92087 6.14545 7.58392 6.32727 7.23165 6.58182L6.88705 6.82182L5.06445 6.13091L4 7.86909L5.55456 9.01818L5.50096 9.42545C5.47798 9.61455 5.45501 9.81091 5.45501 10C5.45501 10.1891 5.47033 10.3855 5.50096 10.5673L5.55456 10.9745L4 12.1236L5.0568 13.8691L6.88705 13.1709L7.23165 13.4255C7.56094 13.6655 7.89024 13.8473 8.25016 13.9855L8.65603 14.1455L8.94703 16ZM10 12.5C11.3807 12.5 12.5 11.3807 12.5 10C12.5 8.61929 11.3807 7.5 10 7.5C8.61929 7.5 7.5 8.61929 7.5 10C7.5 11.3807 8.61929 12.5 10 12.5Z" fill="var(--color)"/>
 </svg>
diff --git a/ash/webui/camera_app_ui/resources/js/js.gni b/ash/webui/camera_app_ui/resources/js/js.gni
index 96661f7..3566714a 100644
--- a/ash/webui/camera_app_ui/resources/js/js.gni
+++ b/ash/webui/camera_app_ui/resources/js/js.gni
@@ -42,6 +42,7 @@
   "lib/comlink.ts",
   "lib/comlink_protocol.ts",
   "lib/ffmpeg.js",
+  "lit/svg_wrapper.ts",
   "main.ts",
   "menu.ts",
   "metrics.ts",
diff --git a/ash/webui/camera_app_ui/resources/js/lit/svg_wrapper.ts b/ash/webui/camera_app_ui/resources/js/lit/svg_wrapper.ts
new file mode 100644
index 0000000..62c2a89
--- /dev/null
+++ b/ash/webui/camera_app_ui/resources/js/lit/svg_wrapper.ts
@@ -0,0 +1,74 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(pihsun): Fix these after CL:4355362 is relanded and CL:4371823 is
+// landed.
+import {
+  css,
+  LitElement,
+} from 'chrome://resources/mwc/lit/index.js';
+
+import {assertExists} from '../assert.js';
+import * as dom from '../dom.js';
+import {preloadedImages} from '../preload_images.js';
+
+const loadedSvgs = new Map<string, SVGElement>();
+
+export class SvgWrapper extends LitElement {
+  static override styles = css`
+    :host {
+      display: block;
+    }
+  `;
+
+  static override properties = {
+    name: {type: String},
+  };
+
+  name = null;
+
+  override render(): unknown {
+    if (this.name === null) {
+      return null;
+    }
+    return assertExists(loadedSvgs.get(this.name)).cloneNode(true);
+  }
+}
+
+/**
+ * Loads all svg images, and define the <svg-wrapper> element.
+ *
+ * This only needs to be called once at startup.
+ */
+export function loadSvgImages(): void {
+  for (const [imageName, image] of Object.entries(preloadedImages)) {
+    const container = document.createElement('div');
+    container.innerHTML = image;
+    const svg = assertExists(container.querySelector('svg'));
+    loadedSvgs.set(imageName, svg);
+  }
+
+  for (const el of dom.getAll('[data-svg]', HTMLElement)) {
+    const imageName = assertExists(el.dataset['svg']);
+    const svg = document.createElement('svg-wrapper');
+    svg.setAttribute('name', imageName);
+    // The parent element of the SVG is typically a button and would
+    // handle a11y instead of the SVG itself.
+    svg.setAttribute('aria-hidden', 'true');
+    el.appendChild(svg);
+  }
+
+  // This needs to be called after svg are loaded, so the SvgWrapper will
+  // always find the svg.
+  // JavaScript code that want to show svg should use <svg-wrapper> directly
+  // instead of using data-svg attribute.
+  window.customElements.define('svg-wrapper', SvgWrapper);
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    /* eslint-disable-next-line @typescript-eslint/naming-convention */
+    'svg-wrapper': SvgWrapper;
+  }
+}
diff --git a/ash/webui/camera_app_ui/resources/js/main.ts b/ash/webui/camera_app_ui/resources/js/main.ts
index 773e262..a2c6487 100644
--- a/ash/webui/camera_app_ui/resources/js/main.ts
+++ b/ash/webui/camera_app_ui/resources/js/main.ts
@@ -16,6 +16,7 @@
 import {GalleryButton} from './gallerybutton.js';
 import {I18nString} from './i18n_string.js';
 import {Intent} from './intent.js';
+import {loadSvgImages} from './lit/svg_wrapper.js';
 import * as metrics from './metrics.js';
 import * as filesystem from './models/file_system.js';
 import * as loadTimeData from './models/load_time_data.js';
@@ -255,7 +256,7 @@
       // For intent only requiring open camera with specific mode without
       // returning the capture result, finish it directly.
       if (this.intent !== null && !this.intent.shouldHandleResult) {
-        this.intent.finish();
+        await this.intent.finish();
       }
     })();
 
@@ -278,32 +279,37 @@
     await ChromeHelper.getInstance().initCameraUsageMonitor(
         exploitUsage, releaseUsage);
 
+    let cameraStartSuccessful = false;
+
     const startCamera = (async () => {
       await cameraResourceInitialized.wait();
-      const isSuccess = await this.cameraManager.requestResume();
+      cameraStartSuccessful = await this.cameraManager.requestResume();
 
-      if (isSuccess) {
+      if (cameraStartSuccessful) {
         const {aspectRatio} = this.cameraManager.getPreviewResolution();
         const {width, height} = getDefaultWindowSize(aspectRatio);
         window.resizeTo(width, height);
       }
-
-      nav.close(ViewName.SPLASH);
-      nav.open(ViewName.CAMERA);
-
-      const windowCreationTime = window.windowCreationTime;
-      this.perfLogger.start(
-          PerfEvent.LAUNCHING_FROM_WINDOW_CREATION, windowCreationTime);
-      this.perfLogger.stop(
-          PerfEvent.LAUNCHING_FROM_WINDOW_CREATION, {hasError: !isSuccess});
-      if (appWindow !== null) {
-        appWindow.onAppLaunched();
-      }
     })();
 
     preloadImages();
+    loadSvgImages();
     metrics.sendLaunchEvent({launchType});
     await Promise.all([showWindow, startCamera]);
+
+    nav.close(ViewName.SPLASH);
+    nav.open(ViewName.CAMERA);
+
+    const windowCreationTime = window.windowCreationTime;
+    this.perfLogger.start(
+        PerfEvent.LAUNCHING_FROM_WINDOW_CREATION, windowCreationTime);
+    this.perfLogger.stop(
+        PerfEvent.LAUNCHING_FROM_WINDOW_CREATION,
+        {hasError: !cameraStartSuccessful});
+
+    if (appWindow !== null) {
+      appWindow.onAppLaunched();
+    }
   }
 
   /**
@@ -378,6 +384,8 @@
 
 /**
  * Preload images to avoid flickering.
+ * TODO(pihsun): Remove this and stop including .svg file in CCA once all
+ * images are migrated to use data-svg / loadSvgImages.
  */
 function preloadImages() {
   const imagesContainer = document.createElement('div');
diff --git a/ash/webui/camera_app_ui/resources/js/preload_images.d.ts b/ash/webui/camera_app_ui/resources/js/preload_images.d.ts
index bcf377c..5fea045a 100644
--- a/ash/webui/camera_app_ui/resources/js/preload_images.d.ts
+++ b/ash/webui/camera_app_ui/resources/js/preload_images.d.ts
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// TODO(pihsun): Remove this file once we have generated preload_images.js
-// checked into the source tree.
-
 export const preloadImagesList: string[];
+
+/**
+ * Mapping of SVG file name to it's content.
+ */
+export const preloadedImages: Record<string, string>;
diff --git a/ash/webui/camera_app_ui/resources/utils/cca.py b/ash/webui/camera_app_ui/resources/utils/cca.py
index eaca4ba..292cf1d 100755
--- a/ash/webui/camera_app_ui/resources/utils/cca.py
+++ b/ash/webui/camera_app_ui/resources/utils/cca.py
@@ -53,7 +53,9 @@
             re.search(r'in_app_images\s*=\s*(\[.*?\])', f.read(),
                       re.DOTALL).group(1))
     with tempfile.NamedTemporaryFile('w') as f:
-        f.writelines(asset + '\n' for asset in in_app_images)
+        f.writelines(
+            os.path.abspath(f'images/{asset}') + '\n'
+            for asset in in_app_images)
         f.flush()
         cmd = [
             'utils/gen_preload_images_js.py',
diff --git a/ash/webui/camera_app_ui/resources/utils/gen_preload_images_js.py b/ash/webui/camera_app_ui/resources/utils/gen_preload_images_js.py
index 8fd75dd..6792d9b2 100755
--- a/ash/webui/camera_app_ui/resources/utils/gen_preload_images_js.py
+++ b/ash/webui/camera_app_ui/resources/utils/gen_preload_images_js.py
@@ -21,12 +21,19 @@
         help='File contains a list of images to be appended')
     args = argument_parser.parse_args()
     with open(args.images_list_file) as f:
-        filenames = [
-            os.path.basename(filename) for filename in shlex.split(f.read())
-        ]
-    with open(args.output_file, 'w') as f:
+        files = shlex.split(f.read())
+
+    images = {}
+    for image in files:
+        with open(image, 'r', encoding='utf-8') as f:
+            images[os.path.basename(image)] = f.read()
+
+    with open(args.output_file, 'w', encoding='utf-8') as f:
+        filenames = [os.path.basename(f) for f in files]
         f.write('export const preloadImagesList = %s;' %
                 json.dumps(filenames, indent=2))
+        f.write('export const preloadedImages = %s;' % json.dumps(images))
+
     return 0
 
 
diff --git a/ash/webui/camera_app_ui/resources/views/main.html b/ash/webui/camera_app_ui/resources/views/main.html
index f732d9d1..dfa81a4 100644
--- a/ash/webui/camera_app_ui/resources/views/main.html
+++ b/ash/webui/camera_app_ui/resources/views/main.html
@@ -121,7 +121,8 @@
       </div>
       <div class="top-stripe left-stripe buttons circle">
         <button id="open-settings" tabindex="0"
-                i18n-label="settings_button" aria-haspopup="true"></button>
+                i18n-label="settings_button" aria-haspopup="true"
+                data-svg="camera_button_settings.svg"></button>
       </div>
       <div class="top-stripe left-stripe buttons circle">
         <button id="back-to-review-document" tabindex="0"
diff --git a/ash/webui/files_internals/files_internals_ui.h b/ash/webui/files_internals/files_internals_ui.h
index 59f8e9c..121e344 100644
--- a/ash/webui/files_internals/files_internals_ui.h
+++ b/ash/webui/files_internals/files_internals_ui.h
@@ -12,7 +12,6 @@
 #include "ash/webui/files_internals/url_constants.h"
 #include "base/memory/weak_ptr.h"
 #include "content/public/browser/web_ui_data_source.h"
-#include "content/public/browser/webui_config.h"
 #include "content/public/common/url_constants.h"
 #include "ui/webui/mojo_web_ui_controller.h"
 
diff --git a/ash/webui/os_feedback_ui/BUILD.gn b/ash/webui/os_feedback_ui/BUILD.gn
index 84331a9b4..dddd7fdc 100644
--- a/ash/webui/os_feedback_ui/BUILD.gn
+++ b/ash/webui/os_feedback_ui/BUILD.gn
@@ -19,6 +19,7 @@
 
   deps = [
     "//ash/constants:constants",
+    "//ash/webui/common:chrome_os_webui_config",
     "//ash/webui/os_feedback_ui/backend",
     "//ash/webui/os_feedback_ui/mojom",
     "//ash/webui/resources:os_feedback_resources",
diff --git a/ash/webui/os_feedback_ui/os_feedback_ui.cc b/ash/webui/os_feedback_ui/os_feedback_ui.cc
index 6fef5120..9e2c9e72 100644
--- a/ash/webui/os_feedback_ui/os_feedback_ui.cc
+++ b/ash/webui/os_feedback_ui/os_feedback_ui.cc
@@ -126,6 +126,11 @@
 
 }  // namespace
 
+bool OSFeedbackUIConfig::IsWebUIEnabled(
+    content::BrowserContext* browser_context) {
+  return base::FeatureList::IsEnabled(ash::features::kOsFeedback);
+}
+
 OSFeedbackUI::OSFeedbackUI(
     content::WebUI* web_ui,
     std::unique_ptr<OsFeedbackDelegate> feedback_delegate)
diff --git a/ash/webui/os_feedback_ui/os_feedback_ui.h b/ash/webui/os_feedback_ui/os_feedback_ui.h
index 2c9c914..30a05e4f 100644
--- a/ash/webui/os_feedback_ui/os_feedback_ui.h
+++ b/ash/webui/os_feedback_ui/os_feedback_ui.h
@@ -7,9 +7,12 @@
 
 #include <memory>
 
+#include "ash/webui/common/chrome_os_webui_config.h"
 #include "ash/webui/os_feedback_ui/backend/feedback_service_provider.h"
 #include "ash/webui/os_feedback_ui/backend/help_content_provider.h"
 #include "ash/webui/os_feedback_ui/mojom/os_feedback_ui.mojom.h"
+#include "ash/webui/os_feedback_ui/url_constants.h"
+#include "content/public/common/url_constants.h"
 #include "ui/webui/mojo_web_ui_controller.h"
 #include "ui/webui/resources/cr_components/color_change_listener/color_change_listener.mojom.h"
 
@@ -23,8 +26,20 @@
 
 namespace ash {
 
+class OSFeedbackUI;
 class OsFeedbackDelegate;
 
+// WebUIConfig for chrome://os-feedback
+class OSFeedbackUIConfig : public ChromeOSWebUIConfig<OSFeedbackUI> {
+ public:
+  explicit OSFeedbackUIConfig(CreateWebUIControllerFunc create_controller_func)
+      : ChromeOSWebUIConfig(content::kChromeUIScheme,
+                            ash::kChromeUIOSFeedbackHost,
+                            create_controller_func) {}
+
+  bool IsWebUIEnabled(content::BrowserContext* browser_context) override;
+};
+
 class OSFeedbackUI : public ui::MojoWebUIController {
  public:
   OSFeedbackUI(content::WebUI* web_ui,
diff --git a/ash/wm/client_controlled_state.cc b/ash/wm/client_controlled_state.cc
index e0b30f1..0ee09394 100644
--- a/ash/wm/client_controlled_state.cc
+++ b/ash/wm/client_controlled_state.cc
@@ -121,6 +121,15 @@
     // Then ask delegate to set the desired bounds for the snap state.
     delegate_->HandleBoundsRequest(window_state, window_state->GetStateType(),
                                    bounds, window_state->GetDisplay().id());
+  } else if (window_state->IsFloated()) {
+    const gfx::Rect bounds =
+        Shell::Get()->tablet_mode_controller()->InTabletMode()
+            ? FloatController::GetPreferredFloatWindowTabletBounds(
+                  window_state->window())
+            : FloatController::GetPreferredFloatWindowClamshellBounds(
+                  window_state->window());
+    delegate_->HandleBoundsRequest(window_state, window_state->GetStateType(),
+                                   bounds, window_state->GetDisplay().id());
   } else if (event->type() == WM_EVENT_DISPLAY_BOUNDS_CHANGED) {
     // Explicitly handle the primary change because it can change the display id
     // with no bounds change.
diff --git a/ash/wm/client_controlled_state_unittest.cc b/ash/wm/client_controlled_state_unittest.cc
index 91b0c62..2d9f9a4 100644
--- a/ash/wm/client_controlled_state_unittest.cc
+++ b/ash/wm/client_controlled_state_unittest.cc
@@ -1061,6 +1061,18 @@
   EXPECT_TRUE(window_state()->IsFloated());
   EXPECT_EQ(kShellWindowId_FloatContainer, window()->parent()->GetId());
 
+  // Test rotate.
+  ASSERT_TRUE(chromeos::wm::IsLandscapeOrientationForWindow(window()));
+  Shell::Get()->display_manager()->SetDisplayRotation(
+      display::Screen::GetScreen()->GetPrimaryDisplay().id(),
+      display::Display::ROTATE_90, display::Display::RotationSource::USER);
+  ASSERT_FALSE(chromeos::wm::IsLandscapeOrientationForWindow(window()));
+  EXPECT_EQ(
+      InTabletMode()
+          ? FloatController::GetPreferredFloatWindowTabletBounds(window())
+          : FloatController::GetPreferredFloatWindowClamshellBounds(window()),
+      delegate()->requested_bounds());
+
   // Test minimize.
   const WMEvent minimize_event(WM_EVENT_MINIMIZE);
   window_state()->OnWMEvent(&minimize_event);
diff --git a/base/android/reached_addresses_bitset.h b/base/android/reached_addresses_bitset.h
index 472bab08..e5b3426 100644
--- a/base/android/reached_addresses_bitset.h
+++ b/base/android/reached_addresses_bitset.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/base_export.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/no_destructor.h"
 
 namespace base {
@@ -64,7 +65,9 @@
 
   uintptr_t start_address_;
   uintptr_t end_address_;
-  std::atomic<uint32_t>* reached_;
+  // This field is not a raw_ptr<> because the rewriter couldn't handle the
+  // global variable in a build configuration specific code.
+  RAW_PTR_EXCLUSION std::atomic<uint32_t>* reached_;
 };
 
 }  // namespace android
diff --git a/base/threading/thread_restrictions.cc b/base/threading/thread_restrictions.cc
index 50d9b6fe..dd6e049 100644
--- a/base/threading/thread_restrictions.cc
+++ b/base/threading/thread_restrictions.cc
@@ -260,11 +260,6 @@
   GetBaseSyncPrimitivesDisallowedTls() = BooleanWithStack(false);
 }
 
-// static
-void PermanentSingletonAllowance::AllowSingleton() {
-  GetSingletonDisallowedTls() = BooleanWithStack(false);
-}
-
 }  // namespace base
 
 #endif  // DCHECK_IS_ON()
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
index 8b95d5a..4c9ff445 100644
--- a/base/threading/thread_restrictions.h
+++ b/base/threading/thread_restrictions.h
@@ -216,6 +216,9 @@
 class BrowserMainLoop;
 class BrowserProcessIOThread;
 class BrowserTestBase;
+#if BUILDFLAG(IS_IOS)
+class ContentMainRunnerImpl;
+#endif  // BUILDFLAG(IS_IOS)
 class DesktopCaptureDevice;
 class DWriteFontCollectionProxy;
 class DWriteFontProxyImpl;
@@ -1003,27 +1006,15 @@
   friend class base::TestCustomDisallow;
   friend class content::BrowserMainLoop;
   friend class content::BrowserTestBase;
+#if BUILDFLAG(IS_IOS)
+  friend class content::ContentMainRunnerImpl;
+#endif  // BUILDFLAG(IS_IOS)
   friend class web::WebMainLoop;
 
   static void AllowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
   static void AllowBaseSyncPrimitives() EMPTY_BODY_IF_DCHECK_IS_OFF;
 };
 
-// Similar to PermanentThreadAllowance but separate because it's dangerous and
-// should have even fewer friends.
-class BASE_EXPORT PermanentSingletonAllowance {
- public:
-  // Class is merely a namespace-with-friends.
-  PermanentSingletonAllowance() = delete;
-
- private:
-  // Re-allow singletons on this thread. Since //base APIs DisallowSingleton()
-  // when they risk running past shutdown, this should only be called in rare
-  // cases where the caller knows the process will be killed rather than
-  // shutdown.
-  static void AllowSingleton() EMPTY_BODY_IF_DCHECK_IS_OFF;
-};
-
 #undef INLINE_OR_NOT_TAIL_CALLED
 #undef EMPTY_BODY_IF_DCHECK_IS_OFF
 #undef DEFAULT_IF_DCHECK_IS_OFF
diff --git a/build/config/rust.gni b/build/config/rust.gni
index 9435aa1..5706af3 100644
--- a/build/config/rust.gni
+++ b/build/config/rust.gni
@@ -27,7 +27,7 @@
   # slowly and carefully and there may be no actual bugs there.
   enable_rust = is_linux && !is_official_build && !using_sanitizer &&
                 target_cpu != "x86" && !use_clang_coverage && is_clang &&
-                target_os == host_os && build_with_chromium
+                build_with_chromium
 
   # As we incrementally enable Rust on mainstream builders, we want to enable
   # the toolchain (by switching 'enable_rust' to true) while still disabling
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index fe91bdc4..108bbcf 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-12.20230413.3.1
+12.20230414.0.1
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni
index 280ba61..774b3f7 100644
--- a/buildtools/deps_revisions.gni
+++ b/buildtools/deps_revisions.gni
@@ -5,5 +5,5 @@
 declare_args() {
   # Used to cause full rebuilds on libc++ rolls. This should be kept in sync
   # with the libcxx_revision vars in //DEPS.
-  libcxx_revision = "a112d60e2f99bce2892f6aa75b7a6999cdcf8961"
+  libcxx_revision = "5488b5c294dd4b9640adbef628f2dcd6f85a6c09"
 }
diff --git a/chrome/VERSION b/chrome/VERSION
index e389504..00ed882 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=114
 MINOR=0
-BUILD=5714
+BUILD=5715
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index d7b49d2..b0110cee 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -2352,50 +2352,6 @@
     ]
   }
 
-  # Defines a target that derives from the chrome public application. This
-  # can be either an APK or an app bundle module. This supports
-  # chrome_public_xxx targets (for Android L-M). For Android N+, see instead
-  # monochrome_public_apk_or_module_tmpl() below.
-  #
-  # Variables:
-  #  target_type: Determines the final target type. Should be one of
-  #    'android_apk', or 'android_app_bundle_module'.
-  #  apk_name: For 'android_apk' target types, name of the final APK without
-  #    an .apk suffix (e.g. 'ChromePublic').
-  #  is_base_module: For 'android_app_bundle_module' target types only,
-  #     set to true to indicate that this is a base application module
-  #     (instead of a feature module).
-  template("chrome_public_apk_or_module_tmpl") {
-    _is_bundle_module = invoker.target_type == "android_app_bundle_module"
-    chrome_public_common_apk_or_module_tmpl(target_name) {
-      forward_variables_from(invoker,
-                             [
-                               "add_view_trace_events",
-                               "apk_name",
-                               "bundle_target",
-                               "is_base_module",
-                               "target_type",
-                               "enable_lint",
-                               "enable_multidex",
-                               "lint_baseline_file",
-                               "lint_suppressions_dep",
-                               "lint_suppressions_file",
-                               "manual_jni_registration",
-                             ])
-      deps = chrome_public_shared_deps
-
-      if (_is_bundle_module) {
-        deps += [ ":chrome_bundle_module_pak_assets" ]
-      } else {
-        deps += [ ":chrome_apk_pak_assets" ]
-      }
-
-      shared_libraries = [ ":libchrome" ]
-
-      version_name = chrome_version_name
-    }
-  }
-
   chrome_public_apk_or_module_tmpl("chrome_public_apk") {
     target_type = "android_apk"
     apk_name = "ChromePublic"
@@ -2548,83 +2504,6 @@
     annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
   }
 
-  # Defines a target that derives from the monochrome public application. This
-  # can be either an APK or an app bundle module. Note that these only work
-  # on Android N+ devices, see chrome_public_apk_or_module_tmpl() for a template
-  # that supports generating targets for older Android releases.
-  #
-  # Variables:
-  #   target_type: Either 'android_apk' or 'android_app_bundle_module'.
-  #   apk_name: For APK target types, the final APK name without an .apk
-  #     suffix (e.g. "MonochromePublic").
-  #   is_base_module: For module target types, a boolean indicating whether
-  #     this is a base bundle module (instead of a feature one).
-  #   is_64_bit_browser: When compiling in a 64-bit configuration, a boolean
-  #     indicating whether the browser is 64-bit or 32-bit.
-  #   include_32_bit_webview: When compiling a 64-bit browser configuration, if
-  #     true, a 32-bit WebView library will also be built and included.
-  template("monochrome_public_apk_or_module_tmpl") {
-    _is_trichrome = defined(invoker.is_trichrome) && invoker.is_trichrome
-    _is_bundle = invoker.target_type == "android_app_bundle_module"
-
-    monochrome_public_common_apk_or_module_tmpl(target_name) {
-      forward_variables_from(invoker,
-                             [
-                               "add_view_trace_events",
-                               "apk_name",
-                               "bundle_target",
-                               "expected_android_manifest",
-                               "include_32_bit_webview",
-                               "include_64_bit_webview",
-                               "is_64_bit_browser",
-                               "is_base_module",
-                               "is_trichrome",
-                               "resource_ids_provider_dep",
-                               "static_library_provider",
-                               "target_type",
-                               "use_chromium_linker",
-                             ])
-
-      if (!_is_trichrome) {
-        # Resource allowlist used when generating R.java files and causes
-        # only the webview subset of resources to be marked as non-final.
-        # Strings in this target will also be kept in the base apk rather than placed in the language splits.
-        shared_resources_allowlist_target =
-            "//android_webview:system_webview_no_weblayer_apk"
-
-        # Ensure the localized resources for all locales are used, even when
-        # a smaller set is specified through aapt_locale_allowlist.
-        shared_resources_allowlist_locales = platform_pak_locales
-      }
-
-      deps = []
-      if (_is_bundle) {
-        deps += [
-          "//chrome/android:chrome_base_module_resources",
-
-          # deps in delegate_public_impl_java are put into the Chrome module, but the language deps
-          # are needed by the base module.
-          "//components/language/android:ulp_delegate_public_java",
-        ]
-      } else {
-        deps += [ ":delegate_public_impl_java" ]
-      }
-      if (!_is_trichrome) {
-        deps += [
-          "//android_webview:platform_service_bridge_upstream_implementation_java",
-          "//android_webview/nonembedded:icon_resources",
-          "//android_webview/nonembedded:monochrome_devui_launcher_icon_resources",
-        ]
-        if (!_is_bundle) {
-          deps += [ ":monochrome_java" ]
-        }
-        if (webview_includes_weblayer) {
-          deps += [ "//weblayer/browser/java:upstream_java" ]
-        }
-      }
-    }
-  }
-
   if (android_64bit_target_cpu && skip_secondary_abi_for_cq) {
     group("trichrome_library_apk") {
       deps = [ ":trichrome_library_64_apk" ]
@@ -2633,7 +2512,8 @@
       deps = [ ":monochrome_64_public_apk" ]
     }
   } else {
-    monochrome_public_apk_or_module_tmpl("monochrome_public_apk") {
+    chrome_public_apk_or_module_tmpl("monochrome_public_apk") {
+      is_monochrome = true
       apk_name = "MonochromePublic"
       target_type = "android_apk"
       if (android_64bit_target_cpu) {
@@ -2672,7 +2552,8 @@
   }
 
   if (android_64bit_target_cpu) {
-    monochrome_public_apk_or_module_tmpl("monochrome_64_public_apk") {
+    chrome_public_apk_or_module_tmpl("monochrome_64_public_apk") {
+      is_monochrome = true
       apk_name = "MonochromePublic64"
       target_type = "android_apk"
       is_64_bit_browser = true
@@ -2850,48 +2731,7 @@
         include_32_bit_webview = !skip_secondary_abi_for_cq
       }
 
-      # This is where we would add the shared_libraries entry for
-      # :libchromefortest in the non-Monochrome version. However, doing so in the
-      # Monochrome version causes Chrome to crash on startup due to being unable
-      # to load the library, and looking at the libraries included in the APK
-      # shows both libchromefortest and libmonochrome, when only one should be
-      # present. The tests currently work fine with just libmonochrome, so keep
-      # it this way until we actually need the test-only library. This may be
-      # related to monochrome_public_common_apk_or_module_tmpl adding its own
-      # shared libraries, but chrome_public_common_apk_or_module_tmpl not. See
-      # https://crbug.com/974017.
-      deps = [
-        ":chrome_test_ar_java",
-        "//third_party/android_sdk:android_test_mock_java",
-      ]
-
-      # Include ArCore files directly instead of using bundles. This does
-      # require us to explicitly re-declare our dependency on ARCore, which
-      # otherwise should have already been included, since the native libraries
-      # need to know that it is available. Though we'd always need to forcibly
-      # include the manifest DEP here as well
-      deps += [
-        "//third_party/arcore-android-sdk-client:com_google_ar_core_java",
-        "//third_party/arcore-android-sdk-client:com_google_ar_core_java__ignored_manifest",
-      ]
-
-      _libarcore_dir = get_label_info(
-                           "//third_party/arcore-android-sdk-client:com_google_ar_core_java($default_toolchain)",
-                           "target_out_dir") + "/com_google_ar_core_java/jni"
-
-      # We store this as a separate .so in the APK and only load as needed.
-      if (android_64bit_target_cpu) {
-        if (skip_secondary_abi_for_cq) {
-          loadable_modules = [ "$_libarcore_dir/arm64-v8a/libarcore_sdk_c.so" ]
-        } else {
-          secondary_abi_loadable_modules =
-              [ "$_libarcore_dir/armeabi-v7a/libarcore_sdk_c.so" ]
-        }
-      } else {
-        loadable_modules = [ "$_libarcore_dir/armeabi-v7a/libarcore_sdk_c.so" ]
-      }
-
-      additional_apks = [ "//net/android:net_test_support_apk" ]
+      deps = [ ":chrome_test_ar_java" ]
     }
   }
 
@@ -3114,22 +2954,19 @@
     ]
   }
 
-  template("monochrome_or_trichrome_public_bundle_tmpl") {
-    _base_module_target_name = "${invoker.target_name}__base_bundle_module"
+  template("chrome_bundle_tmpl") {
+    _is_monochrome = defined(invoker.is_monochrome) && invoker.is_monochrome
     _is_trichrome = defined(invoker.is_trichrome) && invoker.is_trichrome
+    assert(_is_monochrome || _is_trichrome, "TODO: https://crbug.com/1426950")
 
-    if (_is_trichrome) {
-      _bundle_name = "TrichromeChrome${invoker.bundle_suffix}"
-    } else {
-      _bundle_name = "MonochromePublic${invoker.bundle_suffix}"
-    }
-
-    monochrome_public_apk_or_module_tmpl(_base_module_target_name) {
+    _base_module_target_name = "${invoker.target_name}__base_bundle_module"
+    chrome_public_apk_or_module_tmpl(_base_module_target_name) {
       forward_variables_from(invoker,
                              [
                                "add_view_trace_events",
                                "expected_android_manifest",
                                "is_64_bit_browser",
+                               "is_monochrome",
                                "is_trichrome",
                                "include_32_bit_webview",
                                "include_64_bit_webview",
@@ -3137,7 +2974,6 @@
                                "resource_ids_provider_dep",
                              ])
       target_type = "android_app_bundle_module"
-      is_base_module = true
       bundle_target = ":${invoker.target_name}"
 
       if (defined(invoker.expected_android_manifest_template)) {
@@ -3156,6 +2992,7 @@
                                "include_32_bit_webview",
                                "include_64_bit_webview",
                                "is_64_bit_browser",
+                               "is_monochrome",
                                "is_trichrome",
                                "lint_baseline_file",
                                "lint_min_sdk_version",
@@ -3165,20 +3002,19 @@
                                "expected_libs_and_assets",
                                "expected_proguard_config",
                              ])
-      is_monochrome = !_is_trichrome
       base_module_target = ":$_base_module_target_name"
-      bundle_name = _bundle_name
       manifest_package = chrome_public_manifest_package
-      if (is_monochrome) {
-        module_descs = monochrome_module_descs
-      } else {
+      if (_is_trichrome) {
+        bundle_name = "TrichromeChrome${invoker.bundle_suffix}"
         module_descs = chrome_module_descs
+      } else if (_is_monochrome) {
+        bundle_name = "MonochromePublic${invoker.bundle_suffix}"
+        module_descs = monochrome_module_descs
       }
       chrome_deps = [ ":delegate_public_impl_java" ]
       if (!_is_trichrome) {
         chrome_deps += [ "//chrome/android:monochrome_java" ]
       }
-
       if (!is_java_debug) {
         proguard_android_sdk_dep = webview_framework_dep
       }
@@ -3207,7 +3043,9 @@
   } else {
     # Public webview targets don't work with non-public sdks.
     # https://crbug.com/1000763
-    monochrome_or_trichrome_public_bundle_tmpl("monochrome_public_bundle") {
+    chrome_bundle_tmpl("monochrome_public_bundle") {
+      is_monochrome = true
+
       # Monochrome bundle is used as our unified lint target, so it needs to set the
       # lowest shipping minSdkVersion to catch all potential NewApi errors.
       lint_min_sdk_version = default_min_sdk_version
@@ -3247,7 +3085,7 @@
       }
     }
 
-    monochrome_or_trichrome_public_bundle_tmpl("trichrome_chrome_bundle") {
+    chrome_bundle_tmpl("trichrome_chrome_bundle") {
       bundle_suffix = ""
       is_trichrome = true
       static_library_provider = ":trichrome_library_apk"
@@ -3360,13 +3198,14 @@
   }
 
   if (android_64bit_target_cpu) {
-    monochrome_or_trichrome_public_bundle_tmpl("monochrome_64_public_bundle") {
+    chrome_bundle_tmpl("monochrome_64_public_bundle") {
+      is_monochrome = true
       bundle_suffix = "64"
       is_64_bit_browser = true
       include_32_bit_webview = false
     }
 
-    monochrome_or_trichrome_public_bundle_tmpl("trichrome_chrome_64_bundle") {
+    chrome_bundle_tmpl("trichrome_chrome_64_bundle") {
       is_trichrome = true
       bundle_suffix = "64"
       is_64_bit_browser = true
@@ -3379,22 +3218,21 @@
     }
 
     if (!skip_secondary_abi_for_cq) {
-      monochrome_or_trichrome_public_bundle_tmpl(
-          "monochrome_32_public_bundle") {
+      chrome_bundle_tmpl("monochrome_32_public_bundle") {
+        is_monochrome = true
         bundle_suffix = "32"
         is_64_bit_browser = false
         include_64_bit_webview = false
       }
 
-      monochrome_or_trichrome_public_bundle_tmpl(
-          "monochrome_64_32_public_bundle") {
+      chrome_bundle_tmpl("monochrome_64_32_public_bundle") {
+        is_monochrome = true
         bundle_suffix = "6432"
         is_64_bit_browser = true
         include_32_bit_webview = true
       }
 
-      monochrome_or_trichrome_public_bundle_tmpl(
-          "trichrome_chrome_64_32_bundle") {
+      chrome_bundle_tmpl("trichrome_chrome_64_32_bundle") {
         is_trichrome = true
         bundle_suffix = "6432"
         is_64_bit_browser = true
@@ -3405,7 +3243,7 @@
               "expectations/$target_name.$target_cpu.libs_and_assets.expected"
         }
       }
-      monochrome_or_trichrome_public_bundle_tmpl("trichrome_chrome_32_bundle") {
+      chrome_bundle_tmpl("trichrome_chrome_32_bundle") {
         is_trichrome = true
         bundle_suffix = "32"
         is_64_bit_browser = false
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index 28fe242..1e96988 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -109,8 +109,6 @@
 # Variables:
 #   target_type: Either 'android_apk' or 'android_app_bundle_module'.
 #   apk_name: For APK target types, the final APK name without a suffix.
-#   is_base_module: For bundle module target types, true iff this is a base
-#     application module, instead of a feature module.
 #   shared_libraries: List of native shared libraries targets to include in
 #     the final target (e.g. [ ":libchrome" ]).
 #   is_monochrome: Indicates that this target contains chrome and webview
@@ -124,29 +122,35 @@
 #   Plus all other variables accepted by android_apk() or
 #   android_app_bundle_module(), depending on the target type.
 #
-template("chrome_public_common_apk_or_module_tmpl") {
-  assert(
-      invoker.target_type == "android_apk" ||
-          invoker.target_type == "android_app_bundle_module" ||
-          invoker.target_type == "instrumentation_test_apk",
-      "Invalid target_type definition, should be 'android_apk' or 'android_app_bundle_module'")
+template("chrome_common_apk_or_module_tmpl") {
+  _target_type = invoker.target_type
+  assert(_target_type == "android_apk" ||
+         _target_type == "android_app_bundle_module" ||
+         _target_type == "instrumentation_test_apk")
 
   _is_monochrome = defined(invoker.is_monochrome) && invoker.is_monochrome
   _is_trichrome = defined(invoker.is_trichrome) && invoker.is_trichrome
-  _is_bundle = invoker.target_type == "android_app_bundle_module"
+  _is_bundle = _target_type == "android_app_bundle_module"
 
+  _is_64_bit_browser =
+      android_64bit_target_cpu &&
+      (!defined(invoker.is_64_bit_browser) || invoker.is_64_bit_browser)
   if (_is_trichrome || _is_monochrome) {
     _include_64_bit_webview =
         android_64bit_target_cpu && (!defined(invoker.include_64_bit_webview) ||
                                      invoker.include_64_bit_webview)
     _include_32_bit_webview = !defined(invoker.include_32_bit_webview) ||
                               invoker.include_32_bit_webview
+    _include_primary_abi = !android_64bit_target_cpu || _is_64_bit_browser ||
+                           _include_64_bit_webview
+    _include_secondary_abi = android_64bit_target_cpu &&
+                             (!_is_64_bit_browser || _include_32_bit_webview)
+    if (_include_secondary_abi) {
+      _secondary_out_dir =
+          get_label_info("X($android_secondary_abi_toolchain)", "root_out_dir")
+      not_needed([ "_secondary_out_dir" ])
+    }
   }
-  _is_64_bit_browser =
-      android_64bit_target_cpu &&
-      (!defined(invoker.is_64_bit_browser) || invoker.is_64_bit_browser)
-  _is_secondary_abi_primary = !_is_64_bit_browser && android_64bit_target_cpu
-  not_needed([ "_is_secondary_abi_primary" ])
 
   assert(!(_is_monochrome && _is_trichrome),
          "Cannot be both trichrome and monochrome!")
@@ -154,12 +158,6 @@
          "If trichrome library is used, static_library_provider must be set " +
              "so that a dep can be added on the library APK.")
 
-  if (!defined(invoker.target_type)) {
-    _target_type = "android_apk"
-  } else {
-    _target_type = invoker.target_type
-  }
-
   if (_is_trichrome) {
     _version_code = TRICHROME_VERSION_MAP["${android_64bit_target_cpu}_${_is_64_bit_browser}_${_include_64_bit_webview}_${_include_32_bit_webview}"]
   } else if (_is_monochrome) {
@@ -169,104 +167,147 @@
     _version_code = chrome_modern_version_code
   }
 
-  # TODO(crbug.com/1411557): Remove option for custom manifest.
-  if (!defined(invoker.android_manifest)) {
-    if (defined(invoker.manifest_package)) {
-      _manifest_package = invoker.manifest_package
-    } else {
-      _manifest_package = chrome_public_manifest_package
-    }
+  if (defined(invoker.manifest_package)) {
+    _manifest_package = invoker.manifest_package
+  } else {
+    _manifest_package = chrome_public_manifest_package
+  }
 
-    _android_manifest = "$target_gen_dir/$target_name/AndroidManifest.xml"
+  _android_manifest = "$target_gen_dir/$target_name/AndroidManifest.xml"
 
-    # TODO(crbug.com/1411557): Move out of manifest/ when downstream is updated.
-    # _split.xml is used in chrome_bundle template.
-    _split_android_manifest =
-        "$target_gen_dir/manifest/$target_name/AndroidManifest_split.xml"
-    _android_manifest_target_name = "${target_name}__android_manifest"
-    split_manifest_template(_android_manifest_target_name) {
-      definitions_in_split = _is_bundle
-      split_input = "//chrome/android/java/AndroidManifest_split.xml"
-      split_output = _split_android_manifest
-      includes = []
-      output = _android_manifest
-      variables = default_chrome_public_jinja_variables +
-                  [ "manifest_package=$_manifest_package" ]
-      if (_is_trichrome) {
-        input = "//chrome/android/java/AndroidManifest_trichrome_chrome.xml"
-        includes = [ "//chrome/android/java/AndroidManifest.xml" ]
-        variables +=
-            trichrome_jinja_variables + [ "trichrome_version=$_version_code" ]
-      } else if (_is_monochrome) {
-        input = "//chrome/android/java/AndroidManifest_monochrome.xml"
-        includes = [
-          "//android_webview/nonembedded/java/AndroidManifest.xml",
-          "//chrome/android/java/AndroidManifest.xml",
-        ]
-        variables += monochrome_android_manifest_jinja_variables
-        if (_is_64_bit_browser) {
-          variables += [ "webview_library=libmonochrome_64.so" ]
-        } else {
-          variables += [ "webview_library=libmonochrome.so" ]
-        }
+  # TODO(crbug.com/1411557): Move out of manifest/ when downstream is updated.
+  # _split.xml is used in chrome_bundle template.
+  _split_android_manifest =
+      "$target_gen_dir/manifest/$target_name/AndroidManifest_split.xml"
+  _android_manifest_target_name = "${target_name}__android_manifest"
+  split_manifest_template(_android_manifest_target_name) {
+    definitions_in_split = _is_bundle
+    split_input = "//chrome/android/java/AndroidManifest_split.xml"
+    split_output = _split_android_manifest
+    includes = []
+    output = _android_manifest
+    variables = default_chrome_public_jinja_variables +
+                [ "manifest_package=$_manifest_package" ]
+    if (_is_trichrome) {
+      input = "//chrome/android/java/AndroidManifest_trichrome_chrome.xml"
+      includes = [ "//chrome/android/java/AndroidManifest.xml" ]
+      variables +=
+          trichrome_jinja_variables + [ "trichrome_version=$_version_code" ]
+    } else if (_is_monochrome) {
+      input = "//chrome/android/java/AndroidManifest_monochrome.xml"
+      includes = [
+        "//android_webview/nonembedded/java/AndroidManifest.xml",
+        "//chrome/android/java/AndroidManifest.xml",
+      ]
+      variables += monochrome_android_manifest_jinja_variables
+      if (_is_64_bit_browser) {
+        variables += [ "webview_library=libmonochrome_64.so" ]
       } else {
-        input = "//chrome/android/java/AndroidManifest.xml"
+        variables += [ "webview_library=libmonochrome.so" ]
       }
-      if (_is_monochrome || _is_trichrome) {
-        _force_32_bit = _include_32_bit_webview && _include_64_bit_webview &&
-                        !_is_64_bit_browser
-        variables += [
-          "force_32_bit=$_force_32_bit",
-          "include_arcore_manifest_flag=$enable_arcore",
-        ]
+    } else {
+      input = "//chrome/android/java/AndroidManifest.xml"
+    }
+    if (_is_monochrome || _is_trichrome) {
+      _force_32_bit = _include_32_bit_webview && _include_64_bit_webview &&
+                      !_is_64_bit_browser
+      variables += [
+        "force_32_bit=$_force_32_bit",
+        "include_arcore_manifest_flag=$enable_arcore",
+      ]
 
-        # TODO(crbug.com/1411557): Remove block.
-        if (_is_64_bit_browser) {
-          variables -= [ use_32bit_abi_jinja_variable ]
-        }
+      # TODO(crbug.com/1411557): Remove block.
+      if (_is_64_bit_browser) {
+        variables -= [ use_32bit_abi_jinja_variable ]
       }
-      if (defined(invoker.jinja_input)) {
-        includes += [ input ]
-        input = invoker.jinja_input
-      }
-      if (defined(invoker.jinja_extra_variables)) {
-        variables += invoker.jinja_extra_variables
-      }
-      if (defined(invoker.jinja_extra_includes)) {
-        includes += invoker.jinja_extra_includes
-      }
+    }
+    if (defined(invoker.jinja_input)) {
+      includes += [ input ]
+      input = invoker.jinja_input
+    }
+    if (defined(invoker.jinja_extra_variables)) {
+      variables += invoker.jinja_extra_variables
+    }
+    if (defined(invoker.jinja_extra_includes)) {
+      includes += invoker.jinja_extra_includes
     }
   }
   target(_target_type, target_name) {
-    forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
-    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
+    android_manifest = _android_manifest
+    android_manifest_dep = ":$_android_manifest_target_name"
+    manifest_package = _manifest_package
 
-    if (!defined(assert_no_deps)) {
-      assert_no_deps = []
-    }
-
-    # https://crbug.com/1415351
-    assert_no_deps += [
-      "//third_party/androidx:androidx_window_extensions_core_core_java",
-      "//third_party/androidx:androidx_window_sidecar_sidecar_java",
-      "//third_party/androidx:androidx_window_window_java_java",
-    ]
-
-    # TODO(crbug.com/1411557): Do not allows custom manifest dep.
-    if (defined(_android_manifest_target_name)) {
-      android_manifest = _android_manifest
-      android_manifest_dep = ":$_android_manifest_target_name"
-      manifest_package = _manifest_package
-    }
-
-    if (!defined(min_sdk_version) && _is_trichrome) {
+    if (defined(invoker.min_sdk_version)) {
+      min_sdk_version = invoker.min_sdk_version
+    } else if (_is_trichrome) {
       min_sdk_version = 29
     }
-    if (defined(expected_android_manifest)) {
+    if (defined(invoker.version_name)) {
+      version_name = invoker.version_name
+    } else {
+      version_name = chrome_version_name
+    }
+    if (defined(invoker.version_code)) {
+      # Override for the actual versionCode, but not for trichrome_version.
+      version_code = invoker.version_code
+    } else {
+      version_code = _version_code
+    }
+    if (defined(invoker.expected_android_manifest)) {
       expected_android_manifest_version_code_offset = chrome_version_code
       expected_android_manifest_library_version_offset = chrome_version_code
     }
 
+    if (_target_type == "android_apk") {
+      command_line_flags_file = "chrome-command-line"
+    }
+
+    if (_is_bundle) {
+      is_base_module = true
+
+      # Sets ISOLATED_SPLITS_ENABLED in BuildConfig.java.
+      isolated_splits_enabled = true
+    }
+
+    product_config_java_packages = [ "org.chromium.chrome.browser" ]
+
+    if (_is_monochrome) {
+      alternative_android_sdk_dep = webview_framework_dep
+      app_as_shared_lib = true
+
+      # Resource allowlist used when generating R.java files and causes
+      # only the webview subset of resources to be marked as non-final.
+      # Strings in this target will also be kept in the base apk rather than placed in the language splits.
+      shared_resources_allowlist_target =
+          "//android_webview:system_webview_no_weblayer_apk"
+
+      # Ensure the localized resources for all locales are used, even when
+      # a smaller set is specified through aapt_locale_allowlist.
+      shared_resources_allowlist_locales = platform_pak_locales
+
+      product_config_java_packages += [ webview_product_config_java_package ]
+
+      if (webview_includes_weblayer) {
+        product_config_java_packages += [ weblayer_product_config_java_package ]
+      }
+    }
+
+    if (enable_silent_java_assert_reporting) {
+      custom_assertion_handler = crash_reporting_assertion_handler
+    }
+
+    if (allow_jni_multiplexing) {
+      enable_jni_multiplexing = true
+    }
+
+    # TODO(agrieve): Make this the default for apks with minSdkVersion > 21.
+    if (_is_monochrome || _is_trichrome) {
+      no_xml_namespaces = true
+    }
+
+    # Include resource strings files only for supported locales.
+    aapt_locale_allowlist = platform_pak_locales
+
     resource_exclusion_regex = common_resource_exclusion_regex
     resource_exclusion_exceptions = common_resource_exclusion_exceptions
 
@@ -276,7 +317,7 @@
       "*ic_lock.*",  # Bottom edge seems misaligned.
     ]
 
-    # Note most of these, with the exception of resource_exclusion_exceptions,
+    # Most of these, with the exception of resource_exclusion_exceptions,
     # are currently duplicated in system_webview_apk_tmpl.gni.
 
     # Used only by alert dialog on tiny screens.
@@ -290,256 +331,259 @@
     # Instead of manually filtering, unused resource removal would be better:
     # https://crbug.com/636448
     resource_exclusion_regex += "|${_material_package}/xml.*badge_"
-    _material_package = "*com_google_android_material*"
 
-    if (!_is_monochrome) {
-      product_config_java_packages = [ "org.chromium.chrome.browser" ]
-    }
+    if (!is_java_debug) {
+      # Android supports webp transparent resources properly since API level 18,
+      # so this can only be activated for modern ones (which target API >= 21).
+      png_to_webp = true
 
-    # Android supports webp transparent resources properly since API level 18,
-    # so this can only be activated for modern ones (which target API >= 21).
-    if (!defined(png_to_webp)) {
-      png_to_webp = !is_java_debug
-    }
+      proguard_enabled = true
+      proguard_configs = [ "//chrome/android/proguard/main.flags" ]
+      if (_is_monochrome) {
+        proguard_configs +=
+            [ "//android_webview/nonembedded/java/proguard.flags" ]
+      }
+      if (defined(invoker.proguard_configs)) {
+        proguard_configs += invoker.proguard_configs
+      }
 
-    # We only optimize resources for bundles since APKs are not shipped.
-    # Resources only live in the base module atm as such we only need to set
-    # these on the base module
-    if (_is_bundle) {
-      # Removes metadata needed for Resources.getIdentifier("resource_name").
-      strip_resource_names = !is_java_debug
+      # We only optimize resources for bundles since APKs are not shipped.
+      # Resources only live in the base module atm as such we only need to set
+      # these on the base module
+      if (_is_bundle) {
+        # Removes metadata needed for Resources.getIdentifier("resource_name").
+        strip_resource_names = true
 
-      # Shortens resource file names in apk eg: res/drawable/button.xml -> res/a.xml
-      short_resource_paths = !is_java_debug
+        # Shortens resource file names in apk eg: res/drawable/button.xml -> res/a.xml
+        short_resource_paths = true
 
-      # Removes unused resources from the apk. Only enabled on official builds
-      # since it adds a slow step and serializes the build graph causing fewer
-      # expensive tasks (eg: proguarding, resource optimization) to be run in
-      # parallel by adding dependencies between them (adds around 10-20
-      # seconds on my machine).
-      strip_unused_resources = is_official_build
-    }
+        # Removes unused resources from the apk. Only enabled on official builds
+        # since it adds a slow step and serializes the build graph causing fewer
+        # expensive tasks (eg: proguarding, resource optimization) to be run in
+        # parallel by adding dependencies between them (adds around 10-20
+        # seconds on my machine).
+        strip_unused_resources = is_official_build
 
-    if (!defined(aapt_locale_allowlist)) {
-      # Include resource strings files only for supported locales.
-      aapt_locale_allowlist = platform_pak_locales
-    }
-
-    if (!defined(use_chromium_linker)) {
-      # The Chromium Linker depends on ASharedMemory_create() introduced in O.
-      use_chromium_linker = chromium_linker_supported && _is_trichrome
-    }
-
-    if (_is_trichrome) {
-      static_library_provider_use_secondary_abi = _is_secondary_abi_primary
-
-      # http://crbug.com/1042107.
-      if (is_component_build) {
-        if (android_64bit_target_cpu && _is_64_bit_browser) {
-          main_component_library = "libmonochrome_64.cr.so"
-        } else {
-          main_component_library = "libmonochrome.cr.so"
+        # Resources config for blocklisting resource names from obfuscation
+        resources_config_paths = [ "//chrome/android/aapt2.config" ]
+        if (_is_monochrome || _is_trichrome) {
+          resources_config_paths += [ "//android_webview/aapt2.config" ]
+        }
+        if (defined(invoker.resources_config_paths)) {
+          resources_config_paths += invoker.resources_config_paths
         }
       }
     }
 
-    if (!_is_monochrome && !_is_trichrome) {
+    deps = [
+      "//chrome/android:chrome_base_module_resources",
+      "//chrome/android:chrome_public_non_pak_assets",
+    ]
+
+    # TODO(agrieve): Make uncondtional when moving to trampoline.
+    if (_is_monochrome || _is_trichrome) {
+      deps += [ "//components/crash/android:handler_java" ]
+    }
+    if (_is_monochrome) {
+      deps += [ "//chrome/android:base_monochrome_module_java" ]
+    } else {
+      deps += [ "//chrome/android:base_module_java" ]
+    }
+    if (defined(invoker.deps)) {
+      deps += invoker.deps
+    }
+
+    if (!_is_trichrome) {
+      # These go in trichrome library.
       deps += [
-        "//components/crash/core/app:chrome_crashpad_handler_named_as_so",
         "//gin:v8_snapshot_assets",
         "//third_party/icu:icu_assets",
       ]
-      if (!defined(loadable_modules)) {
-        loadable_modules = []
-      }
-      loadable_modules += [ "$root_out_dir/libchrome_crashpad_handler.so" ]
-      if (!defined(library_always_compress)) {
-        library_always_compress = []
-      }
-      library_always_compress += [
-        "libchrome_crashpad_handler.so",
-        "libchromium_android_linker.so",
-      ]
-    }
 
-    if (dfmify_dev_ui && !_is_bundle) {
-      # Dev UI is a feature in a DFM, and APKs don't use DFMs. To make the code
-      # available for APKs add a dependency on it.
-      deps += [ "//chrome/android/features/dev_ui:java" ]
-    }
-    if (enable_vr && !_is_bundle) {
-      # VR is a feature in a DFM, and APKs don't use DFMs, but we
-      # unconditionally include vr code in our native library. To make the code
-      # available for APKs, add a dependency on it.
-      deps += [ "//chrome/android/features/vr:java" ]
-    }
-
-    if (!is_java_debug) {
-      proguard_enabled = true
-      if (!defined(proguard_configs)) {
-        proguard_configs = []
-      }
-      proguard_configs += [ "//chrome/android/proguard/main.flags" ]
-    }
-
-    if (use_chromium_linker) {
-      if (_is_secondary_abi_primary) {
-        _secondary_linker = "//base/android/linker:chromium_android_linker($android_secondary_abi_toolchain)"
-        deps += [ _secondary_linker ]
-        _secondary_out_dir = get_label_info(_secondary_linker, "root_out_dir")
-        secondary_abi_loadable_modules +=
-            [ "$_secondary_out_dir/libchromium_android_linker$shlib_extension" ]
-      } else {
-        deps += [ "//base/android/linker:chromium_android_linker" ]
-        loadable_modules +=
-            [ "$root_out_dir/libchromium_android_linker$shlib_extension" ]
-      }
-    }
-    if (build_with_internal_optimization_guide) {
-      if (_is_secondary_abi_primary) {
-        _secondary_optimization_guide = "//components/optimization_guide/internal:optimization_guide_internal($android_secondary_abi_toolchain)"
-        deps += [ _secondary_optimization_guide ]
-        _secondary_out_dir =
-            get_label_info(_secondary_optimization_guide, "root_out_dir")
-        secondary_abi_loadable_modules +=
-            [ "$_secondary_out_dir/liboptimization_guide_internal.so" ]
-      } else {
-        deps += [ "//components/optimization_guide/internal:optimization_guide_internal" ]
-        loadable_modules +=
-            [ "$root_out_dir/liboptimization_guide_internal.so" ]
-      }
-    }
-    if (_target_type == "android_apk") {
-      command_line_flags_file = "chrome-command-line"
-    }
-    if (!_is_trichrome) {
+      # TODO(agrieve): This is excluded from trichrome in preparation for
+      # "synchronized proguarding", which we've since abandoned. Enable for
+      # trichrome, or just remove the version check altogether.
       build_config_include_product_version_resource = true
       deps += [ "//chrome/android:product_version_resources" ]
     }
 
-    if (!_is_bundle || !(_is_monochrome || _is_trichrome)) {
-      deps += [ "//chrome/android:chrome_all_java" ]
-    }
-
     if (_is_bundle) {
       # Required to support macro resources.
       # See https://crbug.com/1278419
       deps += [ ":${target_name}__all_dfm_resources" ]
+    } else {
+      # For bundles, this exists in the "chrome" split.
+      deps += [ "//chrome/android:chrome_all_java" ]
+
+      if (dfmify_dev_ui) {
+        # For bundles, Dev UI is a feature in a DFM.
+        deps += [ "//chrome/android/features/dev_ui:java" ]
+      }
+      if (enable_vr) {
+        # For bundles, VR is a feature in a DFM.
+        deps += [ "//chrome/android/features/vr:java" ]
+      }
+    }
+
+    if (_is_monochrome) {
+      deps += [
+        "//android_webview/glue:glue_java",
+        "//android_webview/nonembedded:monochrome_devui_launcher_icon_resources",
+        "//android_webview/nonembedded:nonembedded_java",
+      ]
+
+      # For bundles, this lives in chrome split.
+      if (!_is_bundle) {
+        deps += [ "//chrome/android:monochrome_java" ]
+      }
+
+      if (_include_primary_abi) {
+        deps += [ "//android_webview:monochrome_webview_primary_abi_assets" ]
+      }
+      if (_include_secondary_abi) {
+        deps += [ "//android_webview:monochrome_webview_secondary_abi_assets" ]
+      }
+    }
+
+    if (_is_bundle && _is_monochrome) {
+      deps += [ "//chrome/android:monochrome_bundle_module_pak_assets" ]
+    } else if (_is_bundle && _is_trichrome) {
+      deps += [ "//chrome/android:trichrome_chrome_bundle_module_pak_assets" ]
+    } else if (_is_bundle) {
+      deps += [ "//chrome/android:chrome_bundle_module_pak_assets" ]
+    } else if (_is_monochrome) {
+      deps += [ "//chrome/android:monochrome_apk_pak_assets" ]
+    } else {
+      assert(!_is_trichrome)
+      deps += [ "//chrome/android:chrome_apk_pak_assets" ]
+    }
+
+    if (defined(invoker.add_upstream_only_deps) &&
+        invoker.add_upstream_only_deps) {
+      if (_is_monochrome) {
+        deps += upstream_only_webview_deps
+      } else if (!_is_trichrome) {
+        deps += [
+          "//chrome/android:chrome_public_apk_base_module_resources",
+          "//chrome/android:chrome_public_base_module_java",
+          "//chrome/android:chrome_public_non_pak_assets",
+          "//components/browser_ui/styles/android:chrome_public_apk_resources",
+        ]
+      }
+      if (_is_bundle) {
+        deps += [
+          # deps in delegate_public_impl_java are put into the Chrome module, but the language deps
+          # are needed by the base module.
+          "//components/language/android:ulp_delegate_public_java",
+        ]
+      } else {
+        deps += [ "//chrome/android:delegate_public_impl_java" ]
+      }
+    }
+
+    # https://crbug.com/1415351
+    assert_no_deps = [
+      "//third_party/androidx:androidx_window_extensions_core_core_java",
+      "//third_party/androidx:androidx_window_sidecar_sidecar_java",
+      "//third_party/androidx:androidx_window_window_java_java",
+    ]
+    if (defined(invoker.assert_no_deps)) {
+      assert_no_deps += invoker.assert_no_deps
     }
 
     # Unwind tables are included in the stack_unwinder DFM on Android, so they
     # aren't needed for bundle builds. However, we keep them for non-bundle
     # builds, such as test and development apks (e.g. chrome_public_apk), to
     # allow tests and developers to use them directly.
-    if (!_is_bundle && add_unwind_tables_in_chrome_32bit_apk) {
-      _needs_32bit_lib =
-          target_cpu == "arm" || ((_is_monochrome || _is_trichrome) &&
-                                  target_cpu == "arm64" && !_is_64_bit_browser)
-
-      if (_needs_32bit_lib) {
-        if (_is_monochrome || _is_trichrome) {
-          deps += [ "//chrome/android:libmonochrome_unwind_table_assets" ]
-        } else {
-          deps += [ "//chrome/android:libchrome_unwind_table_assets" ]
-        }
+    if (!defined(invoker.shared_libraries) && !_is_bundle &&
+        add_unwind_tables_in_chrome_32bit_apk &&
+        (target_cpu == "arm" ||
+         (target_cpu == "arm64" && !_is_64_bit_browser))) {
+      if (_is_monochrome || _is_trichrome) {
+        deps += [ "//chrome/android:libmonochrome_unwind_table_assets" ]
+      } else {
+        deps += [ "//chrome/android:libchrome_unwind_table_assets" ]
       }
     }
 
+    data_deps = []
+    if (defined(invoker.data_deps)) {
+      data_deps += invoker.data_deps
+    }
+
     # Prefer to add this data_dep on the final target instead of java targets
     # like chrome_all_java so that all other targets can build in parallel with
     # lint.
     if (!disable_android_lint) {
-      if (!defined(data_deps)) {
-        data_deps = []
-      }
       data_deps += [ "//chrome/android:android_lint" ]
     }
 
-    if (enable_silent_java_assert_reporting) {
-      custom_assertion_handler = crash_reporting_assertion_handler
-    }
-
-    if (allow_jni_multiplexing) {
-      enable_jni_multiplexing = true
-    }
-
-    if (!defined(version_name)) {
-      version_name = chrome_version_name
-    }
-    version_code = _version_code
-
-    # Override for the actual versionCode, but not for trichrome_version.
-    if (defined(invoker.version_code)) {
-      version_code = invoker.version_code
-    }
-  }
-}
-
-# The equivalent of chrome_common_apk_or_module_tmpl for all builds of
-# monochrome and trichrome chrome.
-template("monochrome_public_common_apk_or_module_tmpl") {
-  chrome_public_common_apk_or_module_tmpl(target_name) {
-    _overrides = {
-      _is_bundle_module = defined(invoker.target_type) &&
-                          invoker.target_type == "android_app_bundle_module"
-
-      if (_is_bundle_module) {
-        assert(
-            defined(invoker.is_base_module),
-            "_is_bundle_module is true but the invoker does not define is_base_module!")
-      }
-
-      is_trichrome = defined(invoker.is_trichrome) && invoker.is_trichrome
-      is_monochrome = !is_trichrome
-
-      shared_libraries = []
-      if (defined(invoker.shared_libraries)) {
-        shared_libraries += invoker.shared_libraries
-      }
+    shared_libraries = []
+    loadable_modules = []
+    if (android_64bit_target_cpu) {
       secondary_abi_shared_libraries = []
-      if (defined(invoker.secondary_abi_shared_libraries)) {
-        secondary_abi_shared_libraries += invoker.secondary_abi_shared_libraries
-      }
-      loadable_modules = []
-      if (defined(invoker.loadable_modules)) {
-        loadable_modules = invoker.loadable_modules
-      }
       secondary_abi_loadable_modules = []
-      if (defined(invoker.secondary_abi_loadable_modules)) {
-        secondary_abi_loadable_modules = invoker.secondary_abi_loadable_modules
-      }
-      native_lib_placeholders = []
-      if (defined(invoker.native_lib_placeholders)) {
-        native_lib_placeholders = invoker.native_lib_placeholders
-      }
-      secondary_native_lib_placeholders = []
-      if (defined(invoker.secondary_native_lib_placeholders)) {
-        secondary_native_lib_placeholders =
-            invoker.secondary_native_lib_placeholders
-      }
+    }
+    if (defined(invoker.loadable_modules)) {
+      loadable_modules = invoker.loadable_modules
+    }
+    if (defined(invoker.secondary_abi_loadable_modules)) {
+      secondary_abi_loadable_modules = invoker.secondary_abi_loadable_modules
+    }
 
-      deps = [
-        "//chrome/android:chrome_public_non_pak_assets",
-        "//components/crash/android:handler_java",
+    if (_is_64_bit_browser && build_hwasan_splits) {
+      _hwasan_toolchain = "//build/toolchain/android:android_clang_arm64_hwasan"
+    }
+
+    if (defined(invoker.shared_libraries)) {
+      shared_libraries += invoker.shared_libraries
+    } else if (_is_monochrome) {
+      if (android_64bit_target_cpu) {
+        # Build //android_webview:monochrome with the opposite bitness that
+        # Chrome runs in.
+        if (_is_64_bit_browser) {
+          shared_libraries += [ "//chrome/android:libmonochrome_64" ]
+          if (_include_32_bit_webview) {
+            secondary_abi_shared_libraries += [ "//android_webview:monochrome_64($android_secondary_abi_toolchain)" ]
+          }
+          if (build_hwasan_splits) {
+            shared_libraries +=
+                [ "//chrome/android:libmonochrome_64($_hwasan_toolchain)" ]
+          }
+        } else {
+          if (_include_64_bit_webview) {
+            shared_libraries += [ "//android_webview:monochrome" ]
+          }
+          secondary_abi_shared_libraries += [
+            "//chrome/android:libmonochrome($android_secondary_abi_toolchain)",
+          ]
+        }
+      } else {
+        shared_libraries += [ "//chrome/android:libmonochrome" ]
+      }
+    } else if (!_is_trichrome) {
+      shared_libraries += [ "//chrome/android:libchrome" ]
+    }
+
+    # TODO(agrieve): Enable for chrome_public_apk as well.
+    if (enable_arcore && (_is_monochrome || _is_trichrome)) {
+      # The arcore manifest needs to be merged into the base module because
+      # the Play Store verifies the com.google.ar.core.min_apk_version
+      # meta-data tag is in the base manifest.
+      deps += [
+        "//third_party/arcore-android-sdk-client:com_google_ar_core_java",
+        "//third_party/arcore-android-sdk-client:com_google_ar_core_java__ignored_manifest",
       ]
-      if (defined(invoker.deps)) {
-        deps += invoker.deps
-      }
 
-      if (_is_bundle_module && invoker.is_base_module && enable_arcore &&
-          is_monochrome) {
-        # AR DFM is disabled - set the loadable_modules /
-        # secondary_abi_loadable_modules to what would be brought in by the
-        # module. The AR Java will be brought in by the chrome_bundle target.
-        # This needs to happen for monochrome builds of base module if ARCore is
-        # enabled. For Trichrome, the native library is added to
-        # TrichromeLibrary.apk so it's not needed here.
-        _libarcore_dir = get_label_info(
-                             "//third_party/arcore-android-sdk-client:com_google_ar_core_java($default_toolchain)",
-                             "target_out_dir") + "/com_google_ar_core_java/jni"
+      # For Trichrome, the native library is added to TrichromeLibrary.apk so
+      # it's not needed here.
+      if (!_is_trichrome) {
+        _arcore_target = "//third_party/arcore-android-sdk-client:com_google_ar_core_J__unpack_aar"
+        _libarcore_dir = get_label_info(_arcore_target, "target_out_dir") +
+                         "/com_google_ar_core_java/jni"
 
         if (android_64bit_target_cpu) {
-          if (invoker.is_64_bit_browser) {
+          if (_is_64_bit_browser) {
             loadable_modules +=
                 [ "$_libarcore_dir/arm64-v8a/libarcore_sdk_c.so" ]
           } else {
@@ -551,234 +595,138 @@
               [ "$_libarcore_dir/armeabi-v7a/libarcore_sdk_c.so" ]
         }
       }
+    }
+    library_always_compress = []
+    if (defined(invoker.library_always_compress)) {
+      library_always_compress = invoker.library_always_compress
+    }
 
-      if (_is_bundle_module) {
-        # Sets ISOLATED_SPLITS_ENABLED in BuildConfig.java.
-        isolated_splits_enabled = true
-      }
-
-      if (_is_bundle_module && invoker.is_base_module) {
-        # The arcore manifest needs to be merged into the base module because
-        # the Play Store verifies the com.google.ar.core.min_apk_version
-        # meta-data tag is in the base manifest.
-        if (enable_arcore) {
-          deps += [
-            "//third_party/arcore-android-sdk-client:com_google_ar_core_java",
-            "//third_party/arcore-android-sdk-client:com_google_ar_core_java__ignored_manifest",
-          ]
-        }
-
-        if (is_monochrome) {
-          deps += [ "//chrome/android:base_monochrome_module_java" ]
-        } else {
-          deps += [ "//chrome/android:base_module_java" ]
-        }
-      }
-
-      if (android_64bit_target_cpu && (is_monochrome || is_trichrome)) {
-        _include_64_bit_webview = !defined(invoker.include_64_bit_webview) ||
-                                  invoker.include_64_bit_webview
-        _include_32_bit_webview = !defined(invoker.include_32_bit_webview) ||
-                                  invoker.include_32_bit_webview
-      }
-      if (is_monochrome) {
-        product_config_java_packages = [
-          "org.chromium.chrome.browser",
-          webview_product_config_java_package,
-        ]
-
-        if (webview_includes_weblayer) {
-          product_config_java_packages +=
-              [ weblayer_product_config_java_package ]
-        }
-
-        # Flag whether additional deps and libs should be included for each ABI.
-        _include_primary_support = false
-        _include_secondary_support = false
-
-        if (android_64bit_target_cpu) {
-          # Build //android_webview:monochrome with the opposite bitness that
-          # Chrome runs in.
-          if (invoker.is_64_bit_browser) {
-            _include_primary_support = true
-            shared_libraries += [ "//chrome/android:libmonochrome_64" ]
-            if (_include_32_bit_webview) {
-              secondary_abi_shared_libraries += [ "//android_webview:monochrome_64($android_secondary_abi_toolchain)" ]
-              _include_secondary_support = true
-            }
-          } else {
-            secondary_abi_shared_libraries +=
-                [ "//chrome/android:monochrome_secondary_abi_lib" ]
-            _include_secondary_support = true
-            if (_include_64_bit_webview) {
-              shared_libraries += [ "//android_webview:monochrome" ]
-              _include_primary_support = true
-            }
-          }
-        } else {
-          shared_libraries += [ "//chrome/android:libmonochrome" ]
-          _include_primary_support = true
-        }
-
+    # TODO(agrieve): Use Crashpad trampoline in chrome_public_apk.
+    if (!_is_monochrome && !_is_trichrome) {
+      deps +=
+          [ "//components/crash/core/app:chrome_crashpad_handler_named_as_so" ]
+      loadable_modules += [ "$root_out_dir/libchrome_crashpad_handler.so" ]
+      library_always_compress += [ "libchrome_crashpad_handler.so" ]
+    } else if (!_is_trichrome) {
+      # Crashpad trampoline lives in TrichromeLibrary.apk.
+      # https://chromium.googlesource.com/chromium/src/+/main/docs/android_native_libraries.md#Crashpad-Packaging
+      if (_include_primary_abi) {
         deps += [
-          "//android_webview/glue:glue_java",
-          "//android_webview/nonembedded:nonembedded_java",
+          "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline",
         ]
-        if (!_is_bundle_module) {
-          deps += [ "//chrome/android:monochrome_java" ]
-        }
-
-        if (_include_primary_support) {
-          deps += [
-            "//android_webview:monochrome_webview_primary_abi_assets",
-            "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline",
-          ]
-          loadable_modules +=
-              [ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
-        }
-        if (_include_secondary_support) {
-          _trampoline =
-              "//third_party/crashpad/crashpad/handler:" +
-              "crashpad_handler_trampoline($android_secondary_abi_toolchain)"
-
-          deps += [
-            "//android_webview:monochrome_webview_secondary_abi_assets",
-            _trampoline,
-          ]
-
-          _secondary_out_dir = get_label_info(_trampoline, "root_out_dir")
-          secondary_abi_loadable_modules +=
-              [ "$_secondary_out_dir/libcrashpad_handler_trampoline.so" ]
-        }
-
-        if (defined(invoker.alternative_android_sdk_dep)) {
-          alternative_android_sdk_dep = invoker.alternative_android_sdk_dep
-        } else {
-          alternative_android_sdk_dep = webview_framework_dep
-        }
-        if (defined(invoker.app_as_shared_lib)) {
-          app_as_shared_lib = invoker.app_as_shared_lib
-        } else {
-          app_as_shared_lib = true
-        }
-        _pak_prefix = "monochrome"
+        loadable_modules +=
+            [ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
       }
-      if (is_trichrome) {
-        # Include placeholder libraries to make Chrome multiarch in the same way
-        # as Monochrome, even though Chrome only runs with one of the two
-        # bitnesses. This allows the "32-bit" and "64-bit" versions of Chrome to
-        # depend on their respective versions of the shared library APK even
-        # though they're functionally the same.
-        if (android_64bit_target_cpu) {
-          if (invoker.is_64_bit_browser) {
-            native_lib_placeholders += [ "libdummy.so" ]
-            if (_include_32_bit_webview) {
-              secondary_native_lib_placeholders += [ "libdummy.so" ]
-            }
-          } else {
-            secondary_native_lib_placeholders += [ "libdummy.so" ]
-            if (_include_64_bit_webview) {
-              native_lib_placeholders += [ "libdummy.so" ]
-            }
-          }
-        } else {
-          native_lib_placeholders += [ "libdummy.so" ]
-        }
-
-        _pak_prefix = "trichrome_chrome"
+      if (_include_secondary_abi) {
+        deps += [ "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline($android_secondary_abi_toolchain)" ]
+        secondary_abi_loadable_modules +=
+            [ "$_secondary_out_dir/libcrashpad_handler_trampoline.so" ]
       }
+    }
 
-      # The Chromium Linker depends on ASharedMemory_create() introduced in O.
-      use_chromium_linker = is_trichrome && chromium_linker_supported
+    # The Chromium Linker depends on ASharedMemory_create() introduced in O.
+    use_chromium_linker = chromium_linker_supported && _is_trichrome
 
-      if (build_hwasan_splits && android_64bit_target_cpu &&
-          invoker.is_64_bit_browser) {
-        _hwasan_toolchain =
-            "//build/toolchain/android:android_clang_arm64_hwasan"
-        shared_libraries +=
-            [ "//chrome/android:libmonochrome_64($_hwasan_toolchain)" ]
-
-        if (use_chromium_linker) {
-          shared_libraries += [
-            "//base/android/linker:chromium_android_linker($_hwasan_toolchain)",
-          ]
-        }
+    if (use_chromium_linker) {
+      if (android_64bit_target_cpu && !_is_64_bit_browser) {
+        deps += [ "//base/android/linker:chromium_android_linker($android_secondary_abi_toolchain)" ]
+        secondary_abi_loadable_modules +=
+            [ "$_secondary_out_dir/libchromium_android_linker$shlib_extension" ]
+      } else {
+        deps += [ "//base/android/linker:chromium_android_linker" ]
+        loadable_modules +=
+            [ "$root_out_dir/libchromium_android_linker$shlib_extension" ]
       }
-
-      # We only optimize resources in bundles.
-      if (_is_bundle_module) {
-        # Resources config for blocklisting resource names from obfuscation
-        resources_config_paths = [
-          "//android_webview/aapt2.config",
-          "//chrome/android/aapt2.config",
+      if (_is_64_bit_browser && build_hwasan_splits) {
+        deps += [
+          "//base/android/linker:chromium_android_linker($_hwasan_toolchain)",
         ]
-        if (defined(invoker.resources_config_paths)) {
-          resources_config_paths += invoker.resources_config_paths
-        }
+        _hwasan_outdir = get_label_info(":($_hwasan_toolchain)", "root_out_dir")
+        loadable_modules +=
+            [ "$_hwasan_outdir/libchromium_android_linker$shlib_extension" ]
       }
+    }
 
-      if (defined(invoker.never_incremental)) {
-        never_incremental = invoker.never_incremental
-      } else if (!defined(invoker.target_type) ||
-                 invoker.target_type == "android_apk") {
-        # Incremental install doesn't work for monochrome. See crbug.com/663492.
-      }
-
-      # Strip xml namespaces for monochrome. This should only be done for apks
-      # targeting API > 21 which for chrome is only Monochrome. This is due to
-      # how android public and private resource ids are namespaced.
-      if (defined(invoker.no_xml_namespaces)) {
-        no_xml_namespaces = invoker.no_xml_namespaces
+    if (build_with_internal_optimization_guide) {
+      if (android_64bit_target_cpu && !_is_64_bit_browser) {
+        _secondary_optimization_guide = "//components/optimization_guide/internal:optimization_guide_internal($android_secondary_abi_toolchain)"
+        deps += [ _secondary_optimization_guide ]
+        secondary_abi_loadable_modules +=
+            [ "$_secondary_out_dir/liboptimization_guide_internal.so" ]
       } else {
-        no_xml_namespaces = true
+        deps += [ "//components/optimization_guide/internal:optimization_guide_internal" ]
+        loadable_modules +=
+            [ "$root_out_dir/liboptimization_guide_internal.so" ]
+      }
+    }
+
+    if (_is_trichrome) {
+      if (android_64bit_target_cpu && !_is_64_bit_browser) {
+        static_library_provider_use_secondary_abi = true
       }
 
-      if (_is_bundle_module) {
-        _pak_prefix += "_bundle_module"
-      } else {
-        _pak_prefix += "_apk"
+      # Include placeholder libraries to make Chrome multiarch in the same way
+      # as Monochrome, even though Chrome only runs with one of the two
+      # bitnesses. This allows the "32-bit" and "64-bit" versions of Chrome to
+      # depend on their respective versions of the shared library APK even
+      # though they're functionally the same.
+      if (_include_primary_abi && loadable_modules == []) {
+        native_lib_placeholders = [ "libdummy.so" ]
       }
-      deps += [ "//chrome/android:${_pak_prefix}_pak_assets" ]
+      if (_include_secondary_abi && secondary_abi_loadable_modules == []) {
+        secondary_native_lib_placeholders = [ "libdummy.so" ]
+      }
 
-      if (!is_java_debug) {
-        proguard_configs = []
-        if (defined(invoker.proguard_configs)) {
-          proguard_configs += invoker.proguard_configs
-        }
-        if (is_monochrome) {
-          proguard_configs +=
-              [ "//android_webview/nonembedded/java/proguard.flags" ]
+      # http://crbug.com/1042107.
+      if (is_component_build) {
+        if (_is_64_bit_browser) {
+          main_component_library = "libmonochrome_64.cr.so"
+        } else {
+          main_component_library = "libmonochrome.cr.so"
         }
       }
     }
 
-    # The _overrides scope is used to ensure that:
-    # * Values set in invoker cannot accidentally clobber values set in
-    #   _overrides.
-    # * Values set in _overrides cannot accidentaly clobber values set in
-    #   invoker (since the forward_variables_from will fail).
-    _override_args = [
-      "alternative_android_sdk_dep",
-      "app_as_shared_lib",
-      "deps",
-      "is_monochrome",
-      "is_trichrome",
-      "isolated_splits_enabled",
-      "loadable_modules",
-      "native_lib_placeholders",
-      "never_incremental",
-      "no_xml_namespaces",
-      "product_config_java_packages",
-      "proguard_configs",
-      "resources_config_paths",
-      "secondary_abi_loadable_modules",
-      "secondary_abi_shared_libraries",
-      "secondary_native_lib_placeholders",
-      "shared_libraries",
-      "use_chromium_linker",
-      "webview_product_config_java_package",
-    ]
-    forward_variables_from(invoker, "*", _override_args)
-    forward_variables_from(_overrides, _override_args)
+    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
+    forward_variables_from(invoker,
+                           "*",
+                           TESTONLY_AND_VISIBILITY + [
+                                 "assert_no_deps",
+                                 "data_deps",
+                                 "deps",
+                                 "loadable_modules",
+                                 "manifest_package",
+                                 "proguard_configs",
+                                 "resources_config_paths",
+                                 "secondary_abi_loadable_modules",
+                                 "secondary_abi_shared_libraries",
+                                 "shared_libraries",
+                                 "version_code",
+                                 "version_name",
+                               ])
+  }
+}
+
+# For creating chrome targets without internal customizations.
+template("chrome_public_apk_or_module_tmpl") {
+  chrome_common_apk_or_module_tmpl(target_name) {
+    add_upstream_only_deps = true
+    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
+    forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
+  }
+}
+
+# TODO(https://crbug.com/1427610): Remove.
+template("monochrome_public_common_apk_or_module_tmpl") {
+  chrome_common_apk_or_module_tmpl(target_name) {
+    forward_variables_from(invoker, "*")
+    if (!defined(is_monochrome)) {
+      is_trichrome = true
+    }
+  }
+}
+template("chrome_public_common_apk_or_module_tmpl") {
+  chrome_common_apk_or_module_tmpl(target_name) {
+    forward_variables_from(invoker, "*")
   }
 }
diff --git a/chrome/android/chrome_test_apk_tmpl.gni b/chrome/android/chrome_test_apk_tmpl.gni
index 5ca00db6a..106ee78 100644
--- a/chrome/android/chrome_test_apk_tmpl.gni
+++ b/chrome/android/chrome_test_apk_tmpl.gni
@@ -4,50 +4,40 @@
 
 import("//chrome/android/chrome_public_apk_tmpl.gni")
 
-# Dependencies that are common to any chrome_public derivative targets.
-chrome_public_shared_deps = [
-  "//chrome/android:chrome_app_java_resources",
-  "//chrome/android:chrome_public_apk_base_module_resources",
-  "//chrome/android:chrome_public_base_module_java",
-  "//chrome/android:chrome_public_non_pak_assets",
-  "//components/browser_ui/styles/android:chrome_public_apk_resources",
-  "//gin:v8_snapshot_assets",
-  "//third_party/icu:icu_assets",
-]
-
 chrome_public_test_manifest_package = "org.chromium.chrome.tests"
 
 template("chrome_test_apk_tmpl") {
-  chrome_public_common_apk_or_module_tmpl(target_name) {
+  chrome_public_apk_or_module_tmpl(target_name) {
     testonly = true
     target_type = "instrumentation_test_apk"
     bundles_supported = true
-    jinja_input = "//chrome/android/javatests/AndroidManifest.xml"
-    manifest_package = chrome_public_test_manifest_package
+
+    if (!defined(invoker.is_monochrome)) {
+      jinja_input = "//chrome/android/javatests/AndroidManifest.xml"
+      manifest_package = chrome_public_test_manifest_package
+    }
     shared_libraries = [ "//chrome/android:libchromefortest" ]
 
-    deps = chrome_public_shared_deps + invoker.deps + [
-             "//chrome/android:chrome_apk_pak_assets",
-             "//chrome/android:chrome_public_base_module_java_for_test",
-             "//third_party/android_sdk:android_test_base_java",
-             "//third_party/android_sdk:android_test_mock_java",
-             "//third_party/android_sdk:android_test_runner_java",
-             "//third_party/androidx:androidx_test_runner_java",
-           ]
+    deps = [
+      "//chrome/android:chrome_public_base_module_java_for_test",
+      "//third_party/android_sdk:android_test_base_java",
+      "//third_party/android_sdk:android_test_mock_java",
+      "//third_party/android_sdk:android_test_runner_java",
+      "//third_party/androidx:androidx_test_runner_java",
+    ]
+    if (defined(invoker.deps)) {
+      deps += invoker.deps
+    }
     if (add_unwind_tables_in_chrome_32bit_apk && current_cpu == "arm") {
       deps += [ "//chrome/android:libchromefortest_unwind_table_assets" ]
     }
-    if (enable_vr) {
-      # Contains VrFirstRunActivity, which is referenced by AndroidManifest.xml.
-      deps += [ "//chrome/android/features/vr:java" ]
-    }
 
+    # For EmbeddedTestServer.
     additional_apks = [ "//net/android:net_test_support_apk" ]
     if (defined(invoker.additional_apks)) {
       additional_apks += invoker.additional_apks
     }
     if (!is_java_debug) {
-      proguard_enabled = true
       proguard_configs = [ "//chrome/android/proguard/apk_for_test.flags" ]
       if (defined(invoker.proguard_configs)) {
         proguard_configs += invoker.proguard_configs
@@ -68,54 +58,18 @@
   }
 }
 
+# TODO(agrieve): Delete this and have all tests use chrome_test_apk_tmpl.
 template("monochrome_test_apk_tmpl") {
-  monochrome_public_common_apk_or_module_tmpl(target_name) {
-    forward_variables_from(invoker,
-                           [
-                             "apk_name",
-                             "data_deps",
-                             "is_64_bit_browser",
-                             "include_64_bit_webview",
-                             "include_32_bit_webview",
-                             "loadable_modules",
-                             "proguard_configs",
-                             "secondary_abi_loadable_modules",
-                             "target_sdk_version",
-                           ])
-    testonly = true
-    target_type = "instrumentation_test_apk"
-
-    # TODO(agrieve): Add: manifest_package = chrome_public_test_manifest_package
+  chrome_test_apk_tmpl(target_name) {
+    is_monochrome = true
+    manifest_package = chrome_public_manifest_package
 
     jinja_input = "//chrome/android/javatests/AndroidManifest_monochrome.xml"
     jinja_extra_includes = [ "//chrome/android/javatests/AndroidManifest.xml" ]
     jinja_extra_variables =
         [ "test_manifest_package=$chrome_public_test_manifest_package" ]
 
-    deps = chrome_public_shared_deps + invoker.deps + [
-             "//android_webview:platform_service_bridge_upstream_implementation_java",
-             "//chrome/android:chrome_public_base_module_java_for_test",
-             "//chrome/android:monochrome_apk_pak_assets",
-             "//third_party/android_sdk:android_test_base_java",
-             "//third_party/android_sdk:android_test_mock_java",
-             "//third_party/android_sdk:android_test_runner_java",
-             "//third_party/androidx:androidx_test_runner_java",
-           ]
-
-    if (webview_includes_weblayer) {
-      deps += [ "//weblayer/browser/java:upstream_java" ]
-    }
-
-    additional_apks = [ "//net/android:net_test_support_apk" ]
-    if (defined(invoker.additional_apks)) {
-      additional_apks += invoker.additional_apks
-    }
-    if (!is_java_debug) {
-      if (!defined(proguard_configs)) {
-        proguard_configs = []
-      }
-      proguard_enabled = true
-      proguard_configs += [ "//chrome/android/proguard/apk_for_test.flags" ]
-    }
+    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
+    forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
   }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragment.java
index a1508b5..793cb3e3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragment.java
@@ -45,6 +45,7 @@
 public class AutofillPaymentMethodsFragment
         extends PreferenceFragmentCompat implements PersonalDataManager.PersonalDataManagerObserver,
                                                     FragmentHelpAndFeedbackLauncher {
+    private static final String PREF_MANDATORY_REAUTH = "mandatory_reauth";
     private static final String PREF_PAYMENT_APPS = "payment_apps";
 
     private HelpAndFeedbackLauncher mHelpAndFeedbackLauncher;
@@ -140,7 +141,15 @@
                     R.string.autofill_settings_page_enable_payment_method_mandatory_reauth_label);
             mandatoryReauthSwitch.setSummary(
                     R.string.autofill_settings_page_enable_payment_method_mandatory_reauth_sublabel);
-            // TODO(crbug.com/1427216): Set the checked value and listener to bind to the new pref.
+            mandatoryReauthSwitch.setChecked(
+                    PersonalDataManager.isAutofillPaymentMethodsMandatoryReauthEnabled());
+            mandatoryReauthSwitch.setKey(PREF_MANDATORY_REAUTH);
+            mandatoryReauthSwitch.setOnPreferenceChangeListener((preference, newValue) -> {
+                assert preference.getKey().equals(PREF_MANDATORY_REAUTH);
+                // TODO(crbug.com/1427216): Invoke device authenticator when toggle is clicked.
+                PersonalDataManager.setAutofillPaymentMethodsMandatoryReauth((boolean) newValue);
+                return true;
+            });
             getPreferenceScreen().addPreference(mandatoryReauthSwitch);
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java
index 1c0da83..d6bc39d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java
@@ -218,6 +218,7 @@
                 boolean willBeSelected = launchType != TabLaunchType.FROM_LONGPRESS_BACKGROUND
                                 && launchType != TabLaunchType.FROM_LONGPRESS_BACKGROUND_IN_GROUP
                                 && launchType != TabLaunchType.FROM_RECENT_TABS
+                                && launchType != TabLaunchType.FROM_RESTORE_TABS_UI
                         || (!getTabModelSelector().isIncognitoSelected() && incognito);
                 float lastTapX = LocalizationUtils.isLayoutRtl() ? mHost.getWidth() * mPxToDp : 0.f;
                 float lastTapY = 0.f;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
index fcd7a436..00335fd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
@@ -136,6 +136,8 @@
                 return "ReadingList";
             case TabLaunchType.FROM_TAB_SWITCHER_UI:
                 return "TabSwitcherUI";
+            case TabLaunchType.FROM_RESTORE_TABS_UI:
+                return "RestoreTabsUI";
             default:
                 assert false : "Unexpected serialization of tabLaunchType: " + tabLaunchType;
                 return "TypeUnknown";
@@ -515,6 +517,7 @@
                 break;
             case TabLaunchType.FROM_CHROME_UI:
             case TabLaunchType.FROM_TAB_SWITCHER_UI:
+            case TabLaunchType.FROM_RESTORE_TABS_UI:
             case TabLaunchType.FROM_TAB_GROUP_UI:
             case TabLaunchType.FROM_STARTUP:
             case TabLaunchType.FROM_LAUNCHER_SHORTCUT:
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragmentTest.java
index 7bbbed7..bca3c53 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragmentTest.java
@@ -23,6 +23,8 @@
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.preferences.Pref;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.settings.SettingsActivity;
 import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -31,6 +33,9 @@
 import org.chromium.components.autofill.VirtualCardEnrollmentState;
 import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
 import org.chromium.components.policy.test.annotations.Policies;
+import org.chromium.components.prefs.PrefService;
+import org.chromium.components.user_prefs.UserPrefs;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 import java.util.concurrent.TimeoutException;
 
@@ -280,6 +285,12 @@
     @MediumTest
     @Features.EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_PAYMENTS_MANDATORY_REAUTH})
     public void testMandatoryReauthToggle_displayToggle() throws Exception {
+        // Simulate the pref was enabled previously, to ensure the toggle value is set
+        // correspondingly.
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            getPrefService().setBoolean(Pref.AUTOFILL_PAYMENT_METHODS_MANDATORY_REAUTH, true);
+        });
+
         SettingsActivity activity = mSettingsActivityTestRule.startSettingsActivity();
 
         // Verify that the preference on the initial screen map is only Save and Fill toggle +
@@ -287,12 +298,45 @@
         Assert.assertEquals(4, getPreferenceScreen(activity).getPreferenceCount());
         ChromeSwitchPreference mandatoryReauthPreference =
                 (ChromeSwitchPreference) getPreferenceScreen(activity).getPreference(1);
-        assertThat(mandatoryReauthPreference.getTitle())
-                .isEqualTo(activity.getString(
+        Assert.assertEquals(mandatoryReauthPreference.getTitle(),
+                activity.getString(
                         R.string.autofill_settings_page_enable_payment_method_mandatory_reauth_label));
+        Assert.assertTrue(mandatoryReauthPreference.isChecked());
+    }
+
+    @Test
+    @MediumTest
+    @Features.EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_PAYMENTS_MANDATORY_REAUTH})
+    public void testMandatoryReauthToggle_switchValueOnClicked() throws Exception {
+        // Initial state, Reauth pref is disabled by default.
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            getPrefService().setBoolean(Pref.AUTOFILL_PAYMENT_METHODS_MANDATORY_REAUTH, false);
+        });
+
+        SettingsActivity activity = mSettingsActivityTestRule.startSettingsActivity();
+
+        // Verify that the preference on the initial screen map is only Save and Fill toggle +
+        // Mandatory Reauth toggle + Add Card button + Payment Apps.
+        Assert.assertEquals(4, getPreferenceScreen(activity).getPreferenceCount());
+        ChromeSwitchPreference mandatoryReauthPreference =
+                (ChromeSwitchPreference) getPreferenceScreen(activity).getPreference(1);
+        Assert.assertEquals(mandatoryReauthPreference.getTitle(),
+                activity.getString(
+                        R.string.autofill_settings_page_enable_payment_method_mandatory_reauth_label));
+        Assert.assertFalse(mandatoryReauthPreference.isChecked());
+
+        // Simulate click on the Reauth toggle.
+        TestThreadUtils.runOnUiThreadBlocking(mandatoryReauthPreference::performClick);
+
+        // Verify that the Reauth toggle is now checked.
+        Assert.assertTrue(mandatoryReauthPreference.isChecked());
     }
 
     private static PreferenceScreen getPreferenceScreen(SettingsActivity activity) {
         return ((AutofillPaymentMethodsFragment) activity.getMainFragment()).getPreferenceScreen();
     }
+
+    private static PrefService getPrefService() {
+        return UserPrefs.get(Profile.getLastUsedRegularProfile());
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/javascript/CloseWatcherTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/javascript/CloseWatcherTest.java
index e620cfc..a70b3de 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/javascript/CloseWatcherTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/javascript/CloseWatcherTest.java
@@ -27,7 +27,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        "enable-experimental-web-platform-features", "enable-blink-features=CloseWatcher"})
+        "enable-experimental-web-platform-features", "enable-features=CloseWatcher"})
 public class CloseWatcherTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java
index 8893c127..23fd41e3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java
@@ -688,10 +688,11 @@
         Assert.assertEquals(17, LaunchTypeAtCreation.FROM_RECENT_TABS);
         Assert.assertEquals(18, LaunchTypeAtCreation.FROM_READING_LIST);
         Assert.assertEquals(19, LaunchTypeAtCreation.FROM_TAB_SWITCHER_UI);
+        Assert.assertEquals(20, LaunchTypeAtCreation.FROM_RESTORE_TABS_UI);
         Assert.assertEquals(
                 "Need to increment 1 to expected value each time a LaunchTypeAtCreation "
                         + "is added. Also need to add any new LaunchTypeAtCreation to this test.",
-                22, LaunchTypeAtCreation.names.length);
+                23, LaunchTypeAtCreation.names.length);
     }
 
     @SmallTest
diff --git a/chrome/android/trichrome.gni b/chrome/android/trichrome.gni
index 32ebe22..c693f23 100644
--- a/chrome/android/trichrome.gni
+++ b/chrome/android/trichrome.gni
@@ -44,6 +44,14 @@
        invoker.include_64_bit_webview) && android_64bit_target_cpu
   _include_32_bit_webview =
       !defined(invoker.include_32_bit_webview) || invoker.include_32_bit_webview
+  _include_primary_abi =
+      !android_64bit_target_cpu || _is_64_bit_browser || _include_64_bit_webview
+  _include_secondary_abi = android_64bit_target_cpu &&
+                           (!_is_64_bit_browser || _include_32_bit_webview)
+  if (_include_secondary_abi) {
+    _secondary_out_dir =
+        get_label_info("X($android_secondary_abi_toolchain)", "root_out_dir")
+  }
   _version_code = TRICHROME_VERSION_MAP["${android_64bit_target_cpu}_${_is_64_bit_browser}_${_include_64_bit_webview}_${_include_32_bit_webview}"]
 
   # TODO(crbug.com/1411557): Remove option for custom manifest.
@@ -87,40 +95,35 @@
       expected_android_manifest_library_version_offset = chrome_version_code
     }
 
-    # TODO(torne): since there's no real java code in the library right now,
-    # leave out the build hooks and let them get compiled into each APK. Later
-    # this should probably be in the library.
-    no_build_hooks = true
+    omit_dex = true
     include_size_info = is_official_build
-
     alternative_android_sdk_dep = webview_framework_dep
     r_java_root_package_name = "trichrome_lib"
     app_as_shared_lib = true
+    version_name = chrome_version_name
+    version_code = _version_code
+    min_sdk_version = 29
 
     # No support for this has been added, also not supported by test runner
     # since trichrome library is used in "additional_apks" in the trichrome
     # bundle smoke tests.
     never_incremental = true
 
-    version_name = chrome_version_name
-    version_code = _version_code
-    min_sdk_version = 29
-
     # TODO(torne): using icon_resources just to get a temporary icon
     deps = [
       "//android_webview/nonembedded:icon_resources",
       "//third_party/icu:icu_assets",
     ]
+    if (_include_primary_abi) {
+      deps += [ "//gin:v8_snapshot_assets" ]
+    }
+    if (_include_secondary_abi) {
+      deps += [ "//gin:v8_snapshot_secondary_abi_assets" ]
+    }
     if (defined(invoker.deps)) {
       deps += invoker.deps
     }
 
-    omit_dex = true
-
-    # Flag whether additional deps and libs should be included for each ABI.
-    _include_primary_support = false
-    _include_secondary_support = false
-
     if (android_64bit_target_cpu) {
       # Include the actual browser-bitness libmonochrome library, dependencies
       # (crashpad and linker), and an opposite-bitness placeholder library to
@@ -128,64 +131,54 @@
       # precompiled for both architectures.
       if (_is_64_bit_browser) {
         shared_libraries = [ "//chrome/android:libmonochrome_64" ]
-        _include_primary_support = true
         if (_include_32_bit_webview) {
           secondary_native_lib_placeholders = [ "libdummy.so" ]
         }
+        if (build_hwasan_splits) {
+          _hwasan_toolchain =
+              "//build/toolchain/android:android_clang_arm64_hwasan"
+          shared_libraries +=
+              [ "//chrome/android:libmonochrome_64($_hwasan_toolchain)" ]
+        }
       } else {
         secondary_abi_shared_libraries =
             [ "//chrome/android:monochrome_secondary_abi_lib" ]
-        _include_secondary_support = true
         if (invoker.include_64_bit_webview) {
           native_lib_placeholders = [ "libdummy.so" ]
         }
       }
     } else {
       shared_libraries = [ "//chrome/android:libmonochrome" ]
-      _include_primary_support = true
     }
 
-    if (_include_primary_support) {
+    # https://chromium.googlesource.com/chromium/src/+/main/docs/android_native_libraries.md#Crashpad-Packaging
+    loadable_modules = []
+    secondary_abi_loadable_modules = []
+    if (_include_primary_abi) {
       deps += [
-        "//gin:v8_snapshot_assets",
         "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline",
       ]
-      loadable_modules = [ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
+      loadable_modules += [ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
     }
-    if (_include_secondary_support) {
-      _trampoline =
-          "//third_party/crashpad/crashpad/handler:" +
-          "crashpad_handler_trampoline($android_secondary_abi_toolchain)"
-      deps += [
-        "//gin:v8_snapshot_secondary_abi_assets",
-        _trampoline,
-      ]
-      _secondary_out_dir = get_label_info(_trampoline, "root_out_dir")
-      secondary_abi_loadable_modules =
+    if (_include_secondary_abi) {
+      deps += [ "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline($android_secondary_abi_toolchain)" ]
+      secondary_abi_loadable_modules +=
           [ "$_secondary_out_dir/libcrashpad_handler_trampoline.so" ]
     }
 
     if (enable_arcore) {
-      _libarcore_dir = get_label_info(
-                           "//third_party/arcore-android-sdk-client:com_google_ar_core_java($default_toolchain)",
-                           "target_out_dir") + "/com_google_ar_core_java/jni"
-      not_needed([ "_libarcore_dir" ])
+      _arcore_target = "//third_party/arcore-android-sdk-client:com_google_ar_core_J__unpack_aar"
+      _libarcore_dir = get_label_info(_arcore_target, "target_out_dir") +
+                       "/com_google_ar_core_java/jni"
+      deps += [ "//third_party/arcore-android-sdk-client:com_google_ar_core_J__unpack_aar" ]
 
-      _arcore_extra_deps = [ "//third_party/arcore-android-sdk-client:com_google_ar_core_J__unpack_aar" ]
-      not_needed([ "_arcore_extra_deps" ])
-
-      if (_include_primary_support) {
+      if (_include_primary_abi) {
         loadable_modules +=
             [ "$_libarcore_dir/$android_app_abi/libarcore_sdk_c.so" ]
-        deps += _arcore_extra_deps
       }
-      if (_include_secondary_support) {
-        if (enable_arcore) {
-          secondary_abi_loadable_modules += [
-            "$_libarcore_dir/$android_app_secondary_abi/libarcore_sdk_c.so",
-          ]
-          deps += _arcore_extra_deps
-        }
+      if (_include_secondary_abi) {
+        secondary_abi_loadable_modules +=
+            [ "$_libarcore_dir/$android_app_secondary_abi/libarcore_sdk_c.so" ]
       }
     }
     forward_variables_from(invoker,
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index 7e1d696..9ef05ee 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -1526,6 +1526,9 @@
       <message name="IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_MESSAGE_DESCRIPTION" desc="Description shown in the message shown when a user changes their account-level tailored security setting encouraging them to enable Enhanced Safe Browsing">
         Enhanced protection does more to block phishing and malware
       </message>
+      <message name="IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_MESSAGE_DESCRIPTION_UPDATED" desc="Description shown in the message shown when a user changes their account-level tailored security setting encouraging them to enable Enhanced Safe Browsing">
+        Enhanced Safe Browsing does more to protect you against dangerous websites and downloads
+      </message>
       <message name="IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_MESSAGE_ACCEPT" desc="Accept button shown in the message shown when a user changes their account-level tailored security setting encouraging them to enable Enhanced Safe Browsing">
         Continue
       </message>
diff --git a/chrome/app/chromium_strings_grd/IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_MESSAGE_DESCRIPTION_UPDATED.png.sha1 b/chrome/app/chromium_strings_grd/IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_MESSAGE_DESCRIPTION_UPDATED.png.sha1
new file mode 100644
index 0000000..1d006325
--- /dev/null
+++ b/chrome/app/chromium_strings_grd/IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_MESSAGE_DESCRIPTION_UPDATED.png.sha1
@@ -0,0 +1 @@
+b77004c8404344587e70e4c50ee5e178caf2b17e
\ No newline at end of file
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index 15ee610..6c120cd 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -1627,6 +1627,9 @@
       <message name="IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_MESSAGE_DESCRIPTION" desc="Description shown in the message shown when a user changes their account-level tailored security setting encouraging them to enable Enhanced Safe Browsing">
         Enhanced protection does more to block phishing and malware
       </message>
+      <message name="IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_MESSAGE_DESCRIPTION_UPDATED" desc="Description shown in the message shown when a user changes their account-level tailored security setting encouraging them to enable Enhanced Safe Browsing">
+        Enhanced Safe Browsing does more to protect you against dangerous websites and downloads
+      </message>
       <message name="IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_MESSAGE_ACCEPT" desc="Accept button shown in the message shown when a user changes their account-level tailored security setting encouraging them to enable Enhanced Safe Browsing">
         Continue
       </message>
diff --git a/chrome/app/google_chrome_strings_grd/IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_MESSAGE_DESCRIPTION_UPDATED.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_MESSAGE_DESCRIPTION_UPDATED.png.sha1
new file mode 100644
index 0000000..1d006325
--- /dev/null
+++ b/chrome/app/google_chrome_strings_grd/IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_MESSAGE_DESCRIPTION_UPDATED.png.sha1
@@ -0,0 +1 @@
+b77004c8404344587e70e4c50ee5e178caf2b17e
\ No newline at end of file
diff --git a/chrome/app/password_manager_ui_strings.grdp b/chrome/app/password_manager_ui_strings.grdp
index 8cf3814..e5172f0 100644
--- a/chrome/app/password_manager_ui_strings.grdp
+++ b/chrome/app/password_manager_ui_strings.grdp
@@ -445,4 +445,9 @@
   <message name="IDS_PASSWORD_MANAGER_UI_MOVE_PASSWORDS_BUTTON" desc="An action button for the dialog which allows users to move all their passwords from device to Google account.">
     Move
   </message>
+  <if expr="is_win or is_macosx">
+    <message name="IDS_PASSWORD_MANAGER_UI_MANAGE_PASSKEYS_LABEL" desc="The label on a button that a user can click in order to see and delete passkeys saved on their computer. For consistency, the word 'passkey' is in the glossary with translations already suggested.">
+      Manage passkeys
+    </message>
+  </if>
 </grit-part>
diff --git a/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_MANAGE_PASSKEYS_LABEL.png.sha1 b/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_MANAGE_PASSKEYS_LABEL.png.sha1
new file mode 100644
index 0000000..1931e29
--- /dev/null
+++ b/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_MANAGE_PASSKEYS_LABEL.png.sha1
@@ -0,0 +1 @@
+34c5ebcf3ef3bb134589a5932a8d1a19ce43986b
\ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 071c652b..ad9cf5d1 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -8016,6 +8016,12 @@
          "EsbIphBubbleAndCollapseSettingsVariations")},
 #endif  // !BUILDFLAG(IS_ANDROID)
 
+    {"enable-tailored-security-updated-messages",
+     flag_descriptions::kEnableTailoredSecurityUpdatedMessagesName,
+     flag_descriptions::kEnableTailoredSecurityUpdatedMessagesDescription,
+     kOsAll,
+     FEATURE_VALUE_TYPE(safe_browsing::kTailoredSecurityUpdatedMessages)},
+
 #if !BUILDFLAG(IS_ANDROID)
     {"sct-auditing", flag_descriptions::kSCTAuditingName,
      flag_descriptions::kSCTAuditingDescription, kOsDesktop,
diff --git a/chrome/browser/android/foreign_session_helper.cc b/chrome/browser/android/foreign_session_helper.cc
index 5acbcc3f..10e38b1 100644
--- a/chrome/browser/android/foreign_session_helper.cc
+++ b/chrome/browser/android/foreign_session_helper.cc
@@ -7,6 +7,7 @@
 #include <jni.h>
 #include <stddef.h>
 
+#include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
 #include "base/functional/bind.h"
 #include "chrome/browser/android/tab_android.h"
@@ -254,6 +255,43 @@
   return true;
 }
 
+jboolean ForeignSessionHelper::GetMobileAndTabletForeignSessions(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& result) {
+  OpenTabsUIDelegate* open_tabs = GetOpenTabsUIDelegate(profile_);
+  if (!open_tabs) {
+    return false;
+  }
+
+  std::vector<const SyncedSession*> sessions;
+  if (!open_tabs->GetAllForeignSessions(&sessions)) {
+    return false;
+  }
+
+  ScopedJavaLocalRef<jobject> last_pushed_session;
+  size_t skipped_tabs_on_restore = 0;
+
+  // Note: we don't own the SyncedSessions themselves.
+  for (const SyncedSession* session : sessions) {
+    if (session->GetDeviceFormFactor() ==
+            syncer::DeviceInfo::FormFactor::kPhone ||
+        session->GetDeviceFormFactor() ==
+            syncer::DeviceInfo::FormFactor::kTablet) {
+      last_pushed_session.Reset(Java_ForeignSessionHelper_pushSession(
+          env, result, ConvertUTF8ToJavaString(env, session->GetSessionTag()),
+          ConvertUTF8ToJavaString(env, session->GetSessionName()),
+          session->GetModifiedTime().ToJavaTime()));
+
+      // Push the full session, with tabs ordered by visual position.
+      JNI_ForeignSessionHelper_CopySessionToJava(env, *session,
+                                                 last_pushed_session);
+    } else {
+      skipped_tabs_on_restore++;
+    }
+  }
+  return (skipped_tabs_on_restore != sessions.size());
+}
+
 jboolean ForeignSessionHelper::OpenForeignSessionTab(
     JNIEnv* env,
     const JavaParamRef<jobject>& j_tab,
@@ -315,3 +353,106 @@
 
   service->SetInvalidationsForSessionsEnabled(enabled);
 }
+
+jint ForeignSessionHelper::OpenForeignSessionTabsAsBackgroundTabs(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& j_tab,
+    const JavaParamRef<jintArray>& j_session_tab_ids,
+    const JavaParamRef<jstring>& session_tag) {
+  std::vector<int> session_tab_ids;
+  base::android::JavaIntArrayToIntVector(env, j_session_tab_ids,
+                                         &session_tab_ids);
+  int tabs_android_count = env->GetArrayLength(j_session_tab_ids);
+
+  TabAndroid* tab_android = TabAndroid::GetNativeTab(env, j_tab);
+  if (!tab_android) {
+    return 0;
+  }
+
+  // Open the first tab in the list with a renderer and web contents.
+  if (!ForeignSessionHelper::RestoreTabWithRenderer(session_tag, j_tab,
+                                                    session_tab_ids[0])) {
+    return 0;
+  }
+  content::WebContents* web_contents = tab_android->web_contents();
+  if (!web_contents) {
+    return 0;
+  }
+  int num_tabs_restored = 1;
+
+  // Using the web contents of the first tab, load the rest of the tabs
+  // with no renderer and as background tabs.
+  for (int i = 1; i < tabs_android_count; i++) {
+    if (ForeignSessionHelper::RestoreTabNoRenderer(
+            session_tag, session_tab_ids[i], web_contents)) {
+      num_tabs_restored++;
+    }
+  }
+  return num_tabs_restored;
+}
+
+bool ForeignSessionHelper::RestoreTabWithRenderer(
+    const JavaParamRef<jstring>& session_tag,
+    const JavaParamRef<jobject>& j_tab,
+    int session_tab_id) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  OpenTabsUIDelegate* open_tabs = GetOpenTabsUIDelegate(profile_);
+  if (!open_tabs) {
+    return false;
+  }
+
+  const sessions::SessionTab* foreground_session_tab;
+
+  if (!open_tabs->GetForeignTab(ConvertJavaStringToUTF8(env, session_tag),
+                                SessionID::FromSerializedValue(session_tab_id),
+                                &foreground_session_tab)) {
+    return false;
+  }
+
+  if (foreground_session_tab->navigations.empty()) {
+    return false;
+  }
+
+  TabAndroid* tab_android = TabAndroid::GetNativeTab(env, j_tab);
+  if (!tab_android) {
+    return false;
+  }
+  content::WebContents* web_contents = tab_android->web_contents();
+  if (!web_contents) {
+    return false;
+  }
+
+  SessionRestore::RestoreForeignSessionTab(web_contents,
+                                           *foreground_session_tab,
+                                           WindowOpenDisposition::CURRENT_TAB);
+  return true;
+}
+
+bool ForeignSessionHelper::RestoreTabNoRenderer(
+    const JavaParamRef<jstring>& session_tag,
+    int session_tab_id,
+    content::WebContents* web_contents) {
+  OpenTabsUIDelegate* open_tabs = GetOpenTabsUIDelegate(profile_);
+  if (!open_tabs) {
+    return false;
+  }
+
+  const sessions::SessionTab* background_session_tab;
+
+  if (!open_tabs->GetForeignTab(
+          ConvertJavaStringToUTF8(base::android::AttachCurrentThread(),
+                                  session_tag),
+          SessionID::FromSerializedValue(session_tab_id),
+          &background_session_tab)) {
+    return false;
+  }
+
+  if (background_session_tab->navigations.empty()) {
+    return false;
+  }
+
+  SessionRestore::RestoreForeignSessionTab(
+      web_contents, *background_session_tab,
+      WindowOpenDisposition::NEW_BACKGROUND_TAB, true);
+  return true;
+}
diff --git a/chrome/browser/android/foreign_session_helper.h b/chrome/browser/android/foreign_session_helper.h
index a128230a..6bf9c26 100644
--- a/chrome/browser/android/foreign_session_helper.h
+++ b/chrome/browser/android/foreign_session_helper.h
@@ -11,6 +11,8 @@
 #include "base/callback_list.h"
 #include "base/memory/raw_ptr.h"
 #include "chrome/browser/profiles/profile.h"
+#include "components/sync_sessions/open_tabs_ui_delegate.h"
+#include "content/public/browser/web_contents.h"
 
 using base::android::ScopedJavaLocalRef;
 
@@ -34,6 +36,9 @@
   jboolean GetForeignSessions(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& result);
+  jboolean GetMobileAndTabletForeignSessions(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& result);
   jboolean OpenForeignSessionTab(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& j_tab,
@@ -44,10 +49,25 @@
       JNIEnv* env,
       const base::android::JavaParamRef<jstring>& session_tag);
   void SetInvalidationsForSessionsEnabled(JNIEnv* env, jboolean enabled);
+  jint OpenForeignSessionTabsAsBackgroundTabs(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& j_tab,
+      const base::android::JavaParamRef<jintArray>& j_session_tab_ids,
+      const base::android::JavaParamRef<jstring>& session_tag);
 
  private:
   // Fires |callback_| if it is not null.
   void FireForeignSessionCallback();
+  // Returns whether a foreground tab with renderer was restored.
+  bool RestoreTabWithRenderer(
+      const base::android::JavaParamRef<jstring>& session_tag,
+      const base::android::JavaParamRef<jobject>& j_tab,
+      int session_tab_id);
+  // Returns whether a background tab with no renderer was restored.
+  bool RestoreTabNoRenderer(
+      const base::android::JavaParamRef<jstring>& session_tag,
+      int session_tab_id,
+      content::WebContents* web_contents);
 
   raw_ptr<Profile> profile_;  // weak
   base::android::ScopedJavaGlobalRef<jobject> callback_;
diff --git a/chrome/browser/android/profile_key_startup_accessor.h b/chrome/browser/android/profile_key_startup_accessor.h
index 73db67c..27fa613f 100644
--- a/chrome/browser/android/profile_key_startup_accessor.h
+++ b/chrome/browser/android/profile_key_startup_accessor.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_ANDROID_PROFILE_KEY_STARTUP_ACCESSOR_H_
 #define CHROME_BROWSER_ANDROID_PROFILE_KEY_STARTUP_ACCESSOR_H_
 
+#include "base/memory/raw_ptr_exclusion.h"
+
 class ProfileKey;
 
 // The ProfileKeyStartupAccessor is a singleton class that exposes the
@@ -29,7 +31,9 @@
   void Reset();
 
  private:
-  ProfileKey* key_;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #global-scope
+  RAW_PTR_EXCLUSION ProfileKey* key_;
 };
 
 #endif  // CHROME_BROWSER_ANDROID_PROFILE_KEY_STARTUP_ACCESSOR_H_
diff --git a/chrome/browser/apps/app_service/app_service_proxy_lacros.cc b/chrome/browser/apps/app_service/app_service_proxy_lacros.cc
index 1fa3e7f..f55b783 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_lacros.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_lacros.cc
@@ -625,7 +625,7 @@
 
 void AppServiceProxyLacros::InitWebsiteMetrics() {
   if (metrics_service_) {
-    metrics_service_->Start();
+    metrics_service_->InitDeviceTypeAndStart();
   }
 }
 
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc b/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc
index 9305329..8d175841 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc
+++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc
@@ -1241,6 +1241,12 @@
 }
 
 void AppPlatformMetrics::SaveUsageTime() {
+  if (!ShouldRecordUkm(profile_)) {
+    // Do not persist usage data to the pref store if it cannot be reported.
+    // This will prevent unnecessary disk space usage.
+    return;
+  }
+
   ScopedDictPrefUpdate usage_dict_pref(profile_->GetPrefs(), kAppUsageTime);
   for (auto it : usage_time_per_two_hours_) {
     const std::string& instance_id = it.first.ToString();
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc
index 37b6b133..4ab0162 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc
+++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc
@@ -2215,6 +2215,30 @@
       Eq(kAppRunningDuration));
 }
 
+TEST_P(AppPlatformMetricsServiceTest, ShouldNotPersistUsageDataIfSyncDisabled) {
+  // Disable sync state.
+  sync_service()->SetDisableReasons(
+      syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY);
+
+  // Create a new window for the app.
+  auto window = std::make_unique<aura::Window>(nullptr);
+  window->Init(ui::LAYER_NOT_DRAWN);
+
+  // Set the window active state and simulate app usage.
+  static constexpr char kAppId[] = "a";
+  const base::UnguessableToken& kInstanceId = base::UnguessableToken::Create();
+  ModifyInstance(kInstanceId, kAppId, window.get(),
+                 ::apps::InstanceState::kActive);
+  static constexpr base::TimeDelta kAppRunningDuration = base::Minutes(5);
+  task_environment_.FastForwardBy(kAppRunningDuration);
+
+  // Close app window to stop tracking further usage and verify usage info is
+  // not persisted in the pref store.
+  ModifyInstance(kInstanceId, kAppId, window.get(),
+                 ::apps::InstanceState::kDestroyed);
+  ASSERT_TRUE(GetPrefService()->GetDict(kAppUsageTime).empty());
+}
+
 INSTANTIATE_TEST_SUITE_P(All,
                          AppPlatformMetricsServiceTest,
                          testing::Bool() /* IsLacrosPrimary */);
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics.cc b/chrome/browser/apps/app_service/metrics/website_metrics.cc
index c4b9fc82b..aad053f 100644
--- a/chrome/browser/apps/app_service/metrics/website_metrics.cc
+++ b/chrome/browser/apps/app_service/metrics/website_metrics.cc
@@ -225,6 +225,13 @@
 
 void WebsiteMetrics::OnURLsDeleted(history::HistoryService* history_service,
                                    const history::DeletionInfo& deletion_info) {
+  if (deletion_info.is_from_expiration()) {
+    // This is an auto-expiration of history that happens after 90 days. Any
+    // data recorded here must be newer than this threshold, so ignore the
+    // expiration.
+    return;
+  }
+
   // To simplify the implementation, remove all recorded urls no matter whatever
   // `deletion_info`.
   webcontents_to_ukm_key_.clear();
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 ab9cefa7..8d89f8f 100644
--- a/chrome/browser/apps/app_service/metrics/website_metrics_browsertest.cc
+++ b/chrome/browser/apps/app_service/metrics/website_metrics_browsertest.cc
@@ -2,9 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <set>
+
 #include "base/containers/contains.h"
 #include "base/json/values_util.h"
 #include "base/run_loop.h"
+#include "base/time/time.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
@@ -28,7 +31,9 @@
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/wm/core/window_util.h"
+#include "url/gurl.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/apps/app_service/metrics/app_platform_metrics_service.h"
@@ -119,10 +124,6 @@
 #endif
   }
 
-  void TearDownOnMainThread() override {
-    InProcessBrowserTest::TearDownOnMainThread();
-  }
-
   void SetUpCommandLine(base::CommandLine* command_line) override {
     InProcessBrowserTest ::SetUpCommandLine(command_line);
     command_line->AppendSwitch(switches::kNoStartupWindow);
@@ -311,13 +312,7 @@
   std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_;
 };
 
-// crbug.com/1399461 Disable flaky test.
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#define MAYBE_InsertAndCloseTabs DISABLED_InsertAndCloseTabs
-#else
-#define MAYBE_InsertAndCloseTabs InsertAndCloseTabs
-#endif
-IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest, MAYBE_InsertAndCloseTabs) {
+IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest, InsertAndCloseTabs) {
   InstallWebAppOpeningAsTab("https://a.example.org");
 
   Browser* browser = CreateBrowser();
@@ -414,13 +409,7 @@
   EXPECT_TRUE(url_infos().empty());
 }
 
-// crbug.com/1399461 Disable flaky test.
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#define MAYBE_ForegroundTabNavigate DISABLED_ForegroundTabNavigate
-#else
-#define MAYBE_ForegroundTabNavigate ForegroundTabNavigate
-#endif
-IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest, MAYBE_ForegroundTabNavigate) {
+IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest, ForegroundTabNavigate) {
   Browser* browser = CreateBrowser();
   auto* window = browser->window()->GetNativeWindow();
   EXPECT_EQ(1u, window_to_web_contents().size());
@@ -476,14 +465,7 @@
   EXPECT_TRUE(url_infos().empty());
 }
 
-// crbug.com/1399461 Disable flaky test.
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#define MAYBE_NavigateToBackgroundTab DISABLED_NavigateToBackgroundTab
-#else
-#define MAYBE_NavigateToBackgroundTab NavigateToBackgroundTab
-#endif
-IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest,
-                       MAYBE_NavigateToBackgroundTab) {
+IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest, NavigateToBackgroundTab) {
   auto website_metrics_ptr = std::make_unique<apps::TestWebsiteMetrics>(
       ProfileManager::GetPrimaryUserProfile());
   auto* metrics = website_metrics_ptr.get();
@@ -615,14 +597,7 @@
   EXPECT_TRUE(url_infos().empty());
 }
 
-// crbug.com/1399461 Disable flaky test.
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#define MAYBE_NavigateToUrlWithManifest DISABLED_NavigateToUrlWithManifest
-#else
-#define MAYBE_NavigateToUrlWithManifest NavigateToUrlWithManifest
-#endif
-IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest,
-                       MAYBE_NavigateToUrlWithManifest) {
+IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest, NavigateToUrlWithManifest) {
   auto website_metrics_ptr = std::make_unique<apps::TestWebsiteMetrics>(
       ProfileManager::GetPrimaryUserProfile());
   auto* metrics = website_metrics_ptr.get();
@@ -685,13 +660,7 @@
   EXPECT_TRUE(url_infos().empty());
 }
 
-// crbug.com/1399461 Disable flaky test.
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#define MAYBE_MultipleBrowser DISABLED_MultipleBrowser
-#else
-#define MAYBE_MultipleBrowser MultipleBrowser
-#endif
-IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest, MAYBE_MultipleBrowser) {
+IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest, MultipleBrowser) {
   // Setup: two browsers with two tabs each.
   auto* browser1 = CreateBrowser();
   auto* window1 = browser1->window()->GetNativeWindow();
@@ -811,14 +780,8 @@
   EXPECT_TRUE(url_infos().empty());
 }
 
-// crbug.com/1399461 Disable flaky test.
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#define MAYBE_MoveActivatedTabToNewBrowser DISABLED_MoveActivatedTabToNewBrowser
-#else
-#define MAYBE_MoveActivatedTabToNewBrowser MoveActivatedTabToNewBrowser
-#endif
 IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest,
-                       MAYBE_MoveActivatedTabToNewBrowser) {
+                       MoveActivatedTabToNewBrowser) {
   auto website_metrics_ptr = std::make_unique<apps::TestWebsiteMetrics>(
       ProfileManager::GetPrimaryUserProfile());
   auto* metrics = website_metrics_ptr.get();
@@ -948,15 +911,8 @@
   EXPECT_TRUE(url_infos().empty());
 }
 
-// crbug.com/1399461 Disable flaky test.
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#define MAYBE_MoveInActivatedTabToNewBrowser \
-  DISABLED_MoveInActivatedTabToNewBrowser
-#else
-#define MAYBE_MoveInActivatedTabToNewBrowser MoveInActivatedTabToNewBrowser
-#endif
 IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest,
-                       MAYBE_MoveInActivatedTabToNewBrowser) {
+                       MoveInActivatedTabToNewBrowser) {
   // Create a browser with two tabs.
   auto* browser1 = CreateBrowser();
   auto* window1 = browser1->window()->GetNativeWindow();
@@ -1077,13 +1033,7 @@
   EXPECT_TRUE(webcontents_to_ukm_key().empty());
 }
 
-// crbug.com/1399461 Disable flaky test.
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#define MAYBE_OnURLsDeleted DISABLED_OnURLsDeleted
-#else
-#define MAYBE_OnURLsDeleted OnURLsDeleted
-#endif
-IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest, MAYBE_OnURLsDeleted) {
+IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest, OnURLsDeleted) {
   // Setup: two browsers with one tabs each.
   auto* browser1 = CreateBrowser();
   auto* window1 = browser1->window()->GetNativeWindow();
@@ -1111,13 +1061,52 @@
                 /*is_activated=*/false, /*promotable=*/false);
   VerifyUrlInfo(GURL("https://b.example.org"),
                 /*is_activated=*/true, /*promotable=*/false);
+
+  // Simulate OnURLsDeleted is called for an expiration. Nothing should be
+  // cleared.
+  auto info = history::DeletionInfo(
+      history::DeletionTimeRange(base::Time(), base::Time::Now()),
+      /*is_from_expiration=*/true, {}, {}, absl::optional<std::set<GURL>>());
+  website_metrics()->OnURLsDeleted(nullptr, info);
+  EXPECT_EQ(2u, window_to_web_contents().size());
+  EXPECT_EQ(2u, webcontents_to_observer_map().size());
+  EXPECT_TRUE(base::Contains(webcontents_to_observer_map(),
+                             window_to_web_contents()[window1]));
+  EXPECT_TRUE(base::Contains(webcontents_to_observer_map(),
+                             window_to_web_contents()[window2]));
+  EXPECT_EQ(window_to_web_contents()[window1]->GetVisibleURL(),
+            GURL("https://a.example.org"));
+  EXPECT_EQ(window_to_web_contents()[window2]->GetVisibleURL(),
+            GURL("https://b.example.org"));
+  EXPECT_EQ(2u, webcontents_to_ukm_key().size());
+  EXPECT_EQ(webcontents_to_ukm_key()[tab_app1], GURL("https://a.example.org"));
+  EXPECT_EQ(webcontents_to_ukm_key()[tab_app2], GURL("https://b.example.org"));
+  VerifyUrlInfo(GURL("https://a.example.org"),
+                /*is_activated=*/false, /*promotable=*/false);
+  VerifyUrlInfo(GURL("https://b.example.org"),
+                /*is_activated=*/true, /*promotable=*/false);
+
+  // Persist data to prefs and verify.
   website_metrics()->OnFiveMinutes();
   VerifyUrlInfoInPref(GURL("https://a.example.org"),
                       /*promotable=*/false);
   VerifyUrlInfoInPref(GURL("https://b.example.org"),
                       /*promotable=*/false);
 
-  // Simulate OnURLsDeleted is called.
+  // Simulate OnURLsDeleted again for an expiration. The prefs should not be
+  // affected
+  website_metrics()->OnURLsDeleted(nullptr, info);
+  EXPECT_EQ(2u, webcontents_to_ukm_key().size());
+  EXPECT_EQ(2u, url_infos().size());
+  EXPECT_EQ(webcontents_to_ukm_key()[tab_app1], GURL("https://a.example.org"));
+  EXPECT_EQ(webcontents_to_ukm_key()[tab_app2], GURL("https://b.example.org"));
+  VerifyUrlInfoInPref(GURL("https://a.example.org"),
+                      /*promotable=*/false);
+  VerifyUrlInfoInPref(GURL("https://b.example.org"),
+                      /*promotable=*/false);
+
+  // Simulate OnURLsDeleted for a non-expiration and ensure prefs and
+  // in-memory usage data is cleared.
   website_metrics()->OnURLsDeleted(nullptr,
                                    history::DeletionInfo::ForAllHistory());
   EXPECT_EQ(2u, window_to_web_contents().size());
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics_service_lacros.cc b/chrome/browser/apps/app_service/metrics/website_metrics_service_lacros.cc
index b805e60..f91cf9f 100644
--- a/chrome/browser/apps/app_service/metrics/website_metrics_service_lacros.cc
+++ b/chrome/browser/apps/app_service/metrics/website_metrics_service_lacros.cc
@@ -23,7 +23,17 @@
 }  // namespace
 
 WebsiteMetricsServiceLacros::WebsiteMetricsServiceLacros(Profile* profile)
-    : profile_(profile) {
+    : profile_(profile) {}
+
+WebsiteMetricsServiceLacros::~WebsiteMetricsServiceLacros() = default;
+
+// static
+void WebsiteMetricsServiceLacros::RegisterProfilePrefs(
+    PrefRegistrySimple* registry) {
+  registry->RegisterDictionaryPref(kWebsiteUsageTime);
+}
+
+void WebsiteMetricsServiceLacros::InitDeviceTypeAndStart() {
   auto* service = chromeos::LacrosService::Get();
   if (!service || !service->IsAvailable<crosapi::mojom::DeviceAttributes>()) {
     return;
@@ -43,14 +53,6 @@
           weak_ptr_factory_.GetWeakPtr()));
 }
 
-WebsiteMetricsServiceLacros::~WebsiteMetricsServiceLacros() = default;
-
-// static
-void WebsiteMetricsServiceLacros::RegisterProfilePrefs(
-    PrefRegistrySimple* registry) {
-  registry->RegisterDictionaryPref(kWebsiteUsageTime);
-}
-
 void WebsiteMetricsServiceLacros::Start() {
   // Check every `kFiveMinutes` to record websites usage time.
   five_minutes_timer_.Start(FROM_HERE, kFiveMinutes, this,
@@ -83,6 +85,7 @@
     int user_type_by_device_type) {
   website_metrics_ = std::make_unique<apps::WebsiteMetrics>(
       profile_, user_type_by_device_type);
+  Start();
 }
 
 }  // namespace apps
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics_service_lacros.h b/chrome/browser/apps/app_service/metrics/website_metrics_service_lacros.h
index e7a77ca..cfa6cb2 100644
--- a/chrome/browser/apps/app_service/metrics/website_metrics_service_lacros.h
+++ b/chrome/browser/apps/app_service/metrics/website_metrics_service_lacros.h
@@ -29,6 +29,9 @@
 
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
 
+  // Asynchronously initialise the device type and then call Start() when done.
+  void InitDeviceTypeAndStart();
+
   // Start the timer for website metrics.
   void Start();
 
diff --git a/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.cc b/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.cc
index 4900b8c..2464131 100644
--- a/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.cc
+++ b/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.cc
@@ -100,7 +100,7 @@
   }
 
  private:
-  ArcInputOverlayManager* const owner_;
+  raw_ptr<ArcInputOverlayManager> const owner_;
 };
 
 // static
diff --git a/chrome/browser/ash/extensions/file_manager/private_api_drive.cc b/chrome/browser/ash/extensions/file_manager/private_api_drive.cc
index 0bd1e9f3..faabdc8 100644
--- a/chrome/browser/ash/extensions/file_manager/private_api_drive.cc
+++ b/chrome/browser/ash/extensions/file_manager/private_api_drive.cc
@@ -47,8 +47,10 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/ui/webui/ash/manage_mirrorsync/manage_mirrorsync_dialog.h"
+#include "chrome/common/extensions/api/file_manager_private.h"
 #include "chrome/common/extensions/api/file_manager_private_internal.h"
 #include "chrome/common/extensions/extension_constants.h"
+#include "chromeos/ash/components/drivefs/drivefs_pin_manager.h"
 #include "chromeos/ash/components/drivefs/drivefs_util.h"
 #include "chromeos/ash/components/network/network_handler.h"
 #include "chromeos/ash/components/network/network_state_handler.h"
@@ -998,6 +1000,25 @@
 }
 
 ExtensionFunction::ResponseAction
+FileManagerPrivateGetBulkPinProgressFunction::Run() {
+  Profile* const profile = Profile::FromBrowserContext(browser_context());
+  drive::DriveIntegrationService* integration_service =
+      drive::util::GetIntegrationServiceByProfile(profile);
+  if (!integration_service) {
+    return RespondNow(Error("Drive not available"));
+  }
+
+  if (!integration_service->GetPinManager()) {
+    return RespondNow(Error("Pin Manager not available"));
+  }
+
+  return RespondNow(ArgumentList(
+      api::file_manager_private::GetBulkPinProgress::Results::Create(
+          file_manager::util::BulkPinProgressToJs(
+              integration_service->GetPinManager()->GetProgress()))));
+}
+
+ExtensionFunction::ResponseAction
 FileManagerPrivateOpenManageSyncSettingsFunction::Run() {
   if (ash::features::IsDriveFsMirroringEnabled()) {
     ash::ManageMirrorSyncDialog::Show(
diff --git a/chrome/browser/ash/extensions/file_manager/private_api_drive.h b/chrome/browser/ash/extensions/file_manager/private_api_drive.h
index 0f66890..e262598 100644
--- a/chrome/browser/ash/extensions/file_manager/private_api_drive.h
+++ b/chrome/browser/ash/extensions/file_manager/private_api_drive.h
@@ -213,6 +213,18 @@
   ResponseAction Run() override;
 };
 
+// Implements the chrome.fileManagerPrivate.getBulkPinProgress method.
+class FileManagerPrivateGetBulkPinProgressFunction : public ExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.getBulkPinProgress",
+                             FILEMANAGERPRIVATE_GETBULKPINPROGRESS)
+
+ protected:
+  ~FileManagerPrivateGetBulkPinProgressFunction() override = default;
+
+  ResponseAction Run() override;
+};
+
 }  // namespace extensions
 
 #endif  // CHROME_BROWSER_ASH_EXTENSIONS_FILE_MANAGER_PRIVATE_API_DRIVE_H_
diff --git a/chrome/browser/ash/extensions/file_manager/private_api_util.cc b/chrome/browser/ash/extensions/file_manager/private_api_util.cc
index cde0f08..77b3892 100644
--- a/chrome/browser/ash/extensions/file_manager/private_api_util.cc
+++ b/chrome/browser/ash/extensions/file_manager/private_api_util.cc
@@ -32,6 +32,7 @@
 #include "chrome/browser/ash/guest_os/public/types.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/api/file_manager_private.h"
+#include "chromeos/ash/components/drivefs/drivefs_pin_manager.h"
 #include "chromeos/ash/components/drivefs/drivefs_util.h"
 #include "chromeos/ash/components/drivefs/sync_status_tracker.h"
 #include "components/drive/drive_api_util.h"
@@ -239,6 +240,40 @@
   }
 }
 
+extensions::api::file_manager_private::BulkPinStage DrivefsPinStageToJs(
+    drivefs::pinning::Stage stage) {
+  switch (stage) {
+    case drivefs::pinning::Stage::kStopped:
+      return extensions::api::file_manager_private::BULK_PIN_STAGE_STOPPED;
+    case drivefs::pinning::Stage::kPaused:
+      return extensions::api::file_manager_private::BULK_PIN_STAGE_PAUSED;
+    case drivefs::pinning::Stage::kGettingFreeSpace:
+      return extensions::api::file_manager_private::
+          BULK_PIN_STAGE_GETTING_FREE_SPACE;
+    case drivefs::pinning::Stage::kListingFiles:
+      return extensions::api::file_manager_private::
+          BULK_PIN_STAGE_LISTING_FILES;
+    case drivefs::pinning::Stage::kSyncing:
+      return extensions::api::file_manager_private::BULK_PIN_STAGE_SYNCING;
+    case drivefs::pinning::Stage::kSuccess:
+      return extensions::api::file_manager_private::BULK_PIN_STAGE_SUCCESS;
+    case drivefs::pinning::Stage::kCannotGetFreeSpace:
+      return extensions::api::file_manager_private::
+          BULK_PIN_STAGE_CANNOT_GET_FREE_SPACE;
+    case drivefs::pinning::Stage::kCannotListFiles:
+      return extensions::api::file_manager_private::
+          BULK_PIN_STAGE_CANNOT_LIST_FILES;
+    case drivefs::pinning::Stage::kNotEnoughSpace:
+      return extensions::api::file_manager_private::
+          BULK_PIN_STAGE_NOT_ENOUGH_SPACE;
+    case drivefs::pinning::Stage::kCannotEnableDocsOffline:
+      return extensions::api::file_manager_private::
+          BULK_PIN_STAGE_CANNOT_ENABLE_DOCS_OFFLINE;
+  }
+  NOTREACHED();
+  return extensions::api::file_manager_private::BULK_PIN_STAGE_NONE;
+}
+
 }  // namespace
 
 // Creates an instance and starts the process.
@@ -712,5 +747,17 @@
   }
 }
 
+extensions::api::file_manager_private::BulkPinProgress BulkPinProgressToJs(
+    const drivefs::pinning::Progress& progress) {
+  extensions::api::file_manager_private::BulkPinProgress result;
+  result.stage = DrivefsPinStageToJs(progress.stage);
+  result.free_space_bytes = progress.free_space;
+  result.required_space_bytes = progress.required_space;
+  result.bytes_to_pin = progress.bytes_to_pin;
+  result.pinned_bytes = progress.pinned_bytes;
+  result.files_to_pin = progress.files_to_pin;
+  return result;
+}
+
 }  // namespace util
 }  // namespace file_manager
diff --git a/chrome/browser/ash/extensions/file_manager/private_api_util.h b/chrome/browser/ash/extensions/file_manager/private_api_util.h
index 7490b17..dd1470c24 100644
--- a/chrome/browser/ash/extensions/file_manager/private_api_util.h
+++ b/chrome/browser/ash/extensions/file_manager/private_api_util.h
@@ -39,6 +39,10 @@
 class EventLogger;
 }
 
+namespace drivefs::pinning {
+struct Progress;
+}
+
 namespace extensions {
 namespace api {
 namespace file_manager_private {
@@ -177,6 +181,11 @@
     extensions::api::file_manager_private::FileCategory input_category,
     ash::RecentSource::FileType* output_type);
 
+// Converts the given |progress| struct containing the progress of Drive's bulk
+// pinning to its file manager private equivalent.
+extensions::api::file_manager_private::BulkPinProgress BulkPinProgressToJs(
+    const drivefs::pinning::Progress& progress);
+
 }  // namespace util
 }  // namespace file_manager
 
diff --git a/chrome/browser/ash/file_manager/file_tasks.cc b/chrome/browser/ash/file_manager/file_tasks.cc
index 483ff8a5..97bf7bc 100644
--- a/chrome/browser/ash/file_manager/file_tasks.cc
+++ b/chrome/browser/ash/file_manager/file_tasks.cc
@@ -46,6 +46,7 @@
 #include "chrome/browser/ash/file_manager/open_with_browser.h"
 #include "chrome/browser/ash/file_manager/url_util.h"
 #include "chrome/browser/ash/file_system_provider/mount_path_util.h"
+#include "chrome/browser/ash/file_system_provider/provided_file_system_info.h"
 #include "chrome/browser/ash/file_system_provider/provided_file_system_interface.h"
 #include "chrome/browser/ash/file_system_provider/service.h"
 #include "chrome/browser/ash/fileapi/file_system_backend.h"
@@ -108,8 +109,37 @@
     "open-web-drive-office-powerpoint";
 const char kActionIdOpenInOffice[] = "open-in-office";
 const char kActionIdOpenWeb[] = "OPEN_WEB";
+const char kODFSExtensionId[] = "gnnndjlaomemikopnjhhnoombakkkkdg";
 
-const char kODFSExtensionId[] = "ajdgmkbkgifbokednjgbmieaemeighkg";
+// Searches for the installed extension in order of preference.
+std::string GetODFSExtensionId(Profile* profile) {
+  const ash::file_system_provider::Service* const service =
+      ash::file_system_provider::Service::Get(profile);
+
+  for (const auto& [provider_id, provider] : service->GetProviders()) {
+    if (provider_id.GetType() !=
+        ash::file_system_provider::ProviderId::EXTENSION) {
+      continue;
+    }
+    const auto& extension_id = provider_id.GetExtensionId();
+
+    // App from official internal build.
+    if (extension_id == kODFSExtensionId) {
+      return kODFSExtensionId;
+    }
+
+    // App built manually from internal repo.
+    if (extension_id == "gcpjnalmmghdoadafjgomdlghfnllceo") {
+      return "gcpjnalmmghdoadafjgomdlghfnllceo";
+    }
+
+    // App built manually from internal git, used for the early dogfood.
+    if (extension_id == "ajdgmkbkgifbokednjgbmieaemeighkg") {
+      return "ajdgmkbkgifbokednjgbmieaemeighkg";
+    }
+  }
+  return {};
+}
 
 namespace {
 
diff --git a/chrome/browser/ash/file_manager/file_tasks.h b/chrome/browser/ash/file_manager/file_tasks.h
index d160c067..baff22a 100644
--- a/chrome/browser/ash/file_manager/file_tasks.h
+++ b/chrome/browser/ash/file_manager/file_tasks.h
@@ -133,6 +133,10 @@
 
 extern const char kODFSExtensionId[];
 
+// Checks which extension is installed and return the latest one installed or ""
+// if none is installed
+std::string GetODFSExtensionId(Profile* profile);
+
 // Task types as explained in the comment above. Search for <task-type>.
 enum TaskType {
   TASK_TYPE_UNKNOWN = 0,  // Used only for handling errors.
diff --git a/chrome/browser/ash/login/demo_mode/demo_session.cc b/chrome/browser/ash/login/demo_mode/demo_session.cc
index f724618..5c89cbd 100644
--- a/chrome/browser/ash/login/demo_mode/demo_session.cc
+++ b/chrome/browser/ash/login/demo_mode/demo_session.cc
@@ -568,8 +568,8 @@
     // The hashing salt for the AA experiment.
     std::string demo_mode_aa_experiment_hashing_salt = "fae448044d545f9c";
 
-    std::vector<std::string> best_buy_retailer_names = {"BBY", "bby", "BestBuy",
-                                                        "BBT"};
+    std::vector<std::string> best_buy_retailer_names = {"bby", "bestbuy",
+                                                        "bbt"};
     std::vector<std::string>::iterator it;
 
     it = std::find(best_buy_retailer_names.begin(),
diff --git a/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc b/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc
index 6e1b261e..e052af76 100644
--- a/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc
+++ b/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc
@@ -267,7 +267,7 @@
     test::OobeJS().ClickOnPath(kDemoPreferencesNext);
   }
 
-  // Type in valid input and the "continue" button is enabled.
+  // Type in valid input and verify that the "continue" button is enabled.
   void SetAndVerifyValidRetailerNameAndStoreNumber(
       const std::string& expected_retailer_name,
       const std::string& expected_store_number) {
@@ -576,7 +576,8 @@
   // it's shown again when Demo setup completes.
   LoginOrLockScreenVisibleWaiter().WaitEvenIfShown();
 
-  EXPECT_EQ("Retailer", g_browser_process->local_state()->GetString(
+  // Verify that pref value has been normalized to uppercase.
+  EXPECT_EQ("retailer", g_browser_process->local_state()->GetString(
                             prefs::kDemoModeRetailerId));
   EXPECT_EQ("1234", g_browser_process->local_state()->GetString(
                         prefs::kDemoModeStoreId));
diff --git a/chrome/browser/ash/login/demo_mode/demo_setup_controller.cc b/chrome/browser/ash/login/demo_mode/demo_setup_controller.cc
index 0fb5524f..43b5fac2 100644
--- a/chrome/browser/ash/login/demo_mode/demo_setup_controller.cc
+++ b/chrome/browser/ash/login/demo_mode/demo_setup_controller.cc
@@ -39,6 +39,8 @@
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "google_apis/gaia/google_service_auth_error.h"
+#include "third_party/icu/source/common/unicode/bytestream.h"
+#include "third_party/icu/source/common/unicode/casemap.h"
 #include "ui/base/l10n/l10n_util.h"
 
 namespace ash {
@@ -488,6 +490,19 @@
 
 DemoSetupController::~DemoSetupController() = default;
 
+void DemoSetupController::SetAndCanonicalizeRetailerName(
+    const std::string& retailer_name) {
+  icu::StringByteSink<std::string> byte_sink(&retailer_name_);
+  UErrorCode error_code = U_ZERO_ERROR;
+  icu::CaseMap::utf8Fold(/* options= */ 0, retailer_name, byte_sink,
+                         /* edits= */ nullptr, error_code);
+  retailer_name_.erase(
+      std::remove_if(
+          retailer_name_.begin(), retailer_name_.end(),
+          [](unsigned char c) { return std::ispunct(c) || std::isspace(c); }),
+      retailer_name_.end());
+}
+
 void DemoSetupController::Enroll(
     OnSetupSuccess on_setup_success,
     OnSetupError on_setup_error,
diff --git a/chrome/browser/ash/login/demo_mode/demo_setup_controller.h b/chrome/browser/ash/login/demo_mode/demo_setup_controller.h
index bce5da32..c57269c 100644
--- a/chrome/browser/ash/login/demo_mode/demo_setup_controller.h
+++ b/chrome/browser/ash/login/demo_mode/demo_setup_controller.h
@@ -202,9 +202,11 @@
     demo_config_ = demo_config;
   }
 
-  void set_retailer_name(const std::string& retailer_name) {
-    retailer_name_ = retailer_name;
-  }
+  // Set a canonicalized (whitespace and punctuation removed, case homogenized)
+  // version of the retailer name string.
+  void SetAndCanonicalizeRetailerName(const std::string& retailer_name);
+
+  std::string get_retailer_name_for_testing() { return retailer_name_; }
 
   void set_store_number(const std::string& store_number) {
     store_number_ = store_number;
diff --git a/chrome/browser/ash/login/demo_mode/demo_setup_controller_unittest.cc b/chrome/browser/ash/login/demo_mode/demo_setup_controller_unittest.cc
index 477720c..1ebc2b7e 100644
--- a/chrome/browser/ash/login/demo_mode/demo_setup_controller_unittest.cc
+++ b/chrome/browser/ash/login/demo_mode/demo_setup_controller_unittest.cc
@@ -377,7 +377,7 @@
   SetupMockDemoModeOnlineEnrollmentHelper(DemoModeSetupResult::SUCCESS);
 
   tested_controller_->set_demo_config(DemoSession::DemoModeConfig::kOnline);
-  tested_controller_->set_retailer_name("Retailer");
+  tested_controller_->SetAndCanonicalizeRetailerName("Retailer");
   tested_controller_->set_store_number("1234");
   tested_controller_->Enroll(
       base::BindOnce(&DemoSetupControllerTestHelper::OnSetupSuccess,
@@ -390,11 +390,50 @@
   EXPECT_TRUE(
       helper_->WaitResult(true, DemoSetupController::DemoSetupStep::kComplete));
   EXPECT_EQ("", GetDeviceRequisition());
-  EXPECT_EQ("Retailer", g_browser_process->local_state()->GetString(
+  EXPECT_EQ("retailer", g_browser_process->local_state()->GetString(
                             prefs::kDemoModeRetailerId));
   EXPECT_EQ("1234", g_browser_process->local_state()->GetString(
                         prefs::kDemoModeStoreId));
 }
 
+struct RetailerNameCanonicalizationTestCase {
+  std::string retailer_name;
+  std::string canonicalized_retailer_name;
+};
+
+class RetailerNameCanonicalizationTest
+    : public DemoSetupControllerTest,
+      public ::testing::WithParamInterface<
+          RetailerNameCanonicalizationTestCase> {
+ public:
+  RetailerNameCanonicalizationTest() = default;
+  ~RetailerNameCanonicalizationTest() override = default;
+};
+
+TEST_P(RetailerNameCanonicalizationTest, SetAndCanonicalizeRetailerName) {
+  tested_controller_->SetAndCanonicalizeRetailerName(GetParam().retailer_name);
+  ASSERT_EQ(tested_controller_->get_retailer_name_for_testing(),
+            GetParam().canonicalized_retailer_name);
+}
+
+const RetailerNameCanonicalizationTestCase kRetailerNameTestCases[] = {
+    {"retailer", "retailer"},
+    {"RETAILER", "retailer"},
+    {"ReTaiLeR", "retailer"},
+    {"retailer with spaces", "retailerwithspaces"},
+    {"retailer' w:th $ymbols", "retailerwthymbols"},
+    // Don't remove numeric chars
+    {"r3ta1ler", "r3ta1ler"},
+    // Test various case-sensitive diacritics and non-latin characters
+    {"rétailër", "rétailër"},
+    {"RÉTAILËR", "rétailër"},
+    {"RÆTÅILØR", "rætåilør"},
+    {"بائع تجزئة", "بائعتجزئة"},
+    {"小売業者.com", "小売業者com"}};
+
+INSTANTIATE_TEST_SUITE_P(TestRetailerNameTransformations,
+                         RetailerNameCanonicalizationTest,
+                         testing::ValuesIn(kRetailerNameTestCases));
+
 }  // namespace
 }  //  namespace ash
diff --git a/chrome/browser/ash/login/screens/demo_preferences_screen.cc b/chrome/browser/ash/login/screens/demo_preferences_screen.cc
index 5d78e5a..afe83d1 100644
--- a/chrome/browser/ash/login/screens/demo_preferences_screen.cc
+++ b/chrome/browser/ash/login/screens/demo_preferences_screen.cc
@@ -69,7 +69,7 @@
     const std::string& store_number_input = args[2].GetString();
     DemoSetupController* demo_setup_controller =
         WizardController::default_controller()->demo_setup_controller();
-    demo_setup_controller->set_retailer_name(retailer_name_input);
+    demo_setup_controller->SetAndCanonicalizeRetailerName(retailer_name_input);
     demo_setup_controller->set_store_number(store_number_input);
 
     exit_callback_.Run(Result::COMPLETED);
diff --git a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc
index e164e40..f26f39c 100644
--- a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc
+++ b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc
@@ -103,6 +103,9 @@
 
 }  // namespace
 
+ChromeOsFeedbackDelegate::ChromeOsFeedbackDelegate(content::WebUI* web_ui)
+    : ChromeOsFeedbackDelegate(Profile::FromWebUI(web_ui)) {}
+
 ChromeOsFeedbackDelegate::ChromeOsFeedbackDelegate(Profile* profile)
     : ChromeOsFeedbackDelegate(profile,
                                FeedbackPrivateAPI::GetFactoryInstance()
@@ -121,6 +124,17 @@
   }
 }
 
+ChromeOsFeedbackDelegate ChromeOsFeedbackDelegate::CreateForTesting(
+    Profile* profile) {
+  return ChromeOsFeedbackDelegate(profile);
+}
+
+ChromeOsFeedbackDelegate ChromeOsFeedbackDelegate::CreateForTesting(
+    Profile* profile,
+    scoped_refptr<extensions::FeedbackService> feedback_service) {
+  return ChromeOsFeedbackDelegate(profile, feedback_service);
+}
+
 ChromeOsFeedbackDelegate::~ChromeOsFeedbackDelegate() {
   auto* screenshot_manager = OsFeedbackScreenshotManager::GetIfExists();
   if (screenshot_manager) {
diff --git a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.h b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.h
index c29f5c0..15cd7c68 100644
--- a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.h
+++ b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.h
@@ -14,6 +14,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "components/feedback/system_logs/system_logs_source.h"
+#include "content/public/browser/web_ui.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
@@ -27,15 +28,17 @@
 
 class ChromeOsFeedbackDelegate : public OsFeedbackDelegate {
  public:
-  explicit ChromeOsFeedbackDelegate(Profile* profile);
-  ChromeOsFeedbackDelegate(
-      Profile* profile,
-      scoped_refptr<extensions::FeedbackService> feedback_service);
+  explicit ChromeOsFeedbackDelegate(content::WebUI* web_ui);
   ~ChromeOsFeedbackDelegate() override;
 
   ChromeOsFeedbackDelegate(const ChromeOsFeedbackDelegate&) = delete;
   ChromeOsFeedbackDelegate& operator=(const ChromeOsFeedbackDelegate&) = delete;
 
+  static ChromeOsFeedbackDelegate CreateForTesting(Profile* profile);
+  static ChromeOsFeedbackDelegate CreateForTesting(
+      Profile* profile,
+      scoped_refptr<extensions::FeedbackService> feedback_service);
+
   // OsFeedbackDelegate:
   std::string GetApplicationLocale() override;
   absl::optional<GURL> GetLastActivePageUrl() override;
@@ -53,6 +56,10 @@
   bool IsChildAccount() override;
 
  private:
+  explicit ChromeOsFeedbackDelegate(Profile* profile);
+  ChromeOsFeedbackDelegate(
+      Profile* profile,
+      scoped_refptr<extensions::FeedbackService> feedback_service);
   void OnSendFeedbackDone(SendReportCallback callback, bool status);
   void OpenWebDialog(GURL url, const std::string& args);
   // Loading system logs could be slow. Preload them to reduce potential user
diff --git a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc
index 6c5a1be..69636835 100644
--- a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc
+++ b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc
@@ -199,8 +199,9 @@
   ~ChromeOsFeedbackDelegateTest() override = default;
 
   absl::optional<GURL> GetLastActivePageUrl() {
-    ChromeOsFeedbackDelegate feedback_delegate_(browser()->profile());
-    return feedback_delegate_.GetLastActivePageUrl();
+    auto feedback_delegate =
+        ChromeOsFeedbackDelegate::CreateForTesting(browser()->profile());
+    return feedback_delegate.GetLastActivePageUrl();
   }
 
  protected:
@@ -240,12 +241,12 @@
           std::move(callback).Run(true);
         });
 
-    auto feedback_delegate_ = std::make_unique<ChromeOsFeedbackDelegate>(
+    auto feedback_delegate = ChromeOsFeedbackDelegate::CreateForTesting(
         profile_, std::move(mock_feedback_service));
 
     if (preload_system_logs) {
       // Trigger preloading.
-      feedback_delegate_->GetLastActivePageUrl();
+      feedback_delegate.GetLastActivePageUrl();
       // Wait for preloading is completed.
       EXPECT_TRUE(fetch_future.Take());
     }
@@ -254,7 +255,7 @@
         CreateFakePngData());
 
     base::test::TestFuture<SendReportStatus> future;
-    feedback_delegate_->SendReport(std::move(report), future.GetCallback());
+    feedback_delegate.SendReport(std::move(report), future.GetCallback());
 
     EXPECT_EQ(SendReportStatus::kSuccess, future.Get());
   }
@@ -309,8 +310,9 @@
 
 // Test GetApplicationLocale returns a valid locale.
 IN_PROC_BROWSER_TEST_F(ChromeOsFeedbackDelegateTest, GetApplicationLocale) {
-  ChromeOsFeedbackDelegate feedback_delegate_(browser()->profile());
-  EXPECT_EQ(feedback_delegate_.GetApplicationLocale(), "en-US");
+  auto feedback_delegate =
+      ChromeOsFeedbackDelegate::CreateForTesting(browser()->profile());
+  EXPECT_EQ(feedback_delegate.GetApplicationLocale(), "en-US");
 }
 
 // Test GetLastActivePageUrl returns last active page url if any.
@@ -328,21 +330,23 @@
       IdentityManagerFactory::GetForProfile(browser()->profile());
   EXPECT_TRUE(identity_manager);
 
-  ChromeOsFeedbackDelegate feedback_delegate_(browser()->profile());
-  EXPECT_EQ(feedback_delegate_.GetSignedInUserEmail(), "");
+  auto feedback_delegate =
+      ChromeOsFeedbackDelegate::CreateForTesting(browser()->profile());
+  EXPECT_EQ(feedback_delegate.GetSignedInUserEmail(), "");
 
   signin::MakePrimaryAccountAvailable(identity_manager, kSignedInUserEmail,
                                       signin::ConsentLevel::kSignin);
-  EXPECT_EQ(feedback_delegate_.GetSignedInUserEmail(), kSignedInUserEmail);
+  EXPECT_EQ(feedback_delegate.GetSignedInUserEmail(), kSignedInUserEmail);
 }
 
 // Test GetPerformanceTraceId returns id for performance trace data if any.
 IN_PROC_BROWSER_TEST_F(ChromeOsFeedbackDelegateTest, GetPerformanceTraceId) {
-  ChromeOsFeedbackDelegate feedback_delegate_(browser()->profile());
-  EXPECT_EQ(feedback_delegate_.GetPerformanceTraceId(), 0);
+  auto feedback_delegate =
+      ChromeOsFeedbackDelegate::CreateForTesting(browser()->profile());
+  EXPECT_EQ(feedback_delegate.GetPerformanceTraceId(), 0);
   std::unique_ptr<ContentTracingManager> tracing_manager =
       ContentTracingManager::Create();
-  EXPECT_EQ(feedback_delegate_.GetPerformanceTraceId(), 1);
+  EXPECT_EQ(feedback_delegate.GetPerformanceTraceId(), 1);
 }
 
 // Test that feedback params and data are populated with correct data before
@@ -593,13 +597,14 @@
 
 // Test GetScreenshot returns correct data when there is a screenshot.
 IN_PROC_BROWSER_TEST_F(ChromeOsFeedbackDelegateTest, HasScreenshot) {
-  ChromeOsFeedbackDelegate feedback_delegate_(browser()->profile());
+  auto feedback_delegate =
+      ChromeOsFeedbackDelegate::CreateForTesting(browser()->profile());
 
   OsFeedbackScreenshotManager::GetInstance()->SetPngDataForTesting(
       CreateFakePngData());
 
   base::test::TestFuture<const std::vector<uint8_t>&> future;
-  feedback_delegate_.GetScreenshotPng(future.GetCallback());
+  feedback_delegate.GetScreenshotPng(future.GetCallback());
 
   const std::vector<uint8_t> expected{12, 11, 99};
   const std::vector<uint8_t> result = future.Get();
@@ -608,9 +613,10 @@
 
 // Test GetScreenshot returns empty array when there is not a screenshot.
 IN_PROC_BROWSER_TEST_F(ChromeOsFeedbackDelegateTest, NoScreenshot) {
-  ChromeOsFeedbackDelegate feedback_delegate_(browser()->profile());
+  auto feedback_delegate =
+      ChromeOsFeedbackDelegate::CreateForTesting(browser()->profile());
   base::test::TestFuture<const std::vector<uint8_t>&> future;
-  feedback_delegate_.GetScreenshotPng(future.GetCallback());
+  feedback_delegate.GetScreenshotPng(future.GetCallback());
 
   const std::vector<uint8_t> result = future.Get();
   EXPECT_EQ(0u, result.size());
@@ -618,13 +624,14 @@
 
 // Test if Diagnostics app is opened.
 IN_PROC_BROWSER_TEST_F(ChromeOsFeedbackDelegateTest, OpenDiagnosticsApp) {
-  ChromeOsFeedbackDelegate feedback_delegate_(browser()->profile());
+  auto feedback_delegate =
+      ChromeOsFeedbackDelegate::CreateForTesting(browser()->profile());
   ash::SystemWebAppManager::GetForTest(browser()->profile())
       ->InstallSystemAppsForTesting();
 
   ui_test_utils::BrowserChangeObserver browser_opened(
       nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded);
-  feedback_delegate_.OpenDiagnosticsApp();
+  feedback_delegate.OpenDiagnosticsApp();
   browser_opened.Wait();
 
   Browser* app_browser = ash::FindSystemWebAppBrowser(
@@ -636,13 +643,14 @@
 
 // Test if Explore app is opened.
 IN_PROC_BROWSER_TEST_F(ChromeOsFeedbackDelegateTest, OpenExploreApp) {
-  ChromeOsFeedbackDelegate feedback_delegate_(browser()->profile());
+  auto feedback_delegate =
+      ChromeOsFeedbackDelegate::CreateForTesting(browser()->profile());
   ash::SystemWebAppManager::GetForTest(browser()->profile())
       ->InstallSystemAppsForTesting();
 
   ui_test_utils::BrowserChangeObserver browser_opened(
       nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded);
-  feedback_delegate_.OpenExploreApp();
+  feedback_delegate.OpenExploreApp();
   browser_opened.Wait();
 
   Browser* app_browser = ash::FindSystemWebAppBrowser(
@@ -666,9 +674,10 @@
   EXPECT_EQ(owned_widgets_pre_dialog.size(), 0u);
 
   // Initialize the delegate.
-  ChromeOsFeedbackDelegate feedback_delegate_(browser()->profile());
+  auto feedback_delegate =
+      ChromeOsFeedbackDelegate::CreateForTesting(browser()->profile());
 
-  feedback_delegate_.OpenMetricsDialog();
+  feedback_delegate.OpenMetricsDialog();
 
   std::set<views::Widget*> owned_widgets_post_dialog;
   views::Widget::GetAllOwnedWidgets(feedback_window,
@@ -691,9 +700,10 @@
   EXPECT_EQ(owned_widgets_pre_dialog.size(), 0u);
 
   // Initialize the delegate.
-  ChromeOsFeedbackDelegate feedback_delegate_(browser()->profile());
+  auto feedback_delegate =
+      ChromeOsFeedbackDelegate::CreateForTesting(browser()->profile());
 
-  feedback_delegate_.OpenSystemInfoDialog();
+  feedback_delegate.OpenSystemInfoDialog();
 
   std::set<views::Widget*> owned_widgets_post_dialog;
   views::Widget::GetAllOwnedWidgets(feedback_window,
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_integration_browsertest.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_integration_browsertest.cc
index 44da64d4..a6603e1 100644
--- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_integration_browsertest.cc
+++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_integration_browsertest.cc
@@ -10,37 +10,32 @@
 #include "ash/shell.h"
 #include "ash/webui/personalization_app/personalization_app_url_constants.h"
 #include "ash/webui/system_apps/public/system_web_app_type.h"
-#include "base/files/file_path.h"
 #include "base/functional/callback.h"
 #include "base/functional/callback_helpers.h"
 #include "base/memory/raw_ptr.h"
-#include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/scoped_observation.h"
 #include "base/test/bind.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/test_switches.h"
-#include "cc/test/pixel_comparator.h"
 #include "cc/test/pixel_test_utils.h"
 #include "chrome/browser/apps/app_service/app_launch_params.h"
 #include "chrome/browser/ash/system_web_apps/test_support/system_web_app_integration_test.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/exclusive_access/exclusive_access_test.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/common/chrome_paths.h"
 #include "chromeos/ui/base/window_properties.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
 #include "ui/base/class_property.h"
-#include "ui/compositor/layer.h"
 #include "ui/display/test/display_manager_test_api.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/test/sk_color_eq.h"
 #include "ui/message_center/message_center.h"
 #include "ui/snapshot/snapshot_aura.h"
 #include "ui/views/widget/widget.h"
@@ -160,14 +155,29 @@
   const raw_ptr<const ui::ClassProperty<T>> key_;
 };
 
-void CallJavascriptAndWaitForPropertyChange(content::WebContents* web_contents,
-                                            const std::u16string& javascript) {
-  WindowPropertyWaiter<bool> window_property_waiter(
-      web_contents->GetTopLevelNativeWindow(),
-      chromeos::kWindowManagerManagesOpacityKey);
+void CallMakeTransparentAndWaitForOpacityChange(
+    content::WebContents* web_contents) {
   web_contents->GetPrimaryMainFrame()->ExecuteJavaScriptForTests(
-      javascript, base::DoNothing());
-  window_property_waiter.Wait();
+      u"personalizationTestApi.makeTransparent()", base::DoNothing());
+
+  auto* window = web_contents->GetTopLevelNativeWindow();
+  auto* const opacityKey = chromeos::kWindowManagerManagesOpacityKey;
+
+  if (window->GetProperty(opacityKey)) {
+    // Wait for opacity key to change to false.
+    WindowPropertyWaiter<bool> window_property_waiter(window, opacityKey);
+    window_property_waiter.Wait();
+  }
+
+  // Wait for a round trip through renderer and compositor for transparency to
+  // take effect.
+  base::RunLoop loop;
+  web_contents->GetPrimaryMainFrame()->InsertVisualStateCallback(
+      base::BindLambdaForTesting([&loop](bool visual_state_updated) {
+        ASSERT_TRUE(visual_state_updated);
+        loop.Quit();
+      }));
+  loop.Run();
 }
 
 class WallpaperChangeWaiter : public ash::WallpaperControllerObserver {
@@ -283,8 +293,7 @@
   Browser* browser;
   content::WebContents* web_contents = LaunchAppAtWallpaperSubpage(&browser);
 
-  CallJavascriptAndWaitForPropertyChange(
-      web_contents, u"personalizationTestApi.makeTransparent();");
+  CallMakeTransparentAndWaitForOpacityChange(web_contents);
 
   EXPECT_TRUE(web_contents->GetTopLevelNativeWindow()->GetTransparent());
   EXPECT_FALSE(web_contents->GetTopLevelNativeWindow()->GetProperty(
@@ -298,8 +307,7 @@
   content::WebContents* web_contents = LaunchAppAtWallpaperSubpage(&browser);
   aura::Window* window = web_contents->GetTopLevelNativeWindow();
 
-  CallJavascriptAndWaitForPropertyChange(
-      web_contents, u"personalizationTestApi.makeTransparent();");
+  CallMakeTransparentAndWaitForOpacityChange(web_contents);
 
   ash::WindowBackdrop* window_backdrop = ash::WindowBackdrop::Get(window);
   EXPECT_EQ(ash::WindowBackdrop::BackdropMode::kDisabled,
@@ -307,25 +315,28 @@
 }
 
 // Test that the background color is forced to be transparent.
-// Disabled due to flakiness. crbug.com/1294458
 IN_PROC_BROWSER_TEST_P(PersonalizationAppIntegrationTest,
-                       DISABLED_SetsTransparentBackgroundColor) {
+                       SetsTransparentBackgroundColor) {
   WaitForTestSystemAppInstall();
   Browser* browser;
   content::WebContents* web_contents = LaunchAppAtWallpaperSubpage(&browser);
+  DCHECK(web_contents);
 
-  CallJavascriptAndWaitForPropertyChange(
-      web_contents, u"personalizationTestApi.makeTransparent();");
+  CallMakeTransparentAndWaitForOpacityChange(web_contents);
 
   BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
-  EXPECT_EQ(SK_ColorTRANSPARENT,
-            browser_view->contents_web_view()->GetBackground()->get_color());
+  EXPECT_FALSE(browser_view->contents_web_view()->GetBackground())
+      << "No background set for personalization app contents web view";
 
-  // Personalization app by default has an opaque content background color.
+  EXPECT_NE(
+      SK_ColorTRANSPARENT,
+      web_contents->GetRenderWidgetHostView()->GetBackgroundColor().value())
+      << "personalization app starts with opaque background color";
+
   // Trigger full screen mode, which sets a transparent background color.
   SetAppFullscreenAndWait(browser, web_contents);
 
-  EXPECT_EQ(
+  EXPECT_SKCOLOR_EQ(
       SK_ColorTRANSPARENT,
       web_contents->GetRenderWidgetHostView()->GetBackgroundColor().value());
 }
@@ -353,8 +364,7 @@
   Browser* browser;
   content::WebContents* web_contents = LaunchAppAtWallpaperSubpage(&browser);
 
-  CallJavascriptAndWaitForPropertyChange(
-      web_contents, u"personalizationTestApi.makeTransparent();");
+  CallMakeTransparentAndWaitForOpacityChange(web_contents);
 
   WallpaperChangeWaiter wallpaper_changer;
   wallpaper_changer.SetWallpaperAndWait();
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.cc
index 16193d5..06cdcbe3 100644
--- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.cc
+++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.cc
@@ -194,7 +194,7 @@
   web_contents->GetRenderWidgetHostView()->SetBackgroundColor(
       SK_ColorTRANSPARENT);
 
-  // Set a background color override.
+  // Turn off the web contents background.
   static_cast<ContentsWebView*>(BrowserView::GetBrowserViewForNativeWindow(
                                     web_contents->GetTopLevelNativeWindow())
                                     ->contents_web_view())
diff --git a/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java
index 7290883..fb1d9c0 100644
--- a/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java
+++ b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java
@@ -1319,6 +1319,21 @@
     }
 
     /**
+     * @return Whether the Autofill feature for payment methods mandatory reauth is enabled.
+     */
+    public static boolean isAutofillPaymentMethodsMandatoryReauthEnabled() {
+        return getPrefService().getBoolean(Pref.AUTOFILL_PAYMENT_METHODS_MANDATORY_REAUTH);
+    }
+
+    /**
+     * Enables or disables the Autofill feature for payment methods mandatory reauth.
+     * @param enable True to enable payment methods mandatory reauth, false otherwise.
+     */
+    public static void setAutofillPaymentMethodsMandatoryReauth(boolean enable) {
+        getPrefService().setBoolean(Pref.AUTOFILL_PAYMENT_METHODS_MANDATORY_REAUTH, enable);
+    }
+
+    /**
      * @return Whether the Autofill feature is managed.
      */
     public static boolean isAutofillManaged() {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index c5c4701..41c233d 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -3304,6 +3304,11 @@
     "expiry_milestone": 120
   },
   {
+    "name": "enable-tailored-security-updated-messages",
+    "owners": [ "awado", "jacastro", "chrome-counter-abuse-alerts@google.com"],
+    "expiry_milestone": 120
+  },
+  {
     "name": "enable-tflite-language-detection",
     "owners": [ "sophiechang", "chrome-intelligence-core@google.com" ],
     "expiry_milestone": 116
@@ -4178,8 +4183,8 @@
   },
   {
     "name": "fuse-box-debug",
-    "owners": [ "nigeltao", "noel", "simmonsjosh@google.com" ],
-    "expiry_milestone": 114
+    "owners": [ "nigeltao", "simmonsjosh@google.com" ],
+    "expiry_milestone": 126
   },
   {
     "name": "gaia-id-in-amf",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 578b9e8a..fdbfbe1c 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1175,6 +1175,12 @@
     "directed to the chrome security settings page through ESB promotions and "
     "also collapses the ESB option.";
 
+const char kEnableTailoredSecurityUpdatedMessagesName[] =
+    "Enable tailored security updated messages";
+const char kEnableTailoredSecurityUpdatedMessagesDescription[] =
+    "Updates the tailored security dialog strings and icons for their "
+    "respective platforms.";
+
 const char kEnableNetworkLoggingToFileName[] = "Enable network logging to file";
 const char kEnableNetworkLoggingToFileDescription[] =
     "Enables network logging to a file named netlog.json in the user data "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index bb33d3a..e9b73f1 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -686,6 +686,9 @@
 extern const char kEnableEnhancedSafeBrowsingSettingsImprovementsName[];
 extern const char kEnableEnhancedSafeBrowsingSettingsImprovementsDescription[];
 
+extern const char kEnableTailoredSecurityUpdatedMessagesName[];
+extern const char kEnableTailoredSecurityUpdatedMessagesDescription[];
+
 extern const char kEnableFencedFramesName[];
 extern const char kEnableFencedFramesDescription[];
 
diff --git a/chrome/browser/new_tab_page/modules/history_clusters/history_clusters.mojom b/chrome/browser/new_tab_page/modules/history_clusters/history_clusters.mojom
index 755dc8d9..a9bc0b8e 100644
--- a/chrome/browser/new_tab_page/modules/history_clusters/history_clusters.mojom
+++ b/chrome/browser/new_tab_page/modules/history_clusters/history_clusters.mojom
@@ -9,8 +9,8 @@
 
 // Browser-side handler for requests from WebUI page.
 interface PageHandler {
-  // Get the most relevant history cluster.
-  GetCluster() => (history_clusters.mojom.Cluster? cluster);
+  // Get a series of relevant history clusters.
+  GetClusters() => (array<history_clusters.mojom.Cluster> clusters);
 
   // Open or make visible the Journeys UI on the Side Panel.
   ShowJourneysSidePanel(string query);
diff --git a/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler.cc b/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler.cc
index 9120a66..9fb4fec 100644
--- a/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler.cc
+++ b/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler.cc
@@ -228,12 +228,13 @@
 HistoryClustersPageHandler::~HistoryClustersPageHandler() = default;
 
 void HistoryClustersPageHandler::CallbackWithClusterData(
-    GetClusterCallback callback,
+    GetClustersCallback callback,
     std::vector<history::Cluster> clusters,
     history_clusters::QueryClustersContinuationParams continuation_params) {
   const TemplateURLService* template_url_service =
       TemplateURLServiceFactory::GetForProfile(profile_);
   if (!template_url_service) {
+    std::move(callback).Run({});
     return;
   }
 
@@ -312,19 +313,22 @@
                               clusters.size());
 
   if (clusters.empty()) {
-    std::move(callback).Run(nullptr);
+    std::move(callback).Run({});
     return;
   }
 
-  base::UmaHistogramCounts100("NewTabPage.HistoryClusters.NumVisits",
-                              clusters.front().visits.size());
-  base::UmaHistogramCounts100("NewTabPage.HistoryClusters.NumRelatedSearches",
-                              clusters.front().related_searches.size());
-
   history::Cluster top_cluster = clusters.front();
-  auto cluster_mojom =
-      history_clusters::ClusterToMojom(template_url_service, top_cluster);
-  std::move(callback).Run(std::move(cluster_mojom));
+  base::UmaHistogramCounts100("NewTabPage.HistoryClusters.NumVisits",
+                              top_cluster.visits.size());
+  base::UmaHistogramCounts100("NewTabPage.HistoryClusters.NumRelatedSearches",
+                              top_cluster.related_searches.size());
+
+  std::vector<history_clusters::mojom::ClusterPtr> clusters_mojom;
+  for (const auto& cluster : clusters) {
+    clusters_mojom.push_back(
+        history_clusters::ClusterToMojom(template_url_service, cluster));
+  }
+  std::move(callback).Run(std::move(clusters_mojom));
 
   if (!IsCartModuleEnabled() || !cart_service_) {
     return;
@@ -344,7 +348,7 @@
   }
 }
 
-void HistoryClustersPageHandler::GetCluster(GetClusterCallback callback) {
+void HistoryClustersPageHandler::GetClusters(GetClustersCallback callback) {
   const std::string fake_data_param = base::GetFieldTrialParamValueByFeature(
       ntp_features::kNtpHistoryClustersModule,
       ntp_features::kNtpHistoryClustersModuleDataParam);
@@ -355,7 +359,7 @@
     if (kFakeDataParams.size() != 2) {
       LOG(ERROR) << "Invalid history clusters fake data selection parameter "
                     "format.";
-      std::move(callback).Run(nullptr);
+      std::move(callback).Run({});
       return;
     }
 
@@ -364,13 +368,15 @@
     if (!base::StringToInt(kFakeDataParams.at(0), &num_visits) ||
         !base::StringToInt(kFakeDataParams.at(1), &num_images) ||
         num_visits < num_images) {
-      std::move(callback).Run(nullptr);
+      std::move(callback).Run({});
       return;
     }
 
-    std::move(callback).Run(history_clusters::ClusterToMojom(
+    std::vector<history_clusters::mojom::ClusterPtr> clusters_mojom;
+    clusters_mojom.push_back(history_clusters::ClusterToMojom(
         TemplateURLServiceFactory::GetForProfile(profile_),
         GenerateSampleCluster(num_visits, num_images)));
+    std::move(callback).Run(std::move(clusters_mojom));
     return;
   }
 
diff --git a/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler.h b/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler.h
index 9419d89..3ee99389 100644
--- a/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler.h
+++ b/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler.h
@@ -43,16 +43,16 @@
   ~HistoryClustersPageHandler() override;
 
   // mojom::PageHandler:
-  void GetCluster(GetClusterCallback callback) override;
+  void GetClusters(GetClustersCallback callback) override;
   void ShowJourneysSidePanel(const std::string& query) override;
   void OpenUrlsInTabGroup(const std::vector<GURL>&) override;
   void DismissCluster(
       const std::vector<history_clusters::mojom::URLVisitPtr> visits) override;
 
  private:
-  // Forward the most relevant history cluster to the callback if any.
+  // Forward the most relevant history clusters to the callback if any.
   void CallbackWithClusterData(
-      GetClusterCallback callback,
+      GetClustersCallback callback,
       std::vector<history::Cluster> clusters,
       history_clusters::QueryClustersContinuationParams continuation_params);
 
diff --git a/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler_unittest.cc b/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler_unittest.cc
index f0827f4b..60c1b29 100644
--- a/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler_unittest.cc
+++ b/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler_unittest.cc
@@ -189,7 +189,8 @@
   return sample_visit;
 }
 
-history::Cluster SampleCluster(int srp_visits,
+history::Cluster SampleCluster(int id,
+                               int srp_visits,
                                int non_srp_visits,
                                const std::vector<std::string> related_searches =
                                    {"fruits", "red fruits", "healthy fruits"}) {
@@ -203,7 +204,7 @@
   visits.insert(visits.end(), non_srp_visits, sample_non_srp_visit);
 
   std::string kSampleLabel = "LabelOne";
-  return history::Cluster(1, std::move(visits),
+  return history::Cluster(id, std::move(visits),
                           {{u"apples", history::ClusterKeywordData()},
                            {u"Red Oranges", history::ClusterKeywordData()}},
                           /*should_show_on_prominent_ui_surfaces=*/true,
@@ -213,37 +214,55 @@
                               base::UTF8ToUTF16(kSampleLabel)));
 }
 
-TEST_F(HistoryClustersPageHandlerTest, GetCluster) {
+history::Cluster SampleCluster(int srp_visits,
+                               int non_srp_visits,
+                               const std::vector<std::string> related_searches =
+                                   {"fruits", "red fruits", "healthy fruits"}) {
+  return SampleCluster(1, srp_visits, non_srp_visits, related_searches);
+}
+
+TEST_F(HistoryClustersPageHandlerTest, GetClusters) {
   base::HistogramTester histogram_tester;
 
-  const history::Cluster kSampleCluster =
-      SampleCluster(/*srp_visits=*/1, /*non_srp_visits=*/2);
-  const std::vector<history::Cluster> kSampleClusters = {kSampleCluster};
-  test_history_clusters_service().SetClustersToReturn(kSampleClusters);
+  const int kSampleClusterCount = 3;
+  std::vector<history::Cluster> sample_clusters;
+  for (int i = 0; i < kSampleClusterCount; i++) {
+    sample_clusters.push_back(
+        SampleCluster(i, /*srp_visits=*/1, /*non_srp_visits=*/2));
+  }
+  test_history_clusters_service().SetClustersToReturn(sample_clusters);
 
-  history_clusters::mojom::ClusterPtr cluster_mojom;
-  base::MockCallback<HistoryClustersPageHandler::GetClusterCallback> callback;
+  std::vector<history_clusters::mojom::ClusterPtr> clusters_mojom;
+  base::MockCallback<HistoryClustersPageHandler::GetClustersCallback> callback;
   EXPECT_CALL(callback, Run(testing::_))
       .Times(1)
       .WillOnce(testing::Invoke(
-          [&cluster_mojom](history_clusters::mojom::ClusterPtr cluster_arg) {
-            cluster_mojom = std::move(cluster_arg);
+          [&clusters_mojom](
+              std::vector<history_clusters::mojom::ClusterPtr> clusters_arg) {
+            clusters_mojom = std::move(clusters_arg);
           }));
-  handler().GetCluster(callback.Get());
-  ASSERT_TRUE(cluster_mojom);
-  ASSERT_EQ(1u, cluster_mojom->id);
-  ASSERT_EQ(base::UTF16ToUTF8(kSampleCluster.label.value()),
-            cluster_mojom->label);
-  ASSERT_EQ(3u, cluster_mojom->visits.size());
-  ASSERT_EQ(base::UTF16ToUTF8(kSampleCluster.visits[0].url_for_display),
-            cluster_mojom->visits[0]->url_for_display);
+  handler().GetClusters(callback.Get());
+
+  ASSERT_EQ(3u, clusters_mojom.size());
+
+  for (unsigned int i = 0; i < kSampleClusterCount; i++) {
+    const auto& cluster_mojom = clusters_mojom[i];
+    ASSERT_TRUE(cluster_mojom);
+    ASSERT_EQ(i, cluster_mojom->id);
+    ASSERT_EQ(3u, cluster_mojom->visits.size());
+    for (size_t u = 1; u < cluster_mojom->visits.size(); u++) {
+      ASSERT_EQ(kSampleNonSearchUrl, cluster_mojom->visits[u]->url_for_display);
+    }
+  }
 
   histogram_tester.ExpectUniqueSample(
       "NewTabPage.HistoryClusters.IneligibleReason", 0, 1);
+
   histogram_tester.ExpectUniqueSample(
       "NewTabPage.HistoryClusters.HasClusterToShow", true, 1);
   histogram_tester.ExpectUniqueSample(
-      "NewTabPage.HistoryClusters.NumClusterCandidates", 1, 1);
+      "NewTabPage.HistoryClusters.NumClusterCandidates", 3, 1);
+
   histogram_tester.ExpectUniqueSample("NewTabPage.HistoryClusters.NumVisits", 3,
                                       1);
   histogram_tester.ExpectUniqueSample(
@@ -259,14 +278,15 @@
   test_history_clusters_service().SetClustersToReturn(kSampleClusters);
 
   history_clusters::mojom::ClusterPtr cluster_mojom;
-  base::MockCallback<HistoryClustersPageHandler::GetClusterCallback> callback;
+  base::MockCallback<HistoryClustersPageHandler::GetClustersCallback> callback;
   EXPECT_CALL(callback, Run(testing::_))
       .Times(1)
       .WillOnce(testing::Invoke(
-          [&cluster_mojom](history_clusters::mojom::ClusterPtr cluster_arg) {
-            cluster_mojom = std::move(cluster_arg);
+          [&cluster_mojom](
+              std::vector<history_clusters::mojom::ClusterPtr> clusters_arg) {
+            cluster_mojom = std::move(clusters_arg.front());
           }));
-  handler().GetCluster(callback.Get());
+  handler().GetClusters(callback.Get());
   ASSERT_TRUE(cluster_mojom);
   ASSERT_EQ(1u, cluster_mojom->id);
   ASSERT_EQ(base::UTF16ToUTF8(kSampleCluster.label.value()),
@@ -300,16 +320,17 @@
           IDS_HISTORY_CLUSTERS_CLUSTER_LABEL_SEARCH_TERMS, u"Red fruits"));
   test_history_clusters_service().SetClustersToReturn({kSampleCluster});
 
-  history_clusters::mojom::ClusterPtr cluster_mojom;
-  base::MockCallback<HistoryClustersPageHandler::GetClusterCallback> callback;
+  std::vector<history_clusters::mojom::ClusterPtr> clusters_mojom;
+  base::MockCallback<HistoryClustersPageHandler::GetClustersCallback> callback;
   EXPECT_CALL(callback, Run(testing::_))
       .Times(1)
       .WillOnce(testing::Invoke(
-          [&cluster_mojom](history_clusters::mojom::ClusterPtr cluster_arg) {
-            cluster_mojom = std::move(cluster_arg);
+          [&clusters_mojom](
+              std::vector<history_clusters::mojom::ClusterPtr> clusters_arg) {
+            clusters_mojom = std::move(clusters_arg);
           }));
-  handler().GetCluster(callback.Get());
-  ASSERT_FALSE(cluster_mojom);
+  handler().GetClusters(callback.Get());
+  ASSERT_EQ(0u, clusters_mojom.size());
 
   histogram_tester.ExpectUniqueSample(
       "NewTabPage.HistoryClusters.IneligibleReason", 2, 1);
@@ -326,16 +347,17 @@
       SampleCluster(/*srp_visits=*/0, /*non_srp_visits=*/3);
   test_history_clusters_service().SetClustersToReturn({kSampleCluster});
 
-  history_clusters::mojom::ClusterPtr cluster_mojom;
-  base::MockCallback<HistoryClustersPageHandler::GetClusterCallback> callback;
+  std::vector<history_clusters::mojom::ClusterPtr> clusters_mojom;
+  base::MockCallback<HistoryClustersPageHandler::GetClustersCallback> callback;
   EXPECT_CALL(callback, Run(testing::_))
       .Times(1)
       .WillOnce(testing::Invoke(
-          [&cluster_mojom](history_clusters::mojom::ClusterPtr cluster_arg) {
-            cluster_mojom = std::move(cluster_arg);
+          [&clusters_mojom](
+              std::vector<history_clusters::mojom::ClusterPtr> clusters_arg) {
+            clusters_mojom = std::move(clusters_arg);
           }));
-  handler().GetCluster(callback.Get());
-  ASSERT_FALSE(cluster_mojom);
+  handler().GetClusters(callback.Get());
+  ASSERT_EQ(0u, clusters_mojom.size());
 
   histogram_tester.ExpectUniqueSample(
       "NewTabPage.HistoryClusters.IneligibleReason", 3, 1);
@@ -352,16 +374,17 @@
       SampleCluster(/*srp_visits=*/1, /*non_srp_visits=*/1);
   test_history_clusters_service().SetClustersToReturn({kSampleCluster});
 
-  history_clusters::mojom::ClusterPtr cluster_mojom;
-  base::MockCallback<HistoryClustersPageHandler::GetClusterCallback> callback;
+  std::vector<history_clusters::mojom::ClusterPtr> clusters_mojom;
+  base::MockCallback<HistoryClustersPageHandler::GetClustersCallback> callback;
   EXPECT_CALL(callback, Run(testing::_))
       .Times(1)
       .WillOnce(testing::Invoke(
-          [&cluster_mojom](history_clusters::mojom::ClusterPtr cluster_arg) {
-            cluster_mojom = std::move(cluster_arg);
+          [&clusters_mojom](
+              std::vector<history_clusters::mojom::ClusterPtr> clusters_arg) {
+            clusters_mojom = std::move(clusters_arg);
           }));
-  handler().GetCluster(callback.Get());
-  ASSERT_FALSE(cluster_mojom);
+  handler().GetClusters(callback.Get());
+  ASSERT_EQ(0u, clusters_mojom.size());
 
   histogram_tester.ExpectUniqueSample(
       "NewTabPage.HistoryClusters.IneligibleReason", 4, 1);
@@ -389,16 +412,17 @@
           IDS_HISTORY_CLUSTERS_CLUSTER_LABEL_SEARCH_TERMS, u"Red fruits"));
   test_history_clusters_service().SetClustersToReturn({kSampleCluster});
 
-  history_clusters::mojom::ClusterPtr cluster_mojom;
-  base::MockCallback<HistoryClustersPageHandler::GetClusterCallback> callback;
+  std::vector<history_clusters::mojom::ClusterPtr> clusters_mojom;
+  base::MockCallback<HistoryClustersPageHandler::GetClustersCallback> callback;
   EXPECT_CALL(callback, Run(testing::_))
       .Times(1)
       .WillOnce(testing::Invoke(
-          [&cluster_mojom](history_clusters::mojom::ClusterPtr cluster_arg) {
-            cluster_mojom = std::move(cluster_arg);
+          [&clusters_mojom](
+              std::vector<history_clusters::mojom::ClusterPtr> clusters_arg) {
+            clusters_mojom = std::move(clusters_arg);
           }));
-  handler().GetCluster(callback.Get());
-  ASSERT_FALSE(cluster_mojom);
+  handler().GetClusters(callback.Get());
+  ASSERT_EQ(0u, clusters_mojom.size());
 
   histogram_tester.ExpectUniqueSample(
       "NewTabPage.HistoryClusters.IneligibleReason", 5, 1);
@@ -413,19 +437,21 @@
   base::HistogramTester histogram_tester;
 
   const history::Cluster kSampleCluster = SampleCluster(
-      /*srp_visits=*/1, /*non_srp_visits=*/2, /*related_searches=*/{});
+      /*id=*/1, /*srp_visits=*/1, /*non_srp_visits=*/2,
+      /*related_searches=*/{});
   test_history_clusters_service().SetClustersToReturn({kSampleCluster});
 
-  history_clusters::mojom::ClusterPtr cluster_mojom;
-  base::MockCallback<HistoryClustersPageHandler::GetClusterCallback> callback;
+  std::vector<history_clusters::mojom::ClusterPtr> clusters_mojom;
+  base::MockCallback<HistoryClustersPageHandler::GetClustersCallback> callback;
   EXPECT_CALL(callback, Run(testing::_))
       .Times(1)
       .WillOnce(testing::Invoke(
-          [&cluster_mojom](history_clusters::mojom::ClusterPtr cluster_arg) {
-            cluster_mojom = std::move(cluster_arg);
+          [&clusters_mojom](
+              std::vector<history_clusters::mojom::ClusterPtr> clusters_arg) {
+            clusters_mojom = std::move(clusters_arg);
           }));
-  handler().GetCluster(callback.Get());
-  ASSERT_FALSE(cluster_mojom);
+  handler().GetClusters(callback.Get());
+  ASSERT_EQ(0u, clusters_mojom.size());
 
   histogram_tester.ExpectUniqueSample(
       "NewTabPage.HistoryClusters.IneligibleReason", 6, 1);
@@ -449,58 +475,21 @@
 
   test_history_clusters_service().SetClustersToReturn({});
   history_clusters::mojom::ClusterPtr cluster_mojom;
-  base::MockCallback<HistoryClustersPageHandler::GetClusterCallback> callback;
+  base::MockCallback<HistoryClustersPageHandler::GetClustersCallback> callback;
   EXPECT_CALL(callback, Run(testing::_))
       .Times(1)
       .WillOnce(testing::Invoke(
-          [&cluster_mojom](history_clusters::mojom::ClusterPtr cluster_arg) {
-            cluster_mojom = std::move(cluster_arg);
+          [&cluster_mojom](
+              std::vector<history_clusters::mojom::ClusterPtr> clusters_arg) {
+            cluster_mojom = std::move(clusters_arg.front());
           }));
-  handler().GetCluster(callback.Get());
+  handler().GetClusters(callback.Get());
   ASSERT_TRUE(cluster_mojom);
   ASSERT_EQ(0u, cluster_mojom->id);
   // The cluster visits should include an additional entry for the SRP visit.
   ASSERT_EQ(kNumVisits + 1, cluster_mojom->visits.size());
 }
 
-TEST_F(HistoryClustersPageHandlerTest, MultipleClusters) {
-  base::HistogramTester histogram_tester;
-
-  const history::Cluster kSampleCluster =
-      SampleCluster(/*srp_visits=*/1, /*non_srp_visits=*/2);
-  const std::vector<history::Cluster> kSampleClusters = {kSampleCluster,
-                                                         kSampleCluster};
-  test_history_clusters_service().SetClustersToReturn(kSampleClusters);
-
-  history_clusters::mojom::ClusterPtr cluster_mojom;
-  base::MockCallback<HistoryClustersPageHandler::GetClusterCallback> callback;
-  EXPECT_CALL(callback, Run(testing::_))
-      .Times(1)
-      .WillOnce(testing::Invoke(
-          [&cluster_mojom](history_clusters::mojom::ClusterPtr cluster_arg) {
-            cluster_mojom = std::move(cluster_arg);
-          }));
-  handler().GetCluster(callback.Get());
-  ASSERT_TRUE(cluster_mojom);
-  ASSERT_EQ(1u, cluster_mojom->id);
-  ASSERT_EQ(base::UTF16ToUTF8(kSampleCluster.label.value()),
-            cluster_mojom->label);
-  ASSERT_EQ(3u, cluster_mojom->visits.size());
-  ASSERT_EQ(base::UTF16ToUTF8(kSampleCluster.visits[0].url_for_display),
-            cluster_mojom->visits[0]->url_for_display);
-
-  histogram_tester.ExpectUniqueSample(
-      "NewTabPage.HistoryClusters.IneligibleReason", 0, 1);
-  histogram_tester.ExpectUniqueSample(
-      "NewTabPage.HistoryClusters.HasClusterToShow", true, 1);
-  histogram_tester.ExpectUniqueSample(
-      "NewTabPage.HistoryClusters.NumClusterCandidates", 2, 1);
-  histogram_tester.ExpectUniqueSample("NewTabPage.HistoryClusters.NumVisits", 3,
-                                      1);
-  histogram_tester.ExpectUniqueSample(
-      "NewTabPage.HistoryClusters.NumRelatedSearches", 3, 1);
-}
-
 TEST_F(HistoryClustersPageHandlerTest,
        NoClusterReturnedForInvalidModuleDataParam) {
   base::test::ScopedFeatureList features;
@@ -514,32 +503,34 @@
   const history::Cluster kSampleCluster =
       SampleCluster(/*srp_visits=*/1, /*non_srp_visits=*/2);
   test_history_clusters_service().SetClustersToReturn({kSampleCluster});
-  history_clusters::mojom::ClusterPtr cluster_mojom;
-  base::MockCallback<HistoryClustersPageHandler::GetClusterCallback> callback;
+
+  std::vector<history_clusters::mojom::ClusterPtr> clusters_mojom;
+  base::MockCallback<HistoryClustersPageHandler::GetClustersCallback> callback;
   EXPECT_CALL(callback, Run(testing::_))
       .Times(1)
       .WillOnce(testing::Invoke(
-          [&cluster_mojom](history_clusters::mojom::ClusterPtr cluster_arg) {
-            cluster_mojom = std::move(cluster_arg);
+          [&clusters_mojom](
+              std::vector<history_clusters::mojom::ClusterPtr> clusters_arg) {
+            clusters_mojom = std::move(clusters_arg);
           }));
-  handler().GetCluster(callback.Get());
-  ASSERT_FALSE(cluster_mojom);
+  handler().GetClusters(callback.Get());
+  ASSERT_EQ(0u, clusters_mojom.size());
 }
 
 TEST_F(HistoryClustersPageHandlerTest, NoClusters) {
   base::HistogramTester histogram_tester;
 
-  history_clusters::mojom::ClusterPtr cluster_mojom;
-  base::MockCallback<HistoryClustersPageHandler::GetClusterCallback> callback;
+  std::vector<history_clusters::mojom::ClusterPtr> clusters_mojom;
+  base::MockCallback<HistoryClustersPageHandler::GetClustersCallback> callback;
   EXPECT_CALL(callback, Run(testing::_))
       .Times(1)
       .WillOnce(testing::Invoke(
-          [&cluster_mojom](history_clusters::mojom::ClusterPtr cluster_arg) {
-            cluster_mojom = std::move(cluster_arg);
+          [&clusters_mojom](
+              std::vector<history_clusters::mojom::ClusterPtr> clusters_arg) {
+            clusters_mojom = std::move(clusters_arg);
           }));
-  handler().GetCluster(callback.Get());
-  // Callback should be invoked with a nullptr.
-  ASSERT_FALSE(cluster_mojom);
+  handler().GetClusters(callback.Get());
+  ASSERT_EQ(0u, clusters_mojom.size());
 
   histogram_tester.ExpectUniqueSample(
       "NewTabPage.HistoryClusters.IneligibleReason", 1, 1);
@@ -645,7 +636,7 @@
             urls.push_back(url);
             callbacks.push_back(std::move(callback));
           })));
-  handler().GetCluster(base::DoNothing());
+  handler().GetClusters(base::DoNothing());
   // Simulate one URL being identified as having a cart.
   std::move(callbacks[0]).Run(true);
   for (size_t i = 1; i < callbacks.size(); i++) {
@@ -668,7 +659,7 @@
             urls.push_back(url);
             callbacks.push_back(std::move(callback));
           })));
-  handler().GetCluster(base::DoNothing());
+  handler().GetClusters(base::DoNothing());
   // Simulate none URL being identified as having a cart.
   for (size_t i = 0; i < callbacks.size(); i++) {
     std::move(callbacks[i]).Run(false);
diff --git a/chrome/browser/policy/policy_value_and_status_aggregator.cc b/chrome/browser/policy/policy_value_and_status_aggregator.cc
index 93ebf61..11f5f13 100644
--- a/chrome/browser/policy/policy_value_and_status_aggregator.cc
+++ b/chrome/browser/policy/policy_value_and_status_aggregator.cc
@@ -42,6 +42,7 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
+#include "chrome/browser/policy/management_utils.h"
 #include "chrome/browser/policy/status_provider/ash_lacros_policy_stack_bridge.h"
 #include "chrome/browser/policy/status_provider/user_policy_status_provider_lacros.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
@@ -200,8 +201,10 @@
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   // We will use AshLacrosPolicyStackBridge to retrieve device policies in
   // Lacros.
-  aggregator->AddPolicyStatusAndValueProvider(
-      kDeviceStatusKey, std::make_unique<AshLacrosPolicyStackBridge>());
+  if (policy::IsDeviceEnterpriseManaged()) {
+    aggregator->AddPolicyStatusAndValueProvider(
+        kDeviceStatusKey, std::make_unique<AshLacrosPolicyStackBridge>());
+  }
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
 
   // Machine policies.
diff --git a/chrome/browser/recent_tabs/BUILD.gn b/chrome/browser/recent_tabs/BUILD.gn
index 68d349c4..1fe9ce78 100644
--- a/chrome/browser/recent_tabs/BUILD.gn
+++ b/chrome/browser/recent_tabs/BUILD.gn
@@ -16,6 +16,7 @@
     "//base:jni_java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/tab:java",
+    "//chrome/browser/tabmodel:java",
     "//content/public/android:content_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//url:gurl_java",
@@ -31,6 +32,7 @@
     ":java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/recent_tabs/internal:java",
+    "//chrome/browser/tabmodel:java",
   ]
 }
 
diff --git a/chrome/browser/recent_tabs/android/java/src/org/chromium/chrome/browser/recent_tabs/ForeignSessionHelper.java b/chrome/browser/recent_tabs/android/java/src/org/chromium/chrome/browser/recent_tabs/ForeignSessionHelper.java
index 27f2707..98e7e7e 100644
--- a/chrome/browser/recent_tabs/android/java/src/org/chromium/chrome/browser/recent_tabs/ForeignSessionHelper.java
+++ b/chrome/browser/recent_tabs/android/java/src/org/chromium/chrome/browser/recent_tabs/ForeignSessionHelper.java
@@ -6,10 +6,15 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import org.chromium.base.CollectionUtil;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabLaunchType;
+import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
+import org.chromium.content_public.browser.LoadUrlParams;
+import org.chromium.content_public.common.ContentUrlConstants;
 import org.chromium.url.GURL;
 
 import java.util.ArrayList;
@@ -181,6 +186,24 @@
     }
 
     /**
+     * @return The list of synced foreign sessions that are from a mobile or tablet device. If it
+     * fails to get them for some reason will return an empty list.
+     */
+    public List<ForeignSession> getMobileAndTabletForeignSessions() {
+        if (!isTabSyncEnabled()) {
+            return Collections.emptyList();
+        }
+        List<ForeignSession> result = new ArrayList<ForeignSession>();
+        boolean received = ForeignSessionHelperJni.get().getMobileAndTabletForeignSessions(
+                mNativeForeignSessionHelper, result);
+        if (!received) {
+            result = Collections.emptyList();
+        }
+
+        return result;
+    }
+
+    /**
      * Opens the given foreign tab in a new tab.
      * @param tab Tab to load the session into.
      * @param session Session that the target tab belongs to.
@@ -214,6 +237,32 @@
                 mNativeForeignSessionHelper, enabled);
     }
 
+    /**
+     * Lazily instantiate a list of tabs as background tabs.
+     * @param sessionTabs List of target tabs to open.
+     * @param session Foreign session that holds the list of target tabs to open.
+     * @param tabCreatorManager Tab creator manager to create a new foreground tab for tab restore.
+     * @return The number of tabs that were successfully restored.
+     */
+    public int openForeignSessionTabsAsBackgroundTabs(List<ForeignSessionTab> sessionTabs,
+            ForeignSession session, TabCreatorManager tabCreatorManager) {
+        List<Integer> tabIds = new ArrayList<>();
+        Tab newForegroundTab = tabCreatorManager.getTabCreator(false).createNewTab(
+                new LoadUrlParams(ContentUrlConstants.ABOUT_BLANK_URL),
+                TabLaunchType.FROM_RESTORE_TABS_UI, null);
+
+        for (ForeignSessionTab tab : sessionTabs) {
+            tabIds.add(tab.id);
+        }
+        if (tabIds.size() == 0) {
+            return 0;
+        }
+
+        return ForeignSessionHelperJni.get().openForeignSessionTabsAsBackgroundTabs(
+                mNativeForeignSessionHelper, newForegroundTab,
+                CollectionUtil.integerListToIntArray(tabIds), session.tag);
+    }
+
     @NativeMethods
     interface Natives {
         long init(Profile profile);
@@ -224,9 +273,13 @@
                 long nativeForeignSessionHelper, ForeignSessionCallback callback);
         boolean getForeignSessions(
                 long nativeForeignSessionHelper, List<ForeignSession> resultSessions);
+        boolean getMobileAndTabletForeignSessions(
+                long nativeForeignSessionHelper, List<ForeignSession> resultSessions);
         boolean openForeignSessionTab(long nativeForeignSessionHelper, Tab tab, String sessionTag,
                 int tabId, int disposition);
         void deleteForeignSession(long nativeForeignSessionHelper, String sessionTag);
         void setInvalidationsForSessionsEnabled(long nativeForeignSessionHelper, boolean enabled);
+        int openForeignSessionTabsAsBackgroundTabs(
+                long nativeForeignSessionHelper, Tab tab, int[] tabIds, String sessionTag);
     }
 }
diff --git a/chrome/browser/recent_tabs/internal/BUILD.gn b/chrome/browser/recent_tabs/internal/BUILD.gn
index b97e820c..b08e41d 100644
--- a/chrome/browser/recent_tabs/internal/BUILD.gn
+++ b/chrome/browser/recent_tabs/internal/BUILD.gn
@@ -30,6 +30,7 @@
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/recent_tabs:java",
     "//chrome/browser/tab:java",
+    "//chrome/browser/tabmodel:java",
     "//components/feature_engagement/public:public_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//ui/android:ui_java",
@@ -57,6 +58,7 @@
     "//chrome/browser/feature_engagement:java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/recent_tabs:java",
+    "//chrome/browser/tabmodel:java",
     "//components/feature_engagement/public:public_java",
     "//third_party/androidx:androidx_test_runner_java",
     "//third_party/hamcrest:hamcrest_library_java",
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerFactory.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerFactory.java
index 9b996ef..7909739 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerFactory.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerFactory.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.recent_tabs;
 
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 
 /**
  * A factory interface for building a RestoreTabsController instance.
@@ -23,8 +24,9 @@
     /**
      * @return An instance of RestoreTabsControllerImpl.
      */
-    public static RestoreTabsControllerImpl createInstance(
-            Profile profile, RestoreTabsControllerFactory.ControllerListener listener) {
-        return new RestoreTabsControllerImpl(profile, listener);
+    public static RestoreTabsControllerImpl createInstance(Profile profile,
+            RestoreTabsControllerFactory.ControllerListener listener,
+            TabCreatorManager tabCreatorManager) {
+        return new RestoreTabsControllerImpl(profile, listener, tabCreatorManager);
     }
 }
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerImpl.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerImpl.java
index c760c77..d50d9776 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerImpl.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerImpl.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.recent_tabs;
 
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 
 /**
  * Controller for accessing helper functions for the singleton factory instance.
@@ -13,10 +14,11 @@
     private RestoreTabsFeatureHelper mHelper;
     private RestoreTabsCoordinator mRestoreTabsCoordinator;
 
-    public RestoreTabsControllerImpl(
-            Profile profile, RestoreTabsControllerFactory.ControllerListener listener) {
+    public RestoreTabsControllerImpl(Profile profile,
+            RestoreTabsControllerFactory.ControllerListener listener,
+            TabCreatorManager tabCreatorManager) {
         mHelper = new RestoreTabsFeatureHelperImpl();
-        mRestoreTabsCoordinator = new RestoreTabsCoordinator(profile, listener);
+        mRestoreTabsCoordinator = new RestoreTabsCoordinator(profile, listener, tabCreatorManager);
     }
 
     public void destroy() {
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinator.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinator.java
index 85b0452..f541a14b 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinator.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinator.java
@@ -5,36 +5,35 @@
 package org.chromium.chrome.browser.recent_tabs;
 
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 import org.chromium.ui.modelutil.PropertyModel;
 
 /**
  * Coordinator to manage the Restore Tabs on FRE feature.
  */
 public class RestoreTabsCoordinator {
-    private ForeignSessionHelper mForeignSessionHelper;
     private RestoreTabsMediator mMediator;
     private PropertyModel mModel = RestoreTabsProperties.createDefaultModel();
 
-    public RestoreTabsCoordinator(
-            Profile profile, RestoreTabsControllerFactory.ControllerListener listener) {
-        this(new ForeignSessionHelper(profile), new RestoreTabsMediator(), listener);
+    public RestoreTabsCoordinator(Profile profile,
+            RestoreTabsControllerFactory.ControllerListener listener,
+            TabCreatorManager tabCreatorManager) {
+        this(profile, new RestoreTabsMediator(), listener, tabCreatorManager);
     }
 
-    protected RestoreTabsCoordinator(ForeignSessionHelper helper, RestoreTabsMediator mediator,
-            RestoreTabsControllerFactory.ControllerListener listener) {
-        mForeignSessionHelper = helper;
+    protected RestoreTabsCoordinator(Profile profile, RestoreTabsMediator mediator,
+            RestoreTabsControllerFactory.ControllerListener listener,
+            TabCreatorManager tabCreatorManager) {
         mMediator = mediator;
-        mMediator.initialize(mModel, listener);
+        mMediator.initialize(mModel, listener, profile, tabCreatorManager);
     }
 
     public void destroy() {
-        mForeignSessionHelper.destroy();
-        mForeignSessionHelper = null;
         mMediator.destroy();
         mMediator = null;
     }
 
     public void showOptions() {
-        mMediator.showOptions(mForeignSessionHelper.getForeignSessions());
+        mMediator.showOptions();
     }
 }
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinatorUnitTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinatorUnitTest.java
index e0f7b4b..fe5777e 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinatorUnitTest.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinatorUnitTest.java
@@ -6,7 +6,6 @@
 
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -16,10 +15,8 @@
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.chrome.browser.recent_tabs.ForeignSessionHelper.ForeignSession;
-
-import java.util.ArrayList;
-import java.util.List;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 
 /**
  * Unit tests for RestoreTabsCoordinator.
@@ -30,31 +27,24 @@
     @Mock
     private RestoreTabsMediator mMediator;
     @Mock
-    private ForeignSessionHelper mForeignSessionHelper;
+    private Profile mProfile;
+    @Mock
+    private RestoreTabsControllerFactory.ControllerListener mListener;
+    @Mock
+    private TabCreatorManager mTabCreatorManager;
 
     private RestoreTabsCoordinator mCoordinator;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mCoordinator = new RestoreTabsCoordinator(mForeignSessionHelper, mMediator,
-                new RestoreTabsControllerFactory.ControllerListener() {
-                    @Override
-                    public void onDismissed() {
-                        mCoordinator.destroy();
-                    }
-                });
+        mCoordinator =
+                new RestoreTabsCoordinator(mProfile, mMediator, mListener, mTabCreatorManager);
     }
 
     @Test
     public void testRestoreTabsCoordinator_showOptions() {
-        ForeignSession session =
-                new ForeignSession("tag", "John's iPhone 6", 32L, new ArrayList<>());
-        List<ForeignSession> testSessions = new ArrayList<>();
-        testSessions.add(session);
-
-        when(mForeignSessionHelper.getForeignSessions()).thenReturn(testSessions);
         mCoordinator.showOptions();
-        verify(mMediator, times(1)).showOptions(testSessions);
+        verify(mMediator, times(1)).showOptions();
     }
 }
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsFeatureHelperUnitTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsFeatureHelperUnitTest.java
index 3d73f413..0905068 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsFeatureHelperUnitTest.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsFeatureHelperUnitTest.java
@@ -22,6 +22,7 @@
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 import org.chromium.components.feature_engagement.EventConstants;
 import org.chromium.components.feature_engagement.Tracker;
 
@@ -45,6 +46,8 @@
     private Tracker mTracker;
     @Mock
     private RestoreTabsControllerFactory.ControllerListener mListener;
+    @Mock
+    private TabCreatorManager mTabCreatorManager;
 
     @Before
     public void setUp() {
@@ -53,7 +56,8 @@
         TrackerFactory.setTrackerForTests(mTracker);
         jniMocker.mock(ForeignSessionHelperJni.TEST_HOOKS, mForeignSessionHelperJniMock);
 
-        mController = RestoreTabsControllerFactory.createInstance(mProfile, mListener);
+        mController = RestoreTabsControllerFactory.createInstance(
+                mProfile, mListener, mTabCreatorManager);
         mHelper = mController.getFeatureHelper();
     }
 
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediator.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediator.java
index f111911..ac4f261 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediator.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediator.java
@@ -6,6 +6,7 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.recent_tabs.ForeignSessionHelper.ForeignSession;
 import org.chromium.chrome.browser.recent_tabs.ForeignSessionHelper.ForeignSessionTab;
 import org.chromium.chrome.browser.recent_tabs.ForeignSessionHelper.ForeignSessionWindow;
@@ -14,6 +15,7 @@
 import org.chromium.chrome.browser.recent_tabs.ui.RestoreTabsDetailScreenCoordinator;
 import org.chromium.chrome.browser.recent_tabs.ui.RestoreTabsPromoScreenCoordinator;
 import org.chromium.chrome.browser.recent_tabs.ui.TabItemProperties;
+import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
 import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -27,10 +29,21 @@
 public class RestoreTabsMediator {
     private RestoreTabsControllerFactory.ControllerListener mListener;
     private PropertyModel mModel;
+    private ForeignSessionHelper mForeignSessionHelper;
+    private TabCreatorManager mTabCreatorManager;
 
-    public void initialize(
-            PropertyModel model, RestoreTabsControllerFactory.ControllerListener listener) {
+    public void initialize(PropertyModel model,
+            RestoreTabsControllerFactory.ControllerListener listener, Profile profile,
+            TabCreatorManager tabCreatorManager) {
+        initialize(model, listener, new ForeignSessionHelper(profile), tabCreatorManager);
+    }
+
+    protected void initialize(PropertyModel model,
+            RestoreTabsControllerFactory.ControllerListener listener,
+            ForeignSessionHelper foreignSessionHelper, TabCreatorManager tabCreatorManager) {
         mListener = listener;
+        mForeignSessionHelper = foreignSessionHelper;
+        mTabCreatorManager = tabCreatorManager;
         mModel = model;
         mModel.set(RestoreTabsProperties.HOME_SCREEN_DELEGATE, createHomeScreenDelegate());
         mModel.set(RestoreTabsProperties.DETAIL_SCREEN_BACK_CLICK_HANDLER,
@@ -38,6 +51,8 @@
     }
 
     public void destroy() {
+        mForeignSessionHelper.destroy();
+        mForeignSessionHelper = null;
         mModel.set(RestoreTabsProperties.VISIBLE, false);
     }
 
@@ -51,7 +66,7 @@
 
             @Override
             public void onAllTabsChosen() {
-                mModel.set(RestoreTabsProperties.VISIBLE, false);
+                restoreChosenTabs();
             };
 
             @Override
@@ -61,8 +76,8 @@
         };
     }
 
-    public void showOptions(List<ForeignSession> sessions) {
-        setDeviceListItems(sessions);
+    public void showOptions() {
+        setDeviceListItems(mForeignSessionHelper.getMobileAndTabletForeignSessions());
         setTabListItems();
         setCurrentScreen(mModel.get(RestoreTabsProperties.CURRENT_SCREEN));
         mModel.set(RestoreTabsProperties.VISIBLE, true);
@@ -126,6 +141,9 @@
                     item.model.get(ForeignSessionItemProperties.SESSION_PROFILE));
             item.model.set(ForeignSessionItemProperties.IS_SELECTED, isSelected);
         }
+
+        // After selecting a device, rebuild all the tab list items for the new selection.
+        setTabListItems();
     }
 
     /**
@@ -229,8 +247,29 @@
 
             @Override
             public void onSelectedTabsChosen() {
-                mModel.set(RestoreTabsProperties.VISIBLE, false);
+                restoreChosenTabs();
             };
         };
     }
+
+    private void restoreChosenTabs() {
+        if (!mModel.get(RestoreTabsProperties.VISIBLE)) {
+            return; // Dismiss only if not dismissed yet.
+        }
+
+        List<ForeignSessionTab> tabs = new ArrayList<>();
+        ModelList selectedTabs = mModel.get(RestoreTabsProperties.REVIEW_TABS_MODEL_LIST);
+        for (ListItem item : selectedTabs) {
+            if (item.model.get(TabItemProperties.IS_SELECTED)) {
+                tabs.add(item.model.get(TabItemProperties.FOREIGN_SESSION_TAB));
+            }
+        }
+
+        // TODO(crbug.com/1426921): Consider adding a safeguard for not allowing restoration
+        // below 1, and adding a spinner if restoring the tabs becomes a batched process.
+        assert selectedTabs.size() > 0;
+        mForeignSessionHelper.openForeignSessionTabsAsBackgroundTabs(
+                tabs, mModel.get(RestoreTabsProperties.SELECTED_DEVICE), mTabCreatorManager);
+        dismiss();
+    }
 }
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediatorUnitTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediatorUnitTest.java
index 951053e..48d9c23 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediatorUnitTest.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediatorUnitTest.java
@@ -5,6 +5,8 @@
 package org.chromium.chrome.browser.recent_tabs;
 
 import static org.hamcrest.Matchers.instanceOf;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import static org.chromium.chrome.browser.recent_tabs.RestoreTabsProperties.CURRENT_SCREEN;
 import static org.chromium.chrome.browser.recent_tabs.RestoreTabsProperties.DETAIL_SCREEN_BACK_CLICK_HANDLER;
@@ -25,6 +27,8 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -35,6 +39,7 @@
 import org.chromium.chrome.browser.recent_tabs.ui.RestoreTabsDetailScreenCoordinator;
 import org.chromium.chrome.browser.recent_tabs.ui.RestoreTabsPromoScreenCoordinator;
 import org.chromium.chrome.browser.recent_tabs.ui.TabItemProperties;
+import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
 import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -47,21 +52,25 @@
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public class RestoreTabsMediatorUnitTest {
+    @Mock
+    private RestoreTabsControllerFactory.ControllerListener mListener;
+    @Mock
+    private ForeignSessionHelper mForeignSessionHelper;
+    @Mock
+    private TabCreatorManager mTabCreatorManager;
+
     private PropertyModel mModel = RestoreTabsProperties.createDefaultModel();
     private RestoreTabsMediator mMediator = new RestoreTabsMediator();
 
     @Before
     public void setUp() {
-        mMediator.initialize(mModel, new RestoreTabsControllerFactory.ControllerListener() {
-            @Override
-            public void onDismissed() {
-                mMediator.destroy();
-            }
-        });
+        MockitoAnnotations.initMocks(this);
+        mMediator.initialize(mModel, mListener, mForeignSessionHelper, mTabCreatorManager);
     }
 
     @After
     public void tearDown() {
+        mMediator.destroy();
         mModel = null;
     }
 
@@ -83,7 +92,8 @@
         List<ForeignSession> testSessions = new ArrayList<>();
         testSessions.add(session);
 
-        mMediator.showOptions(testSessions);
+        when(mForeignSessionHelper.getMobileAndTabletForeignSessions()).thenReturn(testSessions);
+        mMediator.showOptions();
         Assert.assertEquals(mModel.get(VISIBLE), true);
         mMediator.dismiss();
         Assert.assertEquals(mModel.get(VISIBLE), false);
@@ -96,8 +106,8 @@
         List<ForeignSession> testSessions = new ArrayList<>();
         testSessions.add(session);
 
-        mMediator.showOptions(testSessions);
-
+        when(mForeignSessionHelper.getMobileAndTabletForeignSessions()).thenReturn(testSessions);
+        mMediator.showOptions();
         Assert.assertEquals(mModel.get(VISIBLE), true);
         Assert.assertEquals(mModel.get(CURRENT_SCREEN), HOME_SCREEN);
         Assert.assertEquals(mModel.get(SELECTED_DEVICE), testSessions.get(0));
@@ -111,16 +121,43 @@
         delegate.onShowDeviceList();
         Assert.assertEquals(mModel.get(CURRENT_SCREEN), DEVICE_SCREEN);
 
-        // Testing the onAllTabsChosen member function.
-        delegate.onAllTabsChosen();
-        Assert.assertEquals(mModel.get(VISIBLE), false);
-
         // Testing the onReviewTabsChosen member function.
         delegate.onReviewTabsChosen();
         Assert.assertEquals(mModel.get(CURRENT_SCREEN), REVIEW_TABS_SCREEN);
     }
 
     @Test
+    public void testRestoreTabsMediator_createHomeScreenDelegateOnAllTabsChosen() {
+        RestoreTabsPromoScreenCoordinator.Delegate delegate = mModel.get(HOME_SCREEN_DELEGATE);
+        mModel.set(VISIBLE, true);
+
+        ForeignSessionTab tab1 = new ForeignSessionTab(
+                JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_1), "title", 32L, 0);
+        ModelList tabItems = mModel.get(REVIEW_TABS_MODEL_LIST);
+        PropertyModel model1 = TabItemProperties.create(/*tab=*/tab1, /*isSelected=*/true);
+        tabItems.add(new ListItem(DetailItemType.TAB, model1));
+        ForeignSessionTab tab2 = new ForeignSessionTab(
+                JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_1), "title", 32L, 0);
+        PropertyModel model2 = TabItemProperties.create(/*tab=*/tab2, /*isSelected=*/true);
+        tabItems.add(new ListItem(DetailItemType.TAB, model2));
+
+        // Only add the selected tab
+        List<ForeignSessionTab> tabs = new ArrayList<>();
+        tabs.add(tab1);
+        tabs.add(tab2);
+
+        ForeignSession session =
+                new ForeignSession("tag", "John's iPhone 6", 32L, new ArrayList<>());
+        mModel.set(SELECTED_DEVICE, session);
+
+        delegate.onAllTabsChosen();
+        verify(mForeignSessionHelper)
+                .openForeignSessionTabsAsBackgroundTabs(
+                        tabs, mModel.get(SELECTED_DEVICE), mTabCreatorManager);
+        Assert.assertEquals(mModel.get(VISIBLE), false);
+    }
+
+    @Test
     public void testRestoreTabsMediator_setDeviceListItemsNoSelection() {
         ForeignSession session1 =
                 new ForeignSession("tag1", "John's iPhone 6", 32L, new ArrayList<>());
@@ -162,6 +199,39 @@
     }
 
     @Test
+    public void testRestoreTabsMediator_setSelectedDeviceItemResetsTabList() {
+        ForeignSessionTab tab1 = new ForeignSessionTab(
+                JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_1), "title", 32L, 0);
+        PropertyModel model1 = TabItemProperties.create(tab1, false);
+
+        ModelList tabItems = mModel.get(REVIEW_TABS_MODEL_LIST);
+        tabItems.add(new ListItem(DetailItemType.TAB, model1));
+
+        Assert.assertEquals(tabItems.size(), 1);
+
+        // Add two new tabs to check they are not the same as the one above.
+        ForeignSessionTab tab2 = new ForeignSessionTab(
+                JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_1), "title2", 32L, 0);
+        ForeignSessionTab tab3 = new ForeignSessionTab(
+                JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_1), "title3", 32L, 0);
+        List<ForeignSessionTab> tabs = new ArrayList<>();
+        tabs.add(tab2);
+        tabs.add(tab3);
+
+        ForeignSessionWindow window = new ForeignSessionWindow(31L, 1, tabs);
+        List<ForeignSessionWindow> windows = new ArrayList<>();
+        windows.add(window);
+
+        ForeignSession session = new ForeignSession("tag", "John's iPhone 6", 32L, windows);
+        mMediator.setSelectedDeviceItem(session);
+
+        Assert.assertEquals(mModel.get(SELECTED_DEVICE), session);
+        Assert.assertEquals(tabItems.size(), 2);
+        Assert.assertEquals(tabItems.get(0).model.get(TabItemProperties.FOREIGN_SESSION_TAB), tab2);
+        Assert.assertEquals(tabItems.get(1).model.get(TabItemProperties.FOREIGN_SESSION_TAB), tab3);
+    }
+
+    @Test
     public void testRestoreTabsMediator_setCurrentScreenDevices() {
         mMediator.setCurrentScreen(DEVICE_SCREEN);
 
@@ -250,9 +320,33 @@
         tabItems.add(new ListItem(DetailItemType.TAB, model));
         delegate.onChangeSelectionStateForAllTabs();
         Assert.assertEquals(mModel.get(NUM_TABS_DESELECTED), tabItems.size());
+    }
 
-        // Testing the onSelectedTabsChosen member function.
+    @Test
+    public void testRestoreTabsMediator_createReviewTabsScreenDelegateOnSelectedTabsChosen() {
+        mModel.set(VISIBLE, true);
+        mMediator.setCurrentScreen(REVIEW_TABS_SCREEN);
+        RestoreTabsDetailScreenCoordinator.Delegate delegate =
+                mModel.get(REVIEW_TABS_SCREEN_DELEGATE);
+
+        ModelList tabItems = mModel.get(REVIEW_TABS_MODEL_LIST);
+        ForeignSessionTab tab1 = new ForeignSessionTab(
+                JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_1), "title", 32L, 0);
+        PropertyModel model1 = TabItemProperties.create(/*tab=*/tab1, /*isSelected=*/true);
+        tabItems.add(new ListItem(DetailItemType.TAB, model1));
+        ForeignSessionTab tab2 = new ForeignSessionTab(
+                JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_1), "title", 32L, 0);
+        PropertyModel model2 = TabItemProperties.create(/*tab=*/tab2, /*isSelected=*/false);
+        tabItems.add(new ListItem(DetailItemType.TAB, model2));
+
+        // Only add the selected tab
+        List<ForeignSessionTab> tabs = new ArrayList<>();
+        tabs.add(tab1);
+
         delegate.onSelectedTabsChosen();
+        verify(mForeignSessionHelper)
+                .openForeignSessionTabsAsBackgroundTabs(
+                        tabs, mModel.get(SELECTED_DEVICE), mTabCreatorManager);
         Assert.assertEquals(mModel.get(VISIBLE), false);
     }
 
diff --git a/chrome/browser/resources/new_tab_page/lazy_load.ts b/chrome/browser/resources/new_tab_page/lazy_load.ts
index 038fd4db..bdc044d4 100644
--- a/chrome/browser/resources/new_tab_page/lazy_load.ts
+++ b/chrome/browser/resources/new_tab_page/lazy_load.ts
@@ -39,7 +39,7 @@
 export {FeedProxy} from './modules/feed/feed_module_proxy.js';
 export {feedDescriptor, FeedModuleElement, feedV2Descriptor} from './modules/feed/module.js';
 export {HistoryClustersProxy, HistoryClustersProxyImpl} from './modules/history_clusters/history_clusters_proxy.js';
-export {HistoryClusterElementType, HistoryClusterImageDisplayState, HistoryClusterLayoutType, historyClustersDescriptor, HistoryClustersModuleElement, LAYOUT_1_MIN_IMAGE_VISITS, LAYOUT_1_MIN_VISITS, LAYOUT_2_MIN_IMAGE_VISITS, LAYOUT_2_MIN_VISITS, LAYOUT_3_MIN_IMAGE_VISITS, LAYOUT_3_MIN_VISITS, MIN_RELATED_SEARCHES} from './modules/history_clusters/module.js';
+export {HistoryClusterElementType, HistoryClusterImageDisplayState, HistoryClusterLayoutType, historyClustersDescriptor, HistoryClustersModuleElement, LAYOUT_1_MIN_IMAGE_VISITS, LAYOUT_1_MIN_VISITS, LAYOUT_2_MIN_IMAGE_VISITS, LAYOUT_2_MIN_VISITS, LAYOUT_3_MIN_IMAGE_VISITS, LAYOUT_3_MIN_VISITS} from './modules/history_clusters/module.js';
 export {SuggestTileModuleElement} from './modules/history_clusters/suggest_tile.js';
 export {TileModuleElement} from './modules/history_clusters/tile.js';
 export {InfoDialogElement} from './modules/info_dialog.js';
diff --git a/chrome/browser/resources/new_tab_page/modules/history_clusters/module.ts b/chrome/browser/resources/new_tab_page/modules/history_clusters/module.ts
index a2342e9..2d9d963 100644
--- a/chrome/browser/resources/new_tab_page/modules/history_clusters/module.ts
+++ b/chrome/browser/resources/new_tab_page/modules/history_clusters/module.ts
@@ -25,7 +25,6 @@
 export const LAYOUT_2_MIN_VISITS = 3;
 export const LAYOUT_3_MIN_IMAGE_VISITS = 2;
 export const LAYOUT_3_MIN_VISITS = 4;
-export const MIN_RELATED_SEARCHES = 3;
 
 /**
  * Available module UI layouts. This enum must match the numbering for
@@ -221,20 +220,19 @@
 }
 
 async function createElement(): Promise<HistoryClustersModuleElement|null> {
-  const data =
-      await HistoryClustersProxyImpl.getInstance().handler.getCluster();
-  // Do not show module if no cluster or not enough related search results.
-  if (!data.cluster ||
-      data.cluster.relatedSearches.length < MIN_RELATED_SEARCHES) {
+  const {clusters} =
+      await HistoryClustersProxyImpl.getInstance().handler.getClusters();
+  // Do not show module if there are no clusters.
+  if (clusters.length === 0) {
     recordSelectedLayout(HistoryClusterLayoutType.NONE);
     return null;
   }
 
   const element = new HistoryClustersModuleElement();
-  element.cluster = data.cluster!;
+  element.cluster = clusters[0];
   // Pull out the SRP to be used in the header and to open the cluster
   // in tab group.
-  element.searchResultPage = data.cluster!.visits[0];
+  element.searchResultPage = clusters[0]!.visits[0];
 
   // History cluster visits minus the SRP that is included, since the SRP
   // isn't used in the layout.
diff --git a/chrome/browser/resources/new_tab_page/modules/module_descriptors.ts b/chrome/browser/resources/new_tab_page/modules/module_descriptors.ts
index 9686651..e0bc2ae 100644
--- a/chrome/browser/resources/new_tab_page/modules/module_descriptors.ts
+++ b/chrome/browser/resources/new_tab_page/modules/module_descriptors.ts
@@ -72,7 +72,7 @@
   // clusters module without rendering it.
   if (!loadTimeData.getBoolean('historyClustersModuleEnabled') &&
       loadTimeData.getBoolean('historyClustersModuleLoadEnabled')) {
-    HistoryClustersProxyImpl.getInstance().handler.getCluster();
+    HistoryClustersProxyImpl.getInstance().handler.getClusters();
   }
 }
 counterfactualLoad();
diff --git a/chrome/browser/resources/password_manager/BUILD.gn b/chrome/browser/resources/password_manager/BUILD.gn
index c804ca5..d5dc03df 100644
--- a/chrome/browser/resources/password_manager/BUILD.gn
+++ b/chrome/browser/resources/password_manager/BUILD.gn
@@ -65,6 +65,7 @@
 
   non_web_component_files = [
     "password_manager.ts",
+    "passkeys_browser_proxy.ts",
     "password_manager_proxy.ts",
     "prefs/extension_control_browser_proxy.ts",
     "router.ts",
diff --git a/chrome/browser/resources/password_manager/passkeys_browser_proxy.ts b/chrome/browser/resources/password_manager/passkeys_browser_proxy.ts
new file mode 100644
index 0000000..39059e6c
--- /dev/null
+++ b/chrome/browser/resources/password_manager/passkeys_browser_proxy.ts
@@ -0,0 +1,30 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {sendWithPromise} from 'chrome://resources/js/cr.js';
+
+export interface PasskeysBrowserProxy {
+  /**
+   * Determines whether any passkeys exist on the local device.
+   * May report false positives if the last passkey was recently deleted.
+   */
+  hasPasskeys(): Promise<boolean>;
+}
+
+export class PasskeysBrowserProxyImpl implements PasskeysBrowserProxy {
+  hasPasskeys() {
+    return sendWithPromise('passkeysHasPasskeys');
+  }
+
+  static getInstance(): PasskeysBrowserProxy {
+    return passkeysProxyInstance ||
+        (passkeysProxyInstance = new PasskeysBrowserProxyImpl());
+  }
+
+  static setInstance(obj: PasskeysBrowserProxy) {
+    passkeysProxyInstance = obj;
+  }
+}
+
+let passkeysProxyInstance: PasskeysBrowserProxy|null = null;
diff --git a/chrome/browser/resources/password_manager/password_manager.ts b/chrome/browser/resources/password_manager/password_manager.ts
index 3428284b0..58cfe1e 100644
--- a/chrome/browser/resources/password_manager/password_manager.ts
+++ b/chrome/browser/resources/password_manager/password_manager.ts
@@ -14,6 +14,9 @@
 export {AddPasswordDialogElement} from './dialogs/add_password_dialog.js';
 export {AuthTimedOutDialogElement} from './dialogs/auth_timed_out_dialog.js';
 export {EditPasswordDialogElement} from './dialogs/edit_password_dialog.js';
+// <if expr="is_win or is_macosx">
+export {PasskeysBrowserProxy, PasskeysBrowserProxyImpl} from './passkeys_browser_proxy.js';
+// </if>
 export {PasswordDetailsCardElement} from './password_details_card.js';
 export {PasswordDetailsSectionElement} from './password_details_section.js';
 export {PasswordListItemElement} from './password_list_item.js';
diff --git a/chrome/browser/resources/password_manager/settings_section.html b/chrome/browser/resources/password_manager/settings_section.html
index 756349d..47a98a0 100644
--- a/chrome/browser/resources/password_manager/settings_section.html
+++ b/chrome/browser/resources/password_manager/settings_section.html
@@ -99,6 +99,12 @@
       on-click="onAddShortcutClick_" label="$i18n{addShortcut}" hide-icon
       sub-label="$i18n{addShortcutDescription}" role-description="button">
   </cr-link-row>
+  <if expr="is_win or is_macosx">
+    <cr-link-row id="managePasskeysRow" external
+        class="cr-row settings-cr-link-row" hidden$="[[!hasPasskeys_]]"
+        on-click="onManagePasskeysClick_" label="$i18n{managePasskeysLabel}">
+    </cr-link-row>
+  </if>
 </div>
 <h3 id="blockedSitesTitle" class="page-title">$i18n{blockedSitesTitle}</h3>
 <div class="card" id="blockedSites">
diff --git a/chrome/browser/resources/password_manager/settings_section.ts b/chrome/browser/resources/password_manager/settings_section.ts
index a7f0d156d4..60ab4dc 100644
--- a/chrome/browser/resources/password_manager/settings_section.ts
+++ b/chrome/browser/resources/password_manager/settings_section.ts
@@ -16,6 +16,9 @@
 import {OpenWindowProxyImpl} from 'chrome://resources/js/open_window_proxy.js';
 import {DomRepeatEvent, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+// <if expr="is_win or is_macosx">
+import {PasskeysBrowserProxyImpl} from './passkeys_browser_proxy.js';
+// </if>
 import {BlockedSite, BlockedSitesListChangedListener, CredentialsChangedListener, PasswordManagerImpl} from './password_manager_proxy.js';
 import {PrefToggleButtonElement} from './prefs/pref_toggle_button.js';
 import {getTemplate} from './settings_section.html.js';
@@ -29,6 +32,7 @@
     blockedSitesList: HTMLElement,
     passwordToggle: PrefToggleButtonElement,
     trustedVaultBanner: CrLinkRowElement,
+    managePasskeysRow: CrLinkRowElement,
   };
 }
 
@@ -67,6 +71,11 @@
         value: false,
       },
 
+      hasPasskeys_: {
+        type: Boolean,
+        value: false,
+      },
+
       /** The visibility state of the trusted vault banner. */
       trustedVaultBannerState_: {
         type: Object,
@@ -76,6 +85,7 @@
   }
 
   private blockedSites_: BlockedSite[];
+  private hasPasskeys_: boolean;
   private hasPasswordsToExport_: boolean;
   private trustedVaultBannerState_: TrustedVaultBannerState;
 
@@ -111,6 +121,12 @@
         trustedVaultStateChanged);
     this.addWebUiListener(
         'trusted-vault-banner-state-changed', trustedVaultStateChanged);
+
+    // <if expr="is_win or is_macosx">
+    PasskeysBrowserProxyImpl.getInstance().hasPasskeys().then(hasPasskeys => {
+      this.hasPasskeys_ = hasPasskeys;
+    });
+    // </if>
   }
 
   override disconnectedCallback() {
@@ -214,6 +230,13 @@
       this.optInForAccountStorage();
     }
   }
+
+  private onManagePasskeysClick_() {
+    // In the future this may, e.g., open System Settings on macOS for iCloud
+    // Keychain, or open Control Panel on Windows for Hello. Currently passkey
+    // management is filled in via Chrome settings.
+    OpenWindowProxyImpl.getInstance().openUrl('chrome://settings/passkeys');
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/settings/chromeos/device_page/storage.html b/chrome/browser/resources/settings/chromeos/device_page/storage.html
index 0be081a7..0f2aacf 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/storage.html
+++ b/chrome/browser/resources/settings/chromeos/device_page/storage.html
@@ -192,8 +192,7 @@
   <cr-link-row id="driveOfflineSize" class="hr" on-click="onDriveOfflineClick_"
       label="$i18n{storageItemOffline}"
       sub-label="$i18n{storageSizeComputing}"
-      external
-      button-aria-description="$i18n{opensInNewTab}">
+      role-description="$i18n{subpageArrowRoleDescription}">
   </cr-link-row>
 </template>
 <template is="dom-if" if="[[showCrostiniStorage_]]">
diff --git a/chrome/browser/resources/settings/chromeos/device_page/storage.ts b/chrome/browser/resources/settings/chromeos/device_page/storage.ts
index 9bd88f6c..5b01196 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/storage.ts
+++ b/chrome/browser/resources/settings/chromeos/device_page/storage.ts
@@ -202,8 +202,9 @@
    * Handler for tapping the "Offline files" item.
    */
   private onDriveOfflineClick_(): void {
-    // TODO(b/266631636): Offline files row should redirect users to Files
-    // settings > Drive settings.
+    Router.getInstance().navigateTo(
+        routes.GOOGLE_DRIVE,
+        /* dynamicParams= */ undefined, /* removeSearch= */ true);
   }
 
   /**
diff --git a/chrome/browser/resources/settings/chromeos/lazy_load.ts b/chrome/browser/resources/settings/chromeos/lazy_load.ts
index ba647f7..16999b37 100644
--- a/chrome/browser/resources/settings/chromeos/lazy_load.ts
+++ b/chrome/browser/resources/settings/chromeos/lazy_load.ts
@@ -112,6 +112,7 @@
 export {TetherConnectionDialogElement} from './internet_page/tether_connection_dialog.js';
 export {KeyboardShortcutBanner} from './keyboard_shortcut_banner/keyboard_shortcut_banner.js';
 export {SettingsMultideviceCombinedSetupItemElement} from './multidevice_page/multidevice_combined_setup_item.js';
+export {SettingsMultideviceSmartlockItemElement} from './multidevice_page/multidevice_smartlock_item.js';
 export {SettingsAudioAndCaptionsPageElement} from './os_a11y_page/audio_and_captions_page.js';
 export {BluetoothBrailleDisplayListener, BluetoothBrailleDisplayManager} from './os_a11y_page/bluetooth_braille_display_manager.js';
 export {BluetoothBrailleDisplayUiElement} from './os_a11y_page/bluetooth_braille_display_ui.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.ts b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.ts
index 9978e2e..b7f6271 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.ts
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.ts
@@ -23,7 +23,7 @@
 import {MultiDeviceFeatureMixin} from './multidevice_feature_mixin.js';
 import {getTemplate} from './multidevice_smartlock_item.html.js';
 
-interface SettingsMultideviceSmartlockItemElement {
+export interface SettingsMultideviceSmartlockItemElement {
   $: {
     smartLockItem: SettingsMultideviceFeatureItemElement,
   };
@@ -32,7 +32,7 @@
 const SettingsMultideviceSmartlockItemElementBase =
     MultiDeviceFeatureMixin(WebUiListenerMixin(PolymerElement));
 
-class SettingsMultideviceSmartlockItemElement extends
+export class SettingsMultideviceSmartlockItemElement extends
     SettingsMultideviceSmartlockItemElementBase {
   static get is() {
     return 'settings-multidevice-smartlock-item' as const;
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.ts b/chrome/browser/resources/settings/chromeos/os_settings.ts
index 68b3c268..48827d36 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.ts
+++ b/chrome/browser/resources/settings/chromeos/os_settings.ts
@@ -140,8 +140,8 @@
 export * as searchResultIconMojom from './mojom-webui/search/search_result_icon.mojom-webui.js';
 export * as userActionRecorderMojom from './mojom-webui/search/user_action_recorder.mojom-webui.js';
 export * as settingMojom from './mojom-webui/setting.mojom-webui.js';
-export {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_page/multidevice_browser_proxy.js';
-export {MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, PhoneHubFeatureAccessProhibitedReason, PhoneHubFeatureAccessStatus, PhoneHubPermissionsSetupMode, SmartLockSignInEnabledState} from './multidevice_page/multidevice_constants.js';
+export {AndroidSmsInfo, MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_page/multidevice_browser_proxy.js';
+export {MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, PhoneHubFeatureAccessProhibitedReason, PhoneHubFeatureAccessStatus, PhoneHubPermissionsSetupAction, PhoneHubPermissionsSetupFeatureCombination, PhoneHubPermissionsSetupFlowScreens, PhoneHubPermissionsSetupMode, SmartLockSignInEnabledState} from './multidevice_page/multidevice_constants.js';
 export {NotificationAccessSetupOperationStatus} from './multidevice_page/multidevice_notification_access_setup_dialog.js';
 export {PermissionsSetupStatus, SetupFlowStatus} from './multidevice_page/multidevice_permissions_setup_dialog.js';
 export {Account, NearbyAccountManagerBrowserProxy, NearbyAccountManagerBrowserProxyImpl} from './nearby_share_page/nearby_account_manager_browser_proxy.js';
diff --git a/chrome/browser/safe_browsing/tailored_security/unconsented_message_android.cc b/chrome/browser/safe_browsing/tailored_security/unconsented_message_android.cc
index d14157f..b3d9a98b 100644
--- a/chrome/browser/safe_browsing/tailored_security/unconsented_message_android.cc
+++ b/chrome/browser/safe_browsing/tailored_security/unconsented_message_android.cc
@@ -13,9 +13,11 @@
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/google_chrome_strings.h"
+#include "chrome/grit/theme_resources.h"
 #include "components/messages/android/message_dispatcher_bridge.h"
 #include "components/messages/android/message_enums.h"
 #include "components/safe_browsing/core/browser/tailored_security_service/tailored_security_outcome.h"
+#include "components/safe_browsing/core/common/features.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 #include "components/signin/public/base/consent_level.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
@@ -102,8 +104,14 @@
   message_->SetTitle(l10n_util::GetStringUTF16(message_title));
   message_->SetPrimaryButtonText(l10n_util::GetStringUTF16(primary_button));
   if (!is_in_flow_) {
-    message_->SetDescription(l10n_util::GetStringUTF16(
-        IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_MESSAGE_DESCRIPTION));
+    if (base::FeatureList::IsEnabled(
+            safe_browsing::kTailoredSecurityUpdatedMessages)) {
+      message_->SetDescription(l10n_util::GetStringUTF16(
+          IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_MESSAGE_DESCRIPTION_UPDATED));
+    } else {
+      message_->SetDescription(l10n_util::GetStringUTF16(
+          IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_MESSAGE_DESCRIPTION));
+    }
   }
 
   if (is_in_flow_) {
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc
index e8747021..e74c58a 100644
--- a/chrome/browser/sessions/session_restore.cc
+++ b/chrome/browser/sessions/session_restore.cc
@@ -1216,7 +1216,8 @@
 WebContents* SessionRestore::RestoreForeignSessionTab(
     content::WebContents* source_web_contents,
     const sessions::SessionTab& tab,
-    WindowOpenDisposition disposition) {
+    WindowOpenDisposition disposition,
+    bool skip_renderer_creation) {
   Browser* browser = chrome::FindBrowserWithWebContents(source_web_contents);
   Profile* profile = browser->profile();
   StartupTabs startup_tabs;
diff --git a/chrome/browser/sessions/session_restore.h b/chrome/browser/sessions/session_restore.h
index 518cb41f..c427e3ba 100644
--- a/chrome/browser/sessions/session_restore.h
+++ b/chrome/browser/sessions/session_restore.h
@@ -93,11 +93,13 @@
   // restores the given session tab to the browser of |source_web_contents| if
   // the disposition is not NEW_WINDOW. Returns the WebContents corresponding
   // to the restored tab. If |disposition| is CURRENT_TAB, |source_web_contents|
-  // may be destroyed.
+  // may be destroyed. If |skip_renderer_creation| is true, depending on if
+  // |disposition| is BACKGROUND_TAB, lazily initialize tabs without a renderer.
   static content::WebContents* RestoreForeignSessionTab(
       content::WebContents* source_web_contents,
       const sessions::SessionTab& tab,
-      WindowOpenDisposition disposition);
+      WindowOpenDisposition disposition,
+      bool skip_renderer_creation = false);
 
   // Returns true if we're in the process of restoring |profile|.
   static bool IsRestoring(const Profile* profile);
diff --git a/chrome/browser/sessions/session_restore_android.cc b/chrome/browser/sessions/session_restore_android.cc
index 58424941..b1b89688 100644
--- a/chrome/browser/sessions/session_restore_android.cc
+++ b/chrome/browser/sessions/session_restore_android.cc
@@ -23,7 +23,8 @@
 content::WebContents* SessionRestore::RestoreForeignSessionTab(
     content::WebContents* web_contents,
     const sessions::SessionTab& session_tab,
-    WindowOpenDisposition disposition) {
+    WindowOpenDisposition disposition,
+    bool skip_renderer_creation) {
   DCHECK(session_tab.navigations.size() > 0);
   content::BrowserContext* context = web_contents->GetBrowserContext();
   Profile* profile = Profile::FromBrowserContext(context);
@@ -32,8 +33,20 @@
   std::vector<std::unique_ptr<content::NavigationEntry>> entries =
       sessions::ContentSerializedNavigationBuilder::ToNavigationEntries(
           session_tab.navigations, profile);
+
+  bool is_background_tab =
+      (disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) ? true : false;
+  content::WebContents::CreateParams create_params(context);
+  if (is_background_tab && skip_renderer_creation) {
+    create_params.initially_hidden = true;
+    create_params.desired_renderer_state =
+        content::WebContents::CreateParams::kNoRendererProcess;
+  }
+  // Ensure that skipping renderer creation is only enabled for background tabs.
+  DCHECK(skip_renderer_creation ? is_background_tab : true);
   std::unique_ptr<content::WebContents> new_web_contents =
-      content::WebContents::Create(content::WebContents::CreateParams(context));
+      content::WebContents::Create(create_params);
+
   content::WebContents* raw_new_web_contents = new_web_contents.get();
   int selected_index = session_tab.normalized_navigation_index();
   new_web_contents->GetController().Restore(
@@ -41,13 +54,14 @@
 
   TabAndroid* current_tab = TabAndroid::FromWebContents(web_contents);
   DCHECK(current_tab);
+  // If swapped, return the current tab's most up-to-date web contents.
   if (disposition == WindowOpenDisposition::CURRENT_TAB) {
     current_tab->SwapWebContents(std::move(new_web_contents), false, false);
-  } else {
-    DCHECK(disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB ||
-           disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB);
-    tab_model->CreateTab(current_tab, new_web_contents.release());
+    return current_tab->web_contents();
   }
+  DCHECK(disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB ||
+         disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB);
+  tab_model->CreateTab(current_tab, new_web_contents.release());
   return raw_new_web_contents;
 }
 
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java
index e780e91c..bc361cc 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java
@@ -347,6 +347,8 @@
                 return TabLaunchType.FROM_TAB_GROUP_UI;
             case LaunchTypeAtCreation.FROM_TAB_SWITCHER_UI:
                 return TabLaunchType.FROM_TAB_SWITCHER_UI;
+            case LaunchTypeAtCreation.FROM_RESTORE_TABS_UI:
+                return TabLaunchType.FROM_RESTORE_TABS_UI;
             case LaunchTypeAtCreation.FROM_LONGPRESS_BACKGROUND_IN_GROUP:
                 return TabLaunchType.FROM_LONGPRESS_BACKGROUND_IN_GROUP;
             case LaunchTypeAtCreation.FROM_APP_WIDGET:
@@ -405,6 +407,8 @@
                 return LaunchTypeAtCreation.FROM_TAB_GROUP_UI;
             case TabLaunchType.FROM_TAB_SWITCHER_UI:
                 return LaunchTypeAtCreation.FROM_TAB_SWITCHER_UI;
+            case TabLaunchType.FROM_RESTORE_TABS_UI:
+                return LaunchTypeAtCreation.FROM_RESTORE_TABS_UI;
             case TabLaunchType.FROM_LONGPRESS_BACKGROUND_IN_GROUP:
                 return LaunchTypeAtCreation.FROM_LONGPRESS_BACKGROUND_IN_GROUP;
             case TabLaunchType.FROM_APP_WIDGET:
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/flatbuffer/critical_persisted_tab_data.fbs b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/flatbuffer/critical_persisted_tab_data.fbs
index fb23deeb..5810c6b 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/flatbuffer/critical_persisted_tab_data.fbs
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/flatbuffer/critical_persisted_tab_data.fbs
@@ -37,6 +37,7 @@
     FROM_RECENT_TABS = 17,
     FROM_READING_LIST = 18,
     FROM_TAB_SWITCHER_UI = 19,
+    FROM_RESTORE_TABS_UI = 20,
     // Add new values here and don't change existing values
     // as they are persisted across restarts. Changing existing
     // values will lead to backwards compatibility issues crbug.com/1286984.
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelOrderControllerImpl.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelOrderControllerImpl.java
index 8d90c1b..e25f7fd 100644
--- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelOrderControllerImpl.java
+++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelOrderControllerImpl.java
@@ -145,7 +145,8 @@
     @Override
     public boolean willOpenInForeground(@TabLaunchType int type, boolean isNewTabIncognito) {
         // Restore is handling the active index by itself.
-        if (type == TabLaunchType.FROM_RESTORE || type == TabLaunchType.FROM_BROWSER_ACTIONS) {
+        if (type == TabLaunchType.FROM_RESTORE || type == TabLaunchType.FROM_BROWSER_ACTIONS
+                || type == TabLaunchType.FROM_RESTORE_TABS_UI) {
             return false;
         }
         return type != TabLaunchType.FROM_LONGPRESS_BACKGROUND
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 1464d1f..c3f0148 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3091,6 +3091,10 @@
       "webui/settings/ash/device_stylus_handler.h",
       "webui/settings/ash/fast_pair_saved_devices_handler.cc",
       "webui/settings/ash/fast_pair_saved_devices_handler.h",
+      "webui/settings/ash/files_page/google_drive_page_handler.cc",
+      "webui/settings/ash/files_page/google_drive_page_handler.h",
+      "webui/settings/ash/files_page/google_drive_page_handler_factory.cc",
+      "webui/settings/ash/files_page/google_drive_page_handler_factory.h",
       "webui/settings/ash/files_section.cc",
       "webui/settings/ash/files_section.h",
       "webui/settings/ash/fingerprint_handler.cc",
@@ -3234,6 +3238,7 @@
       "//ash/style:style",
       "//ash/webui/camera_app_ui",
       "//ash/webui/color_internals",
+      "//ash/webui/common:chrome_os_webui_config",
       "//ash/webui/common/resources/office_fallback:resources",
       "//ash/webui/connectivity_diagnostics",
       "//ash/webui/demo_mode_app_ui",
@@ -3313,6 +3318,7 @@
       "//chrome/browser/ui/webui/ash/parent_access:proto",
       "//chrome/browser/ui/webui/ash/vm:mojo_bindings",
       "//chrome/browser/ui/webui/nearby_share:mojom",
+      "//chrome/browser/ui/webui/settings/ash/files_page/mojom",
       "//chrome/browser/ui/webui/settings/ash/input_device_settings:mojom",
       "//chrome/browser/ui/webui/settings/ash/os_apps_page/mojom",
       "//chrome/browser/ui/webui/settings/ash/search:mojo_bindings",
diff --git a/chrome/browser/ui/android/tab_model/tab_model.h b/chrome/browser/ui/android/tab_model/tab_model.h
index 3df944f..d00e4d0 100644
--- a/chrome/browser/ui/android/tab_model/tab_model.h
+++ b/chrome/browser/ui/android/tab_model/tab_model.h
@@ -108,6 +108,9 @@
     FROM_READING_LIST,
     // Opened from Tab Switcher UI.
     FROM_TAB_SWITCHER_UI,
+    // Opened from the Restore Tabs UI. When restoring synced tabs the first
+    // tab is opened but not brought to the foreground.
+    FROM_RESTORE_TABS_UI,
     // Must be last.
     SIZE
   };
diff --git a/chrome/browser/ui/color/chrome_color_id.h b/chrome/browser/ui/color/chrome_color_id.h
index da374e0..bec7416 100644
--- a/chrome/browser/ui/color/chrome_color_id.h
+++ b/chrome/browser/ui/color/chrome_color_id.h
@@ -215,7 +215,6 @@
   E_CPONLY(kColorOmniboxChipForegroundNormalVisibility) \
   E_CPONLY(kColorOmniboxKeywordSelected) \
   E_CPONLY(kColorOmniboxKeywordSeparator) \
-  E_CPONLY(kColorOmniboxNullResultMessage) \
   E_CPONLY(kColorOmniboxResultsBackground) \
   E_CPONLY(kColorOmniboxResultsBackgroundHovered) \
   E_CPONLY(kColorOmniboxResultsBackgroundSelected) \
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index b4864e4d..b0690c42 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -44,6 +44,7 @@
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "ui/base/ui_base_features.h"
 #include "ui/color/color_id.h"
 #include "ui/events/event.h"
 #include "ui/gfx/canvas.h"
@@ -101,8 +102,11 @@
  public:
   METADATA_HEADER(OmniboxResultSelectionIndicator);
 
-  const int kStrokeThickness =
-      base::FeatureList::IsEnabled(omnibox::kExpandedStateColors) ? 4 : 3;
+  const bool cr2023_expanded_state_colors_enabled =
+      features::GetChromeRefresh2023Level() ==
+          features::ChromeRefresh2023Level::kLevel2 ||
+      base::FeatureList::IsEnabled(omnibox::kExpandedStateColors);
+  const int kStrokeThickness = cr2023_expanded_state_colors_enabled ? 4 : 3;
 
   explicit OmniboxResultSelectionIndicator(OmniboxResultView* result_view)
       : result_view_(result_view) {
diff --git a/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc
index 2920935..bb10f9fb 100644
--- a/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc
@@ -812,4 +812,142 @@
       controller->BeforeCloseTab(1, CloseTabSource::CLOSE_TAB_FROM_MOUSE));
 }
 
+IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, HomeTabScopeSegmentWildcard) {
+  GURL start_url =
+      embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
+  AppId app_id = InstallWebAppFromPage(browser(), start_url);
+  Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
+  TabStripModel* tab_strip = app_browser->tab_strip_model();
+
+  EXPECT_TRUE(registrar().IsTabbedWindowModeEnabled(app_id));
+
+  // Expect app opened with pinned home tab.
+  EXPECT_EQ(tab_strip->count(), 1);
+  EXPECT_TRUE(tab_strip->IsTabPinned(0));
+  EXPECT_EQ(tab_strip->GetWebContentsAt(0)->GetVisibleURL(), start_url);
+  EXPECT_EQ(tab_strip->active_index(), 0);
+  // Navigate to an out of home tab scope URL.
+  OpenUrlAndWait(app_browser,
+                 embedded_test_server()->GetURL("/web_apps/favicon_only.html"));
+  // Expect URL to have opened in a new  tab.
+  EXPECT_EQ(tab_strip->count(), 2);
+  EXPECT_EQ(tab_strip->active_index(), 1);
+
+  // Navigate to an in home tab scope URL.
+  OpenUrlAndWait(app_browser, embedded_test_server()->GetURL(
+                                  "/web_apps/title_appname_prefix.html"));
+  // Expect it was opened in home tab.
+  EXPECT_EQ(tab_strip->count(), 2);
+  EXPECT_EQ(tab_strip->active_index(), 0);
+  EXPECT_EQ(
+      tab_strip->GetActiveWebContents()->GetVisibleURL(),
+      embedded_test_server()->GetURL("/web_apps/title_appname_prefix.html"));
+
+  // Navigate to start_url.
+  OpenUrlAndWait(app_browser, start_url);
+  // Expect it was opened in home tab.
+  EXPECT_EQ(tab_strip->count(), 2);
+  EXPECT_EQ(tab_strip->active_index(), 0);
+  EXPECT_EQ(tab_strip->GetActiveWebContents()->GetVisibleURL(), start_url);
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, HomeTabScopeFixedString) {
+  GURL start_url = embedded_test_server()->GetURL(
+      "/web_apps/get_manifest.html?tab_strip_fixed_home_scope.json");
+  AppId app_id = InstallWebAppFromPage(browser(), start_url);
+  Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
+  TabStripModel* tab_strip = app_browser->tab_strip_model();
+
+  EXPECT_TRUE(registrar().IsTabbedWindowModeEnabled(app_id));
+
+  // Expect app opened with pinned home tab.
+  EXPECT_EQ(tab_strip->count(), 1);
+  EXPECT_TRUE(tab_strip->IsTabPinned(0));
+  EXPECT_EQ(tab_strip->GetWebContentsAt(0)->GetVisibleURL(), start_url);
+  EXPECT_EQ(tab_strip->active_index(), 0);
+
+  // Navigate to an in home tab scope URL.
+  OpenUrlAndWait(app_browser, embedded_test_server()->GetURL(
+                                  "/web_apps/title_appname_prefix.html"));
+  // Expect it was opened in home tab.
+  EXPECT_EQ(tab_strip->count(), 1);
+  EXPECT_EQ(tab_strip->active_index(), 0);
+  EXPECT_EQ(
+      tab_strip->GetActiveWebContents()->GetVisibleURL(),
+      embedded_test_server()->GetURL("/web_apps/title_appname_prefix.html"));
+
+  // Navigate to an out of home tab scope URL.
+  OpenUrlAndWait(app_browser,
+                 embedded_test_server()->GetURL("/web_apps/favicon_only.html"));
+  // Expect URL to have opened in a new  tab.
+  EXPECT_EQ(tab_strip->count(), 2);
+  EXPECT_EQ(tab_strip->active_index(), 1);
+
+  // Navigate to another in home tab scope URL.
+  OpenUrlAndWait(app_browser, embedded_test_server()->GetURL(
+                                  "/web_apps/tab_strip_customizations.html"));
+  // Expect it was opened in home tab.
+  EXPECT_EQ(tab_strip->count(), 2);
+  EXPECT_EQ(tab_strip->active_index(), 0);
+  EXPECT_EQ(tab_strip->GetActiveWebContents()->GetVisibleURL(),
+            embedded_test_server()->GetURL(
+                "/web_apps/tab_strip_customizations.html"));
+
+  // Navigate to start_url.
+  OpenUrlAndWait(app_browser, start_url);
+  // Expect it was opened in home tab.
+  EXPECT_EQ(tab_strip->count(), 2);
+  EXPECT_EQ(tab_strip->active_index(), 0);
+  EXPECT_EQ(tab_strip->GetActiveWebContents()->GetVisibleURL(), start_url);
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, HomeTabScopeWildcardString) {
+  GURL start_url = embedded_test_server()->GetURL(
+      "/web_apps/get_manifest.html?tab_strip_wildcard_home_scope.json");
+  AppId app_id = InstallWebAppFromPage(browser(), start_url);
+  Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
+  TabStripModel* tab_strip = app_browser->tab_strip_model();
+
+  EXPECT_TRUE(registrar().IsTabbedWindowModeEnabled(app_id));
+
+  // Expect app opened with pinned home tab.
+  EXPECT_EQ(tab_strip->count(), 1);
+  EXPECT_TRUE(tab_strip->IsTabPinned(0));
+  EXPECT_EQ(tab_strip->GetWebContentsAt(0)->GetVisibleURL(), start_url);
+  EXPECT_EQ(tab_strip->active_index(), 0);
+
+  // Navigate to an in home tab scope URL.
+  OpenUrlAndWait(app_browser, embedded_test_server()->GetURL(
+                                  "/web_apps/title_appname_prefix.html"));
+  // Expect it was opened in home tab.
+  EXPECT_EQ(tab_strip->count(), 1);
+  EXPECT_EQ(tab_strip->active_index(), 0);
+  EXPECT_EQ(
+      tab_strip->GetActiveWebContents()->GetVisibleURL(),
+      embedded_test_server()->GetURL("/web_apps/title_appname_prefix.html"));
+
+  // Navigate to an out of home tab scope URL.
+  OpenUrlAndWait(app_browser,
+                 embedded_test_server()->GetURL("/banners/theme-color.html"));
+  // Expect URL to have opened in a new  tab.
+  EXPECT_EQ(tab_strip->count(), 2);
+  EXPECT_EQ(tab_strip->active_index(), 1);
+
+  // Navigate to another in home tab scope URL.
+  OpenUrlAndWait(app_browser, embedded_test_server()->GetURL(
+                                  "/web_apps/standalone/basic.html"));
+  // Expect it was opened in home tab.
+  EXPECT_EQ(tab_strip->count(), 2);
+  EXPECT_EQ(tab_strip->active_index(), 0);
+  EXPECT_EQ(tab_strip->GetActiveWebContents()->GetVisibleURL(),
+            embedded_test_server()->GetURL("/web_apps/standalone/basic.html"));
+
+  // Navigate to start_url.
+  OpenUrlAndWait(app_browser, start_url);
+  // Expect it was opened in home tab.
+  EXPECT_EQ(tab_strip->count(), 2);
+  EXPECT_EQ(tab_strip->active_index(), 0);
+  EXPECT_EQ(tab_strip->GetActiveWebContents()->GetVisibleURL(), start_url);
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/ui/web_applications/DEPS b/chrome/browser/ui/web_applications/DEPS
index 2240ada..6bf98a6 100644
--- a/chrome/browser/ui/web_applications/DEPS
+++ b/chrome/browser/ui/web_applications/DEPS
@@ -1,3 +1,7 @@
+include_rules = {
+  "+third_party/liburlpattern",
+}
+
 specific_include_rules = {
   "web_app_interactive_uitest\.cc": [
     "+ash/shell.h",
diff --git a/chrome/browser/ui/web_applications/app_browser_controller.cc b/chrome/browser/ui/web_applications/app_browser_controller.cc
index 230d9c26..3bc5560e 100644
--- a/chrome/browser/ui/web_applications/app_browser_controller.cc
+++ b/chrome/browser/ui/web_applications/app_browser_controller.cc
@@ -440,6 +440,10 @@
   return GetAppStartUrl();
 }
 
+bool AppBrowserController::IsUrlInHomeTabScope(const GURL& url) const {
+  return false;
+}
+
 #if BUILDFLAG(IS_MAC)
 bool AppBrowserController::AlwaysShowToolbarInFullscreen() const {
   return true;
diff --git a/chrome/browser/ui/web_applications/app_browser_controller.h b/chrome/browser/ui/web_applications/app_browser_controller.h
index 04c4a088..fb831ba2 100644
--- a/chrome/browser/ui/web_applications/app_browser_controller.h
+++ b/chrome/browser/ui/web_applications/app_browser_controller.h
@@ -149,6 +149,9 @@
   // Gets the new tab URL for tabbed apps.
   virtual GURL GetAppNewTabUrl() const;
 
+  // Returns whether the url is within the scope of the tab strip home tab.
+  virtual bool IsUrlInHomeTabScope(const GURL& url) const;
+
   // Determines whether the specified url is 'inside' the app |this| controls.
   virtual bool IsUrlInAppScope(const GURL& url) const = 0;
 
diff --git a/chrome/browser/ui/web_applications/tabbed_web_app_navigation_throttle.cc b/chrome/browser/ui/web_applications/tabbed_web_app_navigation_throttle.cc
index 47ecc83..6c41755 100644
--- a/chrome/browser/ui/web_applications/tabbed_web_app_navigation_throttle.cc
+++ b/chrome/browser/ui/web_applications/tabbed_web_app_navigation_throttle.cc
@@ -90,8 +90,8 @@
   auto* tab_helper = WebAppTabHelper::FromWebContents(web_contents);
   DCHECK(tab_helper);
   bool navigating_from_home_tab = tab_helper->is_pinned_home_tab();
-  bool navigation_url_is_home_url = IsPinnedHomeTabUrl(
-      provider->registrar_unsafe(), app_id, navigation_handle()->GetURL());
+  bool navigation_url_is_home_url =
+      app_controller->IsUrlInHomeTabScope(navigation_handle()->GetURL());
 
   // Navigations from the home tab to another URL should open in a new tab.
   if (navigating_from_home_tab && !navigation_url_is_home_url) {
diff --git a/chrome/browser/ui/web_applications/web_app_browser_controller.cc b/chrome/browser/ui/web_applications/web_app_browser_controller.cc
index 5e6671b2..a317bd8 100644
--- a/chrome/browser/ui/web_applications/web_app_browser_controller.cc
+++ b/chrome/browser/ui/web_applications/web_app_browser_controller.cc
@@ -488,6 +488,42 @@
   return registrar().GetAppNewTabUrl(app_id());
 }
 
+bool WebAppBrowserController::IsUrlInHomeTabScope(const GURL& url) const {
+  if (!registrar().IsTabbedWindowModeEnabled(app_id())) {
+    return false;
+  }
+
+  if (!IsUrlInAppScope(url)) {
+    return false;
+  }
+
+  absl::optional<GURL> pinned_home_url =
+      registrar().GetAppPinnedHomeTabUrl(app_id());
+  if (!pinned_home_url) {
+    return false;
+  }
+
+  // We ignore query params and hash ref when deciding what should be
+  // opened as the home tab.
+  GURL::Replacements replacements;
+  replacements.ClearQuery();
+  replacements.ClearRef();
+  if (url.ReplaceComponents(replacements) ==
+      pinned_home_url.value().ReplaceComponents(replacements)) {
+    return true;
+  }
+
+  if (!home_tab_scope_.has_value()) {
+    home_tab_scope_ = GetTabbedHomeTabScope();
+  }
+
+  if (home_tab_scope_.has_value()) {
+    std::vector<int> vec;
+    return home_tab_scope_.value().Match(url.path(), &vec);
+  }
+  return false;
+}
+
 bool WebAppBrowserController::IsUrlInAppScope(const GURL& url) const {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   if (system_app() && system_app()->IsUrlInSystemAppScope(url))
@@ -608,8 +644,7 @@
   // considered "appy".
   WebAppTabHelper::FromWebContents(contents)->set_acting_as_app(true);
 
-  if (AppUsesTabbed() && IsPinnedHomeTabUrl(registrar(), app_id(),
-                                            contents->GetLastCommittedURL())) {
+  if (AppUsesTabbed() && IsUrlInHomeTabScope(contents->GetLastCommittedURL())) {
     WebAppTabHelper::FromWebContents(contents)->set_is_pinned_home_tab(true);
   }
 }
@@ -741,4 +776,34 @@
   return registrar().GetAppBackgroundColor(app_id());
 }
 
+absl::optional<RE2::Set> WebAppBrowserController::GetTabbedHomeTabScope()
+    const {
+  const WebApp* web_app = registrar().GetAppById(app_id());
+  if (!web_app) {
+    return absl::nullopt;
+  }
+  TabStrip tab_strip = web_app->tab_strip().value();
+  if (const auto* params =
+          absl::get_if<blink::Manifest::HomeTabParams>(&tab_strip.home_tab)) {
+    std::vector<blink::Manifest::UrlPattern> scope_patterns =
+        params->scope_patterns;
+
+    RE2::Set scope_set = RE2::Set(RE2::Options(), RE2::Anchor::UNANCHORED);
+    for (auto& scope : scope_patterns) {
+      liburlpattern::Options options = {.delimiter_list = "/",
+                                        .prefix_list = "/",
+                                        .sensitive = true,
+                                        .strict = false};
+      liburlpattern::Pattern pattern(scope.pathname, options, "[^/]+?");
+      std::string error;
+      scope_set.Add(pattern.GenerateRegexString(), &error);
+    }
+
+    if (scope_set.Compile()) {
+      return scope_set;
+    }
+  }
+  return absl::nullopt;
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/ui/web_applications/web_app_browser_controller.h b/chrome/browser/ui/web_applications/web_app_browser_controller.h
index bf7b0caaa..5464384d 100644
--- a/chrome/browser/ui/web_applications/web_app_browser_controller.h
+++ b/chrome/browser/ui/web_applications/web_app_browser_controller.h
@@ -24,6 +24,9 @@
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "components/services/app_service/public/cpp/icon_types.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/liburlpattern/options.h"
+#include "third_party/liburlpattern/pattern.h"
+#include "third_party/re2/src/re2/set.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/models/image_model.h"
 
@@ -87,6 +90,7 @@
   std::u16string GetFormattedUrlOrigin() const override;
   GURL GetAppStartUrl() const override;
   GURL GetAppNewTabUrl() const override;
+  bool IsUrlInHomeTabScope(const GURL& url) const override;
   bool IsUrlInAppScope(const GURL& url) const override;
   WebAppBrowserController* AsWebAppBrowserController() override;
   bool CanUserUninstall() const override;
@@ -171,6 +175,10 @@
   // given the current state of dark/light mode.
   absl::optional<SkColor> GetResolvedManifestBackgroundColor() const;
 
+  // Returns the set of scope patterns for the home tab scope of tabbed web
+  // apps.
+  absl::optional<RE2::Set> GetTabbedHomeTabScope() const;
+
   const raw_ref<WebAppProvider> provider_;
 
   // Save the display mode at time of launch. The web app display mode may
@@ -186,6 +194,8 @@
   mutable absl::optional<ui::ImageModel> app_icon_;
   mutable absl::optional<gfx::ImageSkia> home_tab_icon_;
 
+  mutable absl::optional<RE2::Set> home_tab_scope_;
+
 #if BUILDFLAG(IS_CHROMEOS)
   // The result of digital asset link verification of the web app.
   // Only used for web-only TWAs installed through the Play Store.
diff --git a/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc b/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc
index a556cc57..e82aff87 100644
--- a/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc
@@ -39,10 +39,6 @@
 #include "chrome/common/chrome_features.h"
 #endif
 
-#if BUILDFLAG(IS_WIN)
-#include "base/test/test_reg_util_win.h"
-#endif
-
 namespace web_app {
 
 WebAppControllerBrowserTest::WebAppControllerBrowserTest()
@@ -59,18 +55,6 @@
     features::kWebAppsCrosapi, ash::features::kLacrosPrimary
 #endif
   });
-
-#if BUILDFLAG(IS_WIN)
-  registry_override_.OverrideRegistry(HKEY_CURRENT_USER);
-  base::win::RegKey key;
-  // In a real registry, this key would exist, but since we're using
-  // hive override, it's empty, so we create this key.
-  // TODO(https://b/273981744): Move this and the registry override to the
-  // OsIntegrationTestOverride class.
-  key.Create(HKEY_CURRENT_USER,
-             L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
-             KEY_SET_VALUE);
-#endif
 }
 
 WebAppControllerBrowserTest::~WebAppControllerBrowserTest() = default;
diff --git a/chrome/browser/ui/web_applications/web_app_controller_browsertest.h b/chrome/browser/ui/web_applications/web_app_controller_browsertest.h
index c39a317..8df2e19 100644
--- a/chrome/browser/ui/web_applications/web_app_controller_browsertest.h
+++ b/chrome/browser/ui/web_applications/web_app_controller_browsertest.h
@@ -17,10 +17,6 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "url/gurl.h"
 
-#if BUILDFLAG(IS_WIN)
-#include "base/test/test_reg_util_win.h"
-#endif
-
 class Profile;
 
 namespace base {
@@ -111,12 +107,6 @@
   net::EmbeddedTestServer https_server_;
   base::CallbackListSubscription create_services_subscription_;
 
-#if BUILDFLAG(IS_WIN)
-  // This is used to ensure any registry changes by this test don't affect other
-  // parts of the the trybot and are cleaned up.
-  registry_util::RegistryOverrideManager registry_override_;
-#endif
-
   // Similar to net::MockCertVerifier, but also updates the CertVerifier
   // used by the NetworkService.
   content::ContentMockCertVerifier cert_verifier_;
diff --git a/chrome/browser/ui/web_applications/web_app_launch_utils.cc b/chrome/browser/ui/web_applications/web_app_launch_utils.cc
index 8866929..33b440b5 100644
--- a/chrome/browser/ui/web_applications/web_app_launch_utils.cc
+++ b/chrome/browser/ui/web_applications/web_app_launch_utils.cc
@@ -309,22 +309,23 @@
     }
   }
 
-  bool as_pinned_home_tab = IsPinnedHomeTabUrl(registrar, app_id, launch_url);
+  Browser* browser = nullptr;
 
   if (registrar.IsTabbedWindowModeEnabled(app_id)) {
-    if (Browser* browser =
-            AppBrowserController::FindForWebApp(*profile, app_id)) {
-      return ReparentWebContentsIntoAppBrowser(contents, browser, app_id,
-                                               as_pinned_home_tab);
-    }
+    browser = AppBrowserController::FindForWebApp(*profile, app_id);
   }
 
-  return ReparentWebContentsIntoAppBrowser(
-      contents,
-      Browser::Create(Browser::CreateParams::CreateForApp(
-          GenerateApplicationNameFromAppId(app_id), true /* trusted_source */,
-          gfx::Rect(), profile, true /* user_gesture */)),
-      app_id, as_pinned_home_tab);
+  if (!browser) {
+    browser = Browser::Create(Browser::CreateParams::CreateForApp(
+        GenerateApplicationNameFromAppId(app_id), true /* trusted_source */,
+        gfx::Rect(), profile, true /* user_gesture */));
+  }
+
+  bool as_pinned_home_tab =
+      browser->app_controller()->IsUrlInHomeTabScope(launch_url);
+
+  return ReparentWebContentsIntoAppBrowser(contents, browser, app_id,
+                                           as_pinned_home_tab);
 }
 
 void SetWebContentsActingAsApp(content::WebContents* contents,
@@ -444,11 +445,9 @@
 
 content::WebContents* NavigateWebAppUsingParams(const std::string& app_id,
                                                 NavigateParams& nav_params) {
-  WebAppRegistrar& registrar =
-      WebAppProvider::GetForLocalAppsUnchecked(nav_params.browser->profile())
-          ->registrar_unsafe();
-
-  if (IsPinnedHomeTabUrl(registrar, app_id, nav_params.url)) {
+  if (nav_params.browser->app_controller() &&
+      nav_params.browser->app_controller()->IsUrlInHomeTabScope(
+          nav_params.url)) {
     // Navigations to the home tab URL in tabbed apps should happen in the home
     // tab.
     nav_params.browser->tab_strip_model()->ActivateTabAt(0);
diff --git a/chrome/browser/ui/web_applications/web_app_tabbed_utils.cc b/chrome/browser/ui/web_applications/web_app_tabbed_utils.cc
index 573aed9..f18e85a 100644
--- a/chrome/browser/ui/web_applications/web_app_tabbed_utils.cc
+++ b/chrome/browser/ui/web_applications/web_app_tabbed_utils.cc
@@ -20,24 +20,4 @@
   return HasPinnedHomeTab(tab_strip_model) && index == 0;
 }
 
-bool IsPinnedHomeTabUrl(const WebAppRegistrar& registrar,
-                        const AppId& app_id,
-                        GURL launch_url) {
-  if (!registrar.IsTabbedWindowModeEnabled(app_id))
-    return false;
-
-  absl::optional<GURL> pinned_home_url =
-      registrar.GetAppPinnedHomeTabUrl(app_id);
-  if (!pinned_home_url)
-    return false;
-
-  // A launch URL which is the home tab URL with query params and
-  // hash ref should be opened as the home tab.
-  GURL::Replacements replacements;
-  replacements.ClearQuery();
-  replacements.ClearRef();
-  return launch_url.ReplaceComponents(replacements) ==
-         pinned_home_url.value().ReplaceComponents(replacements);
-}
-
 }  // namespace web_app
diff --git a/chrome/browser/ui/web_applications/web_app_tabbed_utils.h b/chrome/browser/ui/web_applications/web_app_tabbed_utils.h
index d9a1e8a..0e5b70e 100644
--- a/chrome/browser/ui/web_applications/web_app_tabbed_utils.h
+++ b/chrome/browser/ui/web_applications/web_app_tabbed_utils.h
@@ -18,11 +18,6 @@
 // Returns whether the tab at the given index is the pinned home tab.
 bool IsPinnedHomeTab(const TabStripModel* tab_strip_model, int index);
 
-// Returns whether the given launch_url should be treated as the home tab URL.
-bool IsPinnedHomeTabUrl(const WebAppRegistrar& registrar,
-                        const AppId& app_id,
-                        GURL launch_url);
-
 }  // namespace web_app
 
 #endif  // CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_TABBED_UTILS_H_
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc
index b2d74c5..f932673 100644
--- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc
+++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc
@@ -56,7 +56,7 @@
 std::vector<ProvidedFileSystemInfo> GetODFSFileSystems(Profile* profile) {
   Service* service = Service::Get(profile);
   ProviderId provider_id = ProviderId::CreateFromExtensionId(
-      file_manager::file_tasks::kODFSExtensionId);
+      file_manager::file_tasks::GetODFSExtensionId(profile));
   return service->GetProvidedFileSystemInfoList(provider_id);
 }
 
@@ -183,7 +183,7 @@
 
   file_system_provider::ProviderId provider_id =
       file_system_provider::ProviderId::CreateFromExtensionId(
-          file_manager::file_tasks::kODFSExtensionId);
+          file_manager::file_tasks::GetODFSExtensionId(profile));
   if (parser.file_system()->GetFileSystemInfo().provider_id() != provider_id) {
     return false;
   }
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_page_handler.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_page_handler.cc
index ed871e8..48b43a8f 100644
--- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_page_handler.cc
+++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_page_handler.cc
@@ -98,7 +98,7 @@
     SignInToOneDriveCallback callback) {
   Service* service = Service::Get(profile_);
   ProviderId provider_id = ProviderId::CreateFromExtensionId(
-      file_manager::file_tasks::kODFSExtensionId);
+      file_manager::file_tasks::GetODFSExtensionId(profile_));
   web_ui_->GetWebContents()->GetTopLevelNativeWindow()->Hide();
   service->RequestMount(
       provider_id,
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/one_drive_upload_handler.cc b/chrome/browser/ui/webui/ash/cloud_upload/one_drive_upload_handler.cc
index 00723890..269953b3 100644
--- a/chrome/browser/ui/webui/ash/cloud_upload/one_drive_upload_handler.cc
+++ b/chrome/browser/ui/webui/ash/cloud_upload/one_drive_upload_handler.cc
@@ -95,7 +95,7 @@
 
   // Destination url.
   ProviderId provider_id = ProviderId::CreateFromExtensionId(
-      file_manager::file_tasks::kODFSExtensionId);
+      file_manager::file_tasks::GetODFSExtensionId(profile_));
   Service* service = Service::Get(profile_);
   std::vector<ProvidedFileSystemInfo> file_systems =
       service->GetProvidedFileSystemInfoList(provider_id);
diff --git a/chrome/browser/ui/webui/ash/enterprise_reporting/enterprise_reporting_ui.cc b/chrome/browser/ui/webui/ash/enterprise_reporting/enterprise_reporting_ui.cc
index 6ed6cde..5ae143dd 100644
--- a/chrome/browser/ui/webui/ash/enterprise_reporting/enterprise_reporting_ui.cc
+++ b/chrome/browser/ui/webui/ash/enterprise_reporting/enterprise_reporting_ui.cc
@@ -36,4 +36,9 @@
 
 EnterpriseReportingUI::~EnterpriseReportingUI() = default;
 
+bool EnterpriseReportingUIConfig::IsWebUIEnabled(
+    content::BrowserContext* browser_context) {
+  return base::FeatureList::IsEnabled(ash::features::kEnterpriseReportingUI);
+}
+
 }  // namespace ash::reporting
diff --git a/chrome/browser/ui/webui/ash/enterprise_reporting/enterprise_reporting_ui.h b/chrome/browser/ui/webui/ash/enterprise_reporting/enterprise_reporting_ui.h
index 793ad658..e343868 100644
--- a/chrome/browser/ui/webui/ash/enterprise_reporting/enterprise_reporting_ui.h
+++ b/chrome/browser/ui/webui/ash/enterprise_reporting/enterprise_reporting_ui.h
@@ -5,10 +5,26 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_ASH_ENTERPRISE_REPORTING_ENTERPRISE_REPORTING_UI_H_
 #define CHROME_BROWSER_UI_WEBUI_ASH_ENTERPRISE_REPORTING_ENTERPRISE_REPORTING_UI_H_
 
+#include "ash/webui/common/chrome_os_webui_config.h"
+#include "chrome/common/webui_url_constants.h"
 #include "content/public/browser/web_ui_controller.h"
+#include "content/public/common/url_constants.h"
 
 namespace ash::reporting {
 
+class EnterpriseReportingUI;
+
+// WebUIConfig for chrome://enterprise-reporting
+class EnterpriseReportingUIConfig
+    : public ChromeOSWebUIConfig<EnterpriseReportingUI> {
+ public:
+  EnterpriseReportingUIConfig()
+      : ChromeOSWebUIConfig(content::kChromeUIScheme,
+                            chrome::kChromeUIEnterpriseReportingHost) {}
+
+  bool IsWebUIEnabled(content::BrowserContext* browser_context) override;
+};
+
 // The WebUI for chrome://enterprise-reporting
 class EnterpriseReportingUI : public content::WebUIController {
  public:
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 0da84db7..ca77fe355 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -598,13 +598,6 @@
       base::BindRepeating(&BindEcheConnectionStatusHandler, manager));
 }
 
-template <>
-WebUIController* NewWebUI<ash::OSFeedbackUI>(WebUI* web_ui, const GURL& url) {
-  Profile* profile = Profile::FromWebUI(web_ui);
-  return new ash::OSFeedbackUI(
-      web_ui, std::make_unique<ash::ChromeOsFeedbackDelegate>(profile));
-}
-
 void BindScanService(
     Profile* profile,
     mojo::PendingReceiver<ash::scanning::mojom::ScanService> pending_receiver) {
@@ -964,20 +957,12 @@
     return &NewWebUI<ConflictsUI>;
 #endif
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  if (base::FeatureList::IsEnabled(ash::features::kOsFeedback)) {
-    if (url.host_piece() == ash::kChromeUIOSFeedbackHost)
-      return &NewWebUI<ash::OSFeedbackUI>;
-  }
   if (url.host_piece() == ash::kChromeUIFaceMLAppHost) {
     if (!ash::features::IsFaceMLSwaEnabled()) {
       return nullptr;
     }
     return &NewComponentUI<ash::FaceMLAppUI, ash::ChromeFaceMLUserProvider>;
   }
-  if (url.host_piece() == chrome::kChromeUIEnterpriseReportingHost &&
-      base::FeatureList::IsEnabled(ash::features::kEnterpriseReportingUI)) {
-    return &NewWebUI<ash::reporting::EnterpriseReportingUI>;
-  }
   if (url.host_piece() == ash::file_manager::kChromeUIFileManagerHost) {
     return &NewComponentUI<ash::file_manager::FileManagerUI,
                            ChromeFileManagerUIDelegate>;
diff --git a/chrome/browser/ui/webui/chromeos/chrome_web_ui_configs_chromeos.cc b/chrome/browser/ui/webui/chromeos/chrome_web_ui_configs_chromeos.cc
index 730212c..1cf465d 100644
--- a/chrome/browser/ui/webui/chromeos/chrome_web_ui_configs_chromeos.cc
+++ b/chrome/browser/ui/webui/chromeos/chrome_web_ui_configs_chromeos.cc
@@ -13,8 +13,10 @@
 #include "ash/webui/color_internals/color_internals_ui.h"
 #include "ash/webui/files_internals/files_internals_ui.h"
 #include "ash/webui/firmware_update_ui/firmware_update_app_ui.h"
+#include "ash/webui/os_feedback_ui/os_feedback_ui.h"
 #include "ash/webui/shortcut_customization_ui/shortcut_customization_app_ui.h"
 #include "ash/webui/system_extensions_internals_ui/system_extensions_internals_ui.h"
+#include "chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.h"
 #include "chrome/browser/ash/web_applications/camera_app/chrome_camera_app_ui_delegate.h"
 #include "chrome/browser/ash/web_applications/files_internals_ui_delegate.h"
 #include "chrome/browser/ui/webui/ash/account_manager/account_manager_error_ui.h"
@@ -33,6 +35,7 @@
 #include "chrome/browser/ui/webui/ash/cryptohome_ui.h"
 #include "chrome/browser/ui/webui/ash/drive_internals_ui.h"
 #include "chrome/browser/ui/webui/ash/emoji/emoji_ui.h"
+#include "chrome/browser/ui/webui/ash/enterprise_reporting/enterprise_reporting_ui.h"
 #include "chrome/browser/ui/webui/ash/healthd_internals/healthd_internals_ui.h"
 #include "chrome/browser/ui/webui/ash/human_presence_internals_ui.h"
 #include "chrome/browser/ui/webui/ash/in_session_password_change/password_change_ui.h"
@@ -138,9 +141,14 @@
   map.AddWebUIConfig(std::make_unique<ash::NotificationTesterUIConfig>());
   map.AddWebUIConfig(
       std::make_unique<ash::office_fallback::OfficeFallbackUIConfig>());
+  map.AddWebUIConfig(
+      MakeComponentConfig<ash::OSFeedbackUIConfig, ash::OSFeedbackUI,
+                          ash::ChromeOsFeedbackDelegate>());
   map.AddWebUIConfig(std::make_unique<ash::settings::OSSettingsUIConfig>());
   map.AddWebUIConfig(std::make_unique<ash::ParentAccessUIConfig>());
   map.AddWebUIConfig(std::make_unique<ash::PasswordChangeUIConfig>());
+  map.AddWebUIConfig(
+      std::make_unique<ash::reporting::EnterpriseReportingUIConfig>());
   map.AddWebUIConfig(std::make_unique<ash::PowerUIConfig>());
   map.AddWebUIConfig(std::make_unique<ash::SetTimeUIConfig>());
   map.AddWebUIConfig(std::make_unique<ash::ShortcutCustomizationAppUIConfig>());
diff --git a/chrome/browser/ui/webui/password_manager/password_manager_ui.cc b/chrome/browser/ui/webui/password_manager/password_manager_ui.cc
index 27412c9f..3b06f31e 100644
--- a/chrome/browser/ui/webui/password_manager/password_manager_ui.cc
+++ b/chrome/browser/ui/webui/password_manager/password_manager_ui.cc
@@ -6,6 +6,7 @@
 
 #include "base/i18n/message_formatter.h"
 #include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
 #include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
 #include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -41,6 +42,7 @@
 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
+#include "chrome/browser/ui/webui/settings/settings_security_key_handler.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
 #endif
 
@@ -166,6 +168,9 @@
     {"localPasswordManager",
      IDS_PASSWORD_BUBBLES_PASSWORD_MANAGER_LINK_TEXT_SAVING_ON_DEVICE},
     {"manage", IDS_SETTINGS_MANAGE},
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
+    {"managePasskeysLabel", IDS_PASSWORD_MANAGER_UI_MANAGE_PASSKEYS_LABEL},
+#endif
     {"menu", IDS_MENU},
     {"missingTLD", IDS_PASSWORD_MANAGER_UI_MISSING_TLD},
     {"moreActions", IDS_PASSWORD_MANAGER_UI_MORE_ACTIONS},
@@ -366,6 +371,9 @@
           password_manager::PromoCardInterface::GetAllPromoCardsForProfile(
               profile)));
 #endif
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
+  web_ui->AddMessageHandler(std::make_unique<settings::PasskeysHandler>());
+#endif
   auto* source = CreateAndAddPasswordsUIHTMLSource(profile, web_ui);
   AddPluralStrings(web_ui);
   ManagedUIHandler::Initialize(web_ui, source);
diff --git a/chrome/browser/ui/webui/settings/ash/files_page/OWNERS b/chrome/browser/ui/webui/settings/ash/files_page/OWNERS
new file mode 100644
index 0000000..73220a8
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/ash/files_page/OWNERS
@@ -0,0 +1 @@
+file://ui/file_manager/OWNERS
diff --git a/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler.cc b/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler.cc
new file mode 100644
index 0000000..8467c76
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler.cc
@@ -0,0 +1,92 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ash/drive/drive_integration_service.h"
+#include "chrome/browser/ui/webui/settings/ash/files_page/mojom/google_drive_handler.mojom.h"
+#include "ui/base/text/bytes_formatting.h"
+
+namespace ash::settings {
+
+using drivefs::pinning::Progress;
+
+namespace {
+
+google_drive::mojom::StatusPtr CreateStatusPtr(const Progress& progress) {
+  auto status = google_drive::mojom::Status::New();
+  status->required_space =
+      base::UTF16ToUTF8(ui::FormatBytes(progress.required_space));
+  status->remaining_space = base::UTF16ToUTF8(
+      ui::FormatBytes(progress.free_space - progress.required_space));
+  status->stage = progress.stage;
+  return status;
+}
+
+}  // namespace
+
+GoogleDrivePageHandler::GoogleDrivePageHandler(
+    mojo::PendingReceiver<google_drive::mojom::PageHandler> receiver,
+    mojo::PendingRemote<google_drive::mojom::Page> page,
+    Profile* profile)
+    : profile_(profile),
+      page_(std::move(page)),
+      receiver_(this, std::move(receiver)) {}
+
+GoogleDrivePageHandler::~GoogleDrivePageHandler() {
+  auto* const pin_manager = GetPinManager();
+  if (!pin_manager || !pin_manager->HasObserver(this)) {
+    return;
+  }
+  pin_manager->RemoveObserver(this);
+}
+
+void GoogleDrivePageHandler::CalculateRequiredSpace() {
+  auto* pin_manager = GetPinManager();
+  if (!pin_manager) {
+    page_->OnServiceUnavailable();
+    return;
+  }
+
+  NotifyProgress(pin_manager->GetProgress());
+  if (!pin_manager->HasObserver(this)) {
+    pin_manager->AddObserver(this);
+  }
+  pin_manager->CalculateRequiredSpace();
+}
+
+void GoogleDrivePageHandler::NotifyProgress(const Progress& progress) {
+  page_->OnProgress(CreateStatusPtr(progress));
+}
+
+drivefs::pinning::PinManager* GoogleDrivePageHandler::GetPinManager() {
+  drive::DriveIntegrationService* service =
+      drive::DriveIntegrationServiceFactory::FindForProfile(profile_);
+  if (!service || !service->IsMounted() || !service->GetPinManager()) {
+    return nullptr;
+  }
+  return service->GetPinManager();
+}
+
+void GoogleDrivePageHandler::OnProgress(const Progress& progress) {
+  if (progress.stage != drivefs::pin_manager_types::mojom::Stage::kSuccess &&
+      !progress.IsError()) {
+    return;
+  }
+
+  auto* pin_manager = GetPinManager();
+  if (!pin_manager) {
+    page_->OnServiceUnavailable();
+    return;
+  }
+
+  NotifyProgress(progress);
+}
+
+void GoogleDrivePageHandler::OnDrop() {
+  page_->OnServiceUnavailable();
+}
+
+}  // namespace ash::settings
diff --git a/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler.h b/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler.h
new file mode 100644
index 0000000..52e37ab
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler.h
@@ -0,0 +1,54 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_ASH_FILES_PAGE_GOOGLE_DRIVE_PAGE_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_ASH_FILES_PAGE_GOOGLE_DRIVE_PAGE_HANDLER_H_
+
+#include "base/memory/raw_ptr.h"
+#include "chrome/browser/ui/webui/settings/ash/files_page/mojom/google_drive_handler.mojom.h"
+#include "chromeos/ash/components/drivefs/drivefs_pin_manager.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+class Profile;
+
+namespace ash::settings {
+
+// ChromeOS "Google Drive" settings page UI handler.
+class GoogleDrivePageHandler : public google_drive::mojom::PageHandler,
+                               drivefs::pinning::PinManager::Observer {
+ public:
+  GoogleDrivePageHandler(
+      mojo::PendingReceiver<google_drive::mojom::PageHandler> receiver,
+      mojo::PendingRemote<google_drive::mojom::Page> page,
+      Profile* profile);
+
+  GoogleDrivePageHandler(const GoogleDrivePageHandler&) = delete;
+  GoogleDrivePageHandler& operator=(const GoogleDrivePageHandler&) = delete;
+
+  ~GoogleDrivePageHandler() override;
+
+ private:
+  // google_drive::mojom::PageHandler:
+  void CalculateRequiredSpace() override;
+
+  // drivefs::pinning::PinManager::Observer
+  void OnProgress(const drivefs::pinning::Progress& progress) override;
+  void OnDrop() override;
+
+  void NotifyServiceUnavailable();
+  void NotifyProgress(const drivefs::pinning::Progress& progress);
+
+  drivefs::pinning::PinManager* GetPinManager();
+  raw_ptr<Profile> profile_;
+
+  mojo::Remote<google_drive::mojom::Page> page_;
+  mojo::Receiver<google_drive::mojom::PageHandler> receiver_{this};
+};
+
+}  // namespace ash::settings
+
+#endif  // CHROME_BROWSER_UI_WEBUI_SETTINGS_ASH_FILES_PAGE_GOOGLE_DRIVE_PAGE_HANDLER_H_
diff --git a/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler_factory.cc b/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler_factory.cc
new file mode 100644
index 0000000..549e754
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler_factory.cc
@@ -0,0 +1,36 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler_factory.h"
+
+#include <memory>
+#include <utility>
+
+#include "chrome/browser/ui/webui/settings/ash/files_page/mojom/google_drive_handler.mojom.h"
+
+namespace ash::settings {
+
+GoogleDrivePageHandlerFactory::GoogleDrivePageHandlerFactory(Profile* profile)
+    : profile_(profile) {}
+
+GoogleDrivePageHandlerFactory::~GoogleDrivePageHandlerFactory() = default;
+
+void GoogleDrivePageHandlerFactory::Bind(
+    mojo::PendingReceiver<google_drive::mojom::PageHandlerFactory> receiver) {
+  CHECK(!page_factory_receiver_.is_bound()) << "PageFactory already bound";
+
+  page_factory_receiver_.Bind(std::move(receiver));
+}
+
+void GoogleDrivePageHandlerFactory::CreatePageHandler(
+    mojo::PendingRemote<google_drive::mojom::Page> page,
+    mojo::PendingReceiver<google_drive::mojom::PageHandler> receiver) {
+  DCHECK(page);
+  DCHECK(!page_handler_);
+
+  page_handler_ = std::make_unique<GoogleDrivePageHandler>(
+      std::move(receiver), std::move(page), profile_);
+}
+
+}  // namespace ash::settings
diff --git a/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler_factory.h b/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler_factory.h
new file mode 100644
index 0000000..7bb854d
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler_factory.h
@@ -0,0 +1,49 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_ASH_FILES_PAGE_GOOGLE_DRIVE_PAGE_HANDLER_FACTORY_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_ASH_FILES_PAGE_GOOGLE_DRIVE_PAGE_HANDLER_FACTORY_H_
+
+#include <memory>
+
+#include "chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler.h"
+#include "chrome/browser/ui/webui/settings/ash/files_page/mojom/google_drive_handler.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+
+class Profile;
+
+namespace ash::settings {
+
+class GoogleDrivePageHandlerFactory
+    : public google_drive::mojom::PageHandlerFactory {
+ public:
+  explicit GoogleDrivePageHandlerFactory(Profile* profile);
+
+  GoogleDrivePageHandlerFactory(const GoogleDrivePageHandlerFactory&) = delete;
+  GoogleDrivePageHandlerFactory& operator=(
+      const GoogleDrivePageHandlerFactory&) = delete;
+
+  ~GoogleDrivePageHandlerFactory() override;
+
+  void Bind(
+      mojo::PendingReceiver<google_drive::mojom::PageHandlerFactory> receiver);
+
+ private:
+  // google_drive::mojom::PageHandlerFactory:
+  void CreatePageHandler(mojo::PendingRemote<google_drive::mojom::Page> page,
+                         mojo::PendingReceiver<google_drive::mojom::PageHandler>
+                             receiver) override;
+
+  raw_ptr<Profile> profile_;
+
+  std::unique_ptr<GoogleDrivePageHandler> page_handler_;
+  mojo::Receiver<google_drive::mojom::PageHandlerFactory>
+      page_factory_receiver_{this};
+};
+
+}  // namespace ash::settings
+
+#endif  // CHROME_BROWSER_UI_WEBUI_SETTINGS_ASH_FILES_PAGE_GOOGLE_DRIVE_PAGE_HANDLER_FACTORY_H_
diff --git a/chrome/browser/ui/webui/settings/ash/files_page/mojom/BUILD.gn b/chrome/browser/ui/webui/settings/ash/files_page/mojom/BUILD.gn
new file mode 100644
index 0000000..4e77d3d6
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/ash/files_page/mojom/BUILD.gn
@@ -0,0 +1,20 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/chromeos/ui_mode.gni")
+import("//mojo/public/tools/bindings/mojom.gni")
+
+assert(is_chromeos_ash)
+
+mojom("mojom") {
+  sources = [ "google_drive_handler.mojom" ]
+
+  webui_module_path = "/"
+  use_typescript_sources = true
+
+  public_deps = [
+    "//chromeos/ash/components/drivefs/mojom:pin_manager_types",
+    "//mojo/public/mojom/base",
+  ]
+}
diff --git a/chrome/browser/ui/webui/settings/ash/files_page/mojom/OWNERS b/chrome/browser/ui/webui/settings/ash/files_page/mojom/OWNERS
new file mode 100644
index 0000000..1feb514
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/ash/files_page/mojom/OWNERS
@@ -0,0 +1,4 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chrome/browser/ui/webui/settings/ash/files_page/mojom/google_drive_handler.mojom b/chrome/browser/ui/webui/settings/ash/files_page/mojom/google_drive_handler.mojom
new file mode 100644
index 0000000..db6508c
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/ash/files_page/mojom/google_drive_handler.mojom
@@ -0,0 +1,50 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module ash.settings.google_drive.mojom;
+
+import "chromeos/ash/components/drivefs/mojom/pin_manager_types.mojom";
+
+// Contains the current status of the underlying pin manager as it progress
+// through the various stages.
+struct Status {
+  // The space required to pin all the items that are in a users My drive
+  // directory, this excludes any items that are already available offline or
+  // pinned.
+  string required_space;
+
+  // The remaining space is the free disk space minus the `required_space`.
+  string remaining_space;
+
+  // The current stage the pin manager is going through.
+  drivefs.pin_manager_types.mojom.Stage stage;
+};
+
+// Lives in the browser process. A renderer uses this to create a page handler
+// that enables communication between a renderer and the browser process.
+interface PageHandlerFactory {
+  // Creates a PageHandler and connects it up to the Page.
+  CreatePageHandler(pending_remote<Page> page,
+                    pending_receiver<PageHandler> handler);
+};
+
+// Lives in the browser process. A renderer uses this to invoke methods that
+// are implemented in the browser process.
+interface PageHandler {
+  // Starts calculating the required space, updates will get sent via the `Page`
+  // method exposed below.
+  CalculateRequiredSpace();
+};
+
+// Interface for the Google drive settings page. Implemented in Javascript and
+// used by the page handler to send asynchronous updates.
+interface Page {
+  // Invoked when the underlying services (e.g. PinManager or
+  // DriveIntegrationService) go offline or are unavailable.
+  OnServiceUnavailable();
+
+  // Invoked when the status changes whilst pinning or calculating available
+  // storage.
+  OnProgress(Status status);
+};
diff --git a/chrome/browser/web_applications/test/os_integration_test_override_impl.cc b/chrome/browser/web_applications/test/os_integration_test_override_impl.cc
index 18f343cc..bddb1a18 100644
--- a/chrome/browser/web_applications/test/os_integration_test_override_impl.cc
+++ b/chrome/browser/web_applications/test/os_integration_test_override_impl.cc
@@ -737,6 +737,16 @@
   });
   SetUpdateMimeInfoDatabaseOnLinuxCallbackForTesting(std::move(callback));
 #endif
+
+#if BUILDFLAG(IS_WIN)
+  registry_override_.OverrideRegistry(HKEY_CURRENT_USER);
+  base::win::RegKey key;
+  // In a real registry, this key would exist, but since we're using
+  // hive override, it's empty, so we create this key.
+  key.Create(HKEY_CURRENT_USER,
+             L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
+             KEY_SET_VALUE);
+#endif
 }
 
 OsIntegrationTestOverrideImpl::~OsIntegrationTestOverrideImpl() {
diff --git a/chrome/browser/web_applications/test/os_integration_test_override_impl.h b/chrome/browser/web_applications/test/os_integration_test_override_impl.h
index 6aafb81..e30fe7c 100644
--- a/chrome/browser/web_applications/test/os_integration_test_override_impl.h
+++ b/chrome/browser/web_applications/test/os_integration_test_override_impl.h
@@ -27,6 +27,7 @@
 
 #if BUILDFLAG(IS_WIN)
 #include "base/containers/flat_map.h"
+#include "base/test/test_reg_util_win.h"
 #endif
 
 class Profile;
@@ -269,6 +270,10 @@
   base::ScopedTempDir quick_launch_;
   base::ScopedTempDir startup_;
 
+  // This is used to ensure any registry changes by this test don't affect other
+  // parts of the the trybot and are cleaned up.
+  registry_util::RegistryOverrideManager registry_override_;
+
   // Records all ShellLinkItems for a given AppUserModelId for handling
   // shortcuts menu registration.
   JumpListEntryMap jump_list_entry_map_;
diff --git a/chrome/browser/web_applications/test/web_app_test.cc b/chrome/browser/web_applications/test/web_app_test.cc
index 163faa6..0ee1ae9 100644
--- a/chrome/browser/web_applications/test/web_app_test.cc
+++ b/chrome/browser/web_applications/test/web_app_test.cc
@@ -7,23 +7,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
 
-#if BUILDFLAG(IS_WIN)
-#include "base/test/test_reg_util_win.h"
-#endif
-
-WebAppTest::WebAppTest() {
-#if BUILDFLAG(IS_WIN)
-  registry_override_.OverrideRegistry(HKEY_CURRENT_USER);
-  base::win::RegKey key;
-  // In a real registry, this key would exist, but since we're using
-  // hive override, it's empty, so we create this key.
-  // TODO(https://b/273981744): Move this and the registry override to the
-  // OsIntegrationTestOverride class.
-  key.Create(HKEY_CURRENT_USER,
-             L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
-             KEY_SET_VALUE);
-#endif
-}
+WebAppTest::WebAppTest() = default;
 
 void WebAppTest::SetUp() {
   ASSERT_TRUE(testing_profile_manager_.SetUp());
diff --git a/chrome/browser/web_applications/test/web_app_test.h b/chrome/browser/web_applications/test/web_app_test.h
index a24b56f..ab6f046a 100644
--- a/chrome/browser/web_applications/test/web_app_test.h
+++ b/chrome/browser/web_applications/test/web_app_test.h
@@ -11,10 +11,6 @@
 #include "chrome/test/base/testing_profile_manager.h"
 #include "content/public/test/test_renderer_host.h"
 
-#if BUILDFLAG(IS_WIN)
-#include "base/test/test_reg_util_win.h"
-#endif
-
 // Consider to implement web app specific test harness independent of
 // RenderViewHost.
 class WebAppTest : public content::RenderViewHostTestHarness {
@@ -37,12 +33,6 @@
   TestingProfileManager testing_profile_manager_{
       TestingBrowserProcess::GetGlobal()};
   raw_ptr<TestingProfile> profile_;
-
-#if BUILDFLAG(IS_WIN)
-  // This is used to ensure any registry changes by this test don't affect other
-  // parts of the the trybot and are cleaned up.
-  registry_util::RegistryOverrideManager registry_override_;
-#endif
 };
 
 #endif  // CHROME_BROWSER_WEB_APPLICATIONS_TEST_WEB_APP_TEST_H_
diff --git a/chrome/build/lacros64.pgo.txt b/chrome/build/lacros64.pgo.txt
index af6049a2..c94c615 100644
--- a/chrome/build/lacros64.pgo.txt
+++ b/chrome/build/lacros64.pgo.txt
@@ -1 +1 @@
-chrome-chromeos-amd64-generic-main-1681170847-7ab3c3d43fea3925fcc375680e698d06c7a7b401.profdata
+chrome-chromeos-amd64-generic-main-1681444487-446f36bde5408596e96963320bda12b4120a7baf.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 562cec8..86f6c79 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1681408779-a51ca6409bd52549bc0a4dfabd8d7100f1800a42.profdata
+chrome-linux-main-1681430387-176775fac18e3ca7d1d26b30841a13d7d055ad8d.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 642d6b74..486ccdb 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1681415994-3afce92f72a711deeb417a8f712f8335adf11ebb.profdata
+chrome-mac-arm-main-1681444487-40fd7b8e2ce6f51ed57ccd2c386cb8ed661155cc.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 352e127..623f2b8 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1681408779-ea51d93c73ced0c9764685b502df06d179a75775.profdata
+chrome-mac-main-1681430387-f716453bc365514fba9f3ab6db2dd14a82fbf74a.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 29c1d5b..3a9a9bc 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1681408779-df528b372f44a09535f7b91fa49ac4eea82569c9.profdata
+chrome-win32-main-1681430387-1fafc5fdfa748cdd69ec530e838e11aadfadeb7e.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 5110e28..58c41e42 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1681408779-3d41b8eead752c812455d8a446463aa32e46c96a.profdata
+chrome-win64-main-1681441189-b689e92588ae466b9d596a5009180ac8cc62b142.profdata
diff --git a/chrome/common/extensions/api/file_manager_private.idl b/chrome/common/extensions/api/file_manager_private.idl
index 2e94920..d4e3a2f 100644
--- a/chrome/common/extensions/api/file_manager_private.idl
+++ b/chrome/common/extensions/api/file_manager_private.idl
@@ -374,6 +374,30 @@
   incorrect_assignment
 };
 
+// Describes the stage the bulk pinning manager is in. This enum should be kept
+// in sync with chromeos/ash/components/drivefs/drivefs_pin_manager.h
+enum BulkPinStage {
+  // Initial stage.
+  stopped,
+
+  // Paused because of unfavorable network conditions.
+  paused,
+
+  // In-progress stages.
+  getting_free_space,
+  listing_files,
+  syncing,
+
+  // Final success stage.
+  success,
+
+  // Final error stages.
+  cannot_get_free_space,
+  cannot_list_files,
+  not_enough_space,
+  cannot_enable_docs_offline
+};
+
 // These three fields together uniquely identify a task.
 dictionary FileTaskDescriptor {
   DOMString appId;
@@ -1161,6 +1185,30 @@
   double deletionDate;
 };
 
+// The current progress of the bulk pinning manager. This is a subset of the
+// Progress struct in chromeos/ash/components/drivefs/drivefs_pin_manager.h
+dictionary BulkPinProgress {
+  // The stage the bulk pin manager is in.
+  BulkPinStage stage;
+
+  // Estimated amount of free space on the stateful partition in bytes.
+  long freeSpaceBytes;
+
+  // Estimated amount of free space required in order to successfully complete
+  // pinning.
+  long requiredSpaceBytes;
+
+  // Estimated amount of bytes remaining to be downloaded in order to
+  // successfully complete pinning.
+  long bytesToPin;
+
+  // Bytes that have been downloaded so far.
+  long pinnedBytes;
+
+  // Total number of files to pin.
+  long filesToPin;
+};
+
 // Callback that does not take arguments.
 callback SimpleCallback = void();
 
@@ -1335,6 +1383,8 @@
 
 callback ParseTrashInfoFilesCallback = void(ParsedTrashInfoFile[] files);
 
+callback GetBulkPinProgressCallback = void(BulkPinProgress progress);
+
 interface Functions {
   // Cancels file selection.
   static void cancelDialog();
@@ -1896,6 +1946,9 @@
   [nocompile]
   static void parseTrashInfoFiles([instanceOf=Entry] object[] entries,
                                   ParseTrashInfoFilesCallback callback);
+
+  // Returns the current progress of the bulk pinning manager.
+  static void getBulkPinProgress(GetBulkPinProgressCallback callback);
 };
 
 // Events supported by fileManagerPrivate API. These events are broadcasted.
diff --git a/chrome/test/data/web_apps/tab_strip_customizations.json b/chrome/test/data/web_apps/tab_strip_customizations.json
index fc3d229..411ec93 100644
--- a/chrome/test/data/web_apps/tab_strip_customizations.json
+++ b/chrome/test/data/web_apps/tab_strip_customizations.json
@@ -18,6 +18,9 @@
           "sizes": "200x200 192x192 300x300",
           "type": "image/png"
         }
+      ],
+      "scope_patterns": [
+        {"pathname": "/:foo/title_appname_prefix.html"}
       ]
     },
     "new_tab_button": {
diff --git a/chrome/test/data/web_apps/tab_strip_fixed_home_scope.json b/chrome/test/data/web_apps/tab_strip_fixed_home_scope.json
new file mode 100644
index 0000000..3e278f7
--- /dev/null
+++ b/chrome/test/data/web_apps/tab_strip_fixed_home_scope.json
@@ -0,0 +1,21 @@
+{
+  "name": "Manifest with tab strip customizations",
+  "icons": [
+    {
+      "src": "basic-192.png",
+      "sizes": "192x192",
+      "type": "image/png"
+    }
+  ],
+  "start_url": "get_manifest.html",
+  "display": "standalone",
+  "display_override": [ "tabbed" ],
+  "tab_strip": {
+    "home_tab": {
+      "scope_patterns": [
+        {"pathname": "/web_apps/tab_strip_customizations.html"},
+        {"pathname": "/web_apps/title_appname_prefix.html"}
+      ]
+    }
+  }
+}
diff --git a/chrome/test/data/web_apps/tab_strip_wildcard_home_scope.json b/chrome/test/data/web_apps/tab_strip_wildcard_home_scope.json
new file mode 100644
index 0000000..8abe56a
--- /dev/null
+++ b/chrome/test/data/web_apps/tab_strip_wildcard_home_scope.json
@@ -0,0 +1,21 @@
+{
+  "name": "Manifest with tab strip customizations",
+  "icons": [
+    {
+      "src": "basic-192.png",
+      "sizes": "192x192",
+      "type": "image/png"
+    }
+  ],
+  "start_url": "/web_apps/get_manifest.html",
+  "scope": "/",
+  "display": "standalone",
+  "display_override": [ "tabbed" ],
+  "tab_strip": {
+    "home_tab": {
+      "scope_patterns": [
+        {"pathname": "/web_apps/*"}
+      ]
+    }
+  }
+}
diff --git a/chrome/test/data/webui/new_tab_page/modules/history_clusters/module_test.ts b/chrome/test/data/webui/new_tab_page/modules/history_clusters/module_test.ts
index 0992dbe..3e541e0 100644
--- a/chrome/test/data/webui/new_tab_page/modules/history_clusters/module_test.ts
+++ b/chrome/test/data/webui/new_tab_page/modules/history_clusters/module_test.ts
@@ -6,7 +6,7 @@
 
 import {Cluster, URLVisit} from 'chrome://new-tab-page/history_cluster_types.mojom-webui.js';
 import {PageHandlerRemote} from 'chrome://new-tab-page/history_clusters.mojom-webui.js';
-import {DismissModuleEvent, HistoryClusterElementType, HistoryClusterImageDisplayState, HistoryClusterLayoutType, historyClustersDescriptor, HistoryClustersModuleElement, HistoryClustersProxyImpl, LAYOUT_1_MIN_IMAGE_VISITS, LAYOUT_1_MIN_VISITS, LAYOUT_2_MIN_IMAGE_VISITS, LAYOUT_2_MIN_VISITS, LAYOUT_3_MIN_IMAGE_VISITS, LAYOUT_3_MIN_VISITS, MIN_RELATED_SEARCHES, PageImageServiceBrowserProxy} from 'chrome://new-tab-page/lazy_load.js';
+import {DismissModuleEvent, HistoryClusterElementType, HistoryClusterImageDisplayState, HistoryClusterLayoutType, historyClustersDescriptor, HistoryClustersModuleElement, HistoryClustersProxyImpl, LAYOUT_1_MIN_IMAGE_VISITS, LAYOUT_1_MIN_VISITS, LAYOUT_2_MIN_IMAGE_VISITS, LAYOUT_2_MIN_VISITS, LAYOUT_3_MIN_IMAGE_VISITS, LAYOUT_3_MIN_VISITS, PageImageServiceBrowserProxy} from 'chrome://new-tab-page/lazy_load.js';
 import {$$} from 'chrome://new-tab-page/new_tab_page.js';
 import {PageImageServiceHandlerRemote} from 'chrome://resources/cr_components/page_image_service/page_image_service.mojom-webui.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
@@ -18,7 +18,7 @@
 
 import {installMock} from '../../test_support.js';
 
-import {createRelatedSearches, createSampleVisits, GOOGLE_SEARCH_BASE_URL} from './test_support.js';
+import {createRelatedSearches, createSampleVisits, GOOGLE_SEARCH_BASE_URL, MIN_RELATED_SEARCHES} from './test_support.js';
 
 const DISPLAY_LAYOUT_METRIC_NAME = 'NewTabPage.HistoryClusters.DisplayLayout';
 
@@ -89,12 +89,12 @@
     metrics = fakeMetricsPrivate();
   });
 
-  async function initializeModule(cluster: Cluster|
-                                  null): Promise<HistoryClustersModuleElement> {
-    handler.setResultFor('getCluster', Promise.resolve({cluster: cluster}));
+  async function initializeModule(clusters: Cluster[]):
+      Promise<HistoryClustersModuleElement> {
+    handler.setResultFor('getClusters', Promise.resolve({clusters}));
     const moduleElement = await historyClustersDescriptor.initialize(0) as
         HistoryClustersModuleElement;
-    await handler.whenCalled('getCluster');
+    await handler.whenCalled('getClusters');
     document.body.append(moduleElement);
     await waitAfterNextRender(moduleElement);
     return moduleElement;
@@ -103,7 +103,7 @@
   suite('core', () => {
     test('No module created if no history cluster data', async () => {
       // Arrange.
-      const moduleElement = await initializeModule(null);
+      const moduleElement = await initializeModule([]);
 
       // Assert.
       assertEquals(null, moduleElement);
@@ -119,30 +119,16 @@
       const cluster: Partial<Cluster> = {
         visits: createSampleVisits(2, 0),
       };
-      const moduleElement = await initializeModule(createSampleCluster(
-          HistoryClusterLayoutType.NONE, undefined, cluster));
+      const moduleElement = await initializeModule([createSampleCluster(
+          HistoryClusterLayoutType.NONE, undefined, cluster)]);
 
       // Assert.
       assertEquals(null, moduleElement);
     });
 
-    test('No module created when less than min related searches', async () => {
-      // Arrange.
-      const moduleElement = await initializeModule(
-          createSampleCluster(undefined, MIN_RELATED_SEARCHES - 1));
-
-      // Assert.
-      assertEquals(null, moduleElement);
-      assertEquals(1, metrics.count(DISPLAY_LAYOUT_METRIC_NAME));
-      assertEquals(
-          1,
-          metrics.count(
-              DISPLAY_LAYOUT_METRIC_NAME, HistoryClusterLayoutType.NONE));
-    });
-
     test('Layout 1 is used', async () => {
       // Arrange.
-      const moduleElement = await initializeModule(createSampleCluster());
+      const moduleElement = await initializeModule([createSampleCluster()]);
 
       // Assert.
       assertTrue(!!moduleElement);
@@ -167,7 +153,7 @@
     test('Layout 2 is used', async () => {
       // Arrange.
       const moduleElement = await initializeModule(
-          createSampleCluster(HistoryClusterLayoutType.LAYOUT_2));
+          [createSampleCluster(HistoryClusterLayoutType.LAYOUT_2)]);
 
       // Assert.
       assertTrue(!!moduleElement);
@@ -192,7 +178,7 @@
     test('Layout 3 is used', async () => {
       // Arrange.
       const moduleElement = await initializeModule(
-          createSampleCluster(HistoryClusterLayoutType.LAYOUT_3));
+          [createSampleCluster(HistoryClusterLayoutType.LAYOUT_3)]);
 
       // Assert.
       assertTrue(!!moduleElement);
@@ -217,8 +203,8 @@
     test('Header element populated with correct data', async () => {
       // Arrange.
       const sampleClusterLabel = '"Sample Journey"';
-      const moduleElement = await initializeModule(createSampleCluster(
-          undefined, undefined, {label: sampleClusterLabel}));
+      const moduleElement = await initializeModule([createSampleCluster(
+          undefined, undefined, {label: sampleClusterLabel})]);
 
       // Assert.
       assertTrue(!!moduleElement);
@@ -235,8 +221,8 @@
     test('Header info button click opens info dialog', async () => {
       // Arrange.
       const sampleClusterLabel = '"Sample Journey"';
-      const moduleElement = await initializeModule(createSampleCluster(
-          undefined, undefined, {label: sampleClusterLabel}));
+      const moduleElement = await initializeModule([createSampleCluster(
+          undefined, undefined, {label: sampleClusterLabel})]);
 
       // Act.
       assertTrue(!!moduleElement);
@@ -252,8 +238,8 @@
     test('Backend is notified when Show all button is triggered', async () => {
       const sampleClusterUnquotedLabel = 'Sample Journey';
       const sampleClusterLabel = `"${sampleClusterUnquotedLabel}"`;
-      const moduleElement = await initializeModule(createSampleCluster(
-          undefined, MIN_RELATED_SEARCHES, {label: sampleClusterLabel}));
+      const moduleElement = await initializeModule([createSampleCluster(
+          undefined, MIN_RELATED_SEARCHES, {label: sampleClusterLabel})]);
       assertTrue(!!moduleElement);
 
       const headerElement = $$(moduleElement, 'ntp-module-header');
@@ -282,7 +268,7 @@
         async () => {
           const sampleCluster =
               createSampleCluster(HistoryClusterLayoutType.LAYOUT_1);
-          const moduleElement = await initializeModule(sampleCluster);
+          const moduleElement = await initializeModule([sampleCluster]);
           assertTrue(!!moduleElement);
 
           const openAllButton =
@@ -306,7 +292,7 @@
       const sampleClusterLabel = '"Sample Journey"';
       const sampleCluster = createSampleCluster(
           undefined, undefined, {label: sampleClusterLabel});
-      const moduleElement = await initializeModule(sampleCluster);
+      const moduleElement = await initializeModule([sampleCluster]);
       assertTrue(!!moduleElement);
 
       // Act.
@@ -334,7 +320,7 @@
           test('Module produces visit tile click metrics', async () => {
             // Arrange.
             const moduleElement =
-                await initializeModule(createSampleCluster(layoutType));
+                await initializeModule([createSampleCluster(layoutType)]);
 
             // Assert.
             assertTrue(!!moduleElement);
@@ -361,7 +347,7 @@
           test('Module produces suggest tile click metrics', async () => {
             // Arrange.
             const moduleElement =
-                await initializeModule(createSampleCluster(layoutType));
+                await initializeModule([createSampleCluster(layoutType)]);
 
             // Assert.
             assertTrue(!!moduleElement);
@@ -393,7 +379,7 @@
           'getPageImageUrl', Promise.resolve(null));
 
       const moduleElement = await initializeModule(
-          createSampleCluster(HistoryClusterLayoutType.LAYOUT_1));
+          [createSampleCluster(HistoryClusterLayoutType.LAYOUT_1)]);
       assertTrue(!!moduleElement);
       await waitAfterNextRender(moduleElement);
 
@@ -420,7 +406,7 @@
       }));
 
       const moduleElement = await initializeModule(
-          createSampleCluster(HistoryClusterLayoutType.LAYOUT_1));
+          [createSampleCluster(HistoryClusterLayoutType.LAYOUT_1)]);
       assertTrue(!!moduleElement);
       await waitAfterNextRender(moduleElement);
 
diff --git a/chrome/test/data/webui/new_tab_page/modules/history_clusters/suggest_tile_test.ts b/chrome/test/data/webui/new_tab_page/modules/history_clusters/suggest_tile_test.ts
index b9de439..584942e2 100644
--- a/chrome/test/data/webui/new_tab_page/modules/history_clusters/suggest_tile_test.ts
+++ b/chrome/test/data/webui/new_tab_page/modules/history_clusters/suggest_tile_test.ts
@@ -4,12 +4,12 @@
 
 import 'chrome://webui-test/mojo_webui_test_support.js';
 
-import {MIN_RELATED_SEARCHES, SuggestTileModuleElement} from 'chrome://new-tab-page/lazy_load.js';
+import {SuggestTileModuleElement} from 'chrome://new-tab-page/lazy_load.js';
 import {$$} from 'chrome://new-tab-page/new_tab_page.js';
 import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {createRelatedSearches} from './test_support.js';
+import {createRelatedSearches, MIN_RELATED_SEARCHES} from './test_support.js';
 
 suite('NewTabPageModulesHistoryClustersModuleSuggestTileTest', () => {
   let suggestTileElement: SuggestTileModuleElement;
diff --git a/chrome/test/data/webui/new_tab_page/modules/history_clusters/test_support.ts b/chrome/test/data/webui/new_tab_page/modules/history_clusters/test_support.ts
index 3c9c83f..ea1ba05 100644
--- a/chrome/test/data/webui/new_tab_page/modules/history_clusters/test_support.ts
+++ b/chrome/test/data/webui/new_tab_page/modules/history_clusters/test_support.ts
@@ -3,7 +3,9 @@
 // found in the LICENSE file.
 
 import {SearchQuery, URLVisit} from 'chrome://new-tab-page/history_cluster_types.mojom-webui.js';
-import {LAYOUT_1_MIN_IMAGE_VISITS, LAYOUT_1_MIN_VISITS, MIN_RELATED_SEARCHES} from 'chrome://new-tab-page/lazy_load.js';
+import {LAYOUT_1_MIN_IMAGE_VISITS, LAYOUT_1_MIN_VISITS} from 'chrome://new-tab-page/lazy_load.js';
+
+export const MIN_RELATED_SEARCHES = 3;
 
 export function createVisit(overrides?: Partial<URLVisit>): URLVisit {
   return Object.assign(
diff --git a/chrome/test/data/webui/password_manager/BUILD.gn b/chrome/test/data/webui/password_manager/BUILD.gn
index cec4caa..bfc6a36 100644
--- a/chrome/test/data/webui/password_manager/BUILD.gn
+++ b/chrome/test/data/webui/password_manager/BUILD.gn
@@ -31,6 +31,9 @@
     "test_sync_browser_proxy.ts",
     "test_util.ts",
   ]
+  if (is_win || is_mac) {
+    files += [ "test_passkeys_browser_proxy.ts" ]
+  }
   if (is_chrome_branded) {
     files += [ "promo_cards_test.ts" ]
   }
diff --git a/chrome/test/data/webui/password_manager/settings_section_test.ts b/chrome/test/data/webui/password_manager/settings_section_test.ts
index 371613c..71940dc 100644
--- a/chrome/test/data/webui/password_manager/settings_section_test.ts
+++ b/chrome/test/data/webui/password_manager/settings_section_test.ts
@@ -17,6 +17,14 @@
 import {TestSyncBrowserProxy} from './test_sync_browser_proxy.js';
 import {createBlockedSiteEntry, createPasswordEntry, makePasswordManagerPrefs} from './test_util.js';
 
+// clang-format off
+// <if expr="is_win or is_macosx">
+import {PasskeysBrowserProxyImpl} from 'chrome://password-manager/password_manager.js';
+
+import {TestPasskeysBrowserProxy} from './test_passkeys_browser_proxy.js';
+// </if>
+// clang-format on
+
 /**
  * Helper method that validates a that elements in the exception list match
  * the expected data.
@@ -38,6 +46,9 @@
   let passwordManager: TestPasswordManagerProxy;
   let openWindowProxy: TestOpenWindowProxy;
   let syncProxy: TestSyncBrowserProxy;
+  // <if expr="is_win or is_macosx">
+  let passkeysProxy: TestPasskeysBrowserProxy;
+  // </if>
 
   setup(function() {
     document.body.innerHTML = window.trustedTypes!.emptyHTML;
@@ -47,6 +58,10 @@
     OpenWindowProxyImpl.setInstance(openWindowProxy);
     syncProxy = new TestSyncBrowserProxy();
     SyncBrowserProxyImpl.setInstance(syncProxy);
+    // <if expr="is_win or is_macosx">
+    passkeysProxy = new TestPasskeysBrowserProxy();
+    PasskeysBrowserProxyImpl.setInstance(passkeysProxy);
+    // </if>
   });
 
   test('pref value displayed in the UI', async function() {
@@ -370,4 +385,29 @@
             !!settings.shadowRoot!.querySelector<PrefToggleButtonElement>(
                 '#accountStorageToggle'));
       });
+
+  // <if expr="is_win or is_macosx">
+  test('managePasskeysNotShownWithoutPasskeys', async function() {
+    passkeysProxy.passkeysPresent = false;
+    const settings = document.createElement('settings-section');
+    document.body.appendChild(settings);
+    await passkeysProxy.whenCalled('passkeysHasPasskeys');
+    flush();
+    assertFalse(isVisible(settings.$.managePasskeysRow));
+  });
+
+  test('managePasskeysShownWhenNeeded', async function() {
+    passkeysProxy.passkeysPresent = true;
+    const settings = document.createElement('settings-section');
+    document.body.appendChild(settings);
+    await passkeysProxy.whenCalled('passkeysHasPasskeys');
+    flush();
+    const row = settings.$.managePasskeysRow;
+    assertTrue(isVisible(row));
+
+    row.click();
+    const url = await openWindowProxy.whenCalled('openUrl');
+    assertEquals('chrome://settings/passkeys', url);
+  });
+  // </if>
 });
diff --git a/chrome/test/data/webui/password_manager/test_passkeys_browser_proxy.ts b/chrome/test/data/webui/password_manager/test_passkeys_browser_proxy.ts
new file mode 100644
index 0000000..e1d4bbf
--- /dev/null
+++ b/chrome/test/data/webui/password_manager/test_passkeys_browser_proxy.ts
@@ -0,0 +1,24 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/** @fileoverview Test implementation of PasskeysBrowserProxy. */
+
+import {PasskeysBrowserProxy} from 'chrome://password-manager/password_manager.js';
+import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
+
+export class TestPasskeysBrowserProxy extends TestBrowserProxy implements
+    PasskeysBrowserProxy {
+  passkeysPresent: boolean = false;
+
+  constructor() {
+    super([
+      'passkeysHasPasskeys',
+    ]);
+  }
+
+  hasPasskeys(): Promise<boolean> {
+    this.methodCalled('passkeysHasPasskeys');
+    return Promise.resolve(this.passkeysPresent);
+  }
+}
diff --git a/chrome/test/data/webui/settings/chromeos/BUILD.gn b/chrome/test/data/webui/settings/chromeos/BUILD.gn
index 8477214e..683e7c4d 100644
--- a/chrome/test/data/webui/settings/chromeos/BUILD.gn
+++ b/chrome/test/data/webui/settings/chromeos/BUILD.gn
@@ -73,11 +73,6 @@
     "manage_users_subpage_tests.js",
     "multidevice_feature_item_tests.js",
     "multidevice_feature_toggle_tests.js",
-    "multidevice_notification_access_setup_dialog_tests.js",
-    "multidevice_page_tests.js",
-    "multidevice_permissions_setup_dialog_tests.js",
-    "multidevice_smartlock_item_test.js",
-    "multidevice_subpage_tests.js",
     "multidevice_task_continuation_disabled_link_tests.js",
     "multidevice_task_continuation_item_tests.js",
     "multidevice_wifi_sync_disabled_link_tests.js",
@@ -126,7 +121,6 @@
     "test_guest_os_browser_proxy.js",
     "test_kerberos_accounts_browser_proxy.js",
     "test_metrics_consent_browser_proxy.js",
-    "test_multidevice_browser_proxy.js",
     "test_os_languages_browser_proxy.js",
     "test_os_languages_metrics_proxy.js",
     "test_os_lifetime_browser_proxy.js",
@@ -198,8 +192,14 @@
 
     "keyboard_shortcut_banner/keyboard_shortcut_banner_test.ts",
 
+    "multidevice_page/multidevice_page_tests.js",
     "multidevice_page/multidevice_combined_setup_item_tests.ts",
+    "multidevice_page/multidevice_notification_access_setup_dialog_tests.js",
+    "multidevice_page/multidevice_permissions_setup_dialog_tests.js",
+    "multidevice_page/multidevice_smartlock_item_test.ts",
+    "multidevice_page/multidevice_subpage_tests.js",
     "multidevice_page/multidevice_wifi_sync_item_tests.ts",
+    "multidevice_page/test_multidevice_browser_proxy.ts",
 
     "nearby_share_page/nearby_share_confirm_page_test.ts",
     "nearby_share_page/nearby_share_high_visibility_page_test.ts",
diff --git a/chrome/test/data/webui/settings/chromeos/cellular_networks_list_test.js b/chrome/test/data/webui/settings/chromeos/cellular_networks_list_test.js
index d9e4bda..982e38b 100644
--- a/chrome/test/data/webui/settings/chromeos/cellular_networks_list_test.js
+++ b/chrome/test/data/webui/settings/chromeos/cellular_networks_list_test.js
@@ -18,7 +18,7 @@
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 import {eventToPromise} from 'chrome://webui-test/test_util.js';
 
-import {TestMultideviceBrowserProxy} from './test_multidevice_browser_proxy.js';
+import {TestMultideviceBrowserProxy} from './multidevice_page/test_multidevice_browser_proxy.js';
 
 suite('CellularNetworksList', function() {
   let cellularNetworkList;
diff --git a/chrome/test/data/webui/settings/chromeos/multidevice_notification_access_setup_dialog_tests.js b/chrome/test/data/webui/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog_tests.js
similarity index 96%
rename from chrome/test/data/webui/settings/chromeos/multidevice_notification_access_setup_dialog_tests.js
rename to chrome/test/data/webui/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog_tests.js
index ed44f5b..f08093e 100644
--- a/chrome/test/data/webui/settings/chromeos/multidevice_notification_access_setup_dialog_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog_tests.js
@@ -6,7 +6,6 @@
 import {assert} from 'chrome://resources/ash/common/assert.js';
 import {webUIListenerCallback} from 'chrome://resources/ash/common/cr.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 
 import {TestMultideviceBrowserProxy} from './test_multidevice_browser_proxy.js';
@@ -44,9 +43,8 @@
     browserProxy = new TestMultideviceBrowserProxy();
     MultiDeviceBrowserProxyImpl.setInstanceForTesting(browserProxy);
 
-    notificationAccessSetupDialog =
-        document.createElement(
-            'settings-multidevice-notification-access-setup-dialog');
+    notificationAccessSetupDialog = document.createElement(
+        'settings-multidevice-notification-access-setup-dialog');
     document.body.appendChild(notificationAccessSetupDialog);
     flush();
     buttonContainer =
@@ -64,7 +62,7 @@
     assertEquals(browserProxy.getCallCount('attemptNotificationSetup'), 1);
 
     simulateStatusChanged(
-      NotificationAccessSetupOperationStatus.CONNECTION_REQUESTED);
+        NotificationAccessSetupOperationStatus.CONNECTION_REQUESTED);
     assertTrue(isSetupInstructionsShownSeparately());
     assertTrue(!!buttonContainer.querySelector('#cancelButton'));
     assertFalse(!!buttonContainer.querySelector('#getStartedButton'));
@@ -78,8 +76,8 @@
     assertFalse(!!buttonContainer.querySelector('#doneButton'));
     assertFalse(!!buttonContainer.querySelector('#tryAgainButton'));
 
-    simulateStatusChanged(NotificationAccessSetupOperationStatus.
-        SENT_MESSAGE_TO_PHONE_AND_WAITING_FOR_RESPONSE);
+    simulateStatusChanged(NotificationAccessSetupOperationStatus
+                              .SENT_MESSAGE_TO_PHONE_AND_WAITING_FOR_RESPONSE);
     assertTrue(isSetupInstructionsShownSeparately());
     assertTrue(!!buttonContainer.querySelector('#cancelButton'));
     assertFalse(!!buttonContainer.querySelector('#getStartedButton'));
diff --git a/chrome/test/data/webui/settings/chromeos/multidevice_page_tests.js b/chrome/test/data/webui/settings/chromeos/multidevice_page/multidevice_page_tests.js
similarity index 99%
rename from chrome/test/data/webui/settings/chromeos/multidevice_page_tests.js
rename to chrome/test/data/webui/settings/chromeos/multidevice_page/multidevice_page_tests.js
index db0b255..98426b2 100644
--- a/chrome/test/data/webui/settings/chromeos/multidevice_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/multidevice_page/multidevice_page_tests.js
@@ -287,7 +287,7 @@
     PolymerTest.clearBody();
     browserProxy = new TestMultideviceBrowserProxy();
     MultiDeviceBrowserProxyImpl.setInstanceForTesting(browserProxy);
-    browserProxy.data.notificationAccessStatus =
+    browserProxy.data_.notificationAccessStatus =
         PhoneHubFeatureAccessStatus.AVAILABLE_BUT_NOT_GRANTED;
 
     multidevicePage = document.createElement('settings-multidevice-page');
@@ -332,9 +332,9 @@
     PolymerTest.clearBody();
     browserProxy = new TestMultideviceBrowserProxy();
     MultiDeviceBrowserProxyImpl.setInstanceForTesting(browserProxy);
-    browserProxy.data.notificationAccessStatus =
+    browserProxy.data_.notificationAccessStatus =
         PhoneHubFeatureAccessStatus.AVAILABLE_BUT_NOT_GRANTED;
-    browserProxy.data.isPhoneHubPermissionsDialogSupported = true;
+    browserProxy.data_.isPhoneHubPermissionsDialogSupported = true;
 
     multidevicePage = document.createElement('settings-multidevice-page');
     assertTrue(!!multidevicePage);
diff --git a/chrome/test/data/webui/settings/chromeos/multidevice_permissions_setup_dialog_tests.js b/chrome/test/data/webui/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog_tests.js
similarity index 99%
rename from chrome/test/data/webui/settings/chromeos/multidevice_permissions_setup_dialog_tests.js
rename to chrome/test/data/webui/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog_tests.js
index 8722435..273ef205 100644
--- a/chrome/test/data/webui/settings/chromeos/multidevice_permissions_setup_dialog_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog_tests.js
@@ -6,7 +6,6 @@
 import {assert} from 'chrome://resources/ash/common/assert.js';
 import {webUIListenerCallback} from 'chrome://resources/ash/common/cr.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
 import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 
 import {TestMultideviceBrowserProxy} from './test_multidevice_browser_proxy.js';
diff --git a/chrome/test/data/webui/settings/chromeos/multidevice_page/multidevice_smartlock_item_test.ts b/chrome/test/data/webui/settings/chromeos/multidevice_page/multidevice_smartlock_item_test.ts
new file mode 100644
index 0000000..69f82011
--- /dev/null
+++ b/chrome/test/data/webui/settings/chromeos/multidevice_page/multidevice_smartlock_item_test.ts
@@ -0,0 +1,171 @@
+// Copyright 2021 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://os-settings/chromeos/lazy_load.js';
+
+import {SettingsMultideviceSmartlockItemElement} from 'chrome://os-settings/chromeos/lazy_load.js';
+import {MultiDeviceBrowserProxyImpl, MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, Router} from 'chrome://os-settings/chromeos/os_settings.js';
+import {assert} from 'chrome://resources/js/assert_ts.js';
+import {webUIListenerCallback} from 'chrome://resources/js/cr.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+
+import {createFakePageContentData, TestMultideviceBrowserProxy} from './test_multidevice_browser_proxy.js';
+
+suite('<settings-multidevice-smartlock-item>', () => {
+  let smartLockItem: SettingsMultideviceSmartlockItemElement;
+  let browserProxy: TestMultideviceBrowserProxy;
+
+  /**
+   * Sets pageContentData via WebUI Listener and flushes.
+   */
+  function setPageContentData(newPageContentData: MultiDevicePageContentData) {
+    webUIListenerCallback(
+        'settings.updateMultidevicePageContentData', newPageContentData);
+    flush();
+  }
+
+  /**
+   * Sets pageContentData to the specified mode. If it is a mode corresponding
+   * to a set host, it will set the hostDeviceName to the provided name or else
+   * default to HOST_DEVICE.
+   * @param newHostDeviceName Overrides default if |newMode|
+   *     corresponds to a set host.
+   */
+  function setHostData(
+      newMode: MultiDeviceSettingsMode, newHostDeviceName?: string): void {
+    setPageContentData(createFakePageContentData(newMode, newHostDeviceName));
+  }
+
+  function setSmartLockState(newState: MultiDeviceFeatureState) {
+    setPageContentData(Object.assign(
+        {}, smartLockItem.pageContentData, {smartLockState: newState}));
+  }
+
+  function setBetterTogetherState(newState: MultiDeviceFeatureState) {
+    setPageContentData(Object.assign(
+        {}, smartLockItem.pageContentData, {betterTogetherState: newState}));
+  }
+
+  /**
+   * @param {boolean} enabled Whether to enable or disable the feature.
+   * @return {!Promise} Promise which resolves when the state change has been
+   *     verified.
+   * @private
+   */
+  async function simulateFeatureStateChangeRequest(enabled: boolean) {
+    const token = 'token1';
+    smartLockItem.authToken = {
+      lifetimeSeconds: 300,
+      token: token,
+    };
+
+    // When the user requets a feature state change, an event with the relevant
+    // details is handled.
+    const featureToggleClickedEvent =
+        new CustomEvent('feature-toggle-clicked', {
+          bubbles: true,
+          composed: true,
+          detail: {feature: MultiDeviceFeature.SMART_LOCK, enabled},
+        });
+    smartLockItem.dispatchEvent(featureToggleClickedEvent);
+    flush();
+
+    const params = await browserProxy.whenCalled('setFeatureEnabledState');
+    assertEquals(MultiDeviceFeature.SMART_LOCK, params[0]);
+    assertEquals(enabled, params[1]);
+    assertEquals(token, params[2]);
+
+    // Reset the resolver so that setFeatureEnabledState() can be called
+    // multiple times in a test.
+    browserProxy.resetResolver('setFeatureEnabledState');
+  }
+
+  /**
+   * @param isSmartLockSignInRemoved Whether to enable or disable the
+   *     isSmartLockSignInRemoved flag.
+   * TODO(b/227674947): When Sign in with Smart Lock is removed, this function
+   * can be replaced with a normal setup() function that will automatically run
+   * before each test and not require a param.
+   */
+  function initializeElement(isSmartLockSignInRemoved: boolean = false) {
+    loadTimeData.overrideValues(
+        {'isSmartLockSignInRemoved': isSmartLockSignInRemoved});
+    browserProxy = new TestMultideviceBrowserProxy();
+    MultiDeviceBrowserProxyImpl.setInstanceForTesting(browserProxy);
+
+    smartLockItem =
+        document.createElement('settings-multidevice-smartlock-item');
+
+    document.body.appendChild(smartLockItem);
+    flush();
+
+    setHostData(MultiDeviceSettingsMode.HOST_SET_VERIFIED);
+    setBetterTogetherState(MultiDeviceFeatureState.ENABLED_BY_USER);
+    setSmartLockState(MultiDeviceFeatureState.ENABLED_BY_USER);
+
+    return browserProxy.whenCalled('getPageContentData');
+  }
+
+  teardown(() => {
+    smartLockItem.remove();
+    Router.getInstance().resetRouteForTesting();
+  });
+
+  test('settings row visibile only if host is verified', () => {
+    initializeElement();
+    for (const mode of Object.values(MultiDeviceSettingsMode)) {
+      setHostData(mode as MultiDeviceSettingsMode);
+      setBetterTogetherState(MultiDeviceFeatureState.ENABLED_BY_USER);
+      setSmartLockState(MultiDeviceFeatureState.ENABLED_BY_USER);
+      const featureItem =
+          smartLockItem.shadowRoot!.querySelector('#smartLockItem');
+      if (mode === MultiDeviceSettingsMode.HOST_SET_VERIFIED) {
+        assert(featureItem);
+      } else {
+        assertEquals(null, featureItem);
+      }
+    }
+  });
+
+  test('settings row visibile only if feature is supported', () => {
+    initializeElement();
+    let featureItem = smartLockItem.shadowRoot!.querySelector('#smartLockItem');
+    assert(featureItem);
+
+    setHostData(MultiDeviceSettingsMode.HOST_SET_VERIFIED);
+    setSmartLockState(MultiDeviceFeatureState.NOT_SUPPORTED_BY_CHROMEBOOK);
+    featureItem = smartLockItem.shadowRoot!.querySelector('#smartLockItem');
+    assertEquals(null, featureItem);
+
+    setHostData(MultiDeviceSettingsMode.HOST_SET_VERIFIED);
+    setSmartLockState(MultiDeviceFeatureState.NOT_SUPPORTED_BY_PHONE);
+    featureItem = smartLockItem.shadowRoot!.querySelector('#smartLockItem');
+    assertEquals(null, featureItem);
+  });
+
+  test('settings row visibile only if better together suite is enabled', () => {
+    initializeElement();
+    let featureItem = smartLockItem.shadowRoot!.querySelector('#smartLockItem');
+    assert(featureItem);
+    setBetterTogetherState(MultiDeviceFeatureState.DISABLED_BY_USER);
+    featureItem = smartLockItem.shadowRoot!.querySelector('#smartLockItem');
+    assertEquals(null, featureItem);
+  });
+
+  test('feature toggle click event handled', async () => {
+    initializeElement();
+    await simulateFeatureStateChangeRequest(false);
+    await simulateFeatureStateChangeRequest(true);
+  });
+
+  test('SmartLockSignInRemoved flag removes subpage', async () => {
+    initializeElement(/*isSmartLockSignInRemoved=*/ true);
+    const featureItem = smartLockItem.shadowRoot!.querySelector(
+        'settings-multidevice-feature-item');
+    assert(featureItem);
+    assertEquals(undefined, featureItem.subpageRoute);
+  });
+});
diff --git a/chrome/test/data/webui/settings/chromeos/multidevice_subpage_tests.js b/chrome/test/data/webui/settings/chromeos/multidevice_page/multidevice_subpage_tests.js
similarity index 99%
rename from chrome/test/data/webui/settings/chromeos/multidevice_subpage_tests.js
rename to chrome/test/data/webui/settings/chromeos/multidevice_page/multidevice_subpage_tests.js
index 0ef1db3..edb7a400 100644
--- a/chrome/test/data/webui/settings/chromeos/multidevice_subpage_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/multidevice_page/multidevice_subpage_tests.js
@@ -5,9 +5,8 @@
 import {MultiDeviceBrowserProxyImpl, MultiDeviceFeature, MultiDeviceFeatureState, MultiDeviceSettingsMode, PhoneHubFeatureAccessStatus, Router, routes} from 'chrome://os-settings/chromeos/os_settings.js';
 import {getDeepActiveElement} from 'chrome://resources/ash/common/util.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
-
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
 import {TestMultideviceBrowserProxy} from './test_multidevice_browser_proxy.js';
 
diff --git a/chrome/test/data/webui/settings/chromeos/multidevice_page/test_multidevice_browser_proxy.ts b/chrome/test/data/webui/settings/chromeos/multidevice_page/test_multidevice_browser_proxy.ts
new file mode 100644
index 0000000..7c581f85
--- /dev/null
+++ b/chrome/test/data/webui/settings/chromeos/multidevice_page/test_multidevice_browser_proxy.ts
@@ -0,0 +1,188 @@
+// Copyright 2018 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {AndroidSmsInfo, MultiDeviceBrowserProxy, MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, PhoneHubPermissionsSetupAction, PhoneHubPermissionsSetupFeatureCombination, PhoneHubPermissionsSetupFlowScreens} from 'chrome://os-settings/chromeos/os_settings.js';
+import {webUIListenerCallback} from 'chrome://resources/ash/common/cr.m.js';
+import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
+
+/**
+ * Default Host device for PageContentData.
+ */
+export const HOST_DEVICE = 'Pixel XL';
+
+/**
+ * Test value for messages for web permissions origin.
+ */
+export const TEST_ANDROID_SMS_ORIGIN = 'http://foo.com';
+
+/**
+ * Builds fake pageContentData for the specified mode. If it is a mode
+ * corresponding to a set host, it will set the hostDeviceName to the provided
+ * name or else default to HOST_DEVICE.
+ * @param hostDeviceName Overrides default if |mode| corresponds
+ *     to a set host.
+ */
+export function createFakePageContentData(
+    mode: MultiDeviceSettingsMode,
+    hostDeviceName?: string): MultiDevicePageContentData {
+  const pageContentData = {mode: mode} as MultiDevicePageContentData;
+  if ([
+        MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER,
+        MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION,
+        MultiDeviceSettingsMode.HOST_SET_VERIFIED,
+      ].includes(mode)) {
+    pageContentData.hostDeviceName = hostDeviceName || HOST_DEVICE;
+  }
+  return pageContentData;
+}
+
+/**
+ * Note: Only showMultiDeviceSetupDialog is used by the multidevice-page
+ * element.
+ */
+export class TestMultideviceBrowserProxy extends TestBrowserProxy implements
+    MultiDeviceBrowserProxy {
+  private data_ =
+      createFakePageContentData(MultiDeviceSettingsMode.NO_HOST_SET);
+  private androidSmsInfo_:
+      AndroidSmsInfo = {origin: TEST_ANDROID_SMS_ORIGIN, enabled: true};
+  private smartLockSignInAllowed_: boolean = true;
+
+  constructor() {
+    super([
+      'showMultiDeviceSetupDialog',
+      'getPageContentData',
+      'setFeatureEnabledState',
+      'setUpAndroidSms',
+      'getSmartLockSignInEnabled',
+      'setSmartLockSignInEnabled',
+      'getSmartLockSignInAllowed',
+      'getAndroidSmsInfo',
+      'attemptNotificationSetup',
+      'cancelNotificationSetup',
+      'attemptAppsSetup',
+      'cancelAppsSetup',
+      'attemptCombinedFeatureSetup',
+      'cancelCombinedFeatureSetup',
+      'attemptFeatureSetupConnection',
+      'cancelFeatureSetupConnection',
+      'logPhoneHubPermissionSetUpScreenAction',
+      'logPhoneHubPermissionOnboardingSetupMode',
+      'logPhoneHubPermissionOnboardingSetupResult',
+    ]);
+  }
+
+  getPageContentData(): Promise<MultiDevicePageContentData> {
+    this.methodCalled('getPageContentData');
+    return Promise.resolve(this.data_);
+  }
+
+  showMultiDeviceSetupDialog(): void {
+    this.methodCalled('showMultiDeviceSetupDialog');
+  }
+
+  setFeatureEnabledState(
+      feature: MultiDeviceFeature, enabled: boolean,
+      authToken?: string): Promise<boolean> {
+    this.methodCalled('setFeatureEnabledState', [feature, enabled, authToken]);
+    if (feature === MultiDeviceFeature.MESSAGES) {
+      this.androidSmsInfo_.enabled = enabled;
+      webUIListenerCallback(
+          'settings.onAndroidSmsInfoChange', this.androidSmsInfo_);
+    }
+    return Promise.resolve(true);
+  }
+
+  setUpAndroidSms(): void {
+    this.methodCalled('setUpAndroidSms');
+  }
+
+  getSmartLockSignInEnabled(): Promise<boolean> {
+    this.methodCalled('getSmartLockSignInEnabled');
+    return Promise.resolve(true);
+  }
+
+  setSmartLockSignInEnabled(enabled: boolean, authToken?: string): void {
+    this.methodCalled('setSmartLockSignInEnabled', [enabled, authToken]);
+    webUIListenerCallback('smart-lock-signin-enabled-changed', enabled);
+  }
+
+  getSmartLockSignInAllowed(): Promise<boolean> {
+    this.methodCalled('getSmartLockSignInAllowed');
+    return Promise.resolve(this.smartLockSignInAllowed_);
+  }
+
+  getAndroidSmsInfo(): Promise<AndroidSmsInfo> {
+    this.methodCalled('getAndroidSmsInfo');
+    return Promise.resolve(this.androidSmsInfo_);
+  }
+
+  attemptNotificationSetup(): void {
+    this.methodCalled('attemptNotificationSetup');
+  }
+
+  cancelNotificationSetup(): void {
+    this.methodCalled('cancelNotificationSetup');
+  }
+
+  attemptAppsSetup(): void {
+    this.methodCalled('attemptAppsSetup');
+  }
+
+  cancelAppsSetup(): void {
+    this.methodCalled('cancelAppsSetup');
+  }
+
+  attemptCombinedFeatureSetup(
+      showCameraRoll: boolean, showNotifications: boolean): void {
+    this.methodCalled(
+        'attemptCombinedFeatureSetup', [showCameraRoll, showNotifications]);
+  }
+
+  cancelCombinedFeatureSetup(): void {
+    this.methodCalled('cancelCombinedFeatureSetup');
+  }
+
+  attemptFeatureSetupConnection(): void {
+    this.methodCalled('attemptFeatureSetupConnection');
+  }
+
+  cancelFeatureSetupConnection(): void {
+    this.methodCalled('cancelFeatureSetupConnection');
+  }
+
+  setInstantTetheringStateForTest(state: MultiDeviceFeatureState): void {
+    this.data_.instantTetheringState = state;
+    webUIListenerCallback(
+        'settings.updateMultidevicePageContentData',
+        Object.assign({}, this.data_));
+  }
+
+  logPhoneHubPermissionSetUpScreenAction(
+      screen: PhoneHubPermissionsSetupFlowScreens,
+      action: PhoneHubPermissionsSetupAction): void {
+    this.methodCalled(
+        'logPhoneHubPermissionSetUpScreenAction', [screen, action]);
+  }
+
+  logPhoneHubPermissionSetUpButtonClicked(
+      setupMode: PhoneHubPermissionsSetupFeatureCombination): void {
+    chrome.send('logPhoneHubPermissionSetUpButtonClicked', [setupMode]);
+  }
+
+  logPhoneHubPermissionOnboardingSetupMode(
+      setupMode: PhoneHubPermissionsSetupFeatureCombination): void {
+    this.methodCalled('logPhoneHubPermissionOnboardingSetupMode', [setupMode]);
+  }
+
+  logPhoneHubPermissionOnboardingSetupResult(
+      completedMode: PhoneHubPermissionsSetupFeatureCombination): void {
+    this.methodCalled(
+        'logPhoneHubPermissionOnboardingSetupResult', [completedMode]);
+  }
+
+  removeHostDevice(): void {}
+
+  retryPendingHostSetup(): void {}
+}
diff --git a/chrome/test/data/webui/settings/chromeos/multidevice_smartlock_item_test.js b/chrome/test/data/webui/settings/chromeos/multidevice_smartlock_item_test.js
deleted file mode 100644
index 43c11ff9..0000000
--- a/chrome/test/data/webui/settings/chromeos/multidevice_smartlock_item_test.js
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'chrome://os-settings/chromeos/lazy_load.js';
-
-import {MultiDeviceBrowserProxyImpl, MultiDeviceFeature, MultiDeviceFeatureState, MultiDeviceSettingsMode, Router, routes} from 'chrome://os-settings/chromeos/os_settings.js';
-import {webUIListenerCallback} from 'chrome://resources/ash/common/cr.m.js';
-import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
-
-import {createFakePageContentData, TestMultideviceBrowserProxy} from './test_multidevice_browser_proxy.js';
-
-suite('Multidevice', function() {
-  let smartLockItem = null;
-  let browserProxy = null;
-
-  /** @type {Array<MultiDeviceSettingsMode>} */
-  let ALL_MODES;
-
-  /** @type {!Route} */
-  let initialRoute;
-
-  /**
-   * Sets pageContentData via WebUI Listener and flushes.
-   * @param {!MultiDevicePageContentData}
-   */
-  function setPageContentData(newPageContentData) {
-    webUIListenerCallback(
-        'settings.updateMultidevicePageContentData', newPageContentData);
-    flush();
-  }
-
-  /**
-   * Sets pageContentData to the specified mode. If it is a mode corresponding
-   * to a set host, it will set the hostDeviceName to the provided name or else
-   * default to HOST_DEVICE.
-   * @param {MultiDeviceSettingsMode} newMode
-   * @param {string=} opt_newHostDeviceName Overrides default if |newMode|
-   *     corresponds to a set host.
-   */
-  function setHostData(newMode, opt_newHostDeviceName) {
-    setPageContentData(
-        createFakePageContentData(newMode, opt_newHostDeviceName));
-  }
-
-  /**
-   * @param {MultiDeviceFeatureState} newState
-   */
-  function setSmartLockState(newState) {
-    setPageContentData(Object.assign(
-        {}, smartLockItem.pageContentData, {smartLockState: newState}));
-  }
-
-  /**
-   * @param {MultiDeviceFeatureState} newState
-   */
-  function setBetterTogetherState(newState) {
-    setPageContentData(Object.assign(
-        {}, smartLockItem.pageContentData, {betterTogetherState: newState}));
-  }
-
-  /**
-   * Clicks an element, and asserts that the route has changed to
-   * |expectedRoute|, then navigates back to |initialRoute|.
-   * @param {HTMLElement} element. Target of click.
-   * @param {?Route} expectedRoute. The expected current route after
-   * clicking |element|. If null, then the |initialRoute| is expected.
-   */
-  function expectRouteOnClick(element, expectedRoute) {
-    element.click();
-    flush();
-    if (expectedRoute) {
-      assertEquals(expectedRoute, Router.getInstance().currentRoute);
-      Router.getInstance().navigateTo(initialRoute);
-    }
-    assertEquals(initialRoute, Router.getInstance().currentRoute);
-  }
-
-  /**
-   * @param {boolean} enabled Whether to enable or disable the feature.
-   * @return {!Promise} Promise which resolves when the state change has been
-   *     verified.
-   * @private
-   */
-  async function simulateFeatureStateChangeRequest(enabled) {
-    const token = 'token1';
-    smartLockItem.authToken =
-        /** @type{chrome.quickUnlockPrivate} */ {
-          lifetimeDuration: 300,
-          token: token,
-        };
-
-    // When the user requets a feature state change, an event with the relevant
-    // details is handled.
-    const featureToggleClickedEvent =
-        new CustomEvent('feature-toggle-clicked', {
-          bubbles: true,
-          composed: true,
-          detail: {feature: MultiDeviceFeature.SMART_LOCK, enabled},
-        });
-    smartLockItem.dispatchEvent(featureToggleClickedEvent);
-    flush();
-
-    const params = await browserProxy.whenCalled('setFeatureEnabledState');
-    assertEquals(MultiDeviceFeature.SMART_LOCK, params[0]);
-    assertEquals(enabled, params[1]);
-    assertEquals(token, params[2]);
-
-    // Reset the resolver so that setFeatureEnabledState() can be called
-    // multiple times in a test.
-    browserProxy.resetResolver('setFeatureEnabledState');
-  }
-
-  /**
-   * @param {?boolean} isSmartLockSignInRemoved Whether to enable or disable the
-   *     isSmartLockSignInRemoved flag.
-   * @private
-   * TODO(b/227674947): When Sign in with Smart Lock is removed, this function
-   * can be replaced with a normal setup() function that will automatically run
-   * before each test and not require a param.
-   */
-  function initializeElement(isSmartLockSignInRemoved) {
-    loadTimeData.overrideValues(
-        {'isSmartLockSignInRemoved': !!isSmartLockSignInRemoved});
-    PolymerTest.clearBody();
-    browserProxy = new TestMultideviceBrowserProxy();
-    MultiDeviceBrowserProxyImpl.setInstanceForTesting(browserProxy);
-
-    smartLockItem =
-        document.createElement('settings-multidevice-smartlock-item');
-    assertTrue(!!smartLockItem);
-
-    document.body.appendChild(smartLockItem);
-    flush();
-
-    initialRoute = routes.LOCK_SCREEN;
-    setHostData(MultiDeviceSettingsMode.HOST_SET_VERIFIED);
-    setBetterTogetherState(MultiDeviceFeatureState.ENABLED_BY_USER);
-    setSmartLockState(MultiDeviceFeatureState.ENABLED_BY_USER);
-
-    return browserProxy.whenCalled('getPageContentData');
-  }
-
-  suiteSetup(function() {
-    ALL_MODES = Object.values(MultiDeviceSettingsMode);
-  });
-
-  teardown(function() {
-    if (smartLockItem) {
-      smartLockItem.remove();
-    }
-    Router.getInstance().resetRouteForTesting();
-  });
-
-  test('settings row visibile only if host is verified', function() {
-    initializeElement();
-    for (const mode of ALL_MODES) {
-      setHostData(mode);
-      setBetterTogetherState(MultiDeviceFeatureState.ENABLED_BY_USER);
-      setSmartLockState(MultiDeviceFeatureState.ENABLED_BY_USER);
-      const featureItem =
-          smartLockItem.shadowRoot.querySelector('#smartLockItem');
-      if (mode === MultiDeviceSettingsMode.HOST_SET_VERIFIED) {
-        assertTrue(!!featureItem);
-      } else {
-        assertFalse(!!featureItem);
-      }
-    }
-  });
-
-  test('settings row visibile only if feature is supported', function() {
-    initializeElement();
-    let featureItem = smartLockItem.shadowRoot.querySelector('#smartLockItem');
-    assertTrue(!!featureItem);
-
-    setHostData(MultiDeviceSettingsMode.HOST_SET_VERIFIED);
-    setSmartLockState(MultiDeviceFeatureState.NOT_SUPPORTED_BY_CHROMEBOOK);
-    featureItem = smartLockItem.shadowRoot.querySelector('#smartLockItem');
-    assertFalse(!!featureItem);
-
-    setHostData(MultiDeviceSettingsMode.HOST_SET_VERIFIED);
-    setSmartLockState(MultiDeviceFeatureState.NOT_SUPPORTED_BY_PHONE);
-    featureItem = smartLockItem.shadowRoot.querySelector('#smartLockItem');
-    assertFalse(!!featureItem);
-  });
-
-  test(
-      'settings row visibile only if better together suite is enabled',
-      function() {
-        initializeElement();
-        let featureItem =
-            smartLockItem.shadowRoot.querySelector('#smartLockItem');
-        assertTrue(!!featureItem);
-        setBetterTogetherState(MultiDeviceFeatureState.DISABLED_BY_USER);
-        featureItem = smartLockItem.shadowRoot.querySelector('#smartLockItem');
-        assertFalse(!!featureItem);
-      });
-
-  test('feature toggle click event handled', async function() {
-    initializeElement();
-    await simulateFeatureStateChangeRequest(false);
-    await simulateFeatureStateChangeRequest(true);
-  });
-
-  test('SmartLockSignInRemoved flag removes subpage', async function() {
-    initializeElement(/*isSmartLockSignInRemoved=*/ true);
-    const featureItem =
-        smartLockItem.shadowRoot.querySelector('#smartLockItem');
-    assertTrue(!!featureItem);
-    assertEquals(undefined, featureItem.subpageRoute);
-  });
-});
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
index 8b02bc8..c2a2b7b 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
@@ -364,11 +364,23 @@
  // TODO(b/208932892): Re-enable once flakiness is fixed.
  // ['MultideviceFeatureItem', 'multidevice_feature_item_tests.js'],
  ['MultideviceFeatureToggle', 'multidevice_feature_toggle_tests.js'],
+ ['MultidevicePage', 'multidevice_page/multidevice_page_tests.js'],
  [
-   'MultideviceNotificationAccessSetupDialog',
-   'multidevice_notification_access_setup_dialog_tests.js',
+   'MultidevicePageMultideviceNotificationAccessSetupDialog',
+   'multidevice_page/multidevice_notification_access_setup_dialog_tests.js',
  ],
- ['MultidevicePage', 'multidevice_page_tests.js'],
+ [
+   'MultidevicePageMultidevicePermissionsSetupDialog',
+   'multidevice_page/multidevice_permissions_setup_dialog_tests.js',
+ ],
+ [
+   'MultidevicePageMultideviceSmartlockItem',
+   'multidevice_page/multidevice_smartlock_item_test.js'
+ ],
+ [
+   'MultidevicePageMultideviceSubPage',
+   'multidevice_page/multidevice_subpage_tests.js'
+ ],
  [
    'MultiDevicePageMultideviceCombinedSetupItem',
    'multidevice_page/multidevice_combined_setup_item_tests.js'
@@ -378,12 +390,6 @@
    'multidevice_page/multidevice_wifi_sync_item_tests.js'
  ],
  [
-   'MultidevicePermissionsSetupDialog',
-   'multidevice_permissions_setup_dialog_tests.js',
- ],
- ['MultideviceSmartLockItem', 'multidevice_smartlock_item_test.js'],
- ['MultideviceSubPage', 'multidevice_subpage_tests.js'],
- [
    'MultideviceTaskContinuationItem',
    'multidevice_task_continuation_item_tests.js',
  ],
diff --git a/chrome/test/data/webui/settings/chromeos/test_multidevice_browser_proxy.js b/chrome/test/data/webui/settings/chromeos/test_multidevice_browser_proxy.js
deleted file mode 100644
index 1b53098..0000000
--- a/chrome/test/data/webui/settings/chromeos/test_multidevice_browser_proxy.js
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {MultiDeviceFeature, MultiDeviceSettingsMode} from 'chrome://os-settings/chromeos/os_settings.js';
-import {webUIListenerCallback} from 'chrome://resources/ash/common/cr.m.js';
-import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
-
-/**
- * Default Host device for PageContentData.
- */
-export const HOST_DEVICE = 'Pixel XL';
-
-/**
- * Test value for messages for web permissions origin.
- */
-export const TEST_ANDROID_SMS_ORIGIN = 'http://foo.com';
-
-/**
- * Builds fake pageContentData for the specified mode. If it is a mode
- * corresponding to a set host, it will set the hostDeviceName to the provided
- * name or else default to HOST_DEVICE.
- * @param {MultiDeviceSettingsMode} mode
- * @param {string=} opt_hostDeviceName Overrides default if |mode| corresponds
- *     to a set host.
- * @return {!MultiDevicePageContentData}
- */
-export function createFakePageContentData(mode, opt_hostDeviceName) {
-  const pageContentData = {mode: mode};
-  if ([
-        MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER,
-        MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION,
-        MultiDeviceSettingsMode.HOST_SET_VERIFIED,
-      ].includes(mode)) {
-    pageContentData.hostDeviceName = opt_hostDeviceName || HOST_DEVICE;
-  }
-  return pageContentData;
-}
-
-/**
- * @implements {MultideviceBrowserProxy}
- * Note: Only showMultiDeviceSetupDialog is used by the multidevice-page
- * element.
- */
-export class TestMultideviceBrowserProxy extends TestBrowserProxy {
-  constructor() {
-    super([
-      'showMultiDeviceSetupDialog',
-      'getPageContentData',
-      'setFeatureEnabledState',
-      'setUpAndroidSms',
-      'getSmartLockSignInEnabled',
-      'setSmartLockSignInEnabled',
-      'getSmartLockSignInAllowed',
-      'getAndroidSmsInfo',
-      'attemptNotificationSetup',
-      'cancelNotificationSetup',
-      'attemptAppsSetup',
-      'cancelAppsSetup',
-      'attemptCombinedFeatureSetup',
-      'cancelCombinedFeatureSetup',
-      'attemptFeatureSetupConnection',
-      'cancelFeatureSetupConnection',
-      'logPhoneHubPermissionSetUpScreenAction',
-      'logPhoneHubPermissionOnboardingSetupMode',
-      'logPhoneHubPermissionOnboardingSetupResult',
-    ]);
-    this.data = createFakePageContentData(MultiDeviceSettingsMode.NO_HOST_SET);
-    this.androidSmsInfo = {origin: TEST_ANDROID_SMS_ORIGIN, enabled: true};
-    this.smartLockSignInAllowed = true;
-  }
-
-  /** @override */
-  getPageContentData() {
-    this.methodCalled('getPageContentData');
-    return Promise.resolve(this.data);
-  }
-
-  /** @override */
-  showMultiDeviceSetupDialog() {
-    this.methodCalled('showMultiDeviceSetupDialog');
-  }
-
-  /** @override */
-  setFeatureEnabledState(feature, enabled, opt_authToken) {
-    this.methodCalled(
-        'setFeatureEnabledState', [feature, enabled, opt_authToken]);
-    if (feature === MultiDeviceFeature.MESSAGES) {
-      this.androidSmsInfo.enabled = enabled;
-      webUIListenerCallback(
-          'settings.onAndroidSmsInfoChange', this.androidSmsInfo);
-    }
-  }
-
-  /** @override */
-  setUpAndroidSms() {
-    this.methodCalled('setUpAndroidSms');
-  }
-
-  /** @override */
-  getSmartLockSignInEnabled() {
-    this.methodCalled('getSmartLockSignInEnabled');
-    return Promise.resolve(true);
-  }
-
-  /** @override */
-  setSmartLockSignInEnabled(enabled, opt_authToken) {
-    this.methodCalled('setSmartLockSignInEnabled', [enabled, opt_authToken]);
-    webUIListenerCallback('smart-lock-signin-enabled-changed', enabled);
-  }
-
-  /** @override */
-  getSmartLockSignInAllowed() {
-    this.methodCalled('getSmartLockSignInAllowed');
-    return Promise.resolve(this.smartLockSignInAllowed);
-  }
-
-  /** @override */
-  getAndroidSmsInfo() {
-    this.methodCalled('getAndroidSmsInfo');
-    return Promise.resolve(this.androidSmsInfo);
-  }
-
-  /** @override */
-  attemptNotificationSetup() {
-    this.methodCalled('attemptNotificationSetup');
-  }
-
-  /** @override */
-  cancelNotificationSetup() {
-    this.methodCalled('cancelNotificationSetup');
-  }
-
-  /** @override */
-  attemptAppsSetup() {
-    this.methodCalled('attemptAppsSetup');
-  }
-
-  /** @override */
-  cancelAppsSetup() {
-    this.methodCalled('cancelAppsSetup');
-  }
-
-  /** @override */
-  attemptCombinedFeatureSetup(cameraRoll, notifications) {
-    this.methodCalled(
-        'attemptCombinedFeatureSetup', [cameraRoll, notifications]);
-  }
-
-  /** @override */
-  cancelCombinedFeatureSetup() {
-    this.methodCalled('cancelCombinedFeatureSetup');
-  }
-
-  /** @override */
-  attemptFeatureSetupConnection() {
-    this.methodCalled('attemptFeatureSetupConnection');
-  }
-
-  /** @override */
-  cancelFeatureSetupConnection() {
-    this.methodCalled('cancelFeatureSetupConnection');
-  }
-
-  /**
-   * @param {MultiDeviceFeature} state
-   */
-  setInstantTetheringStateForTest(state) {
-    this.data.instantTetheringState = state;
-    webUIListenerCallback(
-        'settings.updateMultidevicePageContentData',
-        Object.assign({}, this.data));
-  }
-
-  /** @override */
-  logPhoneHubPermissionSetUpScreenAction(screen, action) {
-    this.methodCalled(
-        'logPhoneHubPermissionSetUpScreenAction', [screen, action]);
-  }
-
-  /** @override */
-  logPhoneHubPermissionOnboardingSetupMode(setup_mode) {
-    this.methodCalled('logPhoneHubPermissionOnboardingSetupMode', [setup_mode]);
-  }
-
-  /** @override */
-  logPhoneHubPermissionOnboardingSetupResult(completed_mode) {
-    this.methodCalled(
-        'logPhoneHubPermissionOnboardingSetupResult', [completed_mode]);
-  }
-}
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt
index 98d5e11..023b3ddae 100644
--- a/chromeos/profiles/atom.afdo.newest.txt
+++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-atom-114-5672.6-1680517341-benchmark-114.0.5703.0-r1-redacted.afdo.xz
+chromeos-chrome-amd64-atom-114-5692.0-1681124563-benchmark-114.0.5712.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt
index 6bfbca06..c9f210c 100644
--- a/chromeos/profiles/bigcore.afdo.newest.txt
+++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-bigcore-114-5672.7-1680514590-benchmark-114.0.5703.0-r1-redacted.afdo.xz
+chromeos-chrome-amd64-bigcore-114-5672.21-1681120054-benchmark-114.0.5712.0-r1-redacted.afdo.xz
diff --git a/components/offline_pages/core/background/load_termination_listener.h b/components/offline_pages/core/background/load_termination_listener.h
index 4eb6cd8..812d772 100644
--- a/components/offline_pages/core/background/load_termination_listener.h
+++ b/components/offline_pages/core/background/load_termination_listener.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_LOAD_TERMINATION_LISTENER_H_
 #define COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_LOAD_TERMINATION_LISTENER_H_
 
+#include "base/memory/raw_ptr_exclusion.h"
 #include "components/offline_pages/core/background/offliner.h"
 
 namespace offline_pages {
@@ -28,7 +29,9 @@
 
  protected:
   // Raw pointer because this class is owned by Offliner.
-  Offliner* offliner_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #constexpr-ctor-field-initializer
+  RAW_PTR_EXCLUSION Offliner* offliner_ = nullptr;
 };
 
 }  // namespace offline_pages
diff --git a/components/safe_browsing/android/safe_browsing_api_handler_bridge.h b/components/safe_browsing/android/safe_browsing_api_handler_bridge.h
index 9fd9d03..e85b202 100644
--- a/components/safe_browsing/android/safe_browsing_api_handler_bridge.h
+++ b/components/safe_browsing/android/safe_browsing_api_handler_bridge.h
@@ -11,6 +11,7 @@
 
 #include "base/android/jni_android.h"
 #include "base/functional/callback.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "components/safe_browsing/core/browser/db/v4_protocol_manager_util.h"
 
 class GURL;
@@ -56,7 +57,9 @@
   // reputation from GmsCore.
   jlong next_callback_id_ = 0;
 
-  UrlCheckInterceptor* interceptor_for_testing_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #constexpr-ctor-field-initializer
+  RAW_PTR_EXCLUSION UrlCheckInterceptor* interceptor_for_testing_ = nullptr;
 };
 
 // Interface allowing simplified interception of calls to
diff --git a/components/safe_browsing/core/common/features.cc b/components/safe_browsing/core/common/features.cc
index 65418b28..409128b 100644
--- a/components/safe_browsing/core/common/features.cc
+++ b/components/safe_browsing/core/common/features.cc
@@ -254,6 +254,10 @@
 #endif
 );
 
+BASE_FEATURE(kTailoredSecurityUpdatedMessages,
+             "TailoredSecurityUpdatedMessages",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 BASE_FEATURE(kThreatDomDetailsTagAndAttributeFeature,
              "ThreatDomDetailsTagAttributes",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/components/safe_browsing/core/common/features.h b/components/safe_browsing/core/common/features.h
index 1d87521..dd585dc 100644
--- a/components/safe_browsing/core/common/features.h
+++ b/components/safe_browsing/core/common/features.h
@@ -254,6 +254,9 @@
 // Controls whether the integration of tailored security settings is enabled.
 BASE_DECLARE_FEATURE(kTailoredSecurityIntegration);
 
+// Enable new updated strings and icons for the Tailored Security dialogs.
+BASE_DECLARE_FEATURE(kTailoredSecurityUpdatedMessages);
+
 // Specifies which non-resource HTML Elements to collect based on their tag and
 // attributes. It's a single param containing a comma-separated list of pairs.
 // For example: "tag1,id,tag1,height,tag2,foo" - this will collect elements with
diff --git a/components/services/storage/service_worker/service_worker_database.cc b/components/services/storage/service_worker/service_worker_database.cc
index e94d1f0..cd2eefd 100644
--- a/components/services/storage/service_worker/service_worker_database.cc
+++ b/components/services/storage/service_worker/service_worker_database.cc
@@ -1755,6 +1755,21 @@
                 << data.script_url() << "' and/or the storage key's origin '"
                 << key.origin() << "' are invalid or have mismatching origins.";
     // TODO(crbug.com/1423325): remove the code when the reason is clarified.
+    if (scope_url.DeprecatedGetOriginAsURL() !=
+        script_url.DeprecatedGetOriginAsURL()) {
+      GURL scope_origin = scope_url.DeprecatedGetOriginAsURL();
+      GURL script_origin = script_url.DeprecatedGetOriginAsURL();
+      base::debug::Alias(&scope_origin);
+      base::debug::Alias(&script_origin);
+      base::debug::DumpWithoutCrashing();
+    }
+    if (key.origin() != url::Origin::Create(scope_url)) {
+      url::Origin key_origin = key.origin();
+      url::Origin scope_origin = url::Origin::Create(scope_url);
+      base::debug::Alias(&key_origin);
+      base::debug::Alias(&scope_origin);
+      base::debug::DumpWithoutCrashing();
+    }
     base::debug::DumpWithoutCrashing();
     return Status::kErrorCorrupted;
   }
diff --git a/components/update_client/crx_cache.cc b/components/update_client/crx_cache.cc
index 61beabc..1d8e61a0 100644
--- a/components/update_client/crx_cache.cc
+++ b/components/update_client/crx_cache.cc
@@ -103,6 +103,10 @@
             return result;
 #endif
         }());
+    for (base::FilePath file_path = file_enum.Next(); !file_path.empty();
+         file_path = file_enum.Next()) {
+      base::DeleteFile(file_path);
+    }
   }
 }
 
diff --git a/components/webapps/browser/android/installable/installable_ambient_badge_message_controller_unittest.cc b/components/webapps/browser/android/installable/installable_ambient_badge_message_controller_unittest.cc
index 5c67cbf..03b6ca16 100644
--- a/components/webapps/browser/android/installable/installable_ambient_badge_message_controller_unittest.cc
+++ b/components/webapps/browser/android/installable/installable_ambient_badge_message_controller_unittest.cc
@@ -5,6 +5,7 @@
 #include "components/webapps/browser/android/installable/installable_ambient_badge_message_controller.h"
 
 #include "base/android/jni_android.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "components/messages/android/mock_message_dispatcher_bridge.h"
 #include "components/webapps/browser/android/installable/installable_ambient_badge_client.h"
 #include "components/webapps/browser/android/webapps_icon_utils.h"
@@ -66,7 +67,9 @@
   messages::MockMessageDispatcherBridge message_dispatcher_bridge_;
   MockInstallableAmbientBadgeClient client_mock_;
   InstallableAmbientBadgeMessageController message_controller_;
-  messages::MessageWrapper* message_wrapper_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #addr-of
+  RAW_PTR_EXCLUSION messages::MessageWrapper* message_wrapper_ = nullptr;
   SkBitmap test_icon;
 };
 
diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc
index 4e3ff63c..38c5f465 100644
--- a/content/app/content_main_runner_impl.cc
+++ b/content/app/content_main_runner_impl.cc
@@ -131,6 +131,10 @@
 #include "sandbox/mac/seatbelt_exec.h"
 #endif  // BUILDFLAG(IS_WIN)
 
+#if BUILDFLAG(IS_IOS)
+#include "base/threading/thread_restrictions.h"
+#endif  // BUILDFLAG(IS_IOS)
+
 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
 #include <signal.h>
 
@@ -1276,6 +1280,19 @@
   DCHECK(is_initialized_);
   DCHECK(!is_shutdown_);
 
+#if BUILDFLAG(IS_IOS)
+  // This would normally be handled by BrowserMainLoop shutdown, but since iOS
+  // (like Android) does not run this shutdown, we also need to ensure that we
+  // permit sync primitives during shutdown. If we don't do this, eg, tearing
+  // down test fixtures will often fail.
+  // TODO(crbug.com/800808): ideally these would both be scoped allowances.
+  // That would be one of the first step to ensure no persistent work is being
+  // done after ThreadPoolInstance::Shutdown() in order to move towards atomic
+  // shutdown.
+  base::PermanentThreadAllowance::AllowBaseSyncPrimitives();
+  base::PermanentThreadAllowance::AllowBlocking();
+#endif
+
   mojo_ipc_support_.reset();
 
   const base::CommandLine& command_line =
diff --git a/content/browser/android/overscroll_controller_android_unittest.cc b/content/browser/android/overscroll_controller_android_unittest.cc
index 5581abb..bda4755 100644
--- a/content/browser/android/overscroll_controller_android_unittest.cc
+++ b/content/browser/android/overscroll_controller_android_unittest.cc
@@ -5,6 +5,7 @@
 #include "content/browser/android/overscroll_controller_android.h"
 #include <memory>
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "cc/input/overscroll_behavior.h"
 #include "cc/layers/layer.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -111,7 +112,9 @@
 
  protected:
   raw_ptr<MockGlow> glow_;
-  MockRefresh* refresh_;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #addr-of
+  RAW_PTR_EXCLUSION MockRefresh* refresh_;
   std::unique_ptr<MockCompositor> compositor_;
   std::unique_ptr<OverscrollControllerAndroid> controller_;
   float dip_scale_;
diff --git a/content/browser/compute_pressure/compute_pressure_unittest.cc b/content/browser/compute_pressure/compute_pressure_unittest.cc
index e98baee1..3ed13129 100644
--- a/content/browser/compute_pressure/compute_pressure_unittest.cc
+++ b/content/browser/compute_pressure/compute_pressure_unittest.cc
@@ -41,9 +41,7 @@
 class PressureManagerSync {
  public:
   explicit PressureManagerSync(device::mojom::PressureManager* manager)
-      : manager_(*manager) {
-    DCHECK(manager);
-  }
+      : manager_(raw_ref<device::mojom::PressureManager>::from_ptr(manager)) {}
   ~PressureManagerSync() = default;
 
   PressureManagerSync(const PressureManagerSync&) = delete;
@@ -93,7 +91,7 @@
 
   void SetNextUpdateCallback(base::OnceClosure callback) {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    DCHECK(!update_callback_) << " already called before update received";
+    CHECK(!update_callback_) << " already called before update received";
 
     update_callback_ = std::move(callback);
   }
diff --git a/content/browser/hid/hid_service.cc b/content/browser/hid/hid_service.cc
index eccc870..3ac96a2 100644
--- a/content/browser/hid/hid_service.cc
+++ b/content/browser/hid/hid_service.cc
@@ -276,11 +276,24 @@
     std::move(callback).Run(mojo::NullRemote());
     return;
   }
+
+  auto* delegate = GetContentClient()->browser()->GetHidDelegate();
+  if (!delegate) {
+    std::move(callback).Run(mojo::NullRemote());
+    return;
+  }
+
+  auto* device_info = delegate->GetDeviceInfo(browser_context, device_guid);
+  if (!device_info ||
+      !delegate->HasDevicePermission(browser_context, origin_, *device_info)) {
+    std::move(callback).Run(mojo::NullRemote());
+    return;
+  }
+
   if (watchers_.empty()) {
     IncrementActiveFrameCount();
   }
 
-  auto* delegate = GetContentClient()->browser()->GetHidDelegate();
   delegate->IncrementConnectionCount(browser_context, origin_);
 
   mojo::PendingRemote<device::mojom::HidConnectionWatcher> watcher;
diff --git a/content/browser/hid/hid_service_unittest.cc b/content/browser/hid/hid_service_unittest.cc
index 5efc6e4..b5c57969 100644
--- a/content/browser/hid/hid_service_unittest.cc
+++ b/content/browser/hid/hid_service_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <cstddef>
 #include <memory>
 #include <vector>
 
@@ -393,6 +394,9 @@
 
   base::RunLoop run_loop;
   mojo::Remote<device::mojom::HidConnection> connection;
+  EXPECT_CALL(hid_delegate(), GetDeviceInfo)
+      .WillOnce(Return(device_info.get()));
+  EXPECT_CALL(hid_delegate(), HasDevicePermission).WillOnce(Return(true));
   EXPECT_CALL(hid_delegate(),
               IncrementConnectionCount(GetBrowserContext(service_creation_type),
                                        url::Origin::Create(GURL(kTestUrl))));
@@ -425,8 +429,9 @@
   auto service_creation_type = GetParam();
   const auto& service = GetService(service_creation_type);
 
-  // Note here no device is added into the HID manager so opening connection
+  // Note here no device is connected to the HID manager so opening connection
   // will fail.
+  auto device_info = CreateDeviceWithOneReport();
 
   mojo::PendingRemote<device::mojom::HidConnectionClient> hid_connection_client;
   connection_client()->Bind(
@@ -438,6 +443,9 @@
   mojo::Remote<device::mojom::HidConnection> connection;
   TestFuture<mojo::PendingRemote<device::mojom::HidConnection>>
       pending_remote_future;
+  EXPECT_CALL(hid_delegate(), GetDeviceInfo)
+      .WillOnce(Return(device_info.get()));
+  EXPECT_CALL(hid_delegate(), HasDevicePermission).WillOnce(Return(true));
   EXPECT_CALL(hid_delegate(),
               IncrementConnectionCount(GetBrowserContext(service_creation_type),
                                        url::Origin::Create(GURL(kTestUrl))));
@@ -478,6 +486,9 @@
 
   base::RunLoop run_loop;
   mojo::Remote<device::mojom::HidConnection> connection;
+  EXPECT_CALL(hid_delegate(), GetDeviceInfo)
+      .WillOnce(Return(device_info.get()));
+  EXPECT_CALL(hid_delegate(), HasDevicePermission).WillOnce(Return(true));
   EXPECT_CALL(hid_delegate(),
               IncrementConnectionCount(browser_context(),
                                        url::Origin::Create(GURL(kTestUrl))));
@@ -564,8 +575,6 @@
   auto device_info = device::mojom::HidDeviceInfo::New();
   device_info->guid = kTestGuid;
   ConnectDevice(*device_info);
-  EXPECT_CALL(hid_delegate(), GetDeviceInfo)
-      .WillOnce(Return(device_info.get()));
 
   // Connect the device.
   mojo::PendingRemote<device::mojom::HidConnectionClient> hid_connection_client;
@@ -576,6 +585,9 @@
 
   base::RunLoop run_loop;
   mojo::Remote<device::mojom::HidConnection> connection;
+  EXPECT_CALL(hid_delegate(), GetDeviceInfo)
+      .WillOnce(Return(device_info.get()));
+  EXPECT_CALL(hid_delegate(), HasDevicePermission).WillOnce(Return(true));
   EXPECT_CALL(hid_delegate(),
               IncrementConnectionCount(GetBrowserContext(service_creation_type),
                                        url::Origin::Create(GURL(kTestUrl))));
@@ -588,6 +600,7 @@
             run_loop.Quit();
           }));
   run_loop.Run();
+  testing::Mock::VerifyAndClearExpectations(&hid_delegate());
 
   CheckWebContentsHidServiceConnectedState(service_creation_type, true);
   EXPECT_TRUE(connection.is_connected());
@@ -596,12 +609,15 @@
   connection.set_disconnect_handler(disconnect_loop.QuitClosure());
 
   // Simulate user revoking permission.
-  EXPECT_CALL(hid_delegate(), HasDevicePermission).WillOnce(Return(false));
   url::Origin origin = url::Origin::Create(GURL(kTestUrl));
   EXPECT_CALL(hid_delegate(),
               DecrementConnectionCount(GetBrowserContext(service_creation_type),
                                        url::Origin::Create(GURL(kTestUrl))));
+  EXPECT_CALL(hid_delegate(), GetDeviceInfo)
+      .WillOnce(Return(device_info.get()));
+  EXPECT_CALL(hid_delegate(), HasDevicePermission).WillOnce(Return(false));
   hid_delegate().OnPermissionRevoked(origin);
+  testing::Mock::VerifyAndClearExpectations(&hid_delegate());
 
   disconnect_loop.Run();
   CheckWebContentsHidServiceConnectedState(service_creation_type, false);
@@ -641,6 +657,9 @@
 
   base::RunLoop run_loop;
   mojo::Remote<device::mojom::HidConnection> connection;
+  EXPECT_CALL(hid_delegate(), GetDeviceInfo)
+      .WillOnce(Return(device_info.get()));
+  EXPECT_CALL(hid_delegate(), HasDevicePermission).WillOnce(Return(true));
   EXPECT_CALL(hid_delegate(),
               IncrementConnectionCount(GetBrowserContext(service_creation_type),
                                        url::Origin::Create(GURL(kTestUrl))));
@@ -710,6 +729,9 @@
 
   base::RunLoop run_loop;
   mojo::Remote<device::mojom::HidConnection> connection;
+  EXPECT_CALL(hid_delegate(), GetDeviceInfo)
+      .WillOnce(Return(device_info.get()));
+  EXPECT_CALL(hid_delegate(), HasDevicePermission).WillOnce(Return(true));
   EXPECT_CALL(hid_delegate(),
               IncrementConnectionCount(GetBrowserContext(service_creation_type),
                                        url::Origin::Create(GURL(kTestUrl))));
@@ -790,6 +812,9 @@
 
   base::RunLoop connect_loop;
   mojo::Remote<device::mojom::HidConnection> connection;
+  EXPECT_CALL(hid_delegate(), GetDeviceInfo)
+      .WillOnce(Return(device_info.get()));
+  EXPECT_CALL(hid_delegate(), HasDevicePermission).WillOnce(Return(true));
   EXPECT_CALL(hid_delegate(),
               IncrementConnectionCount(GetBrowserContext(service_creation_type),
                                        url::Origin::Create(GURL(kTestUrl))));
@@ -874,14 +899,14 @@
   const auto& service = GetService(service_creation_type);
 
   // For now the device has permission.
-  EXPECT_CALL(hid_delegate(), HasDevicePermission).WillOnce(Return(true));
+  EXPECT_CALL(hid_delegate(), HasDevicePermission).WillRepeatedly(Return(true));
 
   // Create a new device.
   auto device_info = device::mojom::HidDeviceInfo::New();
   device_info->guid = kTestGuid;
   ConnectDevice(*device_info);
   EXPECT_CALL(hid_delegate(), GetDeviceInfo)
-      .WillOnce(Return(device_info.get()));
+      .WillRepeatedly(Return(device_info.get()));
 
   // Connect the device.
   mojo::PendingRemote<device::mojom::HidConnectionClient> hid_connection_client;
@@ -945,6 +970,8 @@
   std::vector<FakeHidConnectionClient> connection_clients(num_devices);
   EXPECT_CALL(hid_delegate(), IncrementConnectionCount).Times(num_devices);
   for (size_t device_idx = 0; device_idx < num_devices; device_idx++) {
+    EXPECT_CALL(hid_delegate(), GetDeviceInfo)
+        .WillOnce(Return(devices[device_idx].get()));
     connections.push_back(OpenDevice(service, devices[device_idx],
                                      connection_clients[device_idx]));
   }
@@ -982,6 +1009,8 @@
   std::vector<FakeHidConnectionClient> connection_clients(num_devices);
   EXPECT_CALL(hid_delegate(), IncrementConnectionCount).Times(num_devices);
   for (size_t device_idx = 0; device_idx < num_devices; device_idx++) {
+    EXPECT_CALL(hid_delegate(), GetDeviceInfo)
+        .WillOnce(Return(devices[device_idx].get()));
     connections.push_back(OpenDevice(service, devices[device_idx],
                                      connection_clients[device_idx]));
   }
@@ -1028,6 +1057,8 @@
   std::vector<FakeHidConnectionClient> connection_clients(num_devices);
   EXPECT_CALL(hid_delegate(), IncrementConnectionCount).Times(num_devices);
   for (size_t device_idx = 0; device_idx < num_devices; device_idx++) {
+    EXPECT_CALL(hid_delegate(), GetDeviceInfo)
+        .WillOnce(Return(devices[device_idx].get()));
     connections.push_back(OpenDevice(service, devices[device_idx],
                                      connection_clients[device_idx]));
   }
@@ -1164,6 +1195,9 @@
       hid_connection_client.InitWithNewPipeAndPassReceiver());
   base::RunLoop connect_loop;
   mojo::Remote<device::mojom::HidConnection> connection;
+  EXPECT_CALL(hid_delegate(), GetDeviceInfo)
+      .WillOnce(Return(device_info.get()));
+  EXPECT_CALL(hid_delegate(), HasDevicePermission).WillOnce(Return(true));
   EXPECT_CALL(hid_delegate(),
               IncrementConnectionCount(GetBrowserContext(service_creation_type),
                                        url::Origin::Create(GURL(kTestUrl))));
@@ -1323,4 +1357,34 @@
             "WebHID is not allowed from an opaque origin.");
 }
 
+TEST_P(HidServiceTest, ConnectionFailedWithoutPermission) {
+  auto service_creation_type = GetParam();
+  const auto& service = GetService(service_creation_type);
+
+  // Create a new device.
+  auto device_info = device::mojom::HidDeviceInfo::New();
+  device_info->guid = kTestGuid;
+  ConnectDevice(*device_info);
+
+  // Connect the device.
+  mojo::PendingRemote<device::mojom::HidConnectionClient> hid_connection_client;
+  connection_client()->Bind(
+      hid_connection_client.InitWithNewPipeAndPassReceiver());
+
+  CheckWebContentsHidServiceConnectedState(service_creation_type, false);
+
+  base::RunLoop run_loop;
+  mojo::Remote<device::mojom::HidConnection> connection;
+  TestFuture<mojo::PendingRemote<device::mojom::HidConnection>>
+      pending_remote_future;
+  EXPECT_CALL(hid_delegate(), GetDeviceInfo)
+      .WillOnce(Return(device_info.get()));
+  EXPECT_CALL(hid_delegate(), HasDevicePermission).WillOnce(Return(false));
+  service->Connect(kTestGuid, std::move(hid_connection_client),
+                   pending_remote_future.GetCallback());
+  EXPECT_FALSE(pending_remote_future.Take());
+  run_loop.RunUntilIdle();
+  CheckWebContentsHidServiceConnectedState(service_creation_type, false);
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/close_listener_host.cc b/content/browser/renderer_host/close_listener_host.cc
index 243f9dc6..8a852d6 100644
--- a/content/browser/renderer_host/close_listener_host.cc
+++ b/content/browser/renderer_host/close_listener_host.cc
@@ -4,7 +4,9 @@
 
 #include "content/browser/renderer_host/close_listener_host.h"
 
+#include "base/feature_list.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/features_generated.h"
 
 namespace content {
 
@@ -24,8 +26,10 @@
 }
 
 bool CloseListenerHost::SignalIfActive() {
-  if (!close_listener_)
+  if (!close_listener_ ||
+      !base::FeatureList::IsEnabled(blink::features::kCloseWatcher)) {
     return false;
+  }
   close_listener_->Signal();
   return true;
 }
diff --git a/content/browser/renderer_host/close_listener_host_browsertest.cc b/content/browser/renderer_host/close_listener_host_browsertest.cc
index 609fbc440..da08f46 100644
--- a/content/browser/renderer_host/close_listener_host_browsertest.cc
+++ b/content/browser/renderer_host/close_listener_host_browsertest.cc
@@ -4,6 +4,8 @@
 
 #include "content/browser/renderer_host/close_listener_host.h"
 
+#include "base/base_switches.h"
+#include "base/test/scoped_feature_list.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test.h"
@@ -18,6 +20,10 @@
 
 class CloseListenerHostBrowserTest : public ContentBrowserTest {
  public:
+  CloseListenerHostBrowserTest() {
+    feature_list_.InitWithFeatures({blink::features::kCloseWatcher}, {});
+  }
+
   void SetUpOnMainThread() override {
     host_resolver()->AddRule("*", "127.0.0.1");
     ASSERT_TRUE(embedded_test_server()->Start());
@@ -26,8 +32,6 @@
   void SetUpCommandLine(base::CommandLine* command_line) override {
     command_line->AppendSwitch(
         switches::kEnableExperimentalWebPlatformFeatures);
-    command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
-                                    "CloseWatcher");
   }
 
   WebContentsImpl* web_contents() const {
@@ -52,6 +56,8 @@
     watcher.AlsoWaitForTitle(signaled_title);
     EXPECT_EQ(signaled_title, watcher.WaitAndGetTitle());
   }
+
+  base::test::ScopedFeatureList feature_list_;
 };
 
 IN_PROC_BROWSER_TEST_F(CloseListenerHostBrowserTest,
diff --git a/content/browser/webrtc/resources/dump_creator.js b/content/browser/webrtc/resources/dump_creator.js
index 8b86d0b..5383364 100644
--- a/content/browser/webrtc/resources/dump_creator.js
+++ b/content/browser/webrtc/resources/dump_creator.js
@@ -27,52 +27,82 @@
      * @type {Element}
      * @private
      */
-    this.root_ = document.createElement('details');
+    this.createDumpRoot(containerElement);
+    this.createAudioRecordingRoot(containerElement);
+    this.createPacketRecordingRoot(containerElement);
+  }
 
-    this.root_.className = 'peer-connection-dump-root';
-    containerElement.appendChild(this.root_);
+  createDumpRoot(containerElement) {
+    this.dumpRoot_ = document.createElement('details');
+
+    this.dumpRoot_.className = 'peer-connection-dump-root';
+    containerElement.appendChild(this.dumpRoot_);
     const summary = document.createElement('summary');
-    this.root_.appendChild(summary);
-    summary.textContent = 'Create Dump';
+    this.dumpRoot_.appendChild(summary);
+    summary.textContent = 'Create a WebRTC-Internals dump';
     const content = document.createElement('div');
-    this.root_.appendChild(content);
-
+    this.dumpRoot_.appendChild(content);
     content.appendChild($('dump-template').content.cloneNode(true));
     content.getElementsByTagName('a')[0].addEventListener(
-        'click', this.onDownloadData_.bind(this));
-    content.getElementsByTagName('input')[1].addEventListener(
-        'click', this.onAudioDebugRecordingsChanged_.bind(this));
-    content.getElementsByTagName('input')[2].addEventListener(
+      'click', this.onDownloadData_.bind(this));
+  }
+
+  createAudioRecordingRoot(containerElement) {
+    this.audioRoot_ = document.createElement('details');
+
+    this.audioRoot_.className = 'peer-connection-dump-root';
+    containerElement.appendChild(this.audioRoot_);
+    const summary = document.createElement('summary');
+    this.audioRoot_.appendChild(summary);
+    summary.textContent = 'Create diagnostic audio recordings';
+    const content = document.createElement('div');
+    this.audioRoot_.appendChild(content);
+    content.appendChild($('audio-recording-template').content.cloneNode(true));
+    content.getElementsByTagName('input')[0].addEventListener(
+      'click', this.onAudioDebugRecordingsChanged_.bind(this));
+
+  }
+
+  createPacketRecordingRoot(containerElement) {
+    this.packetRoot_ = document.createElement('details');
+
+    this.packetRoot_.className = 'peer-connection-dump-root';
+    containerElement.appendChild(this.packetRoot_);
+    const summary = document.createElement('summary');
+    this.packetRoot_.appendChild(summary);
+    summary.textContent = 'Create diagnostic packet recordings';
+    const content = document.createElement('div');
+    this.packetRoot_.appendChild(content);
+    content.appendChild($('packet-recording-template').content.cloneNode(true));
+    content.getElementsByTagName('input')[0].addEventListener(
         'click', this.onEventLogRecordingsChanged_.bind(this));
   }
 
   // Mark the diagnostic audio recording checkbox checked.
   setAudioDebugRecordingsCheckbox() {
-    this.root_.getElementsByTagName('input')[1].checked = true;
+    this.audioRoot_.getElementsByTagName('input')[0].checked = true;
   }
 
   // Mark the diagnostic audio recording checkbox unchecked.
   clearAudioDebugRecordingsCheckbox() {
-    this.root_.getElementsByTagName('input')[1].checked = false;
+    this.audioRoot_.getElementsByTagName('input')[0].checked = false;
   }
 
   // Mark the event log recording checkbox checked.
   setEventLogRecordingsCheckbox() {
-    this.root_.getElementsByTagName('input')[2].checked = true;
+    this.packetRoot_.getElementsByTagName('input')[0].checked = true;
   }
 
   // Mark the event log recording checkbox unchecked.
   clearEventLogRecordingsCheckbox() {
-    this.root_.getElementsByTagName('input')[2].checked = false;
+    this.packetRoot_.getElementsByTagName('input')[0].checked = false;
   }
 
   // Mark the event log recording checkbox as mutable/immutable.
   setEventLogRecordingsCheckboxMutability(mutable) {
-    // TODO(eladalon): Remove reliance on number and order of elements.
-    // https://crbug.com/817391
-    this.root_.getElementsByTagName('input')[2].disabled = !mutable;
+    this.packetRoot_.getElementsByTagName('input')[0].disabled = !mutable;
     if (!mutable) {
-      const label = this.root_.getElementsByTagName('label')[2];
+      const label = this.packetRoot_.getElementsByTagName('label')[0];
       label.style = 'color:red;';
       label.textContent =
           ' WebRTC event logging\'s state was set by a command line flag.';
@@ -85,7 +115,7 @@
    * @private
    */
   async onDownloadData_(event) {
-    const useCompression = this.root_.getElementsByTagName('input')[0].checked;
+    const useCompression = this.dumpRoot_.getElementsByTagName('input')[0].checked;
     const dumpObject = {
       'getUserMedia': userMediaRequests,
       'PeerConnections': peerConnectionDataStore,
@@ -108,7 +138,7 @@
       return;
     }
     url = URL.createObjectURL(textBlob);
-    const anchor = this.root_.getElementsByTagName('a')[0];
+    const anchor = this.dumpRoot_.getElementsByTagName('a')[0];
     anchor.download = 'webrtc_internals_dump.txt'
     anchor.href = url;
     // The default action of the anchor will download the url.
@@ -120,7 +150,7 @@
    * @private
    */
   onAudioDebugRecordingsChanged_() {
-    const enabled = this.root_.getElementsByTagName('input')[1].checked;
+    const enabled = this.audioRoot_.getElementsByTagName('input')[0].checked;
     if (enabled) {
       chrome.send('enableAudioDebugRecordings');
     } else {
@@ -134,7 +164,7 @@
    * @private
    */
   onEventLogRecordingsChanged_() {
-    const enabled = this.root_.getElementsByTagName('input')[2].checked;
+    const enabled = this.packetRoot_.getElementsByTagName('input')[0].checked;
     if (enabled) {
       chrome.send('enableEventLogRecordings');
     } else {
diff --git a/content/browser/webrtc/resources/webrtc_internals.css b/content/browser/webrtc/resources/webrtc_internals.css
index 54573674..9d302afc 100644
--- a/content/browser/webrtc/resources/webrtc_internals.css
+++ b/content/browser/webrtc/resources/webrtc_internals.css
@@ -125,7 +125,7 @@
   margin: 5px 0 5px 0;
 }
 
-.audio-diagnostic-dumps-info {
+.dumps-info {
   max-width: 60em;
 }
 
diff --git a/content/browser/webrtc/resources/webrtc_internals.html b/content/browser/webrtc/resources/webrtc_internals.html
index 4d6050b5c..6ee3668 100644
--- a/content/browser/webrtc/resources/webrtc_internals.html
+++ b/content/browser/webrtc/resources/webrtc_internals.html
@@ -17,41 +17,50 @@
     <template id="td-colspan-template"><td colspan=2></td></template>
     <template id="time-event-template"><tbody><tr><th>Time</th><th class="update-log-header-event">Event</th></tr></tbody></template>
     <template id="dump-template">
-      <div>
+      <div id="dump">
         <a>
-          <button>Download the PeerConnection updates and stats data</button>
+          <button>Download the "webrtc-internals dump"</button>
         </a>
         <label>
           <input type="checkbox">Compress result
         </label>
+        <p class="dumps-info">The "webrtc-internals" dump is a JSON file containing API calls, events and getStats-like information about RTCPeerConnection objects as well as getUsermedia/getDisplayMedia API calls.</p>
       </div>
-      <p>
-        <label>
-          <input type="checkbox">Enable diagnostic audio recordings
-        </label>
-      </p>
-      <p class="audio-diagnostic-dumps-info">A diagnostic audio recording is used for analyzing audio problems. It consists of several files and contains the audio played out to the speaker (output) and captured from the microphone (input). The data is saved locally. Checking this box will enable recordings of all ongoing input and output audio streams (including non-WebRTC streams) and for future audio streams. When the box is unchecked or this page is closed, all ongoing recordings will be stopped and this recording functionality disabled. Recording audio from multiple tabs is supported as well as multiple recordings from the same tab.</p>
-      <p>When enabling, select a base filename to which the following suffixes will be added:</p>
-      <div>&lt;base filename&gt;.&lt;render process ID&gt;.aec_dump.&lt;AEC dump recording ID&gt;</div>
-      <div>&lt;base filename&gt;.input.&lt;stream recording ID&gt;.wav</div>
-      <div>&lt;base filename&gt;.output.&lt;stream recording ID&gt;.wav</div>
-      <p class="audio-diagnostic-dumps-info">It is recommended to choose a new base filename each time the feature is enabled to avoid ending up with partially overwritten or unusable audio files.</p>
-      <p>
-        <label>
-          <input type="checkbox" disabled>Enable diagnostic packet and event recording
-        </label>
-      </p>
-      <p class="audio-diagnostic-dumps-info">A diagnostic packet and event recording can be used for analyzing various issues related to thread starvation, jitter buffers or bandwidth estimation. Two types of data are logged. First, incoming and outgoing RTP headers and RTCP packets are logged. These do not include any audio or video information, nor any other types of personally identifiable information (so no IP addresses or URLs). Checking this box will enable the recording for ongoing WebRTC calls and for future WebRTC calls. When the box is unchecked or this page is closed, all ongoing recordings will be stopped and this recording functionality will be disabled for future WebRTC calls. Recording in multiple tabs or multiple recordings in the same tab will cause multiple log files to be created. When enabling, a filename for the recording can be entered. The entered filename is used as a base, to which the following suffixes will be appended.</p>
-      <p>&lt;base filename&gt;_&lt;date&gt;_&lt;timestamp&gt;_&lt;render process ID&gt;_&lt;recording ID&gt;</p>
-      <p class="audio-diagnostic-dumps-info">If a file with the same name already exists, it will be overwritten. No more than 5 logfiles  will be created, and each of them is limited to 60MB of storage.  On Android these limits are 3 files of at most 10MB each.  When the limit is reached, the checkbox must be unchecked and  rechecked to resume logging.</p>
+    </template>
+    <template id="audio-recording-template">
+      <div id="audio-recording">
+        <p>
+          <label>
+            <input type="checkbox">Enable diagnostic audio recordings
+          </label>
+        </p>
+        <p class="dumps-info">A diagnostic audio recording is used for analyzing audio problems. It consists of several files and contains the audio played out to the speaker (output) and captured from the microphone (input). The data is saved locally. Checking this box will enable recordings of all ongoing input and output audio streams (including non-WebRTC streams) and for future audio streams. When the box is unchecked or this page is closed, all ongoing recordings will be stopped and this recording functionality disabled. Recording audio from multiple tabs is supported as well as multiple recordings from the same tab.</p>
+        <p>When enabling, select a base filename to which the following suffixes will be added:</p>
+        <div>&lt;base filename&gt;.&lt;render process ID&gt;.aec_dump.&lt;AEC dump recording ID&gt;</div>
+        <div>&lt;base filename&gt;.input.&lt;stream recording ID&gt;.wav</div>
+        <div>&lt;base filename&gt;.output.&lt;stream recording ID&gt;.wav</div>
+        <p class="dumps-info">It is recommended to choose a new base filename each time the feature is enabled to avoid ending up with partially overwritten or unusable audio files.</p>
+      </div>
+    </template>
+    <template id="packet-recording-template">
+      <div id="packet-recording">
+        <p>
+          <label>
+            <input type="checkbox" disabled>Enable diagnostic packet and event recording
+          </label>
+        </p>
+        <p class="dumps-info">A diagnostic packet and event recording can be used for analyzing various issues related to thread starvation, jitter buffers or bandwidth estimation. Two types of data are logged. First, incoming and outgoing RTP headers and RTCP packets are logged. These do not include any audio or video information, nor any other types of personally identifiable information (so no IP addresses or URLs). Checking this box will enable the recording for ongoing WebRTC calls and for future WebRTC calls. When the box is unchecked or this page is closed, all ongoing recordings will be stopped and this recording functionality will be disabled for future WebRTC calls. Recording in multiple tabs or multiple recordings in the same tab will cause multiple log files to be created. When enabling, a filename for the recording can be entered. The entered filename is used as a base, to which the following suffixes will be appended.</p>
+        <p>&lt;base filename&gt;_&lt;date&gt;_&lt;timestamp&gt;_&lt;render process ID&gt;_&lt;recording ID&gt;</p>
+        <p class="dumps-info">If a file with the same name already exists, it will be overwritten. No more than 5 logfiles  will be created, and each of them is limited to 60MB of storage.  On Android these limits are 3 files of at most 10MB each.  When the limit is reached, the checkbox must be unchecked and  rechecked to resume logging.</p>
+      </div>
     </template>
     <template id="stats-template">
       <div>
-        Read stats From:
+        Read stats from:
         <select id="statsSelectElement">
         </select>
         <p><b>Note:</b> computed stats are in []. Experimental stats are marked with an * at the end and do not show up in the getStats result.</p>
-        <p id="legacy-stats-warning"><b>Note:</b> the callback-based getStats API and many of its goog-prefixed values are non-standard and may be removed from the getStats() API in the future.</p>
+        <p id="legacy-stats-warning"><b>Note:</b> the callback-based getStats API and many of its goog-prefixed values are non-standard. The API is deprecated and <a href="https://groups.google.com/g/discuss-webrtc/c/EmcOEY2gj6w/m/EcTFK_cQAgAJ">scheduled for removal in M117</a>.</p>
       </div>
     </template>
   </body>
diff --git a/content/browser/webrtc/resources/webrtc_internals.js b/content/browser/webrtc/resources/webrtc_internals.js
index 29e25ce..68ddeda 100644
--- a/content/browser/webrtc/resources/webrtc_internals.js
+++ b/content/browser/webrtc/resources/webrtc_internals.js
@@ -107,6 +107,7 @@
 
 function initialize() {
   dumpCreator = new DumpCreator($('content-root'));
+
   $('content-root').appendChild(createStatsSelectionOptionElements());
   tabView = new TabView($('content-root'));
   ssrcInfoManager = new SsrcInfoManager();
diff --git a/device/bluetooth/bluetooth_low_energy_central_manager_delegate.mm b/device/bluetooth/bluetooth_low_energy_central_manager_delegate.mm
index 41dfbda2..ce8e20a2 100644
--- a/device/bluetooth/bluetooth_low_energy_central_manager_delegate.mm
+++ b/device/bluetooth/bluetooth_low_energy_central_manager_delegate.mm
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/memory/raw_ptr.h"
+#include "build/build_config.h"
 #include "device/bluetooth/bluetooth_low_energy_adapter_apple.h"
 #include "device/bluetooth/bluetooth_low_energy_discovery_manager_mac.h"
 
@@ -31,7 +32,11 @@
                                              rssi);
   }
 
-  void UpdatedState() {
+  void UpdatedState(bool powered) {
+#if BUILDFLAG(IS_IOS)
+    // On Mac, the Bluetooth classic code notifies the power changed.
+    adapter_->NotifyAdapterPoweredChanged(powered);
+#endif
     discovery_manager_->TryStartDiscovery();
     adapter_->LowEnergyCentralManagerUpdatedState();
   }
@@ -82,7 +87,7 @@
 
 - (void)centralManagerDidUpdateState:(CBCentralManager*)central {
   // Notifies when the powered state of the central manager changed.
-  _bridge->UpdatedState();
+  _bridge->UpdatedState(central.state == CBManagerStatePoweredOn);
 }
 
 - (void)centralManager:(CBCentralManager*)central
diff --git a/device/bluetooth/floss/bluetooth_device_floss.cc b/device/bluetooth/floss/bluetooth_device_floss.cc
index c73334ee..8dffc2e2 100644
--- a/device/bluetooth/floss/bluetooth_device_floss.cc
+++ b/device/bluetooth/floss/bluetooth_device_floss.cc
@@ -554,6 +554,11 @@
 
 void BluetoothDeviceFloss::CreateGattConnectionImpl(
     absl::optional<device::BluetoothUUID> service_uuid) {
+  // Generally, the first ever connection to a device should be direct and
+  // subsequent connections to known devices should be invoked with is_direct =
+  // false. Refer to |autoConnect| on BluetoothGatt.java.
+  bool is_direct = !IsBondedImpl();
+
   if (num_connecting_calls_++ == 0)
     adapter()->NotifyDeviceChanged(this);
 
@@ -564,7 +569,7 @@
   FlossDBusManager::Get()->GetGattManagerClient()->Connect(
       base::BindOnce(&BluetoothDeviceFloss::OnConnectGatt,
                      weak_ptr_factory_.GetWeakPtr()),
-      address_, FlossDBusClient::BluetoothTransport::kLe);
+      address_, FlossDBusClient::BluetoothTransport::kLe, is_direct);
 }
 
 void BluetoothDeviceFloss::OnConnectGatt(DBusResult<Void> ret) {
@@ -590,6 +595,7 @@
 }
 
 void BluetoothDeviceFloss::DisconnectGatt() {
+  svc_resolved_ = false;
   FlossDBusManager::Get()->GetGattManagerClient()->Disconnect(base::DoNothing(),
                                                               address_);
 }
@@ -833,8 +839,10 @@
 
   svc_resolved_ = true;
 
-  // Replace the previous gatt services.
-  gatt_services_.clear();
+  // Copy the GATT services list here and clear the original so that when we
+  // send GattServiceRemoved(), GetGattServices() returns no services.
+  GattServiceMap gatt_services_swapped;
+  gatt_services_swapped.swap(gatt_services_);
 
   for (const auto& service : services) {
     BLUETOOTH_LOG(EVENT) << "Adding new remote GATT service for device: "
diff --git a/device/bluetooth/floss/bluetooth_remote_gatt_characteristic_floss.cc b/device/bluetooth/floss/bluetooth_remote_gatt_characteristic_floss.cc
index 4049d43..c8f847d1 100644
--- a/device/bluetooth/floss/bluetooth_remote_gatt_characteristic_floss.cc
+++ b/device/bluetooth/floss/bluetooth_remote_gatt_characteristic_floss.cc
@@ -44,6 +44,19 @@
 
 BluetoothRemoteGattCharacteristicFloss::
     ~BluetoothRemoteGattCharacteristicFloss() {
+  // Reply to pending callbacks
+  if (std::get<1>(pending_write_callbacks_)) {
+    auto [callback, error_callback, data] = std::move(pending_write_callbacks_);
+    if (error_callback) {
+      std::move(error_callback)
+          .Run(BluetoothGattServiceFloss::GattErrorCode::kUnknown);
+    }
+  }
+  if (pending_read_callback_) {
+    std::move(pending_read_callback_)
+        .Run(BluetoothGattServiceFloss::GattErrorCode::kUnknown, {});
+  }
+
   descriptors_.clear();
   service_->RemoveObserverForHandle(characteristic_->instance_id);
 }
diff --git a/device/bluetooth/floss/fake_floss_gatt_manager_client.cc b/device/bluetooth/floss/fake_floss_gatt_manager_client.cc
index fe4cb3d..682eee2 100644
--- a/device/bluetooth/floss/fake_floss_gatt_manager_client.cc
+++ b/device/bluetooth/floss/fake_floss_gatt_manager_client.cc
@@ -22,7 +22,8 @@
 
 void FakeFlossGattManagerClient::Connect(ResponseCallback<Void> callback,
                                          const std::string& remote_device,
-                                         const BluetoothTransport& transport) {
+                                         const BluetoothTransport& transport,
+                                         bool is_direct) {
   std::move(callback).Run(DBusResult<Void>({}));
 }
 
diff --git a/device/bluetooth/floss/fake_floss_gatt_manager_client.h b/device/bluetooth/floss/fake_floss_gatt_manager_client.h
index 1209f96..0bfd33e 100644
--- a/device/bluetooth/floss/fake_floss_gatt_manager_client.h
+++ b/device/bluetooth/floss/fake_floss_gatt_manager_client.h
@@ -21,7 +21,8 @@
 
   void Connect(ResponseCallback<Void> callback,
                const std::string& remote_device,
-               const BluetoothTransport& transport) override;
+               const BluetoothTransport& transport,
+               bool is_direct) override;
 
   void AddService(ResponseCallback<Void> callback,
                   GattService service) override;
diff --git a/device/bluetooth/floss/floss_gatt_manager_client.cc b/device/bluetooth/floss/floss_gatt_manager_client.cc
index 779ca21..7e783d3 100644
--- a/device/bluetooth/floss/floss_gatt_manager_client.cc
+++ b/device/bluetooth/floss/floss_gatt_manager_client.cc
@@ -289,10 +289,8 @@
 
 void FlossGattManagerClient::Connect(ResponseCallback<Void> callback,
                                      const std::string& remote_device,
-                                     const BluetoothTransport& transport) {
-  // Gatt client connections occur immediately instead of when next seen.
-  constexpr bool is_direct = true;
-
+                                     const BluetoothTransport& transport,
+                                     bool is_direct) {
   // Opportunistic connections should be false because we want connections to
   // immediately fail with timeout if it doesn't work out.
   const bool opportunistic = false;
diff --git a/device/bluetooth/floss/floss_gatt_manager_client.h b/device/bluetooth/floss/floss_gatt_manager_client.h
index 3f105cf..9e2291d 100644
--- a/device/bluetooth/floss/floss_gatt_manager_client.h
+++ b/device/bluetooth/floss/floss_gatt_manager_client.h
@@ -380,7 +380,8 @@
   // Create a GATT client connection to a remote device on given transport.
   virtual void Connect(ResponseCallback<Void> callback,
                        const std::string& remote_device,
-                       const BluetoothTransport& transport);
+                       const BluetoothTransport& transport,
+                       bool is_direct);
 
   // Disconnect GATT for given device.
   virtual void Disconnect(ResponseCallback<Void> callback,
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index 9387b62..ff49882d 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -1843,6 +1843,7 @@
   OS_EVENTS_STOPCAPTURINGEVENTS = 1780,
   SIDEPANEL_SETPANELBEHAVIOR = 1781,
   SIDEPANEL_GETPANELBEHAVIOR = 1782,
+  FILEMANAGERPRIVATE_GETBULKPINPROGRESS = 1783,
   // Last entry: Add new entries above, then run:
   // tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/gpu/command_buffer/service/gles2_external_framebuffer_unittest.cc b/gpu/command_buffer/service/gles2_external_framebuffer_unittest.cc
index b41b9ec..9445e627 100644
--- a/gpu/command_buffer/service/gles2_external_framebuffer_unittest.cc
+++ b/gpu/command_buffer/service/gles2_external_framebuffer_unittest.cc
@@ -224,10 +224,8 @@
 INSTANTIATE_TEST_SUITE_P(
     ,
     GLES2ExternalFrameBufferTest,
-    ::testing::Combine(::testing::Values(viz::SharedImageFormat::SinglePlane(
-                                             viz::ResourceFormat::RGBA_8888),
-                                         viz::SharedImageFormat::SinglePlane(
-                                             viz::ResourceFormat::RGBX_8888)),
+    ::testing::Combine(::testing::Values(viz::SinglePlaneFormat::kRGBA_8888,
+                                         viz::SinglePlaneFormat::kRGBX_8888),
                        ::testing::Values(0, 8),
                        ::testing::Bool(),
                        ::testing::Bool(),
diff --git a/gpu/command_buffer/service/image_reader_gl_owner.h b/gpu/command_buffer/service/image_reader_gl_owner.h
index bf3609b..1174097 100644
--- a/gpu/command_buffer/service/image_reader_gl_owner.h
+++ b/gpu/command_buffer/service/image_reader_gl_owner.h
@@ -10,6 +10,7 @@
 #include "base/android/android_image_reader_compat.h"
 #include "base/containers/flat_map.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/raw_ref.h"
 #include "base/threading/thread_checker.h"
 #include "gpu/command_buffer/service/ref_counted_lock.h"
@@ -83,8 +84,12 @@
     base::ScopedFD GetReadyFence() const;
 
    private:
-    ImageReaderGLOwner* texture_owner_;
-    AImage* image_;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #union
+    RAW_PTR_EXCLUSION ImageReaderGLOwner* texture_owner_;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #union
+    RAW_PTR_EXCLUSION AImage* image_;
     base::ScopedFD ready_fence_;
   };
 
diff --git a/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory.cc
index 804dc94e..28123f5 100644
--- a/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory.cc
@@ -20,23 +20,14 @@
 // Check if a format is supported by DXGI for DComp surfaces or swap chains.
 // https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/converting-data-color-space
 bool IsFormatSupportedForScanout(viz::SharedImageFormat format) {
-  if (format.is_multi_plane()) {
-    return false;
-  }
-
-  switch (format.resource_format()) {
-    case viz::ResourceFormat::RGBA_8888:
-    case viz::ResourceFormat::BGRA_8888:
-    case viz::ResourceFormat::RGBX_8888:
-    case viz::ResourceFormat::BGRX_8888:
-    case viz::ResourceFormat::RGBA_F16:
-    case viz::ResourceFormat::RGBA_1010102:
-      return true;
-
-    default:
-      return false;
-  }
+  return ((format == viz::SinglePlaneFormat::kRGBA_8888) ||
+          (format == viz::SinglePlaneFormat::kBGRA_8888) ||
+          (format == viz::SinglePlaneFormat::kRGBX_8888) ||
+          (format == viz::SinglePlaneFormat::kBGRX_8888) ||
+          (format == viz::SinglePlaneFormat::kRGBA_F16) ||
+          (format == viz::SinglePlaneFormat::kRGBA_1010102));
 }
+
 constexpr uint32_t kDXGISwapChainUsage = SHARED_IMAGE_USAGE_DISPLAY_READ |
                                          SHARED_IMAGE_USAGE_DISPLAY_WRITE |
                                          SHARED_IMAGE_USAGE_SCANOUT;
diff --git a/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory_unittest.cc
index 7651e2d..2508d86f 100644
--- a/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory_unittest.cc
@@ -648,18 +648,18 @@
 };
 
 TEST_F(DCompImageBackingFactoryVisualTreeTest, DCompSurfaceCanDisplay) {
-  viz::ResourceFormat formats[4] = {
-      viz::ResourceFormat::RGBA_8888,
-      viz::ResourceFormat::BGRA_8888,
-      viz::ResourceFormat::RGBX_8888,
-      viz::ResourceFormat::BGRX_8888,
+  viz::SharedImageFormat formats[4] = {
+      viz::SinglePlaneFormat::kRGBA_8888,
+      viz::SinglePlaneFormat::kBGRA_8888,
+      viz::SinglePlaneFormat::kRGBX_8888,
+      viz::SinglePlaneFormat::kBGRX_8888,
   };
 
   SkColor test_color = SkColorSetRGB(0x20, 0x40, 0x80);
   SkColor expected_color = test_color;
   for (auto format : formats) {
-    RunTest(kDCompSurfaceUsage, viz::SharedImageFormat::SinglePlane(format),
-            gfx::ColorSpace::CreateSRGB(), false, test_color, expected_color);
+    RunTest(kDCompSurfaceUsage, format, gfx::ColorSpace::CreateSRGB(), false,
+            test_color, expected_color);
   }
 }
 
@@ -673,16 +673,16 @@
 
 TEST_F(DCompImageBackingFactoryVisualTreeTest,
        DCompSurfaceCanDisplayWithAlpha) {
-  viz::ResourceFormat formats[2] = {
-      viz::ResourceFormat::RGBA_8888,
-      viz::ResourceFormat::BGRA_8888,
+  viz::SharedImageFormat formats[2] = {
+      viz::SinglePlaneFormat::kRGBA_8888,
+      viz::SinglePlaneFormat::kBGRA_8888,
   };
 
   SkColor test_color = SkColorSetARGB(0x80, 0x20, 0x40, 0x80);
   SkColor expected_color = SkColorSetRGB(0x10, 0x20, 0x40);
   for (auto format : formats) {
-    RunTest(kDCompSurfaceUsage, viz::SharedImageFormat::SinglePlane(format),
-            gfx::ColorSpace::CreateSRGB(), true, test_color, expected_color);
+    RunTest(kDCompSurfaceUsage, format, gfx::ColorSpace::CreateSRGB(), true,
+            test_color, expected_color);
   }
 }
 
@@ -696,18 +696,18 @@
 }
 
 TEST_F(DCompImageBackingFactoryVisualTreeTest, DXGISwapChainCanDisplay) {
-  viz::ResourceFormat formats[4] = {
-      viz::ResourceFormat::RGBA_8888,
-      viz::ResourceFormat::BGRA_8888,
-      viz::ResourceFormat::RGBX_8888,
-      viz::ResourceFormat::BGRX_8888,
+  viz::SharedImageFormat formats[4] = {
+      viz::SinglePlaneFormat::kRGBA_8888,
+      viz::SinglePlaneFormat::kBGRA_8888,
+      viz::SinglePlaneFormat::kRGBX_8888,
+      viz::SinglePlaneFormat::kBGRX_8888,
   };
 
   SkColor test_color = SkColorSetRGB(0x20, 0x40, 0x80);
   SkColor expected_color = test_color;
   for (auto format : formats) {
-    RunTest(kDXGISwapChainUsage, viz::SharedImageFormat::SinglePlane(format),
-            gfx::ColorSpace::CreateSRGB(), false, test_color, expected_color);
+    RunTest(kDXGISwapChainUsage, format, gfx::ColorSpace::CreateSRGB(), false,
+            test_color, expected_color);
   }
 }
 
@@ -728,16 +728,16 @@
 
 TEST_F(DCompImageBackingFactoryVisualTreeTest,
        DXGISwapChainCanDisplayWithAlpha) {
-  viz::ResourceFormat formats[2] = {
-      viz::ResourceFormat::RGBA_8888,
-      viz::ResourceFormat::BGRA_8888,
+  viz::SharedImageFormat formats[2] = {
+      viz::SinglePlaneFormat::kRGBA_8888,
+      viz::SinglePlaneFormat::kBGRA_8888,
   };
 
   SkColor test_color = SkColorSetARGB(0x80, 0x20, 0x40, 0x80);
   SkColor expected_color = SkColorSetRGB(0x10, 0x20, 0x40);
   for (auto format : formats) {
-    RunTest(kDXGISwapChainUsage, viz::SharedImageFormat::SinglePlane(format),
-            gfx::ColorSpace::CreateSRGB(), true, test_color, expected_color);
+    RunTest(kDXGISwapChainUsage, format, gfx::ColorSpace::CreateSRGB(), true,
+            test_color, expected_color);
   }
 }
 
diff --git a/media/audio/android/aaudio_output.h b/media/audio/android/aaudio_output.h
index 0ed311d..4473578 100644
--- a/media/audio/android/aaudio_output.h
+++ b/media/audio/android/aaudio_output.h
@@ -8,6 +8,7 @@
 #include <aaudio/AAudio.h>
 
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/synchronization/lock.h"
 #include "base/thread_annotations.h"
 #include "base/threading/thread_checker.h"
@@ -64,7 +65,9 @@
 
   std::unique_ptr<AudioBus> audio_bus_;
 
-  AAudioStream* aaudio_stream_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #addr-of
+  RAW_PTR_EXCLUSION AAudioStream* aaudio_stream_ = nullptr;
 
   // Bound to the audio data callback. Outlives |this| in case the callbacks
   // continue after |this| is destroyed. See crbug.com/1183255.
diff --git a/media/capture/BUILD.gn b/media/capture/BUILD.gn
index a7dbefa..b56936b 100644
--- a/media/capture/BUILD.gn
+++ b/media/capture/BUILD.gn
@@ -334,6 +334,7 @@
     deps += [
       "//ash/constants",
       "//build/config/linux/libdrm",
+      "//chromeos/ash/components/mojo_service_manager",
       "//chromeos/components/sensors:sensors",
       "//chromeos/dbus/power",
       "//components/chromeos_camera:mojo_mjpeg_decode_accelerator",
diff --git a/media/capture/video/chromeos/DEPS b/media/capture/video/chromeos/DEPS
index 3518318..69fb2cb 100644
--- a/media/capture/video/chromeos/DEPS
+++ b/media/capture/video/chromeos/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+ash/constants/ash_features.h",
   "+ash/webui/camera_app_ui/document_scanner_service_client.h",
+  "+chromeos/ash/components/mojo_service_manager",
   "+chromeos/components/sensors",
   "+chromeos/dbus",
   "+components/chromeos_camera",
diff --git a/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc b/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc
index 67d950d9..49f8014 100644
--- a/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc
+++ b/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc
@@ -28,6 +28,8 @@
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/trace_event/trace_event.h"
+#include "chromeos/ash/components/mojo_service_manager/connection.h"
+#include "chromeos/ash/components/mojo_service_manager/mojom/mojo_service_manager.mojom.h"
 #include "chromeos/components/sensors/sensor_util.h"
 #include "components/device_event_log/device_event_log.h"
 #include "media/capture/video/chromeos/mojom/camera_common.mojom.h"
@@ -537,6 +539,16 @@
           base::BindPostTaskToCurrentDefault(std::move(callback))));
 }
 
+void CameraHalDispatcherImpl::BindServiceToMojoServiceManager(
+    const std::string& service_name,
+    mojo::ScopedMessagePipeHandle receiver) {
+  main_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &CameraHalDispatcherImpl::BindToMojoServiceManagerOnUIThread,
+          base::Unretained(this), service_name, std::move(receiver)));
+}
+
 void CameraHalDispatcherImpl::CameraDeviceActivityChange(
     int32_t camera_id,
     bool opened,
@@ -1127,4 +1139,13 @@
   return &token_manager_;
 }
 
+void CameraHalDispatcherImpl::BindToMojoServiceManagerOnUIThread(
+    const std::string service_name,
+    mojo::ScopedMessagePipeHandle receiver) {
+  CHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  CHECK(ash::mojo_service_manager::IsServiceManagerBound());
+  ash::mojo_service_manager::GetServiceManagerProxy()->Request(
+      service_name, /*timeout=*/absl::nullopt, std::move(receiver));
+}
+
 }  // namespace media
diff --git a/media/capture/video/chromeos/camera_hal_dispatcher_impl.h b/media/capture/video/chromeos/camera_hal_dispatcher_impl.h
index 08be2e9..6799195d 100644
--- a/media/capture/video/chromeos/camera_hal_dispatcher_impl.h
+++ b/media/capture/video/chromeos/camera_hal_dispatcher_impl.h
@@ -272,6 +272,9 @@
       mojo::PendingRemote<chromeos::sensors::mojom::SensorHalClient> client,
       const base::UnguessableToken& auth_token,
       RegisterSensorClientWithTokenCallback callback) final;
+  void BindServiceToMojoServiceManager(
+      const std::string& service_name,
+      mojo::ScopedMessagePipeHandle receiver) final;
 
   // CameraHalServerCallbacks implementations.
   void CameraDeviceActivityChange(int32_t camera_id,
@@ -383,6 +386,10 @@
   base::flat_set<std::string> GetDeviceIdsFromCameraIds(
       base::flat_set<int32_t> camera_ids);
 
+  void BindToMojoServiceManagerOnUIThread(
+      const std::string service_name,
+      mojo::ScopedMessagePipeHandle receiver);
+
   void StopOnProxyThread();
 
   TokenManager* GetTokenManagerForTesting();
diff --git a/media/capture/video/chromeos/mojom/cros_camera_service.mojom b/media/capture/video/chromeos/mojom/cros_camera_service.mojom
index 1b8e3759c..ff80973 100644
--- a/media/capture/video/chromeos/mojom/cros_camera_service.mojom
+++ b/media/capture/video/chromeos/mojom/cros_camera_service.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Next min version: 10
+// Next min version: 11
 
 module cros.mojom;
 
@@ -117,6 +117,13 @@
   [MinVersion=6] RegisterSensorClientWithToken@6(
       pending_remote<chromeos.sensors.mojom.SensorHalClient> client,
       mojo_base.mojom.UnguessableToken auth_token) => (int32 result);
+
+  // Workaround for cros-camera service to request other services via
+  // mojo service manager.
+  // TODO(b/258095854): Remove this once camera mojo network is migrated to
+  // mojo service manager.
+  [MinVersion=10] BindServiceToMojoServiceManager@7(string service_name,
+      handle<message_pipe> receiver);
 };
 
 // The CrOS camera HAL v3 Mojo server.
diff --git a/media/muxers/BUILD.gn b/media/muxers/BUILD.gn
index f53a1b8a..8933aae 100644
--- a/media/muxers/BUILD.gn
+++ b/media/muxers/BUILD.gn
@@ -15,6 +15,8 @@
     "file_webm_muxer_delegate.h",
     "live_webm_muxer_delegate.cc",
     "live_webm_muxer_delegate.h",
+    "mp4_muxer_context.cc",
+    "mp4_muxer_context.h",
     "muxer.cc",
     "muxer.h",
     "output_position_tracker.cc",
@@ -37,6 +39,7 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
+    "mp4_muxer_context_unittest.cc",
     "output_position_tracker_unittest.cc",
     "webm_muxer_unittest.cc",
   ]
diff --git a/media/muxers/mp4_muxer_context.cc b/media/muxers/mp4_muxer_context.cc
new file mode 100644
index 0000000..6648cb44
--- /dev/null
+++ b/media/muxers/mp4_muxer_context.cc
@@ -0,0 +1,57 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/muxers/mp4_muxer_context.h"
+
+#include "media/muxers/output_position_tracker.h"
+
+namespace media {
+
+Mp4MuxerContext::Mp4MuxerContext(
+    std::unique_ptr<OutputPositionTracker> output_position_tracker)
+    : output_position_tracker_(std::move(output_position_tracker)) {}
+
+Mp4MuxerContext::~Mp4MuxerContext() = default;
+
+// Track will be created and inserted to vector whatever arrives at
+// Muxer.
+absl::optional<size_t> Mp4MuxerContext::GetVideoIndex() const {
+  return video_index_;
+}
+
+void Mp4MuxerContext::SetVideoIndex(size_t index) {
+  CHECK(!video_index_.has_value());
+  video_index_ = index;
+}
+
+absl::optional<size_t> Mp4MuxerContext::GetAudioIndex() const {
+  return audio_index_;
+}
+
+void Mp4MuxerContext::SetAudioIndex(size_t index) {
+  CHECK(!audio_index_.has_value());
+  audio_index_ = index;
+}
+
+void Mp4MuxerContext::SetCurrentFragmentMoofOffset(size_t offset) {
+  moof_offset_in_fragment_ = offset;
+}
+
+size_t Mp4MuxerContext::GetCurrentFragmentMoofOffset() const {
+  return moof_offset_in_fragment_.value();
+}
+
+void Mp4MuxerContext::SetCurrentFragmentMdatOffset(size_t offset) {
+  mdat_offset_in_fragment_ = offset;
+}
+
+size_t Mp4MuxerContext::GetCurrentFragmentMdatOffset() const {
+  return mdat_offset_in_fragment_.value();
+}
+
+OutputPositionTracker& Mp4MuxerContext::GetOutputPositionTracker() const {
+  return *output_position_tracker_;
+}
+
+}  // namespace media
diff --git a/media/muxers/mp4_muxer_context.h b/media/muxers/mp4_muxer_context.h
new file mode 100644
index 0000000..bff7fc4
--- /dev/null
+++ b/media/muxers/mp4_muxer_context.h
@@ -0,0 +1,62 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_MUXERS_MP4_MUXER_CONTEXT_H_
+#define MEDIA_MUXERS_MP4_MUXER_CONTEXT_H_
+
+#include <memory>
+
+#include "base/sequence_checker.h"
+#include "media/base/media_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace media {
+
+class OutputPositionTracker;
+
+// The class provides any additional data that isn't part of box.
+// Usually, the data will be set in the middle of box data creation, but
+// can be also set during writing box.
+class MEDIA_EXPORT Mp4MuxerContext {
+ public:
+  explicit Mp4MuxerContext(
+      std::unique_ptr<OutputPositionTracker> output_position_tracker);
+  ~Mp4MuxerContext();
+  Mp4MuxerContext(const Mp4MuxerContext&) = delete;
+  Mp4MuxerContext& operator=(const Mp4MuxerContext&) = delete;
+
+  // Track will be created and inserted to vector by the order of arrival
+  // on Muxer so video or audio index could be different on new stream
+  // collection (e.g. after putRequest)
+  absl::optional<size_t> GetVideoIndex() const;
+  void SetVideoIndex(size_t index);
+
+  absl::optional<size_t> GetAudioIndex() const;
+  void SetAudioIndex(size_t index);
+
+  void SetCurrentFragmentMoofOffset(size_t offset);
+  size_t GetCurrentFragmentMoofOffset() const;
+
+  void SetCurrentFragmentMdatOffset(size_t offset);
+  size_t GetCurrentFragmentMdatOffset() const;
+
+  OutputPositionTracker& GetOutputPositionTracker() const;
+
+ private:
+  absl::optional<size_t> video_index_;
+  absl::optional<size_t> audio_index_;
+
+  // MOOF offset will be `base_data_offset` of TFHD in the same fragment.
+  absl::optional<size_t> moof_offset_in_fragment_;
+
+  // MDAT offset will be `data_offset` of TRUN in the same fragment.
+  absl::optional<size_t> mdat_offset_in_fragment_;
+
+  std::unique_ptr<OutputPositionTracker> output_position_tracker_;
+  SEQUENCE_CHECKER(sequence_checker_);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_MUXERS_MP4_MUXER_CONTEXT_H_
diff --git a/media/muxers/mp4_muxer_context_unittest.cc b/media/muxers/mp4_muxer_context_unittest.cc
new file mode 100644
index 0000000..a5c30074
--- /dev/null
+++ b/media/muxers/mp4_muxer_context_unittest.cc
@@ -0,0 +1,54 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/functional/bind.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "media/muxers/mp4_muxer_context.h"
+#include "media/muxers/output_position_tracker.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+TEST(Mp4MuxerContextTest, Default) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  std::string written_data;
+  base::RunLoop run_loop;
+
+  auto output_position_tracker =
+      std::make_unique<OutputPositionTracker>(base::BindRepeating(
+          [](std::string* written_data, base::OnceClosure run_loop_quit,
+             base::StringPiece data) {
+            written_data->append(data.data(), data.size());
+            std::move(run_loop_quit).Run();
+          },
+          &written_data, run_loop.QuitClosure()));
+
+  Mp4MuxerContext mp4_context(std::move(output_position_tracker));
+  EXPECT_FALSE(mp4_context.GetVideoIndex().has_value());
+  EXPECT_FALSE(mp4_context.GetAudioIndex().has_value());
+
+  mp4_context.SetVideoIndex(1);
+  mp4_context.SetAudioIndex(2);
+  mp4_context.SetCurrentFragmentMoofOffset(12345);
+  mp4_context.SetCurrentFragmentMdatOffset(12345678);
+
+  std::string str1 = "abc";
+  mp4_context.GetOutputPositionTracker().WriteString(str1);
+  run_loop.Run();
+
+  EXPECT_TRUE(mp4_context.GetVideoIndex().has_value());
+  EXPECT_TRUE(mp4_context.GetAudioIndex().has_value());
+  EXPECT_EQ(mp4_context.GetVideoIndex(), static_cast<size_t>(1));
+  EXPECT_EQ(mp4_context.GetAudioIndex(), static_cast<size_t>(2));
+  EXPECT_EQ(mp4_context.GetCurrentFragmentMoofOffset(),
+            static_cast<size_t>(12345));
+  EXPECT_EQ(mp4_context.GetCurrentFragmentMdatOffset(),
+            static_cast<size_t>(12345678));
+  EXPECT_EQ(str1, written_data);
+}
+
+}  // namespace media
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 20e4a00..ade5bfdf 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -660,6 +660,7 @@
     "http/http_status_code.cc",
     "http/http_status_code.h",
     "http/http_status_code_list.h",
+    "http/http_stream.cc",
     "http/http_stream.h",
     "http/http_stream_factory.cc",
     "http/http_stream_factory.h",
diff --git a/net/android/dummy_spnego_authenticator.h b/net/android/dummy_spnego_authenticator.h
index f2f22f6..6a3981db 100644
--- a/net/android/dummy_spnego_authenticator.h
+++ b/net/android/dummy_spnego_authenticator.h
@@ -12,6 +12,7 @@
 #include <string>
 
 #include "base/android/scoped_java_ref.h"
+#include "base/memory/raw_ptr_exclusion.h"
 
 // Provides an interface for controlling the DummySpnegoAuthenticator service.
 // This includes a basic stub of the Mock GSSAPI library, so that OS independent
@@ -26,7 +27,9 @@
 
 typedef struct gss_OID_desc_struct {
   uint32_t length;
-  void* elements;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #global-scope
+  RAW_PTR_EXCLUSION void* elements;
 } gss_OID_desc, *gss_OID;
 
 extern gss_OID CHROME_GSS_SPNEGO_MECH_OID_DESC;
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index 025869ad..f6f9bf3 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -996,8 +996,6 @@
   DCHECK(entry->writers->IsEmpty());
   DCHECK(success || make_readers.empty());
 
-  entry->writers_done_writing_to_entry_history = absl::make_optional(success);
-
   if (!success && should_keep_entry) {
     // Restart already validated transactions so that they are able to read
     // the truncated status of the entry.
diff --git a/net/http/http_cache.h b/net/http/http_cache.h
index 52682432..ddbcbab 100644
--- a/net/http/http_cache.h
+++ b/net/http/http_cache.h
@@ -395,8 +395,6 @@
 
     // True if entry is doomed.
     bool doomed = false;
-
-    absl::optional<bool> writers_done_writing_to_entry_history;
   };
 
   using ActiveEntriesMap =
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index d8c1a38..d8bade0 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -124,6 +124,15 @@
   // this network transaction was prematurely cancelled.
   GenerateNetworkErrorLoggingReport(ERR_ABORTED);
 #endif  // BUILDFLAG(ENABLE_REPORTING)
+
+  if (quic_protocol_error_retry_delay_) {
+    base::UmaHistogramTimes(
+        IsGoogleHostWithAlpnH3(url_.host())
+            ? "Net.QuicProtocolErrorRetryDelayH3SupportedGoogleHost.Failure"
+            : "Net.QuicProtocolErrorRetryDelay.Failure",
+        *quic_protocol_error_retry_delay_);
+  }
+
   if (stream_.get()) {
     // TODO(mbelshe): The stream_ should be able to compute whether or not the
     //                stream should be kept alive.  No reason to compute here
@@ -164,8 +173,8 @@
   request_->extra_headers.GetHeader(HttpRequestHeaders::kUserAgent,
                                     &request_user_agent_);
   request_reporting_upload_depth_ = request_->reporting_upload_depth;
-  start_timeticks_ = base::TimeTicks::Now();
 #endif  // BUILDFLAG(ENABLE_REPORTING)
+  start_timeticks_ = base::TimeTicks::Now();
 
   if (request_->load_flags & LOAD_DISABLE_CERT_NETWORK_FETCHES) {
     server_ssl_config_.disable_cert_verification_network_fetches = true;
@@ -1175,7 +1184,7 @@
         response_.headers->response_code());
     // This will close the socket - it would be weird to try and reuse it, even
     // if the server doesn't actually close it.
-    ResetConnectionAndRequestForResend();
+    ResetConnectionAndRequestForResend(RetryReason::kHttpRequestTimeout);
     return OK;
   }
 
@@ -1227,7 +1236,7 @@
     enable_alternative_services_ = false;
     net_log_.AddEvent(
         NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST);
-    ResetConnectionAndRequestForResend();
+    ResetConnectionAndRequestForResend(RetryReason::kHttpMisdirectedRequest);
     return OK;
   }
 
@@ -1341,6 +1350,15 @@
 #if BUILDFLAG(ENABLE_REPORTING)
     GenerateNetworkErrorLoggingReport(result);
 #endif  // BUILDFLAG(ENABLE_REPORTING)
+
+    if (result == OK && quic_protocol_error_retry_delay_) {
+      base::UmaHistogramTimes(
+          IsGoogleHostWithAlpnH3(url_.host())
+              ? "Net.QuicProtocolErrorRetryDelayH3SupportedGoogleHost.Success"
+              : "Net.QuicProtocolErrorRetryDelay.Success",
+          *quic_protocol_error_retry_delay_);
+      quic_protocol_error_retry_delay_.reset();
+    }
   }
 
   // Clear these to avoid leaving around old state.
@@ -1522,7 +1540,7 @@
 
   // HttpServerProperties should have been updated, so when the request is sent
   // again, it will automatically use HTTP/1.1.
-  ResetConnectionAndRequestForResend();
+  ResetConnectionAndRequestForResend(RetryReason::kHttp11Required);
   return OK;
 }
 
@@ -1569,7 +1587,8 @@
         retry_attempts_++;
         net_log_.AddEventWithNetErrorCode(
             NetLogEventType::HTTP_TRANSACTION_RESTART_AFTER_ERROR, error);
-        ResetConnectionAndRequestForResend();
+        ResetConnectionAndRequestForResend(
+            RetryReason::kSslClientAuthSignatureFailed);
         return OK;
       }
     }
@@ -1577,6 +1596,44 @@
   return error;
 }
 
+// static
+absl::optional<HttpNetworkTransaction::RetryReason>
+HttpNetworkTransaction::GetRetryReasonForIOError(int error) {
+  switch (error) {
+    case ERR_CONNECTION_RESET:
+      return RetryReason::kConnectionReset;
+    case ERR_CONNECTION_CLOSED:
+      return RetryReason::kConnectionClosed;
+    case ERR_CONNECTION_ABORTED:
+      return RetryReason::kConnectionAborted;
+    case ERR_SOCKET_NOT_CONNECTED:
+      return RetryReason::kSocketNotConnected;
+    case ERR_EMPTY_RESPONSE:
+      return RetryReason::kEmptyResponse;
+    case ERR_EARLY_DATA_REJECTED:
+      return RetryReason::kEarlyDataRejected;
+    case ERR_WRONG_VERSION_ON_EARLY_DATA:
+      return RetryReason::kWrongVersionOnEarlyData;
+    case ERR_HTTP2_PING_FAILED:
+      return RetryReason::kHttp2PingFailed;
+    case ERR_HTTP2_SERVER_REFUSED_STREAM:
+      return RetryReason::kHttp2ServerRefusedStream;
+    case ERR_HTTP2_PUSHED_STREAM_NOT_AVAILABLE:
+      return RetryReason::kHttp2PushedStreamNotAvailable;
+    case ERR_HTTP2_CLAIMED_PUSHED_STREAM_RESET_BY_SERVER:
+      return RetryReason::kHttp2ClaimedPushedStreamResetByServer;
+    case ERR_HTTP2_PUSHED_RESPONSE_DOES_NOT_MATCH:
+      return RetryReason::kHttp2PushedResponseDoesNotMatch;
+    case ERR_QUIC_HANDSHAKE_FAILED:
+      return RetryReason::kQuicHandshakeFailed;
+    case ERR_QUIC_GOAWAY_REQUEST_CAN_BE_RETRIED:
+      return RetryReason::kQuicGoawayRequestCanBeRetried;
+    case ERR_QUIC_PROTOCOL_ERROR:
+      return RetryReason::kQuicProtocolError;
+  }
+  return absl::nullopt;
+}
+
 // This method determines whether it is safe to resend the request after an
 // IO error. It should only be called in response to errors received before
 // final set of response headers have been successfully parsed, that the
@@ -1591,14 +1648,19 @@
   GenerateNetworkErrorLoggingReportIfError(error);
 #endif  // BUILDFLAG(ENABLE_REPORTING)
 
-  switch (error) {
+  absl::optional<HttpNetworkTransaction::RetryReason> retry_reason =
+      GetRetryReasonForIOError(error);
+  if (!retry_reason) {
+    return error;
+  }
+  switch (*retry_reason) {
     // If we try to reuse a connection that the server is in the process of
     // closing, we may end up successfully writing out our request (or a
     // portion of our request) only to find a connection error when we try to
     // read from (or finish writing to) the socket.
-    case ERR_CONNECTION_RESET:
-    case ERR_CONNECTION_CLOSED:
-    case ERR_CONNECTION_ABORTED:
+    case RetryReason::kConnectionReset:
+    case RetryReason::kConnectionClosed:
+    case RetryReason::kConnectionAborted:
     // There can be a race between the socket pool checking checking whether a
     // socket is still connected, receiving the FIN, and sending/reading data
     // on a reused socket.  If we receive the FIN between the connectedness
@@ -1606,62 +1668,75 @@
     // is disconnected when we get a ERR_SOCKET_NOT_CONNECTED.  This will most
     // likely happen when trying to retrieve its IP address.
     // See http://crbug.com/105824 for more details.
-    case ERR_SOCKET_NOT_CONNECTED:
+    case RetryReason::kSocketNotConnected:
     // If a socket is closed on its initial request, HttpStreamParser returns
     // ERR_EMPTY_RESPONSE. This may still be close/reuse race if the socket was
     // preconnected but failed to be used before the server timed it out.
-    case ERR_EMPTY_RESPONSE:
+    case RetryReason::kEmptyResponse:
       if (ShouldResendRequest()) {
         net_log_.AddEventWithNetErrorCode(
             NetLogEventType::HTTP_TRANSACTION_RESTART_AFTER_ERROR, error);
-        ResetConnectionAndRequestForResend();
+        ResetConnectionAndRequestForResend(*retry_reason);
         error = OK;
       }
       break;
-    case ERR_EARLY_DATA_REJECTED:
-    case ERR_WRONG_VERSION_ON_EARLY_DATA:
+    case RetryReason::kEarlyDataRejected:
+    case RetryReason::kWrongVersionOnEarlyData:
       net_log_.AddEventWithNetErrorCode(
           NetLogEventType::HTTP_TRANSACTION_RESTART_AFTER_ERROR, error);
       // Disable early data on the SSLConfig on a reset.
       can_send_early_data_ = false;
-      ResetConnectionAndRequestForResend();
+      ResetConnectionAndRequestForResend(*retry_reason);
       error = OK;
       break;
-    case ERR_HTTP2_PING_FAILED:
-    case ERR_HTTP2_SERVER_REFUSED_STREAM:
-    case ERR_HTTP2_PUSHED_STREAM_NOT_AVAILABLE:
-    case ERR_HTTP2_CLAIMED_PUSHED_STREAM_RESET_BY_SERVER:
-    case ERR_HTTP2_PUSHED_RESPONSE_DOES_NOT_MATCH:
-    case ERR_QUIC_HANDSHAKE_FAILED:
-    case ERR_QUIC_GOAWAY_REQUEST_CAN_BE_RETRIED:
+    case RetryReason::kHttp2PingFailed:
+    case RetryReason::kHttp2ServerRefusedStream:
+    case RetryReason::kHttp2PushedStreamNotAvailable:
+    case RetryReason::kHttp2ClaimedPushedStreamResetByServer:
+    case RetryReason::kHttp2PushedResponseDoesNotMatch:
+    case RetryReason::kQuicHandshakeFailed:
+    case RetryReason::kQuicGoawayRequestCanBeRetried:
       if (HasExceededMaxRetries())
         break;
       net_log_.AddEventWithNetErrorCode(
           NetLogEventType::HTTP_TRANSACTION_RESTART_AFTER_ERROR, error);
       retry_attempts_++;
-      ResetConnectionAndRequestForResend();
+      ResetConnectionAndRequestForResend(*retry_reason);
       error = OK;
       break;
-    case ERR_QUIC_PROTOCOL_ERROR:
-      if (GetResponseHeaders() != nullptr ||
-          !stream_->GetAlternativeService(&retried_alternative_service_)) {
+    case RetryReason::kQuicProtocolError:
+      if (GetResponseHeaders() != nullptr) {
         // If the response headers have already been received and passed up
-        // then the request can not be retried. Also, if there was no
-        // alternative service used for this request, then there is no
-        // alternative service to be disabled.
+        // then the request can not be retried.
+        RecordQuicProtocolErrorMetrics(
+            QuicProtocolErrorRetryStatus::kNoRetryHeaderReceived);
         break;
       }
-      if (HasExceededMaxRetries())
+      if (!stream_->GetAlternativeService(&retried_alternative_service_)) {
+        // If there was no alternative service used for this request, then there
+        // is no alternative service to be disabled.  Note: We expect this
+        // doesn't happen. But records the UMA just in case.
+        RecordQuicProtocolErrorMetrics(
+            QuicProtocolErrorRetryStatus::kNoRetryNoAlternativeService);
         break;
+      }
+      if (HasExceededMaxRetries()) {
+        RecordQuicProtocolErrorMetrics(
+            QuicProtocolErrorRetryStatus::kNoRetryExceededMaxRetries);
+        break;
+      }
+
       if (session_->http_server_properties()->IsAlternativeServiceBroken(
               retried_alternative_service_, network_anonymization_key_)) {
         // If the alternative service was marked as broken while the request
         // was in flight, retry the request which will not use the broken
         // alternative service.
+        RecordQuicProtocolErrorMetrics(
+            QuicProtocolErrorRetryStatus::kRetryAltServiceBroken);
         net_log_.AddEventWithNetErrorCode(
             NetLogEventType::HTTP_TRANSACTION_RESTART_AFTER_ERROR, error);
         retry_attempts_++;
-        ResetConnectionAndRequestForResend();
+        ResetConnectionAndRequestForResend(*retry_reason);
         error = OK;
       } else if (session_->context()
                      .quic_context->params()
@@ -1669,14 +1744,24 @@
         // Disable alternative services for this request and retry it. If the
         // retry succeeds, then the alternative service will be marked as
         // broken then.
+        RecordQuicProtocolErrorMetrics(
+            QuicProtocolErrorRetryStatus::kRetryAltServiceNotBroken);
         enable_alternative_services_ = false;
         net_log_.AddEventWithNetErrorCode(
             NetLogEventType::HTTP_TRANSACTION_RESTART_AFTER_ERROR, error);
         retry_attempts_++;
-        ResetConnectionAndRequestForResend();
+        ResetConnectionAndRequestForResend(*retry_reason);
         error = OK;
       }
       break;
+
+    // The following reasons are not covered here.
+    case RetryReason::kHttpRequestTimeout:
+    case RetryReason::kHttpMisdirectedRequest:
+    case RetryReason::kHttp11Required:
+    case RetryReason::kSslClientAuthSignatureFailed:
+      NOTREACHED();
+      break;
   }
   return error;
 }
@@ -1707,8 +1792,8 @@
   net_error_details_.quic_connection_error = quic::QUIC_NO_ERROR;
 #if BUILDFLAG(ENABLE_REPORTING)
   network_error_logging_report_generated_ = false;
-  start_timeticks_ = base::TimeTicks::Now();
 #endif  // BUILDFLAG(ENABLE_REPORTING)
+  start_timeticks_ = base::TimeTicks::Now();
 }
 
 void HttpNetworkTransaction::CacheNetErrorDetailsAndResetStream() {
@@ -1740,7 +1825,18 @@
   return num_restarts_ < kMaxRestarts;
 }
 
-void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
+void HttpNetworkTransaction::ResetConnectionAndRequestForResend(
+    RetryReason retry_reason) {
+  base::UmaHistogramEnumeration(
+      IsGoogleHostWithAlpnH3(url_.host())
+          ? "Net.NetworkTransactionH3SupportedGoogleHost.RetryReason"
+          : "Net.NetworkTransaction.RetryReason",
+      retry_reason);
+  if (retry_reason == RetryReason::kQuicProtocolError) {
+    quic_protocol_error_retry_delay_ =
+        base::TimeTicks::Now() - start_timeticks_;
+  }
+
   if (stream_.get()) {
     stream_->Close(true);
     CacheNetErrorDetailsAndResetStream();
@@ -1755,8 +1851,8 @@
 #if BUILDFLAG(ENABLE_REPORTING)
   // Reset for new request.
   network_error_logging_report_generated_ = false;
-  start_timeticks_ = base::TimeTicks::Now();
 #endif  // BUILDFLAG(ENABLE_REPORTING)
+  start_timeticks_ = base::TimeTicks::Now();
 
   ResetStateForRestart();
 }
@@ -1888,4 +1984,43 @@
   return result;
 }
 
+void HttpNetworkTransaction::RecordQuicProtocolErrorMetrics(
+    QuicProtocolErrorRetryStatus retry_status) {
+  std::string histogram = "Net.QuicProtocolError";
+  if (IsGoogleHostWithAlpnH3(url_.host())) {
+    histogram += "H3SupportedGoogleHost";
+  }
+  base::UmaHistogramEnumeration(histogram + ".RetryStatus", retry_status);
+
+  if (!stream_) {
+    return;
+  }
+  absl::optional<quic::QuicErrorCode> connection_error =
+      stream_->GetQuicErrorCode();
+  absl::optional<quic::QuicRstStreamErrorCode> stream_error =
+      stream_->GetQuicRstStreamErrorCode();
+  if (!connection_error || !stream_error) {
+    return;
+  }
+  switch (retry_status) {
+    case QuicProtocolErrorRetryStatus::kNoRetryExceededMaxRetries:
+      histogram += ".NoRetryExceededMaxRetries";
+      break;
+    case QuicProtocolErrorRetryStatus::kNoRetryHeaderReceived:
+      histogram += ".NoRetryHeaderReceived";
+      break;
+    case QuicProtocolErrorRetryStatus::kNoRetryNoAlternativeService:
+      histogram += ".NoRetryNoAlternativeService";
+      break;
+    case QuicProtocolErrorRetryStatus::kRetryAltServiceBroken:
+      histogram += ".RetryAltServiceBroken";
+      break;
+    case QuicProtocolErrorRetryStatus::kRetryAltServiceNotBroken:
+      histogram += ".RetryAltServiceNotBroken";
+      break;
+  }
+  base::UmaHistogramSparse(histogram + ".QuicErrorCode", *connection_error);
+  base::UmaHistogramSparse(histogram + ".QuicStreamErrorCode", *stream_error);
+}
+
 }  // namespace net
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index 4ef51e6..8e6ade1 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -34,6 +34,7 @@
 #include "net/socket/connection_attempts.h"
 #include "net/ssl/ssl_config_service.h"
 #include "net/websockets/websocket_handshake_stream_base.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace net {
 
@@ -261,9 +262,35 @@
   // proceed.
   bool CheckMaxRestarts();
 
+  // These values are persisted to logs. Entries should not be renumbered and
+  // numeric values should never be reused.
+  enum class RetryReason {
+    kHttpRequestTimeout = 0,
+    kHttpMisdirectedRequest = 1,
+    kHttp11Required = 2,
+    kSslClientAuthSignatureFailed = 3,
+    kConnectionReset = 4,
+    kConnectionClosed = 5,
+    kConnectionAborted = 6,
+    kSocketNotConnected = 7,
+    kEmptyResponse = 8,
+    kEarlyDataRejected = 9,
+    kWrongVersionOnEarlyData = 10,
+    kHttp2PingFailed = 11,
+    kHttp2ServerRefusedStream = 12,
+    kHttp2PushedStreamNotAvailable = 13,
+    kHttp2ClaimedPushedStreamResetByServer = 14,
+    kHttp2PushedResponseDoesNotMatch = 15,
+    kQuicHandshakeFailed = 16,
+    kQuicGoawayRequestCanBeRetried = 17,
+    kQuicProtocolError = 18,
+    kMaxValue = kQuicProtocolError,
+  };
+  static absl::optional<RetryReason> GetRetryReasonForIOError(int error);
+
   // Resets the connection and the request headers for resend.  Called when
   // ShouldResendRequest() is true.
-  void ResetConnectionAndRequestForResend();
+  void ResetConnectionAndRequestForResend(RetryReason retry_reason);
 
   // Sets up the state machine to restart the transaction with auth.
   void PrepareForAuthRestart(HttpAuth::Target target);
@@ -312,6 +339,23 @@
 
   void ResumeAfterConnected(int result);
 
+  // These values are persisted to logs. Entries should not be renumbered and
+  // numeric values should never be reused.
+  enum class QuicProtocolErrorRetryStatus {
+    kNoRetryExceededMaxRetries = 0,
+    kNoRetryHeaderReceived = 1,
+    kNoRetryNoAlternativeService = 2,
+    kRetryAltServiceBroken = 3,
+    kRetryAltServiceNotBroken = 4,
+    kMaxValue = kRetryAltServiceNotBroken,
+  };
+
+  void RecordQuicProtocolErrorMetrics(
+      QuicProtocolErrorRetryStatus retry_status);
+
+  void RecordMetricsIfError(int rv);
+  void RecordMetrics(int rv);
+
   scoped_refptr<HttpAuthController>
       auth_controllers_[HttpAuth::AUTH_NUM_TARGETS];
 
@@ -376,8 +420,8 @@
   std::string request_referrer_;
   std::string request_user_agent_;
   int request_reporting_upload_depth_ = 0;
-  base::TimeTicks start_timeticks_;
 #endif
+  base::TimeTicks start_timeticks_;
 
   // The size in bytes of the buffer we use to drain the response body that
   // we want to throw away.  The response body is typically a small error
@@ -449,6 +493,8 @@
   size_t num_restarts_ = 0;
 
   bool close_connection_on_destruction_ = false;
+
+  absl::optional<base::TimeDelta> quic_protocol_error_retry_delay_;
 };
 
 }  // namespace net
diff --git a/net/http/http_stream.cc b/net/http/http_stream.cc
new file mode 100644
index 0000000..d1e6ace
--- /dev/null
+++ b/net/http/http_stream.cc
@@ -0,0 +1,18 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/http/http_stream.h"
+
+namespace net {
+
+absl::optional<quic::QuicErrorCode> HttpStream::GetQuicErrorCode() const {
+  return absl::nullopt;
+}
+
+absl::optional<quic::QuicRstStreamErrorCode>
+HttpStream::GetQuicRstStreamErrorCode() const {
+  return absl::nullopt;
+}
+
+}  // namespace net
diff --git a/net/http/http_stream.h b/net/http/http_stream.h
index f8f40d2..7e37392 100644
--- a/net/http/http_stream.h
+++ b/net/http/http_stream.h
@@ -24,6 +24,8 @@
 #include "net/base/net_export.h"
 #include "net/base/request_priority.h"
 #include "net/http/http_raw_request_headers.h"
+#include "net/third_party/quiche/src/quiche/quic/core/quic_error_codes.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace net {
 
@@ -211,6 +213,15 @@
   // Accept-CH header fields received in HTTP responses, this value is available
   // before any requests are made.
   virtual base::StringPiece GetAcceptChViaAlps() const = 0;
+
+  // If `this` is using a Quic stream, set the `connection_error` of the Quic
+  // stream. Otherwise returns nullopt.
+  virtual absl::optional<quic::QuicErrorCode> GetQuicErrorCode() const;
+
+  // If `this` is using a Quic stream, set the `stream_error' status of the Quic
+  // stream. Otherwise returns nullopt.
+  virtual absl::optional<quic::QuicRstStreamErrorCode>
+  GetQuicRstStreamErrorCode() const;
 };
 
 }  // namespace net
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc
index c646c5d2..c6973e29 100644
--- a/net/quic/quic_http_stream.cc
+++ b/net/quic/quic_http_stream.cc
@@ -433,6 +433,21 @@
   return session()->GetAcceptChViaAlps(url::SchemeHostPort(request_info_->url));
 }
 
+absl::optional<quic::QuicErrorCode> QuicHttpStream::GetQuicErrorCode() const {
+  if (stream_) {
+    return stream_->connection_error();
+  }
+  return connection_error_;
+}
+
+absl::optional<quic::QuicRstStreamErrorCode>
+QuicHttpStream::GetQuicRstStreamErrorCode() const {
+  if (stream_) {
+    return stream_->stream_error();
+  }
+  return stream_error_;
+}
+
 void QuicHttpStream::ReadTrailingHeaders() {
   int rv = stream_->ReadTrailingHeaders(
       &trailing_header_block_,
@@ -762,6 +777,8 @@
   closed_stream_received_bytes_ = stream_->NumBytesConsumed();
   closed_stream_sent_bytes_ = stream_->stream_bytes_written();
   closed_is_first_stream_ = stream_->IsFirstStream();
+  connection_error_ = stream_->connection_error();
+  stream_error_ = stream_->stream_error();
 }
 
 int QuicHttpStream::MapStreamError(int rv) {
diff --git a/net/quic/quic_http_stream.h b/net/quic/quic_http_stream.h
index 812bc4e..5b6872e 100644
--- a/net/quic/quic_http_stream.h
+++ b/net/quic/quic_http_stream.h
@@ -76,6 +76,9 @@
   void SetRequestIdempotency(Idempotency idempotency) override;
   const std::set<std::string>& GetDnsAliases() const override;
   base::StringPiece GetAcceptChViaAlps() const override;
+  absl::optional<quic::QuicErrorCode> GetQuicErrorCode() const override;
+  absl::optional<quic::QuicRstStreamErrorCode> GetQuicRstStreamErrorCode()
+      const override;
 
   static HttpResponseInfo::ConnectionInfo ConnectionInfoFromQuicVersion(
       quic::ParsedQuicVersion quic_version);
@@ -205,6 +208,9 @@
   // the default value of false.
   bool closed_is_first_stream_ = false;
 
+  absl::optional<quic::QuicErrorCode> connection_error_;
+  absl::optional<quic::QuicRstStreamErrorCode> stream_error_;
+
   // The caller's callback to be used for asynchronous operations.
   CompletionOnceCallback callback_;
 
diff --git a/services/device/BUILD.gn b/services/device/BUILD.gn
index 830c8d1..210581e 100644
--- a/services/device/BUILD.gn
+++ b/services/device/BUILD.gn
@@ -201,6 +201,7 @@
   if (is_win) {
     sources += [
       "battery/battery_status_manager_win_unittest.cc",
+      "compute_pressure/cpu_probe_win_unittest.cc",
       "generic_sensor/platform_sensor_and_provider_unittest_win.cc",
       "geolocation/wifi_data_provider_win_unittest.cc",
     ]
@@ -373,7 +374,10 @@
   }
 
   if (is_mac) {
-    sources += [ "geolocation/core_location_provider_unittest.mm" ]
+    sources += [
+      "compute_pressure/cpu_probe_mac_unittest.cc",
+      "geolocation/core_location_provider_unittest.mm",
+    ]
   }
 
   # UsbContext is a libusb-specific object.
diff --git a/services/device/compute_pressure/core_times.cc b/services/device/compute_pressure/core_times.cc
index afbae93..38bb2e3 100644
--- a/services/device/compute_pressure/core_times.cc
+++ b/services/device/compute_pressure/core_times.cc
@@ -9,7 +9,7 @@
 namespace device {
 
 CoreTimes::CoreTimes(const std::initializer_list<uint64_t>& times) {
-  DCHECK_EQ(times.size(), 10u);
+  CHECK_EQ(times.size(), 10u);
 
   size_t i = 0;
   for (auto value : times)
diff --git a/services/device/compute_pressure/cpu_probe.cc b/services/device/compute_pressure/cpu_probe.cc
index 9aa0bada..e049ee7 100644
--- a/services/device/compute_pressure/cpu_probe.cc
+++ b/services/device/compute_pressure/cpu_probe.cc
@@ -53,7 +53,7 @@
     base::RepeatingCallback<void(mojom::PressureState)> sampling_callback)
     : sampling_interval_(sampling_interval),
       sampling_callback_(std::move(sampling_callback)) {
-  DCHECK(sampling_callback_);
+  CHECK(sampling_callback_);
 }
 
 CpuProbe::~CpuProbe() {
@@ -67,7 +67,7 @@
     return;
   }
 
-  DCHECK(!got_probe_baseline_) << "got_probe_baseline_ incorrectly reset";
+  CHECK(!got_probe_baseline_) << "got_probe_baseline_ incorrectly reset";
 
   // Schedule the first CpuProbe update right away. This update result will
   // not be reported, thanks to the accounting done by `got_probe_baseline_`.
diff --git a/services/device/compute_pressure/cpu_probe_linux.cc b/services/device/compute_pressure/cpu_probe_linux.cc
index 8934d5df..1c5651c5 100644
--- a/services/device/compute_pressure/cpu_probe_linux.cc
+++ b/services/device/compute_pressure/cpu_probe_linux.cc
@@ -82,7 +82,7 @@
   double utilization_sum = 0.0;
   int utilization_cores = 0;
   for (size_t i = 0; i < per_core_times.size(); ++i) {
-    DCHECK_GE(last_per_core_times_.size(), i);
+    CHECK_GE(last_per_core_times_.size(), i);
 
     const CoreTimes& core_times = per_core_times[i];
 
@@ -118,7 +118,7 @@
     size_t core_index,
     const CoreTimes& initial_core_times) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK_EQ(last_per_core_times_.size(), core_index);
+  CHECK_EQ(last_per_core_times_.size(), core_index);
 
   last_per_core_times_.push_back(initial_core_times);
 }
diff --git a/services/device/compute_pressure/cpu_probe_linux_unittest.cc b/services/device/compute_pressure/cpu_probe_linux_unittest.cc
index 60983d0d..32c8cd05 100644
--- a/services/device/compute_pressure/cpu_probe_linux_unittest.cc
+++ b/services/device/compute_pressure/cpu_probe_linux_unittest.cc
@@ -11,41 +11,13 @@
 #include "base/functional/callback_helpers.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/task/sequenced_task_runner.h"
-#include "base/test/repeating_test_future.h"
 #include "base/test/task_environment.h"
 #include "services/device/compute_pressure/cpu_probe.h"
+#include "services/device/compute_pressure/pressure_test_support.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace device {
 
-// TestDouble for CpuProbeLinux that overrides OnPressureSampleAvailable()
-// to get PressureSample.
-class FakeCpuProbeLinux : public CpuProbeLinux {
- public:
-  FakeCpuProbeLinux(
-      base::TimeDelta sampling_interval,
-      base::RepeatingCallback<void(mojom::PressureState)> sampling_callback,
-      base::FilePath procfs_stat_path)
-      : CpuProbeLinux(sampling_interval,
-                      std::move(sampling_callback),
-                      std::move(procfs_stat_path)) {}
-  ~FakeCpuProbeLinux() override = default;
-
-  FakeCpuProbeLinux(const FakeCpuProbeLinux&) = delete;
-  FakeCpuProbeLinux& operator=(const FakeCpuProbeLinux&) = delete;
-
-  void OnPressureSampleAvailable(PressureSample sample) override {
-    CpuProbeLinux::OnPressureSampleAvailable(sample);
-    sample_.AddValue(std::move(sample));
-  }
-
-  PressureSample WaitForSample() { return sample_.Take(); }
-
- private:
-  base::test::RepeatingTestFuture<PressureSample> sample_;
-};
-
 class CpuProbeLinuxTest : public testing::Test {
  public:
   CpuProbeLinuxTest() = default;
@@ -61,7 +33,7 @@
     stat_file_ = base::File(fake_stat_path_, base::File::FLAG_CREATE_ALWAYS |
                                                  base::File::FLAG_WRITE);
 
-    probe_ = std::make_unique<FakeCpuProbeLinux>(
+    probe_ = std::make_unique<FakePlatformCpuProbe<CpuProbeLinux>>(
         base::Milliseconds(10), base::DoNothing(), fake_stat_path_);
   }
 
@@ -80,7 +52,7 @@
   base::ScopedTempDir temp_dir_;
   base::FilePath fake_stat_path_;
   base::File stat_file_;
-  std::unique_ptr<FakeCpuProbeLinux> probe_;
+  std::unique_ptr<FakePlatformCpuProbe<CpuProbeLinux>> probe_;
 };
 
 TEST_F(CpuProbeLinuxTest, ProductionDataNoCrash) {
diff --git a/services/device/compute_pressure/cpu_probe_mac.cc b/services/device/compute_pressure/cpu_probe_mac.cc
index f796149..907daaf 100644
--- a/services/device/compute_pressure/cpu_probe_mac.cc
+++ b/services/device/compute_pressure/cpu_probe_mac.cc
@@ -83,7 +83,7 @@
   double utilization_sum = 0.0;
   int utilization_cores = 0;
   for (size_t i = 0; i < per_core_times.size(); ++i) {
-    DCHECK_GE(last_per_core_times_.size(), i);
+    CHECK_GE(last_per_core_times_.size(), i);
 
     const CoreTimes& core_times = per_core_times[i];
 
@@ -119,7 +119,7 @@
     size_t core_index,
     const CoreTimes& initial_core_times) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK_EQ(last_per_core_times_.size(), core_index);
+  CHECK_EQ(last_per_core_times_.size(), core_index);
 
   last_per_core_times_.push_back(initial_core_times);
 }
diff --git a/services/device/compute_pressure/cpu_probe_mac.h b/services/device/compute_pressure/cpu_probe_mac.h
index ef1800f..332e431 100644
--- a/services/device/compute_pressure/cpu_probe_mac.h
+++ b/services/device/compute_pressure/cpu_probe_mac.h
@@ -28,12 +28,15 @@
   CpuProbeMac(const CpuProbeMac&) = delete;
   CpuProbeMac& operator=(const CpuProbeMac&) = delete;
 
- private:
-  class BlockingTaskRunnerHelper;
-
+ protected:
   CpuProbeMac(base::TimeDelta,
               base::RepeatingCallback<void(mojom::PressureState)>);
 
+ private:
+  FRIEND_TEST_ALL_PREFIXES(CpuProbeMacTest, ProductionDataNoCrash);
+
+  class BlockingTaskRunnerHelper;
+
   // CpuProbe implementation.
   void Update() override;
 
diff --git a/services/device/compute_pressure/cpu_probe_mac_unittest.cc b/services/device/compute_pressure/cpu_probe_mac_unittest.cc
new file mode 100644
index 0000000..4bb6803
--- /dev/null
+++ b/services/device/compute_pressure/cpu_probe_mac_unittest.cc
@@ -0,0 +1,43 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/device/compute_pressure/cpu_probe_mac.h"
+
+#include "base/functional/callback_helpers.h"
+#include "base/test/task_environment.h"
+#include "services/device/compute_pressure/cpu_probe.h"
+#include "services/device/compute_pressure/pressure_test_support.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace device {
+
+class CpuProbeMacTest : public testing::Test {
+ public:
+  CpuProbeMacTest() = default;
+
+  ~CpuProbeMacTest() override = default;
+
+  void SetUp() override {
+    probe_ = std::make_unique<FakePlatformCpuProbe<CpuProbeMac>>(
+        base::Milliseconds(10), base::DoNothing());
+  }
+
+ protected:
+  base::test::TaskEnvironment task_environment_;
+  std::unique_ptr<FakePlatformCpuProbe<CpuProbeMac>> probe_;
+};
+
+TEST_F(CpuProbeMacTest, ProductionDataNoCrash) {
+  probe_->Update();
+  EXPECT_EQ(probe_->WaitForSample().cpu_utilization,
+            CpuProbe::kUnsupportedValue.cpu_utilization)
+      << "No baseline on first Update()";
+
+  probe_->Update();
+  PressureSample sample = probe_->WaitForSample();
+  EXPECT_GE(sample.cpu_utilization, 0.0);
+  EXPECT_LE(sample.cpu_utilization, 1.0);
+}
+
+}  // namespace device
diff --git a/services/device/compute_pressure/cpu_probe_unittest.cc b/services/device/compute_pressure/cpu_probe_unittest.cc
index c62ac740..fa36e00 100644
--- a/services/device/compute_pressure/cpu_probe_unittest.cc
+++ b/services/device/compute_pressure/cpu_probe_unittest.cc
@@ -65,7 +65,7 @@
  private:
   void SetNextUpdateCallback(base::OnceClosure callback) {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    DCHECK(!update_callback_)
+    CHECK(!update_callback_)
         << __func__ << " already called before update received";
     update_callback_ = std::move(callback);
   }
diff --git a/services/device/compute_pressure/cpu_probe_win.h b/services/device/compute_pressure/cpu_probe_win.h
index 1de3fa7..d7df5aa5 100644
--- a/services/device/compute_pressure/cpu_probe_win.h
+++ b/services/device/compute_pressure/cpu_probe_win.h
@@ -28,12 +28,15 @@
   CpuProbeWin(const CpuProbeWin&) = delete;
   CpuProbeWin& operator=(const CpuProbeWin&) = delete;
 
- private:
-  class BlockingTaskRunnerHelper;
-
+ protected:
   CpuProbeWin(base::TimeDelta,
               base::RepeatingCallback<void(mojom::PressureState)>);
 
+ private:
+  FRIEND_TEST_ALL_PREFIXES(CpuProbeWinTest, ProductionDataNoCrash);
+
+  class BlockingTaskRunnerHelper;
+
   // CpuProbe implementation.
   void Update() override;
 
diff --git a/services/device/compute_pressure/cpu_probe_win_unittest.cc b/services/device/compute_pressure/cpu_probe_win_unittest.cc
new file mode 100644
index 0000000..a301e0e
--- /dev/null
+++ b/services/device/compute_pressure/cpu_probe_win_unittest.cc
@@ -0,0 +1,43 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/device/compute_pressure/cpu_probe_win.h"
+
+#include "base/functional/callback_helpers.h"
+#include "base/test/task_environment.h"
+#include "services/device/compute_pressure/cpu_probe.h"
+#include "services/device/compute_pressure/pressure_test_support.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace device {
+
+class CpuProbeWinTest : public testing::Test {
+ public:
+  CpuProbeWinTest() = default;
+
+  ~CpuProbeWinTest() override = default;
+
+  void SetUp() override {
+    probe_ = std::make_unique<FakePlatformCpuProbe<CpuProbeWin>>(
+        base::Milliseconds(10), base::DoNothing());
+  }
+
+ protected:
+  base::test::TaskEnvironment task_environment_;
+  std::unique_ptr<FakePlatformCpuProbe<CpuProbeWin>> probe_;
+};
+
+TEST_F(CpuProbeWinTest, ProductionDataNoCrash) {
+  probe_->Update();
+  EXPECT_EQ(probe_->WaitForSample().cpu_utilization,
+            CpuProbe::kUnsupportedValue.cpu_utilization)
+      << "No baseline on first Update()";
+
+  probe_->Update();
+  PressureSample sample = probe_->WaitForSample();
+  EXPECT_GE(sample.cpu_utilization, 0.0);
+  EXPECT_LE(sample.cpu_utilization, 1.0);
+}
+
+}  // namespace device
diff --git a/services/device/compute_pressure/host_processor_info_scanner.cc b/services/device/compute_pressure/host_processor_info_scanner.cc
index 7b69aa6..ed191f1 100644
--- a/services/device/compute_pressure/host_processor_info_scanner.cc
+++ b/services/device/compute_pressure/host_processor_info_scanner.cc
@@ -53,7 +53,7 @@
                          sizeof(processor_cpu_load_info)));
 
   for (natural_t i = 0; i < number_of_processors; ++i) {
-    DCHECK_GE(core_times_.size(), i);
+    CHECK_GE(core_times_.size(), i);
 
     if (core_times_.size() <= i) {
       core_times_.resize(i + 1);
diff --git a/services/device/compute_pressure/pressure_manager_impl_unittest.cc b/services/device/compute_pressure/pressure_manager_impl_unittest.cc
index fe154dc54..184282a 100644
--- a/services/device/compute_pressure/pressure_manager_impl_unittest.cc
+++ b/services/device/compute_pressure/pressure_manager_impl_unittest.cc
@@ -32,9 +32,7 @@
 class PressureManagerImplSync {
  public:
   explicit PressureManagerImplSync(mojom::PressureManager* manager)
-      : manager_(*manager) {
-    DCHECK(manager);
-  }
+      : manager_(raw_ref<mojom::PressureManager>::from_ptr(manager)) {}
   ~PressureManagerImplSync() = default;
 
   PressureManagerImplSync(const PressureManagerImplSync&) = delete;
@@ -75,7 +73,7 @@
   const std::vector<mojom::PressureUpdate>& updates() const { return updates_; }
 
   void SetNextUpdateCallback(base::OnceClosure callback) {
-    DCHECK(!update_callback_) << " already called before update received";
+    CHECK(!update_callback_) << " already called before update received";
     update_callback_ = std::move(callback);
   }
 
diff --git a/services/device/compute_pressure/pressure_test_support.cc b/services/device/compute_pressure/pressure_test_support.cc
index 7c942bca..f1a88a5 100644
--- a/services/device/compute_pressure/pressure_test_support.cc
+++ b/services/device/compute_pressure/pressure_test_support.cc
@@ -51,7 +51,7 @@
     : CpuProbe(sampling_interval, std::move(sampling_callback)),
       samples_(std::move(samples)),
       callback_(std::move(callback)) {
-  DCHECK_GT(samples_.size(), 0u);
+  CHECK_GT(samples_.size(), 0u);
 }
 
 StreamingCpuProbe::~StreamingCpuProbe() {
diff --git a/services/device/compute_pressure/pressure_test_support.h b/services/device/compute_pressure/pressure_test_support.h
index 8660d5abf..d1038525 100644
--- a/services/device/compute_pressure/pressure_test_support.h
+++ b/services/device/compute_pressure/pressure_test_support.h
@@ -7,8 +7,11 @@
 
 #include <stdint.h>
 
+#include <type_traits>
+
 #include "base/functional/callback_forward.h"
 #include "base/synchronization/lock.h"
+#include "base/test/repeating_test_future.h"
 #include "base/thread_annotations.h"
 #include "base/time/time.h"
 #include "services/device/compute_pressure/cpu_probe.h"
@@ -17,6 +20,28 @@
 
 namespace device {
 
+// Test double for platform specific CpuProbe that overrides
+// OnPressureSampleAvailable() to get PressureSample.
+template <typename T,
+          typename = std::enable_if_t<std::is_base_of_v<CpuProbe, T>>>
+class FakePlatformCpuProbe : public T {
+ public:
+  template <typename... Args>
+  explicit FakePlatformCpuProbe(Args&&... args)
+      : T(std::forward<Args>(args)...) {}
+  ~FakePlatformCpuProbe() override = default;
+
+  void OnPressureSampleAvailable(PressureSample sample) override {
+    T::OnPressureSampleAvailable(sample);
+    sample_.AddValue(std::move(sample));
+  }
+
+  PressureSample WaitForSample() { return sample_.Take(); }
+
+ private:
+  base::test::RepeatingTestFuture<PressureSample> sample_;
+};
+
 // Test double for CpuProbe that always returns a predetermined value.
 class FakeCpuProbe : public CpuProbe {
  public:
diff --git a/services/device/compute_pressure/procfs_stat_cpu_parser.cc b/services/device/compute_pressure/procfs_stat_cpu_parser.cc
index 03a2244..dc3a21dd 100644
--- a/services/device/compute_pressure/procfs_stat_cpu_parser.cc
+++ b/services/device/compute_pressure/procfs_stat_cpu_parser.cc
@@ -69,7 +69,7 @@
     if (core_id < 0)
       continue;
 
-    DCHECK_LE(core_times_.size(), size_t{std::numeric_limits<int>::max()});
+    CHECK_LE(core_times_.size(), size_t{std::numeric_limits<int>::max()});
     if (static_cast<int>(core_times_.size()) <= core_id)
       core_times_.resize(core_id + 1);
 
@@ -102,7 +102,7 @@
 // static
 void ProcfsStatCpuParser::UpdateCore(base::StringPiece core_line,
                                      CoreTimes& core_times) {
-  DCHECK_GE(CoreIdFromLine(core_line), 0);
+  CHECK_GE(CoreIdFromLine(core_line), 0);
 
   static constexpr base::StringPiece kSpaceSeparator(" ", 1);
   std::vector<base::StringPiece> tokens = base::SplitStringPiece(
diff --git a/services/device/public/cpp/test/scoped_pressure_manager_overrider.cc b/services/device/public/cpp/test/scoped_pressure_manager_overrider.cc
index 664048f..5c497c20 100644
--- a/services/device/public/cpp/test/scoped_pressure_manager_overrider.cc
+++ b/services/device/public/cpp/test/scoped_pressure_manager_overrider.cc
@@ -66,7 +66,7 @@
 
 void ScopedPressureManagerOverrider::set_fake_pressure_manager(
     std::unique_ptr<FakePressureManager> pressure_manager) {
-  DCHECK(!pressure_manager_->is_bound());
+  CHECK(!pressure_manager_->is_bound());
   pressure_manager_ = std::move(pressure_manager);
   DeviceService::OverridePressureManagerBinderForTesting(base::BindRepeating(
       &FakePressureManager::Bind, base::Unretained(pressure_manager_.get())));
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 567cc76d..ceff1c7 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -1522,9 +1522,12 @@
       {
         "args": [],
         "bucket": "chromiumos-image-archive",
-        "cros_board": "zork",
-        "cros_img": "zork-public/R110-15277.0.0",
-        "name": "lacros_all_tast_tests ZORK_PUBLIC",
+        "cros_board": "eve",
+        "cros_img": "eve-public/R114-15410.0.0",
+        "dut_pool": "chromium",
+        "name": "lacros_all_tast_tests EVE_PUBLIC_LKGM",
+        "public_builder": "cros_test_platform_public",
+        "public_builder_bucket": "testplatform-public",
         "resultdb": {
           "enable": true,
           "has_native_resultdb_integration": true
@@ -1535,7 +1538,7 @@
         "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests/",
         "test_level_retries": 2,
         "timeout_sec": 10800,
-        "variant_id": "ZORK_PUBLIC"
+        "variant_id": "EVE_PUBLIC_LKGM"
       }
     ]
   },
@@ -5618,9 +5621,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5631,8 +5634,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
@@ -5783,9 +5786,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5796,8 +5799,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
@@ -5930,9 +5933,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5943,8 +5946,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json
index 66caf37..9a0c86d 100644
--- a/testing/buildbot/chromium.coverage.json
+++ b/testing/buildbot/chromium.coverage.json
@@ -25212,9 +25212,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25225,8 +25225,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
@@ -25377,9 +25377,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25390,8 +25390,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
@@ -25524,9 +25524,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25537,8 +25537,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 7e2b986..0c004b3d 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -31112,7 +31112,10 @@
         "bucket": "chromiumos-image-archive",
         "cros_board": "eve",
         "cros_img": "eve-public/R114-15410.0.0",
+        "dut_pool": "chromium",
         "name": "lacros_all_tast_tests EVE_PUBLIC_LKGM",
+        "public_builder": "cros_test_platform_public",
+        "public_builder_bucket": "testplatform-public",
         "resultdb": {
           "enable": true,
           "has_native_resultdb_integration": true
@@ -33946,9 +33949,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -33958,8 +33961,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
@@ -34111,9 +34114,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -34123,8 +34126,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
@@ -34258,9 +34261,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -34270,8 +34273,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
@@ -35698,9 +35701,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -35710,8 +35713,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
@@ -35863,9 +35866,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -35875,8 +35878,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
@@ -36010,9 +36013,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -36022,8 +36025,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
@@ -36739,9 +36742,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -36751,8 +36754,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 8912b3c1..b233455 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -17723,12 +17723,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -17739,8 +17739,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
@@ -17908,12 +17908,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -17924,8 +17924,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
@@ -18070,12 +18070,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 114.0.5713.0",
+        "description": "Run with ash-chrome version 114.0.5714.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -18086,8 +18086,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5713.0",
-              "revision": "version:114.0.5713.0"
+              "location": "lacros_version_skew_tests_v114.0.5714.0",
+              "revision": "version:114.0.5714.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 458c6123..568303f 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -7378,7 +7378,7 @@
     'lacros_skylab_tests_amd64_generic_rel': {
       'lacros_skylab_tests': {
         'variants': [
-          'CROS_ZORK_PUBLIC',
+          'CROS_EVE_PUBLIC_LKGM',
         ]
       },
     },
diff --git a/testing/buildbot/tryserver.chromium.chromiumos.json b/testing/buildbot/tryserver.chromium.chromiumos.json
index 5b22e20..328e6d9f 100644
--- a/testing/buildbot/tryserver.chromium.chromiumos.json
+++ b/testing/buildbot/tryserver.chromium.chromiumos.json
@@ -9,9 +9,12 @@
       {
         "args": [],
         "bucket": "chromiumos-image-archive",
-        "cros_board": "zork",
-        "cros_img": "zork-public/R110-15277.0.0",
-        "name": "lacros_all_tast_tests ZORK_PUBLIC",
+        "cros_board": "eve",
+        "cros_img": "eve-public/R114-15410.0.0",
+        "dut_pool": "chromium",
+        "name": "lacros_all_tast_tests EVE_PUBLIC_LKGM",
+        "public_builder": "cros_test_platform_public",
+        "public_builder_bucket": "testplatform-public",
         "resultdb": {
           "enable": true,
           "has_native_resultdb_integration": true
@@ -22,7 +25,7 @@
         "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests/",
         "test_level_retries": 2,
         "timeout_sec": 10800,
-        "variant_id": "ZORK_PUBLIC"
+        "variant_id": "EVE_PUBLIC_LKGM"
       }
     ]
   }
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 6670906..70595d0 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -22,16 +22,16 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5713.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5714.0/test_ash_chrome',
     ],
-    'description': 'Run with ash-chrome version 114.0.5713.0',
+    'description': 'Run with ash-chrome version 114.0.5714.0',
     'identifier': 'Lacros version skew testing ash canary',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v114.0.5713.0',
-          'revision': 'version:114.0.5713.0',
+          'location': 'lacros_version_skew_tests_v114.0.5714.0',
+          'revision': 'version:114.0.5714.0',
         },
       ],
     },
@@ -469,6 +469,9 @@
       'cros_chrome_version': '114.0.5692.0',
       'cros_img': 'eve-public/R114-15410.0.0',
       'bucket': 'chromiumos-image-archive',
+      'dut_pool': 'chromium',
+      'public_builder': 'cros_test_platform_public',
+      'public_builder_bucket': 'testplatform-public',
     },
     'enabled': True,
     'identifier': 'EVE_PUBLIC_LKGM',
@@ -724,16 +727,6 @@
     'enabled': True,
     'identifier': 'VOLTEER_RELEASE_LKGM',
   },
-  'CROS_ZORK_PUBLIC': {
-    'skylab': {
-      'cros_board': 'zork',
-      'cros_chrome_version': '110.0.5464.0',
-      'cros_img': 'zork-public/R110-15277.0.0',
-      'bucket': 'chromiumos-image-archive',
-    },
-    'enabled': True,
-    'identifier': 'ZORK_PUBLIC',
-  },
   'LACROS_AMD64_GENERIC': {
     'args': [
       '--board=amd64-generic',
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
index 47472a8..1d52fd0 100644
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -2301,6 +2301,7 @@
       keywords: ["auto"],
       default_value: "Length()",
       typedom_types: ["Keyword", "Length", "Percentage"],
+      computed_style_protected_functions: ["getter"],
       converter: "ConvertLengthOrAuto",
       logical_property_group: {
         name: "inset",
@@ -3014,6 +3015,7 @@
       keywords: ["auto", "fit-content", "min-content", "max-content"],
       default_value: "Length()",
       typedom_types: ["Keyword", "Length", "Percentage"],
+      computed_style_protected_functions: ["getter"],
       converter: "ConvertLengthSizing",
       logical_property_group: {
         name: "size",
@@ -3138,6 +3140,7 @@
       keywords: ["auto"],
       default_value: "Length()",
       typedom_types: ["Keyword", "Length", "Percentage"],
+      computed_style_protected_functions: ["getter"],
       converter: "ConvertLengthOrAuto",
       logical_property_group: {
         name: "inset",
@@ -3406,6 +3409,7 @@
       field_group: "box",
       field_template: "<length>",
       default_value: "Length::None()",
+      computed_style_protected_functions: ["getter"],
       converter: "ConvertLengthMaxSizing",
       keywords: ["none"],
       typedom_types: ["Keyword", "Length", "Percentage"],
@@ -3423,6 +3427,7 @@
       field_group: "box",
       field_template: "<length>",
       default_value: "Length::None()",
+      computed_style_protected_functions: ["getter"],
       converter: "ConvertLengthMaxSizing",
       keywords: ["none"],
       typedom_types: ["Keyword", "Length", "Percentage"],
@@ -3440,6 +3445,7 @@
       field_group: "box",
       field_template: "<length>",
       default_value: "Length()",
+      computed_style_protected_functions: ["getter"],
       converter: "ConvertLengthSizing",
       typedom_types: ["Length", "Percentage"],
       logical_property_group: {
@@ -3456,6 +3462,7 @@
       field_group: "box",
       field_template: "<length>",
       default_value: "Length()",
+      computed_style_protected_functions: ["getter"],
       converter: "ConvertLengthSizing",
       typedom_types: ["Length", "Percentage"],
       logical_property_group: {
@@ -4058,6 +4065,7 @@
       keywords: ["auto"],
       default_value: "Length()",
       typedom_types: ["Keyword", "Length", "Percentage"],
+      computed_style_protected_functions: ["getter"],
       converter: "ConvertLengthOrAuto",
       logical_property_group: {
         name: "inset",
@@ -4707,8 +4715,8 @@
       property_methods: ["CSSValueFromComputedStyleInternal"],
       field_group: "box",
       field_template: "keyword",
-      default_value: "normal",
-      keywords: ["normal", "start", "end", "both"],
+      default_value: "none",
+      keywords: ["none", "start", "end", "both"],
       typedom_types: ["Keyword"],
       runtime_flag: "CSSTextBoxTrim",
     },
@@ -5002,6 +5010,7 @@
       keywords: ["auto"],
       default_value: "Length()",
       typedom_types: ["Keyword", "Length", "Percentage"],
+      computed_style_protected_functions: ["getter"],
       converter: "ConvertLengthOrAuto",
       logical_property_group: {
         name: "inset",
@@ -5991,6 +6000,7 @@
       keywords: ["auto", "fit-content", "min-content", "max-content"],
       default_value: "Length()",
       typedom_types: ["Keyword", "Length", "Percentage"],
+      computed_style_protected_functions: ["getter"],
       converter: "ConvertLengthSizing",
       logical_property_group: {
         name: "size",
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
index c1e63e7..336ef27 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
@@ -1404,9 +1404,8 @@
       return value_id == CSSValueID::kNormal || value_id == CSSValueID::kNone;
     case CSSPropertyID::kTextBoxTrim:
       DCHECK(RuntimeEnabledFeatures::CSSTextBoxTrimEnabled());
-      return value_id == CSSValueID::kNormal ||
-             value_id == CSSValueID::kStart || value_id == CSSValueID::kEnd ||
-             value_id == CSSValueID::kBoth;
+      return value_id == CSSValueID::kNone || value_id == CSSValueID::kStart ||
+             value_id == CSSValueID::kEnd || value_id == CSSValueID::kBoth;
     default:
       NOTREACHED();
       return false;
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
index aaef73b..4c3909cc 100644
--- a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
+++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
@@ -577,22 +577,22 @@
   bool is_right_or_bottom;
   switch (property.PropertyID()) {
     case CSSPropertyID::kLeft:
-      positions = std::make_pair(&style.Left(), &style.Right());
+      positions = std::make_pair(&style.UsedLeft(), &style.UsedRight());
       is_horizontal_property = true;
       is_right_or_bottom = false;
       break;
     case CSSPropertyID::kRight:
-      positions = std::make_pair(&style.Right(), &style.Left());
+      positions = std::make_pair(&style.UsedRight(), &style.UsedLeft());
       is_horizontal_property = true;
       is_right_or_bottom = true;
       break;
     case CSSPropertyID::kTop:
-      positions = std::make_pair(&style.Top(), &style.Bottom());
+      positions = std::make_pair(&style.UsedTop(), &style.UsedBottom());
       is_horizontal_property = false;
       is_right_or_bottom = false;
       break;
     case CSSPropertyID::kBottom:
-      positions = std::make_pair(&style.Bottom(), &style.Top());
+      positions = std::make_pair(&style.UsedBottom(), &style.UsedTop());
       is_horizontal_property = false;
       is_right_or_bottom = true;
       break;
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
index ce6f441..4493be44 100644
--- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -138,49 +138,6 @@
   builder.SetTextUnderlinePosition(TextUnderlinePosition::kAuto);
 }
 
-// Adjust style for anchor() and anchor-size() queries.
-void AdjustAnchorQueryStyles(ComputedStyleBuilder& builder) {
-  if (!RuntimeEnabledFeatures::CSSAnchorPositioningEnabled()) {
-    return;
-  }
-
-  // anchor() and anchor-size() can only be used on absolutely positioned
-  // elements.
-  EPosition position = builder.GetPosition();
-  if (position != EPosition::kAbsolute && position != EPosition::kFixed) {
-    if (builder.Left().HasAnchorQueries()) {
-      builder.SetLeft(Length::Auto());
-    }
-    if (builder.Right().HasAnchorQueries()) {
-      builder.SetRight(Length::Auto());
-    }
-    if (builder.Top().HasAnchorQueries()) {
-      builder.SetTop(Length::Auto());
-    }
-    if (builder.Bottom().HasAnchorQueries()) {
-      builder.SetBottom(Length::Auto());
-    }
-    if (builder.Width().HasAnchorQueries()) {
-      builder.SetWidth(Length::Auto());
-    }
-    if (builder.MinWidth().HasAnchorQueries()) {
-      builder.SetMinWidth(Length::Auto());
-    }
-    if (builder.MaxWidth().HasAnchorQueries()) {
-      builder.SetMaxWidth(Length::Auto());
-    }
-    if (builder.Height().HasAnchorQueries()) {
-      builder.SetHeight(Length::Auto());
-    }
-    if (builder.MinHeight().HasAnchorQueries()) {
-      builder.SetMinHeight(Length::Auto());
-    }
-    if (builder.MaxHeight().HasAnchorQueries()) {
-      builder.SetMaxHeight(Length::Auto());
-    }
-  }
-}
-
 bool ElementForcesStackingContext(Element* element) {
   if (!element) {
     return false;
@@ -1114,8 +1071,6 @@
     }
   }
 
-  AdjustAnchorQueryStyles(builder);
-
   if (element && element->HasCustomStyleCallbacks()) {
     element->AdjustStyle(base::PassKey<StyleAdjuster>(), builder);
   }
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
index c188bb6..e7d16db5 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
@@ -77,6 +77,36 @@
   bool IsUseCounted(mojom::WebFeature feature) {
     return GetDocument().IsUseCounted(feature);
   }
+
+  // Access protected inset and sizing property getters
+  const Length& GetTop(const ComputedStyle& style) const { return style.Top(); }
+  const Length& GetBottom(const ComputedStyle& style) const {
+    return style.Bottom();
+  }
+  const Length& GetLeft(const ComputedStyle& style) const {
+    return style.Left();
+  }
+  const Length& GetRight(const ComputedStyle& style) const {
+    return style.Right();
+  }
+  const Length& GetWidth(const ComputedStyle& style) const {
+    return style.Width();
+  }
+  const Length& GetMinWidth(const ComputedStyle& style) const {
+    return style.MinWidth();
+  }
+  const Length& GetMaxWidth(const ComputedStyle& style) const {
+    return style.MaxWidth();
+  }
+  const Length& GetHeight(const ComputedStyle& style) const {
+    return style.Height();
+  }
+  const Length& GetMinHeight(const ComputedStyle& style) const {
+    return style.MinHeight();
+  }
+  const Length& GetMaxHeight(const ComputedStyle& style) const {
+    return style.MaxHeight();
+  }
 };
 
 class StyleResolverTestCQ : public StyleResolverTest {
@@ -2669,26 +2699,26 @@
   Element* target = GetElementById("target");
   const ComputedStyle* base_style = target->GetComputedStyle();
   ASSERT_TRUE(base_style);
-  EXPECT_EQ(Length::Auto(), base_style->Top());
-  EXPECT_EQ(Length::Auto(), base_style->Left());
+  EXPECT_EQ(Length::Auto(), GetTop(*base_style));
+  EXPECT_EQ(Length::Auto(), GetLeft(*base_style));
 
   const ComputedStyle* try1 = target->StyleForPositionFallback(0);
   ASSERT_TRUE(try1);
-  EXPECT_EQ(Length::Auto(), try1->Top());
-  EXPECT_EQ(Length::Fixed(100), try1->Left());
+  EXPECT_EQ(Length::Auto(), GetTop(*try1));
+  EXPECT_EQ(Length::Fixed(100), GetLeft(*try1));
 
   const ComputedStyle* try2 = target->StyleForPositionFallback(1);
   ASSERT_TRUE(try2);
-  EXPECT_EQ(Length::Fixed(100), try2->Top());
-  EXPECT_EQ(Length::Auto(), try2->Left());
+  EXPECT_EQ(Length::Fixed(100), GetTop(*try2));
+  EXPECT_EQ(Length::Auto(), GetLeft(*try2));
 
   // Shorthand should also work
   const ComputedStyle* try3 = target->StyleForPositionFallback(2);
   ASSERT_TRUE(try3);
-  EXPECT_EQ(Length::Fixed(50), try3->Top());
-  EXPECT_EQ(Length::Fixed(50), try3->Left());
-  EXPECT_EQ(Length::Fixed(50), try3->Bottom());
-  EXPECT_EQ(Length::Fixed(50), try3->Right());
+  EXPECT_EQ(Length::Fixed(50), GetTop(*try3));
+  EXPECT_EQ(Length::Fixed(50), GetLeft(*try3));
+  EXPECT_EQ(Length::Fixed(50), GetBottom(*try3));
+  EXPECT_EQ(Length::Fixed(50), GetRight(*try3));
 
   // Returns nullptr when index is out of bound.
   EXPECT_FALSE(target->StyleForPositionFallback(3));
@@ -2738,26 +2768,26 @@
   Element* target = GetElementById("target");
   const ComputedStyle* base_style = target->GetComputedStyle();
   ASSERT_TRUE(base_style);
-  EXPECT_EQ(Length::Fixed(50), base_style->Top());
-  EXPECT_EQ(Length::Fixed(50), base_style->Left());
-  EXPECT_EQ(Length::Fixed(50), base_style->Bottom());
-  EXPECT_EQ(Length::Fixed(50), base_style->Right());
+  EXPECT_EQ(Length::Fixed(50), GetTop(*base_style));
+  EXPECT_EQ(Length::Fixed(50), GetLeft(*base_style));
+  EXPECT_EQ(Length::Fixed(50), GetBottom(*base_style));
+  EXPECT_EQ(Length::Fixed(50), GetRight(*base_style));
 
   // 'inset-inline-start' should resolve to 'bottom'
   const ComputedStyle* try1 = target->StyleForPositionFallback(0);
   ASSERT_TRUE(try1);
-  EXPECT_EQ(Length::Fixed(50), try1->Top());
-  EXPECT_EQ(Length::Fixed(50), try1->Left());
-  EXPECT_EQ(Length::Fixed(100), try1->Bottom());
-  EXPECT_EQ(Length::Fixed(50), try1->Right());
+  EXPECT_EQ(Length::Fixed(50), GetTop(*try1));
+  EXPECT_EQ(Length::Fixed(50), GetLeft(*try1));
+  EXPECT_EQ(Length::Fixed(100), GetBottom(*try1));
+  EXPECT_EQ(Length::Fixed(50), GetRight(*try1));
 
   // 'inset-block' with two parameters should set 'right' and then 'left'
   const ComputedStyle* try2 = target->StyleForPositionFallback(1);
   ASSERT_TRUE(try2);
-  EXPECT_EQ(Length::Fixed(50), try2->Top());
-  EXPECT_EQ(Length::Fixed(90), try2->Left());
-  EXPECT_EQ(Length::Fixed(50), try2->Bottom());
-  EXPECT_EQ(Length::Fixed(100), try2->Right());
+  EXPECT_EQ(Length::Fixed(50), GetTop(*try2));
+  EXPECT_EQ(Length::Fixed(90), GetLeft(*try2));
+  EXPECT_EQ(Length::Fixed(50), GetBottom(*try2));
+  EXPECT_EQ(Length::Fixed(100), GetRight(*try2));
 
   EXPECT_FALSE(target->StyleForPositionFallback(2));
 }
@@ -2784,12 +2814,12 @@
   Element* target = GetElementById("target");
   const ComputedStyle* base_style = target->GetComputedStyle();
   ASSERT_TRUE(base_style);
-  EXPECT_EQ(Length::Auto(), base_style->Top());
+  EXPECT_EQ(Length::Auto(), GetTop(*base_style));
 
   // '2em' should resolve to '40px'
   const ComputedStyle* try1 = target->StyleForPositionFallback(0);
   ASSERT_TRUE(try1);
-  EXPECT_EQ(Length::Fixed(40), try1->Top());
+  EXPECT_EQ(Length::Fixed(40), GetTop(*try1));
 
   EXPECT_FALSE(target->StyleForPositionFallback(1));
 }
@@ -2820,12 +2850,12 @@
 
   const ComputedStyle* base_style = before->GetComputedStyle();
   ASSERT_TRUE(base_style);
-  EXPECT_EQ(Length::Auto(), base_style->Top());
+  EXPECT_EQ(Length::Auto(), GetTop(*base_style));
 
   // 'position-fallback' applies to ::before pseudo-element.
   const ComputedStyle* try1 = before->StyleForPositionFallback(0);
   ASSERT_TRUE(try1);
-  EXPECT_EQ(Length::Fixed(50), try1->Top());
+  EXPECT_EQ(Length::Fixed(50), GetTop(*try1));
 
   EXPECT_FALSE(before->StyleForPositionFallback(1));
 }
@@ -2861,31 +2891,31 @@
   Element* target = GetElementById("target");
   const ComputedStyle* base_style = target->GetComputedStyle();
   ASSERT_TRUE(base_style);
-  EXPECT_EQ(Length::Fixed(50), base_style->Top());
-  EXPECT_EQ(Length::Fixed(50), base_style->Left());
-  EXPECT_EQ(Length::Fixed(50), base_style->Bottom());
-  EXPECT_EQ(Length::Fixed(50), base_style->Right());
+  EXPECT_EQ(Length::Fixed(50), GetTop(*base_style));
+  EXPECT_EQ(Length::Fixed(50), GetLeft(*base_style));
+  EXPECT_EQ(Length::Fixed(50), GetBottom(*base_style));
+  EXPECT_EQ(Length::Fixed(50), GetRight(*base_style));
 
   const ComputedStyle* try1 = target->StyleForPositionFallback(0);
   ASSERT_TRUE(try1);
-  EXPECT_EQ(Length::Auto(), try1->Top());
-  EXPECT_EQ(Length::Fixed(50), try1->Left());
-  EXPECT_EQ(Length::Fixed(50), try1->Bottom());
-  EXPECT_EQ(Length::Fixed(50), try1->Right());
+  EXPECT_EQ(Length::Auto(), GetTop(*try1));
+  EXPECT_EQ(Length::Fixed(50), GetLeft(*try1));
+  EXPECT_EQ(Length::Fixed(50), GetBottom(*try1));
+  EXPECT_EQ(Length::Fixed(50), GetRight(*try1));
 
   const ComputedStyle* try2 = target->StyleForPositionFallback(1);
   ASSERT_TRUE(try2);
-  EXPECT_EQ(Length::Fixed(50), try2->Top());
-  EXPECT_EQ(Length::Fixed(100), try2->Left());
-  EXPECT_EQ(Length::Fixed(50), try2->Bottom());
-  EXPECT_EQ(Length::Fixed(50), try2->Right());
+  EXPECT_EQ(Length::Fixed(50), GetTop(*try2));
+  EXPECT_EQ(Length::Fixed(100), GetLeft(*try2));
+  EXPECT_EQ(Length::Fixed(50), GetBottom(*try2));
+  EXPECT_EQ(Length::Fixed(50), GetRight(*try2));
 
   const ComputedStyle* try3 = target->StyleForPositionFallback(2);
   ASSERT_TRUE(try3);
-  EXPECT_EQ(Length::Fixed(50), try3->Top());
-  EXPECT_EQ(Length::Fixed(50), try3->Left());
-  EXPECT_EQ(Length::Fixed(50), try3->Bottom());
-  EXPECT_EQ(Length::Auto(), try3->Right());
+  EXPECT_EQ(Length::Fixed(50), GetTop(*try3));
+  EXPECT_EQ(Length::Fixed(50), GetLeft(*try3));
+  EXPECT_EQ(Length::Fixed(50), GetBottom(*try3));
+  EXPECT_EQ(Length::Auto(), GetRight(*try3));
 
   EXPECT_FALSE(target->StyleForPositionFallback(3));
 }
@@ -2916,13 +2946,13 @@
   {
     const ComputedStyle* base_style = target->GetComputedStyle();
     ASSERT_TRUE(base_style);
-    EXPECT_EQ(Length::Auto(), base_style->Top());
-    EXPECT_EQ(Length::Auto(), base_style->Left());
+    EXPECT_EQ(Length::Auto(), GetTop(*base_style));
+    EXPECT_EQ(Length::Auto(), GetLeft(*base_style));
 
     const ComputedStyle* fallback = target->StyleForPositionFallback(0);
     ASSERT_TRUE(fallback);
-    EXPECT_EQ(Length::Fixed(100), fallback->Top());
-    EXPECT_EQ(Length::Auto(), fallback->Left());
+    EXPECT_EQ(Length::Fixed(100), GetTop(*fallback));
+    EXPECT_EQ(Length::Auto(), GetLeft(*fallback));
 
     EXPECT_FALSE(target->StyleForPositionFallback(1));
   }
@@ -2933,14 +2963,14 @@
   {
     const ComputedStyle* base_style = target->GetComputedStyle();
     ASSERT_TRUE(base_style);
-    EXPECT_EQ(Length::Auto(), base_style->Top());
-    EXPECT_EQ(Length::Auto(), base_style->Left());
+    EXPECT_EQ(Length::Auto(), GetTop(*base_style));
+    EXPECT_EQ(Length::Auto(), GetLeft(*base_style));
 
     const ComputedStyle* fallback = target->StyleForPositionFallback(0);
     ASSERT_TRUE(fallback);
     ASSERT_TRUE(fallback);
-    EXPECT_EQ(Length::Auto(), fallback->Top());
-    EXPECT_EQ(Length::Fixed(100), fallback->Left());
+    EXPECT_EQ(Length::Auto(), GetTop(*fallback));
+    EXPECT_EQ(Length::Fixed(100), GetLeft(*fallback));
 
     EXPECT_FALSE(target->StyleForPositionFallback(1));
   }
@@ -3155,12 +3185,12 @@
     Element* right = shadow->getElementById("right");
 
     EXPECT_EQ(&GetDocument(),
-              GetAnchorQueryTreeScope(left->ComputedStyleRef().Left()));
+              GetAnchorQueryTreeScope(GetLeft(left->ComputedStyleRef())));
     EXPECT_EQ(&GetDocument(),
-              GetAnchorQueryTreeScope(right->ComputedStyleRef().Right()));
-    EXPECT_EQ(shadow, GetAnchorQueryTreeScope(top->ComputedStyleRef().Top()));
+              GetAnchorQueryTreeScope(GetRight(right->ComputedStyleRef())));
+    EXPECT_EQ(shadow, GetAnchorQueryTreeScope(GetTop(top->ComputedStyleRef())));
     EXPECT_EQ(shadow,
-              GetAnchorQueryTreeScope(bottom->ComputedStyleRef().Bottom()));
+              GetAnchorQueryTreeScope(GetBottom(bottom->ComputedStyleRef())));
   }
 
   {
@@ -3171,14 +3201,14 @@
     Element* block_start = shadow->getElementById("block-start");
     Element* inline_end = shadow->getElementById("inline-end");
 
-    EXPECT_EQ(&GetDocument(),
-              GetAnchorQueryTreeScope(inline_start->ComputedStyleRef().Left()));
-    EXPECT_EQ(&GetDocument(),
-              GetAnchorQueryTreeScope(inline_end->ComputedStyleRef().Right()));
+    EXPECT_EQ(&GetDocument(), GetAnchorQueryTreeScope(
+                                  GetLeft(inline_start->ComputedStyleRef())));
+    EXPECT_EQ(&GetDocument(), GetAnchorQueryTreeScope(
+                                  GetRight(inline_end->ComputedStyleRef())));
     EXPECT_EQ(shadow,
-              GetAnchorQueryTreeScope(block_start->ComputedStyleRef().Top()));
-    EXPECT_EQ(shadow,
-              GetAnchorQueryTreeScope(block_end->ComputedStyleRef().Bottom()));
+              GetAnchorQueryTreeScope(GetTop(block_start->ComputedStyleRef())));
+    EXPECT_EQ(shadow, GetAnchorQueryTreeScope(
+                          GetBottom(block_end->ComputedStyleRef())));
   }
 }
 
@@ -3230,17 +3260,17 @@
   Element* max_height = shadow2->getElementById("max-height");
 
   EXPECT_EQ(&GetDocument(),
-            GetAnchorQueryTreeScope(width->ComputedStyleRef().Width()));
+            GetAnchorQueryTreeScope(GetWidth(width->ComputedStyleRef())));
   EXPECT_EQ(shadow1,
-            GetAnchorQueryTreeScope(height->ComputedStyleRef().Height()));
-  EXPECT_EQ(&GetDocument(),
-            GetAnchorQueryTreeScope(min_width->ComputedStyleRef().MinWidth()));
-  EXPECT_EQ(shadow2,
-            GetAnchorQueryTreeScope(max_width->ComputedStyleRef().MaxWidth()));
-  EXPECT_EQ(shadow2, GetAnchorQueryTreeScope(
-                         min_height->ComputedStyleRef().MinHeight()));
+            GetAnchorQueryTreeScope(GetHeight(height->ComputedStyleRef())));
   EXPECT_EQ(&GetDocument(), GetAnchorQueryTreeScope(
-                                max_height->ComputedStyleRef().MaxHeight()));
+                                GetMinWidth(min_width->ComputedStyleRef())));
+  EXPECT_EQ(shadow2, GetAnchorQueryTreeScope(
+                         GetMaxWidth(max_width->ComputedStyleRef())));
+  EXPECT_EQ(shadow2, GetAnchorQueryTreeScope(
+                         GetMinHeight(min_height->ComputedStyleRef())));
+  EXPECT_EQ(&GetDocument(), GetAnchorQueryTreeScope(
+                                GetMaxHeight(max_height->ComputedStyleRef())));
 }
 
 TEST_F(StyleResolverTestCQ, CanAffectAnimationsMPC) {
diff --git a/third_party/blink/renderer/core/events/mouse_event.cc b/third_party/blink/renderer/core/events/mouse_event.cc
index d83513e..de257aa4 100644
--- a/third_party/blink/renderer/core/events/mouse_event.cc
+++ b/third_party/blink/renderer/core/events/mouse_event.cc
@@ -525,7 +525,12 @@
     layer = layer->EnclosingSelfPaintingLayer();
 
     PhysicalOffset physical_offset;
-    layer->ConvertToLayerCoords(nullptr, physical_offset);
+    if (RuntimeEnabledFeatures::RemoveConvertToLayerCoordsEnabled()) {
+      physical_offset = layer->GetLayoutObject().LocalToAbsolutePoint(
+          physical_offset, kIgnoreTransforms);
+    } else {
+      layer->ConvertToLayerCoords(nullptr, physical_offset);
+    }
     layer_location_ -= gfx::Vector2dF(physical_offset);
 
     layer_location_.Scale(inverse_zoom_factor);
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index 20dce7f..214ee5f5 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -1303,8 +1303,8 @@
   for (const auto& layout_object : *fixed_position_objects_) {
     const ComputedStyle& style = layout_object->StyleRef();
     if (width_changed) {
-      if (style.Width().IsFixed() &&
-          (style.Left().IsAuto() || style.Right().IsAuto())) {
+      if (style.UsedWidth().IsFixed() &&
+          (style.UsedLeft().IsAuto() || style.UsedRight().IsAuto())) {
         layout_object->SetNeedsPositionedMovementLayout();
       } else {
         layout_object->SetNeedsLayoutAndFullPaintInvalidation(
@@ -1312,8 +1312,8 @@
       }
     }
     if (height_changed) {
-      if (style.Height().IsFixed() &&
-          (style.Top().IsAuto() || style.Bottom().IsAuto())) {
+      if (style.UsedHeight().IsFixed() &&
+          (style.UsedTop().IsAuto() || style.UsedBottom().IsAuto())) {
         layout_object->SetNeedsPositionedMovementLayout();
       } else {
         layout_object->SetNeedsLayoutAndFullPaintInvalidation(
diff --git a/third_party/blink/renderer/core/html/html_image_fallback_helper.cc b/third_party/blink/renderer/core/html/html_image_fallback_helper.cc
index d0b6ab7..6be8a9e 100644
--- a/third_party/blink/renderer/core/html/html_image_fallback_helper.cc
+++ b/third_party/blink/renderer/core/html/html_image_fallback_helper.cc
@@ -166,20 +166,22 @@
   if (element.GetDocument().InQuirksMode()) {
     // Mimic the behaviour of the image host by setting symmetric dimensions if
     // only one dimension is specified.
-    if (!builder.Width().IsAuto() && builder.Height().IsAuto())
-      builder.SetHeight(builder.Width());
-    else if (!builder.Height().IsAuto() && builder.Width().IsAuto())
-      builder.SetWidth(builder.Height());
+    if (!builder.UsedWidth().IsAuto() && builder.UsedHeight().IsAuto()) {
+      builder.SetHeight(builder.UsedWidth());
+    } else if (!builder.UsedHeight().IsAuto() && builder.UsedWidth().IsAuto()) {
+      builder.SetWidth(builder.UsedHeight());
+    }
 
-    if (!builder.Width().IsAuto() && !builder.Height().IsAuto())
+    if (!builder.UsedWidth().IsAuto() && !builder.UsedHeight().IsAuto()) {
       fallback.AlignToBaseline();
+    }
   }
 
   bool has_intrinsic_dimensions =
-      !builder.Width().IsAuto() && !builder.Height().IsAuto();
+      !builder.UsedWidth().IsAuto() && !builder.UsedHeight().IsAuto();
   bool has_dimensions_from_ar =
       !builder.AspectRatio().IsAuto() &&
-      (!builder.Width().IsAuto() || !builder.Height().IsAuto());
+      (!builder.UsedWidth().IsAuto() || !builder.UsedHeight().IsAuto());
   bool has_no_alt_attribute =
       element.getAttribute(html_names::kAltAttr).empty();
   bool treat_as_replaced =
@@ -194,13 +196,13 @@
     // attribute, or the Document is in quirks mode The user agent is expected
     // to treat the element as a replaced element whose content is the text that
     // the element represents, if any."
-    fallback.ShowAsReplaced(builder.Width(), builder.Height(),
+    fallback.ShowAsReplaced(builder.UsedWidth(), builder.UsedHeight(),
                             builder.EffectiveZoom());
 
     // 16px for the image and 2px for its top/left border/padding offset.
     int pixels_for_alt_image = 18;
-    if (ImageSmallerThanAltImage(pixels_for_alt_image, builder.Width(),
-                                 builder.Height())) {
+    if (ImageSmallerThanAltImage(pixels_for_alt_image, builder.UsedWidth(),
+                                 builder.UsedHeight())) {
       fallback.HideBrokenImageIcon();
     } else {
       fallback.ShowBorder();
diff --git a/third_party/blink/renderer/core/inspector/inspector_highlight.cc b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
index 9357d343..a7ca53f7 100644
--- a/third_party/blink/renderer/core/inspector/inspector_highlight.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
@@ -1218,8 +1218,8 @@
   Length base_size = Length::Auto();
 
   const Length& flex_basis = layout_object->StyleRef().FlexBasis();
-  const Length& size = is_horizontal ? layout_object->StyleRef().Width()
-                                     : layout_object->StyleRef().Height();
+  const Length& size = is_horizontal ? layout_object->StyleRef().UsedWidth()
+                                     : layout_object->StyleRef().UsedHeight();
 
   if (flex_basis.IsFixed()) {
     base_size = flex_basis;
diff --git a/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc b/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc
index 3fbe8f7..7814a2a5 100644
--- a/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc
@@ -762,8 +762,8 @@
 bool FlexLayoutAlgorithm::ShouldApplyMinSizeAutoForChild(
     const LayoutBox& child) const {
   // css-flexbox section 4.5
-  const Length& min = IsHorizontalFlow() ? child.StyleRef().MinWidth()
-                                         : child.StyleRef().MinHeight();
+  const Length& min = IsHorizontalFlow() ? child.StyleRef().UsedMinWidth()
+                                         : child.StyleRef().UsedMinHeight();
   bool main_axis_is_childs_block_axis =
       IsHorizontalFlow() != child.StyleRef().IsHorizontalWritingMode();
   bool intrinsic_in_childs_block_axis =
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index d1b81ac..0d5081bb 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -3759,7 +3759,7 @@
   // width of the containing block, then any 'auto' values for 'margin-left' or
   // 'margin-right' are, for the following rules, treated as zero.
   LayoutUnit margin_box_width =
-      child_width + (!StyleRef().Width().IsAuto()
+      child_width + (!StyleRef().UsedWidth().IsAuto()
                          ? margin_start_width + margin_end_width
                          : LayoutUnit());
 
@@ -4439,8 +4439,8 @@
   // https://bugs.webkit.org/show_bug.cgi?id=46500
   auto* curr_layout_block = DynamicTo<LayoutBlock>(this);
   if (curr_layout_block && IsOutOfFlowPositioned() &&
-      StyleRef().Height().IsAuto() &&
-      !(StyleRef().Top().IsAuto() || StyleRef().Bottom().IsAuto())) {
+      StyleRef().UsedHeight().IsAuto() &&
+      !(StyleRef().UsedTop().IsAuto() || StyleRef().UsedBottom().IsAuto())) {
     LayoutBlock* block = const_cast<LayoutBlock*>(curr_layout_block);
     LogicalExtentComputedValues computed_values;
     block->ComputeLogicalHeight(block->LogicalHeight(), LayoutUnit(),
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h
index d9e245f..267cb8c 100644
--- a/third_party/blink/renderer/core/layout/layout_box.h
+++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -524,10 +524,11 @@
     const ComputedStyle& style = StyleRef();
     if (style.AspectRatio().IsAuto() || !IsOutOfFlowPositioned())
       return false;
-    if (style.Width().IsAuto() && style.Height().IsAuto() &&
+    if (style.UsedWidth().IsAuto() && style.UsedHeight().IsAuto() &&
         !style.LogicalTop().IsAuto() && !style.LogicalBottom().IsAuto() &&
-        (style.LogicalLeft().IsAuto() || style.LogicalRight().IsAuto()))
+        (style.LogicalLeft().IsAuto() || style.LogicalRight().IsAuto())) {
       return true;
+    }
     return false;
   }
 
diff --git a/third_party/blink/renderer/core/layout/layout_box_hot.cc b/third_party/blink/renderer/core/layout/layout_box_hot.cc
index 71e70ce7..b34edc2 100644
--- a/third_party/blink/renderer/core/layout/layout_box_hot.cc
+++ b/third_party/blink/renderer/core/layout/layout_box_hot.cc
@@ -25,8 +25,9 @@
     return false;
 
   // Only auto width objects can possibly shrink to avoid floats.
-  if (!StyleRef().Width().IsAuto())
+  if (!StyleRef().UsedWidth().IsAuto()) {
     return false;
+  }
 
   // If the containing block is LayoutNG, we will not let legacy layout deal
   // with positioning of floats or sizing of auto-width new formatting context
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
index d617722..6c031af 100644
--- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -739,26 +739,26 @@
   LayoutUnit constraining_width = constraints->constraining_rect.Width();
   LayoutUnit constraining_height = constraints->constraining_rect.Height();
   LayoutUnit horizontal_offsets =
-      MinimumValueForLength(StyleRef().Right(), constraining_width) +
-      MinimumValueForLength(StyleRef().Left(), constraining_width);
+      MinimumValueForLength(StyleRef().UsedRight(), constraining_width) +
+      MinimumValueForLength(StyleRef().UsedLeft(), constraining_width);
   bool skip_right = false;
   bool skip_left = false;
-  if (!StyleRef().Left().IsAuto() && !StyleRef().Right().IsAuto()) {
+  if (!StyleRef().UsedLeft().IsAuto() && !StyleRef().UsedRight().IsAuto()) {
     if (horizontal_offsets + sticky_box_rect.Width() > constraining_width) {
       skip_right = StyleRef().IsLeftToRightDirection();
       skip_left = !skip_right;
     }
   }
 
-  if (!StyleRef().Left().IsAuto() && !skip_left) {
+  if (!StyleRef().UsedLeft().IsAuto() && !skip_left) {
     constraints->left_offset =
-        MinimumValueForLength(StyleRef().Left(), constraining_width);
+        MinimumValueForLength(StyleRef().UsedLeft(), constraining_width);
     constraints->is_anchored_left = true;
   }
 
-  if (!StyleRef().Right().IsAuto() && !skip_right) {
+  if (!StyleRef().UsedRight().IsAuto() && !skip_right) {
     constraints->right_offset =
-        MinimumValueForLength(StyleRef().Right(), constraining_width);
+        MinimumValueForLength(StyleRef().UsedRight(), constraining_width);
     constraints->is_anchored_right = true;
   }
 
@@ -767,22 +767,22 @@
   // mode when related sections are fixed in spec.
   // See http://lists.w3.org/Archives/Public/www-style/2014May/0286.html
   LayoutUnit vertical_offsets =
-      MinimumValueForLength(StyleRef().Top(), constraining_height) +
-      MinimumValueForLength(StyleRef().Bottom(), constraining_height);
-  if (!StyleRef().Top().IsAuto() && !StyleRef().Bottom().IsAuto() &&
+      MinimumValueForLength(StyleRef().UsedTop(), constraining_height) +
+      MinimumValueForLength(StyleRef().UsedBottom(), constraining_height);
+  if (!StyleRef().UsedTop().IsAuto() && !StyleRef().UsedBottom().IsAuto() &&
       vertical_offsets + sticky_box_rect.Height() > constraining_height) {
     skip_bottom = true;
   }
 
-  if (!StyleRef().Top().IsAuto()) {
+  if (!StyleRef().UsedTop().IsAuto()) {
     constraints->top_offset =
-        MinimumValueForLength(StyleRef().Top(), constraining_height);
+        MinimumValueForLength(StyleRef().UsedTop(), constraining_height);
     constraints->is_anchored_top = true;
   }
 
-  if (!StyleRef().Bottom().IsAuto() && !skip_bottom) {
+  if (!StyleRef().UsedBottom().IsAuto() && !skip_bottom) {
     constraints->bottom_offset =
-        MinimumValueForLength(StyleRef().Bottom(), constraining_height);
+        MinimumValueForLength(StyleRef().UsedBottom(), constraining_height);
     constraints->is_anchored_bottom = true;
   }
 
diff --git a/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc b/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc
index 9f77146..87d369e 100644
--- a/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc
+++ b/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc
@@ -120,13 +120,14 @@
   if (StyleRef().Display() == EDisplay::kNone)
     return 0;
 
-  int width =
-      ComputeSize(kMainOrPreferredSize, StyleRef().Width(), container_width);
-  int min_width = ComputeSize(kMinSize, StyleRef().MinWidth(), container_width);
+  int width = ComputeSize(kMainOrPreferredSize, StyleRef().UsedWidth(),
+                          container_width);
+  int min_width =
+      ComputeSize(kMinSize, StyleRef().UsedMinWidth(), container_width);
   int max_width =
-      StyleRef().MaxWidth().IsNone()
+      StyleRef().UsedMaxWidth().IsNone()
           ? width
-          : ComputeSize(kMaxSize, StyleRef().MaxWidth(), container_width);
+          : ComputeSize(kMaxSize, StyleRef().UsedMaxWidth(), container_width);
   return std::max(min_width, std::min(max_width, width));
 }
 
@@ -135,14 +136,14 @@
   if (StyleRef().Display() == EDisplay::kNone)
     return 0;
 
-  int height =
-      ComputeSize(kMainOrPreferredSize, StyleRef().Height(), container_height);
+  int height = ComputeSize(kMainOrPreferredSize, StyleRef().UsedHeight(),
+                           container_height);
   int min_height =
-      ComputeSize(kMinSize, StyleRef().MinHeight(), container_height);
+      ComputeSize(kMinSize, StyleRef().UsedMinHeight(), container_height);
   int max_height =
-      StyleRef().MaxHeight().IsNone()
+      StyleRef().UsedMaxHeight().IsNone()
           ? height
-          : ComputeSize(kMaxSize, StyleRef().MaxHeight(), container_height);
+          : ComputeSize(kMaxSize, StyleRef().UsedMaxHeight(), container_height);
   return std::max(min_height, std::min(max_height, height));
 }
 
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index a472a1a..561a2d7 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -1345,8 +1345,9 @@
   // height will allow the object to grow and shrink based on the content
   // inside. The same goes for for logical width, if this objects is inside a
   // shrink-to-fit container, for instance.
-  if (!style->Width().IsFixed() || !style->Height().IsFixed())
+  if (!style->UsedWidth().IsFixed() || !style->UsedHeight().IsFixed()) {
     return false;
+  }
 
   if (object->IsTextControl()) {
     return true;
diff --git a/third_party/blink/renderer/core/layout/layout_tree_as_text.cc b/third_party/blink/renderer/core/layout/layout_tree_as_text.cc
index 216b1a0..e3fb0dd 100644
--- a/third_party/blink/renderer/core/layout/layout_tree_as_text.cc
+++ b/third_party/blink/renderer/core/layout/layout_tree_as_text.cc
@@ -453,8 +453,7 @@
           layout_view->GetDocument().UpdateStyleAndLayout(
               DocumentUpdateReason::kTest);
           if (auto* layer = layout_view->Layer()) {
-            LayoutTreeAsText::WriteLayers(ts, layer, layer, indent + 1,
-                                          behavior);
+            LayoutTreeAsText::WriteLayers(ts, layer, indent + 1, behavior);
           }
         }
       }
@@ -550,30 +549,16 @@
 }
 
 void LayoutTreeAsText::WriteLayers(WTF::TextStream& ts,
-                                   const PaintLayer* root_layer_arg,
                                    PaintLayer* layer,
                                    int indent,
                                    LayoutAsTextBehavior behavior,
                                    const PaintLayer* marked_layer) {
-  // Calculate the clip rects we should use.
-  const PaintLayer* root_layer = layer->Transform() ? layer : root_layer_arg;
-  PhysicalOffset layer_offset;
-  ClipRect background_rect, foreground_rect;
-  if (layer->GetLayoutObject().FirstFragment().HasLocalBorderBoxProperties()) {
-    layer->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-        .CalculateRects(
-            ClipRectsContext(root_layer,
-                             &root_layer->GetLayoutObject().FirstFragment()),
-            &layer->GetLayoutObject().FirstFragment(), layer_offset,
-            background_rect, foreground_rect);
-  } else {
-    layer->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper)
-        .CalculateRects(ClipRectsContext(root_layer, nullptr), nullptr,
-                        layer_offset, background_rect, foreground_rect);
-  }
+  const LayoutObject& layer_object = layer->GetLayoutObject();
+  PhysicalOffset layer_offset =
+      layer_object.LocalToAbsolutePoint(PhysicalOffset());
 
   bool should_dump = true;
-  auto* embedded = DynamicTo<LayoutEmbeddedContent>(layer->GetLayoutObject());
+  auto* embedded = DynamicTo<LayoutEmbeddedContent>(layer_object);
   if (embedded && embedded->IsThrottledFrameView())
     should_dump = false;
 
@@ -584,8 +569,7 @@
   }
 #endif
 
-  bool should_dump_children =
-      !layer->GetLayoutObject().ChildLayoutBlockedByDisplayLock();
+  bool should_dump_children = !layer_object.ChildLayoutBlockedByDisplayLock();
 
   const auto& neg_list = ChildLayers(layer, kNegativeZOrderChildren);
   bool paints_background_separately = !neg_list.empty();
@@ -602,8 +586,7 @@
       ++curr_indent;
     }
     for (auto& child_layer : neg_list) {
-      WriteLayers(ts, root_layer, child_layer, curr_indent, behavior,
-                  marked_layer);
+      WriteLayers(ts, child_layer, curr_indent, behavior, marked_layer);
     }
   }
 
@@ -623,8 +606,7 @@
       ++curr_indent;
     }
     for (auto& child_layer : normal_flow_list) {
-      WriteLayers(ts, root_layer, child_layer, curr_indent, behavior,
-                  marked_layer);
+      WriteLayers(ts, child_layer, curr_indent, behavior, marked_layer);
     }
   }
 
@@ -637,8 +619,7 @@
       ++curr_indent;
     }
     for (auto& child_layer : pos_list) {
-      WriteLayers(ts, root_layer, child_layer, curr_indent, behavior,
-                  marked_layer);
+      WriteLayers(ts, child_layer, curr_indent, behavior, marked_layer);
     }
   }
 }
@@ -711,7 +692,7 @@
     return ts.Release();
 
   PaintLayer* layer = layout_object->Layer();
-  LayoutTreeAsText::WriteLayers(ts, layer, layer, 0, behavior, marked_layer);
+  LayoutTreeAsText::WriteLayers(ts, layer, 0, behavior, marked_layer);
   WriteSelection(ts, layout_object);
   return ts.Release();
 }
diff --git a/third_party/blink/renderer/core/layout/layout_tree_as_text.h b/third_party/blink/renderer/core/layout/layout_tree_as_text.h
index 8e0f801..0a180190 100644
--- a/third_party/blink/renderer/core/layout/layout_tree_as_text.h
+++ b/third_party/blink/renderer/core/layout/layout_tree_as_text.h
@@ -97,7 +97,6 @@
                                 const LayoutObject&,
                                 LayoutAsTextBehavior);
   static void WriteLayers(WTF::TextStream&,
-                          const PaintLayer* root_layer,
                           PaintLayer*,
                           int indent = 0,
                           LayoutAsTextBehavior = kLayoutAsTextBehaviorNormal,
diff --git a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
index c29f2d57..bae2b55 100644
--- a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
@@ -295,8 +295,9 @@
       const auto& style = Style();
       const auto& child_style = child.Style();
       const PhysicalToLogical<Length> insets_in_flexbox_writing_mode(
-          Style().GetWritingDirection(), child_style.Top(), child_style.Right(),
-          child_style.Bottom(), child_style.Left());
+          Style().GetWritingDirection(), child_style.UsedTop(),
+          child_style.UsedRight(), child_style.UsedBottom(),
+          child_style.UsedLeft());
       if (is_column_) {
         const ItemPosition normalized_alignment =
             FlexLayoutAlgorithm::AlignmentForChild(style, child_style);
@@ -438,15 +439,17 @@
 bool NGFlexLayoutAlgorithm::DoesItemCrossSizeComputeToAuto(
     const NGBlockNode& child) const {
   const ComputedStyle& child_style = child.Style();
-  if (is_horizontal_flow_)
-    return child_style.Height().IsAuto();
-  return child_style.Width().IsAuto();
+  if (is_horizontal_flow_) {
+    return child_style.UsedHeight().IsAuto();
+  }
+  return child_style.UsedWidth().IsAuto();
 }
 
 bool NGFlexLayoutAlgorithm::AspectRatioProvidesMainSize(
     const NGBlockNode& child) const {
-  const Length& cross_axis_length =
-      is_horizontal_flow_ ? child.Style().Height() : child.Style().Width();
+  const Length& cross_axis_length = is_horizontal_flow_
+                                        ? child.Style().UsedHeight()
+                                        : child.Style().UsedWidth();
   return child.HasAspectRatio() &&
          (IsItemCrossAxisLengthDefinite(child, cross_axis_length) ||
           WillChildCrossSizeBeContainerCrossSize(child));
@@ -530,7 +533,7 @@
 Length NGFlexLayoutAlgorithm::GetUsedFlexBasis(const NGBlockNode& child) const {
   const ComputedStyle& child_style = child.Style();
   const Length& specified_length_in_main_axis =
-      is_horizontal_flow_ ? child_style.Width() : child_style.Height();
+      is_horizontal_flow_ ? child_style.UsedWidth() : child_style.UsedHeight();
   const Length& specified_flex_basis = child_style.FlexBasis();
 
   if (specified_flex_basis.IsAuto()) {
@@ -718,8 +721,9 @@
         is_horizontal_flow_ ? physical_border_padding.VerticalSum()
                             : physical_border_padding.HorizontalSum();
 
-    const Length& cross_axis_length =
-        is_horizontal_flow_ ? child.Style().Height() : child.Style().Width();
+    const Length& cross_axis_length = is_horizontal_flow_
+                                          ? child.Style().UsedHeight()
+                                          : child.Style().UsedWidth();
     all_items_have_non_auto_cross_sizes &= !cross_axis_length.IsAuto();
 
     absl::optional<MinMaxSizesResult> min_max_sizes;
@@ -740,9 +744,9 @@
                                                      LayoutUnit::Max()};
     MinMaxSizes min_max_sizes_in_cross_axis_direction{LayoutUnit(),
                                                       LayoutUnit::Max()};
-    const Length& max_property_in_main_axis = is_horizontal_flow_
-                                                  ? child.Style().MaxWidth()
-                                                  : child.Style().MaxHeight();
+    const Length& max_property_in_main_axis =
+        is_horizontal_flow_ ? child.Style().UsedMaxWidth()
+                            : child.Style().UsedMaxHeight();
     if (MainAxisIsInlineAxis(child)) {
       min_max_sizes_in_main_axis_direction.max_size = ResolveMaxInlineLength(
           flex_basis_space, child_style, border_padding_in_child_writing_mode,
@@ -895,8 +899,8 @@
     LayoutUnit flex_base_content_size =
         flex_base_border_box - main_axis_border_padding;
 
-    const Length& min = is_horizontal_flow_ ? child.Style().MinWidth()
-                                            : child.Style().MinHeight();
+    const Length& min = is_horizontal_flow_ ? child.Style().UsedMinWidth()
+                                            : child.Style().UsedMinHeight();
     if (algorithm_.ShouldApplyMinSizeAutoForChild(*child.GetLayoutBox())) {
       LayoutUnit content_size_suggestion;
       if (MainAxisIsInlineAxis(child)) {
@@ -917,7 +921,8 @@
 
       LayoutUnit specified_size_suggestion = LayoutUnit::Max();
       const Length& specified_length_in_main_axis =
-          is_horizontal_flow_ ? child_style.Width() : child_style.Height();
+          is_horizontal_flow_ ? child_style.UsedWidth()
+                              : child_style.UsedHeight();
       // If the item’s computed main size property is definite, then the
       // specified size suggestion is that size.
       if (MainAxisIsInlineAxis(child)) {
@@ -2154,7 +2159,7 @@
   // "... outer preferred size (its width/height as appropriate) if that is not
   // auto ..."
   const Length& preferred_main_axis_length =
-      is_horizontal_flow_ ? child_style.Width() : child_style.Height();
+      is_horizontal_flow_ ? child_style.UsedWidth() : child_style.UsedHeight();
   bool is_preferred_main_axis_length_auto = preferred_main_axis_length.IsAuto();
   // This block of if-statements that computes
   // |is_preferred_main_axis_length_auto| is fragile.
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.cc
index 8143009..acdb73b4 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.cc
@@ -175,13 +175,20 @@
       /* is_parallel_context */ true,
       /* is_last_baseline */ block_axis_alignment == AxisEdge::kLastBaseline);
 
-  if (node.IsGrid()) {
-    // TODO(ethavar): Don't consider subgrids with size containment.
+  // From https://drafts.csswg.org/css-grid-2/#subgrid-listing:
+  //   "...if the grid container is otherwise forced to establish an independent
+  //   formatting context... the grid container is not a subgrid."
+  //
+  // Only layout and paint containment establish an independent formatting
+  // context as specified in:
+  //   https://drafts.csswg.org/css-contain-2/#containment-layout
+  //   https://drafts.csswg.org/css-contain-2/#containment-paint
+  if (node.IsGrid() && !node.ShouldApplyLayoutContainment() &&
+      !node.ShouldApplyPaintContainment()) {
     has_subgridded_columns =
         is_parallel_with_root_grid
             ? style.GridTemplateColumns().IsSubgriddedAxis()
             : style.GridTemplateRows().IsSubgriddedAxis();
-
     has_subgridded_rows = is_parallel_with_root_grid
                               ? style.GridTemplateRows().IsSubgriddedAxis()
                               : style.GridTemplateColumns().IsSubgriddedAxis();
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
index 14eb155..3b357c0 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -1265,6 +1265,7 @@
   bool is_line_created = false;
   LayoutUnit line_block_size;
   LayoutUnit block_delta;
+  NGLineInfo line_info;
   const auto* opportunities_it = opportunities.begin();
   while (opportunities_it != opportunities.end()) {
     const NGLayoutOpportunity& opportunity = *opportunities_it;
@@ -1314,7 +1315,6 @@
                                                  &line_opportunity);
     }
 
-    NGLineInfo line_info;
     NGLineBreaker line_breaker(
         Node(), NGLineBreakerMode::kContent, ConstraintSpace(),
         line_opportunity, leading_floats, handled_leading_floats_index,
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
index 306c8d4f..efe163b 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
@@ -1812,8 +1812,8 @@
 
   if (UNLIKELY(node.IsInitialLetterBox())) {
     LayoutUnit inline_size = LayoutUnit();
+    NGLineInfo line_info;
     do {
-      NGLineInfo line_info;
       line_breaker.NextLine(&line_info);
       if (line_info.Results().empty())
         break;
@@ -1828,8 +1828,8 @@
   MaxSizeFromMinSize max_size_from_min_size(items_data, *max_size_cache,
                                             &floats_max_size);
 
+  NGLineInfo line_info;
   do {
-    NGLineInfo line_info;
     line_breaker.NextLine(&line_info);
     if (line_info.Results().empty())
       break;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
index f6274a5a..493dc5c5 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
@@ -608,8 +608,8 @@
 
 // Initialize internal states for the next line.
 void NGLineBreaker::PrepareNextLine(NGLineInfo* line_info) {
-  // NGLineInfo is not supposed to be re-used because it's not much gain and to
-  // avoid rare code path.
+  line_info->Reset();
+
   const NGInlineItemResults& item_results = line_info->Results();
   DCHECK(item_results.empty());
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
index 4ec7f1f..ada79ab 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
@@ -66,8 +66,8 @@
     NGExclusionSpace exclusion_space;
     NGPositionedFloatVector leading_floats;
     NGLineLayoutOpportunity line_opportunity(available_width);
+    NGLineInfo line_info;
     do {
-      NGLineInfo line_info;
       NGLineBreaker line_breaker(node, NGLineBreakerMode::kContent, space,
                                  line_opportunity, leading_floats, 0u,
                                  break_token, /* column_spanner_path */ nullptr,
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.cc
index b2ccb7d..9258ca6 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.cc
@@ -11,6 +11,49 @@
 
 namespace blink {
 
+void NGLineInfo::Reset() {
+  items_data_ = nullptr;
+  line_style_ = nullptr;
+  results_.Shrink(0);
+
+  bfc_offset_ = NGBfcOffset();
+
+  break_token_ = nullptr;
+  propagated_break_tokens_.Shrink(0);
+
+  block_in_inline_layout_result_ = nullptr;
+
+  available_width_ = LayoutUnit();
+  width_ = LayoutUnit();
+  hang_width_ = LayoutUnit();
+  text_indent_ = LayoutUnit();
+
+  annotation_block_start_adjustment_ = LayoutUnit();
+  initial_letter_box_block_start_adjustment_ = LayoutUnit();
+  initial_letter_box_block_size_ = LayoutUnit();
+
+  start_offset_ = 0;
+  end_item_index_ = 0;
+  end_offset_for_justify_ = 0;
+
+  text_align_ = ETextAlign::kLeft;
+  base_direction_ = TextDirection::kLtr;
+
+  use_first_line_style_ = false;
+  is_last_line_ = false;
+  has_forced_break_ = false;
+  is_empty_line_ = false;
+  has_line_even_if_empty_ = false;
+  is_block_in_inline_ = false;
+  has_overflow_ = false;
+  has_trailing_spaces_ = false;
+  needs_accurate_end_position_ = false;
+  is_ruby_base_ = false;
+  is_ruby_text_ = false;
+  may_have_text_combine_item_ = false;
+  allow_hang_for_alignment_ = false;
+}
+
 void NGLineInfo::SetLineStyle(const NGInlineNode& node,
                               const NGInlineItemsData& items_data,
                               bool use_first_line_style) {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.h b/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.h
index 071f8443..bfd78b1 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_info.h
@@ -30,6 +30,8 @@
   STACK_ALLOCATED();
 
  public:
+  void Reset();
+
   const NGInlineItemsData& ItemsData() const {
     DCHECK(items_data_);
     return *items_data_;
@@ -279,6 +281,8 @@
   // when |NGInlineItemResult| to |results_|.
   bool may_have_text_combine_item_ = false;
   bool allow_hang_for_alignment_ = false;
+
+  // When adding fields, pelase ensure `Reset()` is in sync.
 };
 
 std::ostream& operator<<(std::ostream& ostream, const NGLineInfo& line_info);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_paragraph_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_paragraph_line_breaker.cc
index 9c33f18..9b65dd4 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_paragraph_line_breaker.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_paragraph_line_breaker.cc
@@ -56,8 +56,8 @@
     const NGLineLayoutOpportunity line_opportunity(available_width);
     NGPositionedFloatVector leading_floats;
     NGExclusionSpace exclusion_space;
+    NGLineInfo line_info;
     for (;;) {
-      NGLineInfo line_info;
       NGLineBreaker line_breaker(
           node_, NGLineBreakerMode::kContent, space_, line_opportunity,
           leading_floats,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc
index 6f97917..9ae5bf6 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc
@@ -271,7 +271,7 @@
   const PhysicalSize available_size = ToPhysicalSize(
       available_logical_size, writing_direction.GetWritingMode());
   absl::optional<LayoutUnit> left;
-  if (const Length& left_length = style.Left(); !left_length.IsAuto()) {
+  if (const Length& left_length = style.UsedLeft(); !left_length.IsAuto()) {
     anchor_evaluator->SetAxis(/* is_y_axis */ false,
                               /* is_right_or_bottom */ false,
                               available_size.width);
@@ -279,7 +279,7 @@
                                  anchor_evaluator);
   }
   absl::optional<LayoutUnit> right;
-  if (const Length& right_length = style.Right(); !right_length.IsAuto()) {
+  if (const Length& right_length = style.UsedRight(); !right_length.IsAuto()) {
     anchor_evaluator->SetAxis(/* is_y_axis */ false,
                               /* is_right_or_bottom */ true,
                               available_size.width);
@@ -288,7 +288,7 @@
   }
 
   absl::optional<LayoutUnit> top;
-  if (const Length& top_length = style.Top(); !top_length.IsAuto()) {
+  if (const Length& top_length = style.UsedTop(); !top_length.IsAuto()) {
     anchor_evaluator->SetAxis(/* is_y_axis */ true,
                               /* is_right_or_bottom */ false,
                               available_size.height);
@@ -296,7 +296,8 @@
                                 anchor_evaluator);
   }
   absl::optional<LayoutUnit> bottom;
-  if (const Length& bottom_length = style.Bottom(); !bottom_length.IsAuto()) {
+  if (const Length& bottom_length = style.UsedBottom();
+      !bottom_length.IsAuto()) {
     anchor_evaluator->SetAxis(/* is_y_axis */ true,
                               /* is_right_or_bottom */ true,
                               available_size.height);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
index 59778db..a9a339c3 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -791,8 +791,8 @@
   // TODO(layout-dev): We might be able to determine what the previous
   // static-position was based on |NGLayoutResult::OutOfFlowPositionedOffset|.
   bool depends_on_static_position =
-      (Style().Left().IsAuto() && Style().Right().IsAuto()) ||
-      (Style().Top().IsAuto() && Style().Bottom().IsAuto());
+      (Style().UsedLeft().IsAuto() && Style().UsedRight().IsAuto()) ||
+      (Style().UsedTop().IsAuto() && Style().UsedBottom().IsAuto());
 
   if (depends_on_static_position)
     return nullptr;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.h b/third_party/blink/renderer/core/layout/ng/ng_block_node.h
index 5fd186e..a68d5400 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.h
@@ -231,6 +231,10 @@
     return box_->ShouldApplyLayoutContainment();
   }
 
+  bool ShouldApplyPaintContainment() const {
+    return box_->ShouldApplyPaintContainment();
+  }
+
   bool HasLineIfEmpty() const {
     if (const auto* block = DynamicTo<LayoutBlock>(box_.Get()))
       return block->HasLineIfEmpty();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
index 530db9c..7ed6093 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
@@ -141,13 +141,15 @@
     const auto& child_style = child.Style();
     if (child.IsCSSBox() && child_style.GetPosition() == EPosition::kRelative) {
       if (IsHorizontalWritingMode(Style().GetWritingMode())) {
-        if (child_style.Top().IsPercentOrCalc() ||
-            child_style.Bottom().IsPercentOrCalc())
+        if (child_style.UsedTop().IsPercentOrCalc() ||
+            child_style.UsedBottom().IsPercentOrCalc()) {
           has_descendant_that_depends_on_percentage_block_size_ = true;
+        }
       } else {
-        if (child_style.Left().IsPercentOrCalc() ||
-            child_style.Right().IsPercentOrCalc())
+        if (child_style.UsedLeft().IsPercentOrCalc() ||
+            child_style.UsedRight().IsPercentOrCalc()) {
           has_descendant_that_depends_on_percentage_block_size_ = true;
+        }
       }
     }
   }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
index 1d2cd07..2cf63dd 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
@@ -314,8 +314,8 @@
   MinMaxSizesResult result;
 
   const Length& inline_size = parent_writing_mode == WritingMode::kHorizontalTb
-                                  ? style.Width()
-                                  : style.Height();
+                                  ? style.UsedWidth()
+                                  : style.UsedHeight();
   if (inline_size.IsAuto() || inline_size.IsPercentOrCalc() ||
       inline_size.IsFillAvailable() || inline_size.IsFitContent()) {
     result = min_max_sizes_func(MinMaxSizesType::kContent);
@@ -342,8 +342,8 @@
   }
 
   const Length& max_length = parent_writing_mode == WritingMode::kHorizontalTb
-                                 ? style.MaxWidth()
-                                 : style.MaxHeight();
+                                 ? style.UsedMaxWidth()
+                                 : style.UsedMaxHeight();
   LayoutUnit max;
   if (IsParallelWritingMode(parent_writing_mode, child_writing_mode)) {
     max = ResolveMaxInlineLength(space, style, border_padding,
@@ -354,8 +354,8 @@
   result.sizes.Constrain(max);
 
   const Length& min_length = parent_writing_mode == WritingMode::kHorizontalTb
-                                 ? style.MinWidth()
-                                 : style.MinHeight();
+                                 ? style.UsedMinWidth()
+                                 : style.UsedMinHeight();
   LayoutUnit min;
   if (IsParallelWritingMode(parent_writing_mode, child_writing_mode)) {
     min = ResolveMinInlineLength(space, style, border_padding,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_relative_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_relative_utils.cc
index 39aee74..33e6608 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_relative_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_relative_utils.cc
@@ -35,13 +35,13 @@
   };
 
   absl::optional<LayoutUnit> left =
-      ResolveInset(child_style.Left(), physical_size.width);
+      ResolveInset(child_style.UsedLeft(), physical_size.width);
   absl::optional<LayoutUnit> right =
-      ResolveInset(child_style.Right(), physical_size.width);
+      ResolveInset(child_style.UsedRight(), physical_size.width);
   absl::optional<LayoutUnit> top =
-      ResolveInset(child_style.Top(), physical_size.height);
+      ResolveInset(child_style.UsedTop(), physical_size.height);
   absl::optional<LayoutUnit> bottom =
-      ResolveInset(child_style.Bottom(), physical_size.height);
+      ResolveInset(child_style.UsedBottom(), physical_size.height);
 
   // Common case optimization.
   if (!left && !right && !top && !bottom)
diff --git a/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_foreign_object.cc b/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_foreign_object.cc
index 68c3ac5..8166f23a 100644
--- a/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_foreign_object.cc
+++ b/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_foreign_object.cc
@@ -111,8 +111,8 @@
   const ComputedStyle& style = StyleRef();
   gfx::Vector2dF origin =
       length_context.ResolveLengthPair(style.X(), style.Y(), style);
-  gfx::Vector2dF size =
-      length_context.ResolveLengthPair(style.Width(), style.Height(), style);
+  gfx::Vector2dF size = length_context.ResolveLengthPair(
+      style.UsedWidth(), style.UsedHeight(), style);
   // SetRect() will clamp negative width/height to zero.
   viewport_.SetRect(origin.x(), origin.y(), size.x(), size.y());
 
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc
index 8fa0dc4..2b36b62 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc
@@ -99,10 +99,10 @@
 
   gfx::Vector2dF style_size =
       SVGLengthContext(GetElement())
-          .ResolveLengthPair(StyleRef().Width(), StyleRef().Height(),
+          .ResolveLengthPair(StyleRef().UsedWidth(), StyleRef().UsedHeight(),
                              StyleRef());
-  bool width_is_auto = style_size.x() < 0 || StyleRef().Width().IsAuto();
-  bool height_is_auto = style_size.y() < 0 || StyleRef().Height().IsAuto();
+  bool width_is_auto = style_size.x() < 0 || StyleRef().UsedWidth().IsAuto();
+  bool height_is_auto = style_size.y() < 0 || StyleRef().UsedHeight().IsAuto();
   if (!width_is_auto && !height_is_auto)
     return gfx::SizeF(style_size.x(), style_size.y());
 
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc
index ee7fba4f..9f4a3c7c 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc
@@ -48,8 +48,8 @@
   const ComputedStyle& style = StyleRef();
   gfx::Vector2dF origin =
       length_context.ResolveLengthPair(style.X(), style.Y(), style);
-  gfx::Vector2dF size =
-      length_context.ResolveLengthPair(style.Width(), style.Height(), style);
+  gfx::Vector2dF size = length_context.ResolveLengthPair(
+      style.UsedWidth(), style.UsedHeight(), style);
   // Spec: "A negative value is an error." gfx::Rect::SetRect() clamps negative
   // width/height to 0.
   fill_bounding_box_.SetRect(origin.x(), origin.y(), size.x(), size.y());
diff --git a/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc b/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc
index 50390e2..d827f6e8 100644
--- a/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc
+++ b/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc
@@ -341,10 +341,10 @@
                        length_context.ValueForLength(style.Y(), style,
                                                      SVGLengthMode::kHeight));
     WriteNameValuePair(ts, "width",
-                       length_context.ValueForLength(style.Width(), style,
+                       length_context.ValueForLength(style.UsedWidth(), style,
                                                      SVGLengthMode::kWidth));
     WriteNameValuePair(ts, "height",
-                       length_context.ValueForLength(style.Height(), style,
+                       length_context.ValueForLength(style.UsedHeight(), style,
                                                      SVGLengthMode::kHeight));
   } else if (auto* element = DynamicTo<SVGLineElement>(*svg_element)) {
     WriteNameValuePair(ts, "x1",
diff --git a/third_party/blink/renderer/core/layout/text_autosizer.cc b/third_party/blink/renderer/core/layout/text_autosizer.cc
index d094c45a..0d7da33 100644
--- a/third_party/blink/renderer/core/layout/text_autosizer.cc
+++ b/third_party/blink/renderer/core/layout/text_autosizer.cc
@@ -195,8 +195,8 @@
     if (style.OverflowY() != EOverflow::kVisible
         && style.OverflowY() != EOverflow::kHidden)
       return false;
-    if (style.Height().IsSpecified() || style.MaxHeight().IsSpecified() ||
-        block->IsOutOfFlowPositioned()) {
+    if (style.UsedHeight().IsSpecified() ||
+        style.UsedMaxHeight().IsSpecified() || block->IsOutOfFlowPositioned()) {
       // Some sites (e.g. wikipedia) set their html and/or body elements to
       // height:100%, without intending to constrain the height of the content
       // within them.
@@ -245,7 +245,7 @@
 static bool HasExplicitWidth(const LayoutBlock* block) {
   // FIXME: This heuristic may need to be expanded to other ways a block can be
   // wider or narrower than its parent containing block.
-  return block->Style() && block->StyleRef().Width().IsSpecified();
+  return block->Style() && block->StyleRef().UsedWidth().IsSpecified();
 }
 
 static LayoutObject* GetParent(const LayoutObject* object) {
@@ -860,7 +860,7 @@
         (static_cast<unsigned>(style->UnresolvedFloating()) << 4);
     data.packed_style_properties_ |=
         (static_cast<unsigned>(style->Display()) << 7);
-    const Length& width = style->Width();
+    const Length& width = style->UsedWidth();
     data.packed_style_properties_ |= (width.GetType() << 12);
     // packedStyleProperties effectively using 16 bits now.
 
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc
index 8c4df4e6..348a43ed 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -1045,10 +1045,9 @@
   ClipRectsContext clip_rects_context(this, fragment.fragment_data,
                                       kExcludeOverlayScrollbarSizeForHitTesting,
                                       respect_overflow_clip);
-  Clipper(GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(clip_rects_context, fragment.fragment_data,
-                      fragment.layer_offset, fragment.background_rect,
-                      fragment.foreground_rect);
+  Clipper().CalculateRects(clip_rects_context, fragment.fragment_data,
+                           fragment.layer_offset, fragment.background_rect,
+                           fragment.foreground_rect);
 
   fragments.push_back(fragment);
 }
@@ -1115,10 +1114,9 @@
         kExcludeOverlayScrollbarSizeForHitTesting, respect_overflow_clip,
         PhysicalOffset());
 
-    Clipper(GeometryMapperOption::kUseGeometryMapper)
-        .CalculateRects(clip_rects_context, fragment_data,
-                        fragment.layer_offset, fragment.background_rect,
-                        fragment.foreground_rect);
+    Clipper().CalculateRects(clip_rects_context, fragment_data,
+                             fragment.layer_offset, fragment.background_rect,
+                             fragment.foreground_rect);
 
     fragment.fragment_data = fragment_data;
 
@@ -2342,10 +2340,8 @@
   return gfx::Vector2d();
 }
 
-PaintLayerClipper PaintLayer::Clipper(
-    GeometryMapperOption geometry_mapper_option) const {
-  return PaintLayerClipper(
-      this, geometry_mapper_option == GeometryMapperOption::kUseGeometryMapper);
+PaintLayerClipper PaintLayer::Clipper() const {
+  return PaintLayerClipper(this);
 }
 
 bool PaintLayer::ScrollsOverflow() const {
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h
index e5f69881..a7d9139 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.h
+++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -407,12 +407,7 @@
     return scrollable_area_.Get();
   }
 
-  enum class GeometryMapperOption {
-    kUseGeometryMapper,
-    kDoNotUseGeometryMapper
-  };
-
-  PaintLayerClipper Clipper(GeometryMapperOption) const;
+  PaintLayerClipper Clipper() const;
 
   bool ScrollsOverflow() const;
 
diff --git a/third_party/blink/renderer/core/paint/paint_layer_clipper.cc b/third_party/blink/renderer/core/paint/paint_layer_clipper.cc
index 0130940..075fbac 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_clipper.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_clipper.cc
@@ -67,64 +67,9 @@
   return respect_overflow_clip == kRespectOverflowClip;
 }
 
-static void AdjustClipRectsForChildren(
-    const LayoutBoxModelObject& layout_object,
-    ClipRects& clip_rects) {
-  EPosition position = layout_object.StyleRef().GetPosition();
-  // A fixed object is essentially the root of its containing block hierarchy,
-  // so when we encounter such an object, we reset our clip rects to the
-  // fixedClipRect.
-  if (position == EPosition::kFixed) {
-    clip_rects.SetPosClipRect(clip_rects.FixedClipRect());
-    clip_rects.SetOverflowClipRect(clip_rects.FixedClipRect());
-    clip_rects.SetFixed(true);
-  } else if (position == EPosition::kRelative) {
-    clip_rects.SetPosClipRect(clip_rects.OverflowClipRect());
-  } else if (position == EPosition::kAbsolute) {
-    clip_rects.SetOverflowClipRect(clip_rects.PosClipRect());
-  }
-}
+PaintLayerClipper::PaintLayerClipper(const PaintLayer* layer) : layer_(layer) {}
 
-static void ApplyClipRects(const ClipRectsContext& context,
-                           const LayoutBoxModelObject& layout_object,
-                           const PhysicalOffset& offset,
-                           ClipRects& clip_rects) {
-  const LayoutBox& box = *To<LayoutBox>(&layout_object);
-
-  DCHECK(box.ShouldClipOverflowAlongEitherAxis() || box.HasClip());
-  LayoutView* view = box.View();
-  DCHECK(view);
-
-  if (box.ShouldClipOverflowAlongEitherAxis()) {
-    ClipRect new_overflow_clip =
-        box.OverflowClipRect(offset, context.overlay_scrollbar_clip_behavior);
-    new_overflow_clip.SetHasRadius(box.StyleRef().HasBorderRadius());
-    clip_rects.SetOverflowClipRect(
-        Intersection(new_overflow_clip, clip_rects.OverflowClipRect()));
-    if (box.IsPositioned())
-      clip_rects.SetPosClipRect(
-          Intersection(new_overflow_clip, clip_rects.PosClipRect()));
-    if (box.CanContainFixedPositionObjects())
-      clip_rects.SetFixedClipRect(
-          Intersection(new_overflow_clip, clip_rects.FixedClipRect()));
-    if (box.ShouldApplyPaintContainment())
-      clip_rects.SetPosClipRect(
-          Intersection(new_overflow_clip, clip_rects.PosClipRect()));
-  }
-  if (box.HasClip()) {
-    PhysicalRect new_clip = box.ClipRect(offset);
-    clip_rects.SetPosClipRect(Intersection(new_clip, clip_rects.PosClipRect()));
-    clip_rects.SetOverflowClipRect(
-        Intersection(new_clip, clip_rects.OverflowClipRect()));
-    clip_rects.SetFixedClipRect(
-        Intersection(new_clip, clip_rects.FixedClipRect()));
-  }
-}
-
-PaintLayerClipper::PaintLayerClipper(const PaintLayer* layer,
-                                     bool usegeometry_mapper)
-    : layer_(layer), use_geometry_mapper_(usegeometry_mapper) {}
-
+// TODO(tkent): Merge this into CalculateRects().
 void PaintLayerClipper::CalculateRectsWithGeometryMapper(
     const ClipRectsContext& context,
     const FragmentData& fragment_data,
@@ -168,119 +113,22 @@
                                        PhysicalOffset& layer_offset,
                                        ClipRect& background_rect,
                                        ClipRect& foreground_rect) const {
-  if (use_geometry_mapper_) {
-    DCHECK(fragment_data);
-    DCHECK(fragment_data->HasLocalBorderBoxProperties());
-    // TODO(chrishtr): find the root cause of not having a fragment and fix it.
-    if (!fragment_data->HasLocalBorderBoxProperties())
-      return;
-    CalculateRectsWithGeometryMapper(context, *fragment_data, layer_offset,
-                                     background_rect, foreground_rect);
+  DCHECK(fragment_data);
+  DCHECK(fragment_data->HasLocalBorderBoxProperties());
+  // TODO(chrishtr): find the root cause of not having a fragment and fix it.
+  if (!fragment_data->HasLocalBorderBoxProperties()) {
     return;
   }
-  DCHECK(!fragment_data);
-
-  bool is_clipping_root = layer_ == context.root_layer;
-  LayoutBoxModelObject& layout_object = layer_->GetLayoutObject();
-
-  if (!is_clipping_root && layer_->Parent()) {
-    CalculateBackgroundClipRect(context, background_rect);
-    background_rect.Move(context.sub_pixel_accumulation);
-  }
-
-  foreground_rect = background_rect;
-
-  layer_offset = context.sub_pixel_accumulation;
-  layer_->ConvertToLayerCoords(context.root_layer, layer_offset);
-
-  // Update the clip rects that will be passed to child layers.
-  if (ShouldClipOverflowAlongEitherAxis(context)) {
-    PhysicalRect overflow_and_clip_rect =
-        To<LayoutBox>(layout_object)
-            .OverflowClipRect(layer_offset,
-                              context.overlay_scrollbar_clip_behavior);
-    foreground_rect.Intersect(overflow_and_clip_rect);
-    if (layout_object.StyleRef().HasBorderRadius())
-      foreground_rect.SetHasRadius(true);
-
-    // FIXME: Does not do the right thing with columns yet, since we don't yet
-    // factor in the individual column boxes as overflow.
-
-    PhysicalRect layer_bounds_with_visual_overflow = LocalVisualRect(context);
-    layer_bounds_with_visual_overflow.Move(layer_offset);
-    background_rect.Intersect(layer_bounds_with_visual_overflow);
-  }
-
-  // CSS clip (different than clipping due to overflow) can clip to any box,
-  // even if it falls outside of the border box.
-  if (layout_object.HasClip()) {
-    // Clip applies to *us* as well, so go ahead and update the damageRect.
-    PhysicalRect new_pos_clip =
-        To<LayoutBox>(layout_object).ClipRect(layer_offset);
-    background_rect.Intersect(new_pos_clip);
-    foreground_rect.Intersect(new_pos_clip);
-  }
+  CalculateRectsWithGeometryMapper(context, *fragment_data, layer_offset,
+                                   background_rect, foreground_rect);
 }
 
-void PaintLayerClipper::CalculateClipRects(const ClipRectsContext& context,
-                                           ClipRects& clip_rects) const {
-  const LayoutBoxModelObject& layout_object = layer_->GetLayoutObject();
-  bool is_clipping_root = layer_ == context.root_layer;
-
-  if (is_clipping_root && !context.ShouldRespectRootLayerClip()) {
-    clip_rects.Reset(PhysicalRect(LayoutRect::InfiniteIntRect()));
-    if (layout_object.StyleRef().GetPosition() == EPosition::kFixed)
-      clip_rects.SetFixed(true);
-    return;
-  }
-
-  // For transformed layers, the root layer was shifted to be us, so there is no
-  // need to examine the parent. We want to cache clip rects with us as the
-  // root.
-  PaintLayer* parent_layer = !is_clipping_root ? layer_->Parent() : nullptr;
-  // Ensure that our parent's clip has been calculated so that we can examine
-  // the values.
-  if (parent_layer) {
-    PaintLayerClipper(parent_layer, use_geometry_mapper_)
-        .CalculateClipRects(context, clip_rects);
-  } else {
-    clip_rects.Reset(PhysicalRect(LayoutRect::InfiniteIntRect()));
-  }
-
-  AdjustClipRectsForChildren(layout_object, clip_rects);
-
-  // Computing paint offset is expensive, skip the computation if the object
-  // is known to have no clip. This check is redundant otherwise.
-  if (HasNonVisibleOverflow(*layer_) || layout_object.HasClip()) {
-    // This offset cannot use convertToLayerCoords, because sometimes our
-    // rootLayer may be across some transformed layer boundary, for example, in
-    // the PaintLayerCompositor overlapMap, where clipRects are needed in view
-    // space.
-    PhysicalOffset offset = layout_object.LocalToAncestorPoint(
-        PhysicalOffset(), &context.root_layer->GetLayoutObject());
-
-    ApplyClipRects(context, layout_object, offset, clip_rects);
-  }
-}
-
-static ClipRect BackgroundClipRectForPosition(const ClipRects& parent_rects,
-                                              EPosition position) {
-  if (position == EPosition::kFixed)
-    return parent_rects.FixedClipRect();
-
-  if (position == EPosition::kAbsolute)
-    return parent_rects.PosClipRect();
-
-  return parent_rects.OverflowClipRect();
-}
-
+// TODO(tkent): Merge this into CalculateBackgroundClipRect().
 void PaintLayerClipper::CalculateBackgroundClipRectWithGeometryMapper(
     const ClipRectsContext& context,
     const FragmentData& fragment_data,
     ShouldRespectOverflowClipType should_apply_self_overflow_clip,
     ClipRect& output) const {
-  DCHECK(use_geometry_mapper_);
-
   output.Reset();
   bool is_clipping_root = layer_ == context.root_layer;
   if (is_clipping_root && !context.ShouldRespectRootLayerClip())
@@ -354,55 +202,21 @@
       affected_by_url_bar
           ? layout_object.View()->ViewRect()
           : To<LayoutBox>(layout_object).PhysicalVisualOverflowRect();
-  // At this point layer_bounds_with_visual_overflow only includes the visual
-  // overflow induced by paint, prior to applying filters. This function is
-  // expected the return the final visual rect after filtering.
-  if (layer_->PaintsWithFilters() &&
-      // GeometryMapper will handle filter effects.
-      !use_geometry_mapper_) {
-    layer_bounds_with_visual_overflow =
-        layer_->MapRectForFilter(layer_bounds_with_visual_overflow);
-  }
   return layer_bounds_with_visual_overflow;
 }
 
 void PaintLayerClipper::CalculateBackgroundClipRect(
     const ClipRectsContext& context,
     ClipRect& output) const {
-  if (use_geometry_mapper_) {
-    const auto& fragment_data = layer_->GetLayoutObject().FirstFragment();
-    DCHECK(fragment_data.HasLocalBorderBoxProperties());
-    // TODO(chrishtr): find the root cause of not having a fragment and fix it.
-    if (!fragment_data.HasLocalBorderBoxProperties())
-      return;
-
-    CalculateBackgroundClipRectWithGeometryMapper(context, fragment_data,
-                                                  kIgnoreOverflowClip, output);
+  const auto& fragment_data = layer_->GetLayoutObject().FirstFragment();
+  DCHECK(fragment_data.HasLocalBorderBoxProperties());
+  // TODO(chrishtr): find the root cause of not having a fragment and fix it.
+  if (!fragment_data.HasLocalBorderBoxProperties()) {
     return;
   }
-  DCHECK(layer_->Parent());
-  LayoutView* layout_view = layer_->GetLayoutObject().View();
-  DCHECK(layout_view);
 
-  scoped_refptr<ClipRects> parent_clip_rects = ClipRects::Create();
-  if (layer_ == context.root_layer) {
-    parent_clip_rects->Reset(PhysicalRect(LayoutRect::InfiniteIntRect()));
-  } else {
-    PaintLayerClipper(layer_->Parent(), use_geometry_mapper_)
-        .CalculateClipRects(context, *parent_clip_rects);
-  }
-
-  output = BackgroundClipRectForPosition(
-      *parent_clip_rects, layer_->GetLayoutObject().StyleRef().GetPosition());
-  output.Move(context.sub_pixel_accumulation);
-
-  // Note: infinite clipRects should not be scrolled here, otherwise they will
-  // accidentally no longer be considered infinite.
-  if (parent_clip_rects->Fixed() &&
-      &context.root_layer->GetLayoutObject() == layout_view &&
-      output != PhysicalRect(LayoutRect::InfiniteIntRect())) {
-    output.Move(layout_view->PixelSnappedOffsetForFixedPosition());
-  }
+  CalculateBackgroundClipRectWithGeometryMapper(context, fragment_data,
+                                                kIgnoreOverflowClip, output);
 }
 
 bool PaintLayerClipper::ShouldClipOverflowAlongEitherAxis(
diff --git a/third_party/blink/renderer/core/paint/paint_layer_clipper.h b/third_party/blink/renderer/core/paint/paint_layer_clipper.h
index 09f514d..28c0f2ca 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_clipper.h
+++ b/third_party/blink/renderer/core/paint/paint_layer_clipper.h
@@ -158,13 +158,12 @@
 // a layout tree walk and cache them for painting.
 
 class ClipRect;
-class ClipRects;
 
 class CORE_EXPORT PaintLayerClipper {
   STACK_ALLOCATED();
 
  public:
-  explicit PaintLayerClipper(const PaintLayer*, bool use_geometry_mapper);
+  explicit PaintLayerClipper(const PaintLayer*);
 
   // Computes the same thing as |background_rect| in CalculateRects(), but
   // skips applying CSS clip and the VisualOverflowRect() of |layer_|.
@@ -181,8 +180,6 @@
                       ClipRect& foreground_rect) const;
 
  private:
-  void CalculateClipRects(const ClipRectsContext&, ClipRects&) const;
-
   ALWAYS_INLINE bool ShouldClipOverflowAlongEitherAxis(
       const ClipRectsContext&) const;
 
@@ -206,7 +203,6 @@
   ALWAYS_INLINE PhysicalRect LocalVisualRect(const ClipRectsContext&) const;
 
   const PaintLayer* layer_;
-  bool use_geometry_mapper_;
 
   friend class PaintLayerClipperTest;
 };
diff --git a/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc b/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc
index a0615018..a391d5a3 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc
@@ -35,22 +35,12 @@
                            PhysicalOffset(LayoutUnit(0.25), LayoutUnit(0.35)));
 
   ClipRect background_rect_gm;
-  target_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateBackgroundClipRect(context, background_rect_gm);
+  target_paint_layer->Clipper().CalculateBackgroundClipRect(context,
+                                                            background_rect_gm);
 
   EXPECT_EQ(PhysicalRect(LayoutUnit(8.25), LayoutUnit(8.34375), LayoutUnit(300),
                          LayoutUnit(300)),
             background_rect_gm.Rect());
-
-  ClipRect background_rect_nogm;
-  target_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper)
-      .CalculateBackgroundClipRect(context, background_rect_nogm);
-
-  EXPECT_EQ(PhysicalRect(LayoutUnit(8.25), LayoutUnit(8.34375), LayoutUnit(300),
-                         LayoutUnit(300)),
-            background_rect_nogm.Rect());
 }
 
 TEST_F(PaintLayerClipperTest, BackgroundClipRectSubpixelAccumulation) {
@@ -66,18 +56,10 @@
                            PhysicalOffset(LayoutUnit(0.25), LayoutUnit(0.35)));
 
   ClipRect background_rect_gm;
-  target_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateBackgroundClipRect(context, background_rect_gm);
+  target_paint_layer->Clipper().CalculateBackgroundClipRect(context,
+                                                            background_rect_gm);
 
   EXPECT_TRUE(background_rect_gm.IsInfinite()) << background_rect_gm;
-
-  ClipRect background_rect_nogm;
-  target_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper)
-      .CalculateBackgroundClipRect(context, background_rect_nogm);
-
-  EXPECT_EQ(background_rect_gm.Rect().size, background_rect_nogm.Rect().size);
 }
 
 TEST_F(PaintLayerClipperTest, SVGBackgroundClipRectSubpixelAccumulation) {
@@ -95,18 +77,10 @@
                            PhysicalOffset(LayoutUnit(0.25), LayoutUnit(0.35)));
 
   ClipRect background_rect_gm;
-  target_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateBackgroundClipRect(context, background_rect_gm);
+  target_paint_layer->Clipper().CalculateBackgroundClipRect(context,
+                                                            background_rect_gm);
 
   EXPECT_TRUE(background_rect_gm.IsInfinite()) << background_rect_gm;
-
-  ClipRect background_rect_nogm;
-  target_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper)
-      .CalculateBackgroundClipRect(context, background_rect_nogm);
-
-  EXPECT_EQ(background_rect_gm.Rect().size, background_rect_nogm.Rect().size);
 }
 
 TEST_F(PaintLayerClipperTest, LayoutSVGRoot) {
@@ -127,11 +101,9 @@
   PhysicalOffset layer_offset;
   ClipRect background_rect, foreground_rect;
 
-  target_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context,
-                      &target_paint_layer->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  target_paint_layer->Clipper().CalculateRects(
+      context, &target_paint_layer->GetLayoutObject().FirstFragment(),
+      layer_offset, background_rect, foreground_rect);
 
   EXPECT_EQ(PhysicalRect(LayoutUnit(8.25), LayoutUnit(8.35), LayoutUnit(200),
                          LayoutUnit(300)),
@@ -158,11 +130,9 @@
   PhysicalOffset layer_offset;
   ClipRect background_rect, foreground_rect;
 
-  target_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context,
-                      &target_paint_layer->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  target_paint_layer->Clipper().CalculateRects(
+      context, &target_paint_layer->GetLayoutObject().FirstFragment(),
+      layer_offset, background_rect, foreground_rect);
   // If the PaintLayer clips overflow, the background rect is intersected with
   // the PaintLayer bounds...
   EXPECT_EQ(PhysicalRect(8, 8, 200, 300), background_rect.Rect());
@@ -187,11 +157,9 @@
   PhysicalOffset layer_offset;
   ClipRect background_rect, foreground_rect;
 
-  target_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context,
-                      &target_paint_layer->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  target_paint_layer->Clipper().CalculateRects(
+      context, &target_paint_layer->GetLayoutObject().FirstFragment(),
+      layer_offset, background_rect, foreground_rect);
 
   // Only the foreground rect gets hasRadius set for overflow clipping
   // of descendants.
@@ -224,11 +192,9 @@
   PhysicalOffset layer_offset;
   ClipRect background_rect, foreground_rect;
 
-  child_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context,
-                      &child_paint_layer->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  child_paint_layer->Clipper().CalculateRects(
+      context, &child_paint_layer->GetLayoutObject().FirstFragment(),
+      layer_offset, background_rect, foreground_rect);
 
   EXPECT_EQ(PhysicalRect(0, 0, 200, 300), background_rect.Rect());
   EXPECT_TRUE(background_rect.HasRadius());
@@ -255,11 +221,9 @@
   PhysicalOffset layer_offset;
   ClipRect background_rect, foreground_rect;
 
-  target_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context,
-                      &target_paint_layer->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  target_paint_layer->Clipper().CalculateRects(
+      context, &target_paint_layer->GetLayoutObject().FirstFragment(),
+      layer_offset, background_rect, foreground_rect);
 
   PhysicalRect content_box_rect = target->PhysicalContentBoxRect();
   EXPECT_GT(foreground_rect.Rect().X(),
@@ -283,11 +247,9 @@
   PhysicalOffset layer_offset;
   ClipRect background_rect, foreground_rect;
 
-  target_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context,
-                      &target_paint_layer->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  target_paint_layer->Clipper().CalculateRects(
+      context, &target_paint_layer->GetLayoutObject().FirstFragment(),
+      layer_offset, background_rect, foreground_rect);
   EXPECT_EQ(PhysicalRect(8, 8, 200, 300), background_rect.Rect());
   EXPECT_EQ(PhysicalRect(8, 8, 200, 300), foreground_rect.Rect());
   EXPECT_EQ(PhysicalOffset(8, 8), layer_offset);
@@ -307,9 +269,9 @@
   PhysicalOffset layer_offset;
   ClipRect background_rect, foreground_rect;
 
-  layer->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context, &layer->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  layer->Clipper().CalculateRects(
+      context, &layer->GetLayoutObject().FirstFragment(), layer_offset,
+      background_rect, foreground_rect);
   EXPECT_TRUE(background_rect.IsInfinite()) << background_rect;
   EXPECT_EQ(background_rect.Rect(), foreground_rect.Rect());
   EXPECT_EQ(PhysicalOffset(), layer_offset);
@@ -317,9 +279,9 @@
   ClipRectsContext context_clip(layer,
                                 &layer->GetLayoutObject().FirstFragment());
 
-  layer->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context_clip, &layer->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  layer->Clipper().CalculateRects(
+      context_clip, &layer->GetLayoutObject().FirstFragment(), layer_offset,
+      background_rect, foreground_rect);
   EXPECT_EQ(PhysicalRect(0, 0, 200, 200), background_rect.Rect());
   EXPECT_EQ(PhysicalRect(0, 0, 200, 200), foreground_rect.Rect());
   EXPECT_EQ(PhysicalOffset(), layer_offset);
@@ -341,9 +303,9 @@
   PhysicalOffset layer_offset;
   ClipRect background_rect, foreground_rect;
 
-  layer->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context, &layer->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  layer->Clipper().CalculateRects(
+      context, &layer->GetLayoutObject().FirstFragment(), layer_offset,
+      background_rect, foreground_rect);
   EXPECT_EQ(PhysicalRect(0, 0, 200, 400), background_rect.Rect());
   EXPECT_EQ(PhysicalRect(0, 0, 200, 400), foreground_rect.Rect());
   EXPECT_EQ(PhysicalOffset(), layer_offset);
@@ -351,9 +313,9 @@
   ClipRectsContext context_clip(
       layer->Parent(), &layer->Parent()->GetLayoutObject().FirstFragment());
 
-  layer->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context_clip, &layer->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  layer->Clipper().CalculateRects(
+      context_clip, &layer->GetLayoutObject().FirstFragment(), layer_offset,
+      background_rect, foreground_rect);
   EXPECT_EQ(PhysicalRect(0, 0, 200, 200), background_rect.Rect());
   EXPECT_EQ(PhysicalRect(0, 0, 200, 200), foreground_rect.Rect());
   EXPECT_EQ(PhysicalOffset(), layer_offset);
@@ -377,9 +339,9 @@
   PhysicalOffset layer_offset = infinite_rect.offset;
   ClipRect background_rect(infinite_rect);
   ClipRect foreground_rect(infinite_rect);
-  target->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context, &target->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  target->Clipper().CalculateRects(
+      context, &target->GetLayoutObject().FirstFragment(), layer_offset,
+      background_rect, foreground_rect);
 
   EXPECT_EQ(PhysicalRect(0, 0, 50, 100), background_rect.Rect());
   EXPECT_EQ(PhysicalRect(0, 0, 50, 100), foreground_rect.Rect());
@@ -405,9 +367,9 @@
   PhysicalOffset layer_offset = infinite_rect.offset;
   ClipRect background_rect(infinite_rect);
   ClipRect foreground_rect(infinite_rect);
-  target->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context, &target->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  target->Clipper().CalculateRects(
+      context, &target->GetLayoutObject().FirstFragment(), layer_offset,
+      background_rect, foreground_rect);
 
   // The background rect is used to clip stacking context (layer) output.
   // In this case, nothing is above us, thus the infinite rect. However we do
@@ -417,38 +379,18 @@
   // stacking context (layer) thus including the overflow clip.
   EXPECT_EQ(PhysicalRect(40, 40, 100, 200), foreground_rect.Rect());
 
-  // Test without GeometryMapper.
-  background_rect = infinite_rect;
-  foreground_rect = infinite_rect;
-  target->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper)
-      .CalculateRects(context, nullptr, layer_offset, background_rect,
-                      foreground_rect);
-  // The non-GeometryMapper path applies the immediate filter effect in
-  // background rect.
-  EXPECT_EQ(PhysicalRect(-12, -9, 204, 304), background_rect.Rect());
-  EXPECT_EQ(PhysicalRect(40, 40, 100, 200), foreground_rect.Rect());
-
   // Test mapping to the root layer.
   ClipRectsContext root_context(GetLayoutView().Layer(),
                                 &GetLayoutView().FirstFragment());
   background_rect = infinite_rect;
   foreground_rect = infinite_rect;
-  target->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(root_context, &target->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  target->Clipper().CalculateRects(
+      root_context, &target->GetLayoutObject().FirstFragment(), layer_offset,
+      background_rect, foreground_rect);
   // This includes the filter effect because it's applied before mapping the
   // background rect to the root layer.
   EXPECT_EQ(PhysicalRect(38, 41, 204, 304), background_rect.Rect());
   EXPECT_EQ(PhysicalRect(90, 90, 100, 200), foreground_rect.Rect());
-
-  // Test mapping to the root layer without GeometryMapper.
-  background_rect = infinite_rect;
-  foreground_rect = infinite_rect;
-  target->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper)
-      .CalculateRects(root_context, nullptr, layer_offset, background_rect,
-                      foreground_rect);
-  EXPECT_EQ(PhysicalRect(38, 41, 204, 304), background_rect.Rect());
-  EXPECT_EQ(PhysicalRect(90, 90, 100, 200), foreground_rect.Rect());
 }
 
 TEST_F(PaintLayerClipperTest, IgnoreRootLayerClipWithCSSClip) {
@@ -475,9 +417,9 @@
   PhysicalOffset layer_offset = infinite_rect.offset;
   ClipRect background_rect(infinite_rect);
   ClipRect foreground_rect(infinite_rect);
-  target->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context, &target->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  target->Clipper().CalculateRects(
+      context, &target->GetLayoutObject().FirstFragment(), layer_offset,
+      background_rect, foreground_rect);
 
   EXPECT_TRUE(background_rect.IsInfinite());
   EXPECT_TRUE(foreground_rect.IsInfinite());
@@ -506,9 +448,9 @@
   PhysicalOffset layer_offset(LayoutRect::InfiniteIntRect().origin());
   ClipRect background_rect;
   ClipRect foreground_rect;
-  target->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context, &target->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  target->Clipper().CalculateRects(
+      context, &target->GetLayoutObject().FirstFragment(), layer_offset,
+      background_rect, foreground_rect);
 
   EXPECT_TRUE(background_rect.IsInfinite());
   EXPECT_TRUE(foreground_rect.IsInfinite());
@@ -539,9 +481,9 @@
   PhysicalOffset layer_offset = infinite_rect.offset;
   ClipRect background_rect(infinite_rect);
   ClipRect foreground_rect(infinite_rect);
-  target->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context, &target->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  target->Clipper().CalculateRects(
+      context, &target->GetLayoutObject().FirstFragment(), layer_offset,
+      background_rect, foreground_rect);
 
   EXPECT_TRUE(background_rect.IsInfinite());
   EXPECT_TRUE(foreground_rect.IsInfinite());
@@ -573,22 +515,18 @@
                    .NextFragment()
                    ->NextFragment());
 
-  target_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context,
-                      &target_paint_layer->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  target_paint_layer->Clipper().CalculateRects(
+      context, &target_paint_layer->GetLayoutObject().FirstFragment(),
+      layer_offset, background_rect, foreground_rect);
 
   EXPECT_TRUE(background_rect.IsInfinite());
   EXPECT_TRUE(foreground_rect.IsInfinite());
   EXPECT_EQ(PhysicalOffset(), layer_offset);
 
-  target_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(
-          context,
-          target_paint_layer->GetLayoutObject().FirstFragment().NextFragment(),
-          layer_offset, background_rect, foreground_rect);
+  target_paint_layer->Clipper().CalculateRects(
+      context,
+      target_paint_layer->GetLayoutObject().FirstFragment().NextFragment(),
+      layer_offset, background_rect, foreground_rect);
 
   EXPECT_TRUE(background_rect.IsInfinite());
   EXPECT_TRUE(foreground_rect.IsInfinite());
@@ -616,21 +554,9 @@
 
   PhysicalOffset layer_offset;
   ClipRect background_rect, foreground_rect;
-  child_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context,
-                      &child_paint_layer->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
-
-  // The background and foreground rect are clipped by the scrollbar size.
-  EXPECT_EQ(PhysicalRect(0, 0, 193, 293), background_rect.Rect());
-  EXPECT_EQ(PhysicalRect(0, 0, 193, 293), foreground_rect.Rect());
-  EXPECT_EQ(PhysicalOffset(), layer_offset);
-
-  child_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper)
-      .CalculateRects(context, nullptr, layer_offset, background_rect,
-                      foreground_rect);
+  child_paint_layer->Clipper().CalculateRects(
+      context, &child_paint_layer->GetLayoutObject().FirstFragment(),
+      layer_offset, background_rect, foreground_rect);
 
   // The background and foreground rect are clipped by the scrollbar size.
   EXPECT_EQ(PhysicalRect(0, 0, 193, 293), background_rect.Rect());
@@ -660,21 +586,9 @@
 
   PhysicalOffset layer_offset;
   ClipRect background_rect, foreground_rect;
-  child_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context,
-                      &child_paint_layer->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
-
-  // The background and foreground rect are clipped by the scrollbar size.
-  EXPECT_EQ(PhysicalRect(8, 8, 193, 293), background_rect.Rect());
-  EXPECT_EQ(PhysicalRect(8, 8, 193, 293), foreground_rect.Rect());
-  EXPECT_EQ(PhysicalOffset(8, 8), layer_offset);
-
-  child_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper)
-      .CalculateRects(context, nullptr, layer_offset, background_rect,
-                      foreground_rect);
+  child_paint_layer->Clipper().CalculateRects(
+      context, &child_paint_layer->GetLayoutObject().FirstFragment(),
+      layer_offset, background_rect, foreground_rect);
 
   // The background and foreground rect are clipped by the scrollbar size.
   EXPECT_EQ(PhysicalRect(8, 8, 193, 293), background_rect.Rect());
@@ -702,28 +616,15 @@
 
   PhysicalOffset layer_offset;
   ClipRect background_rect, foreground_rect;
-  parent_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kUseGeometryMapper)
-      .CalculateRects(context,
-                      &parent_paint_layer->GetLayoutObject().FirstFragment(),
-                      layer_offset, background_rect, foreground_rect);
+  parent_paint_layer->Clipper().CalculateRects(
+      context, &parent_paint_layer->GetLayoutObject().FirstFragment(),
+      layer_offset, background_rect, foreground_rect);
 
   // Only the foreground is clipped by the scrollbar size, because we
   // called CalculateRects on the root layer.
   EXPECT_EQ(PhysicalRect(0, 0, 200, 300), background_rect.Rect());
   EXPECT_EQ(PhysicalRect(0, 0, 193, 293), foreground_rect.Rect());
   EXPECT_EQ(PhysicalOffset(), layer_offset);
-
-  parent_paint_layer
-      ->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper)
-      .CalculateRects(context, nullptr, layer_offset, background_rect,
-                      foreground_rect);
-
-  // Only the foreground is clipped by the scrollbar size, because we
-  // called CalculateRects on the root layer.
-  EXPECT_EQ(PhysicalRect(0, 0, 200, 300), background_rect.Rect());
-  EXPECT_EQ(PhysicalRect(0, 0, 193, 293), foreground_rect.Rect());
-  EXPECT_EQ(PhysicalOffset(0, 0), layer_offset);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index 4138cc23..ea6ed0f 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -276,6 +276,8 @@
   friend class CachedUAStyle;
   // Accesses visited and unvisited colors.
   friend class ColorPropertyFunctions;
+  // Accesses inset and sizing property values.
+  friend class LengthPropertyFunctions;
   // Edits the background for media controls and accesses UserModify().
   friend class StyleAdjuster;
   // Access to GetCurrentColor(). (drop-shadow() does not resolve 'currentcolor'
@@ -286,6 +288,9 @@
   // Access to UserModify().
   friend class MatchedPropertiesCache;
 
+  // Allows unit tests to access protected members.
+  friend class StyleResolverTest;
+
   using ComputedStyleBase::Clear;
   using ComputedStyleBase::Floating;
   using ComputedStyleBase::Resize;
@@ -563,7 +568,9 @@
 
   // Returns true if the Element should stick to the viewport bottom as the URL
   // bar hides.
-  bool IsFixedToBottom() const { return !Bottom().IsAuto() && Top().IsAuto(); }
+  bool IsFixedToBottom() const {
+    return !UsedBottom().IsAuto() && UsedTop().IsAuto();
+  }
 
   // Border properties.
   // border-image-slice
@@ -1158,24 +1165,65 @@
   CORE_EXPORT LayoutUnit ComputedLineHeightAsFixed() const;
   LayoutUnit ComputedLineHeightAsFixed(const Font& font) const;
 
+  const Length& AdjustLengthForAnchorQueries(
+      const Length& original_value,
+      const Length& fallback_value) const {
+    if (LIKELY(!original_value.HasAnchorQueries())) {
+      return original_value;
+    }
+    return HasOutOfFlowPosition() ? original_value : fallback_value;
+  }
+
+  // Inset utility functions.
+  const Length& UsedLeft() const {
+    return AdjustLengthForAnchorQueries(Left(), Length::Auto());
+  }
+  const Length& UsedRight() const {
+    return AdjustLengthForAnchorQueries(Right(), Length::Auto());
+  }
+  const Length& UsedTop() const {
+    return AdjustLengthForAnchorQueries(Top(), Length::Auto());
+  }
+  const Length& UsedBottom() const {
+    return AdjustLengthForAnchorQueries(Bottom(), Length::Auto());
+  }
+
   // Width/height utility functions.
+  const Length& UsedWidth() const {
+    return AdjustLengthForAnchorQueries(Width(), Length::Auto());
+  }
+  const Length& UsedHeight() const {
+    return AdjustLengthForAnchorQueries(Height(), Length::Auto());
+  }
+  const Length& UsedMinWidth() const {
+    return AdjustLengthForAnchorQueries(MinWidth(), Length::Auto());
+  }
+  const Length& UsedMinHeight() const {
+    return AdjustLengthForAnchorQueries(MinHeight(), Length::Auto());
+  }
+  const Length& UsedMaxWidth() const {
+    return AdjustLengthForAnchorQueries(MaxWidth(), Length::None());
+  }
+  const Length& UsedMaxHeight() const {
+    return AdjustLengthForAnchorQueries(MaxHeight(), Length::None());
+  }
   const Length& LogicalWidth() const {
-    return IsHorizontalWritingMode() ? Width() : Height();
+    return IsHorizontalWritingMode() ? UsedWidth() : UsedHeight();
   }
   const Length& LogicalHeight() const {
-    return IsHorizontalWritingMode() ? Height() : Width();
+    return IsHorizontalWritingMode() ? UsedHeight() : UsedWidth();
   }
   const Length& LogicalMaxWidth() const {
-    return IsHorizontalWritingMode() ? MaxWidth() : MaxHeight();
+    return IsHorizontalWritingMode() ? UsedMaxWidth() : UsedMaxHeight();
   }
   const Length& LogicalMaxHeight() const {
-    return IsHorizontalWritingMode() ? MaxHeight() : MaxWidth();
+    return IsHorizontalWritingMode() ? UsedMaxHeight() : UsedMaxWidth();
   }
   const Length& LogicalMinWidth() const {
-    return IsHorizontalWritingMode() ? MinWidth() : MinHeight();
+    return IsHorizontalWritingMode() ? UsedMinWidth() : UsedMinHeight();
   }
   const Length& LogicalMinHeight() const {
-    return IsHorizontalWritingMode() ? MinHeight() : MinWidth();
+    return IsHorizontalWritingMode() ? UsedMinHeight() : UsedMinWidth();
   }
 
   // Margin utility functions.
@@ -1542,8 +1590,8 @@
   }
   bool HasStickyConstrainedPosition() const {
     return GetPosition() == EPosition::kSticky &&
-           (!Top().IsAuto() || !Left().IsAuto() || !Right().IsAuto() ||
-            !Bottom().IsAuto());
+           (!UsedTop().IsAuto() || !UsedLeft().IsAuto() ||
+            !UsedRight().IsAuto() || !UsedBottom().IsAuto());
   }
   static EPosition GetPosition(EDisplay display, EPosition position_internal) {
     // Applied sticky position is static for table columns and column groups.
@@ -1605,17 +1653,17 @@
     return PhysicalBoundsToLogical().After();
   }
   bool OffsetEqual(const ComputedStyle& other) const {
-    return Left() == other.Left() && Right() == other.Right() &&
-           Top() == other.Top() && Bottom() == other.Bottom();
+    return UsedLeft() == other.UsedLeft() && UsedRight() == other.UsedRight() &&
+           UsedTop() == other.UsedTop() && UsedBottom() == other.UsedBottom();
   }
 
   // Whether or not a positioned element requires normal flow x/y to be computed
   // to determine its position.
   bool HasAutoLeftAndRight() const {
-    return Left().IsAuto() && Right().IsAuto();
+    return UsedLeft().IsAuto() && UsedRight().IsAuto();
   }
   bool HasAutoTopAndBottom() const {
-    return Top().IsAuto() && Bottom().IsAuto();
+    return UsedTop().IsAuto() && UsedBottom().IsAuto();
   }
   bool HasStaticInlinePosition(bool horizontal) const {
     return horizontal ? HasAutoLeftAndRight() : HasAutoTopAndBottom();
@@ -2656,8 +2704,9 @@
   }
 
   PhysicalToLogical<const Length&> PhysicalBoundsToLogical() const {
-    return PhysicalToLogical<const Length&>(GetWritingDirection(), Top(),
-                                            Right(), Bottom(), Left());
+    return PhysicalToLogical<const Length&>(GetWritingDirection(), UsedTop(),
+                                            UsedRight(), UsedBottom(),
+                                            UsedLeft());
   }
 
   static Difference ComputeDifferenceIgnoringInheritedFirstLineStyle(
@@ -3125,6 +3174,20 @@
            ComputedStyleInitialValues::InitialLineHeight();
   }
 
+  // Sizing properties
+  const Length& UsedWidth() const {
+    if (LIKELY(!Width().HasAnchorQueries())) {
+      return Width();
+    }
+    return HasOutOfFlowPosition() ? Width() : Length::Auto();
+  }
+  const Length& UsedHeight() const {
+    if (LIKELY(!Height().HasAnchorQueries())) {
+      return Height();
+    }
+    return HasOutOfFlowPosition() ? Height() : Length::Auto();
+  }
+
   // margin-*
   void SetMarginTop(const Length& v) {
     if (MarginTop() != v) {
diff --git a/third_party/blink/renderer/core/svg/svg_rect_element.cc b/third_party/blink/renderer/core/svg/svg_rect_element.cc
index 72f7178..df90a1d 100644
--- a/third_party/blink/renderer/core/svg/svg_rect_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_rect_element.cc
@@ -90,8 +90,8 @@
   SVGLengthContext length_context(this);
   const ComputedStyle& style = ComputedStyleRef();
 
-  gfx::Vector2dF size =
-      length_context.ResolveLengthPair(style.Width(), style.Height(), style);
+  gfx::Vector2dF size = length_context.ResolveLengthPair(
+      style.UsedWidth(), style.UsedHeight(), style);
   if (size.x() < 0 || size.y() < 0 || size.IsZero())
     return path;
 
diff --git a/third_party/blink/renderer/modules/compute_pressure/pressure_client_impl.cc b/third_party/blink/renderer/modules/compute_pressure/pressure_client_impl.cc
index 16e4c63..ae20adb1 100644
--- a/third_party/blink/renderer/modules/compute_pressure/pressure_client_impl.cc
+++ b/third_party/blink/renderer/modules/compute_pressure/pressure_client_impl.cc
@@ -160,7 +160,7 @@
   }
 
   // 7. If top-level browsing context does not have system focus, return false.
-  DCHECK(this_frame->GetPage());
+  CHECK(this_frame->GetPage());
   const auto& focus_controller = this_frame->GetPage()->GetFocusController();
   if (!focus_controller.IsFocused()) {
     return false;
diff --git a/third_party/blink/renderer/modules/compute_pressure/pressure_observer.cc b/third_party/blink/renderer/modules/compute_pressure/pressure_observer.cc
index dffbb7d5..023a5d6d 100644
--- a/third_party/blink/renderer/modules/compute_pressure/pressure_observer.cc
+++ b/third_party/blink/renderer/modules/compute_pressure/pressure_observer.cc
@@ -53,7 +53,7 @@
 // static
 wtf_size_t PressureObserver::ToSourceIndex(V8PressureSource::Enum source) {
   wtf_size_t index = static_cast<wtf_size_t>(source);
-  DCHECK_LT(index, V8PressureSource::kEnumSize);
+  CHECK_LT(index, V8PressureSource::kEnumSize);
   return index;
 }
 
@@ -165,7 +165,7 @@
     records_.erase(records_.begin());
 
   records_.push_back(record);
-  DCHECK_LE(records_.size(), kMaxQueuedRecords);
+  CHECK_LE(records_.size(), kMaxQueuedRecords);
 
   if (pending_report_to_callback_.IsActive())
     return;
@@ -196,7 +196,7 @@
 }
 
 void PressureObserver::ReportToCallback(ExecutionContext* execution_context) {
-  DCHECK(observer_callback_);
+  CHECK(observer_callback_);
   if (!execution_context || execution_context->IsContextDestroyed())
     return;
 
diff --git a/third_party/blink/renderer/modules/compute_pressure/pressure_observer_manager.cc b/third_party/blink/renderer/modules/compute_pressure/pressure_observer_manager.cc
index 146225d4..12d75ab 100644
--- a/third_party/blink/renderer/modules/compute_pressure/pressure_observer_manager.cc
+++ b/third_party/blink/renderer/modules/compute_pressure/pressure_observer_manager.cc
@@ -111,7 +111,7 @@
 }
 
 void PressureObserverManager::EnsureServiceConnection() {
-  DCHECK(GetExecutionContext());
+  CHECK(GetExecutionContext());
 
   if (pressure_manager_.is_bound()) {
     return;
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
index 7a543d0..07694ba 100644
--- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
+++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
@@ -94,17 +94,6 @@
   kOpCodeBinary = 0x2,
 };
 
-// When enabled, a page can be aggressively throttled even if it uses a
-// WebSocket. Aggressive throttling does not affect the execution of WebSocket
-// event handlers, so there is little reason to disable it on pages using a
-// WebSocket.
-//
-// TODO(crbug.com/1121725): Cleanup this feature in June 2021, when it becomes
-// enabled by default on Stable.
-BASE_FEATURE(kAllowAggressiveThrottlingWithWebSocket,
-             "AllowAggressiveThrottlingWithWebSocket",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 }  // namespace
 
 void WebSocketChannelImpl::MessageDataDeleter::operator()(char* p) const {
@@ -290,10 +279,7 @@
   if (auto* scheduler = execution_context_->GetScheduler()) {
     feature_handle_for_scheduler_ = scheduler->RegisterFeature(
         SchedulingPolicy::Feature::kWebSocket,
-        base::FeatureList::IsEnabled(kAllowAggressiveThrottlingWithWebSocket)
-            ? SchedulingPolicy{SchedulingPolicy::DisableBackForwardCache()}
-            : SchedulingPolicy{SchedulingPolicy::DisableAggressiveThrottling(),
-                               SchedulingPolicy::DisableBackForwardCache()});
+        SchedulingPolicy{SchedulingPolicy::DisableBackForwardCache()});
   }
 
   if (MixedContentChecker::IsMixedContent(
diff --git a/third_party/blink/renderer/platform/exported/platform.cc b/third_party/blink/renderer/platform/exported/platform.cc
index eddf6b4..0cf40c7 100644
--- a/third_party/blink/renderer/platform/exported/platform.cc
+++ b/third_party/blink/renderer/platform/exported/platform.cc
@@ -50,6 +50,7 @@
 #include "third_party/blink/renderer/platform/bindings/parkable_string_manager.h"
 #include "third_party/blink/renderer/platform/font_family_names.h"
 #include "third_party/blink/renderer/platform/fonts/font_cache_memory_dump_provider.h"
+#include "third_party/blink/renderer/platform/geometry/length.h"
 #include "third_party/blink/renderer/platform/graphics/parkable_image_manager.h"
 #include "third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h"
 #include "third_party/blink/renderer/platform/heap/gc_task_runner.h"
@@ -194,6 +195,7 @@
   DCHECK(!did_initialize_blink_);
   WTF::Partitions::Initialize();
   WTF::Initialize();
+  Length::Initialize();
   ProcessHeap::Init();
   ThreadState::AttachMainThread();
   did_initialize_blink_ = true;
diff --git a/third_party/blink/renderer/platform/geometry/length.cc b/third_party/blink/renderer/platform/geometry/length.cc
index 8f888d8..0e4ef968 100644
--- a/third_party/blink/renderer/platform/geometry/length.cc
+++ b/third_party/blink/renderer/platform/geometry/length.cc
@@ -27,12 +27,23 @@
 
 #include "third_party/blink/renderer/platform/geometry/blend.h"
 #include "third_party/blink/renderer/platform/geometry/calculation_value.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
 #include "third_party/blink/renderer/platform/wtf/size_assertions.h"
+#include "third_party/blink/renderer/platform/wtf/static_constructors.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 
 namespace blink {
 
+PLATFORM_EXPORT DEFINE_GLOBAL(Length, g_auto_length);
+PLATFORM_EXPORT DEFINE_GLOBAL(Length, g_none_length);
+
+// static
+void Length::Initialize() {
+  new (WTF::NotNullTag::kNotNull, (void*)&g_auto_length) Length(kAuto);
+  new (WTF::NotNullTag::kNotNull, (void*)&g_none_length) Length(kNone);
+}
+
 class CalculationValueHandleMap {
   USING_FAST_MALLOC(CalculationValueHandleMap);
 
diff --git a/third_party/blink/renderer/platform/geometry/length.h b/third_party/blink/renderer/platform/geometry/length.h
index 7095bd0..9638c33 100644
--- a/third_party/blink/renderer/platform/geometry/length.h
+++ b/third_party/blink/renderer/platform/geometry/length.h
@@ -46,11 +46,18 @@
 
 class CalculationExpressionNode;
 class CalculationValue;
+class Length;
+
+PLATFORM_EXPORT extern const Length& g_auto_length;
+PLATFORM_EXPORT extern const Length& g_none_length;
 
 class PLATFORM_EXPORT Length {
   DISALLOW_NEW();
 
  public:
+  // Initializes global instances.
+  static void Initialize();
+
   enum class ValueRange { kAll, kNonNegative };
 
   // FIXME: This enum makes it hard to tell in general what values may be
@@ -138,7 +145,7 @@
     return Length(number, kFixed);
   }
   static Length Fixed() { return Length(kFixed); }
-  static Length Auto() { return Length(kAuto); }
+  static const Length& Auto() { return g_auto_length; }
   static Length FillAvailable() { return Length(kFillAvailable); }
   static Length MinContent() { return Length(kMinContent); }
   static Length MaxContent() { return Length(kMaxContent); }
@@ -146,7 +153,7 @@
   static Length ExtendToZoom() { return Length(kExtendToZoom); }
   static Length DeviceWidth() { return Length(kDeviceWidth); }
   static Length DeviceHeight() { return Length(kDeviceHeight); }
-  static Length None() { return Length(kNone); }
+  static const Length& None() { return g_none_length; }
   static Length FitContent() { return Length(kFitContent); }
   static Length Content() { return Length(kContent); }
   template <typename NUMBER_TYPE>
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 62ebc03..3498d4d 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -592,7 +592,6 @@
     },
     {
       name: "CloseWatcher",
-      base_feature: "none",
     },
     {
       name: "CLSScrollAnchoring",
@@ -2006,7 +2005,7 @@
     {
       // crbug.com/1353190
       name: "LayoutNGNoCopyBack",
-      depends_on: ["LayoutMediaNGContainer"],
+      depends_on: ["LayoutMediaNGContainer", "RemoveConvertToLayerCoords"],
       status: "test",
     },
     {
@@ -2781,6 +2780,11 @@
       base_feature: "none",
     },
     {
+      // crbug.com/1432839
+      name: "RemoveConvertToLayerCoords",
+      status: "stable",
+    },
+    {
       name: "RemoveDataUrlInSvgUse",
       status: "experimental",
       base_feature: "none",
diff --git a/third_party/blink/renderer/platform/testing/testing_platform_support.cc b/third_party/blink/renderer/platform/testing/testing_platform_support.cc
index 56751f9..779c216 100644
--- a/third_party/blink/renderer/platform/testing/testing_platform_support.cc
+++ b/third_party/blink/renderer/platform/testing/testing_platform_support.cc
@@ -43,6 +43,7 @@
 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
 #include "third_party/blink/public/platform/web_runtime_features.h"
 #include "third_party/blink/renderer/platform/font_family_names.h"
+#include "third_party/blink/renderer/platform/geometry/length.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/heap/heap_test_platform.h"
 #include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
@@ -209,6 +210,7 @@
 
   WTF::Partitions::Initialize();
   WTF::Initialize();
+  Length::Initialize();
 
   // This must be called after WTF::Initialize(), because ThreadSpecific<>
   // used in this function depends on WTF::IsMainThread().
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 4124ac70..0662c61 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -3424,6 +3424,9 @@
 
 crbug.com/1131471 external/wpt/web-locks/clientids.tentative.https.html [ Failure ]
 
+# Temporarily disabled to land a DevTools icon rework CL
+crbug.com/1427397 http/tests/devtools/network/network-requestblocking-icon.js [ Failure Pass ]
+
 # See also crbug.com/920100 (sheriff 2019-01-09).
 crbug.com/626703 external/wpt/referrer-policy/css-integration/svg/external-stylesheet.html [ Failure Timeout ]
 crbug.com/626703 external/wpt/referrer-policy/css-integration/svg/inline-style.html [ Failure Timeout ]
@@ -3669,7 +3672,6 @@
 crbug.com/618969 external/wpt/css/css-grid/subgrid/grid-gap-larger-001.html [ Failure ]
 crbug.com/618969 external/wpt/css/css-grid/subgrid/grid-gap-larger-002.html [ Failure ]
 crbug.com/618969 external/wpt/css/css-grid/subgrid/grid-gap-smaller-001.html [ Failure ]
-crbug.com/618969 external/wpt/css/css-grid/subgrid/independent-formatting-context.html [ Failure ]
 crbug.com/618969 external/wpt/css/css-grid/subgrid/item-percentage-height-001.html [ Failure ]
 crbug.com/618969 external/wpt/css/css-grid/subgrid/line-names-007.html [ Failure ]
 crbug.com/618969 external/wpt/css/css-grid/subgrid/line-names-012.html [ Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 83087be..8e338f1 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -350,7 +350,7 @@
   },
   {
     "prefix": "compute-pressure",
-    "platforms": ["Linux", "Mac"],
+    "platforms": ["Linux", "Mac", "Win"],
     "bases": ["external/wpt/compute-pressure"],
     "exclusive_tests": "ALL",
     "args": ["--enable-features=ComputePressure"],
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 e4ff798..837a73a7 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
@@ -92750,6 +92750,45 @@
        {}
       ]
      ],
+     "overflow-clip-014.html": [
+      "4edf112e43265cd13465b6e86e9e1c2f288cf78c",
+      [
+       null,
+       [
+        [
+         "/css/reference/ref-filled-green-100px-square.xht",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "overflow-clip-015.html": [
+      "1eb114458c1bf5a1a69620a6ea3a1f746248d610",
+      [
+       null,
+       [
+        [
+         "/css/reference/ref-filled-green-100px-square.xht",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "overflow-clip-016.html": [
+      "4314c0135e26e6afe8659ce74fe24c14cf46281a",
+      [
+       null,
+       [
+        [
+         "/css/reference/ref-filled-green-100px-square.xht",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "overflowed-block-with-no-room-after-000.html": [
       "084e16fb38de072fb83f92ba01302a2e404cdd97",
       [
@@ -134535,7 +134574,7 @@
        ]
       ],
       "independent-formatting-context.html": [
-       "888b23c2f621e1abfa027a4f42cbebb00db89656",
+       "5a76ac2d6dea91a0d13de29d9192aaf8df3ae350",
        [
         null,
         [
@@ -269675,11 +269714,11 @@
   "support": {
    ".cache": {
     "gitignore2.json": [
-     "1c376ec726001351bcb99f7d7d52408bb26060c4",
+     "672433b52e6c2a8b106eea7f3b2ff5740512b408",
      []
     ],
     "mtime.json": [
-     "1f3cee39d216df08639f1757489e81fba625175f",
+     "e9c7411915628908c44bded998b4568fa3325d6a",
      []
     ]
    },
@@ -273993,20 +274032,12 @@
       "90ed0a78576edc041caaa2ae70c319837152b726",
       []
      ],
-     "observer-in-dedicated-worker.js": [
-      "a30edd0a33ede1a1f628c356c92b768ed31e3e2f",
-      []
-     ],
-     "observer-in-shared-worker.js": [
-      "f69eadaacee6324edd021f1f20a245e5dd720cbc",
-      []
-     ],
      "pressure-helpers.js": [
       "5234cf2d78c90d559d3cfd8ee1b86d9b3fa97861",
       []
      ],
      "support-iframe.html": [
-      "57e18b77f62dbae3425e9f8b59b4d43c439ea709",
+      "6b2b3097926b192df23c3e21dd19742bb19e69d4",
       []
      ]
     }
@@ -304669,7 +304700,7 @@
        []
       ],
       "independent-formatting-context-ref.html": [
-       "79b90c340d844568014a3062ea35b2c087044ead",
+       "fe842b2823832e9feaae3534eab8220dd65cf129",
        []
       ],
       "independent-formatting-context.html.ini": [
@@ -346199,6 +346230,10 @@
       "1937997560d0f00bc3b317a59b7d5b5640bacb47",
       []
      ],
+     "element-request-fullscreen-screen-size.https.html.ini": [
+      "8c28bf666f1fa49987d8326a0eb682ad62999a4f",
+      []
+     ],
      "element-request-fullscreen-svg-svg.html.ini": [
       "833d82a04769fcb70c206ade64d293eb23b5e3b7",
       []
@@ -377980,7 +378015,7 @@
       []
      ],
      "mock-pressure-service.js": [
-      "e41464eefc32e154e29e48085a770b908e926437",
+      "21811ed52da2cd4f6782b390d848d0085d0849cc",
       []
      ],
      "mock-pressure-service.js.headers": [
@@ -378381,7 +378416,7 @@
      []
     ],
     "orientation-reading.html.ini": [
-     "a84e655e4a21b4d98482f0565a79c3a217f5559f",
+     "939808a85f01196730f935abbd9d8b76fb387123",
      []
     ],
     "resources": {
@@ -378808,6 +378843,14 @@
      "a70bcae0a4bbdb91e1f80aa0dff29feffbcf4db6",
      []
     ],
+    "authentication-disallowed-when-hidden.https-expected.txt": [
+     "658ad4f569d7460d2d33ca8040938b5ce3cba418",
+     []
+    ],
+    "authentication-disallowed-when-hidden.https.html.ini": [
+     "c86ff86f69a503c7f19541f5eabc875fbd51e640",
+     []
+    ],
     "authentication-icon-data-url.https-expected.txt": [
      "c6927a37c11f0b5fa24dcd5c25ae286f9a2f9685",
      []
@@ -422686,17 +422729,10 @@
     ]
    },
    "compute-pressure": {
-    "compute_pressure_basic.tentative.https.window.js": [
-     "e2d9a0f05bc99a7e798c6ca71a152f72481f5c49",
+    "compute_pressure_basic.tentative.https.any.js": [
+     "18b8985cf51c2c9874af273ceeb38eb697df3345",
      [
-      "compute-pressure/compute_pressure_basic.tentative.https.window.html",
-      {}
-     ]
-    ],
-    "compute_pressure_basic_async.tentative.https.window.js": [
-     "a70ffa98b130d3298b0f7f428ae027992058ff55",
-     [
-      "compute-pressure/compute_pressure_basic_async.tentative.https.window.html",
+      "compute-pressure/compute_pressure_basic.tentative.https.any.html",
       {
        "script_metadata": [
         [
@@ -422710,6 +422746,58 @@
         [
          "script",
          "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ],
+       "timeout": "long"
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_basic.tentative.https.any.sharedworker.html",
+      {
+       "script_metadata": [
+        [
+         "timeout",
+         "long"
+        ],
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ],
+       "timeout": "long"
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_basic.tentative.https.any.worker.html",
+      {
+       "script_metadata": [
+        [
+         "timeout",
+         "long"
+        ],
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
         ]
        ],
        "timeout": "long"
@@ -422717,7 +422805,7 @@
      ]
     ],
     "compute_pressure_cross_origin_focus_control.tentative.https.window.js": [
-     "f88c9fdf64e3afdae60b06fd658256841e9a5283",
+     "950334d6fc57f324b61cede416920534ccce76aa",
      [
       "compute-pressure/compute_pressure_cross_origin_focus_control.tentative.https.window.html",
       {
@@ -422729,6 +422817,14 @@
         [
          "script",
          "/common/get-host-info.sub.js"
+        ],
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
         ]
        ],
        "timeout": "long"
@@ -422736,37 +422832,16 @@
      ]
     ],
     "compute_pressure_detached_iframe.tentative.https.html": [
-     "3b0a5504e536acf9426476122f59b7c8ed24b150",
+     "5511a147048d610125a0d0d485367b88e4e5a70e",
      [
       null,
       {}
      ]
     ],
-    "compute_pressure_disconnect.tentative.https.window.js": [
-     "c9950f2dc84d2ad7001df440b598d0730fe3cfb9",
+    "compute_pressure_disconnect.tentative.https.any.js": [
+     "1d188fad8b8e1cd2123e320d99943c408be55fcd",
      [
-      "compute-pressure/compute_pressure_disconnect.tentative.https.window.html",
-      {}
-     ]
-    ],
-    "compute_pressure_disconnect_idempotent.tentative.https.window.js": [
-     "72021fd2708b6aab870e133f744cf53ebd61f194",
-     [
-      "compute-pressure/compute_pressure_disconnect_idempotent.tentative.https.window.html",
-      {}
-     ]
-    ],
-    "compute_pressure_disconnect_immediately.tentative.https.window.js": [
-     "1abe84d57202ba568d4c1fa459b355e591582a77",
-     [
-      "compute-pressure/compute_pressure_disconnect_immediately.tentative.https.window.html",
-      {}
-     ]
-    ],
-    "compute_pressure_duplicate_updates.tentative.https.window.js": [
-     "6318c0e88fb4336bef892727eac07b6a3c15d67e",
-     [
-      "compute-pressure/compute_pressure_duplicate_updates.tentative.https.window.html",
+      "compute-pressure/compute_pressure_disconnect.tentative.https.any.html",
       {
        "script_metadata": [
         [
@@ -422776,15 +422851,16 @@
         [
          "script",
          "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
         ]
        ]
       }
-     ]
-    ],
-    "compute_pressure_factors.tentative.https.window.js": [
-     "fc2775559647ab6e06b9167ecae608c17d52c709",
+     ],
      [
-      "compute-pressure/compute_pressure_factors.tentative.https.window.html",
+      "compute-pressure/compute_pressure_disconnect.tentative.https.any.sharedworker.html",
       {
        "script_metadata": [
         [
@@ -422794,48 +422870,468 @@
         [
          "script",
          "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_disconnect.tentative.https.any.worker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
         ]
        ]
       }
      ]
     ],
-    "compute_pressure_multiple.tentative.https.window.js": [
-     "6015ae1f81bc495e642a7482757934fa1c1a1924",
+    "compute_pressure_disconnect_idempotent.tentative.https.any.js": [
+     "2f6421ee11711f8d1768cc19d233346440f16f7f",
      [
-      "compute-pressure/compute_pressure_multiple.tentative.https.window.html",
-      {}
+      "compute-pressure/compute_pressure_disconnect_idempotent.tentative.https.any.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_disconnect_idempotent.tentative.https.any.sharedworker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_disconnect_idempotent.tentative.https.any.worker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
      ]
     ],
-    "compute_pressure_multiple_across_iframes.tentative.https.window.js": [
-     "838b9a17a00f2bf14f8443673fac1fbc4560e6fe",
+    "compute_pressure_disconnect_immediately.tentative.https.any.js": [
+     "b96ebd802e666bcd0230406da3435d8969484037",
      [
-      "compute-pressure/compute_pressure_multiple_across_iframes.tentative.https.window.html",
-      {}
+      "compute-pressure/compute_pressure_disconnect_immediately.tentative.https.any.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_disconnect_immediately.tentative.https.any.sharedworker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_disconnect_immediately.tentative.https.any.worker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
      ]
     ],
-    "compute_pressure_observe_idempotent.tentative.https.window.js": [
-     "e60115fee87c15cb25c55382e418e7611514c892",
+    "compute_pressure_duplicate_updates.tentative.https.any.js": [
+     "b5d7690d18295b82bf052faa3a7c93cc5ecc024a",
      [
-      "compute-pressure/compute_pressure_observe_idempotent.tentative.https.window.html",
-      {}
+      "compute-pressure/compute_pressure_duplicate_updates.tentative.https.any.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_duplicate_updates.tentative.https.any.sharedworker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_duplicate_updates.tentative.https.any.worker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
      ]
     ],
-    "compute_pressure_observe_unobserve_failure.tentative.https.window.js": [
-     "c32649da5c3dde260d74c0ab6bbeb275143d385d",
+    "compute_pressure_factors.tentative.https.any.js": [
+     "7486a70f91170c180ea12f8a0acee46a2626b640",
      [
-      "compute-pressure/compute_pressure_observe_unobserve_failure.tentative.https.window.html",
-      {}
+      "compute-pressure/compute_pressure_factors.tentative.https.any.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_factors.tentative.https.any.sharedworker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_factors.tentative.https.any.worker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
      ]
     ],
-    "compute_pressure_options.tentative.https.window.js": [
-     "d142ecc088187e60bcdbbd5a94b81c1d37c89331",
+    "compute_pressure_multiple.tentative.https.any.js": [
+     "c8cef5beca0cba5b26ba897d16f90b08caa1c40d",
      [
-      "compute-pressure/compute_pressure_options.tentative.https.window.html",
-      {}
+      "compute-pressure/compute_pressure_multiple.tentative.https.any.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_multiple.tentative.https.any.sharedworker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_multiple.tentative.https.any.worker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ]
+    ],
+    "compute_pressure_observe_idempotent.tentative.https.any.js": [
+     "5dc3804b2f7ea21f5e189351ea0194f30d6f536d",
+     [
+      "compute-pressure/compute_pressure_observe_idempotent.tentative.https.any.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_observe_idempotent.tentative.https.any.sharedworker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_observe_idempotent.tentative.https.any.worker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ]
+    ],
+    "compute_pressure_observe_unobserve_failure.tentative.https.any.js": [
+     "8eafeb356d815728719b61aee9e9ee704b79bdad",
+     [
+      "compute-pressure/compute_pressure_observe_unobserve_failure.tentative.https.any.html",
+      {
+       "script_metadata": [
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_observe_unobserve_failure.tentative.https.any.sharedworker.html",
+      {
+       "script_metadata": [
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_observe_unobserve_failure.tentative.https.any.worker.html",
+      {
+       "script_metadata": [
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ]
+    ],
+    "compute_pressure_options.tentative.https.any.js": [
+     "69999819d962fbf1841d87a817aed1ac23767f17",
+     [
+      "compute-pressure/compute_pressure_options.tentative.https.any.html",
+      {
+       "script_metadata": [
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_options.tentative.https.any.sharedworker.html",
+      {
+       "script_metadata": [
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_options.tentative.https.any.worker.html",
+      {
+       "script_metadata": [
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
      ]
     ],
     "compute_pressure_privacy_test.tentative.https.window.js": [
-     "d33f6ef09ad1681a2803fc0fda8315dcd80e39f9",
+     "113f4bdf79be9325df22f859c819558ab37429f5",
      [
       "compute-pressure/compute_pressure_privacy_test.tentative.https.window.html",
       {
@@ -422867,6 +423363,14 @@
         [
          "script",
          "/resources/testdriver-vendor.js"
+        ],
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
         ]
        ],
        "timeout": "long"
@@ -422874,26 +423378,16 @@
      ]
     ],
     "compute_pressure_same_origin_focus_control.tentative.https.window.js": [
-     "746f119f249c8c1a7d6451a5672823d011adf22e",
+     "7df0be5c47d161fe4cadcba937f875a0a0cba320",
      [
       "compute-pressure/compute_pressure_same_origin_focus_control.tentative.https.window.html",
-      {}
-     ]
-    ],
-    "compute_pressure_supported_sources.tentative.https.window.js": [
-     "2a69e731e7f9f7c5c0b54ea3b7bc9202bda57f16",
-     [
-      "compute-pressure/compute_pressure_supported_sources.tentative.https.window.html",
-      {}
-     ]
-    ],
-    "compute_pressure_take_records.tentative.https.window.js": [
-     "d294a7e80fd7e4cfcf4bbf5962f9014e1826e331",
-     [
-      "compute-pressure/compute_pressure_take_records.tentative.https.window.html",
       {
        "script_metadata": [
         [
+         "timeout",
+         "long"
+        ],
+        [
          "script",
          "/resources/test-only-api.js"
         ],
@@ -422901,32 +423395,51 @@
          "script",
          "resources/pressure-helpers.js"
         ]
-       ]
+       ],
+       "timeout": "long"
       }
      ]
     ],
-    "compute_pressure_timestamp.tentative.https.window.js": [
-     "aae56180aa3014e6faaa20d2dc421d9393e0ca42",
+    "compute_pressure_supported_sources.tentative.https.any.js": [
+     "63f2666cca69c9ed69b1449fb5c336854d11967d",
      [
-      "compute-pressure/compute_pressure_timestamp.tentative.https.window.html",
+      "compute-pressure/compute_pressure_supported_sources.tentative.https.any.html",
       {
        "script_metadata": [
         [
-         "script",
-         "/resources/test-only-api.js"
-        ],
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_supported_sources.tentative.https.any.sharedworker.html",
+      {
+       "script_metadata": [
         [
-         "script",
-         "resources/pressure-helpers.js"
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_supported_sources.tentative.https.any.worker.html",
+      {
+       "script_metadata": [
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
         ]
        ]
       }
      ]
     ],
-    "compute_pressure_update_toJSON.tentative.https.window.js": [
-     "f21cd464c6630eec60b89ead8510081c4b77d0fa",
+    "compute_pressure_take_records.tentative.https.any.js": [
+     "d93c9b5c886f9d57def646c052f5ea1cce627ea5",
      [
-      "compute-pressure/compute_pressure_update_toJSON.tentative.https.window.html",
+      "compute-pressure/compute_pressure_take_records.tentative.https.any.html",
       {
        "script_metadata": [
         [
@@ -422936,6 +423449,168 @@
         [
          "script",
          "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_take_records.tentative.https.any.sharedworker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_take_records.tentative.https.any.worker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ]
+    ],
+    "compute_pressure_timestamp.tentative.https.any.js": [
+     "f283caa6baebbe531b1fdddb2add2b761b7ad083",
+     [
+      "compute-pressure/compute_pressure_timestamp.tentative.https.any.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_timestamp.tentative.https.any.sharedworker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_timestamp.tentative.https.any.worker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ]
+    ],
+    "compute_pressure_update_toJSON.tentative.https.any.js": [
+     "c1cd240a3bc52b4b9dc79cb594d48ebdd7f64ec7",
+     [
+      "compute-pressure/compute_pressure_update_toJSON.tentative.https.any.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_update_toJSON.tentative.https.any.sharedworker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
+        ]
+       ]
+      }
+     ],
+     [
+      "compute-pressure/compute_pressure_update_toJSON.tentative.https.any.worker.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/test-only-api.js"
+        ],
+        [
+         "script",
+         "resources/pressure-helpers.js"
+        ],
+        [
+         "global",
+         "window,dedicatedworker,sharedworker"
         ]
        ]
       }
@@ -433426,6 +434101,13 @@
        {}
       ]
      ],
+     "anchor-non-oof-inherit.html": [
+      "75f98a1ebfe0e6b61008e2152bea88228829af08",
+      [
+       null,
+       {}
+      ]
+     ],
      "anchor-parse-invalid.html": [
       "de4b0ffac45ec09914bac7bbfd43fabf8b083989",
       [
@@ -505190,6 +505872,15 @@
        }
       ]
      ],
+     "element-request-fullscreen-screen-size.https.html": [
+      "1c2bc9e3d119edb9ebeb88aabe33aeee7b7a334a",
+      [
+       null,
+       {
+        "testdriver": true
+       }
+      ]
+     ],
      "element-request-fullscreen-svg-rect.html": [
       "44adfa68986566e63ad788eeb2f8595076c1c413",
       [
@@ -593786,7 +594477,7 @@
      ]
     ],
     "orientation-reading.html": [
-     "0bebb6723a384fc112358418d783e72a762940e2",
+     "90bbb8071dacf704c5a66b564268af4ee4f92354",
      [
       null,
       {
@@ -594134,6 +594825,13 @@
        {}
       ]
      ],
+     "scroll-timeline-attachment.html": [
+      "78ca257437322a5b24281f9bd45cffabf728cad2",
+      [
+       null,
+       {}
+      ]
+     ],
      "scroll-timeline-axis-computed.html": [
       "b971aba6c0f8a5bd5a6e18ddbef1cc296263c305",
       [
@@ -594323,6 +595021,13 @@
        {}
       ]
      ],
+     "view-timeline-attachment.html": [
+      "47f4444b0dcad286f9a9d538e0e85d05623c3ea3",
+      [
+       null,
+       {}
+      ]
+     ],
      "view-timeline-axis-computed.html": [
       "f4649dab0404a49be5014e2df7475fd151c44342",
       [
@@ -594962,6 +595667,15 @@
       }
      ]
     ],
+    "authentication-disallowed-when-hidden.https.html": [
+     "1c01fa0e89c133122952479e2e3b1a0632ce0007",
+     [
+      null,
+      {
+       "testdriver": true
+      }
+     ]
+    ],
     "authentication-icon-data-url.https.html": [
      "cd820d84c32116a400f76f059af97a0241cfcc37",
      [
@@ -628297,7 +629011,7 @@
      ]
     ],
     "video-encoder.https.any.js": [
-     "b5c511d4062cc5bf473dfbb670491d02c1daa19e",
+     "229ae32edd44307d8683ad8793641d16d9d28c1c",
      [
       "webcodecs/video-encoder.https.any.html",
       {
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_basic_async.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_basic.tentative.https.any.js
similarity index 87%
rename from third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_basic_async.tentative.https.window.js
rename to third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_basic.tentative.https.any.js
index a70ffa9..18b8985c 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_basic_async.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_basic.tentative.https.any.js
@@ -1,6 +1,7 @@
 // META: timeout=long
 // META: script=/resources/test-only-api.js
 // META: script=resources/pressure-helpers.js
+// META: global=window,dedicatedworker,sharedworker
 
 'use strict';
 
@@ -17,9 +18,10 @@
 pressure_test(async (t, mockPressureService) => {
   const changes = await new Promise(resolve => {
     const observer = new PressureObserver(resolve);
+    t.add_cleanup(() => observer.disconnect());
     observer.observe('cpu');
     mockPressureService.setPressureUpdate('cpu', 'critical');
-    mockPressureService.startPlatformCollector(/*sampleRate=*/ 1.0);
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
   });
   assert_true(changes.length === 1);
   assert_equals(changes[0].state, 'critical');
@@ -35,7 +37,7 @@
   const promise = observer.observe('cpu');
   observer.unobserve('cpu');
   mockPressureService.setPressureUpdate('cpu', 'critical');
-  mockPressureService.startPlatformCollector(/*sampleRate=*/ 1.0);
+  mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
 
   return promise_rejects_dom(t, 'NotSupportedError', promise);
 }, 'Removing observer before observe() resolves works');
@@ -47,6 +49,7 @@
   for (let i = 0; i < 2; i++) {
     callbackPromises.push(new Promise(resolve => {
       const observer = new PressureObserver(resolve);
+      t.add_cleanup(() => observer.disconnect());
       observePromises.push(observer.observe('cpu'));
     }));
   }
@@ -54,7 +57,7 @@
   await Promise.all(observePromises);
 
   mockPressureService.setPressureUpdate('cpu', 'critical');
-  mockPressureService.startPlatformCollector(/*sampleRate=*/ 1.0);
+  mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
 
   return Promise.all(callbackPromises);
 }, 'Calling observe() multiple times works');
@@ -69,7 +72,7 @@
     t.add_cleanup(() => observer1.disconnect());
     observer1.observe('cpu');
     mockPressureService.setPressureUpdate('cpu', 'critical');
-    mockPressureService.startPlatformCollector(/*sampleRate=*/ 1.0);
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
   });
   assert_true(observer1_changes.length === 1);
   assert_equals(observer1_changes[0][0].source, 'cpu');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_basic.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_basic.tentative.https.window.js
deleted file mode 100644
index e2d9a0f0..0000000
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_basic.tentative.https.window.js
+++ /dev/null
@@ -1,35 +0,0 @@
-'use strict';
-
-promise_test(async t => {
-  await new Promise((resolve, reject) => {
-    const observer = new PressureObserver(resolve, {sampleRate: 1.0});
-    t.add_cleanup(() => observer.disconnect());
-    observer.observe('cpu').catch(reject);
-  });
-}, 'An active PressureObserver calls its callback at least once');
-
-promise_test(async t => {
-  await new Promise(resolve => {
-    const myDedicatedWorker = new Worker(
-        '/compute-pressure/resources/observer-in-dedicated-worker.js');
-    myDedicatedWorker.onmessage = event => {
-      assert_equals(typeof event.data.time, 'number');
-      assert_equals('cpu', event.data.source);
-      resolve();
-    };
-  });
-}, 'Test receives updates from dedicated worker');
-
-promise_test(async t => {
-  await new Promise(resolve => {
-    const mySharedWorker = new SharedWorker(
-        '/compute-pressure/resources/observer-in-shared-worker.js');
-    mySharedWorker.port.start();
-    mySharedWorker.port.postMessage('observe');
-    mySharedWorker.port.onmessage = event => {
-      assert_equals(typeof event.data.time, 'number');
-      assert_equals('cpu', event.data.source);
-      resolve();
-    };
-  });
-}, 'Test receives updates from shared worker');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_cross_origin_focus_control.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_cross_origin_focus_control.tentative.https.window.js
index f88c9fd..950334d 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_cross_origin_focus_control.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_cross_origin_focus_control.tentative.https.window.js
@@ -1,9 +1,11 @@
 // META: timeout=long
 // META: script=/common/get-host-info.sub.js
+// META: script=/resources/test-only-api.js
+// META: script=resources/pressure-helpers.js
 
 'use strict';
 
-promise_test(async t => {
+pressure_test(async (t, mockPressureService) => {
   const iframe = document.createElement('iframe');
   iframe.src = get_host_info().HTTPS_REMOTE_ORIGIN +
       '/compute-pressure/resources/support-iframe.html';
@@ -20,11 +22,13 @@
     iframe.remove();
   });
   await observer.observe('cpu');
+  mockPressureService.setPressureUpdate('cpu', 'critical');
+  mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
 
-  return new Promise(resolve => t.step_timeout(resolve, 2000));
+  return new Promise(resolve => t.step_timeout(resolve, 1000));
 }, 'Observer in main frame should not receive PressureRecord when focused on cross-origin iframe');
 
-promise_test(async t => {
+pressure_test(async (t, mockPressureService) => {
   const iframe = document.createElement('iframe');
   iframe.src = get_host_info().HTTPS_REMOTE_ORIGIN +
       '/compute-pressure/resources/support-iframe.html';
@@ -49,5 +53,7 @@
       }
     }, {once: true});
     iframe.contentWindow.postMessage({command: 'start'}, '*');
+    mockPressureService.setPressureUpdate('cpu', 'critical');
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
   });
 }, 'Observer in iframe should not receive PressureRecord when focused on cross-origin main frame');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_detached_iframe.tentative.https.html b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_detached_iframe.tentative.https.html
index 3b0a5504..5511a14 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_detached_iframe.tentative.https.html
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_detached_iframe.tentative.https.html
@@ -3,6 +3,8 @@
 <title>PressureObserver on DOMWindow of detached iframe</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="/resources/test-only-api.js"></script>
+<script src="resources/pressure-helpers.js"></script>
 <body>
 <script>
 'use strict';
@@ -21,9 +23,7 @@
   document.body.appendChild(iframe);
   const frame_window = iframe.contentWindow;
 
-  const observer = new frame_window.PressureObserver(
-      () => {},
-      {sampleRate: 1});
+  const observer = new frame_window.PressureObserver(() => {});
   const iframe_DOMException = frame_window.DOMException;
 
   iframe.remove();
@@ -38,9 +38,7 @@
   document.body.appendChild(iframe);
   const frame_window = iframe.contentWindow;
 
-  const observer = new frame_window.PressureObserver(
-      () => {},
-      {sampleRate: 1});
+  const observer = new frame_window.PressureObserver(() => {});
 
   await observer.observe('cpu');
 
@@ -50,43 +48,43 @@
   observer.disconnect();
 }, 'PressureObserver.disconnect() on detached frame returns');
 
-promise_test(async t => {
+pressure_test(async (t, mockPressureService) => {
   const iframe = document.createElement('iframe');
   document.body.appendChild(iframe);
   const frame_window = iframe.contentWindow;
 
-  const observer = new frame_window.PressureObserver(
-      () => {},
-      {sampleRate: 1});
+  const observer = new frame_window.PressureObserver(() => {});
   const iframe_DOMException = frame_window.DOMException;
 
   // await is intentionally not used here. We want to remove the iframe while
   // the returned Promise settles.
-  const observe_promise = observer.observe('cpu');
+  observer.observe('cpu');
   iframe.remove();
 
   // Establish an observer and wait for changes in the main frame. This should
   // keep the test running long enough to catch any crash from the observe()
   // call in the removed iframe's PressureObserver.
   const changes = await new Promise((resolve, reject) => {
-    const observer = new PressureObserver(
-        resolve, {sampleRate: 1});
+    const observer = new PressureObserver(resolve);
     t.add_cleanup(() => observer.disconnect());
     observer.observe('cpu').catch(reject);
+    mockPressureService.setPressureUpdate('cpu', 'critical');
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
   });
-  assert_in_array(changes[0].state, ['nominal', 'fair', 'serious', 'critical'],
-                  'cpu pressure state');
+  assert_equals(changes[0].state, 'critical');
 }, 'Detaching frame while PressureObserver.observe() settles');
 
-promise_test(async t => {
+pressure_test(async (t, mockPressureService) => {
   const iframe = document.createElement('iframe');
   document.body.appendChild(iframe);
   const frame_window = iframe.contentWindow;
   const observer = new frame_window.PressureObserver(() => {
     assert_unreached('The observer callback should not be called');
-  }, {sampleRate: 1});
+  });
 
   await observer.observe('cpu');
+  mockPressureService.setPressureUpdate('cpu', 'critical');
+  mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
 
   iframe.remove();
 
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect.tentative.https.any.js
similarity index 73%
rename from third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect.tentative.https.window.js
rename to third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect.tentative.https.any.js
index c9950f2..1d188fa 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect.tentative.https.any.js
@@ -1,3 +1,7 @@
+// META: script=/resources/test-only-api.js
+// META: script=resources/pressure-helpers.js
+// META: global=window,dedicatedworker,sharedworker
+
 'use strict';
 
 test(t => {
@@ -8,11 +12,11 @@
   observer.disconnect();
 }, 'Call disconnect() directly should not crash');
 
-promise_test(async t => {
+pressure_test(async (t, mockPressureService) => {
   const observer1_changes = [];
   const observer1 = new PressureObserver(change => {
     observer1_changes.push(change);
-  }, {sampleRate: 1.0});
+  });
   t.add_cleanup(() => observer1.disconnect());
   // Ensure that observer1's schema gets registered before observer2 starts.
   await observer1.observe('cpu');
@@ -23,9 +27,11 @@
     const observer2 = new PressureObserver(change => {
       observer2_changes.push(change);
       resolve();
-    }, {sampleRate: 1.0});
+    });
     t.add_cleanup(() => observer2.disconnect());
     observer2.observe('cpu').catch(reject);
+    mockPressureService.setPressureUpdate('cpu', 'critical');
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
   });
 
   assert_equals(
@@ -34,7 +40,5 @@
 
   assert_equals(observer2_changes.length, 1);
   assert_equals(observer2_changes[0].length, 1);
-  assert_in_array(
-      observer2_changes[0][0].state, ['nominal', 'fair', 'serious', 'critical'],
-      'cpu pressure state');
+  assert_equals(observer2_changes[0][0].state, 'critical');
 }, 'Stopped PressureObserver do not receive changes');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect_idempotent.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect_idempotent.tentative.https.any.js
similarity index 69%
rename from third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect_idempotent.tentative.https.window.js
rename to third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect_idempotent.tentative.https.any.js
index 72021fd..2f6421e 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect_idempotent.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect_idempotent.tentative.https.any.js
@@ -1,10 +1,14 @@
+// META: script=/resources/test-only-api.js
+// META: script=resources/pressure-helpers.js
+// META: global=window,dedicatedworker,sharedworker
+
 'use strict';
 
-promise_test(async t => {
+pressure_test(async (t, mockPressureService) => {
   const observer1_changes = [];
   const observer1 = new PressureObserver(changes => {
     observer1_changes.push(changes);
-  }, {sampleRate: 1});
+  });
   t.add_cleanup(() => observer1.disconnect());
   // Ensure that observer1's schema gets registered before observer2 starts.
   const promise = observer1.observe('cpu');
@@ -17,9 +21,11 @@
     const observer2 = new PressureObserver(changes => {
       observer2_changes.push(changes);
       resolve();
-    }, {sampleRate: 1});
+    });
     t.add_cleanup(() => observer2.disconnect());
     observer2.observe('cpu').catch(reject);
+    mockPressureService.setPressureUpdate('cpu', 'critical');
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
   });
 
   assert_equals(
@@ -27,7 +33,5 @@
       'stopped observers should not receive callbacks');
 
   assert_equals(observer2_changes.length, 1);
-  assert_in_array(
-      observer2_changes[0][0].state, ['nominal', 'fair', 'serious', 'critical'],
-      'cpu pressure state');
+  assert_equals(observer2_changes[0][0].state, 'critical');
 }, 'Stopped PressureObserver do not receive changes');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect_immediately.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect_immediately.tentative.https.any.js
similarity index 72%
rename from third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect_immediately.tentative.https.window.js
rename to third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect_immediately.tentative.https.any.js
index 1abe84d5..b96ebd8 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect_immediately.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_disconnect_immediately.tentative.https.any.js
@@ -1,10 +1,14 @@
+// META: script=/resources/test-only-api.js
+// META: script=resources/pressure-helpers.js
+// META: global=window,dedicatedworker,sharedworker
+
 'use strict';
 
-promise_test(async t => {
+pressure_test(async (t, mockPressureService) => {
   const observer1_changes = [];
   const observer1 = new PressureObserver(changes => {
     observer1_changes.push(changes);
-  }, {sampleRate: 1.0});
+  });
   t.add_cleanup(() => observer1.disconnect());
   // Ensure that observer1's schema gets registered before observer2 starts.
   const promise = observer1.observe('cpu');
@@ -16,9 +20,11 @@
     const observer2 = new PressureObserver(changes => {
       observer2_changes.push(changes);
       resolve();
-    }, {sampleRate: 1.0});
+    });
     t.add_cleanup(() => observer2.disconnect());
     observer2.observe('cpu').catch(reject);
+    mockPressureService.setPressureUpdate('cpu', 'critical');
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
   });
 
   assert_equals(
@@ -27,16 +33,14 @@
 
   assert_equals(observer2_changes.length, 1);
   assert_equals(observer2_changes[0].length, 1);
-  assert_in_array(
-      observer2_changes[0][0].state, ['nominal', 'fair', 'serious', 'critical'],
-      'cpu pressure state');
+  assert_equals(observer2_changes[0][0].state, 'critical');
 }, 'Stopped PressureObserver do not receive changes');
 
-promise_test(async t => {
+pressure_test(async (t, mockPressureService) => {
   const observer1_changes = [];
   const observer1 = new PressureObserver(changes => {
     observer1_changes.push(changes);
-  }, {sampleRate: 1});
+  });
   t.add_cleanup(() => observer1.disconnect());
 
   const observer2_changes = [];
@@ -44,12 +48,14 @@
     const observer2 = new PressureObserver(changes => {
       observer2_changes.push(changes);
       resolve();
-    }, {sampleRate: 1});
+    });
     t.add_cleanup(() => observer2.disconnect());
     const promise = observer1.observe('cpu');
     observer2.observe('cpu');
     observer1.disconnect();
     await promise_rejects_dom(t, 'NotSupportedError', promise);
+    mockPressureService.setPressureUpdate('cpu', 'critical');
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
   });
 
   assert_equals(
@@ -57,7 +63,5 @@
       'stopped observers should not receive callbacks');
 
   assert_equals(observer2_changes.length, 1);
-  assert_in_array(
-      observer2_changes[0][0].state, ['nominal', 'fair', 'serious', 'critical'],
-      'cpu pressure state');
+  assert_equals(observer2_changes[0][0].state, 'critical');
 }, 'Removing observer before observe() resolves does not affect other observers');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_duplicate_updates.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_duplicate_updates.tentative.https.any.js
similarity index 97%
rename from third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_duplicate_updates.tentative.https.window.js
rename to third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_duplicate_updates.tentative.https.any.js
index 6318c0e8..b5d7690d 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_duplicate_updates.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_duplicate_updates.tentative.https.any.js
@@ -1,5 +1,6 @@
 // META: script=/resources/test-only-api.js
 // META: script=resources/pressure-helpers.js
+// META: global=window,dedicatedworker,sharedworker
 
 'use strict';
 
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_factors.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_factors.tentative.https.any.js
similarity index 72%
rename from third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_factors.tentative.https.window.js
rename to third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_factors.tentative.https.any.js
index fc27755..7486a70f 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_factors.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_factors.tentative.https.any.js
@@ -1,14 +1,16 @@
 // META: script=/resources/test-only-api.js
 // META: script=resources/pressure-helpers.js
+// META: global=window,dedicatedworker,sharedworker
 
 'use strict';
 
 pressure_test(async (t, mockPressureService) => {
   const changes = await new Promise(resolve => {
-    const observer = new PressureObserver(resolve, {sampleRate: 1.0});
+    const observer = new PressureObserver(resolve);
+    t.add_cleanup(() => observer.disconnect());
     observer.observe('cpu');
     mockPressureService.setPressureUpdate('cpu', 'critical', ['thermal']);
-    mockPressureService.startPlatformCollector(/*sampleRate=*/ 1.0);
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
   });
   assert_true(changes.length === 1);
   assert_equals(changes[0].state, 'critical');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_multiple.tentative.https.any.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_multiple.tentative.https.any.js
new file mode 100644
index 0000000..c8cef5bec
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_multiple.tentative.https.any.js
@@ -0,0 +1,35 @@
+// META: script=/resources/test-only-api.js
+// META: script=resources/pressure-helpers.js
+// META: global=window,dedicatedworker,sharedworker
+
+'use strict';
+
+pressure_test(async (t, mockPressureService) => {
+  const changes1_promise = new Promise((resolve, reject) => {
+    const observer = new PressureObserver(resolve);
+    t.add_cleanup(() => observer.disconnect());
+    observer.observe('cpu').catch(reject);
+  });
+
+  const changes2_promise = new Promise((resolve, reject) => {
+    const observer = new PressureObserver(resolve);
+    t.add_cleanup(() => observer.disconnect());
+    observer.observe('cpu').catch(reject);
+  });
+
+  const changes3_promise = new Promise((resolve, reject) => {
+    const observer = new PressureObserver(resolve);
+    t.add_cleanup(() => observer.disconnect());
+    observer.observe('cpu').catch(reject);
+  });
+
+  mockPressureService.setPressureUpdate('cpu', 'critical');
+  mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
+
+  const [changes1, changes2, changes3] =
+      await Promise.all([changes1_promise, changes2_promise, changes3_promise]);
+
+  for (const changes of [changes1, changes2, changes3]) {
+    assert_equals(changes[0].state, 'critical');
+  }
+}, 'Three PressureObserver instances receive changes');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_multiple.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_multiple.tentative.https.window.js
deleted file mode 100644
index 6015ae1f..0000000
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_multiple.tentative.https.window.js
+++ /dev/null
@@ -1,30 +0,0 @@
-'use strict';
-
-promise_test(async t => {
-  const changes1_promise = new Promise((resolve, reject) => {
-    const observer = new PressureObserver(resolve, {sampleRate: 1.0});
-    t.add_cleanup(() => observer.disconnect());
-    observer.observe('cpu').catch(reject);
-  });
-
-  const changes2_promise = new Promise((resolve, reject) => {
-    const observer = new PressureObserver(resolve, {sampleRate: 1.0});
-    t.add_cleanup(() => observer.disconnect());
-    observer.observe('cpu').catch(reject);
-  });
-
-  const changes3_promise = new Promise((resolve, reject) => {
-    const observer = new PressureObserver(resolve, {sampleRate: 1.0});
-    t.add_cleanup(() => observer.disconnect());
-    observer.observe('cpu').catch(reject);
-  });
-
-  const [changes1, changes2, changes3] =
-      await Promise.all([changes1_promise, changes2_promise, changes3_promise]);
-
-  for (const changes of [changes1, changes2, changes3]) {
-    assert_in_array(
-        changes[0].state, ['nominal', 'fair', 'serious', 'critical'],
-        'cpu pressure state');
-  }
-}, 'Three PressureObserver instances receive changes');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_multiple_across_iframes.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_multiple_across_iframes.tentative.https.window.js
deleted file mode 100644
index 838b9a1..0000000
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_multiple_across_iframes.tentative.https.window.js
+++ /dev/null
@@ -1,40 +0,0 @@
-'use strict';
-
-promise_test(async t => {
-  const changes1_promise = new Promise((resolve, reject) => {
-    const observer = new PressureObserver(resolve, {sampleRate: 1.0});
-    t.add_cleanup(() => observer.disconnect());
-    observer.observe('cpu').catch(reject);
-  });
-
-  // iframe numbers are aligned with observer numbers. The first observer is
-  // in the main frame, so there is no iframe1.
-  const iframe2 = document.createElement('iframe');
-  document.body.appendChild(iframe2);
-
-  const changes2_promise = new Promise((resolve, reject) => {
-    const observer =
-        new iframe2.contentWindow.PressureObserver(resolve, {sampleRate: 1.0});
-    t.add_cleanup(() => observer.disconnect());
-    observer.observe('cpu').catch(reject);
-  });
-
-  const iframe3 = document.createElement('iframe');
-  document.body.appendChild(iframe3);
-
-  const changes3_promise = new Promise((resolve, reject) => {
-    const observer =
-        new iframe3.contentWindow.PressureObserver(resolve, {sampleRate: 1.0});
-    t.add_cleanup(() => observer.disconnect());
-    observer.observe('cpu').catch(reject);
-  });
-
-  const [changes1, changes2, changes3] =
-      await Promise.all([changes1_promise, changes2_promise, changes3_promise]);
-
-  for (const changes of [changes1, changes2, changes3]) {
-    assert_in_array(
-        changes[0].state, ['nominal', 'fair', 'serious', 'critical'],
-        'cpu pressure state');
-  }
-}, 'Three PressureObserver instances, in different iframes, receive changes');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_observe_idempotent.tentative.https.any.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_observe_idempotent.tentative.https.any.js
new file mode 100644
index 0000000..5dc3804b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_observe_idempotent.tentative.https.any.js
@@ -0,0 +1,19 @@
+// META: script=/resources/test-only-api.js
+// META: script=resources/pressure-helpers.js
+// META: global=window,dedicatedworker,sharedworker
+
+'use strict';
+
+pressure_test(async (t, mockPressureService) => {
+  const update = await new Promise((resolve, reject) => {
+    const observer = new PressureObserver(resolve);
+    t.add_cleanup(() => observer.disconnect());
+    observer.observe('cpu').catch(reject);
+    observer.observe('cpu').catch(reject);
+    observer.observe('cpu').catch(reject);
+    mockPressureService.setPressureUpdate('cpu', 'critical');
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
+  });
+
+  assert_equals(update[0].state, 'critical');
+}, 'PressureObserver.observe() is idempotent');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_observe_idempotent.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_observe_idempotent.tentative.https.window.js
deleted file mode 100644
index e60115f..0000000
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_observe_idempotent.tentative.https.window.js
+++ /dev/null
@@ -1,16 +0,0 @@
-'use strict';
-
-promise_test(async t => {
-  const update = await new Promise((resolve, reject) => {
-    const observer = new PressureObserver(resolve, {sampleRate: 1.0});
-    t.add_cleanup(() => observer.disconnect());
-    observer.observe('cpu').catch(reject);
-    observer.observe('cpu').catch(reject);
-    observer.observe('cpu').catch(reject);
-  });
-
-  assert_equals(typeof update[0].state, 'string');
-  assert_in_array(
-      update[0].state, ['nominal', 'fair', 'serious', 'critical'],
-      'cpu pressure state');
-}, 'PressureObserver.observe() is idempotent');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_observe_unobserve_failure.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_observe_unobserve_failure.tentative.https.any.js
similarity index 62%
rename from third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_observe_unobserve_failure.tentative.https.window.js
rename to third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_observe_unobserve_failure.tentative.https.any.js
index c32649da..8eafeb3 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_observe_unobserve_failure.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_observe_unobserve_failure.tentative.https.any.js
@@ -1,15 +1,17 @@
+// META: global=window,dedicatedworker,sharedworker
+
 'use strict';
 
 promise_test(async t => {
-  const observer = new PressureObserver(
-      t.unreached_func('oops should not end up here'), {sampleRate: 1.0});
+  const observer =
+      new PressureObserver(t.unreached_func('oops should not end up here'));
   t.add_cleanup(() => observer.disconnect());
   await promise_rejects_js(t, TypeError, observer.observe('random'));
 }, 'PressureObserver.observe() requires a valid source');
 
 test(t => {
-  const observer = new PressureObserver(
-      t.unreached_func('oops should not end up here'), {sampleRate: 1.0});
+  const observer =
+      new PressureObserver(t.unreached_func('oops should not end up here'));
   t.add_cleanup(() => observer.disconnect());
   assert_throws_js(TypeError, () => {
     observer.unobserve('random');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_options.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_options.tentative.https.any.js
similarity index 93%
rename from third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_options.tentative.https.window.js
rename to third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_options.tentative.https.any.js
index d142ecc..69999819 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_options.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_options.tentative.https.any.js
@@ -1,3 +1,5 @@
+// META: global=window,dedicatedworker,sharedworker
+
 'use strict';
 
 test(t => {
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_privacy_test.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_privacy_test.tentative.https.window.js
index d33f6ef0..113f4bd 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_privacy_test.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_privacy_test.tentative.https.window.js
@@ -5,10 +5,12 @@
 // META: script=/picture-in-picture/resources/picture-in-picture-helpers.js
 // META: script=/resources/testdriver.js
 // META: script=/resources/testdriver-vendor.js
+// META: script=/resources/test-only-api.js
+// META: script=resources/pressure-helpers.js
 
 'use strict';
 
-promise_test(async t => {
+pressure_test(async (t, mockPressureService) => {
   const video = await loadVideo();
   document.body.appendChild(video);
   const pipWindow = await requestPictureInPictureWithTrustedClick(video);
@@ -38,10 +40,12 @@
       video.remove();
     });
     observer.observe('cpu');
+    mockPressureService.setPressureUpdate('cpu', 'critical');
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
   });
 }, 'Observer should receive PressureRecord if associated document is the initiator of active Picture-in-Picture session');
 
-promise_test(async t => {
+pressure_test(async (t, mockPressureService) => {
   await setMediaPermission();
   const stream =
       await navigator.mediaDevices.getUserMedia({video: true, audio: true});
@@ -67,5 +71,7 @@
       stream.getTracks().forEach(track => track.stop());
     });
     observer.observe('cpu');
+    mockPressureService.setPressureUpdate('cpu', 'critical');
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
   });
 }, 'Observer should receive PressureRecord if browsing context is capturing');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_same_origin_focus_control.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_same_origin_focus_control.tentative.https.window.js
index 746f119f..7df0be5 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_same_origin_focus_control.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_same_origin_focus_control.tentative.https.window.js
@@ -1,21 +1,27 @@
+// META: timeout=long
+// META: script=/resources/test-only-api.js
+// META: script=resources/pressure-helpers.js
+
 'use strict';
 
-promise_test(async t => {
+pressure_test(async (t, mockPressureService) => {
   const iframe = document.createElement('iframe');
   document.body.appendChild(iframe);
   iframe.contentWindow.focus();
 
   await new Promise(resolve => {
     const observer = new PressureObserver(resolve);
-    t.add_cleanup(async () => {
+    t.add_cleanup(() => {
       observer.disconnect();
       iframe.remove();
     });
     observer.observe('cpu');
+    mockPressureService.setPressureUpdate('cpu', 'critical');
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
   });
 }, 'Observer in main frame should receive PressureRecord when focused on same-origin iframe');
 
-promise_test(async t => {
+pressure_test(async (t, mockPressureService) => {
   const iframe = document.createElement('iframe');
   document.body.appendChild(iframe);
   // Focus on the main frame to make the iframe lose focus, so that
@@ -31,5 +37,7 @@
       iframe.remove();
     });
     observer.observe('cpu');
+    mockPressureService.setPressureUpdate('cpu', 'critical');
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
   });
 }, 'Observer in iframe should receive PressureRecord when focused on same-origin main frame');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_supported_sources.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_supported_sources.tentative.https.any.js
similarity index 92%
rename from third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_supported_sources.tentative.https.window.js
rename to third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_supported_sources.tentative.https.any.js
index 2a69e73..63f2666c 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_supported_sources.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_supported_sources.tentative.https.any.js
@@ -1,3 +1,5 @@
+// META: global=window,dedicatedworker,sharedworker
+
 'use strict';
 
 test(() => {
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_take_records.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_take_records.tentative.https.any.js
similarity index 67%
rename from third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_take_records.tentative.https.window.js
rename to third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_take_records.tentative.https.any.js
index d294a7e..d93c9b5 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_take_records.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_take_records.tentative.https.any.js
@@ -1,28 +1,28 @@
 // META: script=/resources/test-only-api.js
 // META: script=resources/pressure-helpers.js
+// META: global=window,dedicatedworker,sharedworker
 
 'use strict';
 
 test(t => {
   const observer = new PressureObserver(
-      t.unreached_func('This callback should not have been called.'),
-      {sampleRate: 1.0});
+      t.unreached_func('This callback should not have been called.'));
 
   const records = observer.takeRecords();
   assert_equals(records.length, 0, 'No record before observe');
 }, 'Calling takeRecords() before observe()');
 
-promise_test(async t => {
+pressure_test(async (t, mockPressureService) => {
   let observer;
   const changes = await new Promise(resolve => {
-    observer = new PressureObserver(resolve, {sampleRate: 1.0});
+    observer = new PressureObserver(resolve);
     t.add_cleanup(() => observer.disconnect());
 
     observer.observe('cpu');
+    mockPressureService.setPressureUpdate('cpu', 'critical');
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
   });
-  assert_in_array(
-      changes[0].state, ['nominal', 'fair', 'serious', 'critical'],
-      'cpu presure state');
+  assert_equals(changes[0].state, 'critical');
 
   const records = observer.takeRecords();
   assert_equals(records.length, 0, 'No record available');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_timestamp.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_timestamp.tentative.https.any.js
similarity index 97%
rename from third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_timestamp.tentative.https.window.js
rename to third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_timestamp.tentative.https.any.js
index aae56180..f283caa6 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_timestamp.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_timestamp.tentative.https.any.js
@@ -1,5 +1,6 @@
 // META: script=/resources/test-only-api.js
 // META: script=resources/pressure-helpers.js
+// META: global=window,dedicatedworker,sharedworker
 
 'use strict';
 
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_update_toJSON.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_update_toJSON.tentative.https.any.js
similarity index 84%
rename from third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_update_toJSON.tentative.https.window.js
rename to third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_update_toJSON.tentative.https.any.js
index f21cd464..c1cd240 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_update_toJSON.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_update_toJSON.tentative.https.any.js
@@ -1,12 +1,13 @@
 // META: script=/resources/test-only-api.js
 // META: script=resources/pressure-helpers.js
+// META: global=window,dedicatedworker,sharedworker
 
 pressure_test(async (t, mockPressureService) => {
   const changes = await new Promise(resolve => {
     const observer = new PressureObserver(resolve);
     observer.observe('cpu');
     mockPressureService.setPressureUpdate('cpu', 'critical', ['thermal']);
-    mockPressureService.startPlatformCollector(/*sampleRate=*/ 1.0);
+    mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0);
   });
   assert_true(changes.length === 1);
   const json = changes[0].toJSON();
@@ -15,4 +16,3 @@
   assert_equals(json.factors[0], 'thermal');
   assert_equals(typeof json.time, 'number');
 }, 'Basic functionality test');
-
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/resources/observer-in-dedicated-worker.js b/third_party/blink/web_tests/external/wpt/compute-pressure/resources/observer-in-dedicated-worker.js
deleted file mode 100644
index a30edd0..0000000
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/resources/observer-in-dedicated-worker.js
+++ /dev/null
@@ -1,10 +0,0 @@
-'use strict';
-
-function pressureCallback(update) {
-  postMessage(update[0].toJSON());
-};
-
-const observerWorker =
-    new PressureObserver(pressureCallback, {sampleRate: 0.5});
-
-observerWorker.observe('cpu');
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/resources/observer-in-shared-worker.js b/third_party/blink/web_tests/external/wpt/compute-pressure/resources/observer-in-shared-worker.js
deleted file mode 100644
index f69eadaa..0000000
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/resources/observer-in-shared-worker.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict';
-
-onconnect = function(e) {
-  const port = e.ports[0];  // get the port
-  let started = false;
-
-  port.start();  // Open the port connection to enable two-way communication
-
-  let observerWorker =
-      new PressureObserver(pressureCallback, {sampleRate: 0.5});
-
-  port.onmessage = function(e) {
-    if (started === false)
-      observerWorker.observe('cpu');
-    started = true;
-  };
-
-  function pressureCallback(update) {
-    port.postMessage(update[0].toJSON());
-  };
-}
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/resources/support-iframe.html b/third_party/blink/web_tests/external/wpt/compute-pressure/resources/support-iframe.html
index 57e18b7..6b2b309 100644
--- a/third_party/blink/web_tests/external/wpt/compute-pressure/resources/support-iframe.html
+++ b/third_party/blink/web_tests/external/wpt/compute-pressure/resources/support-iframe.html
@@ -11,7 +11,7 @@
             resolve('success');
         });
         observer.observe('cpu');
-        window.setTimeout(() => { reject('timeout'); }, 2000);
+        window.setTimeout(() => { reject('timeout'); }, 1000);
     });
   } else {
     return Promise.reject(`unknown command "${e.data.command}"`);
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-non-oof-inherit.html b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-non-oof-inherit.html
new file mode 100644
index 0000000..75f98a1e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-non-oof-inherit.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<title>Tests that anchor functions can be inherited from in-flow elements</title>
+<link rel="help" href="https://drafts4.csswg.org/css-anchor-position-1/">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1382151">
+<link rel="author" href="mailto:xiaochengh@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<script src="support/test-common.js"></script>
+
+<style>
+.cb {
+  width: 200px;
+  height: 200px;
+  transform: scale(1);
+}
+
+.anchor {
+  width: 100px;
+  height: 100px;
+  top: 50px;
+  left: 50px;
+  position: relative;
+  background: red;
+  anchor-name: --a;
+}
+
+.target {
+  position: absolute;
+  background: green;
+  top: inherit;
+  bottom: inherit;
+  left: inherit;
+  right: inherit;
+  width: inherit;
+  min-width: inherit;
+  max-width: inherit;
+  height: inherit;
+  min-height: inherit;
+  max-height: inherit;
+}
+
+.inset-parent {
+  top: anchor(--a top);
+  bottom: anchor(--a bottom);
+  left: anchor(--a left);
+  right: anchor(--a right);
+}
+
+.size-parent {
+  width: anchor-size(--a width);
+  height: anchor-size(--a height);
+  top: 50px;
+  left: 50px;
+}
+
+.min-size-parent {
+  min-width: anchor-size(--a width);
+  min-height: anchor-size(--a height);
+  top: 50px;
+  left: 50px;
+  bottom: 200px;
+  right: 200px;
+}
+
+.max-size-parent {
+  max-width: anchor-size(--a width);
+  max-height: anchor-size(--a height);
+  top: 50px;
+  left: 50px;
+  bottom: 0px;
+  right: 0px;
+}
+
+</style>
+
+<body onload="checkLayoutForAnchorPos('.target')">
+
+<p>In each test case, we should see a filled green square with no red.</p>
+
+<div class=cb>
+  <div class="anchor"></div>
+  <div class="inset-parent">
+    <div class="target"
+         data-offset-x=50 data-offset-y=50
+         data-expected-width=100 data-expected-height=100></div>
+  </div>
+</div>
+
+<div class=cb>
+  <div class="anchor"></div>
+  <div class="size-parent">
+    <div class="target"
+         data-offset-x=50 data-offset-y=50
+         data-expected-width=100 data-expected-height=100></div>
+  </div>
+</div>
+
+<div class=cb>
+  <div class="anchor"></div>
+  <div class="min-size-parent">
+    <div class="target"
+         data-offset-x=50 data-offset-y=50
+         data-expected-width=100 data-expected-height=100></div>
+  </div>
+</div>
+
+<div class=cb>
+  <div class="anchor"></div>
+  <div class="max-size-parent">
+    <div class="target"
+         data-offset-x=50 data-offset-y=50
+         data-expected-width=100 data-expected-height=100></div>
+  </div>
+</div>
+
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/independent-formatting-context-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/independent-formatting-context-ref.html
index 79b90c340..fe842b28 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/independent-formatting-context-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/independent-formatting-context-ref.html
@@ -5,12 +5,13 @@
 -->
 <html><head>
   <meta charset="utf-8">
-  <title>Test: subgrid disabled if grid item establishes independent formatting context</title>
+  <title>Reference: subgrid disabled if grid item establishes independent formatting context</title>
   <link rel="author" title="Matt Woodrow" href="https://bugs.webkit.org/show_bug.cgi?id=237692">
   <link rel="help" href="https://drafts.csswg.org/css-grid-2/#subgrid-listing">
   <style>
+
 html,body {
-  color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+  font:16px/1 monospace; padding:0; margin:0; line-height: 0;
 }
 
 .grid {
@@ -31,5 +32,22 @@
 <div class="grid">
 </div>
 
+<div class="grid">
+</div>
+
+<div class="grid">
+</div>
+
+<div class="grid">
+</div>
+
+<div class="grid">
+</div>
+
+<div class="grid">
+</div>
+
+<div class="grid">
+</div>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/independent-formatting-context.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/independent-formatting-context.html
index 888b23c..5a76ac2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/independent-formatting-context.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/independent-formatting-context.html
@@ -10,8 +10,9 @@
   <link rel="help" href="https://drafts.csswg.org/css-grid-2/#subgrid-listing">
   <link rel="match" href="independent-formatting-context-ref.html">
   <style>
+
 html,body {
-  color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+  font:16px/1 monospace; padding:0; margin:0; line-height: 0;
 }
 
 .grid {
@@ -32,19 +33,20 @@
 }
 
 .first {
-  background-color: green;
   grid-row: 1;
+  background-color: green;
 }
 
 .second {
-  background-color: red;
   grid-row: 2;
+  background-color: green;
 }
 
   </style>
 </head>
 <body>
-
+<!-- The subgrid's style attribute establishes an independent formatting context
+      and makes them no longer eligible as subgrids.-->
 <div class="grid">
   <div class="subgrid" style="position:absolute">
     <div class="first"></div>
@@ -57,5 +59,43 @@
   </div>
 </div>
 
+<div class="grid">
+  <div class="subgrid" style="contain: paint">
+    <div class="first"></div>
+  </div>
+</div>
+
+<div class="grid">
+  <div class="subgrid" style="contain: strict">
+    <div class="first"></div>
+  </div>
+</div>
+
+<div class="grid">
+  <div class="subgrid" style="contain: content">
+    <div class="first"></div>
+  </div>
+</div>
+
+<!-- Only layout and paint containment establish an independent formatting
+      context. These tests validate that other types of containment maintain
+      subgrid layout.-->
+<div class="grid">
+  <div class="subgrid" style="contain: none">
+    <div class="second"></div>
+  </div>
+</div>
+
+<div class="grid">
+  <div class="subgrid" style="contain: size">
+    <div class="second"></div>
+  </div>
+</div>
+
+<div class="grid">
+  <div class="subgrid" style="contain: style">
+    <div class="second"></div>
+  </div>
+</div>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/text-box-trim/text-box-trim-valid.html b/third_party/blink/web_tests/external/wpt/css/css-inline/text-box-trim/text-box-trim-valid.html
index 1ce4ceb1..61622774 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/text-box-trim/text-box-trim-valid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/text-box-trim/text-box-trim-valid.html
@@ -5,7 +5,7 @@
 <script src="/css/support/parsing-testcommon.js"></script>
 
 <script>
-test_valid_value('text-box-trim', 'normal');
+test_valid_value('text-box-trim', 'none');
 test_valid_value('text-box-trim', 'start');
 test_valid_value('text-box-trim', 'end');
 test_valid_value('text-box-trim', 'both');
diff --git a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-screen-size.https.html.ini b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-screen-size.https.html.ini
new file mode 100644
index 0000000..8c28bf66
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-screen-size.https.html.ini
@@ -0,0 +1,10 @@
+[element-request-fullscreen-screen-size.https.html]
+  expected:
+    if product == "chrome": TIMEOUT
+  [Screen size is unchanged during element fullscreen]
+    expected:
+      if product == "chrome": TIMEOUT
+
+  [Screen size is unchanged during tab-capture element fullscreen]
+    expected:
+      if product == "chrome": NOTRUN
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/mock-pressure-service.js b/third_party/blink/web_tests/external/wpt/resources/chromium/mock-pressure-service.js
index e41464e..21811ed 100644
--- a/third_party/blink/web_tests/external/wpt/resources/chromium/mock-pressure-service.js
+++ b/third_party/blink/web_tests/external/wpt/resources/chromium/mock-pressure-service.js
@@ -9,10 +9,6 @@
     this.interceptor_.oninterfacerequest = e => {
       this.receiver_.$.bindHandle(e.handle);
     };
-    this.receiver_.onConnectionError.addListener(() => {
-      this.stopPlatformCollector();
-      this.observer_ = null;
-    });
     this.reset();
     this.mojomSourceType_ = new Map([['cpu', PressureSource.kCpu]]);
     this.mojomStateType_ = new Map([
@@ -41,7 +37,7 @@
   }
 
   reset() {
-    this.observer_ = null;
+    this.observers_ = [];
     this.pressureUpdate_ = null;
     this.pressureServiceReadingTimerId_ = null;
     this.pressureStatus_ = PressureStatus.kOk;
@@ -49,7 +45,7 @@
   }
 
   async addClient(observer, source) {
-    if (this.observer_ !== null)
+    if (this.observers_.indexOf(observer) >= 0)
       throw new Error('addClient() has already been called');
 
     // TODO(crbug.com/1342184): Consider other sources.
@@ -57,11 +53,11 @@
     if (source !== PressureSource.kCpu)
       throw new Error('Call addClient() with a wrong PressureSource');
 
-    this.observer_ = observer;
-    this.observer_.onConnectionError.addListener(() => {
-      this.stopPlatformCollector();
-      this.observer_ = null;
+    observer.onConnectionError.addListener(() => {
+      // Remove this observer from observer array.
+      this.observers_.splice(this.observers_.indexOf(observer), 1);
     });
+    this.observers_.push(observer);
 
     return {status: this.pressureStatus_};
   }
@@ -89,20 +85,21 @@
     const epochDeltaInMs = unixEpoch - windowsEpoch;
 
     const timeout = (1 / sampleRate) * 1000;
-    this.pressureServiceReadingTimerId_ = window.setInterval(() => {
-      if (this.pressureUpdate_ === null || this.observer_ === null)
+    this.pressureServiceReadingTimerId_ = self.setInterval(() => {
+      if (this.pressureUpdate_ === null || this.observers_.length === 0)
         return;
       this.pressureUpdate_.timestamp = {
         internalValue: BigInt((new Date().getTime() + epochDeltaInMs) * 1000)
       };
-      this.observer_.onPressureUpdated(this.pressureUpdate_);
+      for (let observer of this.observers_)
+        observer.onPressureUpdated(this.pressureUpdate_);
       this.updatesDelivered_++;
     }, timeout);
   }
 
   stopPlatformCollector() {
     if (this.pressureServiceReadingTimerId_ != null) {
-      window.clearInterval(this.pressureServiceReadingTimerId_);
+      self.clearInterval(this.pressureServiceReadingTimerId_);
       this.pressureServiceReadingTimerId_ = null;
     }
     this.updatesDelivered_ = 0;
diff --git a/third_party/blink/web_tests/external/wpt/screen-orientation/orientation-reading.html b/third_party/blink/web_tests/external/wpt/screen-orientation/orientation-reading.html
index 0bebb67..90bbb8071 100644
--- a/third_party/blink/web_tests/external/wpt/screen-orientation/orientation-reading.html
+++ b/third_party/blink/web_tests/external/wpt/screen-orientation/orientation-reading.html
@@ -6,110 +6,91 @@
 <script src="/resources/testdriver.js"></script>
 <script src="/resources/testdriver-vendor.js"></script>
 <script type="module">
-
-import { makeCleanup, getOppositeOrientation } from "./resources/orientation-utils.js";
+"use strict";
+import {
+  makeCleanup,
+  getOppositeOrientation,
+} from "./resources/orientation-utils.js";
 
 test(() => {
-  assert_true("type" in screen.orientation);
-  assert_true("angle" in screen.orientation);
-}, "Test screen.orientation properties");
+  assert_true("type" in screen.orientation, ".type must be present");
+  assert_true("angle" in screen.orientation, ".angle must be present");
+}, "screen.orientation attributes are present");
 
-test(() => {
-  const type = screen.orientation.type;
-  const angle = screen.orientation.angle;
-
-  if (screen.width > screen.height) {
-    assert_true(type == "landscape-primary" || type == "landscape-secondary");
-  } else if (screen.width < screen.height) {
-    assert_true(type == "portrait-primary" || type == "portrait-secondary");
+async function testExpectedOrientationAngles(expectedAngles) {
+  for (const [orientation, expectedAngle] of Object.entries(expectedAngles)) {
+    try {
+      if (screen.orientation.type !== orientation) {
+        await screen.orientation.lock(orientation);
+      }
+      assert_equals(
+        screen.orientation.angle,
+        expectedAngle,
+        `Orientation angle for '${orientation}' must be ${expectedAngle} degrees`
+      );
+    } catch (err) {
+      // implementation might not support locking to this orientation
+    }
   }
+}
 
-  assert_true(angle == 0 || angle == 90 || angle == 180 || angle == 270);
-}, "Test screen.orientation default values.");
-
-promise_test(async t => {
+promise_test(async (t) => {
   t.add_cleanup(makeCleanup());
   await test_driver.bless("request full screen");
   await document.documentElement.requestFullscreen();
-  try {
-    await screen.orientation.lock("portrait-primary");
-  } catch (err) {
-    // implementation might not support locking to portrait-primary
-    return;
-  }
-  const orientations =
-    screen.orientation.angle === 0
-      ? {
-          secondaryOrientation1: "portrait-secondary",
-          primaryOrientation2: "landscape-primary",
-          secondaryOrientation2: "landscape-secondary",
-        }
-      : {
-          secondaryOrientation1: "landscape-secondary",
-          primaryOrientation2: "portrait-primary",
-          secondaryOrientation2: "portrait-secondary",
-        };
-  try {
-    await screen.orientation.lock(orientations.secondaryOrientation1);
-  } catch (err) {
-    // implementation might not support locking to this orientation
-    return;
-  }
-  assert_equals(
-    screen.orientation.angle,
-    180,
-    "Secondary orientation 1 angle must be 180"
-  );
-  try {
-    await screen.orientation.lock(orientations.primaryOrientation2);
-  } catch (err) {
-    // implementation might not support locking to this orientation
-    return;
-  }
-  assert_true(
-    screen.orientation.angle == 90 || screen.orientation.angle == 270,
-    "Primary orientation 2 angle must be either 90 or 270"
-  );
-  const primaryOrientation2Angle = screen.orientation.angle;
-  const secondaryOrientation2Angle = primaryOrientation2Angle === 90 ? 270 : 90;
-  try {
-    await screen.orientation.lock(orientations.secondaryOrientation2);
-  } catch (err) {
-    // implementation might not support locking to this orientation
-    return;
-  }
-  assert_equals(
-    screen.orientation.angle,
-    secondaryOrientation2Angle,
-    "Secondary orientation 2 angle must be the opposite angle to primary orientation 2"
-  );
-  screen.orientation.unlock();
-}, "Test the orientations and associated angles");
+
+  const expectedAnglesPortrait = {
+    "portrait-primary": 0,
+    "landscape-primary": 90,
+    "portrait-secondary": 180,
+    "landscape-secondary": 270,
+  };
+
+  await testExpectedOrientationAngles(expectedAnglesPortrait);
+}, "Test the orientations and associated angles when the natural orientation is 'portrait'");
+
+promise_test(async (t) => {
+  t.add_cleanup(makeCleanup());
+  await test_driver.bless("request full screen");
+  await document.documentElement.requestFullscreen();
+
+  const expectedAnglesLandscape = {
+    "landscape-primary": 0,
+    "portrait-primary": 90,
+    "landscape-secondary": 180,
+    "portrait-secondary": 270,
+  };
+
+  await testExpectedOrientationAngles(expectedAnglesLandscape);
+}, "Test the orientations and associated angles when the natural orientation is 'landscape'");
 
 test(() => {
-  const type = screen.orientation.type;
-  const angle = screen.orientation.angle;
+  const { angle, type } = screen.orientation;
 
-  try {
-    screen.orientation.type = "foo";
-  } catch (err) {
-    // implementation might throw an exception due to readonly
-  }
-  try {
-    screen.orientation.angle = 42;
-  } catch (err) {
-    // implementation might throw an exception due to readonly
-  }
+  assert_throws_js(
+    TypeError,
+    () => {
+      screen.orientation.type = "foo";
+    },
+    "throws when setting ScreenOrientation.type to a string in strict mode"
+  );
+  assert_throws_js(
+    TypeError,
+    () => {
+      screen.orientation.angle = 42;
+    },
+    "throws when setting ScreenOrientation.angle to a number in strict mode"
+  );
 
   assert_equals(screen.orientation.type, type);
   assert_equals(screen.orientation.angle, angle);
-}, "Test that screen.orientation properties are not writable");
+}, "Test that ScreenOrientation properties are not writable");
 
 test(() => {
   assert_equals(screen.orientation, screen.orientation);
-}, "Test that screen.orientation is always the same object");
+}, "Test that ScreenOrientation is always the same object");
 
-promise_test(async t => {
+promise_test(async (t) => {
   t.add_cleanup(makeCleanup());
   await test_driver.bless("request full screen");
   await document.documentElement.requestFullscreen();
@@ -121,10 +102,18 @@
   // change event is fired before resolving promise by lock.
   const event = await Promise.race([
     orientationWatcher.wait_for("change"),
-    screen.orientation.lock(newOrientationType)
+    screen.orientation.lock(newOrientationType),
   ]);
   assert_true(event instanceof Event, "expected event");
-  assert_not_equals(screen.orientation.type, initialType, "type should have changed");
-  assert_not_equals(screen.orientation.angle, initialAngle, "angle should have changed");
-}, "Test that screen.orientation values change if the orientation changes");
+  assert_not_equals(
+    screen.orientation.type,
+    initialType,
+    ".type must change"
+  );
+  assert_not_equals(
+    screen.orientation.angle,
+    initialAngle,
+    ".angle must change"
+  );
+}, "Test that ScreenOrientation's attribute values change after 'change' event fires");
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/screen-orientation/orientation-reading.html.ini b/third_party/blink/web_tests/external/wpt/screen-orientation/orientation-reading.html.ini
index a84e655..939808a8 100644
--- a/third_party/blink/web_tests/external/wpt/screen-orientation/orientation-reading.html.ini
+++ b/third_party/blink/web_tests/external/wpt/screen-orientation/orientation-reading.html.ini
@@ -1,7 +1,19 @@
 [orientation-reading.html]
   expected: TIMEOUT
+  [Test that ScreenOrientation's attribute values change after 'change' event fires]
+    expected:
+      if product == "chrome": NOTRUN
+
   [Test that screen.orientation values change if the orientation changes]
     expected: NOTRUN
 
   [Test the orientations and associated angles]
     expected: TIMEOUT
+
+  [Test the orientations and associated angles when the natural orientation is 'landscape']
+    expected:
+      if product == "chrome": NOTRUN
+
+  [Test the orientations and associated angles when the natural orientation is 'portrait']
+    expected:
+      if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/secure-payment-confirmation/authentication-disallowed-when-hidden.https-expected.txt b/third_party/blink/web_tests/external/wpt/secure-payment-confirmation/authentication-disallowed-when-hidden.https-expected.txt
new file mode 100644
index 0000000..658ad4f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/secure-payment-confirmation/authentication-disallowed-when-hidden.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL SPC authentication cannot be triggered from a hidden context promise_test: Unhandled rejection with value: object "Error: set_spc_transaction_mode() is not implemented by testdriver-vendor.js"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/secure-payment-confirmation/authentication-disallowed-when-hidden.https.html b/third_party/blink/web_tests/external/wpt/secure-payment-confirmation/authentication-disallowed-when-hidden.https.html
new file mode 100644
index 0000000..1c01fa0
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/secure-payment-confirmation/authentication-disallowed-when-hidden.https.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test for the 'secure-payment-confirmation' payment method authentication - accepted case</title>
+<link rel="help" href="https://w3c.github.io/secure-payment-confirmation#sctn-authentication">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<!-- For minimize() -->
+<script src="/page-visibility/resources/window_state_context.js"></script>
+<script src="utils.sub.js"></script>
+<script>
+'use strict';
+
+promise_test(async t => {
+  const {minimize, restore} = window_state_context(t);
+
+  const authenticator = await window.test_driver.add_virtual_authenticator(
+      AUTHENTICATOR_OPTS);
+  t.add_cleanup(() => {
+    return window.test_driver.remove_virtual_authenticator(authenticator);
+  });
+
+  await window.test_driver.set_spc_transaction_mode("autoAccept");
+  t.add_cleanup(() => {
+    return window.test_driver.set_spc_transaction_mode("none");
+  });
+
+  const credential = await createCredential();
+
+  const challenge = 'server challenge';
+  const payeeOrigin = 'https://merchant.com';
+  const displayName = 'Troycard ***1234';
+  const request = new PaymentRequest([{
+    supportedMethods: 'secure-payment-confirmation',
+    data: {
+      credentialIds: [credential.rawId],
+      challenge: Uint8Array.from(challenge, c => c.charCodeAt(0)),
+      payeeOrigin,
+      rpId: window.location.hostname,
+      timeout: 60000,
+      instrument: {
+        displayName,
+        icon: ICON_URL,
+      },
+    }
+  }], PAYMENT_DETAILS);
+
+  // Before we trigger the Payment Request, minimize the window. This should
+  // cause the show() call to be rejected.
+  await minimize();
+  assert_equals(document.hidden, true);
+
+  await test_driver.bless('user activation');
+  return promise_rejects_dom(t, "AbortError", request.show());
+}, 'SPC authentication cannot be triggered from a hidden context');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/secure-payment-confirmation/authentication-disallowed-when-hidden.https.html.ini b/third_party/blink/web_tests/external/wpt/secure-payment-confirmation/authentication-disallowed-when-hidden.https.html.ini
new file mode 100644
index 0000000..c86ff86
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/secure-payment-confirmation/authentication-disallowed-when-hidden.https.html.ini
@@ -0,0 +1,4 @@
+[authentication-disallowed-when-hidden.https.html]
+  [SPC authentication cannot be triggered from a hidden context]
+    expected:
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt
index 33373fd7..2d68d44 100644
--- a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt
+++ b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt
@@ -334,7 +334,7 @@
 text-align: start
 text-align-last: auto
 text-anchor: start
-text-box-trim: normal
+text-box-trim: none
 text-decoration: none solid rgb(0, 0, 0)
 text-decoration-color: rgb(0, 0, 0)
 text-decoration-line: none
diff --git a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
index 96937e81..85e992c 100644
--- a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
+++ b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
@@ -334,7 +334,7 @@
 text-align: start
 text-align-last: auto
 text-anchor: start
-text-box-trim: normal
+text-box-trim: none
 text-decoration: none solid rgb(0, 0, 0)
 text-decoration-color: rgb(0, 0, 0)
 text-decoration-line: none
diff --git a/third_party/blink/web_tests/fast/overflow/transformed-frame-scrollIntoView-expected.txt b/third_party/blink/web_tests/fast/overflow/transformed-frame-scrollIntoView-expected.txt
index b513188..6e4a71f 100644
--- a/third_party/blink/web_tests/fast/overflow/transformed-frame-scrollIntoView-expected.txt
+++ b/third_party/blink/web_tests/fast/overflow/transformed-frame-scrollIntoView-expected.txt
@@ -4,7 +4,7 @@
   LayoutNGBlockFlow {HTML} at (0,0) size 800x2016
     LayoutNGBlockFlow {BODY} at (8,8) size 784x2000
       LayoutNGBlockFlow {DIV} at (0,0) size 784x2000
-layer at (0,0) hasTransform
+layer at (0,200) hasTransform
   LayoutIFrame (positioned) {IFRAME} at (0,400) size 300x200
     layer at (0,0) scrollY 50.00 scrollHeight 1016
       LayoutNGView at (0,0) size 300x200
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/select/menulist-update-text-popup-expected.txt b/third_party/blink/web_tests/platform/linux/fast/forms/select/menulist-update-text-popup-expected.txt
index 7c95090..8a8bd32 100644
--- a/third_party/blink/web_tests/platform/linux/fast/forms/select/menulist-update-text-popup-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/select/menulist-update-text-popup-expected.txt
@@ -4,11 +4,11 @@
 A
 B
 C
-layer at (0,0)
+layer at (8,50)
   LayoutNGBlockFlow (positioned) {DIV} at (8,50) size 31x20
     LayoutNGFlexibleBox {SELECT} at (0,0) size 31x20 [bgcolor=#EFEFEF] [border: (1px solid #767676)]
     LayoutText {#text} at (0,0) size 0x0
-layer at (5,1)
+layer at (13,51)
   LayoutNGBlockFlow {DIV} at (5,1) size 9x18
     LayoutText {#text} at (0,1) size 9x16
       text run at (0,1) width 9: "C"
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/select/menulist-update-text-popup-expected.txt b/third_party/blink/web_tests/platform/mac/fast/forms/select/menulist-update-text-popup-expected.txt
index a6c9aed..5c088d3 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/select/menulist-update-text-popup-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/select/menulist-update-text-popup-expected.txt
@@ -4,11 +4,11 @@
 A
 B
 C
-layer at (0,0)
+layer at (8,50)
   LayoutNGBlockFlow (positioned) {DIV} at (8,50) size 32x19
     LayoutNGFlexibleBox {SELECT} at (0,0) size 32x19 [bgcolor=#FFFFFF] [border: (1px solid #767676)]
     LayoutText {#text} at (0,0) size 0x0
-layer at (5,1)
+layer at (13,51)
   LayoutNGBlockFlow {DIV} at (5,1) size 10x17
     LayoutText {#text} at (0,1) size 10x15
       text run at (0,1) width 10: "C"
diff --git a/third_party/blink/web_tests/platform/win/fast/forms/select/menulist-update-text-popup-expected.txt b/third_party/blink/web_tests/platform/win/fast/forms/select/menulist-update-text-popup-expected.txt
index c771116c..e29209d 100644
--- a/third_party/blink/web_tests/platform/win/fast/forms/select/menulist-update-text-popup-expected.txt
+++ b/third_party/blink/web_tests/platform/win/fast/forms/select/menulist-update-text-popup-expected.txt
@@ -4,11 +4,11 @@
 A
 B
 C
-layer at (0,0)
+layer at (8,50)
   LayoutNGBlockFlow (positioned) {DIV} at (8,50) size 33x20
     LayoutNGFlexibleBox {SELECT} at (0,0) size 33x20 [bgcolor=#FFFFFF] [border: (1px solid #767676)]
     LayoutText {#text} at (0,0) size 0x0
-layer at (5,1)
+layer at (13,51)
   LayoutNGBlockFlow {DIV} at (5,1) size 9x18
     LayoutText {#text} at (0,1) size 9x16
       text run at (0,1) width 9: "C"
diff --git a/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt b/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt
index 2b22983..5c80559 100644
--- a/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt
+++ b/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt
@@ -334,7 +334,7 @@
 text-align: start
 text-align-last: auto
 text-anchor: start
-text-box-trim: normal
+text-box-trim: none
 text-decoration: none solid rgb(0, 0, 0)
 text-decoration-color: rgb(0, 0, 0)
 text-decoration-line: none
diff --git a/third_party/blink/web_tests/wpt_internal/compute-pressure/losing-focus-suspends-data-delivery.https.window.js b/third_party/blink/web_tests/wpt_internal/compute-pressure/losing-focus-suspends-data-delivery.https.window.js
index fadb38c..69aaf83 100644
--- a/third_party/blink/web_tests/wpt_internal/compute-pressure/losing-focus-suspends-data-delivery.https.window.js
+++ b/third_party/blink/web_tests/wpt_internal/compute-pressure/losing-focus-suspends-data-delivery.https.window.js
@@ -23,7 +23,7 @@
 
   window.internals.setFocused(false);
   mockPressureService.setPressureUpdate('cpu', 'nominal');
-  await new Promise(resolve => t.step_timeout(resolve, 2000));
+  await new Promise(resolve => t.step_timeout(resolve, 1000));
   assert_equals(observerChanges.length, 1);
 
   window.internals.setFocused(true);
diff --git a/third_party/closure_compiler/externs/file_manager_private.js b/third_party/closure_compiler/externs/file_manager_private.js
index 17720a9f..371083c 100644
--- a/third_party/closure_compiler/externs/file_manager_private.js
+++ b/third_party/closure_compiler/externs/file_manager_private.js
@@ -435,6 +435,22 @@
 };
 
 /**
+ * @enum {string}
+ */
+chrome.fileManagerPrivate.BulkPinStage = {
+  STOPPED: 'stopped',
+  PAUSED: 'paused',
+  GETTING_FREE_SPACE: 'getting_free_space',
+  LISTING_FILES: 'listing_files',
+  SYNCING: 'syncing',
+  SUCCESS: 'success',
+  CANNOT_GET_FREE_SPACE: 'cannot_get_free_space',
+  CANNOT_LIST_FILES: 'cannot_list_files',
+  NOT_ENOUGH_SPACE: 'not_enough_space',
+  CANNOT_ENABLE_DOCS_OFFLINE: 'cannot_enable_docs_offline',
+};
+
+/**
  * @typedef {{
  *   appId: string,
  *   taskType: string,
@@ -919,6 +935,18 @@
 chrome.fileManagerPrivate.ParsedTrashInfoFile;
 
 /**
+ * @typedef {{
+ *   stage: !chrome.fileManagerPrivate.BulkPinStage,
+ *   freeSpaceBytes: number,
+ *   requiredSpaceBytes: number,
+ *   bytesToPin: number,
+ *   pinnedBytes: number,
+ *   filesToPin: number
+ * }}
+ */
+chrome.fileManagerPrivate.BulkPinProgress;
+
+/**
  * Cancels file selection.
  */
 chrome.fileManagerPrivate.cancelDialog = function() {};
@@ -1701,6 +1729,11 @@
 chrome.fileManagerPrivate.parseTrashInfoFiles = function(entries, callback) {};
 
 /**
+ * @param {function(!chrome.fileManagerPrivate.BulkPinProgress): void} callback
+ */
+chrome.fileManagerPrivate.getBulkPinProgress = function(callback) {};
+
+/**
  * @type {!ChromeEvent}
  */
 chrome.fileManagerPrivate.onMountCompleted;
diff --git a/third_party/s2cellid/README.chromium b/third_party/s2cellid/README.chromium
index 53c42f734..25044e8 100644
--- a/third_party/s2cellid/README.chromium
+++ b/third_party/s2cellid/README.chromium
@@ -18,6 +18,7 @@
    - mathutil.h mathutil.cc
    - vector.h
      - Change comparison operator implementations to be C++20-compliant
+     - add missing cstdint include
  - _fpcontractoff.h
  - r1interval.h
  - r2.h
diff --git a/third_party/s2cellid/src/s2/util/math/vector.h b/third_party/s2cellid/src/s2/util/math/vector.h
index ded669c..487edc3 100644
--- a/third_party/s2cellid/src/s2/util/math/vector.h
+++ b/third_party/s2cellid/src/s2/util/math/vector.h
@@ -22,6 +22,7 @@
 
 #include <algorithm>
 #include <cmath>
+#include <cstdint>
 #include <cstdlib>
 #include <iosfwd>
 #include <iostream>  // NOLINT(readability/streams)
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 09835e9..15fb89c 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -35814,6 +35814,7 @@
   <int value="1780" label="OS_EVENTS_STOPCAPTURINGEVENTS"/>
   <int value="1781" label="SIDEPANEL_SETPANELBEHAVIOR"/>
   <int value="1782" label="SIDEPANEL_GETPANELBEHAVIOR"/>
+  <int value="1783" label="FILEMANAGERPRIVATE_GETBULKPINPROGRESS"/>
 </enum>
 
 <enum name="ExtensionIconState">
@@ -50790,6 +50791,28 @@
   <int value="9" label="PATCH"/>
 </enum>
 
+<enum name="HttpNetworkTransactionRetryReason">
+  <int value="0" label="HttpRequestTimeout"/>
+  <int value="1" label="HttpMisdirectedRequest"/>
+  <int value="2" label="Http11Required"/>
+  <int value="3" label="SslClientAuthSignatureFailed"/>
+  <int value="4" label="ConnectionReset"/>
+  <int value="5" label="ConnectionClosed"/>
+  <int value="6" label="ConnectionAborted"/>
+  <int value="7" label="SocketNotConnected"/>
+  <int value="8" label="EmptyResponse"/>
+  <int value="9" label="EarlyDataRejected"/>
+  <int value="10" label="WrongVersionOnEarlyData"/>
+  <int value="11" label="Http2PingFailed"/>
+  <int value="12" label="Http2ServerRefusedStream"/>
+  <int value="13" label="Http2PushedStreamNotAvailable"/>
+  <int value="14" label="Http2ClaimedPushedStreamResetByServer"/>
+  <int value="15" label="Http2PushedResponseDoesNotMatch"/>
+  <int value="16" label="QuicHandshakeFailed"/>
+  <int value="17" label="QuicGoawayRequestCanBeRetried"/>
+  <int value="18" label="QuicProtocolError"/>
+</enum>
+
 <enum name="HttpPasswordMigrationMode">
   <int value="0" label="Moved">
     HTTP credentials were moved during migration to HTTPS
@@ -58369,6 +58392,7 @@
   <int value="-1948236151" label="DrawPredictedInkPoint:disabled"/>
   <int value="-1946595906" label="enable-push-api-background-mode"/>
   <int value="-1946522787" label="VrCustomTabBrowsing:disabled"/>
+  <int value="-1946496305" label="TailoredSecurityUpdatedMessages:enabled"/>
   <int value="-1946367770" label="SyncWifiConfigurations:enabled"/>
   <int value="-1946057753" label="GaiaIdCacheInAccountManagerFacade:disabled"/>
   <int value="-1945601266" label="freeze-user-agent"/>
@@ -61178,6 +61202,7 @@
   <int value="-446220201" label="EnableIncognitoShortcutOnDesktop:enabled"/>
   <int value="-444867364" label="Metal:enabled"/>
   <int value="-442352394" label="IframeOneGoogleBar:disabled"/>
+  <int value="-441840790" label="TailoredSecurityUpdatedMessages:disabled"/>
   <int value="-438529902" label="CaptivePortalErrorPage:enabled"/>
   <int value="-438379844" label="SwapSideVolumeButtonsForOrientation:enabled"/>
   <int value="-438348502" label="LogUrlScoringSignals:disabled"/>
@@ -87815,6 +87840,14 @@
   <int value="4" label="NETWORK_IP_ADDRESS_CHANGED"/>
 </enum>
 
+<enum name="QuicProtocolErrorRetryStatus">
+  <int value="0" label="NoRetryExceededMaxRetries"/>
+  <int value="1" label="NoRetryHeaderReceived"/>
+  <int value="2" label="NoRetryNoAlternativeService"/>
+  <int value="3" label="RetryAltServiceBroken"/>
+  <int value="4" label="RetryAltServiceNotBroken"/>
+</enum>
+
 <enum name="QuicRejectReasons">
   <int value="1" label="CLIENT_NONCE_UNKNOWN_FAILURE"/>
   <int value="2" label="CLIENT_NONCE_INVALID_FAILURE"/>
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml
index de1354c3..7b2554b0 100644
--- a/tools/metrics/histograms/metadata/net/histograms.xml
+++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -2210,6 +2210,17 @@
   </summary>
 </histogram>
 
+<histogram name="Net.NetworkTransaction{HostType}.RetryReason"
+    enum="HttpNetworkTransactionRetryReason" expires_after="2023-09-01">
+  <owner>horo@chromium.org</owner>
+  <owner>src/net/OWNERS</owner>
+  <summary>Log the reason when HttpNetworkTransaction retries.</summary>
+  <token key="HostType">
+    <variant name=""/>
+    <variant name="H3SupportedGoogleHost"/>
+  </token>
+</histogram>
+
 <histogram name="Net.NumQuicSessionsAtShutdown" units="units"
     expires_after="2023-10-08">
   <owner>dschinazi@chromium.org</owner>
@@ -2696,6 +2707,81 @@
   <summary>The number of times ServerConfigUpdateMessages ignored.</summary>
 </histogram>
 
+<histogram name="Net.QuicProtocolErrorRetryDelay{HostType}.{FinalResult}"
+    units="ms" expires_after="2023-09-01">
+  <owner>horo@chromium.org</owner>
+  <owner>src/net/OWNERS</owner>
+  <summary>
+    Log the retry delay caused by ERR_QUIC_PROTOCOL_ERROR. Recorded when
+    HttpNetworkTransaction finishes.
+  </summary>
+  <token key="HostType">
+    <variant name=""/>
+    <variant name="H3SupportedGoogleHost"/>
+  </token>
+  <token key="FinalResult">
+    <variant name="Failure"/>
+    <variant name="Success"/>
+  </token>
+</histogram>
+
+<histogram name="Net.QuicProtocolError{HostType}.RetryStatus"
+    enum="QuicProtocolErrorRetryStatus" expires_after="2023-09-01">
+  <owner>horo@chromium.org</owner>
+  <owner>src/net/OWNERS</owner>
+  <summary>
+    The status of how HttpNetworkTransaction handles a ERR_QUIC_PROTOCOL_ERROR.
+    Recorded when HttpNetworkTransaction finishes.
+  </summary>
+  <token key="HostType">
+    <variant name=""/>
+    <variant name="H3SupportedGoogleHost"/>
+  </token>
+</histogram>
+
+<histogram name="Net.QuicProtocolError{HostType}.{RetryStatus}.QuicErrorCode"
+    enum="QuicErrorCodes" expires_after="2023-09-01">
+  <owner>horo@chromium.org</owner>
+  <owner>src/net/OWNERS</owner>
+  <summary>
+    Log the QUIC error code when HttpNetworkTransaction handles a
+    ERR_QUIC_PROTOCOL_ERROR.
+  </summary>
+  <token key="HostType">
+    <variant name=""/>
+    <variant name="H3SupportedGoogleHost"/>
+  </token>
+  <token key="RetryStatus">
+    <variant name="NoRetryExceededMaxRetries"/>
+    <variant name="NoRetryHeaderReceived"/>
+    <variant name="NoRetryNoAlternativeService"/>
+    <variant name="RetryAltServiceBroken"/>
+    <variant name="RetryAltServiceNotBroken"/>
+  </token>
+</histogram>
+
+<histogram
+    name="Net.QuicProtocolError{HostType}.{RetryStatus}.QuicStreamErrorCode"
+    enum="QuicRstStreamErrorCodes" expires_after="2023-09-01">
+  <owner>horo@chromium.org</owner>
+  <owner>src/net/OWNERS</owner>
+  <summary>
+    Log the QUIC stream error code when HttpNetworkTransaction handles a
+    ERR_QUIC_PROTOCOL_ERROR.
+  </summary>
+  <token key="HostType">
+    <variant name=""/>
+    <variant name="H3SupportedGoogleHost"/>
+  </token>
+  <token key="RetryStatus">
+    <variant name="NoRetryExceededMaxRetries"/>
+    <variant name="NoRetryHeaderReceived"/>
+    <variant name="NoRetryNoAlternativeService"/>
+    <variant name="RetryAltServiceBroken"/>
+    <variant name="RetryAltServiceNotBroken"/>
+  </token>
+</histogram>
+
 <histogram name="Net.QuicServerInfo.DiskCacheState"
     enum="QuicServerConfigState" expires_after="2024-04-03">
   <owner>dschinazi@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/quick_answers/histograms.xml b/tools/metrics/histograms/metadata/quick_answers/histograms.xml
index ae2b4be..0e617c6 100644
--- a/tools/metrics/histograms/metadata/quick_answers/histograms.xml
+++ b/tools/metrics/histograms/metadata/quick_answers/histograms.xml
@@ -38,7 +38,8 @@
 
 <histogram name="QuickAnswers.ActiveImpression" enum="QuickAnswersResultType"
     expires_after="2023-10-01">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>llin@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
@@ -50,7 +51,8 @@
 <histogram
     name="QuickAnswers.ActiveImpression.Duration{QuickAnswersClickResultType}"
     units="ms" expires_after="2023-12-01">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>llin@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
@@ -65,7 +67,8 @@
 
 <histogram name="QuickAnswers.Click" enum="QuickAnswersResultType"
     expires_after="2023-10-08">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>llin@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
@@ -75,7 +78,8 @@
 
 <histogram name="QuickAnswers.Click.Duration{QuickAnswersClickResultType}"
     units="ms" expires_after="2023-10-15">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>llin@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
@@ -90,7 +94,8 @@
 
 <histogram name="QuickAnswers.ContextMenu.Close" enum="BooleanClicked"
     expires_after="2023-10-08">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
     Records whether or not the user interacted (via clicking) with a context
@@ -103,7 +108,8 @@
 
 <histogram name="QuickAnswers.ContextMenu.Close.Duration{InteractionType}"
     units="ms" expires_after="2023-10-31">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
     Records the amount of time the context menu was shown before close if the
@@ -118,7 +124,8 @@
 
 <histogram name="QuickAnswers.DictionaryIntent.Language" enum="LanguageName"
     expires_after="2023-07-01">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
     For Quick answers fetch, records the query text language of dictionary
@@ -128,7 +135,8 @@
 
 <histogram name="QuickAnswers.DictionaryIntent.Source"
     enum="QuickAnswersDictionaryIntentSource" expires_after="2023-07-01">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
     For Quick answers fetch, records the source type of dictionary intent
@@ -138,7 +146,8 @@
 
 <histogram name="QuickAnswers.ExitPoint" enum="QuickAnswersExitPoint"
     expires_after="2023-08-15">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
     Record the Quick Answers exit point point when the Quick Answers UI is
@@ -148,7 +157,8 @@
 
 <histogram name="QuickAnswers.FeatureEnabled" enum="BooleanEnabled"
     expires_after="2023-08-15">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
     Record the Quick Answers feature enabled status when the first user session
@@ -158,7 +168,8 @@
 
 <histogram name="QuickAnswers.Intent" enum="QuickAnswersIntentType"
     expires_after="2023-09-03">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>llin@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
@@ -169,7 +180,8 @@
 
 <histogram name="QuickAnswers.Loading.Duration" units="ms"
     expires_after="2023-12-01">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>llin@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
@@ -180,7 +192,8 @@
 
 <histogram name="QuickAnswers.Loading.Status" enum="QuickAnswersLoadStatus"
     expires_after="2023-09-10">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>llin@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
@@ -190,7 +203,8 @@
 
 <histogram name="QuickAnswers.NetworkError.IntentType"
     enum="QuickAnswersIntentType" expires_after="2023-10-08">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
     Records the intent type when network error occurs during the quick answers
@@ -199,8 +213,9 @@
 </histogram>
 
 <histogram name="QuickAnswers.NetworkError.ResponseCode.{IntentType}"
-    enum="HttpResponseCode" expires_after="2023-03-21">
-  <owner>updowndota@chromium.org</owner>
+    enum="HttpResponseCode" expires_after="2023-10-21">
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
     Records the Http response codes when network error occurs when fetching
@@ -215,7 +230,8 @@
 
 <histogram name="QuickAnswers.RequestTextLength.{IntentType}"
     units="characters" expires_after="2023-08-15">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
     For every quick answer request, records the length of the selected text that
@@ -230,7 +246,8 @@
 
 <histogram name="QuickAnswers.Result" enum="QuickAnswersResultType"
     expires_after="2023-09-17">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>llin@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
@@ -241,7 +258,8 @@
 
 <histogram name="QuickAnswers.Result.Duration{QuickAnswersClickResultType}"
     units="ms" expires_after="2023-10-31">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>llin@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
@@ -256,7 +274,8 @@
 
 <histogram name="QuickAnswers.SelectedContent.Length" units="characters"
     expires_after="2023-09-03">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>llin@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
@@ -267,8 +286,8 @@
 
 <histogram name="QuickAnswers.TextToSpeech.EngineEvent"
     enum="QuickAnswersTextToSpeechEngineEvent" expires_after="2023-08-20">
-  <owner>updowndota@chromium.org</owner>
   <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
     Reports the various TTS engine events received by the quick answers TTS
@@ -279,7 +298,8 @@
 
 <histogram name="QuickAnswers.V2.Consent" units="impressions"
     expires_after="2023-10-15">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
     For every quick answers consent impression, records how many times the user
@@ -290,7 +310,8 @@
 <histogram
     name="QuickAnswers.V2.Consent.Duration{QuickAnswersV2ConsentResultType}"
     units="ms" expires_after="2023-08-15">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
     For every quick answers consent result event, records how long the user has
@@ -303,7 +324,8 @@
 <histogram
     name="QuickAnswers.V2.Consent.Impression{QuickAnswersV2ConsentResultType}"
     units="impressions" expires_after="2023-08-15">
-  <owner>updowndota@chromium.org</owner>
+  <owner>angelaxiao@chromium.org</owner>
+  <owner>yawano@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
     For every quick answers consent result event, records how many times the
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 8cd1137d..87cb681 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,16 +5,16 @@
             "full_remote_path": "perfetto-luci-artifacts/adbbb6c78e3a86c5e87b0338d9e42eb6b4ddbf4d/linux-arm64/trace_processor_shell"
         },
         "win": {
-            "hash": "0e2a4c41d5003056f639665381c5cf0f03511e89",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/b57a685175d3070783d25958e0851b8d077b6280/trace_processor_shell.exe"
+            "hash": "aa2df4a39ee7d331ba41f1f02dabdef3c4c9c17a",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/73a3aa98dc279a67a513bfd62aadad0872f715ad/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "1d229abc94dea54ab4bb4327e78e18f942d08bf9",
             "full_remote_path": "perfetto-luci-artifacts/adbbb6c78e3a86c5e87b0338d9e42eb6b4ddbf4d/linux-arm/trace_processor_shell"
         },
         "mac": {
-            "hash": "40fdad52d21c168aec843968a05c75aa6b9f1ef2",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/b57a685175d3070783d25958e0851b8d077b6280/trace_processor_shell"
+            "hash": "4ebdc4ca05b0145e232cce3d5931f6c8eaac218c",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/73a3aa98dc279a67a513bfd62aadad0872f715ad/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "7a4026b8718994145a52586fdec6e9447573345a",
@@ -22,7 +22,7 @@
         },
         "linux": {
             "hash": "6cea21590b19ec403a0565b70a99d26c63cc0d89",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/d4f6e083e11e78c7370e0ce938be04c5d556cb0f/trace_processor_shell"
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/73a3aa98dc279a67a513bfd62aadad0872f715ad/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/style_variable_generator/tests/style_variable_generator_test.py b/tools/style_variable_generator/tests/style_variable_generator_test.py
index 284de8c5a..c77b41d3 100755
--- a/tools/style_variable_generator/tests/style_variable_generator_test.py
+++ b/tools/style_variable_generator/tests/style_variable_generator_test.py
@@ -21,10 +21,17 @@
 
 print(os.path.join(os.path.dirname(__file__)))
 
+# Dirty hack to make updating goldens easier. Setting to true then running the
+# tests will force all goldens to match script output.
+UPDATE_GOLDENS = False
+
 
 class BaseStyleGeneratorTest:
     def assertEqualToFile(self, value, filename):
         path = os.path.join(os.path.dirname(__file__), 'goldens', filename)
+        if UPDATE_GOLDENS:
+            with open(path, 'w') as f:
+                f.write(value)
         with open(path, 'r') as f:
             self.maxDiff = None
             self.assertEqual(value, f.read(), f'Did not match golden: {path}')
@@ -304,4 +311,13 @@
 
 
 if __name__ == '__main__':
+    if UPDATE_GOLDENS:
+        print("""\033[1;31;40m
+============================ [WARNING] ============================
+! UPDATE_GOLDENS IS TRUE. EACH TIME THE TESTS ARE RUN ALL GOLDENS
+  WILL BE UPDATED TO MATCH CURRENT BEHAVIOUR.
+! ALL TESTS WILL PASS WITHOUT BEING CHECKED.
+! THE CODE SHOULD NOT BE SUBBMITTED AS IS.
+===================================================================\033[0m
+        """)
     unittest.main()
diff --git a/ui/color/color_id.h b/ui/color/color_id.h
index 08dedb24..015a88e 100644
--- a/ui/color/color_id.h
+++ b/ui/color/color_id.h
@@ -398,7 +398,6 @@
   E_CPONLY(kColorTextfieldSelectionBackground) \
   E_CPONLY(kColorTextfieldSelectionForeground) \
   E_CPONLY(kColorTextfieldOutline) \
-  E_CPONLY(kColorTextfieldOutlineHover) \
   E_CPONLY(kColorTextfieldDisabledOutline) \
   E_CPONLY(kColorTextfieldInvalidOutline) \
   E_CPONLY(kColorThrobber) \
diff --git a/ui/color/material_ui_color_mixer.cc b/ui/color/material_ui_color_mixer.cc
index be6734d7..2049091 100644
--- a/ui/color/material_ui_color_mixer.cc
+++ b/ui/color/material_ui_color_mixer.cc
@@ -78,7 +78,6 @@
   mixer[kColorTextfieldForegroundDisabled] = {kColorSysStateDisabled};
   mixer[kColorTextfieldForegroundPlaceholder] = {kColorSysOnSurfaceSubtle};
   mixer[kColorTextfieldOutline] = {kColorSysNeutralOutline};
-  mixer[kColorTextfieldOutlineHover] = {kColorSysStateHoverOnSubtle};
   mixer[kColorTextfieldDisabledOutline] = {SK_ColorTRANSPARENT};
   mixer[kColorTextfieldInvalidOutline] = {
       kColorTextfieldForegroundPlaceholderInvalid};
diff --git a/ui/color/ui_color_mixer.cc b/ui/color/ui_color_mixer.cc
index d71ff66..e52dd23 100644
--- a/ui/color/ui_color_mixer.cc
+++ b/ui/color/ui_color_mixer.cc
@@ -269,7 +269,6 @@
   mixer[kColorTextfieldSelectionBackground] = {kColorTextSelectionBackground};
   mixer[kColorTextfieldSelectionForeground] = {kColorTextSelectionForeground};
   mixer[kColorTextfieldOutline] = {kColorFocusableBorderUnfocused};
-  mixer[kColorTextfieldOutlineHover] = {kColorFocusableBorderUnfocused};
   mixer[kColorTextfieldDisabledOutline] = {kColorFocusableBorderUnfocused};
   mixer[kColorTextfieldInvalidOutline] = {kColorAlertHighSeverity};
   mixer[kColorThrobber] =
diff --git a/ui/file_manager/file_manager/common/js/util.js b/ui/file_manager/file_manager/common/js/util.js
index d627c129..3003e2e0 100644
--- a/ui/file_manager/file_manager/common/js/util.js
+++ b/ui/file_manager/file_manager/common/js/util.js
@@ -1533,7 +1533,13 @@
  * @return {boolean}
  */
 util.isOneDrive = (volumeInfo) => {
-  if (volumeInfo?.providerId === 'ajdgmkbkgifbokednjgbmieaemeighkg') {
+  if (
+      // App built manually from internal git, used for the early dogfood.
+      volumeInfo?.providerId === 'ajdgmkbkgifbokednjgbmieaemeighkg' ||
+      // App built manually from internal repo.
+      volumeInfo?.providerId === 'gcpjnalmmghdoadafjgomdlghfnllceo' ||
+      // App from official internal repo.
+      volumeInfo?.providerId === 'gnnndjlaomemikopnjhhnoombakkkkdg') {
     return true;
   }
   return false;
diff --git a/ui/gfx/android/android_surface_control_compat.h b/ui/gfx/android/android_surface_control_compat.h
index 1977603..1c0bb44 100644
--- a/ui/gfx/android/android_surface_control_compat.h
+++ b/ui/gfx/android/android_surface_control_compat.h
@@ -14,6 +14,7 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/files/scoped_file.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/ref_counted.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/time/time.h"
@@ -188,7 +189,9 @@
     void DestroyIfNeeded();
 
     int id_;
-    ASurfaceTransaction* transaction_;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #union
+    RAW_PTR_EXCLUSION ASurfaceTransaction* transaction_;
     OnCommitCb on_commit_cb_;
     OnCompleteCb on_complete_cb_;
     bool need_to_apply_ = false;
diff --git a/ui/gfx/android/java_bitmap.h b/ui/gfx/android/java_bitmap.h
index d5d5b35..ade129e6 100644
--- a/ui/gfx/android/java_bitmap.h
+++ b/ui/gfx/android/java_bitmap.h
@@ -9,6 +9,7 @@
 #include <stdint.h>
 
 #include "base/android/scoped_java_ref.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/gfx_export.h"
@@ -48,7 +49,9 @@
 
  private:
   base::android::ScopedJavaGlobalRef<jobject> bitmap_;
-  void* pixels_;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #addr-of
+  RAW_PTR_EXCLUSION void* pixels_;
   gfx::Size size_;
   BitmapFormat format_;
   uint32_t bytes_per_row_;
diff --git a/ui/gl/android/scoped_a_native_window.h b/ui/gl/android/scoped_a_native_window.h
index 9261324..7ff151f 100644
--- a/ui/gl/android/scoped_a_native_window.h
+++ b/ui/gl/android/scoped_a_native_window.h
@@ -7,6 +7,7 @@
 
 #include <cstddef>
 
+#include "base/memory/raw_ptr_exclusion.h"
 #include "ui/gl/gl_export.h"
 
 struct ANativeWindow;
@@ -39,7 +40,9 @@
 
   void DestroyIfNeeded();
 
-  ANativeWindow* a_native_window_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #constexpr-ctor-field-initializer, #global-scope
+  RAW_PTR_EXCLUSION ANativeWindow* a_native_window_ = nullptr;
 };
 
 }  // namespace gl
diff --git a/ui/gl/dc_layer_tree.cc b/ui/gl/dc_layer_tree.cc
index 36c66f038..f92a91f 100644
--- a/ui/gl/dc_layer_tree.cc
+++ b/ui/gl/dc_layer_tree.cc
@@ -222,12 +222,18 @@
     needs_commit = true;
 
     // All the visual are created together on the first |Update|.
-    DCHECK(!content_visual_);
+    CHECK(!transform_visual_);
+    CHECK(!content_visual_);
+
     hr = dcomp_device->CreateVisual(&clip_visual_);
     CHECK_EQ(hr, S_OK);
+    hr = dcomp_device->CreateVisual(&transform_visual_);
+    CHECK_EQ(hr, S_OK);
     hr = dcomp_device->CreateVisual(&content_visual_);
     CHECK_EQ(hr, S_OK);
-    hr = clip_visual_->AddVisual(content_visual_.Get(), FALSE, nullptr);
+    hr = clip_visual_->AddVisual(transform_visual_.Get(), FALSE, nullptr);
+    CHECK_EQ(hr, S_OK);
+    hr = transform_visual_->AddVisual(content_visual_.Get(), FALSE, nullptr);
     CHECK_EQ(hr, S_OK);
   }
 
@@ -249,19 +255,6 @@
     }
   }
 
-  if (offset_ != quad_rect_offset) {
-    offset_ = quad_rect_offset;
-    needs_commit = true;
-
-    // Visual offset is applied before transform so it behaves similar to how
-    // the compositor uses transform to map quad rect in layer space to target
-    // space.
-    hr = content_visual_->SetOffsetX(offset_.x());
-    CHECK_EQ(hr, S_OK);
-    hr = content_visual_->SetOffsetY(offset_.y());
-    CHECK_EQ(hr, S_OK);
-  }
-
   if (transform_ != quad_to_root_transform) {
     transform_ = quad_to_root_transform;
     needs_commit = true;
@@ -272,7 +265,20 @@
         D2D1::Matrix3x2F(transform_.rc(0, 0), transform_.rc(1, 0),  //
                          transform_.rc(0, 1), transform_.rc(1, 1),  //
                          transform_.rc(0, 3), transform_.rc(1, 3));
-    hr = content_visual_->SetTransform(matrix);
+    hr = transform_visual_->SetTransform(matrix);
+    CHECK_EQ(hr, S_OK);
+  }
+
+  if (offset_ != quad_rect_offset) {
+    offset_ = quad_rect_offset;
+    needs_commit = true;
+
+    // Visual offset is applied after transform so it is affected by the
+    // transform, which is consistent with how the compositor maps quad rects to
+    // their target space.
+    hr = content_visual_->SetOffsetX(offset_.x());
+    CHECK_EQ(hr, S_OK);
+    hr = content_visual_->SetOffsetY(offset_.y());
     CHECK_EQ(hr, S_OK);
   }
 
diff --git a/ui/gl/dc_layer_tree.h b/ui/gl/dc_layer_tree.h
index a84e203..3b5faca 100644
--- a/ui/gl/dc_layer_tree.h
+++ b/ui/gl/dc_layer_tree.h
@@ -224,7 +224,17 @@
       void set_z_order(int z_order) { z_order_ = z_order; }
 
      private:
+      // The root of this subtree. In root space and contains the clip rect.
       Microsoft::WRL::ComPtr<IDCompositionVisual2> clip_visual_;
+      // The child of |clip_visual_|, transforms its children from quad to root
+      // space. This visual exists because |offset_| is in quad space, so it
+      // must be affected by |transform_|. They cannot be on the same visual
+      // since |IDCompositionVisual::SetTransform| and
+      // |IDCompositionVisual::SetOffset[XY]| are applied in the opposite order
+      // than we want.
+      Microsoft::WRL::ComPtr<IDCompositionVisual2> transform_visual_;
+      // The child of |transform_visual_|. In quad space, holds
+      // |dcomp_visual_content_|.
       Microsoft::WRL::ComPtr<IDCompositionVisual2> content_visual_;
 
       // The content to be placed at the leaf of the visual subtree. Either an
diff --git a/ui/gl/dcomp_presenter_unittest.cc b/ui/gl/dcomp_presenter_unittest.cc
index 5e225d2..955fadc 100644
--- a/ui/gl/dcomp_presenter_unittest.cc
+++ b/ui/gl/dcomp_presenter_unittest.cc
@@ -21,6 +21,8 @@
 #include "ui/gfx/frame_data.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/geometry/transform.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+#include "ui/gfx/test/sk_color_eq.h"
 #include "ui/gl/dc_layer_overlay_params.h"
 #include "ui/gl/direct_composition_child_surface_win.h"
 #include "ui/gl/direct_composition_support.h"
@@ -107,14 +109,15 @@
   return texture;
 }
 
+// The precise colors may differ depending on the video processor, so allow a
+// margin for error.
+const int kMaxColorChannelDeviation = 10;
+
 bool AreColorsSimilar(int a, int b) {
-  // The precise colors may differ depending on the video processor, so allow
-  // a margin for error.
-  const int kMargin = 10;
-  return abs(SkColorGetA(a) - SkColorGetA(b)) < kMargin &&
-         abs(SkColorGetR(a) - SkColorGetR(b)) < kMargin &&
-         abs(SkColorGetG(a) - SkColorGetG(b)) < kMargin &&
-         abs(SkColorGetB(a) - SkColorGetB(b)) < kMargin;
+  return abs(SkColorGetA(a) - SkColorGetA(b)) < kMaxColorChannelDeviation &&
+         abs(SkColorGetR(a) - SkColorGetR(b)) < kMaxColorChannelDeviation &&
+         abs(SkColorGetG(a) - SkColorGetG(b)) < kMaxColorChannelDeviation &&
+         abs(SkColorGetB(a) - SkColorGetB(b)) < kMaxColorChannelDeviation;
 }
 
 }  // namespace
@@ -1176,6 +1179,97 @@
   }
 }
 
+// Test that the overlay quad rect's offset is affected by its transform.
+TEST_F(DCompPresenterPixelTest, QuadOffsetAppliedAfterTransform) {
+  if (!presenter_) {
+    return;
+  }
+  // Fails on AMD RX 5500 XT. https://crbug.com/1152565.
+  if (context_ && context_->GetVersionInfo() &&
+      context_->GetVersionInfo()->driver_vendor.find("AMD") !=
+          std::string::npos) {
+    return;
+  }
+
+  // Our overlay quad rect is at 0,50 50x50 and scaled down by 1/2. Since we
+  // expect the transform to affect the quad rect offset, we expect the output
+  // rect to be at 0,25 25x25.
+  const gfx::Rect quad_rect(gfx::Point(0, 50), gfx::Size(50, 50));
+  const gfx::Transform quad_to_root_transform(
+      gfx::AxisTransform2d(0.5, gfx::Vector2dF()));
+
+  Microsoft::WRL::ComPtr<IDCompositionDevice2> dcomp_device =
+      GetDirectCompositionDevice();
+
+  Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
+      QueryD3D11DeviceObjectFromANGLE();
+  ASSERT_TRUE(d3d11_device);
+
+  Microsoft::WRL::ComPtr<ID3D11DeviceContext> context;
+  d3d11_device->GetImmediateContext(&context);
+  ASSERT_TRUE(context);
+
+  gfx::Size window_size(100, 100);
+  EXPECT_TRUE(presenter_->Resize(window_size, 1.0, gfx::ColorSpace(), true));
+  EXPECT_TRUE(presenter_->SetDrawRectangle(gfx::Rect(window_size)));
+
+  InitializeRootAndScheduleRootSurface(window_size, SkColors::kBlack);
+
+  Microsoft::WRL::ComPtr<IDCompositionSurface> surface;
+  ASSERT_HRESULT_SUCCEEDED(dcomp_device->CreateSurface(
+      quad_rect.width(), quad_rect.height(), DXGI_FORMAT_B8G8R8A8_UNORM,
+      DXGI_ALPHA_MODE_IGNORE, &surface));
+  RECT update_rect = D2D1::Rect(0, 0, quad_rect.width(), quad_rect.height());
+  Microsoft::WRL::ComPtr<ID3D11Texture2D> update_texture;
+  POINT update_offset;
+  ASSERT_HRESULT_SUCCEEDED(surface->BeginDraw(
+      &update_rect, IID_PPV_ARGS(&update_texture), &update_offset));
+  Microsoft::WRL::ComPtr<ID3D11RenderTargetView> rtv;
+  ASSERT_HRESULT_SUCCEEDED(d3d11_device->CreateRenderTargetView(
+      update_texture.Get(), nullptr, &rtv));
+  context->ClearRenderTargetView(rtv.Get(), SkColors::kRed.vec());
+  ASSERT_HRESULT_SUCCEEDED(surface->EndDraw());
+
+  auto dc_layer_params = std::make_unique<DCLayerOverlayParams>();
+  dc_layer_params->overlay_image =
+      DCLayerOverlayImage(quad_rect.size(), surface);
+  dc_layer_params->content_rect = gfx::Rect(quad_rect.size());
+  dc_layer_params->quad_rect = quad_rect;
+  dc_layer_params->transform = quad_to_root_transform;
+  dc_layer_params->color_space = gfx::ColorSpace::CreateSRGB();
+  dc_layer_params->z_order = 1;
+
+  presenter_->ScheduleDCLayer(std::move(dc_layer_params));
+  PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK);
+
+  // We expect DComp to display the overlay with the same bounds as if viz were
+  // to composite it.
+  const gfx::Rect mapped_quad_rect = quad_to_root_transform.MapRect(quad_rect);
+
+  // Check the top edge of the scaled overlay
+  EXPECT_SKCOLOR_CLOSE(
+      SK_ColorBLACK,
+      GLTestHelper::ReadBackWindowPixel(
+          window_.hwnd(), gfx::Point(0, mapped_quad_rect.y() - 1)),
+      kMaxColorChannelDeviation);
+  EXPECT_SKCOLOR_CLOSE(SK_ColorRED,
+                       GLTestHelper::ReadBackWindowPixel(
+                           window_.hwnd(), gfx::Point(0, mapped_quad_rect.y())),
+                       kMaxColorChannelDeviation);
+
+  // Check the bottom edge of the scaled overlay
+  EXPECT_SKCOLOR_CLOSE(
+      SK_ColorRED,
+      GLTestHelper::ReadBackWindowPixel(
+          window_.hwnd(), gfx::Point(0, mapped_quad_rect.bottom() - 1)),
+      kMaxColorChannelDeviation);
+  EXPECT_SKCOLOR_CLOSE(
+      SK_ColorBLACK,
+      GLTestHelper::ReadBackWindowPixel(
+          window_.hwnd(), gfx::Point(0, mapped_quad_rect.bottom())),
+      kMaxColorChannelDeviation);
+}
+
 class DCompPresenterBufferCountTest : public DCompPresenterTest,
                                       public testing::WithParamInterface<bool> {
  public:
diff --git a/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc b/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc
index 21178b54..c4b88ae 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc
+++ b/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc
@@ -27,7 +27,7 @@
 #if defined(WAYLAND_GBM)
 #include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/linux/drm_util_linux.h"
-#include "ui/gfx/linux/gbm_device.h"
+#include "ui/gfx/linux/gbm_device.h"  // nogncheck
 #include "ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h"
 #include "ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h"
 #include "ui/ozone/public/ozone_platform.h"
diff --git a/ui/views/controls/menu/menu_scroll_view_container.cc b/ui/views/controls/menu/menu_scroll_view_container.cc
index 06f9bd1c..120769e 100644
--- a/ui/views/controls/menu/menu_scroll_view_container.cc
+++ b/ui/views/controls/menu/menu_scroll_view_container.cc
@@ -455,6 +455,10 @@
   if (use_ash_system_ui_layout_)
     shadow_type = BubbleBorder::CHROMEOS_SYSTEM_UI_SHADOW;
 #endif
+  if (border_color_id_.has_value()) {
+    // If there's a custom border color, use this for the bubble border color.
+    id = border_color_id_.value();
+  }
   auto bubble_border = std::make_unique<BubbleBorder>(arrow_, shadow_type, id);
   bool has_customized_corner = use_ash_system_ui_layout_ && menu_controller &&
                                menu_controller->rounded_corners().has_value();
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index 2920ccd..44308fa 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -54,8 +54,6 @@
 #include "ui/gfx/selection_bound.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/accessibility/view_accessibility.h"
-#include "ui/views/animation/ink_drop.h"
-#include "ui/views/animation/ink_drop_highlight.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/focus_ring.h"
 #include "ui/views/controls/focusable_border.h"
@@ -244,17 +242,6 @@
   FocusRing::Install(this);
   FocusRing::Get(this)->SetOutsetFocusRingDisabled(true);
 
-  if (::features::IsChromeRefresh2023()) {
-    InkDrop::Install(this, std::make_unique<views::InkDropHost>(this));
-    InkDrop::Get(this)->SetMode(InkDropHost::InkDropMode::ON);
-    InkDrop::Get(this)->SetBaseColorCallback(base::BindRepeating(
-        [](Textfield* host) {
-          return host->GetColorProvider()->GetColor(
-              ui::kColorTextfieldOutlineHover);
-        },
-        this));
-  }
-
 #if !BUILDFLAG(IS_MAC)
   // Do not map accelerators on Mac. E.g. They might not reflect custom
   // keybindings that a user has set. But also on Mac, these commands dispatch