diff --git a/DEPS b/DEPS
index b36ceae..dfce8be7 100644
--- a/DEPS
+++ b/DEPS
@@ -229,7 +229,7 @@
   #
   # CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-amd64-generic-chrome-skylab
   # CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-arm-generic-chrome-skylab
-  'lacros_sdk_version': '15308.0.0',
+  'lacros_sdk_version': '15310.0.0',
 
   # Generate location tag metadata to include in tests result data uploaded
   # to ResultDB. This isn't needed on some configs and the tool that generates
@@ -304,19 +304,19 @@
   # 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': '7d27b3d0d2ab4055696fdecc9e462bd4c09c8277',
+  'skia_revision': 'c64a10d525d1deadf468e1fa798a11a0dbc3c526',
   # 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': '7aa5c696c5975f8d00a1b9593a1ae6481616f0e9',
+  'v8_revision': '4117924f44055116480f03dfccb81fbbf741503d',
   # 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': '598b4824eeb30c5d7ed57b2c69c7b67d84b96a23',
+  'angle_revision': '7909258e512dea11f19da20552af35475cdb97e4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '5f9ed9b16931c7155171d31f75004f73f0a3abc8',
+  'swiftshader_revision': 'aae98adc2222dcada4aa952cccad48ab08e34004',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -375,7 +375,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': 'a00d5920f9c31bcd090904bc23143c33f78dd7ad',
+  'catapult_revision': 'cfd313d8fab1b0a1b91fd0e313ed8905d6be3426',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -383,7 +383,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '9975cad7f5b5956999154aaba4eb861ae5185063',
+  'devtools_frontend_revision': '0caa7d40a53947a51bd7197a56f6c7fb79252199',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -443,7 +443,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling nearby
   # and whatever else without interference from each other.
-  'nearby_revision': 'f7f0a266fe5baf2abc96564e696e666d24b54920',
+  'nearby_revision': 'd347d0688b698100506e9dcaf227d3b69c78df67',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling securemessage
   # and whatever else without interference from each other.
@@ -770,12 +770,12 @@
 
   'src/clank': {
     'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' +
-    'c005df50cd7ab6b9a52c95e538c039b8e5006eff',
+    'a1c06e1970fb6f071099c37c8ec62d513042e7a4',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
   'src/docs/website': {
-    'url': Var('chromium_git') + '/website.git' + '@' + '79b970c929c14566dfa1603f5b4e1308bd5c346f',
+    'url': Var('chromium_git') + '/website.git' + '@' + 'd3af706919c5ba1c420d0dc8a39371b1e3dfe736',
   },
 
   'src/ios/third_party/earl_grey2/src': {
@@ -1204,13 +1204,13 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'a4eeafaa2fecd6196c63d67e7245f9fcf3b72870',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '175767738f47a3329b202e3ae63cb572e8ab4304',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '9636f05e9c9a76c807ce6a5f3f91ffe15d492938',
+      'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '38d6adfc379d7d4390016c429af6d0221a3ec122',
     'condition': 'checkout_src_internal',
   },
 
@@ -1829,7 +1829,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '77e0a9f4b43235bffb29ceb9e930cf2de473e10d',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '3fab086614adde1982346cc7cad06d36c6f9db97',
+    Var('webrtc_git') + '/src.git' + '@' + '37d4d840b0b674540986813d4db1b0abafda7d2b',
 
   # 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.
@@ -1899,7 +1899,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@7238ed39b1ff6346cea7304454ca289d1d0b9f5c',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@69f9fedf0bb96f20d3d3c2bd25be33ca24e7c7f8',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index a699bb6..52b02fa 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1631,6 +1631,8 @@
     "system/phonehub/phone_hub_metrics.h",
     "system/phonehub/phone_hub_notification_controller.cc",
     "system/phonehub/phone_hub_notification_controller.h",
+    "system/phonehub/phone_hub_nudge.cc",
+    "system/phonehub/phone_hub_nudge.h",
     "system/phonehub/phone_hub_recent_app_button.cc",
     "system/phonehub/phone_hub_recent_app_button.h",
     "system/phonehub/phone_hub_recent_apps_view.cc",
diff --git a/ash/app_list/views/app_drag_icon_proxy.cc b/ash/app_list/views/app_drag_icon_proxy.cc
index 7d2f801..45fb6f3 100644
--- a/ash/app_list/views/app_drag_icon_proxy.cc
+++ b/ash/app_list/views/app_drag_icon_proxy.cc
@@ -36,7 +36,6 @@
     const gfx::Point& pointer_location_in_screen,
     const gfx::Vector2d& pointer_offset_from_center,
     float scale_factor,
-    bool use_blurred_background,
     bool is_folder_icon) {
   drag_image_widget_ =
       DragImageView::Create(root_window, ui::mojom::DragEventSource::kMouse);
@@ -77,7 +76,7 @@
   image_layer->StackAtBottom(shadow_layer);
   shadow_->SetContentBounds(gfx::Rect(shadow_offset, shadow_size));
 
-  if (use_blurred_background) {
+  if (is_folder_icon) {
     const float radius = size.width() / 2.0f;
     drag_image->layer()->SetRoundedCornerRadius(
         {radius, radius, radius, radius});
diff --git a/ash/app_list/views/app_drag_icon_proxy.h b/ash/app_list/views/app_drag_icon_proxy.h
index 0040984..e379f4b 100644
--- a/ash/app_list/views/app_drag_icon_proxy.h
+++ b/ash/app_list/views/app_drag_icon_proxy.h
@@ -42,16 +42,13 @@
   //     location to maintain pointer offset from the drag image center.
   // `scale_factor` - The scale factor by which the `icon` should be scaled when
   //     shown as a drag image.
-  // `use_blurred_background` - whether the drag image should have blurred
-  //     background.
   // `is_folder_icon` - whether the icon dragged is a folder.
   AppDragIconProxy(aura::Window* root_window,
                    const gfx::ImageSkia& icon,
                    const gfx::Point& pointer_location_in_screen,
                    const gfx::Vector2d& pointer_offset_from_center,
                    float scale_factor,
-                   bool use_blurred_background,
-                   bool is_folder_icon = false);
+                   bool is_folder_icon);
   AppDragIconProxy(const AppDragIconProxy&) = delete;
   AppDragIconProxy& operator=(const AppDragIconProxy&) = delete;
   ~AppDragIconProxy() override;
diff --git a/ash/app_list/views/app_drag_icon_proxy_unittest.cc b/ash/app_list/views/app_drag_icon_proxy_unittest.cc
index 4ee4c748..e18a197 100644
--- a/ash/app_list/views/app_drag_icon_proxy_unittest.cc
+++ b/ash/app_list/views/app_drag_icon_proxy_unittest.cc
@@ -47,7 +47,7 @@
       /*pointer_location_in_screen=*/gfx::Point(100, 200),
       /*pointer_offset_from_center=*/gfx::Vector2d(10, 20),
       /*scale_factor=*/1.0f,
-      /*use_blurred_background=*/false);
+      /*is_folder_icon=*/false);
 
   EXPECT_EQ(gfx::Rect(gfx::Point(65, 155), gfx::Size(50, 50)),
             drag_icon_proxy->GetBoundsInScreen());
@@ -74,7 +74,7 @@
       /*pointer_location_in_screen=*/gfx::Point(1100, 200),
       /*pointer_offset_from_center=*/gfx::Vector2d(10, 20),
       /*scale_factor=*/1.0f,
-      /*use_blurred_background=*/false);
+      /*is_folder_icon=*/false);
 
   EXPECT_EQ(gfx::Rect(gfx::Point(1065, 155), gfx::Size(50, 50)),
             drag_icon_proxy->GetBoundsInScreen());
@@ -99,7 +99,7 @@
       /*pointer_location_in_screen=*/gfx::Point(200, 400),
       /*pointer_offset_from_center=*/gfx::Vector2d(10, 20),
       /*scale_factor=*/2.0f,
-      /*use_blurred_background=*/false);
+      /*is_folder_icon=*/false);
 
   EXPECT_EQ(gfx::Rect(gfx::Point(140, 330), gfx::Size(100, 100)),
             drag_icon_proxy->GetBoundsInScreen());
@@ -110,13 +110,14 @@
 }
 
 TEST_F(AppDragIconProxyTest, BlurSetsRoundedCorners) {
+  // Create a folder icon proxy because only folder icons have background blur.
   auto drag_icon_proxy = std::make_unique<AppDragIconProxy>(
       Shell::GetPrimaryRootWindow(),
       ash::image_util::CreateEmptyImage(gfx::Size(50, 50)),
       /*pointer_location_in_screen=*/gfx::Point(100, 200),
       /*pointer_offset_from_center=*/gfx::Vector2d(10, 20),
       /*scale_factor=*/1.0f,
-      /*use_blurred_background=*/true);
+      /*is_folder_icon=*/true);
 
   // The background should be circular.
   EXPECT_EQ(gfx::RoundedCornersF(25.0f).ToString(),
@@ -133,7 +134,7 @@
       /*pointer_location_in_screen=*/gfx::Point(100, 200),
       /*pointer_offset_from_center=*/gfx::Vector2d(10, 20),
       /*scale_factor=*/2.0f,
-      /*use_blurred_background=*/true);
+      /*is_folder_icon=*/true);
 
   // The background should be circular.
   EXPECT_EQ(gfx::RoundedCornersF(50.0f).ToString(),
@@ -151,7 +152,7 @@
       /*pointer_location_in_screen=*/gfx::Point(100, 200),
       /*pointer_offset_from_center=*/gfx::Vector2d(10, 20),
       /*scale_factor=*/1.0f,
-      /*use_blurred_background=*/false);
+      /*is_folder_icon=*/false);
   EXPECT_EQ(gfx::Rect(gfx::Point(65, 155), gfx::Size(50, 50)),
             drag_icon_proxy->GetBoundsInScreen());
 
@@ -186,7 +187,7 @@
       /*pointer_location_in_screen=*/gfx::Point(100, 200),
       /*pointer_offset_from_center=*/gfx::Vector2d(10, 20),
       /*scale_factor=*/1.0f,
-      /*use_blurred_background=*/false);
+      /*is_folder_icon=*/false);
   EXPECT_EQ(gfx::Rect(gfx::Point(65, 155), gfx::Size(50, 50)),
             drag_icon_proxy->GetBoundsInScreen());
 
@@ -218,7 +219,7 @@
       /*pointer_location_in_screen=*/gfx::Point(100, 200),
       /*pointer_offset_from_center=*/gfx::Vector2d(10, 20),
       /*scale_factor=*/1.0f,
-      /*use_blurred_background=*/false);
+      /*is_folder_icon=*/false);
   EXPECT_EQ(gfx::Rect(gfx::Point(65, 155), gfx::Size(50, 50)),
             drag_icon_proxy->GetBoundsInScreen());
 
@@ -275,7 +276,7 @@
       /*pointer_location_in_screen=*/gfx::Point(100, 200),
       /*pointer_offset_from_center=*/gfx::Vector2d(10, 20),
       /*scale_factor=*/1.0f,
-      /*use_blurred_background=*/false);
+      /*is_folder_icon=*/false);
   EXPECT_EQ(gfx::Rect(gfx::Point(65, 155), gfx::Size(50, 50)),
             drag_icon_proxy->GetBoundsInScreen());
 
@@ -303,7 +304,7 @@
       /*pointer_location_in_screen=*/gfx::Point(100, 200),
       /*pointer_offset_from_center=*/gfx::Vector2d(10, 20),
       /*scale_factor=*/1.0f,
-      /*use_blurred_background=*/false);
+      /*is_folder_icon=*/false);
   EXPECT_EQ(gfx::Rect(gfx::Point(65, 155), gfx::Size(50, 50)),
             drag_icon_proxy->GetBoundsInScreen());
 
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc
index 42b6489..b09b9f7 100644
--- a/ash/app_list/views/apps_grid_view.cc
+++ b/ash/app_list/views/apps_grid_view.cc
@@ -2348,13 +2348,11 @@
       drag_view_->GetIconBoundsInScreen().CenterPoint();
 
   const bool is_folder = drag_view_->item()->is_folder();
-  const bool use_blurred_background = is_folder && IsTabletMode();
   drag_icon_proxy_ = std::make_unique<AppDragIconProxy>(
       GetWidget()->GetNativeWindow()->GetRootWindow(),
       drag_view_->GetIconImage(), location_in_screen,
       location_in_screen - icon_location_in_screen,
-      is_folder ? kDragAndDropProxyScale : 1.0f, use_blurred_background,
-      is_folder);
+      is_folder ? kDragAndDropProxyScale : 1.0f, is_folder);
   drag_view_hider_ = std::make_unique<DragViewHider>(drag_view_);
 }
 
diff --git a/ash/capture_mode/capture_mode_feature_pod_controller_unittest.cc b/ash/capture_mode/capture_mode_feature_pod_controller_unittest.cc
index 614bd4a1..e6d93fb 100644
--- a/ash/capture_mode/capture_mode_feature_pod_controller_unittest.cc
+++ b/ash/capture_mode/capture_mode_feature_pod_controller_unittest.cc
@@ -27,11 +27,9 @@
  public:
   CaptureModeFeaturePodControllerTest() {
     if (IsQsRevampEnabled()) {
-      feature_list_.InitWithFeatures(
-          {features::kQsRevamp, features::kQsRevampWip}, {});
+      feature_list_.InitAndEnableFeature(features::kQsRevamp);
     } else {
-      feature_list_.InitWithFeatures(
-          {}, {features::kQsRevamp, features::kQsRevampWip});
+      feature_list_.InitAndDisableFeature(features::kQsRevamp);
     }
   }
 
diff --git a/ash/clipboard/clipboard_history_controller_impl.cc b/ash/clipboard/clipboard_history_controller_impl.cc
index 147c5ba..41b16f7 100644
--- a/ash/clipboard/clipboard_history_controller_impl.cc
+++ b/ash/clipboard/clipboard_history_controller_impl.cc
@@ -21,7 +21,9 @@
 #include "ash/public/cpp/clipboard_image_model_factory.h"
 #include "ash/public/cpp/window_tree_host_lookup.h"
 #include "ash/shell.h"
+#include "ash/strings/grit/ash_strings.h"
 #include "ash/style/color_util.h"
+#include "ash/system/toast/toast_manager_impl.h"
 #include "ash/wm/window_util.h"
 #include "base/barrier_closure.h"
 #include "base/check_op.h"
@@ -32,6 +34,7 @@
 #include "base/metrics/user_metrics.h"
 #include "base/notreached.h"
 #include "base/one_shot_event.h"
+#include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/lock.h"
 #include "base/task/bind_post_task.h"
@@ -49,9 +52,11 @@
 #include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
 #include "ui/base/ime/input_method.h"
 #include "ui/base/ime/text_input_client.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/image_model.h"
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/base/webui/web_ui_util.h"
+#include "ui/chromeos/events/keyboard_layout_util.h"
 #include "ui/events/event.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/keycodes/keyboard_codes_posix.h"
@@ -677,6 +682,28 @@
       // recorded only once. See `ClipboardHistory::OnDataChanged()` for further
       // explanation.
       base::RecordAction(base::UserMetricsAction("Ash_Clipboard_CopiedItem"));
+
+      // TODO(b/264913203): Add proper string resources for toast.
+      bool use_launcher_key = ui::DeviceUsesKeyboardLayout2();
+      std::u16string shortcut_key = l10n_util::GetStringUTF16(
+          use_launcher_key ? IDS_ASH_SHORTCUT_MODIFIER_LAUNCHER
+                           : IDS_ASH_SHORTCUT_MODIFIER_SEARCH);
+      // TODO(b/265059395): Replace shortcut_key with icon.
+      std::u16string label_text =
+          base::StrCat({u"[li8n] ", shortcut_key, u"+V"});
+
+      if (features::IsClipboardHistoryRefreshEnabled()) {
+        Shell::Get()->toast_manager()->Show(ToastData(
+            kClipboardCopyToastId, ToastCatalogName::kCopyToClipboardAction,
+            u"[li8n] Copied to Clipboard", ToastData::kDefaultToastDuration,
+            /*visible_on_lock_screen=*/false,
+            /*has_dismiss_button=*/true, /*custom_dismiss_text=*/
+            label_text,
+            /*dismiss_callback=*/
+            base::BindRepeating(
+                &ClipboardHistoryControllerImpl::ShowMenuFromToast,
+                weak_ptr_factory_.GetWeakPtr())));
+      }
     } else {
       // Pastes from clipboard history are already recorded in
       // `PasteMenuItemData()`. Here, we record just pastes from the standard
@@ -1035,4 +1062,9 @@
           weak_ptr_factory_.GetWeakPtr()));
 }
 
+void ClipboardHistoryControllerImpl::ShowMenuFromToast() {
+  ShowMenu(CalculateAnchorRect(), ui::MENU_SOURCE_NONE,
+           crosapi::mojom::ClipboardHistoryControllerShowSource::kToast);
+}
+
 }  // namespace ash
diff --git a/ash/clipboard/clipboard_history_controller_impl.h b/ash/clipboard/clipboard_history_controller_impl.h
index cae75386..0822bca 100644
--- a/ash/clipboard/clipboard_history_controller_impl.h
+++ b/ash/clipboard/clipboard_history_controller_impl.h
@@ -41,6 +41,8 @@
 class ClipboardNudgeController;
 class ScopedClipboardHistoryPause;
 
+constexpr char kClipboardCopyToastId[] = "CopiedToClipboard";
+
 // Shows a menu with the last few things saved in the clipboard when the
 // keyboard shortcut is pressed.
 class ASH_EXPORT ClipboardHistoryControllerImpl
@@ -215,6 +217,9 @@
   // Called when the contextual menu is closed.
   void OnMenuClosed();
 
+  // Called when toast button is pressed.
+  void ShowMenuFromToast();
+
   // Observers notified when clipboard history is shown, used, or updated.
   base::ObserverList<ClipboardHistoryController::Observer> observers_;
 
diff --git a/ash/clipboard/clipboard_history_controller_unittest.cc b/ash/clipboard/clipboard_history_controller_unittest.cc
index a0b32fe..7ecea50 100644
--- a/ash/clipboard/clipboard_history_controller_unittest.cc
+++ b/ash/clipboard/clipboard_history_controller_unittest.cc
@@ -13,6 +13,7 @@
 #include "ash/public/cpp/session/session_types.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/shell.h"
+#include "ash/system/toast/toast_manager_impl.h"
 #include "ash/test/ash_test_base.h"
 #include "base/location.h"
 #include "base/run_loop.h"
@@ -20,6 +21,7 @@
 #include "base/task/sequenced_task_runner.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/repeating_test_future.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/test_future.h"
 #include "base/unguessable_token.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -32,6 +34,7 @@
 #include "ui/events/test/event_generator.h"
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/image/image_unittest_util.h"
+#include "ui/views/controls/button/label_button.h"
 
 namespace ash {
 
@@ -488,4 +491,67 @@
   TestEnteringLockScreen();
 }
 
+// Base class for tests of Clipboard History parameterized by whether the
+// `kClipboardHistoryRefresh` feature flag is enabled.
+class ClipboardHistoryControllerRefreshTest
+    : public ClipboardHistoryControllerTest,
+      public testing::WithParamInterface</*refresh_enabled=*/bool> {
+ public:
+  ClipboardHistoryControllerRefreshTest() {
+    scoped_feature_list_.InitWithFeatureState(
+        features::kClipboardHistoryRefresh, IsClipboardHistoryRefreshEnabled());
+  }
+
+  bool IsClipboardHistoryRefreshEnabled() const { return GetParam(); }
+
+  // Some toasts can display on multiple root windows, so the caller can use
+  // `root_window` to target a toast on a specific root window.
+  ToastOverlay* GetCurrentOverlay(
+      aura::Window* root_window = Shell::GetRootWindowForNewWindows()) {
+    return Shell::Get()->toast_manager()->GetCurrentOverlayForTesting(
+        root_window);
+  }
+
+  views::LabelButton* GetDismissButton(
+      aura::Window* root_window = Shell::GetRootWindowForNewWindows()) {
+    ToastOverlay* overlay = GetCurrentOverlay(root_window);
+    DCHECK(overlay);
+    return overlay->dismiss_button_for_testing();
+  }
+
+  void ClickDismissButton(
+      aura::Window* root_window = Shell::GetRootWindowForNewWindows()) {
+    views::LabelButton* dismiss_button = GetDismissButton(root_window);
+    const gfx::Point button_center =
+        dismiss_button->GetBoundsInScreen().CenterPoint();
+    auto* event_generator = GetEventGenerator();
+    event_generator->MoveMouseTo(button_center);
+    event_generator->ClickLeftButton();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+INSTANTIATE_TEST_SUITE_P(All,
+                         ClipboardHistoryControllerRefreshTest,
+                         /*refresh_enabled=*/testing::Bool());
+
+// Tests a toast is shown if something was copied to clipboard history.
+TEST_P(ClipboardHistoryControllerRefreshTest, ShowToast) {
+  // Copy something to enable the clipboard history menu.
+  WriteTextToClipboardAndConfirm(u"test");
+
+  ToastManagerImpl* manager_ = Shell::Get()->toast_manager();
+  if (IsClipboardHistoryRefreshEnabled()) {
+    EXPECT_TRUE(manager_->IsRunning(kClipboardCopyToastId));
+
+    ClickDismissButton();
+    EXPECT_TRUE(GetClipboardHistoryController()->IsMenuShowing());
+
+  } else {
+    EXPECT_FALSE(manager_->IsRunning(kClipboardCopyToastId));
+  }
+}
+
 }  // namespace ash
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 6b45596..69919ec9 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -492,12 +492,6 @@
              "BruschettaAlphaMigrate",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-// Enables the Captive Portal UI 2022 changes, which includes updates to
-// notifications, network details page, quick settings, and portal signin UI.
-BASE_FEATURE(kCaptivePortalUI2022,
-             "CaptivePortalUI2022",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 // Enables the Captive Portal Error Page changes, which shows a suggestion in
 // the Chrome error page on ChromeOS when behind a captive portal.
 BASE_FEATURE(kCaptivePortalErrorPage,
@@ -1726,14 +1720,9 @@
              "ProjectorUseApiKeyForTranslation",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
-// Enable or disable quick settings revamped view. This flag only works when the
-// `QsRevampWip` flag is enabled.
+// Enable or disable quick settings revamped view.
 BASE_FEATURE(kQsRevamp, "QsRevamp", base::FEATURE_DISABLED_BY_DEFAULT);
 
-// Enable or disable quick settings revamped wip view.
-// TODO(b/257541368): remove this flag once the wip view is finished.
-BASE_FEATURE(kQsRevampWip, "QsRevampWip", base::FEATURE_DISABLED_BY_DEFAULT);
-
 // Controls whether the Projector Viewer supports the user experience for
 // secondary account.
 BASE_FEATURE(kProjectorViewerUseSecondaryAccount,
@@ -2380,10 +2369,6 @@
   return base::FeatureList::IsEnabled(kCalendarJelly);
 }
 
-bool IsCaptivePortalUI2022Enabled() {
-  return base::FeatureList::IsEnabled(kCaptivePortalUI2022);
-}
-
 bool IsCaptivePortalErrorPageEnabled() {
   return base::FeatureList::IsEnabled(kCaptivePortalErrorPage);
 }
@@ -3023,8 +3008,7 @@
 }
 
 bool IsQsRevampEnabled() {
-  return base::FeatureList::IsEnabled(kQsRevamp) &&
-         base::FeatureList::IsEnabled(kQsRevampWip);
+  return base::FeatureList::IsEnabled(kQsRevamp);
 }
 
 bool IsProjectorViewerUseSecondaryAccountEnabled() {
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index 5055ee40..8033d5a 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -121,7 +121,6 @@
 BASE_DECLARE_FEATURE(kCameraAppLowStorageWarning);
 COMPONENT_EXPORT(ASH_CONSTANTS)
 BASE_DECLARE_FEATURE(kCameraPrivacySwitchNotifications);
-COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kCaptivePortalUI2022);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kCaptivePortalErrorPage);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kCaptureModeDemoTools);
 COMPONENT_EXPORT(ASH_CONSTANTS)
@@ -493,7 +492,6 @@
 BASE_DECLARE_FEATURE(kProjectorAccountSwitchNotification);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kPromiseIcons);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kQsRevamp);
-COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kQsRevampWip);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kQuickDim);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kVCBackgroundBlur);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kVCBackgroundReplace);
@@ -651,7 +649,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsCalendarViewEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsCalendarModelDebugModeEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsCalendarJellyEnabled();
-COMPONENT_EXPORT(ASH_CONSTANTS) bool IsCaptivePortalUI2022Enabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsCaptivePortalErrorPageEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS)
 bool IsCheckPasswordsAgainstCryptohomeHelperEnabled();
diff --git a/ash/constants/notifier_catalogs.h b/ash/constants/notifier_catalogs.h
index b765023..741522f 100644
--- a/ash/constants/notifier_catalogs.h
+++ b/ash/constants/notifier_catalogs.h
@@ -192,7 +192,8 @@
   kDarkLightMode = 3,
   kAutozoom = 4,
   kAdaptiveCharging = 5,
-  kMaxValue = kAdaptiveCharging,
+  kPhoneHub = 6,
+  kMaxValue = kPhoneHub,
 };
 
 // A living catalog that registers toasts.
@@ -240,7 +241,8 @@
   kEcheTrayCopyPasteNotImplemented = 37,
   kEcheTrayTabletModeNotSupported = 38,
   kNotificationCenterTrayNoNotifications = 39,
-  kMaxValue = kNotificationCenterTrayNoNotifications,
+  kCopyToClipboardAction = 40,
+  kMaxValue = kCopyToClipboardAction,
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/system/toast_data.cc b/ash/public/cpp/system/toast_data.cc
index 181007a6..fc50759 100644
--- a/ash/public/cpp/system/toast_data.cc
+++ b/ash/public/cpp/system/toast_data.cc
@@ -32,13 +32,15 @@
                      base::TimeDelta duration,
                      bool visible_on_lock_screen,
                      bool has_dismiss_button,
-                     const std::u16string& custom_dismiss_text)
+                     const std::u16string& custom_dismiss_text,
+                     base::RepeatingClosure dismiss_callback)
     : id(std::move(id)),
       catalog_name(catalog_name),
       text(text),
       duration(std::max(duration, kMinimumDuration)),
       visible_on_lock_screen(visible_on_lock_screen),
       dismiss_text(GetDismissText(custom_dismiss_text, has_dismiss_button)),
+      dismiss_callback(std::move(dismiss_callback)),
       time_created(base::TimeTicks::Now()) {}
 
 ToastData::ToastData(ToastData&& other) = default;
diff --git a/ash/public/cpp/system/toast_data.h b/ash/public/cpp/system/toast_data.h
index 9dedbe0..6a6f9fe 100644
--- a/ash/public/cpp/system/toast_data.h
+++ b/ash/public/cpp/system/toast_data.h
@@ -41,7 +41,8 @@
             base::TimeDelta duration = kDefaultToastDuration,
             bool visible_on_lock_screen = false,
             bool has_dismiss_button = false,
-            const std::u16string& custom_dismiss_text = std::u16string());
+            const std::u16string& custom_dismiss_text = std::u16string(),
+            base::RepeatingClosure dismiss_callback = base::RepeatingClosure());
   ToastData(ToastData&& other);
   ToastData& operator=(ToastData&& other);
   ~ToastData();
diff --git a/ash/shelf/shelf_party_feature_pod_controller_unittest.cc b/ash/shelf/shelf_party_feature_pod_controller_unittest.cc
index 5cc4ec7..43caf36 100644
--- a/ash/shelf/shelf_party_feature_pod_controller_unittest.cc
+++ b/ash/shelf/shelf_party_feature_pod_controller_unittest.cc
@@ -27,12 +27,10 @@
   ShelfPartyFeaturePodControllerTest() {
     if (IsQsRevampEnabled()) {
       feature_list_.InitWithFeatures(
-          {features::kShelfParty, features::kQsRevamp, features::kQsRevampWip},
-          {});
+          {features::kShelfParty, features::kQsRevamp}, {});
     } else {
-      feature_list_.InitWithFeatures(
-          {features::kShelfParty},
-          {features::kQsRevamp, features::kQsRevampWip});
+      feature_list_.InitWithFeatures({features::kShelfParty},
+                                     {features::kQsRevamp});
     }
   }
 
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index 4c0e2dd..b6a3f331 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -1515,7 +1515,7 @@
                              : kDragAndDropProxyScale;
     drag_icon_proxy_ = std::make_unique<AppDragIconProxy>(
         root_window, drag_view_->GetIconImage(), screen_location,
-        gfx::Vector2d(), scale_factor, /*use_blurred_background=*/false);
+        gfx::Vector2d(), scale_factor, /*is_folder_icon=*/false);
 
     if (pointer == MOUSE) {
       haptics_util::PlayHapticTouchpadEffect(
@@ -1674,7 +1674,7 @@
             root_window, drag_view_->GetIconImage(), screen_location,
             /*cursor_offset_from_center=*/gfx::Vector2d(),
             /*scale_factor=*/1.0f,
-            /*use_blurred_background=*/false);
+            /*is_folder_icon=*/false);
       }
 
       // Re-insert the item and return simply false since the caller will handle
@@ -1707,7 +1707,7 @@
       drag_icon_proxy_ = std::make_unique<AppDragIconProxy>(
           root_window, drag_view_->GetIconImage(), screen_location,
           cursor_offset_from_center, /*scale_factor=*/1.0f,
-          /*use_blurred_background=*/false);
+          /*is_folder_icon=*/false);
       delegate_->CancelScrollForItemDrag();
     }
 
diff --git a/ash/system/accessibility/accessibility_detailed_view_unittest.cc b/ash/system/accessibility/accessibility_detailed_view_unittest.cc
index 065b380..7f8d848 100644
--- a/ash/system/accessibility/accessibility_detailed_view_unittest.cc
+++ b/ash/system/accessibility/accessibility_detailed_view_unittest.cc
@@ -130,8 +130,9 @@
 // toggled.
 bool IsToggleButtonToggled(HoverHighlightView* item) {
   views::View* right_view = item->right_view();
-  if (!views::IsViewClass<TrayToggleButton>(right_view))
+  if (!views::IsViewClass<TrayToggleButton>(right_view)) {
     return false;
+  }
   return static_cast<TrayToggleButton*>(right_view)->GetIsOn();
 }
 
@@ -542,8 +543,9 @@
     // UnifiedAccessibilityDetailedViewController calls
     // AccessibilityDetailedView::OnAccessibilityStatusChanged. Spoof that
     // by calling it directly here.
-    if (detailed_menu_)
+    if (detailed_menu_) {
       detailed_menu_->OnAccessibilityStatusChanged();
+    }
   }
 
   AccessibilityControllerImpl* controller_ = nullptr;
@@ -557,8 +559,7 @@
     : public AccessibilityDetailedViewTest {
  public:
   AccessibilityDetailedViewQsRevampTest() {
-    feature_list_.InitWithFeatures(
-        {features::kQsRevamp, features::kQsRevampWip}, {});
+    feature_list_.InitAndEnableFeature(features::kQsRevamp);
   }
 
  private:
@@ -1160,8 +1161,9 @@
     // calling speech::SodaInstaller::GetInstance() returns a valid instance.
     std::vector<base::test::FeatureRef> enabled_features(
         {ash::features::kOnDeviceSpeechRecognition});
-    if (GetParam() == SodaFeature::kLiveCaption)
+    if (GetParam() == SodaFeature::kLiveCaption) {
       enabled_features.push_back(media::kLiveCaptionMultiLanguage);
+    }
     scoped_feature_list_.InitWithFeatures(enabled_features, {});
     soda_installer_impl_ =
         std::make_unique<speech::SodaInstallerImplChromeOS>();
diff --git a/ash/system/audio/unified_audio_detailed_view_controller_unittest.cc b/ash/system/audio/unified_audio_detailed_view_controller_unittest.cc
index a481194c..9742985 100644
--- a/ash/system/audio/unified_audio_detailed_view_controller_unittest.cc
+++ b/ash/system/audio/unified_audio_detailed_view_controller_unittest.cc
@@ -134,8 +134,7 @@
   // AshTestBase:
   void SetUp() override {
     if (IsQsRevampEnabled()) {
-      scoped_feature_list_.InitWithFeatures(
-          {features::kQsRevamp, features::kQsRevampWip}, {});
+      scoped_feature_list_.InitAndEnableFeature(features::kQsRevamp);
     }
     AshTestBase::SetUp();
 
@@ -430,8 +429,7 @@
   } else {
     scoped_feature_list_.InitWithFeatures(
         {media::kLiveCaption, media::kLiveCaptionSystemWideOnChromeOS,
-         ash::features::kOnDeviceSpeechRecognition, features::kQsRevamp,
-         features::kQsRevampWip},
+         ash::features::kOnDeviceSpeechRecognition, features::kQsRevamp},
         {});
   }
 
diff --git a/ash/system/audio/unified_volume_view_unittest.cc b/ash/system/audio/unified_volume_view_unittest.cc
index f5e18ff55..bf43cfd9 100644
--- a/ash/system/audio/unified_volume_view_unittest.cc
+++ b/ash/system/audio/unified_volume_view_unittest.cc
@@ -31,8 +31,7 @@
   ~UnifiedVolumeViewTest() override = default;
 
   void SetUp() override {
-    feature_list_.InitWithFeatures(
-        {features::kQsRevamp, features::kQsRevampWip}, {});
+    feature_list_.InitAndEnableFeature(features::kQsRevamp);
     AshTestBase::SetUp();
     GetPrimaryUnifiedSystemTray()->ShowBubble();
   }
diff --git a/ash/system/bluetooth/bluetooth_detailed_view_legacy_pixeltest.cc b/ash/system/bluetooth/bluetooth_detailed_view_legacy_pixeltest.cc
index 33ca8d1..7e0a848 100644
--- a/ash/system/bluetooth/bluetooth_detailed_view_legacy_pixeltest.cc
+++ b/ash/system/bluetooth/bluetooth_detailed_view_legacy_pixeltest.cc
@@ -45,9 +45,7 @@
 class BluetoothDetailedViewLegacyPixelTest : public AshTestBase {
  public:
   BluetoothDetailedViewLegacyPixelTest() {
-    feature_list_.InitWithFeatures(
-        /*enabled_features=*/{},
-        /*disabled_features=*/{features::kQsRevamp, features::kQsRevampWip});
+    feature_list_.InitAndDisableFeature(features::kQsRevamp);
   }
 
   // AshTestBase:
diff --git a/ash/system/bluetooth/bluetooth_feature_pod_controller_unittest.cc b/ash/system/bluetooth/bluetooth_feature_pod_controller_unittest.cc
index d9d6586..fb587243 100644
--- a/ash/system/bluetooth/bluetooth_feature_pod_controller_unittest.cc
+++ b/ash/system/bluetooth/bluetooth_feature_pod_controller_unittest.cc
@@ -65,11 +65,9 @@
  public:
   BluetoothFeaturePodControllerTest() {
     if (IsQsRevampEnabled()) {
-      feature_list_.InitWithFeatures(
-          {features::kQsRevamp, features::kQsRevampWip}, {});
+      feature_list_.InitAndEnableFeature(features::kQsRevamp);
     } else {
-      feature_list_.InitWithFeatures(
-          {}, {features::kQsRevamp, features::kQsRevampWip});
+      feature_list_.InitAndDisableFeature(features::kQsRevamp);
     }
   }
 
diff --git a/ash/system/brightness/unified_brightness_view_unittest.cc b/ash/system/brightness/unified_brightness_view_unittest.cc
index 4c802cb..6e971211 100644
--- a/ash/system/brightness/unified_brightness_view_unittest.cc
+++ b/ash/system/brightness/unified_brightness_view_unittest.cc
@@ -29,8 +29,7 @@
   ~UnifiedBrightnessViewTest() override = default;
 
   void SetUp() override {
-    feature_list_.InitWithFeatures(
-        {features::kQsRevamp, features::kQsRevampWip}, {});
+    feature_list_.InitAndEnableFeature(features::kQsRevamp);
     AshTestBase::SetUp();
     GetPrimaryUnifiedSystemTray()->ShowBubble();
     brightness_slider_controller_ =
diff --git a/ash/system/camera/autozoom_feature_pod_controller_unittest.cc b/ash/system/camera/autozoom_feature_pod_controller_unittest.cc
index cc9d579..73c4c3a 100644
--- a/ash/system/camera/autozoom_feature_pod_controller_unittest.cc
+++ b/ash/system/camera/autozoom_feature_pod_controller_unittest.cc
@@ -25,11 +25,9 @@
  public:
   AutozoomFeaturePodControllerTest() {
     if (IsQsRevampEnabled()) {
-      feature_list_.InitWithFeatures(
-          {features::kQsRevamp, features::kQsRevampWip}, {});
+      feature_list_.InitAndEnableFeature(features::kQsRevamp);
     } else {
-      feature_list_.InitWithFeatures(
-          {}, {features::kQsRevamp, features::kQsRevampWip});
+      feature_list_.InitAndDisableFeature(features::kQsRevamp);
     }
   }
 
diff --git a/ash/system/cast/cast_feature_pod_controller_unittest.cc b/ash/system/cast/cast_feature_pod_controller_unittest.cc
index 967ee67..59dae6f 100644
--- a/ash/system/cast/cast_feature_pod_controller_unittest.cc
+++ b/ash/system/cast/cast_feature_pod_controller_unittest.cc
@@ -49,9 +49,7 @@
 class CastFeaturePodControllerTest : public AshTestBase {
  public:
   CastFeaturePodControllerTest() {
-    feature_list_.InitWithFeatures(
-        /*enabled_features=*/{features::kQsRevamp, features::kQsRevampWip},
-        /*disabled_features=*/{});
+    feature_list_.InitAndEnableFeature(features::kQsRevamp);
   }
 
   // AshTestBase:
diff --git a/ash/system/cast/tray_cast_unittest.cc b/ash/system/cast/tray_cast_unittest.cc
index 30c85d1..4a85ebc8 100644
--- a/ash/system/cast/tray_cast_unittest.cc
+++ b/ash/system/cast/tray_cast_unittest.cc
@@ -63,9 +63,7 @@
 class CastDetailedViewTest : public AshTestBase {
  public:
   CastDetailedViewTest() {
-    feature_list_.InitWithFeatures(
-        /*enabled_features=*/{features::kQsRevamp, features::kQsRevampWip},
-        /*disabled_features=*/{});
+    feature_list_.InitAndEnableFeature(features::kQsRevamp);
   }
 
   // AshTestBase:
@@ -88,8 +86,9 @@
 
   std::vector<views::View*> GetDeviceViews() {
     std::vector<views::View*> views;
-    for (const auto& it : detailed_view_->view_to_sink_map_)
+    for (const auto& it : detailed_view_->view_to_sink_map_) {
       views.push_back(it.first);
+    }
     return views;
   }
 
diff --git a/ash/system/channel_indicator/channel_indicator_quick_settings_view_unittest.cc b/ash/system/channel_indicator/channel_indicator_quick_settings_view_unittest.cc
index 05f4b35..f6c6562 100644
--- a/ash/system/channel_indicator/channel_indicator_quick_settings_view_unittest.cc
+++ b/ash/system/channel_indicator/channel_indicator_quick_settings_view_unittest.cc
@@ -23,8 +23,7 @@
   ChannelIndicatorQuickSettingsViewTest() {
     // Param 0 is whether QsRevamp is enabled.
     if (std::get<0>(GetParam())) {
-      feature_list_.InitWithFeatures(
-          {features::kQsRevamp, features::kQsRevampWip}, {});
+      feature_list_.InitAndEnableFeature(features::kQsRevamp);
     }
   }
   ChannelIndicatorQuickSettingsViewTest(
diff --git a/ash/system/do_not_disturb_notification_controller_unittest.cc b/ash/system/do_not_disturb_notification_controller_unittest.cc
index bb0051a..80e1f99 100644
--- a/ash/system/do_not_disturb_notification_controller_unittest.cc
+++ b/ash/system/do_not_disturb_notification_controller_unittest.cc
@@ -30,8 +30,7 @@
 
   void SetUp() override {
     if (IsQsRevampEnabled()) {
-      scoped_feature_list_.InitWithFeatures(
-          {features::kQsRevamp, features::kQsRevampWip}, {});
+      scoped_feature_list_.InitAndEnableFeature(features::kQsRevamp);
     }
     AshTestBase::SetUp();
   }
diff --git a/ash/system/ime/ime_feature_pod_controller_unittest.cc b/ash/system/ime/ime_feature_pod_controller_unittest.cc
index 63bad7e..1c1615d6 100644
--- a/ash/system/ime/ime_feature_pod_controller_unittest.cc
+++ b/ash/system/ime/ime_feature_pod_controller_unittest.cc
@@ -30,11 +30,9 @@
  public:
   IMEFeaturePodControllerTest() {
     if (IsQsRevampEnabled()) {
-      feature_list_.InitWithFeatures(
-          {features::kQsRevamp, features::kQsRevampWip}, {});
+      feature_list_.InitAndEnableFeature(features::kQsRevamp);
     } else {
-      feature_list_.InitWithFeatures(
-          {}, {features::kQsRevamp, features::kQsRevampWip});
+      feature_list_.InitAndDisableFeature(features::kQsRevamp);
     }
   }
 
@@ -97,19 +95,22 @@
   // Creates |count| simulated active IMEs.
   void SetActiveIMECount(int count) {
     available_imes_.resize(count);
-    for (int i = 0; i < count; ++i)
+    for (int i = 0; i < count; ++i) {
       available_imes_[i].id = base::NumberToString(i);
+    }
     RefreshImeController();
   }
 
   void RefreshImeController() {
     std::vector<ImeInfo> available_imes;
-    for (const auto& ime : available_imes_)
+    for (const auto& ime : available_imes_) {
       available_imes.push_back(ime);
+    }
 
     std::vector<ImeMenuItem> menu_items;
-    for (const auto& item : menu_items_)
+    for (const auto& item : menu_items_) {
       menu_items_.push_back(item);
+    }
 
     Shell::Get()->ime_controller()->RefreshIme(
         current_ime_.id, std::move(available_imes), std::move(menu_items));
diff --git a/ash/system/ime_menu/ime_menu_tray_unittest.cc b/ash/system/ime_menu/ime_menu_tray_unittest.cc
index 06ff4834c..45c3349e 100644
--- a/ash/system/ime_menu/ime_menu_tray_unittest.cc
+++ b/ash/system/ime_menu/ime_menu_tray_unittest.cc
@@ -76,10 +76,8 @@
     std::vector<base::test::FeatureRef> disabled_features;
     if (GetParam()) {
       enabled_features.push_back(features::kQsRevamp);
-      enabled_features.push_back(features::kQsRevampWip);
     } else {
       disabled_features.push_back(features::kQsRevamp);
-      disabled_features.push_back(features::kQsRevampWip);
     }
     scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
     AshTestBase::SetUp();
diff --git a/ash/system/locale/locale_detailed_view_unittest.cc b/ash/system/locale/locale_detailed_view_unittest.cc
index 47c5994..79d441c 100644
--- a/ash/system/locale/locale_detailed_view_unittest.cc
+++ b/ash/system/locale/locale_detailed_view_unittest.cc
@@ -25,8 +25,7 @@
 class LocaleDetailedViewTest : public AshTestBase {
  public:
   LocaleDetailedViewTest() {
-    feature_list_.InitWithFeatures(
-        {features::kQsRevamp, features::kQsRevampWip}, {});
+    feature_list_.InitAndEnableFeature(features::kQsRevamp);
   }
 
   void CreateDetailedView() {
diff --git a/ash/system/locale/locale_feature_pod_controller_unittest.cc b/ash/system/locale/locale_feature_pod_controller_unittest.cc
index 663d45f..ea16011f 100644
--- a/ash/system/locale/locale_feature_pod_controller_unittest.cc
+++ b/ash/system/locale/locale_feature_pod_controller_unittest.cc
@@ -31,11 +31,9 @@
  public:
   LocaleFeaturePodControllerTest() {
     if (IsQsRevampEnabled()) {
-      feature_list_.InitWithFeatures(
-          {features::kQsRevamp, features::kQsRevampWip}, {});
+      feature_list_.InitAndEnableFeature(features::kQsRevamp);
     } else {
-      feature_list_.InitWithFeatures(
-          {}, {features::kQsRevamp, features::kQsRevampWip});
+      feature_list_.InitAndDisableFeature(features::kQsRevamp);
     }
   }
 
diff --git a/ash/system/message_center/notification_grouping_controller_unittest.cc b/ash/system/message_center/notification_grouping_controller_unittest.cc
index 6233a03..5a2109c 100644
--- a/ash/system/message_center/notification_grouping_controller_unittest.cc
+++ b/ash/system/message_center/notification_grouping_controller_unittest.cc
@@ -49,13 +49,9 @@
 
   void SetUp() override {
     if (IsQsRevampEnabled()) {
-      scoped_feature_list_.InitWithFeatures(
-          /*enabled_features=*/{features::kQsRevamp, features::kQsRevampWip},
-          /*disabled_features=*/{});
+      scoped_feature_list_.InitAndEnableFeature(features::kQsRevamp);
     } else {
-      scoped_feature_list_.InitWithFeatures(
-          /*enabled_features=*/{},
-          /*disabled_features=*/{features::kQsRevamp, features::kQsRevampWip});
+      scoped_feature_list_.InitAndDisableFeature(features::kQsRevamp);
     }
 
     AshTestBase::SetUp();
diff --git a/ash/system/network/network_detailed_view_controller.cc b/ash/system/network/network_detailed_view_controller.cc
index a0afefb..6654804 100644
--- a/ash/system/network/network_detailed_view_controller.cc
+++ b/ash/system/network/network_detailed_view_controller.cc
@@ -174,13 +174,11 @@
       return;
     }
 
-    // If the captive portal UI flag is enabled, the user is logged in, the
-    // network is connected, and the network is in a portal or proxy state, the
-    // user is shown the portal signin. We do not show portal sign in for user
-    // not logged in because it is the only way for the user to get to the
-    // network details page.
-    if (features::IsCaptivePortalUI2022Enabled() &&
-        Shell::Get()->session_controller()->login_status() !=
+    // If user is logged in, the network is connected, and the network is in a
+    // portal or proxy state, the user is shown the portal signin. We do not
+    // show portal sign in for user not logged in because it is the only way for
+    // the user to get to the network details page.
+    if (Shell::Get()->session_controller()->login_status() !=
             LoginStatus::NOT_LOGGED_IN &&
         chromeos::network_config::StateIsConnected(network->connection_state) &&
         IsNetworkBehindPortalOrProxy(network->portal_state)) {
diff --git a/ash/system/network/network_detailed_view_controller_unittest.cc b/ash/system/network/network_detailed_view_controller_unittest.cc
index c0ba0bfe..70f49cc 100644
--- a/ash/system/network/network_detailed_view_controller_unittest.cc
+++ b/ash/system/network/network_detailed_view_controller_unittest.cc
@@ -613,8 +613,7 @@
        PortalNetworkListItemSelectedWithFlagEnabled) {
   feature_list_.Reset();
   feature_list_.InitWithFeatures(
-      /*enabled_features=*/{features::kCaptivePortalUI2022,
-                            features::kQuickSettingsNetworkRevamp},
+      /*enabled_features=*/{features::kQuickSettingsNetworkRevamp},
       /*disabled_features=*/{});
 
   AddWifiService(shill::kStateRedirectFound);
diff --git a/ash/system/network/network_feature_pod_controller_unittest.cc b/ash/system/network/network_feature_pod_controller_unittest.cc
index e95045b8..4f6ab6d 100644
--- a/ash/system/network/network_feature_pod_controller_unittest.cc
+++ b/ash/system/network/network_feature_pod_controller_unittest.cc
@@ -96,13 +96,10 @@
     auto disabled_features = std::vector<base::test::FeatureRef>();
     enabled_features.push_back(features::kQuickSettingsNetworkRevamp);
     if (IsQsRevampEnabled()) {
-      enabled_features.push_back(features::kQsRevamp);
-      enabled_features.push_back(features::kQsRevampWip);
+      feature_list_.InitAndEnableFeature(features::kQsRevamp);
     } else {
-      disabled_features.push_back(features::kQsRevamp);
-      disabled_features.push_back(features::kQsRevampWip);
+      feature_list_.InitAndDisableFeature(features::kQsRevamp);
     }
-    feature_list_.InitWithFeatures(enabled_features, disabled_features);
 
     AshTestBase::SetUp();
 
diff --git a/ash/system/network/network_list_network_item_view.cc b/ash/system/network/network_list_network_item_view.cc
index 70252ec..a14e153 100644
--- a/ash/system/network/network_list_network_item_view.cc
+++ b/ash/system/network/network_list_network_item_view.cc
@@ -317,13 +317,11 @@
     return;
   }
 
-  if (ash::features::IsCaptivePortalUI2022Enabled()) {
-    absl::optional<std::u16string> portal_subtext =
-        GetPortalStateSubtext(network_properties()->portal_state);
-    if (portal_subtext) {
-      SetWarningSubText(this, *portal_subtext);
-      return;
-    }
+  absl::optional<std::u16string> portal_subtext =
+      GetPortalStateSubtext(network_properties()->portal_state);
+  if (portal_subtext) {
+    SetWarningSubText(this, *portal_subtext);
+    return;
   }
 
   SetupConnectedScrollListItem(this);
diff --git a/ash/system/network/network_list_network_item_view_unittest.cc b/ash/system/network/network_list_network_item_view_unittest.cc
index 505a23b..b4824ec 100644
--- a/ash/system/network/network_list_network_item_view_unittest.cc
+++ b/ash/system/network/network_list_network_item_view_unittest.cc
@@ -68,9 +68,7 @@
   void SetUp() override {
     AshTestBase::SetUp();
 
-    feature_list_.InitWithFeatures(
-        /*enabled_features=*/{features::kQuickSettingsNetworkRevamp},
-        /*disabled_features=*/{features::kCaptivePortalUI2022});
+    feature_list_.InitAndEnableFeature(features::kQuickSettingsNetworkRevamp);
 
     SetUpDefaultNetworkDevices();
 
@@ -279,24 +277,9 @@
 }
 
 TEST_F(NetworkListNetworkItemViewTest, HasCorrectPortalSublabel) {
-  EXPECT_FALSE(network_list_network_item_view()->sub_text_label());
-
-  NetworkStatePropertiesPtr wifi_network = CreateStandaloneNetworkProperties(
-      kWiFiName, NetworkType::kWiFi, ConnectionStateType::kPortal);
-  wifi_network->portal_state = PortalState::kPortal;
-
-  UpdateViewForNetwork(wifi_network);
-  EXPECT_TRUE(network_list_network_item_view()->sub_text_label());
-  EXPECT_EQ(
-      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTED),
-      network_list_network_item_view()->sub_text_label()->GetText());
-}
-
-TEST_F(NetworkListNetworkItemViewTest, HasCorrectPortalSublabelWithFlag) {
   feature_list_.Reset();
   feature_list_.InitWithFeatures(
-      /*enabled_features=*/{features::kCaptivePortalUI2022,
-                            features::kQuickSettingsNetworkRevamp},
+      /*enabled_features=*/{features::kQuickSettingsNetworkRevamp},
       /*disabled_features=*/{});
   EXPECT_FALSE(network_list_network_item_view()->sub_text_label());
 
@@ -311,11 +294,10 @@
       network_list_network_item_view()->sub_text_label()->GetText());
 }
 
-TEST_F(NetworkListNetworkItemViewTest, HasCorrectProxyAuthSublabelWithFlag) {
+TEST_F(NetworkListNetworkItemViewTest, HasCorrectProxyAuthSublabel) {
   feature_list_.Reset();
   feature_list_.InitWithFeatures(
-      /*enabled_features=*/{features::kCaptivePortalUI2022,
-                            features::kQuickSettingsNetworkRevamp},
+      /*enabled_features=*/{features::kQuickSettingsNetworkRevamp},
       /*disabled_features=*/{});
   EXPECT_FALSE(network_list_network_item_view()->sub_text_label());
 
@@ -330,12 +312,10 @@
       network_list_network_item_view()->sub_text_label()->GetText());
 }
 
-TEST_F(NetworkListNetworkItemViewTest,
-       HasCorrectPortalSuspectedSublabelWithFlag) {
+TEST_F(NetworkListNetworkItemViewTest, HasCorrectPortalSuspectedSublabel) {
   feature_list_.Reset();
   feature_list_.InitWithFeatures(
-      /*enabled_features=*/{features::kCaptivePortalUI2022,
-                            features::kQuickSettingsNetworkRevamp},
+      /*enabled_features=*/{features::kQuickSettingsNetworkRevamp},
       /*disabled_features=*/{});
   EXPECT_FALSE(network_list_network_item_view()->sub_text_label());
 
@@ -350,12 +330,10 @@
             network_list_network_item_view()->sub_text_label()->GetText());
 }
 
-TEST_F(NetworkListNetworkItemViewTest,
-       HasCorrectNoConnectivitySublabelWithFlag) {
+TEST_F(NetworkListNetworkItemViewTest, HasCorrectNoConnectivitySublabel) {
   feature_list_.Reset();
   feature_list_.InitWithFeatures(
-      /*enabled_features=*/{features::kCaptivePortalUI2022,
-                            features::kQuickSettingsNetworkRevamp},
+      /*enabled_features=*/{features::kQuickSettingsNetworkRevamp},
       /*disabled_features=*/{});
   EXPECT_FALSE(network_list_network_item_view()->sub_text_label());
 
@@ -695,95 +673,6 @@
 
     for (const auto& connection : GetConnectionStateTypes()) {
       wifi_network->connection_state = connection;
-      std::u16string connection_status;
-      for (const auto& policy : GetPolicies()) {
-        wifi_network->source = policy;
-        switch (connection) {
-          case ConnectionStateType::kConnected:
-          case ConnectionStateType::kPortal:
-          case ConnectionStateType::kOnline: {
-            connection_status = l10n_util::GetStringUTF16(
-                IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTED);
-            if (policy == OncSource::kDevicePolicy) {
-              AssertA11yDescription(
-                  wifi_network,
-                  l10n_util::GetStringFUTF16(
-                      IDS_ASH_STATUS_TRAY_WIFI_NETWORK_A11Y_DESC_MANAGED_WITH_CONNECTION_STATUS,
-                      security_label, connection_status,
-                      base::FormatPercent(kSignalStrength)));
-
-            } else {
-              AssertA11yDescription(
-                  wifi_network,
-                  l10n_util::GetStringFUTF16(
-                      IDS_ASH_STATUS_TRAY_WIFI_NETWORK_A11Y_DESC_WITH_CONNECTION_STATUS,
-                      security_label, connection_status,
-                      base::FormatPercent(kSignalStrength)));
-            }
-            break;
-          }
-          case ConnectionStateType::kConnecting: {
-            connection_status = l10n_util::GetStringUTF16(
-                IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTING);
-            if (policy == OncSource::kDevicePolicy) {
-              AssertA11yDescription(
-                  wifi_network,
-                  l10n_util::GetStringFUTF16(
-                      IDS_ASH_STATUS_TRAY_WIFI_NETWORK_A11Y_DESC_MANAGED_WITH_CONNECTION_STATUS,
-                      security_label, connection_status,
-                      base::FormatPercent(kSignalStrength)));
-
-            } else {
-              AssertA11yDescription(
-                  wifi_network,
-                  l10n_util::GetStringFUTF16(
-                      IDS_ASH_STATUS_TRAY_WIFI_NETWORK_A11Y_DESC_WITH_CONNECTION_STATUS,
-                      security_label, connection_status,
-                      base::FormatPercent(kSignalStrength)));
-            }
-            break;
-          }
-          case ConnectionStateType::kNotConnected:
-            if (policy == OncSource::kDevicePolicy) {
-              AssertA11yDescription(
-                  wifi_network,
-                  l10n_util::GetStringFUTF16(
-                      IDS_ASH_STATUS_TRAY_WIFI_NETWORK_A11Y_DESC_MANAGED,
-                      security_label, base::FormatPercent(kSignalStrength)));
-            } else {
-              AssertA11yDescription(
-                  wifi_network,
-                  l10n_util::GetStringFUTF16(
-                      IDS_ASH_STATUS_TRAY_WIFI_NETWORK_A11Y_DESC,
-                      security_label, base::FormatPercent(kSignalStrength)));
-            }
-        }
-      }
-    }
-  }
-}
-
-TEST_F(NetworkListNetworkItemViewTest, HasExpectedDescriptionForWiFiWithFlag) {
-  feature_list_.Reset();
-  feature_list_.InitWithFeatures(
-      /*enabled_features=*/{features::kCaptivePortalUI2022,
-                            features::kQuickSettingsNetworkRevamp},
-      /*disabled_features=*/{});
-
-  SecurityType security_types[2] = {SecurityType::kNone, SecurityType::kWepPsk};
-
-  NetworkStatePropertiesPtr wifi_network = CreateStandaloneNetworkProperties(
-      kWiFiName, NetworkType::kWiFi, ConnectionStateType::kConnected);
-
-  for (const auto& security : security_types) {
-    wifi_network->type_state->get_wifi()->security = security;
-    const std::u16string security_label = l10n_util::GetStringUTF16(
-        security == SecurityType::kWepPsk
-            ? IDS_ASH_STATUS_TRAY_NETWORK_STATUS_SECURED
-            : IDS_ASH_STATUS_TRAY_NETWORK_STATUS_UNSECURED);
-
-    for (const auto& connection : GetConnectionStateTypes()) {
-      wifi_network->connection_state = connection;
       wifi_network->portal_state = PortalState::kUnknown;  // default
       std::u16string connection_status;
       int desc_id;
diff --git a/ash/system/network/network_list_view_controller_unittest.cc b/ash/system/network/network_list_view_controller_unittest.cc
index f5aec8e..332ed93 100644
--- a/ash/system/network/network_list_view_controller_unittest.cc
+++ b/ash/system/network/network_list_view_controller_unittest.cc
@@ -203,9 +203,7 @@
   void SetUp() override {
     if (IsQsRevampEnabled()) {
       feature_list_.InitWithFeatures(
-          {features::kQsRevamp, features::kQsRevampWip,
-           features::kQuickSettingsNetworkRevamp},
-          {});
+          {features::kQsRevamp, features::kQuickSettingsNetworkRevamp}, {});
     } else {
       feature_list_.InitAndEnableFeature(features::kQuickSettingsNetworkRevamp);
     }
diff --git a/ash/system/network/network_utils.cc b/ash/system/network/network_utils.cc
index 66675f8..2ca6ee8 100644
--- a/ash/system/network/network_utils.cc
+++ b/ash/system/network/network_utils.cc
@@ -64,9 +64,6 @@
 
 absl::optional<std::u16string> GetPortalStateSubtext(
     const chromeos::network_config::mojom::PortalState& portal_state) {
-  if (!ash::features::IsCaptivePortalUI2022Enabled()) {
-    return absl::nullopt;
-  }
   using chromeos::network_config::mojom::PortalState;
   switch (portal_state) {
     case PortalState::kUnknown:
diff --git a/ash/system/network/vpn_feature_pod_controller_unittest.cc b/ash/system/network/vpn_feature_pod_controller_unittest.cc
index 0db066e..0c05538 100644
--- a/ash/system/network/vpn_feature_pod_controller_unittest.cc
+++ b/ash/system/network/vpn_feature_pod_controller_unittest.cc
@@ -34,9 +34,7 @@
 class VPNFeaturePodControllerTest : public AshTestBase {
  public:
   VPNFeaturePodControllerTest() {
-    feature_list_.InitWithFeatures(
-        /*enabled_features=*/{features::kQsRevamp, features::kQsRevampWip},
-        /*disabled_features=*/{});
+    feature_list_.InitAndEnableFeature(features::kQsRevamp);
   }
 
   // AshTestBase:
diff --git a/ash/system/network/vpn_list_view_unittest.cc b/ash/system/network/vpn_list_view_unittest.cc
index 8cdeff5..ac6554e 100644
--- a/ash/system/network/vpn_list_view_unittest.cc
+++ b/ash/system/network/vpn_list_view_unittest.cc
@@ -42,11 +42,9 @@
  public:
   VPNListViewTest() {
     if (IsQsRevampEnabled()) {
-      feature_list_.InitWithFeatures(
-          {features::kQsRevamp, features::kQsRevampWip}, {});
+      feature_list_.InitAndEnableFeature(features::kQsRevamp);
     } else {
-      feature_list_.InitWithFeatures(
-          {}, {features::kQsRevamp, features::kQsRevampWip});
+      feature_list_.InitAndDisableFeature(features::kQsRevamp);
     }
   }
 
@@ -117,38 +115,43 @@
 
   std::vector<const views::View*> GetProviderViews() {
     std::vector<const views::View*> views;
-    for (const auto& it : vpn_list_view_->provider_view_map_)
+    for (const auto& it : vpn_list_view_->provider_view_map_) {
       views.push_back(it.first);
+    }
     return views;
   }
 
   std::vector<const views::View*> GetNetworkViews() {
     std::vector<const views::View*> views;
-    for (const auto& it : vpn_list_view_->network_view_guid_map_)
+    for (const auto& it : vpn_list_view_->network_view_guid_map_) {
       views.push_back(it.first);
+    }
     return views;
   }
 
   const views::View* GetBuiltInProviderView() {
     for (const auto& it : vpn_list_view_->provider_view_map_) {
-      if (it.second->type == VpnType::kOpenVPN)
+      if (it.second->type == VpnType::kOpenVPN) {
         return it.first;
+      }
     }
     return nullptr;
   }
 
   const views::View* GetExtensionProviderView() {
     for (const auto& it : vpn_list_view_->provider_view_map_) {
-      if (it.second->type == VpnType::kExtension)
+      if (it.second->type == VpnType::kExtension) {
         return it.first;
+      }
     }
     return nullptr;
   }
 
   const views::View* GetArcProviderView() {
     for (const auto& it : vpn_list_view_->provider_view_map_) {
-      if (it.second->type == VpnType::kArc)
+      if (it.second->type == VpnType::kArc) {
         return it.first;
+      }
     }
     return nullptr;
   }
@@ -176,17 +179,19 @@
   AddVpnProvidersAndNetwork();
   for (const views::View* view : GetProviderViews()) {
     const views::View* parent = view->parent();
-    if (IsQsRevampEnabled())
+    if (IsQsRevampEnabled()) {
       EXPECT_STREQ(parent->GetClassName(), "RoundedContainer");
-    else
+    } else {
       EXPECT_STREQ(parent->GetClassName(), "ScrollContentsView");
+    }
   }
   for (const views::View* view : GetNetworkViews()) {
     const views::View* parent = view->parent();
-    if (IsQsRevampEnabled())
+    if (IsQsRevampEnabled()) {
       EXPECT_STREQ(parent->GetClassName(), "RoundedContainer");
-    else
+    } else {
       EXPECT_STREQ(parent->GetClassName(), "ScrollContentsView");
+    }
   }
 }
 
@@ -206,8 +211,9 @@
   EXPECT_TRUE(arc_provider->GetEnabled());
 
   // Only QsRevamp has clickable provider rows.
-  if (!IsQsRevampEnabled())
+  if (!IsQsRevampEnabled()) {
     return;
+  }
 
   // Clicking on the built-in provider row creates a built-in VPN network.
   LeftClickOn(built_in_provider);
diff --git a/ash/system/notification_center/notification_center_bubble_unittest.cc b/ash/system/notification_center/notification_center_bubble_unittest.cc
index 9cb5371..a6e7eb6 100644
--- a/ash/system/notification_center/notification_center_bubble_unittest.cc
+++ b/ash/system/notification_center/notification_center_bubble_unittest.cc
@@ -30,8 +30,7 @@
 
   void SetUp() override {
     // Enable quick settings revamp feature.
-    scoped_feature_list_.InitWithFeatures(
-        {features::kQsRevamp, features::kQsRevampWip}, {});
+    scoped_feature_list_.InitAndEnableFeature(features::kQsRevamp);
 
     AshTestBase::SetUp();
 
@@ -54,8 +53,9 @@
 
   // Add a large number of notifications to overflow the scroll view in the
   // notification center.
-  for (int i = 0; i < 100; i++)
+  for (int i = 0; i < 100; i++) {
     test_api()->AddNotification();
+  }
 
   // Show notification center bubble.
   test_api()->ToggleBubble();
@@ -71,8 +71,9 @@
 
   // Add a large number of notifications to overflow the scroll view in the
   // notification center.
-  for (int i = 0; i < 100; i++)
+  for (int i = 0; i < 100; i++) {
     test_api()->AddNotification();
+  }
 
   // Show notification center bubble.
   test_api()->ToggleBubble();
@@ -97,8 +98,9 @@
 
   // Add a large number of notifications to overflow the scroll view in the
   // notification center.
-  for (int i = 0; i < 100; i++)
+  for (int i = 0; i < 100; i++) {
     test_api()->AddNotification();
+  }
 
   // Show notification center bubble.
   test_api()->ToggleBubble();
diff --git a/ash/system/notification_center/notification_center_tray_unittest.cc b/ash/system/notification_center/notification_center_tray_unittest.cc
index 9d4366d..ca2f837 100644
--- a/ash/system/notification_center/notification_center_tray_unittest.cc
+++ b/ash/system/notification_center/notification_center_tray_unittest.cc
@@ -31,8 +31,7 @@
 
   void SetUp() override {
     // Enable quick settings revamp feature.
-    scoped_feature_list_.InitWithFeatures(
-        {features::kQsRevamp, features::kQsRevampWip}, {});
+    scoped_feature_list_.InitAndEnableFeature(features::kQsRevamp);
 
     AshTestBase::SetUp();
 
diff --git a/ash/system/notification_center/notification_center_view_unittest.cc b/ash/system/notification_center/notification_center_view_unittest.cc
index 2df70db..91f2e13 100644
--- a/ash/system/notification_center/notification_center_view_unittest.cc
+++ b/ash/system/notification_center/notification_center_view_unittest.cc
@@ -72,9 +72,7 @@
   void SetUp() override {
     scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
     if (IsQsRevampEnabled()) {
-      scoped_feature_list_->InitWithFeatures(
-          /*enabled_features=*/{features::kQsRevamp, features::kQsRevampWip},
-          /*disabled_features=*/{});
+      scoped_feature_list_->InitAndEnableFeature(features::kQsRevamp);
     }
 
     AshTestBase::SetUp();
diff --git a/ash/system/notification_center/notification_list_view_unittest.cc b/ash/system/notification_center/notification_list_view_unittest.cc
index f90f35b69..25e1eb4c 100644
--- a/ash/system/notification_center/notification_list_view_unittest.cc
+++ b/ash/system/notification_center/notification_list_view_unittest.cc
@@ -263,9 +263,7 @@
   void SetUp() override {
     scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
     if (IsQsRevampEnabled()) {
-      scoped_feature_list_->InitWithFeatures(
-          /*enabled_features=*/{features::kQsRevamp, features::kQsRevampWip},
-          /*disabled_features=*/{});
+      scoped_feature_list_->InitAndEnableFeature(features::kQsRevamp);
     }
 
     NotificationListViewTest::SetUp();
diff --git a/ash/system/phonehub/phone_hub_nudge.cc b/ash/system/phonehub/phone_hub_nudge.cc
new file mode 100644
index 0000000..0debc91
--- /dev/null
+++ b/ash/system/phonehub/phone_hub_nudge.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 "ash/system/phonehub/phone_hub_nudge.h"
+
+#include "ui/gfx/vector_icon_types.h"
+
+namespace ash {
+
+namespace {
+
+// The size of the icon.
+constexpr int kIconSize = 20;
+
+// The spacing between the icon and label in the nudge view.
+constexpr int kIconLabelSpacing = 16;
+
+// The padding which separates the nudge's border with its inner contents.
+constexpr int kNudgePadding = 16;
+
+// The minimum width of the label.
+constexpr int kMinLabelWidth = 200;
+
+constexpr char kPhoneHubNudgeName[] = "PhoneHubNudge";
+
+const gfx::VectorIcon kEmptyIcon;
+
+}  // namespace
+
+PhoneHubNudge::PhoneHubNudge(std::u16string nudge_content)
+    : SystemNudge(kPhoneHubNudgeName,
+                  NudgeCatalogName::kPhoneHub,
+                  kIconSize,
+                  kIconLabelSpacing,
+                  kNudgePadding),
+      nudge_content_(nudge_content) {}
+
+PhoneHubNudge::~PhoneHubNudge() = default;
+
+std::unique_ptr<SystemNudgeLabel> PhoneHubNudge::CreateLabelView() const {
+  return std::make_unique<SystemNudgeLabel>(nudge_content_, kMinLabelWidth);
+}
+
+// TODO (b/264715338) Polish Nudge.
+const gfx::VectorIcon& PhoneHubNudge::GetIcon() const {
+  return kEmptyIcon;
+}
+
+std::u16string PhoneHubNudge::GetAccessibilityText() const {
+  return nudge_content_;
+}
+
+}  // namespace ash
\ No newline at end of file
diff --git a/ash/system/phonehub/phone_hub_nudge.h b/ash/system/phonehub/phone_hub_nudge.h
new file mode 100644
index 0000000..b0f9024
--- /dev/null
+++ b/ash/system/phonehub/phone_hub_nudge.h
@@ -0,0 +1,34 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_SYSTEM_PHONEHUB_PHONE_HUB_NUDGE_H_
+#define ASH_SYSTEM_PHONEHUB_PHONE_HUB_NUDGE_H_
+
+#include "ash/ash_export.h"
+#include "ash/system/tray/system_nudge.h"
+
+namespace ash {
+
+// Implements an educational nudge to inform eligible users
+// of Phone Hub.
+class ASH_EXPORT PhoneHubNudge : public SystemNudge {
+ public:
+  explicit PhoneHubNudge(std::u16string nudge_content);
+  PhoneHubNudge(const PhoneHubNudge&) = delete;
+  PhoneHubNudge& operator=(const PhoneHubNudge&) = delete;
+  ~PhoneHubNudge() override;
+
+ protected:
+  // SystemNudge:
+  std::unique_ptr<SystemNudgeLabel> CreateLabelView() const override;
+  const gfx::VectorIcon& GetIcon() const override;
+  std::u16string GetAccessibilityText() const override;
+
+ private:
+  std::u16string nudge_content_;
+};
+
+}  // namespace ash
+
+#endif  // ASH_SYSTEM_PHONEHUB_PHONE_HUB_NUDGE_H_
\ No newline at end of file
diff --git a/ash/system/privacy_screen/privacy_screen_feature_pod_controller_unittest.cc b/ash/system/privacy_screen/privacy_screen_feature_pod_controller_unittest.cc
index c662ceb5..b3bcf43e 100644
--- a/ash/system/privacy_screen/privacy_screen_feature_pod_controller_unittest.cc
+++ b/ash/system/privacy_screen/privacy_screen_feature_pod_controller_unittest.cc
@@ -35,11 +35,9 @@
  public:
   PrivacyScreenFeaturePodControllerTest() {
     if (IsQsRevampEnabled()) {
-      feature_list_.InitWithFeatures(
-          {features::kQsRevamp, features::kQsRevampWip}, {});
+      feature_list_.InitAndEnableFeature(features::kQsRevamp);
     } else {
-      feature_list_.InitWithFeatures(
-          {}, {features::kQsRevamp, features::kQsRevampWip});
+      feature_list_.InitAndDisableFeature(features::kQsRevamp);
     }
   }
 
diff --git a/ash/system/rotation/rotation_lock_feature_pod_controller_unittest.cc b/ash/system/rotation/rotation_lock_feature_pod_controller_unittest.cc
index 0e72646b1..43f07275 100644
--- a/ash/system/rotation/rotation_lock_feature_pod_controller_unittest.cc
+++ b/ash/system/rotation/rotation_lock_feature_pod_controller_unittest.cc
@@ -22,8 +22,7 @@
  public:
   RotationLockFeaturePodControllerTest() {
     // Disable QsRevamp.
-    feature_list_.InitWithFeatures(
-        {}, {features::kQsRevamp, features::kQsRevampWip});
+    feature_list_.InitAndDisableFeature(features::kQsRevamp);
   }
 
   RotationLockFeaturePodControllerTest(
@@ -216,8 +215,7 @@
 class RotationLockFeaturePodControllerQsRevampTest : public AshTestBase {
  public:
   RotationLockFeaturePodControllerQsRevampTest() {
-    feature_list_.InitWithFeatures(
-        {features::kQsRevamp, features::kQsRevampWip}, {});
+    feature_list_.InitAndEnableFeature(features::kQsRevamp);
   }
 
   // AshTestBase:
diff --git a/ash/system/status_area_widget_unittest.cc b/ash/system/status_area_widget_unittest.cc
index 090973c..3c6b33a 100644
--- a/ash/system/status_area_widget_unittest.cc
+++ b/ash/system/status_area_widget_unittest.cc
@@ -639,8 +639,7 @@
 class StatusAreaWidgetQSRevampTest : public AshTestBase {
  protected:
   void SetUp() override {
-    scoped_feature_list_.InitWithFeatures(
-        {features::kQsRevamp, features::kQsRevampWip}, {});
+    scoped_feature_list_.InitAndEnableFeature(features::kQsRevamp);
     AshTestBase::SetUp();
   }
 
@@ -659,8 +658,7 @@
 // otherwise.
 TEST_F(StatusAreaWidgetQSRevampTest, DateTrayRoundedCornerBehavior) {
   base::test::ScopedFeatureList feature_list;
-  feature_list.InitWithFeatures({features::kQsRevamp, features::kQsRevampWip},
-                                {});
+  feature_list.InitAndEnableFeature(features::kQsRevamp);
 
   StatusAreaWidget* status_area =
       StatusAreaWidgetTestHelper::GetStatusAreaWidget();
diff --git a/ash/system/toast/toast_manager_impl.h b/ash/system/toast/toast_manager_impl.h
index 85900fe..874b9ca 100644
--- a/ash/system/toast/toast_manager_impl.h
+++ b/ash/system/toast/toast_manager_impl.h
@@ -63,6 +63,7 @@
   friend class BluetoothNotificationControllerTest;
   friend class DesksTestApi;
   friend class ToastManagerImplTest;
+  friend class ClipboardHistoryControllerRefreshTest;
   friend class eche_app::LaunchAppHelperTest;
 
   void ShowLatest();
diff --git a/ash/system/toast/toast_overlay.h b/ash/system/toast/toast_overlay.h
index c4c303fb..a23f22b 100644
--- a/ash/system/toast/toast_overlay.h
+++ b/ash/system/toast/toast_overlay.h
@@ -88,6 +88,7 @@
 
  private:
   friend class ToastManagerImplTest;
+  friend class ClipboardHistoryControllerRefreshTest;
   friend class DesksTestApi;
 
   class ToastDisplayObserver;
diff --git a/ash/system/unified/feature_tile_unittest.cc b/ash/system/unified/feature_tile_unittest.cc
index b697932..b632720 100644
--- a/ash/system/unified/feature_tile_unittest.cc
+++ b/ash/system/unified/feature_tile_unittest.cc
@@ -98,10 +98,7 @@
 
 class FeatureTileTest : public AshTestBase {
  public:
-  FeatureTileTest() {
-    feature_list_.InitWithFeatures(
-        {features::kQsRevamp, features::kQsRevampWip}, {});
-  }
+  FeatureTileTest() { feature_list_.InitAndEnableFeature(features::kQsRevamp); }
 
   FeatureTileTest(const FeatureTileTest&) = delete;
   FeatureTileTest& operator=(const FeatureTileTest&) = delete;
diff --git a/ash/system/unified/feature_tiles_container_view.cc b/ash/system/unified/feature_tiles_container_view.cc
index 202f37d..2f69586 100644
--- a/ash/system/unified/feature_tiles_container_view.cc
+++ b/ash/system/unified/feature_tiles_container_view.cc
@@ -118,7 +118,7 @@
   }
 
   for (auto& tile : tiles) {
-    if (create_row) {
+    if (create_row && (tile->GetVisible() || rows_.empty())) {
       int current_page_rows = pages_.back()->children().size();
       // Add a new page if we have reached the max displayable rows per page.
       if (current_page_rows == displayable_rows_) {
@@ -130,8 +130,9 @@
       create_row = false;
     }
     // Invisible tiles don't take any weight.
-    if (tile->GetVisible())
+    if (tile->GetVisible()) {
       row_weight += GetTileWeight(tile->tile_type());
+    }
     DCHECK_LE(row_weight, kMaxRowWeight);
     rows_.back()->AddChildView(std::move(tile));
 
@@ -168,6 +169,8 @@
 
   // Re-add tiles to container.
   AddTiles(std::move(tiles));
+
+  controller_->UpdateBubble();
 }
 
 void FeatureTilesContainerView::SetRowsFromHeight(int max_height) {
@@ -223,8 +226,9 @@
 
   // Uses the max number of rows with the space available.
   int rows = kFeatureTileMaxRows;
-  while (height < (rows * row_height) && rows > kFeatureTileMinRows)
+  while (height < (rows * row_height) && rows > kFeatureTileMinRows) {
     rows--;
+  }
   return rows;
 }
 
diff --git a/ash/system/unified/feature_tiles_container_view_unittest.cc b/ash/system/unified/feature_tiles_container_view_unittest.cc
index 901c8b0..f714597 100644
--- a/ash/system/unified/feature_tiles_container_view_unittest.cc
+++ b/ash/system/unified/feature_tiles_container_view_unittest.cc
@@ -69,8 +69,7 @@
                                       public views::ViewObserver {
  public:
   FeatureTilesContainerViewTest() {
-    feature_list_.InitWithFeatures(
-        {features::kQsRevamp, features::kQsRevampWip}, {});
+    feature_list_.InitAndEnableFeature(features::kQsRevamp);
   }
 
   FeatureTilesContainerViewTest(const FeatureTilesContainerViewTest&) = delete;
diff --git a/ash/system/unified/notification_counter_view_unittest.cc b/ash/system/unified/notification_counter_view_unittest.cc
index 8fe1b16..1300922 100644
--- a/ash/system/unified/notification_counter_view_unittest.cc
+++ b/ash/system/unified/notification_counter_view_unittest.cc
@@ -51,8 +51,7 @@
   void SetUp() override {
     scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
     if (IsQsRevampEnabled()) {
-      scoped_feature_list_->InitWithFeatures(
-          {features::kQsRevamp, features::kQsRevampWip}, {});
+      scoped_feature_list_->InitAndEnableFeature(features::kQsRevamp);
     }
 
     AshTestBase::SetUp();
diff --git a/ash/system/unified/notification_icons_controller_unittest.cc b/ash/system/unified/notification_icons_controller_unittest.cc
index fff080b..59c523b1 100644
--- a/ash/system/unified/notification_icons_controller_unittest.cc
+++ b/ash/system/unified/notification_icons_controller_unittest.cc
@@ -36,8 +36,7 @@
   void SetUp() override {
     scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
     if (IsQsRevampEnabled()) {
-      scoped_feature_list_->InitWithFeatures(
-          {features::kQsRevamp, features::kQsRevampWip}, {});
+      scoped_feature_list_->InitAndEnableFeature(features::kQsRevamp);
     }
 
     AshTestBase::SetUp();
@@ -105,24 +104,27 @@
   EXPECT_TRUE(
       GetNotificationIconsController()->tray_items().back()->GetVisible());
 
-  if (!IsQsRevampEnabled())
+  if (!IsQsRevampEnabled()) {
     EXPECT_TRUE(separator()->GetVisible());
+  }
 
   // Notification icons should not be shown in small screen size.
   UpdateDisplay("600x500");
   EXPECT_FALSE(
       GetNotificationIconsController()->tray_items().back()->GetVisible());
 
-  if (!IsQsRevampEnabled())
+  if (!IsQsRevampEnabled()) {
     EXPECT_FALSE(separator()->GetVisible());
+  }
 
   // Notification icons should be shown in large screen size.
   UpdateDisplay("1680x800");
   EXPECT_TRUE(
       GetNotificationIconsController()->tray_items().back()->GetVisible());
 
-  if (!IsQsRevampEnabled())
+  if (!IsQsRevampEnabled()) {
     EXPECT_TRUE(separator()->GetVisible());
+  }
 }
 
 TEST_P(NotificationIconsControllerTest, ShowNotificationIcons) {
@@ -140,8 +142,9 @@
   EXPECT_FALSE(
       GetNotificationIconsController()->tray_items()[end - 1]->GetVisible());
 
-  if (!IsQsRevampEnabled())
+  if (!IsQsRevampEnabled()) {
     EXPECT_FALSE(separator()->GetVisible());
+  }
 
   // Same case for non pinned or non critical warning notification.
   AddNotification(false /* is_pinned */, false /* is_critical_warning */);
@@ -150,8 +153,9 @@
   EXPECT_FALSE(
       GetNotificationIconsController()->tray_items()[end - 1]->GetVisible());
 
-  if (!IsQsRevampEnabled())
+  if (!IsQsRevampEnabled()) {
     EXPECT_FALSE(separator()->GetVisible());
+  }
 
   // Notification icons should be shown when pinned or critical warning
   // notification is added.
@@ -162,8 +166,9 @@
   EXPECT_FALSE(
       GetNotificationIconsController()->tray_items()[end - 1]->GetVisible());
 
-  if (!IsQsRevampEnabled())
+  if (!IsQsRevampEnabled()) {
     EXPECT_TRUE(separator()->GetVisible());
+  }
 
   std::string id1 =
       AddNotification(false /* is_pinned */, true /* is_critical_warning */);
@@ -172,8 +177,9 @@
   EXPECT_TRUE(
       GetNotificationIconsController()->tray_items()[end - 1]->GetVisible());
 
-  if (!IsQsRevampEnabled())
+  if (!IsQsRevampEnabled()) {
     EXPECT_TRUE(separator()->GetVisible());
+  }
 
   // Remove the critical warning notification should make the tray show only one
   // icon.
@@ -184,8 +190,9 @@
   EXPECT_FALSE(
       GetNotificationIconsController()->tray_items()[end - 1]->GetVisible());
 
-  if (!IsQsRevampEnabled())
+  if (!IsQsRevampEnabled()) {
     EXPECT_TRUE(separator()->GetVisible());
+  }
 
   // Remove the pinned notification, no icon is shown.
   message_center::MessageCenter::Get()->RemoveNotification(id0,
@@ -195,8 +202,9 @@
   EXPECT_FALSE(
       GetNotificationIconsController()->tray_items()[end - 1]->GetVisible());
 
-  if (!IsQsRevampEnabled())
+  if (!IsQsRevampEnabled()) {
     EXPECT_FALSE(separator()->GetVisible());
+  }
 }
 
 TEST_P(NotificationIconsControllerTest, NotShowNotificationIcons) {
@@ -213,8 +221,9 @@
   EXPECT_FALSE(
       GetNotificationIconsController()->tray_items().back()->GetVisible());
 
-  if (!IsQsRevampEnabled())
+  if (!IsQsRevampEnabled()) {
     EXPECT_FALSE(separator()->GetVisible());
+  }
 
   // Notification count does update for this notification.
   GetNotificationIconsController()->notification_counter_view()->Update();
@@ -228,8 +237,9 @@
   EXPECT_FALSE(
       GetNotificationIconsController()->tray_items().back()->GetVisible());
 
-  if (!IsQsRevampEnabled())
+  if (!IsQsRevampEnabled()) {
     EXPECT_FALSE(separator()->GetVisible());
+  }
 
   // Notification count does update for this notification.
   GetNotificationIconsController()->notification_counter_view()->Update();
@@ -243,8 +253,9 @@
   EXPECT_FALSE(
       GetNotificationIconsController()->tray_items().back()->GetVisible());
 
-  if (!IsQsRevampEnabled())
+  if (!IsQsRevampEnabled()) {
     EXPECT_FALSE(separator()->GetVisible());
+  }
 
   // Notification count does not update for this notification (since there's
   // another tray item for this).
diff --git a/ash/system/unified/power_button_unittest.cc b/ash/system/unified/power_button_unittest.cc
index 4bdb4eba5..60e1a3b 100644
--- a/ash/system/unified/power_button_unittest.cc
+++ b/ash/system/unified/power_button_unittest.cc
@@ -33,8 +33,7 @@
   ~PowerButtonTest() override = default;
 
   void SetUp() override {
-    feature_list_.InitWithFeatures(
-        {features::kQsRevamp, features::kQsRevampWip}, {});
+    feature_list_.InitAndEnableFeature(features::kQsRevamp);
     NoSessionAshTestBase::SetUp();
     widget_ = CreateFramelessTestWidget();
     widget_->SetFullscreen(true);
@@ -63,27 +62,31 @@
   bool IsMenuShowing() { return button_->IsMenuShowing(); }
 
   views::View* GetRestartButton() {
-    if (!IsMenuShowing())
+    if (!IsMenuShowing()) {
       return nullptr;
+    }
     return GetMenuView()->GetMenuItemByID(VIEW_ID_QS_POWER_RESTART_MENU_BUTTON);
   }
 
   views::View* GetPowerOffButton() {
-    if (!IsMenuShowing())
+    if (!IsMenuShowing()) {
       return nullptr;
+    }
     return GetMenuView()->GetMenuItemByID(VIEW_ID_QS_POWER_OFF_MENU_BUTTON);
   }
 
   views::View* GetSignOutButton() {
-    if (!IsMenuShowing())
+    if (!IsMenuShowing()) {
       return nullptr;
+    }
 
     return GetMenuView()->GetMenuItemByID(VIEW_ID_QS_POWER_SIGNOUT_MENU_BUTTON);
   }
 
   views::View* GetLockButton() {
-    if (!IsMenuShowing())
+    if (!IsMenuShowing()) {
       return nullptr;
+    }
 
     return GetMenuView()->GetMenuItemByID(VIEW_ID_QS_POWER_LOCK_MENU_BUTTON);
   }
diff --git a/ash/system/unified/quick_settings_footer_unittest.cc b/ash/system/unified/quick_settings_footer_unittest.cc
index b404261..a373cd57 100644
--- a/ash/system/unified/quick_settings_footer_unittest.cc
+++ b/ash/system/unified/quick_settings_footer_unittest.cc
@@ -31,8 +31,7 @@
   ~QuickSettingsFooterTest() override = default;
 
   void SetUp() override {
-    feature_list_.InitWithFeatures(
-        {features::kQsRevamp, features::kQsRevampWip}, {});
+    feature_list_.InitWithFeatures({features::kQsRevamp}, {});
     NoSessionAshTestBase::SetUp();
     widget_ = CreateFramelessTestWidget();
     widget_->SetFullscreen(true);
@@ -59,29 +58,33 @@
   bool IsMenuShowing() { return GetPowerButton()->IsMenuShowing(); }
 
   views::View* GetSignOutButton() {
-    if (!IsMenuShowing())
+    if (!IsMenuShowing()) {
       return nullptr;
+    }
 
     return GetMenuView()->GetMenuItemByID(VIEW_ID_QS_POWER_SIGNOUT_MENU_BUTTON);
   }
 
   views::View* GetLockButton() {
-    if (!IsMenuShowing())
+    if (!IsMenuShowing()) {
       return nullptr;
+    }
 
     return GetMenuView()->GetMenuItemByID(VIEW_ID_QS_POWER_LOCK_MENU_BUTTON);
   }
 
   views::View* GetRestartButton() {
-    if (!IsMenuShowing())
+    if (!IsMenuShowing()) {
       return nullptr;
+    }
 
     return GetMenuView()->GetMenuItemByID(VIEW_ID_QS_POWER_RESTART_MENU_BUTTON);
   }
 
   views::View* GetPowerOffButton() {
-    if (!IsMenuShowing())
+    if (!IsMenuShowing()) {
       return nullptr;
+    }
 
     return GetMenuView()->GetMenuItemByID(VIEW_ID_QS_POWER_OFF_MENU_BUTTON);
   }
diff --git a/ash/system/unified/quick_settings_header_unittest.cc b/ash/system/unified/quick_settings_header_unittest.cc
index aff15e0..6210da9 100644
--- a/ash/system/unified/quick_settings_header_unittest.cc
+++ b/ash/system/unified/quick_settings_header_unittest.cc
@@ -36,8 +36,7 @@
 class QuickSettingsHeaderTest : public NoSessionAshTestBase {
  public:
   QuickSettingsHeaderTest() {
-    feature_list_.InitWithFeatures(
-        {features::kQsRevamp, features::kQsRevampWip}, {});
+    feature_list_.InitAndEnableFeature(features::kQsRevamp);
   }
 
   // AshTestBase:
diff --git a/ash/system/unified/quick_settings_view.cc b/ash/system/unified/quick_settings_view.cc
index 27cde32..e80d1bd 100644
--- a/ash/system/unified/quick_settings_view.cc
+++ b/ash/system/unified/quick_settings_view.cc
@@ -51,8 +51,9 @@
 
   // views::View:
   void Layout() override {
-    for (auto* child : children())
+    for (auto* child : children()) {
       child->SetBoundsRect(GetContentsBounds());
+    }
     views::View::Layout();
   }
 };
@@ -190,11 +191,13 @@
 void QuickSettingsView::ShowMediaControls() {
   media_controls_container_->SetShouldShowMediaControls(true);
 
-  if (detailed_view_container_->GetVisible())
+  if (detailed_view_container_->GetVisible()) {
     return;
+  }
 
-  if (media_controls_container_->MaybeShowMediaControls())
+  if (media_controls_container_->MaybeShowMediaControls()) {
     PreferredSizeChanged();
+  }
 }
 
 void QuickSettingsView::SetDetailedView(
@@ -214,22 +217,25 @@
 void QuickSettingsView::ResetDetailedView() {
   detailed_view_container_->RemoveAllChildViews();
   detailed_view_container_->SetVisible(false);
-  if (media_controls_container_)
+  if (media_controls_container_) {
     media_controls_container_->MaybeShowMediaControls();
+  }
   system_tray_container_->SetVisible(true);
 }
 
 void QuickSettingsView::SaveFocus() {
   auto* focus_manager = GetFocusManager();
-  if (!focus_manager)
+  if (!focus_manager) {
     return;
+  }
 
   saved_focused_view_ = focus_manager->GetFocusedView();
 }
 
 void QuickSettingsView::RestoreFocus() {
-  if (saved_focused_view_)
+  if (saved_focused_view_) {
     saved_focused_view_->RequestFocus();
+  }
 }
 
 int QuickSettingsView::GetCurrentHeight() const {
@@ -260,8 +266,9 @@
 }
 
 void QuickSettingsView::OnGestureEvent(ui::GestureEvent* event) {
-  if (event->type() == ui::ET_SCROLL_FLING_START)
+  if (event->type() == ui::ET_SCROLL_FLING_START) {
     controller_->Fling(event->details().velocity_y());
+  }
 }
 
 BEGIN_METADATA(QuickSettingsView, views::View)
diff --git a/ash/system/unified/quiet_mode_feature_pod_controller_unittest.cc b/ash/system/unified/quiet_mode_feature_pod_controller_unittest.cc
index c85143ba..025a503 100644
--- a/ash/system/unified/quiet_mode_feature_pod_controller_unittest.cc
+++ b/ash/system/unified/quiet_mode_feature_pod_controller_unittest.cc
@@ -38,7 +38,6 @@
     }
     if (IsQsRevampEnabled()) {
       enabled_features.push_back(features::kQsRevamp);
-      enabled_features.push_back(features::kQsRevampWip);
     }
     feature_list_.InitWithFeatures(enabled_features, /*disabled_features*/ {});
     NoSessionAshTestBase::SetUp();
diff --git a/ash/system/unified/unified_system_tray_controller.cc b/ash/system/unified/unified_system_tray_controller.cc
index 5788c1e..0182c84 100644
--- a/ash/system/unified/unified_system_tray_controller.cc
+++ b/ash/system/unified/unified_system_tray_controller.cc
@@ -135,13 +135,15 @@
 }
 
 void UnifiedSystemTrayController::AddObserver(Observer* observer) {
-  if (observer)
+  if (observer) {
     observers_.AddObserver(observer);
+  }
 }
 
 void UnifiedSystemTrayController::RemoveObserver(Observer* observer) {
-  if (observer)
+  if (observer) {
     observers_.RemoveObserver(observer);
+  }
 }
 
 // static
@@ -220,8 +222,9 @@
 
 void UnifiedSystemTrayController::HandleSignOutAction() {
   base::RecordAction(base::UserMetricsAction("StatusArea_SignOut"));
-  if (Shell::Get()->session_controller()->IsDemoSession())
+  if (Shell::Get()->session_controller()->IsDemoSession()) {
     base::RecordAction(base::UserMetricsAction("DemoMode.ExitFromSystemTray"));
+  }
 
   if (ShouldShowDeferredUpdateDialog()) {
     DeferredUpdateDialog::CreateDialog(
@@ -300,8 +303,9 @@
 }
 
 void UnifiedSystemTrayController::ToggleExpanded() {
-  if (animation_->is_animating())
+  if (animation_->is_animating()) {
     return;
+  }
 
   UMA_HISTOGRAM_ENUMERATION("ChromeOS.SystemTray.ToggleExpanded",
                             TOGGLE_EXPANDED_TYPE_BY_BUTTON,
@@ -309,8 +313,9 @@
   if (IsExpanded()) {
     StartAnimation(/*expand=*/false);
     // Expand message center when quick settings is collapsed.
-    if (bubble_)
+    if (bubble_) {
       bubble_->ExpandMessageCenter();
+    }
   } else {
     // Collapse the message center if screen height is limited after expanding
     // the quick settings to its full height.
@@ -324,16 +329,18 @@
 void UnifiedSystemTrayController::BeginDrag(const gfx::PointF& location) {
   UpdateDragThreshold();
   // Ignore swipe collapsing when a detailed view is shown as it's confusing.
-  if (detailed_view_controller_)
+  if (detailed_view_controller_) {
     return;
+  }
   drag_init_point_ = location;
   was_expanded_ = IsExpanded();
 }
 
 void UnifiedSystemTrayController::UpdateDrag(const gfx::PointF& location) {
   // Ignore swipe collapsing when a detailed view is shown as it's confusing.
-  if (detailed_view_controller_)
+  if (detailed_view_controller_) {
     return;
+  }
   double drag_expanded_amount = GetDragExpandedAmount(location);
   animation_->Reset(drag_expanded_amount);
   UpdateExpandedAmount();
@@ -380,8 +387,9 @@
 
 void UnifiedSystemTrayController::EndDrag(const gfx::PointF& location) {
   // Ignore swipe collapsing when a detailed view is shown as it's confusing.
-  if (detailed_view_controller_)
+  if (detailed_view_controller_) {
     return;
+  }
   if (animation_->is_animating()) {
     // Prevent overwriting the state right after fling event
     return;
@@ -393,10 +401,11 @@
                               TOGGLE_EXPANDED_TYPE_COUNT);
   }
 
-  if (expanded && IsMessageCenterCollapseRequired())
+  if (expanded && IsMessageCenterCollapseRequired()) {
     bubble_->CollapseMessageCenter();
-  else
+  } else {
     bubble_->ExpandMessageCenter();
+  }
 
   // If dragging is finished, animate to closer state.
   StartAnimation(expanded);
@@ -404,30 +413,34 @@
 
 void UnifiedSystemTrayController::Fling(int velocity) {
   // Ignore swipe collapsing when a detailed view is shown as it's confusing.
-  if (detailed_view_controller_)
+  if (detailed_view_controller_) {
     return;
+  }
   // Expand when flinging up. Collapse otherwise.
   bool expand = (velocity < 0);
 
-  if (expand && IsMessageCenterCollapseRequired())
+  if (expand && IsMessageCenterCollapseRequired()) {
     bubble_->CollapseMessageCenter();
-  else
+  } else {
     bubble_->ExpandMessageCenter();
+  }
 
   StartAnimation(expand);
 }
 
 void UnifiedSystemTrayController::ShowUserChooserView() {
-  if (!UserChooserDetailedViewController::IsUserChooserEnabled())
+  if (!UserChooserDetailedViewController::IsUserChooserEnabled()) {
     return;
+  }
   animation_->Reset(1.0);
   UpdateExpandedAmount();
   ShowDetailedView(std::make_unique<UserChooserDetailedViewController>(this));
 }
 
 void UnifiedSystemTrayController::ShowNetworkDetailedView(bool force) {
-  if (!force && !IsExpanded())
+  if (!force && !IsExpanded()) {
     return;
+  }
 
   base::RecordAction(base::UserMetricsAction("StatusArea_Network_Detailed"));
 
@@ -440,8 +453,9 @@
 }
 
 void UnifiedSystemTrayController::ShowBluetoothDetailedView() {
-  if (!IsExpanded())
+  if (!IsExpanded()) {
     return;
+  }
 
   base::RecordAction(base::UserMetricsAction("StatusArea_Bluetooth_Detailed"));
   ShowDetailedView(std::make_unique<BluetoothDetailedViewController>(this));
@@ -478,8 +492,9 @@
 }
 
 void UnifiedSystemTrayController::ShowNotifierSettingsView() {
-  if (features::IsOsSettingsAppBadgingToggleEnabled())
+  if (features::IsOsSettingsAppBadgingToggleEnabled()) {
     return;
+  }
 
   DCHECK(Shell::Get()->session_controller()->ShouldShowNotificationTray());
   DCHECK(!Shell::Get()->session_controller()->IsScreenLocked());
@@ -489,8 +504,9 @@
 void UnifiedSystemTrayController::ShowCalendarView(
     calendar_metrics::CalendarViewShowSource show_source,
     calendar_metrics::CalendarEventSource event_source) {
-  if (!features::IsCalendarViewEnabled())
+  if (!features::IsCalendarViewEnabled()) {
     return;
+  }
 
   calendar_metrics::RecordCalendarShowMetrics(show_source, event_source);
   ShowDetailedView(std::make_unique<UnifiedCalendarViewController>(this));
@@ -498,8 +514,9 @@
   showing_calendar_view_ = true;
   showing_audio_detailed_view_ = false;
 
-  for (auto& observer : observers_)
+  for (auto& observer : observers_) {
     observer.OnOpeningCalendarView();
+  }
 }
 
 void UnifiedSystemTrayController::ShowMediaControlsDetailedView() {
@@ -510,8 +527,9 @@
 void UnifiedSystemTrayController::TransitionToMainView(bool restore_focus) {
   if (showing_calendar_view_) {
     showing_calendar_view_ = false;
-    for (auto& observer : observers_)
+    for (auto& observer : observers_) {
       observer.OnTransitioningFromCalendarToMainView();
+    }
   }
 
   showing_audio_detailed_view_ = false;
@@ -524,23 +542,27 @@
 
   if (features::IsQsRevampEnabled()) {
     quick_settings_view_->ResetDetailedView();
-    if (restore_focus)
+    if (restore_focus) {
       quick_settings_view_->RestoreFocus();
+    }
     return;
   }
   unified_view_->ResetDetailedView();
-  if (restore_focus)
+  if (restore_focus) {
     unified_view_->RestoreFocus();
+  }
 }
 
 void UnifiedSystemTrayController::CloseBubble() {
   if (features::IsQsRevampEnabled()) {
-    if (quick_settings_view_->GetWidget())
+    if (quick_settings_view_->GetWidget()) {
       quick_settings_view_->GetWidget()->CloseNow();
+    }
     return;
   }
-  if (unified_view_->GetWidget())
+  if (unified_view_->GetWidget()) {
     unified_view_->GetWidget()->CloseNow();
+  }
 }
 
 bool UnifiedSystemTrayController::FocusOut(bool reverse) {
@@ -556,10 +578,11 @@
 void UnifiedSystemTrayController::EnsureExpanded() {
   if (detailed_view_controller_) {
     showing_audio_detailed_view_ = false;
-    if (features::IsQsRevampEnabled())
+    if (features::IsQsRevampEnabled()) {
       quick_settings_view_->ResetDetailedView();
-    else
+    } else {
       unified_view_->ResetDetailedView();
+    }
 
     // Destroy `detailed_view_controller_` after resetting
     // `quick_settings_view_`'s `detailed_view_` because the detailed view has a
@@ -568,8 +591,9 @@
   }
   StartAnimation(true /*expand*/);
 
-  if (IsMessageCenterCollapseRequired())
+  if (IsMessageCenterCollapseRequired()) {
     bubble_->CollapseMessageCenter();
+  }
 }
 
 void UnifiedSystemTrayController::AnimationEnded(
@@ -639,12 +663,15 @@
   AddFeaturePodItem(std::make_unique<VPNFeaturePodController>(this));
   AddFeaturePodItem(std::make_unique<IMEFeaturePodController>(this));
   AddFeaturePodItem(std::make_unique<LocaleFeaturePodController>(this));
-  if (features::IsDarkLightModeEnabled())
+  if (features::IsDarkLightModeEnabled()) {
     AddFeaturePodItem(std::make_unique<DarkModeFeaturePodController>(this));
-  if (base::FeatureList::IsEnabled(features::kShelfParty))
+  }
+  if (base::FeatureList::IsEnabled(features::kShelfParty)) {
     AddFeaturePodItem(std::make_unique<ShelfPartyFeaturePodController>());
-  if (media::ShouldEnableAutoFraming())
+  }
+  if (media::ShouldEnableAutoFraming()) {
     AddFeaturePodItem(std::make_unique<AutozoomFeaturePodController>());
+  }
   // If you want to add a new feature pod item, add here.
 
   quick_settings_metrics_util::RecordQsFeaturePodCount(
@@ -726,43 +753,49 @@
     manager = unified_view_->GetFocusManager();
   }
 
-  if (manager && manager->GetFocusedView())
+  if (manager && manager->GetFocusedView()) {
     manager->ClearFocus();
+  }
 
   showing_audio_detailed_view_ = false;
-  if (features::IsQsRevampEnabled())
+  if (features::IsQsRevampEnabled()) {
     quick_settings_view_->SetDetailedView(controller->CreateView());
-  else
+  } else {
     unified_view_->SetDetailedView(controller->CreateView());
+  }
 
   detailed_view_controller_ = std::move(controller);
 
-  // |bubble_| may be null in tests.
+  // `bubble_` may be null in tests.
   if (bubble_) {
-    bubble_->UpdateBubble();
+    UpdateBubble();
     // Notify accessibility features that a new view is showing.
     bubble_->NotifyAccessibilityEvent(ax::mojom::Event::kShow, true);
   }
 }
 
 void UnifiedSystemTrayController::UpdateExpandedAmount() {
-  if (quick_settings_view_)
+  if (quick_settings_view_) {
     return;
+  }
   double expanded_amount = animation_->GetCurrentValue();
   unified_view_->SetExpandedAmount(expanded_amount);
 
-  if (expanded_amount == 0.0 || expanded_amount == 1.0)
+  if (expanded_amount == 0.0 || expanded_amount == 1.0) {
     model_->set_expanded_on_open(
         expanded_amount == 1.0
             ? UnifiedSystemTrayModel::StateOnOpen::EXPANDED
             : UnifiedSystemTrayModel::StateOnOpen::COLLAPSED);
+  }
 }
 
 void UnifiedSystemTrayController::ResetToCollapsedIfRequired() {
-  if (quick_settings_view_)
+  if (quick_settings_view_) {
     return;
-  if (model_->IsExplicitlyExpanded())
+  }
+  if (model_->IsExplicitlyExpanded()) {
     return;
+  }
 
   if (unified_view_->feature_pods_container()->row_count() ==
       kUnifiedFeaturePodMinRows) {
@@ -776,10 +809,12 @@
 }
 
 bool UnifiedSystemTrayController::IsDetailedViewShown() const {
-  if (quick_settings_view_)
+  if (quick_settings_view_) {
     return quick_settings_view_->IsDetailedViewShown();
-  if (unified_view_)
+  }
+  if (unified_view_) {
     return unified_view_->IsDetailedViewShown();
+  }
   return false;
 }
 
@@ -805,9 +840,14 @@
   return animation_->IsShowing();
 }
 
+void UnifiedSystemTrayController::UpdateBubble() {
+  bubble_->UpdateBubble();
+}
+
 bool UnifiedSystemTrayController::IsMessageCenterCollapseRequired() const {
-  if (quick_settings_view_)
+  if (quick_settings_view_) {
     return false;
+  }
 
   // Note: This calculaton should be the same as
   // UnifiedMessageCenterBubble::CalculateAvailableHeight().
diff --git a/ash/system/unified/unified_system_tray_controller.h b/ash/system/unified/unified_system_tray_controller.h
index 199165e..f2668456 100644
--- a/ash/system/unified/unified_system_tray_controller.h
+++ b/ash/system/unified/unified_system_tray_controller.h
@@ -184,6 +184,9 @@
   // Return true if UnifiedSystemTray is expanded.
   bool IsExpanded() const;
 
+  // Update the bubble view layout.
+  void UpdateBubble();
+
   scoped_refptr<UnifiedSystemTrayModel> model() { return model_; }
 
   PaginationController* pagination_controller() {
diff --git a/ash/system/unified/unified_system_tray_unittest.cc b/ash/system/unified/unified_system_tray_unittest.cc
index d5f266bc..7648a4a 100644
--- a/ash/system/unified/unified_system_tray_unittest.cc
+++ b/ash/system/unified/unified_system_tray_unittest.cc
@@ -52,9 +52,9 @@
   ~UnifiedSystemTrayTest() override = default;
 
   void SetUp() override {
-    if (IsQsRevampEnabled())
-      feature_list_.InitWithFeatures(
-          {features::kQsRevamp, features::kQsRevampWip}, {});
+    if (IsQsRevampEnabled()) {
+      feature_list_.InitAndEnableFeature(features::kQsRevamp);
+    }
     AshTestBase::SetUp();
   }
 
@@ -294,8 +294,9 @@
 }
 
 TEST_P(UnifiedSystemTrayTest, FocusMessageCenter) {
-  if (IsQsRevampEnabled())
+  if (IsQsRevampEnabled()) {
     return;
+  }
 
   auto* tray = GetPrimaryUnifiedSystemTray();
   tray->ShowBubble();
@@ -321,8 +322,9 @@
 }
 
 TEST_P(UnifiedSystemTrayTest, FocusMessageCenter_MessageCenterBubbleNotShown) {
-  if (IsQsRevampEnabled())
+  if (IsQsRevampEnabled()) {
     return;
+  }
 
   auto* tray = GetPrimaryUnifiedSystemTray();
   tray->ShowBubble();
@@ -336,8 +338,9 @@
 }
 
 TEST_P(UnifiedSystemTrayTest, FocusMessageCenter_VoxEnabled) {
-  if (IsQsRevampEnabled())
+  if (IsQsRevampEnabled()) {
     return;
+  }
 
   auto* tray = GetPrimaryUnifiedSystemTray();
   tray->ShowBubble();
@@ -504,8 +507,9 @@
 // Tests that CalendarView switches back to Quick Settings when screen size is
 // limited and the bubble requires a collapsed state.
 TEST_P(UnifiedSystemTrayTest, CalendarGoesToMainView) {
-  if (IsQsRevampEnabled())
+  if (IsQsRevampEnabled()) {
     return;
+  }
 
   auto* tray = GetPrimaryUnifiedSystemTray();
   tray->ShowBubble();
@@ -681,8 +685,9 @@
 // bubble becomes visible, and otherwise does not automatically show or hide.
 TEST_P(UnifiedSystemTrayTest, BubbleHideBehavior) {
   // This hiding behavior only applies when QsRevamp is enabled.
-  if (!IsQsRevampEnabled())
+  if (!IsQsRevampEnabled()) {
     return;
+  }
 
   // Basic verification test that the unified system tray bubble can show/hide
   // itself when no other bubbles are visible.
diff --git a/ash/webui/common/resources/network/network_list_item.js b/ash/webui/common/resources/network/network_list_item.js
index efd3430..030772b 100644
--- a/ash/webui/common/resources/network/network_list_item.js
+++ b/ash/webui/common/resources/network/network_list_item.js
@@ -16,13 +16,12 @@
 import '//resources/cr_elements/cr_shared_vars.css.js';
 import './network_icon.js';
 
+import {assert} from '//resources/ash/common/assert.js';
 import {CellularSetupPageName} from '//resources/ash/common/cellular_setup/cellular_types.js';
 import {getESimProfileProperties} from '//resources/ash/common/cellular_setup/esim_manager_utils.js';
 import {FocusRowBehavior} from '//resources/ash/common/focus_row_behavior.js';
 import {I18nBehavior} from '//resources/ash/common/i18n_behavior.js';
-import {assert} from '//resources/ash/common/assert.js';
 import {Polymer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js';
 import {ActivationStateType, CrosNetworkConfigRemote, GlobalPolicy, ManagedCellularProperties, ManagedProperties, SecurityType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js';
 import {ConnectionStateType, NetworkType, OncSource, PortalState} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js';
 
@@ -240,18 +239,6 @@
       type: Boolean,
       value: false,
     },
-
-    /**
-     * Return true if captivePortalUI2022 feature flag is enabled.
-     * @private
-     */
-    isCaptivePortalUI2022Enabled_: {
-      type: Boolean,
-      value() {
-        return loadTimeData.valueExists('captivePortalUI2022') &&
-            loadTimeData.getBoolean('captivePortalUI2022');
-      },
-    },
   },
 
   /** @private {?CrosNetworkConfigRemote} */
@@ -656,19 +643,16 @@
 
     const connectionState = this.networkState.connectionState;
     if (OncMojo.connectionStateIsConnected(connectionState)) {
-      if (this.isCaptivePortalUI2022Enabled_) {
-        if (this.isPortalState_(this.networkState.portalState)) {
-          return this.i18n('networkListItemSignIn');
-        }
-        if (this.networkState.portalState === PortalState.kPortalSuspected) {
-          return this.i18n('networkListItemConnectedLimited');
-        }
-        if (this.networkState.portalState === PortalState.kNoInternet) {
-          return this.i18n('networkListItemConnectedNoConnectivity');
-        }
+      if (this.isPortalState_(this.networkState.portalState)) {
+        return this.i18n('networkListItemSignIn');
       }
-      // TODO(khorimoto): Consider differentiating between Portal, Connected,
-      // and Online.
+      if (this.networkState.portalState === PortalState.kPortalSuspected) {
+        return this.i18n('networkListItemConnectedLimited');
+      }
+      if (this.networkState.portalState === PortalState.kNoInternet) {
+        return this.i18n('networkListItemConnectedNoConnectivity');
+      }
+      // TODO(khorimoto): Consider differentiating between Connected and Online.
       return this.i18n('networkListItemConnected');
     }
     if (connectionState === ConnectionStateType.kConnecting) {
@@ -707,7 +691,7 @@
     }
 
     // Warning is shown when there is restricted connectivity.
-    if (this.isCaptivePortalUI2022Enabled_ && this.networkState &&
+    if (this.networkState &&
         OncMojo.isRestrictedConnectivity(this.networkState.portalState)) {
       return true;
     }
@@ -755,8 +739,7 @@
     if (this.isESimUnactivatedProfile_) {
       return false;
     }
-    if (this.isCaptivePortalUI2022Enabled_ &&
-        OncMojo.isRestrictedConnectivity(this.networkState.portalState)) {
+    if (OncMojo.isRestrictedConnectivity(this.networkState.portalState)) {
       return false;
     }
     return OncMojo.connectionStateIsConnected(
diff --git a/ash/webui/shortcut_customization_ui/resources/common/icons.html b/ash/webui/shortcut_customization_ui/resources/common/icons.html
index a50f317..b1a2107f 100644
--- a/ash/webui/shortcut_customization_ui/resources/common/icons.html
+++ b/ash/webui/shortcut_customization_ui/resources/common/icons.html
@@ -85,6 +85,7 @@
       <g id="volume-down"><path d="M18.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM5 9v6h4l5 5V4L9 9H5z"></g>
       <g id="volume-mute"><path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"></g>
       <g id="volume-up"><path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"></g>
+      <g id="plus" viewbox="0 0 16 16" fill="none"><path d="M9 4H7V7H4V9H7V12H9V9H12V7H9V4Z" fill="#5F6368"></path></g>
     </defs>
   </svg>
 </iron-iconset-svg>
\ No newline at end of file
diff --git a/ash/webui/shortcut_customization_ui/resources/js/accelerator_row.html b/ash/webui/shortcut_customization_ui/resources/js/accelerator_row.html
index ff35f65..5bc35b8 100644
--- a/ash/webui/shortcut_customization_ui/resources/js/accelerator_row.html
+++ b/ash/webui/shortcut_customization_ui/resources/js/accelerator_row.html
@@ -6,7 +6,8 @@
     grid-template-rows: repeat(var(--accelerator-row-num-accels), 52px);
   }
 
-  accelerator-view {
+  accelerator-view,
+  text-accelerator {
     grid-column-start: 2;
     padding-bottom: 10px;
     padding-top: 10px;
diff --git a/ash/webui/shortcut_customization_ui/resources/js/fake_data.ts b/ash/webui/shortcut_customization_ui/resources/js/fake_data.ts
index 49f8817..2870e6d7 100644
--- a/ash/webui/shortcut_customization_ui/resources/js/fake_data.ts
+++ b/ash/webui/shortcut_customization_ui/resources/js/fake_data.ts
@@ -44,7 +44,7 @@
         },
         {
           text: stringToMojoString16(' + '),
-          type: TextAcceleratorPartType.kPlainText,
+          type: TextAcceleratorPartType.kDelimiter,
         },
         {
           text: stringToMojoString16('1 '),
diff --git a/ash/webui/shortcut_customization_ui/resources/js/text_accelerator.html b/ash/webui/shortcut_customization_ui/resources/js/text_accelerator.html
index a90d7c3..933e4a9 100644
--- a/ash/webui/shortcut_customization_ui/resources/js/text_accelerator.html
+++ b/ash/webui/shortcut_customization_ui/resources/js/text_accelerator.html
@@ -1,9 +1,17 @@
 <style>
+  .spacing {
+    margin-inline-end: 8px;
+  }
+
   #text-wrapper {
     align-items: center;
     display: flex;
     flex-direction: row;
   }
+
+  iron-icon {
+    --iron-icon-width: 16px;
+  }
 </style>
 
 <div class="container">
diff --git a/ash/webui/shortcut_customization_ui/resources/js/text_accelerator.ts b/ash/webui/shortcut_customization_ui/resources/js/text_accelerator.ts
index de8c7a0..7d129c1 100644
--- a/ash/webui/shortcut_customization_ui/resources/js/text_accelerator.ts
+++ b/ash/webui/shortcut_customization_ui/resources/js/text_accelerator.ts
@@ -3,11 +3,13 @@
 // found in the LICENSE file.
 
 import './input_key.js';
+import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 
+import {IronIconElement} from 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import {PolymerElementProperties} from 'chrome://resources/polymer/v3_0/polymer/interfaces.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {KeyInputState} from './input_key.js';
+import {InputKeyElement, KeyInputState} from './input_key.js';
 import {mojoString16ToString} from './mojo_utils.js';
 import {TextAcceleratorPart, TextAcceleratorPartType} from './shortcut_types.js';
 import {getTemplate} from './text_accelerator.html.js';
@@ -35,26 +37,53 @@
   parts: TextAcceleratorPart[];
 
   private parseAndDisplayTextParts(): void {
-    let finalHtml = '';
+    const wrapper =
+        this.shadowRoot!.querySelector('#text-wrapper') as HTMLDivElement;
+    wrapper.innerHTML = '';
+    const textParts: Node[] = [];
     for (const part of this.parts) {
       const text = mojoString16ToString(part.text);
       if (part.type === TextAcceleratorPartType.kPlainText) {
-        finalHtml += text;
+        textParts.push(this.createPlainTextPart(text));
+      } else if (part.type === TextAcceleratorPartType.kDelimiter) {
+        textParts.push(this.createDelimiterIconPart());
       } else {
-        finalHtml += this.createInputKeyHtmlString(text, part.type);
+        textParts.push(this.createInputKeyPart(text, part.type));
       }
     }
-    // TODO(michaelcheco): Use strictQuery here.
-    (this.shadowRoot!.querySelector('#text-wrapper') as HTMLDivElement)
-        .innerHTML = finalHtml;
+
+    wrapper.append(...textParts);
   }
 
-  private createInputKeyHtmlString(text: string, type: TextAcceleratorPartType):
-      string {
+  private createDelimiterIconPart(): IronIconElement {
+    const icon = document.createElement('iron-icon');
+    icon.classList.add('spacing');
+    icon.icon = this.getIconForDelimiter();
+    icon.id = 'delimiter-icon';
+    return icon;
+  }
+
+  private createInputKeyPart(keyText: string, type: TextAcceleratorPartType):
+      InputKeyElement {
     const keyState = type === TextAcceleratorPartType.kModifier ?
         KeyInputState.MODIFIER_SELECTED :
         KeyInputState.ALPHANUMERIC_SELECTED;
-    return `<input-key key="${text}" key-state=${keyState}></input-key>`;
+    const key = document.createElement('input-key');
+    key.key = keyText;
+    key.keyState = keyState;
+    return key;
+  }
+
+  private getIconForDelimiter(): string {
+    // Update if/when more delimiters are added.
+    return 'shortcut-customization-keys:plus';
+  }
+
+  private createPlainTextPart(text: string): HTMLSpanElement {
+    const span = document.createElement('span');
+    span.classList.add('spacing');
+    span.innerText = text;
+    return span;
   }
 
   static get template(): HTMLTemplateElement {
diff --git a/ash/wm/desks/templates/saved_desk_unittest.cc b/ash/wm/desks/templates/saved_desk_unittest.cc
index ed73f99..0e6b18d 100644
--- a/ash/wm/desks/templates/saved_desk_unittest.cc
+++ b/ash/wm/desks/templates/saved_desk_unittest.cc
@@ -703,6 +703,28 @@
   EXPECT_EQ(1.0f, test_window->layer()->opacity());
 }
 
+// Verifies that we don't get a crash when: creating a window, minimizing it,
+// entering the saved desk library and finally exiting overview. Regression test
+// for http://b/260001863.
+TEST_F(SavedDeskTest, HideMinimizedWindowOverviewItemsOnSavedDeskGridShow) {
+  AddEntry(base::GUID::GenerateRandomV4(), "template_1", base::Time::Now(),
+           DeskTemplateType::kTemplate);
+
+  auto test_window = CreateAppWindow();
+  WindowState::Get(test_window.get())->Minimize();
+
+  // Enter overview mode and the saved desk library. Entering the library will
+  // hide the overview item.
+  OpenOverviewAndShowSavedDeskGrid();
+
+  // Exit overview mode. This needs to be done with a non-zero duration so that
+  // the fade-out animation happens.
+  ui::ScopedAnimationDurationScaleMode animation_scale(
+      ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
+
+  ToggleOverview();
+}
+
 // Tests that when the saved desk grid is shown and the active desk is closed,
 // overview items stay hidden.
 TEST_F(SavedDeskTest, OverviewItemsStayHiddenInSavedDeskGridOnDeskClose) {
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc
index 138c16ca..753ee5d 100644
--- a/ash/wm/overview/overview_grid.cc
+++ b/ash/wm/overview/overview_grid.cc
@@ -45,6 +45,7 @@
 #include "ash/wm/overview/overview_item.h"
 #include "ash/wm/overview/overview_item_view.h"
 #include "ash/wm/overview/overview_session.h"
+#include "ash/wm/overview/overview_types.h"
 #include "ash/wm/overview/overview_utils.h"
 #include "ash/wm/overview/overview_window_drag_controller.h"
 #include "ash/wm/overview/scoped_overview_animation_settings.h"
@@ -70,9 +71,11 @@
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animator.h"
 #include "ui/compositor/presentation_time_recorder.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/compositor/throughput_tracker.h"
 #include "ui/gfx/geometry/transform_util.h"
 #include "ui/gfx/geometry/vector2d_f.h"
+#include "ui/views/animation/animation_builder.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 #include "ui/wm/core/coordinate_conversion.h"
@@ -122,6 +125,12 @@
 constexpr base::TimeDelta kOcclusionUnpauseDurationForRotation =
     base::Milliseconds(300);
 
+// The animiation duration of desks bar slide out animation when exiting
+// overview mode.
+constexpr base::TimeDelta kExpandedDesksBarSlideDuration =
+    base::Milliseconds(350);
+constexpr base::TimeDelta kZeroDesksBarSlideDuration = base::Milliseconds(250);
+
 // Toast id for the toast that is displayed when a user tries to move a window
 // that is visible on all desks to another desk.
 constexpr char kMoveVisibleOnAllDesksWindowToastId[] =
@@ -355,6 +364,44 @@
 
 }  // namespace
 
+// A self-deleting object that performs slide out animation for the desks
+// bar when exiting the overview mode. It owns the desks bar widget, thus when
+// the slide out animation is done, it will delete itself and destroy the desks
+// bar widget as well.
+class DesksBarSlideAnimation {
+ public:
+  DesksBarSlideAnimation(std::unique_ptr<views::Widget> desks_widget,
+                         bool is_zero_state)
+      : desks_widget_(std::move(desks_widget)) {
+    gfx::Transform transform;
+    transform.Translate(0, -desks_widget_->GetWindowBoundsInScreen().height());
+
+    const auto duration = is_zero_state ? kZeroDesksBarSlideDuration
+                                        : kExpandedDesksBarSlideDuration;
+    views::AnimationBuilder()
+        .OnEnded(base::BindOnce(
+            [](DesksBarSlideAnimation* animation) { delete animation; },
+            base::Unretained(this)))
+        .OnAborted(base::BindOnce(
+            [](DesksBarSlideAnimation* animation) { delete animation; },
+            base::Unretained(this)))
+        .SetPreemptionStrategy(
+            ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET)
+        .Once()
+        .SetDuration(duration)
+        .SetTransform(desks_widget_->GetLayer(), transform,
+                      gfx::Tween::ACCEL_30_DECEL_20_85);
+  }
+
+  DesksBarSlideAnimation(const DesksBarSlideAnimation&) = delete;
+  DesksBarSlideAnimation& operator=(const DesksBarSlideAnimation&) = delete;
+
+  ~DesksBarSlideAnimation() = default;
+
+ private:
+  std::unique_ptr<views::Widget> desks_widget_;
+};
+
 // The class to observe the overview window that the dragged tabs will merge
 // into. After the dragged tabs merge into the overview window, and if the
 // overview window represents a minimized window, we need to update the
@@ -459,6 +506,19 @@
 void OverviewGrid::Shutdown(OverviewEnterExitType exit_type) {
   EndNudge();
 
+  if (features::IsJellyrollEnabled() && desks_widget_ &&
+      exit_type != OverviewEnterExitType::kImmediateExit) {
+    // When applying the slide out animation to the `desks_widget_` during
+    // overview grid shutdown phase, we need to make the lifetime of the
+    // `desks_widget_` longer than its owner (overview grid). Thus move the
+    // ownership of `desks_widget_` from the overview grid to
+    // `DesksBarSlideAnimation` which is a self-deleting object, when the
+    // animation is done, it will delete itself and destroy `desks_widget_` as
+    // well.
+    new DesksBarSlideAnimation(std::move(desks_widget_),
+                               desks_bar_view_->IsZeroState());
+  }
+
   SplitViewController::Get(root_window_)->RemoveObserver(this);
   ScreenRotationAnimator::GetForRootWindow(root_window_)->RemoveObserver(this);
   Shell::Get()->wallpaper_controller()->RemoveObserver(this);
diff --git a/ash/wm/overview/overview_item.cc b/ash/wm/overview/overview_item.cc
index d6b5a6ea..9e54c96 100644
--- a/ash/wm/overview/overview_item.cc
+++ b/ash/wm/overview/overview_item.cc
@@ -129,27 +129,6 @@
   base::OnceClosure on_animation_finished_;
 };
 
-OverviewAnimationType GetExitOverviewAnimationTypeForMinimizedWindow(
-    OverviewEnterExitType type,
-    bool should_animate_when_exiting) {
-  // We should never get here when overview mode should exit immediately. The
-  // minimized window's |item_widget_| should be closed and destroyed
-  // immediately.
-  DCHECK_NE(type, OverviewEnterExitType::kImmediateExit);
-
-  // OverviewEnterExitType can only be set to kWindowMinimized in talbet mode.
-  // Fade out the minimized window without animation if switch from tablet mode
-  // to clamshell mode.
-  if (type == OverviewEnterExitType::kFadeOutExit) {
-    return Shell::Get()->tablet_mode_controller()->InTabletMode()
-               ? OVERVIEW_ANIMATION_EXIT_TO_HOME_LAUNCHER
-               : OVERVIEW_ANIMATION_NONE;
-  }
-  return should_animate_when_exiting
-             ? OVERVIEW_ANIMATION_EXIT_OVERVIEW_MODE_FADE_OUT
-             : OVERVIEW_ANIMATION_RESTORE_WINDOW_ZERO;
-}
-
 // Applies |new_bounds_in_screen| to |widget|, animating and observing the
 // transform if necessary.
 void SetWidgetBoundsAndMaybeAnimateTransform(
@@ -318,8 +297,7 @@
   }
 
   OverviewAnimationType animation_type =
-      GetExitOverviewAnimationTypeForMinimizedWindow(
-          enter_exit_type, should_animate_when_exiting_);
+      GetExitOverviewAnimationTypeForMinimizedWindow(enter_exit_type);
   FadeOutWidgetFromOverview(std::move(item_widget_), animation_type);
 }
 
@@ -1358,6 +1336,36 @@
   widget_window->SetTransform(label_transform);
 }
 
+OverviewAnimationType
+OverviewItem::GetExitOverviewAnimationTypeForMinimizedWindow(
+    OverviewEnterExitType type) {
+  // We should never get here when overview mode should exit immediately. The
+  // minimized window's `item_widget_` should be closed and destroyed
+  // immediately.
+  DCHECK_NE(type, OverviewEnterExitType::kImmediateExit);
+
+  // If the managed window has been hidden by the saved desk library, then
+  // we must avoid animating a minimized window. See http://b/260001863.
+  if (ScopedOverviewHideWindows* hide_windows =
+          overview_session_->hide_windows_for_saved_desks_grid()) {
+    if (hide_windows->HasWindow(item_widget_->GetNativeWindow())) {
+      return OVERVIEW_ANIMATION_NONE;
+    }
+  }
+
+  // OverviewEnterExitType can only be set to `kWindowMinimized` in tablet mode.
+  // Fade out the minimized window without animation if switch from tablet mode
+  // to clamshell mode.
+  if (type == OverviewEnterExitType::kFadeOutExit) {
+    return Shell::Get()->tablet_mode_controller()->InTabletMode()
+               ? OVERVIEW_ANIMATION_EXIT_TO_HOME_LAUNCHER
+               : OVERVIEW_ANIMATION_NONE;
+  }
+  return should_animate_when_exiting_
+             ? OVERVIEW_ANIMATION_EXIT_OVERVIEW_MODE_FADE_OUT
+             : OVERVIEW_ANIMATION_RESTORE_WINDOW_ZERO;
+}
+
 void OverviewItem::AnimateOpacity(float opacity,
                                   OverviewAnimationType animation_type) {
   DCHECK_GE(opacity, 0.f);
diff --git a/ash/wm/overview/overview_item.h b/ash/wm/overview/overview_item.h
index da6a3bd..6cf18cf 100644
--- a/ash/wm/overview/overview_item.h
+++ b/ash/wm/overview/overview_item.h
@@ -330,6 +330,11 @@
   // using |animation_type|.
   void AnimateOpacity(float opacity, OverviewAnimationType animation_type);
 
+  // Returns the type of animation to use for an item that manages a minimized
+  // window.
+  OverviewAnimationType GetExitOverviewAnimationTypeForMinimizedWindow(
+      OverviewEnterExitType type);
+
   // Called before dragging. Scales up the window a little bit to indicate its
   // selection and stacks the window at the top of the Z order in order to keep
   // it visible while dragging around.
diff --git a/ash/wm/tablet_mode/tablet_mode_multitask_menu.cc b/ash/wm/tablet_mode/tablet_mode_multitask_menu.cc
index db9d5543..86cb30c 100644
--- a/ash/wm/tablet_mode/tablet_mode_multitask_menu.cc
+++ b/ash/wm/tablet_mode/tablet_mode_multitask_menu.cc
@@ -6,6 +6,7 @@
 
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/public/cpp/window_properties.h"
+#include "ash/screen_util.h"
 #include "ash/style/ash_color_id.h"
 #include "ash/style/system_shadow.h"
 #include "ash/wm/splitview/split_view_controller.h"
@@ -153,13 +154,20 @@
   // Set the widget on the top center of the window.
   const gfx::Size menu_size(menu_view_->GetPreferredSize());
   const gfx::Rect window_bounds(window_->GetBoundsInScreen());
-  gfx::Rect widget_bounds(window_bounds);
+
   // The invisible widget needs to be big enough to include both the menu and
-  // shadow otherwise it would mask parts out.
-  widget_bounds.ClampToCenteredSize(
-      gfx::Size(menu_size.width() + kShadowOutset * 2,
-                menu_size.height() + kShadowOutset * 2));
-  widget_bounds.set_y(window_bounds.y());
+  // shadow otherwise it would mask parts out. Explicitly set the widget size
+  // since `window` may be narrower than the menu and clamp to its bounds.
+  const int widget_width = menu_size.width() + kShadowOutset * 2;
+  gfx::Rect widget_bounds = gfx::Rect(
+      window_bounds.CenterPoint().x() - widget_width / 2, window_bounds.y(),
+      widget_width, menu_size.height() + kShadowOutset * 2);
+  const gfx::Rect work_area =
+      screen_util::GetDisplayWorkAreaBoundsInParent(window);
+  if (!work_area.Contains(widget_bounds)) {
+    widget_bounds.AdjustToFit(work_area);
+  }
+
   widget_->SetBounds(widget_bounds);
   widget_->Show();
 
diff --git a/ash/wm/tablet_mode/tablet_mode_multitask_menu_event_handler_unittest.cc b/ash/wm/tablet_mode/tablet_mode_multitask_menu_event_handler_unittest.cc
index dbf41e9..ce6ac7fc 100644
--- a/ash/wm/tablet_mode/tablet_mode_multitask_menu_event_handler_unittest.cc
+++ b/ash/wm/tablet_mode/tablet_mode_multitask_menu_event_handler_unittest.cc
@@ -9,6 +9,7 @@
 #include "ash/display/screen_orientation_controller_test_api.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
+#include "ash/wm/splitview/split_view_constants.h"
 #include "ash/wm/splitview/split_view_divider.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
 #include "ash/wm/tablet_mode/tablet_mode_multitask_cue.h"
@@ -130,6 +131,25 @@
                    /*end_y=*/window.bounds().y() + kMenuDragPoint);
   }
 
+  void PressPartialPrimary(const aura::Window& window) {
+    ShowMultitaskMenu(window);
+    GetEventGenerator()->GestureTapAt(GetMultitaskMenuView(GetMultitaskMenu())
+                                          ->partial_button_for_testing()
+                                          ->GetBoundsInScreen()
+                                          .left_center());
+  }
+
+  void PressPartialSecondary(const aura::Window& window) {
+    ShowMultitaskMenu(window);
+    gfx::Rect partial_bounds(GetMultitaskMenuView(GetMultitaskMenu())
+                                 ->partial_button_for_testing()
+                                 ->GetBoundsInScreen());
+    gfx::Point secondary_center(
+        gfx::Point(partial_bounds.x() + partial_bounds.width() * 0.67f,
+                   partial_bounds.y() + partial_bounds.y() * 0.5f));
+    GetEventGenerator()->GestureTapAt(secondary_center);
+  }
+
   TabletModeMultitaskMenuEventHandler* GetMultitaskMenuEventHandler() {
     return TabletModeControllerTestApi()
         .tablet_mode_window_manager()
@@ -483,11 +503,7 @@
   base::HistogramTester histogram_tester;
 
   // Test that primary button snaps to 0.67f screen ratio.
-  ShowMultitaskMenu(*window);
-  GetEventGenerator()->GestureTapAt(GetMultitaskMenuView(GetMultitaskMenu())
-                                        ->partial_button_for_testing()
-                                        ->GetBoundsInScreen()
-                                        .left_center());
+  PressPartialPrimary(*window);
   ASSERT_EQ(chromeos::WindowStateType::kPrimarySnapped,
             WindowState::Get(window.get())->GetStateType());
   const gfx::Rect work_area_bounds =
@@ -505,14 +521,7 @@
       chromeos::MultitaskMenuActionType::kPartialSplitButton, 1);
 
   // Test that secondary button snaps to 0.33f screen ratio.
-  ShowMultitaskMenu(*window);
-  gfx::Rect partial_bounds(GetMultitaskMenuView(GetMultitaskMenu())
-                               ->partial_button_for_testing()
-                               ->GetBoundsInScreen());
-  gfx::Point secondary_center(
-      gfx::Point(partial_bounds.x() + partial_bounds.width() * 0.67f,
-                 partial_bounds.y() + partial_bounds.y() * 0.5f));
-  GetEventGenerator()->GestureTapAt(secondary_center);
+  PressPartialSecondary(*window);
   ASSERT_EQ(chromeos::WindowStateType::kSecondarySnapped,
             WindowState::Get(window.get())->GetStateType());
   ASSERT_NEAR(work_area_bounds.width() * 0.33f, window->bounds().width(),
@@ -523,6 +532,35 @@
       chromeos::MultitaskMenuActionType::kPartialSplitButton, 2);
 }
 
+// Tests that the menu bounds are adjusted if the window is narrower than the
+// menu for two partial split windows.
+TEST_F(TabletModeMultitaskMenuEventHandlerTest, AdjustedMenuBounds) {
+  auto window1 = CreateTestWindow();
+  PressPartialPrimary(*window1);
+  auto window2 = CreateTestWindow();
+  PressPartialSecondary(*window2);
+
+  auto* split_view_controller =
+      SplitViewController::Get(Shell::GetPrimaryRootWindow());
+  ASSERT_TRUE(split_view_controller->IsWindowInSplitView(window1.get()));
+  ASSERT_TRUE(split_view_controller->IsWindowInSplitView(window2.get()));
+
+  // Test that the menu fits on the 1/3 window on the right.
+  const gfx::Rect work_area =
+      display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
+  ASSERT_NEAR(work_area.width() * 0.33f, window2->bounds().width(),
+              kSplitviewDividerShortSideLength);
+  ShowMultitaskMenu(*window2);
+  EXPECT_EQ(work_area.right(),
+            GetMultitaskMenu()->widget()->GetWindowBoundsInScreen().right());
+
+  // Swap windows so the 1/3 window is on the left. Test that the menu fits.
+  split_view_controller->SwapWindows();
+  ShowMultitaskMenu(*window2);
+  EXPECT_EQ(work_area.x(),
+            GetMultitaskMenu()->widget()->GetWindowBoundsInScreen().x());
+}
+
 // Tests that tap outside the menu will close the menu.
 TEST_F(TabletModeMultitaskMenuEventHandlerTest, CloseMultitaskMenuOnTap) {
   // Create a display and window that is bigger than the menu.
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 9f50292..f2bc86f 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -4242,6 +4242,7 @@
       "android/java/src/org/chromium/base/PowerMonitorForQ.java",
       "android/java/src/org/chromium/base/Promise.java",
       "android/java/src/org/chromium/base/RadioUtils.java",
+      "android/java/src/org/chromium/base/RequiredCallback.java",
       "android/java/src/org/chromium/base/StreamUtil.java",
       "android/java/src/org/chromium/base/StrictModeContext.java",
       "android/java/src/org/chromium/base/SysUtils.java",
@@ -4468,6 +4469,7 @@
       "test/android/javatests/src/org/chromium/base/test/TestTraceEvent.java",
       "test/android/javatests/src/org/chromium/base/test/UiThreadStatement.java",
       "test/android/javatests/src/org/chromium/base/test/UiThreadTest.java",
+      "test/android/javatests/src/org/chromium/base/test/UnitTestLifetimeAssertRule.java",
       "test/android/javatests/src/org/chromium/base/test/UnitTestNoBrowserProcessHook.java",
       "test/android/javatests/src/org/chromium/base/test/metrics/HistogramTestRule.java",
       "test/android/javatests/src/org/chromium/base/test/params/BaseJUnit4RunnerDelegate.java",
diff --git a/base/android/java/src/org/chromium/base/RequiredCallback.java b/base/android/java/src/org/chromium/base/RequiredCallback.java
new file mode 100644
index 0000000..20d847a7
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/RequiredCallback.java
@@ -0,0 +1,31 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import androidx.annotation.NonNull;
+
+/**
+ * A simple single-argument callback to handle the result of a computation that must be called
+ * exactly once.
+ *
+ * @param <T> The type of the computation's result.
+ */
+public class RequiredCallback<T> implements Callback<T> {
+    // Enforces (under test) that this callback is invoked before it is GC'd.
+    private final LifetimeAssert mLifetimeAssert = LifetimeAssert.create(this);
+    private Callback<T> mCallback;
+
+    public RequiredCallback(@NonNull Callback<T> callback) {
+        mCallback = callback;
+    }
+
+    @Override
+    public void onResult(T result) {
+        assert mCallback != null : "Callback was already called.";
+        mCallback.onResult(result);
+        LifetimeAssert.setSafeToGc(mLifetimeAssert, true);
+        mCallback = null;
+    }
+}
diff --git a/base/android/unguessable_token_android_unittest.cc b/base/android/unguessable_token_android_unittest.cc
index faabb79..7d06c5b 100644
--- a/base/android/unguessable_token_android_unittest.cc
+++ b/base/android/unguessable_token_android_unittest.cc
@@ -14,7 +14,8 @@
   JNIEnv* env = AttachCurrentThread();
   uint64_t high = 0x1234567812345678;
   uint64_t low = 0x0583503029282304;
-  base::UnguessableToken token = base::UnguessableToken::Deserialize(high, low);
+  base::UnguessableToken token =
+      base::UnguessableToken::CreateForTesting(high, low);
   ScopedJavaLocalRef<jobject> jtoken =
       UnguessableTokenAndroid::Create(env, token);
   base::UnguessableToken result =
@@ -27,7 +28,8 @@
   JNIEnv* env = AttachCurrentThread();
   uint64_t high = 0x1234567812345678;
   uint64_t low = 0x0583503029282304;
-  base::UnguessableToken token = base::UnguessableToken::Deserialize(high, low);
+  base::UnguessableToken token =
+      base::UnguessableToken::CreateForTesting(high, low);
   ScopedJavaLocalRef<jobject> jtoken =
       UnguessableTokenAndroid::Create(env, token);
   ScopedJavaLocalRef<jobject> jtoken_clone =
diff --git a/base/files/file_util_unittest.cc b/base/files/file_util_unittest.cc
index 0a8b2997..f7553f5 100644
--- a/base/files/file_util_unittest.cc
+++ b/base/files/file_util_unittest.cc
@@ -862,14 +862,42 @@
       "Unsafe to deny execute access to path");
 }
 
-TEST_F(FileUtilTest, NoExecuteOnSafeFile) {
+MULTIPROCESS_TEST_MAIN(NoExecuteOnSafeFileMain) {
   base::FilePath temp_file;
-  // A file created in temp dir should always be permitted.
-  ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
+  CHECK(base::CreateTemporaryFile(&temp_file));
+
+  // A file with FLAG_WIN_NO_EXECUTE created in temp dir should always be
+  // permitted.
   File reopen_file(temp_file, File::FLAG_READ | File::FLAG_WRITE |
                                   File::FLAG_WIN_NO_EXECUTE |
                                   File::FLAG_OPEN_ALWAYS |
                                   File::FLAG_DELETE_ON_CLOSE);
+  return 0;
+}
+
+TEST_F(FileUtilTest, NoExecuteOnSafeFile) {
+  FilePath new_dir;
+  ASSERT_TRUE(CreateTemporaryDirInDir(
+      temp_dir_.GetPath(), FILE_PATH_LITERAL("NoExecuteOnSafeFileLongPath"),
+      &new_dir));
+
+  FilePath short_dir = base::MakeShortFilePath(new_dir);
+
+  // Verify that the path really is 8.3 now.
+  ASSERT_NE(new_dir.value(), short_dir.value());
+
+  LaunchOptions options;
+  options.environment[L"TMP"] = short_dir.value();
+
+  CommandLine child_command_line(GetMultiProcessTestChildBaseCommandLine());
+
+  Process child_process = SpawnMultiProcessTestChild(
+      "NoExecuteOnSafeFileMain", child_command_line, options);
+  ASSERT_TRUE(child_process.IsValid());
+  int rv = -1;
+  ASSERT_TRUE(WaitForMultiprocessTestChildExit(
+      child_process, TestTimeouts::action_timeout(), &rv));
+  ASSERT_EQ(0, rv);
 }
 
 class FileUtilExecuteEnforcementTest
diff --git a/base/json/values_util_unittest.cc b/base/json/values_util_unittest.cc
index 167d050..33fefea 100644
--- a/base/json/values_util_unittest.cc
+++ b/base/json/values_util_unittest.cc
@@ -95,7 +95,7 @@
   };
   for (const auto& test_case : kTestCases) {
     UnguessableToken input =
-        UnguessableToken::Deserialize(test_case.high, test_case.low);
+        UnguessableToken::CreateForTesting(test_case.high, test_case.low);
     Value expected(test_case.expected);
     SCOPED_TRACE(testing::Message() << "expected: " << test_case.expected);
 
diff --git a/base/system/sys_info_posix.cc b/base/system/sys_info_posix.cc
index 92e70aa..80c750ba 100644
--- a/base/system/sys_info_posix.cc
+++ b/base/system/sys_info_posix.cc
@@ -67,10 +67,16 @@
   if (HANDLE_EINTR(statfs(path.value().c_str(), &stats)) != 0)
     return false;
 
-  switch (stats.f_type) {
+  // This static_cast is here because various libcs disagree about the size
+  // and signedness of statfs::f_type. In particular, glibc has it as either a
+  // signed long or a signed int depending on platform, and other libcs
+  // (following the statfs(2) man page) use unsigned int instead. To avoid
+  // either an unsigned -> signed cast, or a narrowing cast, we always upcast
+  // statfs::f_type to unsigned long. :(
+  switch (static_cast<unsigned long>(stats.f_type)) {
     case TMPFS_MAGIC:
-    case static_cast<int>(HUGETLBFS_MAGIC):
-    case static_cast<int>(RAMFS_MAGIC):
+    case HUGETLBFS_MAGIC:
+    case RAMFS_MAGIC:
       return true;
   }
   return false;
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java b/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java
index 47adda5..df9b013 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java
@@ -236,7 +236,8 @@
      */
     @CallSuper
     protected List<TestRule> getDefaultTestRules() {
-        return Arrays.asList(new BaseJUnit4TestRule(), new MockitoErrorHandler());
+        return Arrays.asList(new BaseJUnit4TestRule(), new MockitoErrorHandler(),
+                new UnitTestLifetimeAssertRule());
     }
 
     /**
diff --git a/base/test/android/javatests/src/org/chromium/base/test/UnitTestLifetimeAssertRule.java b/base/test/android/javatests/src/org/chromium/base/test/UnitTestLifetimeAssertRule.java
new file mode 100644
index 0000000..6b5f1d25
--- /dev/null
+++ b/base/test/android/javatests/src/org/chromium/base/test/UnitTestLifetimeAssertRule.java
@@ -0,0 +1,33 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.test;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import org.chromium.base.LifetimeAssert;
+import org.chromium.base.test.util.Batch;
+import org.chromium.base.test.util.RequiresRestart;
+
+/**
+ * TestRule used to ensure we don't leak LifetimeAsserts in unit tests.
+ */
+public final class UnitTestLifetimeAssertRule implements TestRule {
+    @Override
+    public Statement apply(Statement base, Description description) {
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                base.evaluate();
+                Batch annotation = description.getTestClass().getAnnotation(Batch.class);
+                if (annotation != null && annotation.value().equals(Batch.UNIT_TESTS)) {
+                    if (description.getAnnotation(RequiresRestart.class) != null) return;
+                    LifetimeAssert.assertAllInstancesDestroyedForTesting();
+                }
+            }
+        };
+    }
+}
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
index c89595b..c852af6 100644
--- a/base/threading/thread_restrictions.h
+++ b/base/threading/thread_restrictions.h
@@ -294,10 +294,10 @@
 namespace leveldb::port {
 class ScopedAllowWait;
 }  // namespace leveldb::port
-namespace location::nearby::chrome {
+namespace nearby::chrome {
 class ScheduledExecutor;
 class SubmittableExecutor;
-}  // namespace location::nearby::chrome
+}  // namespace nearby::chrome
 namespace media {
 class AudioInputDevice;
 class AudioOutputDevice;
@@ -737,8 +737,8 @@
   friend class history_report::HistoryReportJniBridge;
   friend class internal::TaskTracker;
   friend class leveldb::port::ScopedAllowWait;
-  friend class location::nearby::chrome::ScheduledExecutor;
-  friend class location::nearby::chrome::SubmittableExecutor;
+  friend class nearby::chrome::ScheduledExecutor;
+  friend class nearby::chrome::SubmittableExecutor;
   friend class media::AudioOutputDevice;
   friend class media::BlockingUrlProtocol;
   friend class media::MojoVideoEncodeAccelerator;
diff --git a/build/android/print_cipd_version.py b/build/android/print_cipd_version.py
new file mode 100755
index 0000000..581295dc
--- /dev/null
+++ b/build/android/print_cipd_version.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import pathlib
+import re
+import subprocess
+
+_DIR_SOURCE_ROOT = str(pathlib.Path(__file__).absolute().parents[2])
+
+
+def main():
+  parser = argparse.ArgumentParser()
+  # Hide args set by wrappers so that using --help with the wrappers does not
+  # show them.
+  parser.add_argument('--subdir', required=True, help=argparse.SUPPRESS)
+  parser.add_argument('--cipd-package', required=True, help=argparse.SUPPRESS)
+  parser.add_argument('--git-log-url', help=argparse.SUPPRESS)
+  parser.add_argument('--cipd-instance', help='Uses value from DEPS by default')
+  args = parser.parse_args()
+
+  if not args.cipd_instance:
+    args.cipd_instance = subprocess.check_output(
+        ['gclient', 'getdep', '-r', f'src/{args.subdir}:{args.cipd_package}'],
+        cwd=_DIR_SOURCE_ROOT,
+        text=True)
+
+  cmd = ['cipd', 'describe', args.cipd_package, '-version', args.cipd_instance]
+  print(' '.join(cmd))
+  output = subprocess.check_output(cmd, text=True)
+  print(output, end='')
+  if args.git_log_url:
+    git_hashes = re.findall(r'version:.*?@(\w+)', output)
+    if not git_hashes:
+      print('Could not find git hash from output.')
+    else:
+      # Multiple version tags exist when multiple versions have the same sha1.
+      last_version = git_hashes[-1]
+      print()
+      print('Recent commits:', args.git_log_url.format(last_version))
+
+
+if __name__ == '__main__':
+  main()
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 0584535c..b274978c 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -236,6 +236,12 @@
       dest='repeat', type=int, default=0,
       help='Number of times to repeat the specified set of tests.')
 
+  # Not useful for junit tests.
+  parser.add_argument(
+      '--use-persistent-shell',
+      action='store_true',
+      help='Uses a persistent shell connection for the adb connection.')
+
   # This is currently only implemented for gtests and instrumentation tests.
   parser.add_argument(
       '--gtest_also_run_disabled_tests', '--gtest-also-run-disabled-tests',
@@ -315,10 +321,6 @@
       action='store_true',
       dest='upload_logcats_file',
       help='Whether to upload logcat file to logdog.')
-  parser.add_argument(
-      '--use-persistent-shell',
-      action='store_true',
-      help='Uses a persistent shell connection for the adb connection.')
 
   logcat_output_group = parser.add_mutually_exclusive_group()
   logcat_output_group.add_argument(
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index 0b6bdf2..59d80ea 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-11.20230113.1.1
+11.20230113.2.1
diff --git a/build/sanitizers/lsan_suppressions.cc b/build/sanitizers/lsan_suppressions.cc
index 10cd761..05459c0 100644
--- a/build/sanitizers/lsan_suppressions.cc
+++ b/build/sanitizers/lsan_suppressions.cc
@@ -93,7 +93,7 @@
     // Suppress leak in SurfaceDrawContext. crbug.com/1265033
     "leak:skgpu::v1::SurfaceDrawContext::drawGlyphRunList\n"
     // Suppress leak in BluetoothServerSocket. crbug.com/1278970
-    "leak:location::nearby::chrome::BluetoothServerSocket::"
+    "leak:nearby::chrome::BluetoothServerSocket::"
     "BluetoothServerSocket\n"
     // Suppress leak in NearbyConnectionBrokerImpl. crbug.com/1279578
     "leak:ash::secure_channel::NearbyConnectionBrokerImpl\n"
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc
index 640e390b..48d1aa6 100644
--- a/cc/layers/layer_unittest.cc
+++ b/cc/layers/layer_unittest.cc
@@ -119,9 +119,9 @@
 namespace {
 
 static auto kArbitrarySourceId1 =
-    base::UnguessableToken::Deserialize(0xdead, 0xbeef);
+    base::UnguessableToken::CreateForTesting(0xdead, 0xbeef);
 static auto kArbitrarySourceId2 =
-    base::UnguessableToken::Deserialize(0xdead, 0xbee0);
+    base::UnguessableToken::CreateForTesting(0xdead, 0xbee0);
 
 // http://google.github.io/googletest/gmock_for_dummies.html#using-mocks-in-tests
 // says that it is undefined behavior if we alternate between calls to
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index 1949501..7715e93 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -295,7 +295,7 @@
   bool directly_composited_image_default_raster_scale_changed_ : 1;
 
   LCDTextDisallowedReason lcd_text_disallowed_reason_ =
-      LCDTextDisallowedReason::kNone;
+      LCDTextDisallowedReason::kNoText;
 
   // If this scale is not zero, it indicates that this layer is a directly
   // composited image layer (i.e. the only thing drawn into this layer is an
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index ac0a599..236f228 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -5288,6 +5288,10 @@
 TEST_F(LegacySWPictureLayerImplTest, UpdateLCDTextInvalidatesPendingTree) {
   gfx::Size layer_bounds(100, 100);
   SetupPendingTree(FakeRasterSource::CreateFilledWithText(layer_bounds));
+  // LCD text is disallowed before SetContentsOpaque(true).
+  EXPECT_FALSE(pending_layer()->can_use_lcd_text());
+  pending_layer()->SetContentsOpaque(true);
+  pending_layer()->UpdateTiles();
 
   EXPECT_TRUE(pending_layer()->can_use_lcd_text());
   EXPECT_TRUE(pending_layer()->HighResTiling()->has_tiles());
@@ -5329,6 +5333,10 @@
   float page_scale = 4.f;
   SetupDrawPropertiesAndUpdateTiles(pending_layer(), page_scale, 1.0f,
                                     page_scale);
+  // LCD text is disallowed before SetContentsOpaque(true).
+  EXPECT_FALSE(pending_layer()->can_use_lcd_text());
+  pending_layer()->SetContentsOpaque(true);
+  pending_layer()->UpdateTiles();
   EXPECT_TRUE(pending_layer()->can_use_lcd_text());
   EXPECT_TRUE(pending_layer()->HighResTiling()->can_use_lcd_text());
   ActivateTree();
@@ -5367,6 +5375,10 @@
   float page_scale = 4.f;
   SetupDrawPropertiesAndUpdateTiles(pending_layer(), ideal_scale, 1.0f,
                                     page_scale);
+  // LCD text is disallowed before SetContentsOpaque(true).
+  EXPECT_FALSE(pending_layer()->can_use_lcd_text());
+  pending_layer()->SetContentsOpaque(true);
+  pending_layer()->UpdateTiles();
   EXPECT_TRUE(pending_layer()->can_use_lcd_text());
   EXPECT_TRUE(pending_layer()->HighResTiling()->can_use_lcd_text());
   ActivateTree();
@@ -6248,6 +6260,7 @@
   ActivateTree();
 
   active_layer()->SetContentsOpaque(true);
+  active_layer()->SetSafeOpaqueBackgroundColor(SkColors::kWhite);
   active_layer()->draw_properties().visible_layer_rect =
       gfx::Rect(0, 0, 1000, 1000);
   active_layer()->UpdateTiles();
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
index 8c3ee05f..becb537 100644
--- a/cc/paint/paint_op_buffer.cc
+++ b/cc/paint/paint_op_buffer.cc
@@ -431,18 +431,6 @@
   }
 }
 
-const PaintOp* PaintOpBuffer::GetOpAtForTesting(size_t index,
-                                                PaintOpType type) const {
-  size_t i = 0;
-  for (const auto& op : *this) {
-    if (i == index) {
-      return op.GetType() == type ? &op : nullptr;
-    }
-    i++;
-  }
-  return nullptr;
-}
-
 PaintOpBuffer::Iterator PaintOpBuffer::begin() const {
   return Iterator(*this);
 }
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
index 8e5758a..680e7fb 100644
--- a/cc/paint/paint_op_buffer.h
+++ b/cc/paint/paint_op_buffer.h
@@ -292,12 +292,6 @@
         op->HasEffectsPreventingLCDTextForSaveLayerAlpha();
   }
 
-  template <typename T>
-  const T* GetOpAtForTesting(size_t index) const {
-    return static_cast<const T*>(GetOpAtForTesting(index, T::kType));
-  }
-  const PaintOp* GetOpAtForTesting(size_t index, PaintOpType type) const;
-
   size_t GetOpOffsetForTracing(const PaintOp& op) const {
     DCHECK_GE(reinterpret_cast<const char*>(&op), data_.get());
     size_t result =
diff --git a/cc/paint/paint_record.h b/cc/paint/paint_record.h
index 0722197..7afa6de 100644
--- a/cc/paint/paint_record.h
+++ b/cc/paint/paint_record.h
@@ -58,11 +58,6 @@
   }
   const PaintOp& GetFirstOp() const { return buffer_->GetFirstOp(); }
 
-  template <typename T>
-  const T* GetOpAtForTesting(size_t index) const {
-    return buffer_->GetOpAtForTesting<T>(index);
-  }
-
   // Given the |bounds| of a PaintOpBuffer that would be transformed by |ctm|
   // when rendered, compute the bounds needed to raster the buffer at a fixed
   // scale into an auxiliary image instead of rasterizing at scale dynamically.
diff --git a/cc/test/test_layer_tree_host_base.cc b/cc/test/test_layer_tree_host_base.cc
index 887fc79..dffbbc6 100644
--- a/cc/test/test_layer_tree_host_base.cc
+++ b/cc/test/test_layer_tree_host_base.cc
@@ -121,9 +121,6 @@
     auto* page_scale_layer = AddLayer<LayerImpl>(pending_tree);
     pending_layer_ = AddLayer<FakePictureLayerImpl>(pending_tree);
     pending_layer_->SetDrawsContent(true);
-    // LCD-text tests require the layer to be initially opaque.
-    pending_layer_->SetContentsOpaque(true);
-    pending_layer_->SetSafeOpaqueBackgroundColor(SkColors::kWhite);
 
     pending_tree->SetElementIdsForTesting();
     SetupRootProperties(pending_root);
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 0f39a04..0e05651 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -128,7 +128,7 @@
   return viz::SurfaceId(
       frame_sink_id,
       viz::LocalSurfaceId(parent_id,
-                          base::UnguessableToken::Deserialize(0, 1u)));
+                          base::UnguessableToken::CreateForTesting(0, 1u)));
 }
 
 struct TestFrameData : public LayerTreeHostImpl::FrameData {
@@ -245,8 +245,8 @@
   }
   void DidActivateSyncTree() override {
     // Make sure the active tree always has a valid LocalSurfaceId.
-    host_impl_->active_tree()->SetLocalSurfaceIdFromParent(
-        viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u)));
+    host_impl_->active_tree()->SetLocalSurfaceIdFromParent(viz::LocalSurfaceId(
+        1, base::UnguessableToken::CreateForTesting(2u, 3u)));
   }
   void WillPrepareTiles() override {}
   void DidPrepareTiles() override { did_prepare_tiles_ = true; }
@@ -323,8 +323,8 @@
     bool init = host_impl_->InitializeFrameSink(layer_tree_frame_sink_.get());
     host_impl_->active_tree()->SetDeviceViewportRect(gfx::Rect(10, 10));
     host_impl_->active_tree()->PushPageScaleFromMainThread(1, 1, 1);
-    host_impl_->active_tree()->SetLocalSurfaceIdFromParent(
-        viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u)));
+    host_impl_->active_tree()->SetLocalSurfaceIdFromParent(viz::LocalSurfaceId(
+        1, base::UnguessableToken::CreateForTesting(2u, 3u)));
     // Set the viz::BeginFrameArgs so that methods which use it are able to.
     auto args = viz::CreateBeginFrameArgsForTesting(
         BEGINFRAME_FROM_HERE, 0, 1, base::TimeTicks() + base::Milliseconds(1));
@@ -5310,8 +5310,8 @@
 
     host_impl_->active_tree()->DidBecomeActive();
     host_impl_->active_tree()->HandleScrollbarShowRequests();
-    host_impl_->active_tree()->SetLocalSurfaceIdFromParent(
-        viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u)));
+    host_impl_->active_tree()->SetLocalSurfaceIdFromParent(viz::LocalSurfaceId(
+        1, base::UnguessableToken::CreateForTesting(2u, 3u)));
 
     DrawFrame();
 
@@ -11272,7 +11272,7 @@
   CopyProperties(root, child);
   child->SetOffsetToTransformParent(gfx::Vector2dF(12, 13));
   layer_tree_host_impl->active_tree()->SetLocalSurfaceIdFromParent(
-      viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u)));
+      viz::LocalSurfaceId(1, base::UnguessableToken::CreateForTesting(2u, 3u)));
   UpdateDrawProperties(layer_tree_host_impl->active_tree());
 
   TestFrameData frame;
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
index eb23c1f5..af2ef9d 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
@@ -289,7 +289,8 @@
                     browserControlsManager, tabCreatorManager, menuOrKeyboardActionController,
                     containerView, shareDelegateSupplier, multiWindowModeStateDispatcher,
                     scrimCoordinator, /* rootView= */ containerView, dynamicResourceLoaderSupplier,
-                    snackbarManager, modalDialogManager, incognitoReauthControllerSupplier);
+                    snackbarManager, modalDialogManager, incognitoReauthControllerSupplier,
+                    backPressManager);
             mTabSwitcherCustomViewManagerSupplier.set(
                     mTabSwitcher.getTabSwitcherCustomViewManager());
         } else {
@@ -313,7 +314,8 @@
                 mIsStartSurfaceEnabled, mActivity, mBrowserControlsManager,
                 this::isActivityFinishingOrDestroyed, excludeQueryTiles,
                 startSurfaceOneshotSupplier, hadWarmStart, jankTracker, initializeMVTilesRunnable,
-                mParentTabSupplier, logoContainerView, backPressManager, feedPlaceholderParentView,
+                mParentTabSupplier, logoContainerView,
+                mTabSwitcher == null ? backPressManager : null, feedPlaceholderParentView,
                 mActivityLifecycleDispatcher, tabSwitcherClickHandler);
 
         startSurfaceOneshotSupplier.set(this);
@@ -509,6 +511,9 @@
 
     @Override
     public boolean onBackPressed() {
+        if (mTabSwitcher != null) {
+            return mTabSwitcher.onBackPressed();
+        }
         return mStartSurfaceMediator.onBackPressed();
     }
 
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
index 28699b2..cf72139 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -216,7 +216,7 @@
             OneshotSupplier<StartSurface> startSurfaceSupplier, boolean hadWarmStart,
             JankTracker jankTracker, Runnable initializeMVTilesRunnable,
             Supplier<Tab> parentTabSupplier, View logoContainerView,
-            BackPressManager backPressManager, ViewGroup feedPlaceholderParentView,
+            @Nullable BackPressManager backPressManager, ViewGroup feedPlaceholderParentView,
             ActivityLifecycleDispatcher activityLifecycleDispatcher,
             OnClickListener tabSwitcherClickHandler) {
         mController = controller;
@@ -423,8 +423,8 @@
         mPreviousStartSurfaceState = StartSurfaceState.NOT_SHOWN;
         mStartSurfaceState = StartSurfaceState.NOT_SHOWN;
 
-        if (BackPressManager.isEnabled()) {
-            backPressManager.addHandler(this, Type.START_SURFACE_MEDIATOR);
+        if (backPressManager != null && BackPressManager.isEnabled()) {
+            backPressManager.addHandler(this, Type.START_SURFACE);
             if (mPropertyModel != null) {
                 mPropertyModel.addObserver((source, key) -> {
                     if (key == IS_INCOGNITO) notifyBackPressStateChanged();
@@ -815,14 +815,28 @@
         mController.showTabSwitcherView(animate);
     }
 
+    /**
+     * This function no longer handles the case when Start is disabled. Instead, the back operations
+     * of the grid tab switcher is handled by TabSwitcherMediator.
+     */
     boolean onBackPressed() {
         boolean ret = onBackPressedInternal();
         if (ret) {
-            BackPressManager.record(BackPressHandler.Type.START_SURFACE_MEDIATOR);
+            BackPressManager.record(BackPressHandler.Type.START_SURFACE);
         }
         return ret;
     }
 
+    /**
+     * This function handles the following cases:
+     * 1) Start surface is showing, including with/without refactoring enabled;
+     * 2) Grid tab switcher is showing, but only when Start surface is enabled and refactoring is
+     *    disabled. This is because the transitions between Start surface and tab switcher
+     *    (secondary tasks view) is handled by the same Layout via state changes. So we have to
+     *    handle the two surfaces together.
+     *    In the ideal scenarios: when a) Start is disabled and b) Start surface refactoring is
+     *    enabled, the back operations of the grid tab switcher is handled by TabSwitcherMediator.
+     */
     private boolean onBackPressedInternal() {
         boolean isOnHomepage = isHomepageShown();
 
@@ -834,14 +848,14 @@
         // the TabSelectionEditor dialog. Therefore, we need to check both controllers as well.
         if (mSecondaryTasksSurfaceController != null
                 && mSecondaryTasksSurfaceController.isDialogVisible()) {
-            boolean ret = mSecondaryTasksSurfaceController.onBackPressed(isOnHomepage);
+            boolean ret = mSecondaryTasksSurfaceController.onBackPressed();
             assert !BackPressManager.isEnabled()
                     || ret : String.format("Wrong back press state: %s, start surface: %s",
                                      mSecondaryTasksSurfaceController.getClass().getName(),
                                      mStartSurfaceState);
             return ret;
         } else if (mController.isDialogVisible()) {
-            boolean ret = mController.onBackPressed(isOnHomepage);
+            boolean ret = mController.onBackPressed();
             assert !BackPressManager.isEnabled()
                     || ret : String.format("Wrong back press state: %s, start surface: %s",
                                      mController.getClass().getName(), mStartSurfaceState);
@@ -857,7 +871,7 @@
                 ReturnToChromeUtil.recordBackNavigationToStart("FromTabSwitcher");
                 return true;
             } else {
-                boolean ret = mSecondaryTasksSurfaceController.onBackPressed(isOnHomepage);
+                boolean ret = mSecondaryTasksSurfaceController.onBackPressed();
                 assert !BackPressManager.isEnabled()
                         || ret : String.format("Wrong back press state: %s, start surface: %s",
                                          mSecondaryTasksSurfaceController.getClass().getName(),
@@ -873,7 +887,7 @@
             }
         }
 
-        boolean ret = mController.onBackPressed(isOnHomepage);
+        boolean ret = mController.onBackPressed();
         assert !BackPressManager.isEnabled()
                 || ret : String.format("Wrong back press state: %s, start surface: %s",
                                  mController.getClass().getName(), mStartSurfaceState);
@@ -1129,15 +1143,14 @@
         // StartSurface is being supplied with OneShotSupplier, notification sends after
         // StartSurface is available to avoid missing events. More detail see:
         // https://crrev.com/c/2427428.
-        mController.onHomepageChanged(isHomepageShown());
+        mController.onHomepageChanged();
         notifyBackPressStateChanged();
     }
 
     // TODO(1347089): Remove this when the Start surface refactoring is enabled by default.
     private void notifyStartSurfaceStateChange() {
         if (mSecondaryTasksSurfaceController != null) {
-            mSecondaryTasksSurfaceController.onHomepageChanged(
-                    mStartSurfaceState == StartSurfaceState.SHOWN_HOMEPAGE);
+            mSecondaryTasksSurfaceController.onHomepageChanged();
         }
         mStartSurfaceSupplier.onAvailable((unused) -> {
             for (StartSurface.StateObserver observer : mStateObservers) {
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java
index 05157b9..425262b 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java
@@ -150,4 +150,9 @@
     public @Nullable TabSwitcherCustomViewManager getTabSwitcherCustomViewManager() {
         return null;
     }
+
+    @Override
+    public boolean onBackPressed() {
+        return false;
+    }
 }
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediator.java
index 22c245c3..ee9baa2 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediator.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediator.java
@@ -44,8 +44,6 @@
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.url.GURL;
 
-import java.util.List;
-
 /** Mediator of the single tab tab switcher. */
 public class SingleTabSwitcherMediator implements TabSwitcher.Controller {
     @VisibleForTesting
@@ -66,7 +64,6 @@
     private Long mTabTitleAvailableTime;
     private boolean mFaviconInitialized;
     private Context mContext;
-    private boolean mIsOnHomepage;
 
     SingleTabSwitcherMediator(Context context, PropertyModel propertyModel,
             TabModelSelector tabModelSelector, TabListFaviconProvider tabListFaviconProvider) {
@@ -83,16 +80,10 @@
                 selectTheCurrentTab();
             }
         });
-        mPropertyModel.addObserver((source, key) -> {
-            if (key == IS_VISIBLE) {
-                mBackPressChangedSupplier.set(shouldInterceptBackPress());
-            }
-        });
 
         mNormalTabModelObserver = new TabModelObserver() {
             @Override
             public void didSelectTab(Tab tab, int type, int lastId) {
-                mBackPressChangedSupplier.set(shouldInterceptBackPress());
                 if (!ReturnToChromeUtil.isStartSurfaceRefactorEnabled(mContext)
                         && mTabModelSelector.isIncognitoSelected()) {
                     return;
@@ -109,27 +100,11 @@
                 }
                 mTabSelectingListener.onTabSelecting(LayoutManagerImpl.time(), tab.getId());
             }
-
-            @Override
-            public void tabPendingClosure(Tab tab) {
-                mBackPressChangedSupplier.set(shouldInterceptBackPress());
-            }
-
-            @Override
-            public void multipleTabsPendingClosure(List<Tab> tabs, boolean isAllTabs) {
-                mBackPressChangedSupplier.set(shouldInterceptBackPress());
-            }
-
-            @Override
-            public void tabClosureUndone(Tab tab) {
-                mBackPressChangedSupplier.set(shouldInterceptBackPress());
-            }
         };
         mTabModelSelectorObserver = new TabModelSelectorObserver() {
             @Override
             public void onTabModelSelected(TabModel newModel, TabModel oldModel) {
                 if (!newModel.isIncognito()) mShouldIgnoreNextSelect = true;
-                mBackPressChangedSupplier.set(shouldInterceptBackPress());
             }
 
             @Override
@@ -267,16 +242,9 @@
     }
 
     @Override
-    public boolean onBackPressed(boolean isOnHomepage) {
-        // If currently on the Start surface, we will stop here. The back button will be handled by
-        // the ChromeTabbedActivity. See https://crbug.com/1187714.
-        if (isOnHomepage) return false;
-
-        if (overviewVisible() && !mTabModelSelector.isIncognitoSelected()
-                && mTabModelSelector.getCurrentTabId() != TabList.INVALID_TAB_INDEX) {
-            selectTheCurrentTab();
-            return true;
-        }
+    public boolean onBackPressed() {
+        // The singe tab switcher shouldn't handle any back button. The back button will be handled
+        // by the ChromeTabbedActivity. See https://crbug.com/1187714.
         return false;
     }
 
@@ -316,15 +284,7 @@
     }
 
     @Override
-    public void onHomepageChanged(boolean isOnHomepage) {
-        mIsOnHomepage = isOnHomepage;
-        mBackPressChangedSupplier.set(shouldInterceptBackPress());
-    }
-
-    private boolean shouldInterceptBackPress() {
-        return !mIsOnHomepage && overviewVisible() && !mTabModelSelector.isIncognitoSelected()
-                && mTabModelSelector.getCurrentTabId() != TabList.INVALID_TAB_INDEX;
-    }
+    public void onHomepageChanged() {}
 
     private void updateSelectedTab(Tab tab) {
         if (tab.isLoading() && TextUtils.isEmpty(tab.getTitle())) {
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java
index b1f35862..6f08599 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java
@@ -139,7 +139,7 @@
                     mView.getBodyViewContainer(), shareDelegateSupplier,
                     multiWindowModeStateDispatcher, scrimCoordinator, rootView,
                     dynamicResourceLoaderSupplier, snackbarManager, modalDialogManager,
-                    incognitoReauthControllerSupplier);
+                    incognitoReauthControllerSupplier, null /*BackPressManager*/);
         } else if (tabSwitcherType == TabSwitcherType.SINGLE) {
             mTabSwitcher = new SingleTabSwitcherCoordinator(
                     activity, mView.getCarouselTabSwitcherContainer(), tabModelSelector);
diff --git a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
index b0d03331..71f48ce 100644
--- a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
+++ b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
@@ -138,7 +138,7 @@
     @Rule
     public TestRule mProcessor = new Features.JUnitProcessor();
     @Mock
-    private TabSwitcher.Controller mMainTabGridController;
+    private TabSwitcher.Controller mCarouselOrSingleTabSwitcherModuleController;
     @Mock
     private TabModelSelector mTabModelSelector;
     @Mock
@@ -202,7 +202,8 @@
     @Captor
     private ArgumentCaptor<TabModelObserver> mTabModelObserverCaptor;
     @Captor
-    private ArgumentCaptor<TabSwitcherViewObserver> mTabSwitcherVisibilityObserverCaptor;
+    private ArgumentCaptor<TabSwitcherViewObserver>
+            mCarouselTabSwitcherModuleVisibilityObserverCaptor;
     @Captor
     private ArgumentCaptor<UrlFocusChangeListener> mUrlFocusChangeListenerCaptor;
     @Captor
@@ -212,10 +213,12 @@
     private ArgumentCaptor<PauseResumeWithNativeObserver>
             mPauseResumeWithNativeObserverArgumentCaptor;
 
-    private ObservableSupplierImpl<Boolean> mControllerBackPressStateSupplier =
-            new ObservableSupplierImpl<>();
-    private ObservableSupplierImpl<Boolean> mControllerDialogVisibleSupplier =
-            new ObservableSupplierImpl<>();
+    private ObservableSupplierImpl<Boolean>
+            mCarouselTabSwitcherModuleControllerBackPressStateSupplier =
+                    new ObservableSupplierImpl<>();
+    private ObservableSupplierImpl<Boolean>
+            mCarouselTabSwitcherModuleControllerDialogVisibleSupplier =
+                    new ObservableSupplierImpl<>();
     private ObservableSupplierImpl<Boolean> mSecondaryControllerBackPressStateSupplier =
             new ObservableSupplierImpl<>();
     private ObservableSupplierImpl<Boolean> mSecondaryControllerDialogVisibleSupplier =
@@ -242,12 +245,14 @@
         doReturn(mIncognitoTabModel).when(mTabModelSelector).getModel(true);
         doReturn(false).when(mNormalTabModel).isIncognito();
         doReturn(true).when(mIncognitoTabModel).isIncognito();
-        doReturn(TabSwitcherType.CAROUSEL).when(mMainTabGridController).getTabSwitcherType();
-        doReturn(mControllerBackPressStateSupplier)
-                .when(mMainTabGridController)
+        doReturn(TabSwitcherType.CAROUSEL)
+                .when(mCarouselOrSingleTabSwitcherModuleController)
+                .getTabSwitcherType();
+        doReturn(mCarouselTabSwitcherModuleControllerBackPressStateSupplier)
+                .when(mCarouselOrSingleTabSwitcherModuleController)
                 .getHandleBackPressChangedSupplier();
-        doReturn(mControllerDialogVisibleSupplier)
-                .when(mMainTabGridController)
+        doReturn(mCarouselTabSwitcherModuleControllerDialogVisibleSupplier)
+                .when(mCarouselOrSingleTabSwitcherModuleController)
                 .isDialogVisibleSupplier();
         doReturn(mSecondaryTasksSurfaceController)
                 .when(mSecondaryTasksSurfaceInitializer)
@@ -282,20 +287,21 @@
         StartSurfaceMediator mediator =
                 createStartSurfaceMediator(/* isStartSurfaceEnabled= */ false);
         verify(mTabModelSelector, never()).addObserver(mTabModelSelectorObserverCaptor.capture());
-        verify(mMainTabGridController)
-                .addTabSwitcherViewObserver(mTabSwitcherVisibilityObserverCaptor.capture());
+        verify(mCarouselOrSingleTabSwitcherModuleController)
+                .addTabSwitcherViewObserver(
+                        mCarouselTabSwitcherModuleVisibilityObserverCaptor.capture());
 
         mediator.showOverview(false);
-        verify(mMainTabGridController).showTabSwitcherView(eq(false));
+        verify(mCarouselOrSingleTabSwitcherModuleController).showTabSwitcherView(eq(false));
 
-        mTabSwitcherVisibilityObserverCaptor.getValue().startedShowing();
-        mTabSwitcherVisibilityObserverCaptor.getValue().finishedShowing();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().startedShowing();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().finishedShowing();
 
         mediator.hideTabSwitcherView(true);
-        verify(mMainTabGridController).hideTabSwitcherView(eq(true));
+        verify(mCarouselOrSingleTabSwitcherModuleController).hideTabSwitcherView(eq(true));
 
-        mTabSwitcherVisibilityObserverCaptor.getValue().startedHiding();
-        mTabSwitcherVisibilityObserverCaptor.getValue().finishedHiding();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().startedHiding();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().finishedHiding();
 
         // TODO(crbug.com/1020223): Test the other SurfaceMode.NO_START_SURFACE operations.
     }
@@ -308,8 +314,9 @@
 
         StartSurfaceMediator mediator =
                 createStartSurfaceMediator(/* isStartSurfaceEnabled= */ true);
-        verify(mMainTabGridController)
-                .addTabSwitcherViewObserver(mTabSwitcherVisibilityObserverCaptor.capture());
+        verify(mCarouselOrSingleTabSwitcherModuleController)
+                .addTabSwitcherViewObserver(
+                        mCarouselTabSwitcherModuleVisibilityObserverCaptor.capture());
 
         assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.NOT_SHOWN));
         // Sets the current StartSurfaceState to SHOWING_START before calling the
@@ -318,7 +325,7 @@
         // {@link StartSurfaceMediator#showOverview()}.
         showHomepageAndVerify(mediator, StartSurfaceState.SHOWING_START);
 
-        verify(mMainTabGridController).showTabSwitcherView(eq(false));
+        verify(mCarouselOrSingleTabSwitcherModuleController).showTabSwitcherView(eq(false));
         verify(mOmniboxStub, times(2))
                 .addUrlFocusChangeListener(mUrlFocusChangeListenerCaptor.capture());
         assertThat(mPropertyModel.get(IS_INCOGNITO), equalTo(false));
@@ -327,8 +334,8 @@
         assertThat(mPropertyModel.get(MV_TILES_VISIBLE), equalTo(true));
         assertThat(mPropertyModel.get(IS_SHOWING_OVERVIEW), equalTo(true));
 
-        mTabSwitcherVisibilityObserverCaptor.getValue().startedShowing();
-        mTabSwitcherVisibilityObserverCaptor.getValue().finishedShowing();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().startedShowing();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().finishedShowing();
 
         UrlFocusChangeListener urlFocusChangeListener =
                 mUrlFocusChangeListenerCaptor.getAllValues().get(1);
@@ -340,13 +347,13 @@
         assertThat(mPropertyModel.get(IS_VOICE_RECOGNITION_BUTTON_VISIBLE), equalTo(true));
 
         mediator.hideTabSwitcherView(true);
-        verify(mMainTabGridController).hideTabSwitcherView(eq(true));
+        verify(mCarouselOrSingleTabSwitcherModuleController).hideTabSwitcherView(eq(true));
 
-        mTabSwitcherVisibilityObserverCaptor.getValue().startedHiding();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().startedHiding();
         assertThat(mPropertyModel.get(IS_SHOWING_OVERVIEW), equalTo(false));
         verify(mOmniboxStub).removeUrlFocusChangeListener(mUrlFocusChangeListenerCaptor.getValue());
 
-        mTabSwitcherVisibilityObserverCaptor.getValue().finishedHiding();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().finishedHiding();
 
         // TODO(crbug.com/1020223): Test the other SurfaceMode.SINGLE_PANE operations.
     }
@@ -831,8 +838,9 @@
 
         StartSurfaceMediator mediator =
                 createStartSurfaceMediator(/* isStartSurfaceEnabled= */ true);
-        verify(mMainTabGridController)
-                .addTabSwitcherViewObserver(mTabSwitcherVisibilityObserverCaptor.capture());
+        verify(mCarouselOrSingleTabSwitcherModuleController)
+                .addTabSwitcherViewObserver(
+                        mCarouselTabSwitcherModuleVisibilityObserverCaptor.capture());
         mediator.setSecondaryTasksSurfacePropertyModel(mSecondaryTasksSurfacePropertyModel);
         assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.NOT_SHOWN));
 
@@ -844,8 +852,8 @@
         assertThat(mPropertyModel.get(BOTTOM_BAR_HEIGHT), equalTo(30));
         assertThat(mSecondaryTasksSurfacePropertyModel.get(BOTTOM_BAR_HEIGHT), equalTo(0));
 
-        mTabSwitcherVisibilityObserverCaptor.getValue().startedShowing();
-        mTabSwitcherVisibilityObserverCaptor.getValue().finishedShowing();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().startedShowing();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().finishedShowing();
 
         mBrowserControlsStateProviderCaptor.getValue().onBottomControlsHeightChanged(0, 0);
         assertThat(mPropertyModel.get(BOTTOM_BAR_HEIGHT), equalTo(0));
@@ -856,7 +864,7 @@
         assertThat(mSecondaryTasksSurfacePropertyModel.get(BOTTOM_BAR_HEIGHT), equalTo(0));
 
         mediator.hideTabSwitcherView(false);
-        mTabSwitcherVisibilityObserverCaptor.getValue().startedHiding();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().startedHiding();
         verify(mBrowserControlsStateProvider)
                 .removeObserver(mBrowserControlsStateProviderCaptor.getValue());
     }
@@ -949,8 +957,9 @@
 
         StartSurfaceMediator mediator =
                 createStartSurfaceMediator(/* isStartSurfaceEnabled= */ true);
-        verify(mMainTabGridController)
-                .addTabSwitcherViewObserver(mTabSwitcherVisibilityObserverCaptor.capture());
+        verify(mCarouselOrSingleTabSwitcherModuleController)
+                .addTabSwitcherViewObserver(
+                        mCarouselTabSwitcherModuleVisibilityObserverCaptor.capture());
 
         if (!ChromeFeatureList.sStartSurfaceRefactor.isEnabled()) {
             assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.NOT_SHOWN));
@@ -958,7 +967,7 @@
         }
         showHomepageAndVerify(mediator, StartSurfaceState.SHOWN_HOMEPAGE);
         verify(mTabModelSelector).addObserver(mTabModelSelectorObserverCaptor.capture());
-        verify(mMainTabGridController).showTabSwitcherView(eq(false));
+        verify(mCarouselOrSingleTabSwitcherModuleController).showTabSwitcherView(eq(false));
         verify(mOmniboxStub, times(2))
                 .addUrlFocusChangeListener(mUrlFocusChangeListenerCaptor.capture());
         assertThat(mPropertyModel.get(IS_FAKE_SEARCH_BOX_VISIBLE), equalTo(true));
@@ -1028,8 +1037,9 @@
 
         StartSurfaceMediator mediator =
                 createStartSurfaceMediator(/* isStartSurfaceEnabled= */ true);
-        verify(mMainTabGridController)
-                .addTabSwitcherViewObserver(mTabSwitcherVisibilityObserverCaptor.capture());
+        verify(mCarouselOrSingleTabSwitcherModuleController)
+                .addTabSwitcherViewObserver(
+                        mCarouselTabSwitcherModuleVisibilityObserverCaptor.capture());
 
         assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.NOT_SHOWN));
         mediator.showOverview(false);
@@ -1044,14 +1054,15 @@
 
         StartSurfaceMediator mediator =
                 createStartSurfaceMediator(/* isStartSurfaceEnabled= */ true);
-        verify(mMainTabGridController)
-                .addTabSwitcherViewObserver(mTabSwitcherVisibilityObserverCaptor.capture());
+        verify(mCarouselOrSingleTabSwitcherModuleController)
+                .addTabSwitcherViewObserver(
+                        mCarouselTabSwitcherModuleVisibilityObserverCaptor.capture());
 
         assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.NOT_SHOWN));
 
         mediator.setSecondaryTasksSurfacePropertyModel(mSecondaryTasksSurfacePropertyModel);
         showHomepageAndVerify(mediator, StartSurfaceState.SHOWING_HOMEPAGE);
-        verify(mMainTabGridController).showTabSwitcherView(eq(false));
+        verify(mCarouselOrSingleTabSwitcherModuleController).showTabSwitcherView(eq(false));
         verify(mOmniboxStub, times(2))
                 .addUrlFocusChangeListener(mUrlFocusChangeListenerCaptor.capture());
         assertThat(mPropertyModel.get(IS_FAKE_SEARCH_BOX_VISIBLE), equalTo(true));
@@ -1087,15 +1098,18 @@
 
         StartSurfaceMediator mediator =
                 createStartSurfaceMediator(/* isStartSurfaceEnabled= */ true);
-        InOrder mainTabGridController = inOrder(mMainTabGridController);
-        mainTabGridController.verify(mMainTabGridController)
-                .addTabSwitcherViewObserver(mTabSwitcherVisibilityObserverCaptor.capture());
+        InOrder carouselTabSwitcherModuleController =
+                inOrder(mCarouselOrSingleTabSwitcherModuleController);
+        carouselTabSwitcherModuleController.verify(mCarouselOrSingleTabSwitcherModuleController)
+                .addTabSwitcherViewObserver(
+                        mCarouselTabSwitcherModuleVisibilityObserverCaptor.capture());
 
         assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.NOT_SHOWN));
 
         mediator.setSecondaryTasksSurfacePropertyModel(mSecondaryTasksSurfacePropertyModel);
         showHomepageAndVerify(mediator, StartSurfaceState.SHOWING_PREVIOUS);
-        mainTabGridController.verify(mMainTabGridController).showTabSwitcherView(eq(false));
+        carouselTabSwitcherModuleController.verify(mCarouselOrSingleTabSwitcherModuleController)
+                .showTabSwitcherView(eq(false));
         InOrder omniboxStub = inOrder(mOmniboxStub);
         omniboxStub.verify(mOmniboxStub, times(2))
                 .addUrlFocusChangeListener(mUrlFocusChangeListenerCaptor.capture());
@@ -1103,11 +1117,12 @@
         assertThat(mediator.shouldShowTabSwitcherToolbar(), equalTo(true));
 
         mediator.hideTabSwitcherView(true);
-        mTabSwitcherVisibilityObserverCaptor.getValue().startedHiding();
-        mTabSwitcherVisibilityObserverCaptor.getValue().finishedHiding();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().startedHiding();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().finishedHiding();
 
         showHomepageAndVerify(mediator, StartSurfaceState.SHOWING_PREVIOUS);
-        mainTabGridController.verify(mMainTabGridController).showTabSwitcherView(eq(false));
+        carouselTabSwitcherModuleController.verify(mCarouselOrSingleTabSwitcherModuleController)
+                .showTabSwitcherView(eq(false));
         omniboxStub.verify(mOmniboxStub, times(2))
                 .addUrlFocusChangeListener(mUrlFocusChangeListenerCaptor.capture());
         assertThat(mPropertyModel.get(IS_FAKE_SEARCH_BOX_VISIBLE), equalTo(true));
@@ -1120,8 +1135,8 @@
         assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.SHOWN_TABSWITCHER));
 
         mediator.hideTabSwitcherView(true);
-        mTabSwitcherVisibilityObserverCaptor.getValue().startedHiding();
-        mTabSwitcherVisibilityObserverCaptor.getValue().finishedHiding();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().startedHiding();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().finishedHiding();
 
         mediator.setStartSurfaceState(StartSurfaceState.SHOWING_PREVIOUS);
         mediator.showOverview(false);
@@ -1139,23 +1154,26 @@
 
         StartSurfaceMediator mediator =
                 createStartSurfaceMediator(/* isStartSurfaceEnabled= */ true);
-        InOrder mainTabGridController = inOrder(mMainTabGridController);
-        mainTabGridController.verify(mMainTabGridController)
-                .addTabSwitcherViewObserver(mTabSwitcherVisibilityObserverCaptor.capture());
+        InOrder carouselTabSwitcherModuleController =
+                inOrder(mCarouselOrSingleTabSwitcherModuleController);
+        carouselTabSwitcherModuleController.verify(mCarouselOrSingleTabSwitcherModuleController)
+                .addTabSwitcherViewObserver(
+                        mCarouselTabSwitcherModuleVisibilityObserverCaptor.capture());
         assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.NOT_SHOWN));
 
         mPropertyModel.set(IS_EXPLORE_SURFACE_VISIBLE, true);
         when(mExploreSurfaceCoordinatorFactory.create(anyBoolean(), anyBoolean(), anyInt()))
                 .thenReturn(mExploreSurfaceCoordinator);
         showHomepageAndVerify(mediator, StartSurfaceState.SHOWING_HOMEPAGE);
-        mainTabGridController.verify(mMainTabGridController).showTabSwitcherView(eq(false));
+        carouselTabSwitcherModuleController.verify(mCarouselOrSingleTabSwitcherModuleController)
+                .showTabSwitcherView(eq(false));
         assertThat(mPropertyModel.get(EXPLORE_SURFACE_COORDINATOR),
                 equalTo(mExploreSurfaceCoordinator));
 
         doReturn(TabLaunchType.FROM_START_SURFACE).when(mTab).getLaunchType();
         mediator.hideTabSwitcherView(true);
-        mTabSwitcherVisibilityObserverCaptor.getValue().startedHiding();
-        mTabSwitcherVisibilityObserverCaptor.getValue().finishedHiding();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().startedHiding();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().finishedHiding();
         assertNull(mPropertyModel.get(EXPLORE_SURFACE_COORDINATOR));
 
         showHomepageAndVerify(mediator, StartSurfaceState.SHOWING_PREVIOUS);
@@ -1164,8 +1182,8 @@
 
         doReturn(TabLaunchType.FROM_LINK).when(mTab).getLaunchType();
         mediator.hideTabSwitcherView(true);
-        mTabSwitcherVisibilityObserverCaptor.getValue().startedHiding();
-        mTabSwitcherVisibilityObserverCaptor.getValue().finishedHiding();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().startedHiding();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().finishedHiding();
         assertNull(mPropertyModel.get(EXPLORE_SURFACE_COORDINATOR));
     }
 
@@ -1232,8 +1250,9 @@
         StartSurfaceMediator mediator = createStartSurfaceMediatorWithoutInit(
                 /* isStartSurfaceEnabled= */ true,
                 /* hadWarmStart= */ false);
-        verify(mMainTabGridController)
-                .addTabSwitcherViewObserver(mTabSwitcherVisibilityObserverCaptor.capture());
+        verify(mCarouselOrSingleTabSwitcherModuleController)
+                .addTabSwitcherViewObserver(
+                        mCarouselTabSwitcherModuleVisibilityObserverCaptor.capture());
 
         assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.NOT_SHOWN));
         // Sets the current StartSurfaceState to SHOWING_START before calling the
@@ -1242,12 +1261,12 @@
         // {@link StartSurfaceMediator#showOverview()}.
         showHomepageAndVerify(mediator, StartSurfaceState.SHOWING_START);
         assertThat(mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE), equalTo(false));
-        verify(mMainTabGridController).showTabSwitcherView(eq(false));
+        verify(mCarouselOrSingleTabSwitcherModuleController).showTabSwitcherView(eq(false));
 
-        when(mMainTabGridController.overviewVisible()).thenReturn(true);
+        when(mCarouselOrSingleTabSwitcherModuleController.overviewVisible()).thenReturn(true);
         mediator.initWithNative(
                 mOmniboxStub, mExploreSurfaceCoordinatorFactory, mPrefService, null);
-        when(mMainTabGridController.overviewVisible()).thenReturn(true);
+        when(mCarouselOrSingleTabSwitcherModuleController.overviewVisible()).thenReturn(true);
         mediator.initWithNative(
                 mOmniboxStub, mExploreSurfaceCoordinatorFactory, mPrefService, null);
         assertThat(mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE), equalTo(true));
@@ -1283,7 +1302,9 @@
                 ChromePreferenceKeys.FEED_ARTICLES_LIST_VISIBLE, false);
         Context context = ContextUtils.getApplicationContext();
         Assert.assertTrue(ReturnToChromeUtil.shouldImproveStartWhenFeedIsDisabled(context));
-        doReturn(TabSwitcherType.SINGLE).when(mMainTabGridController).getTabSwitcherType();
+        doReturn(TabSwitcherType.SINGLE)
+                .when(mCarouselOrSingleTabSwitcherModuleController)
+                .getTabSwitcherType();
 
         Resources resources = context.getResources();
         int tasksSurfaceBodyTopMarginWithTab =
@@ -1373,7 +1394,9 @@
         doReturn(false).when(mTabModelSelector).isIncognitoSelected();
         doReturn(mVoiceRecognitionHandler).when(mOmniboxStub).getVoiceRecognitionHandler();
         doReturn(true).when(mVoiceRecognitionHandler).isVoiceSearchEnabled();
-        doReturn(TabSwitcherType.SINGLE).when(mMainTabGridController).getTabSwitcherType();
+        doReturn(TabSwitcherType.SINGLE)
+                .when(mCarouselOrSingleTabSwitcherModuleController)
+                .getTabSwitcherType();
 
         StartSurfaceMediator mediator =
                 createStartSurfaceMediator(/* isStartSurfaceEnabled= */ true);
@@ -1395,7 +1418,9 @@
         doReturn(2).when(mNormalTabModel).getCount();
         doReturn(true).when(mTabModelSelector).isTabStateInitialized();
 
-        doReturn(TabSwitcherType.SINGLE).when(mMainTabGridController).getTabSwitcherType();
+        doReturn(TabSwitcherType.SINGLE)
+                .when(mCarouselOrSingleTabSwitcherModuleController)
+                .getTabSwitcherType();
         MockTab regularTab = new MockTab(1, false);
         regularTab.setGurlOverrideForTesting(JUnitTestGURLs.getGURL(JUnitTestGURLs.NTP_URL));
         when(mTabModelSelector.getCurrentTab()).thenReturn(regularTab);
@@ -1481,8 +1506,9 @@
         doReturn(mVoiceRecognitionHandler).when(mOmniboxStub).getVoiceRecognitionHandler();
 
         StartSurfaceMediator mediator = createStartSurfaceMediator(/*isStartSurfaceEnabled=*/true);
-        verify(mMainTabGridController)
-                .addTabSwitcherViewObserver(mTabSwitcherVisibilityObserverCaptor.capture());
+        verify(mCarouselOrSingleTabSwitcherModuleController)
+                .addTabSwitcherViewObserver(
+                        mCarouselTabSwitcherModuleVisibilityObserverCaptor.capture());
         showHomepageAndVerify(mediator, StartSurfaceState.SHOWN_HOMEPAGE);
 
         assertThat(mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE), equalTo(true));
@@ -1491,14 +1517,14 @@
         UrlFocusChangeListener listener = mUrlFocusChangeListenerCaptor.getAllValues().get(0);
         assertThat(listener, equalTo(mFeedReliabilityLogger));
 
-        mTabSwitcherVisibilityObserverCaptor.getValue().startedShowing();
-        mTabSwitcherVisibilityObserverCaptor.getValue().finishedShowing();
-        mTabSwitcherVisibilityObserverCaptor.getValue().startedHiding();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().startedShowing();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().finishedShowing();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().startedHiding();
 
         mediator.hideTabSwitcherView(true);
         verify(mOmniboxStub).removeUrlFocusChangeListener(listener);
 
-        mTabSwitcherVisibilityObserverCaptor.getValue().finishedHiding();
+        mCarouselTabSwitcherModuleVisibilityObserverCaptor.getValue().finishedHiding();
     }
 
     @Test
@@ -1520,8 +1546,8 @@
         doReturn(false).when(mTabModelSelector).isIncognitoSelected();
         doReturn(mVoiceRecognitionHandler).when(mOmniboxStub).getVoiceRecognitionHandler();
         doReturn(true).when(mVoiceRecognitionHandler).isVoiceSearchEnabled();
-        doAnswer((inv) -> mControllerDialogVisibleSupplier.get())
-                .when(mMainTabGridController)
+        doAnswer((inv) -> mCarouselTabSwitcherModuleControllerDialogVisibleSupplier.get())
+                .when(mCarouselOrSingleTabSwitcherModuleController)
                 .isDialogVisible();
         doAnswer((inv) -> mSecondaryControllerDialogVisibleSupplier.get())
                 .when(mSecondaryTasksSurfaceController)
@@ -1534,31 +1560,31 @@
         mediator.setStartSurfaceState(StartSurfaceState.SHOWN_TABSWITCHER);
         Assert.assertFalse(
                 "Should not intercept back press by default", mediator.shouldInterceptBackPress());
-        mControllerDialogVisibleSupplier.set(true);
+        mCarouselTabSwitcherModuleControllerDialogVisibleSupplier.set(true);
         Assert.assertTrue(mediator.shouldInterceptBackPress());
-        doReturn(true).when(mMainTabGridController).onBackPressed(false);
+        doReturn(true).when(mCarouselOrSingleTabSwitcherModuleController).onBackPressed();
         mediator.onBackPressed();
-        verify(mMainTabGridController).onBackPressed(false);
+        verify(mCarouselOrSingleTabSwitcherModuleController).onBackPressed();
 
-        mControllerDialogVisibleSupplier.set(false);
+        mCarouselTabSwitcherModuleControllerDialogVisibleSupplier.set(false);
         Assert.assertFalse(mediator.shouldInterceptBackPress());
 
-        mControllerDialogVisibleSupplier.set(true);
+        mCarouselTabSwitcherModuleControllerDialogVisibleSupplier.set(true);
         mSecondaryControllerDialogVisibleSupplier.set(true);
         Assert.assertTrue(mediator.shouldInterceptBackPress());
-        doReturn(true).when(mSecondaryTasksSurfaceController).onBackPressed(false);
+        doReturn(true).when(mSecondaryTasksSurfaceController).onBackPressed();
         mediator.onBackPressed();
-        verify(mMainTabGridController).onBackPressed(false);
+        verify(mCarouselOrSingleTabSwitcherModuleController).onBackPressed();
         verify(mSecondaryTasksSurfaceController,
                 description("Secondary task surface has a higher priority of handling back press"))
-                .onBackPressed(false);
+                .onBackPressed();
 
         mSecondaryControllerDialogVisibleSupplier.set(false);
-        mControllerDialogVisibleSupplier.set(false);
+        mCarouselTabSwitcherModuleControllerDialogVisibleSupplier.set(false);
         verify(mSecondaryTasksSurfaceController,
                 description(
                         "Secondary task surface consumes back press when no dialog is visible."))
-                .onBackPressed(false);
+                .onBackPressed();
 
         mediator.setStartSurfaceState(StartSurfaceState.SHOWN_HOMEPAGE);
         mediator.setStartSurfaceState(StartSurfaceState.SHOWN_TABSWITCHER);
@@ -1581,13 +1607,13 @@
 
         showHomepageAndVerify(mediator, StartSurfaceState.SHOWN_HOMEPAGE);
 
-        doReturn(true).when(mMainTabGridController).isDialogVisible();
+        doReturn(true).when(mCarouselOrSingleTabSwitcherModuleController).isDialogVisible();
         mediator.onBackPressed();
-        verify(mMainTabGridController).onBackPressed(true);
+        verify(mCarouselOrSingleTabSwitcherModuleController).onBackPressed();
 
-        doReturn(false).when(mMainTabGridController).isDialogVisible();
+        doReturn(false).when(mCarouselOrSingleTabSwitcherModuleController).isDialogVisible();
         mediator.onBackPressed();
-        verify(mMainTabGridController, times(2)).onBackPressed(true);
+        verify(mCarouselOrSingleTabSwitcherModuleController, times(2)).onBackPressed();
     }
 
     /**
@@ -1610,23 +1636,17 @@
 
         showHomepageAndVerify(mediator, StartSurfaceState.SHOWN_HOMEPAGE);
 
-        doReturn(true).when(mMainTabGridController).isDialogVisible();
-        doReturn(true).when(mSecondaryTasksSurfaceController).isDialogVisible();
-        mediator.onBackPressed();
-        verify(mMainTabGridController, never()).onBackPressed(true);
-        verify(mSecondaryTasksSurfaceController,
-                description("Secondary task surface has a higher priority of handling back press"))
-                .onBackPressed(true);
-
-        doReturn(true).when(mMainTabGridController).isDialogVisible();
+        doReturn(true).when(mCarouselOrSingleTabSwitcherModuleController).isDialogVisible();
         doReturn(false).when(mSecondaryTasksSurfaceController).isDialogVisible();
         mediator.onBackPressed();
-        verify(mMainTabGridController).onBackPressed(true);
+        verify(mCarouselOrSingleTabSwitcherModuleController).onBackPressed();
+        verify(mSecondaryTasksSurfaceController, never()).onBackPressed();
 
-        doReturn(false).when(mMainTabGridController).isDialogVisible();
+        doReturn(false).when(mCarouselOrSingleTabSwitcherModuleController).isDialogVisible();
         doReturn(false).when(mSecondaryTasksSurfaceController).isDialogVisible();
         mediator.onBackPressed();
-        verify(mMainTabGridController, times(2)).onBackPressed(true);
+        verify(mCarouselOrSingleTabSwitcherModuleController, times(2)).onBackPressed();
+        verify(mSecondaryTasksSurfaceController, never()).onBackPressed();
     }
 
     @Test
@@ -1641,13 +1661,13 @@
 
         showHomepageAndVerify(mediator, null);
 
-        doReturn(true).when(mMainTabGridController).isDialogVisible();
+        doReturn(true).when(mCarouselOrSingleTabSwitcherModuleController).isDialogVisible();
         mediator.onBackPressed();
-        verify(mMainTabGridController, times(1)).onBackPressed(true);
+        verify(mCarouselOrSingleTabSwitcherModuleController, times(1)).onBackPressed();
 
-        doReturn(false).when(mMainTabGridController).isDialogVisible();
+        doReturn(false).when(mCarouselOrSingleTabSwitcherModuleController).isDialogVisible();
         mediator.onBackPressed();
-        verify(mMainTabGridController, times(2)).onBackPressed(true);
+        verify(mCarouselOrSingleTabSwitcherModuleController, times(2)).onBackPressed();
     }
 
     /**
@@ -1668,15 +1688,15 @@
         mediator.setStartSurfaceState(StartSurfaceState.SHOWN_TABSWITCHER);
         Assert.assertEquals(StartSurfaceState.SHOWN_TABSWITCHER, mediator.getStartSurfaceState());
         // The primary task surface is invisible when showing the Tab Switcher.
-        doReturn(false).when(mMainTabGridController).isDialogVisible();
+        doReturn(false).when(mCarouselOrSingleTabSwitcherModuleController).isDialogVisible();
 
         doReturn(true).when(mSecondaryTasksSurfaceController).isDialogVisible();
         mediator.onBackPressed();
-        verify(mMainTabGridController, never()).onBackPressed(false);
-        verify(mSecondaryTasksSurfaceController).onBackPressed(false);
+        verify(mCarouselOrSingleTabSwitcherModuleController, never()).onBackPressed();
+        verify(mSecondaryTasksSurfaceController).onBackPressed();
 
         doReturn(false).when(mSecondaryTasksSurfaceController).isDialogVisible();
-        verify(mSecondaryTasksSurfaceController).onBackPressed(false);
+        verify(mSecondaryTasksSurfaceController).onBackPressed();
 
         mediator.setStartSurfaceState(StartSurfaceState.SHOWN_HOMEPAGE);
         mediator.setStartSurfaceState(StartSurfaceState.SHOWN_TABSWITCHER);
@@ -1743,8 +1763,9 @@
 
     private StartSurfaceMediator createStartSurfaceMediatorWithoutInit(
             boolean isStartSurfaceEnabled, boolean hadWarmStart) {
-        return new StartSurfaceMediator(mMainTabGridController, null /* tabSwitcherContainer */,
-                mTabModelSelector, !isStartSurfaceEnabled ? null : mPropertyModel,
+        return new StartSurfaceMediator(mCarouselOrSingleTabSwitcherModuleController,
+                null /* tabSwitcherContainer */, mTabModelSelector,
+                !isStartSurfaceEnabled ? null : mPropertyModel,
                 isStartSurfaceEnabled ? mSecondaryTasksSurfaceInitializer : null,
                 isStartSurfaceEnabled, ContextUtils.getApplicationContext(),
                 mBrowserControlsStateProvider, mActivityStateChecker, true /* excludeQueryTiles */,
diff --git a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediatorUnitTest.java b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediatorUnitTest.java
index 66612b7..b297d9ca 100644
--- a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediatorUnitTest.java
+++ b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediatorUnitTest.java
@@ -6,7 +6,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyLong;
@@ -37,7 +36,6 @@
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabSelectionType;
-import org.chromium.chrome.browser.tabmodel.TabList;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelFilterProvider;
 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
@@ -252,32 +250,4 @@
 
         mMediator.hideTabSwitcherView(true);
     }
-
-    @Test
-    public void onBackPressed() {
-        assertFalse(mMediator.overviewVisible());
-        mMediator.setOnTabSelectingListener(mOnTabSelectingListener);
-        mMediator.addTabSwitcherViewObserver(mTabSwitcherViewObserver);
-
-        mMediator.onHomepageChanged(false);
-        assertNotEquals(Boolean.TRUE, mMediator.getHandleBackPressChangedSupplier().get());
-        assertFalse(mMediator.onBackPressed(false));
-
-        mMediator.showTabSwitcherView(true);
-        assertEquals(Boolean.TRUE, mMediator.getHandleBackPressChangedSupplier().get());
-        assertTrue(mMediator.onBackPressed(false));
-        verify(mOnTabSelectingListener).onTabSelecting(anyLong(), eq(mTabId));
-
-        mMediator.hideTabSwitcherView(true);
-        assertEquals(Boolean.FALSE, mMediator.getHandleBackPressChangedSupplier().get());
-        doReturn(TabList.INVALID_TAB_INDEX).when(mTabModelSelector).getCurrentTabId();
-        mMediator.showTabSwitcherView(true);
-        assertEquals(Boolean.FALSE, mMediator.getHandleBackPressChangedSupplier().get());
-        assertFalse(mMediator.onBackPressed(false));
-
-        doReturn(mTabId).when(mTabModelSelector).getCurrentTabId();
-        doReturn(true).when(mTabModelSelector).isIncognitoSelected();
-        assertEquals(Boolean.FALSE, mMediator.getHandleBackPressChangedSupplier().get());
-        assertFalse(mMediator.onBackPressed(false));
-    }
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java
index ddc645a..b11bebe 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java
@@ -10,11 +10,13 @@
 
 import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.chrome.browser.back_press.BackPressManager;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.compositor.layouts.Layout;
 import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
@@ -93,6 +95,7 @@
      * @param modalDialogManager Manages modal dialogs.
      * @param incognitoReauthControllerSupplier {@link OneshotSupplier<IncognitoReauthController>}
      *         to detect pending re-auth when tab switcher is shown.
+     * @param backPressManager {@link BackPressManager} to handle back press gesture.
      * @return The {@link TabSwitcher}.
      */
     TabSwitcher createGridTabSwitcher(@NonNull Activity activity,
@@ -109,7 +112,8 @@
             @NonNull Supplier<DynamicResourceLoader> dynamicResourceLoaderSupplier,
             @NonNull SnackbarManager snackbarManager,
             @NonNull ModalDialogManager modalDialogManager,
-            @NonNull OneshotSupplier<IncognitoReauthController> incognitoReauthControllerSupplier);
+            @NonNull OneshotSupplier<IncognitoReauthController> incognitoReauthControllerSupplier,
+            @Nullable BackPressManager backPressManager);
 
     /**
      * Create the {@link TabSwitcher} to display Tabs in carousel.
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java
index 67dab242..f2f58339 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java
@@ -11,12 +11,14 @@
 import android.view.ViewGroup;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import org.chromium.base.SysUtils;
 import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.chrome.browser.back_press.BackPressManager;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.compositor.layouts.Layout;
 import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
@@ -70,7 +72,8 @@
             @NonNull Supplier<DynamicResourceLoader> dynamicResourceLoaderSupplier,
             @NonNull SnackbarManager snackbarManager,
             @NonNull ModalDialogManager modalDialogManager,
-            @NonNull OneshotSupplier<IncognitoReauthController> incognitoReauthControllerSupplier) {
+            @NonNull OneshotSupplier<IncognitoReauthController> incognitoReauthControllerSupplier,
+            @Nullable BackPressManager backPressManager) {
         if (UmaSessionStats.isMetricsServiceAvailable()) {
             UmaSessionStats.registerSyntheticFieldTrial(
                     ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID + SYNTHETIC_TRIAL_POSTFIX,
@@ -86,7 +89,7 @@
                         ? TabListCoordinator.TabListMode.LIST
                         : TabListCoordinator.TabListMode.GRID,
                 rootView, dynamicResourceLoaderSupplier, snackbarManager, modalDialogManager,
-                incognitoReauthControllerSupplier);
+                incognitoReauthControllerSupplier, backPressManager);
     }
 
     @Override
@@ -109,7 +112,7 @@
                 menuOrKeyboardActionController, containerView, shareDelegateSupplier,
                 multiWindowModeStateDispatcher, scrimCoordinator,
                 TabListCoordinator.TabListMode.CAROUSEL, rootView, dynamicResourceLoaderSupplier,
-                snackbarManager, modalDialogManager, null);
+                snackbarManager, modalDialogManager, null, null);
     }
 
     @Override
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java
index 8edcb57b..b9aef63 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java
@@ -119,11 +119,8 @@
         /**
          * Called by the StartSurfaceLayout when the system back button is pressed.
          * @return Whether or not the TabSwitcher consumed the event.
-         * @param isOnHomepage Whether the Start surface is showing.
          */
-        // TODO(crbug.com/1315676): Remove the parameter when tab switcher and start surface are
-        // decoupled.
-        boolean onBackPressed(boolean isOnHomepage);
+        boolean onBackPressed();
 
         /**
          * Called after the Chrome activity is launched.
@@ -151,11 +148,10 @@
 
         /**
          * Called when start surface is showing or hiding.
-         * @param isOnHomepage Whether the Start surface is showing.
          */
         // TODO(crbug.com/1315676): Remove this API when tab switcher and start surface are
         // decoupled.
-        void onHomepageChanged(boolean isOnHomepage);
+        void onHomepageChanged();
 
         /**
          * Sets the parent view for snackbars. If <code>null</code> is given, the original parent
@@ -278,4 +274,6 @@
      */
     @Nullable
     TabSwitcherCustomViewManager getTabSwitcherCustomViewManager();
+
+    boolean onBackPressed();
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
index 0f48901f..775b937 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
@@ -24,6 +24,7 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.chrome.browser.back_press.BackPressManager;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -170,8 +171,8 @@
             @NonNull Supplier<DynamicResourceLoader> dynamicResourceLoaderSupplier,
             @NonNull SnackbarManager snackbarManager,
             @NonNull ModalDialogManager modalDialogManager,
-            @Nullable OneshotSupplier<IncognitoReauthController>
-                    incognitoReauthControllerSupplier) {
+            @Nullable OneshotSupplier<IncognitoReauthController> incognitoReauthControllerSupplier,
+            @Nullable BackPressManager backPressManager) {
         try (TraceEvent e = TraceEvent.scoped("TabSwitcherCoordinator.constructor")) {
             mActivity = activity;
             mMode = mode;
@@ -197,7 +198,8 @@
 
             mMediator = new TabSwitcherMediator(activity, this, containerViewModel,
                     tabModelSelector, browserControls, container, tabContentManager, this, this,
-                    multiWindowModeStateDispatcher, mode, incognitoReauthControllerSupplier);
+                    multiWindowModeStateDispatcher, mode, incognitoReauthControllerSupplier,
+                    backPressManager);
 
             mTabSwitcherCustomViewManager = new TabSwitcherCustomViewManager(mMediator);
 
@@ -578,6 +580,11 @@
     }
 
     @Override
+    public boolean onBackPressed() {
+        return mMediator.onBackPressed();
+    }
+
+    @Override
     public int getTabListTopOffset() {
         return mTabListCoordinator.getTabListTopOffset();
     }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayout.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayout.java
index f896628..3e31bf6 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayout.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayout.java
@@ -336,7 +336,7 @@
 
     @Override
     public boolean onBackPressed() {
-        return mController.onBackPressed(false);
+        return mController.onBackPressed();
     }
 
     @Override
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
index b9ba938..0cc31e4 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
@@ -66,6 +66,7 @@
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.features.start_surface.StartSurfaceUserData;
 import org.chromium.chrome.tab_ui.R;
+import org.chromium.components.browser_ui.widget.gesture.BackPressHandler;
 import org.chromium.ui.modelutil.PropertyModel;
 
 import java.util.List;
@@ -77,7 +78,7 @@
 class TabSwitcherMediator implements TabSwitcher.Controller, TabListRecyclerView.VisibilityListener,
                                      TabListMediator.GridCardOnClickListenerProvider,
                                      PriceMessageService.PriceWelcomeMessageReviewActionProvider,
-                                     TabSwitcherCustomViewManager.Delegate {
+                                     TabSwitcherCustomViewManager.Delegate, BackPressHandler {
     private static final String TAG = "TabSwitcherMediator";
 
     // This should be the same as TabListCoordinator.GRID_LAYOUT_SPAN_COUNT for the selected tab
@@ -152,7 +153,6 @@
             .TabSelectionEditorController mTabSelectionEditorController;
     private TabSwitcher.OnTabSelectingListener mOnTabSelectingListener;
     private PriceMessageService mPriceMessageService;
-    private boolean mIsOnHomepage;
 
     /**
      * This allows to check if re-auth is pending when tab switcher is shown in Incognito mode.
@@ -278,6 +278,7 @@
      * @param mode One of the {@link TabListMode}.
      * @param incognitoReauthControllerSupplier {@link OneshotSupplier<IncognitoReauthController>}
      *         to detect pending re-auth when tab switcher is shown.
+     * @param backPressManager {@link BackPressManager} to handle back press gesture.
      */
     TabSwitcherMediator(Context context, ResetHandler resetHandler,
             PropertyModel containerViewModel, TabModelSelector tabModelSelector,
@@ -285,8 +286,8 @@
             TabContentManager tabContentManager, MessageItemsController messageItemsController,
             PriceWelcomeMessageController priceWelcomeMessageController,
             MultiWindowModeStateDispatcher multiWindowModeStateDispatcher, @TabListMode int mode,
-            @Nullable OneshotSupplier<IncognitoReauthController>
-                    incognitoReauthControllerSupplier) {
+            @Nullable OneshotSupplier<IncognitoReauthController> incognitoReauthControllerSupplier,
+            @Nullable BackPressManager backPressManager) {
         mResetHandler = resetHandler;
         mContainerViewModel = containerViewModel;
         mTabModelSelector = tabModelSelector;
@@ -495,6 +496,10 @@
         if (mMode == TabListMode.GRID) {
             mContainerViewModel.set(BOTTOM_PADDING,
                     (int) context.getResources().getDimension(R.dimen.tab_grid_bottom_padding));
+            if (backPressManager != null && BackPressManager.isEnabled()) {
+                backPressManager.addHandler(this, BackPressHandler.Type.TAB_SWITCHER);
+                notifyBackPressStateChangedInternal();
+            }
         }
 
         mContainerView = containerView;
@@ -829,7 +834,15 @@
     }
 
     @Override
-    public boolean onBackPressed(boolean isOnHomepage) {
+    public boolean onBackPressed() {
+        boolean ret = onBackPressedInternal();
+        if (ret) {
+            BackPressManager.record(BackPressHandler.Type.TAB_SWITCHER);
+        }
+        return ret;
+    }
+
+    private boolean onBackPressedInternal() {
         // The TabSelectionEditor dialog can be shown on the Start surface without showing the Grid
         // Tab switcher, so skip the check of visibility of mContainerViewModel here.
         if (mTabSelectionEditorController != null
@@ -852,7 +865,7 @@
         }
 
         // When the Start surface is showing, we no longer need to call onTabSelecting().
-        if (isOnHomepage && mMode == TabListCoordinator.TabListMode.CAROUSEL) return false;
+        if (mMode == TabListCoordinator.TabListMode.CAROUSEL) return false;
 
         if (mTabModelSelector.getCurrentTab() == null) {
             assert !BackPressManager.isEnabled() : "No tab: Backpress must be handled";
@@ -866,7 +879,7 @@
 
     @Override
     public void handleBackPress() {
-        boolean ret = onBackPressed(mIsOnHomepage);
+        boolean ret = onBackPressedInternal();
         assert ret;
     }
 
@@ -914,8 +927,7 @@
     }
 
     @Override
-    public void onHomepageChanged(boolean isOnHomepage) {
-        mIsOnHomepage = isOnHomepage;
+    public void onHomepageChanged() {
         notifyBackPressStateChangedInternal();
     }
 
@@ -1117,7 +1129,7 @@
         if (!mContainerViewModel.get(IS_VISIBLE)) return false;
 
         // When the Start surface is showing, we no longer need to call onTabSelecting().
-        if (mIsOnHomepage && mMode == TabListCoordinator.TabListMode.CAROUSEL) return false;
+        if (mMode == TabListCoordinator.TabListMode.CAROUSEL) return false;
 
         if (mTabModelSelector.getCurrentTab() == null) return false;
 
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java
index 252efbf..1089f51 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java
@@ -235,7 +235,7 @@
         mMediator = new TabSwitcherMediator(mContext, mResetHandler, mModel, mTabModelSelector,
                 mBrowserControlsStateProvider, mCompositorViewHolder, null, mMessageItemsController,
                 mPriceWelcomeMessageController, mMultiWindowModeStateDispatcher,
-                TabListCoordinator.TabListMode.GRID, mIncognitoReauthControllerSupplier);
+                TabListCoordinator.TabListMode.GRID, mIncognitoReauthControllerSupplier, null);
 
         mMediator.initWithNative(controller, null);
         mMediator.addTabSwitcherViewObserver(mTabSwitcherViewObserver);
@@ -909,14 +909,14 @@
         new TabSwitcherMediator(mContext, mResetHandler, mModel, mTabModelSelector,
                 mBrowserControlsStateProvider, mCompositorViewHolder, null, mMessageItemsController,
                 mPriceWelcomeMessageController, mMultiWindowModeStateDispatcher,
-                TabListCoordinator.TabListMode.GRID, mIncognitoReauthControllerSupplier);
+                TabListCoordinator.TabListMode.GRID, mIncognitoReauthControllerSupplier, null);
         assertEquals(16, mModel.get(TabListContainerProperties.BOTTOM_PADDING));
 
         mModel.set(TabListContainerProperties.BOTTOM_PADDING, 0);
         new TabSwitcherMediator(mContext, mResetHandler, mModel, mTabModelSelector,
                 mBrowserControlsStateProvider, mCompositorViewHolder, null, mMessageItemsController,
                 mPriceWelcomeMessageController, mMultiWindowModeStateDispatcher,
-                TabListCoordinator.TabListMode.STRIP, mIncognitoReauthControllerSupplier);
+                TabListCoordinator.TabListMode.STRIP, mIncognitoReauthControllerSupplier, null);
         assertEquals(0, mModel.get(TabListContainerProperties.BOTTOM_PADDING));
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 5603ef67..40c2144 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -779,8 +779,8 @@
                 mRootUiCoordinator.getScrimCoordinator(),
                 /* rootView= */ tabSwitcherContainer,
                 compositorViewHolder::getDynamicResourceLoader, getSnackbarManager(),
-                getModalDialogManager(),
-                mRootUiCoordinator.getIncognitoReauthControllerSupplier()));
+                getModalDialogManager(), mRootUiCoordinator.getIncognitoReauthControllerSupplier(),
+                mBackPressManager));
     }
 
     private void setupCompositorContentPostNative() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabHeightStrategy.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabHeightStrategy.java
index dbf20011..1056832 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabHeightStrategy.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabHeightStrategy.java
@@ -251,7 +251,7 @@
         initializeHeight();
         updateShadowOffset();
         maybeInvokeResizeCallback();
-        mRestoreAfterFindPage = false;
+        if (!isFixedHeight()) mRestoreAfterFindPage = false;
     }
 
     private int initialY() {
@@ -299,6 +299,10 @@
                 // We should update CCT position before Window#FLAG_LAYOUT_NO_LIMITS is set,
                 // otherwise it is not possible to get the correct content height.
                 mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
+
+                // Clean up the state initiated by IME so the height can be restored when
+                // rotating back to non-full-height mode later.
+                if (mVersionCompat.setImeStateCallback(null)) mStatus = HeightStatus.INITIAL_HEIGHT;
             }
             mPositionUpdater.run();
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabVersionCompat.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabVersionCompat.java
index 9736ab9..873821f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabVersionCompat.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabVersionCompat.java
@@ -20,6 +20,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
+import org.chromium.ui.KeyboardVisibilityDelegate;
 
 import java.util.List;
 
@@ -56,12 +57,15 @@
      * Sets the callback to invoke when IME (soft keyboard) visible state is updated.
      * @param callback Callback to invoke upon IME state update. Can be {@code null} to
      *        remove the callback.
+     * @return {@code true} if setting (or removing) happened as expected.
      */
-    void setImeStateCallback(@Nullable Callback<Boolean> callback) {}
+    abstract boolean setImeStateCallback(@Nullable Callback<Boolean> callback);
 
     /** Implementation that supports R+ */
     @RequiresApi(Build.VERSION_CODES.R)
     private static class PartialCustomTabVersionCompatR extends PartialCustomTabVersionCompat {
+        private WindowInsetsAnimation.Callback mAnimCallback;
+
         private PartialCustomTabVersionCompatR(Activity activity, Runnable positionUpdater) {
             super(activity, positionUpdater);
         }
@@ -104,27 +108,33 @@
         }
 
         @Override
-        void setImeStateCallback(Callback<Boolean> callback) {
-            View view = mActivity.getWindow().getDecorView();
-            var animCallback = callback == null
-                    ? null
-                    : new WindowInsetsAnimation.Callback(
-                            WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP) {
-                          @Override
-                          public WindowInsets onProgress(@NonNull WindowInsets insets,
-                                  @NonNull List<WindowInsetsAnimation> runningAnimations) {
-                              return insets;
-                          }
+        boolean setImeStateCallback(Callback<Boolean> callback) {
+            boolean update = (callback == null) ^ (mAnimCallback == null);
+            if (callback == null && mAnimCallback != null) {
+                mAnimCallback = null;
+            } else if (callback != null && mAnimCallback == null) {
+                mAnimCallback = new WindowInsetsAnimation.Callback(
+                        WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP) {
+                    @Override
+                    public WindowInsets onProgress(@NonNull WindowInsets insets,
+                            @NonNull List<WindowInsetsAnimation> runningAnimations) {
+                        return insets;
+                    }
 
-                          @Override
-                          public void onEnd(@NonNull WindowInsetsAnimation animation) {
-                              WindowInsets insets = mActivity.getWindowManager()
-                                                            .getCurrentWindowMetrics()
-                                                            .getWindowInsets();
-                              callback.onResult(insets.isVisible(WindowInsets.Type.ime()));
-                          }
-                      };
-            view.setWindowInsetsAnimationCallback(animCallback);
+                    @Override
+                    public void onEnd(@NonNull WindowInsetsAnimation animation) {
+                        WindowInsets insets = mActivity.getWindowManager()
+                                                      .getCurrentWindowMetrics()
+                                                      .getWindowInsets();
+                        callback.onResult(insets.isVisible(WindowInsets.Type.ime()));
+                    }
+                };
+            }
+            if (update) {
+                View view = mActivity.getWindow().getDecorView();
+                view.setWindowInsetsAnimationCallback(mAnimCallback);
+            }
+            return update;
         }
     }
 
@@ -135,6 +145,8 @@
 
     /** Implementation that supports version below R */
     private static class PartialCustomTabVersionCompatLegacy extends PartialCustomTabVersionCompat {
+        private View.OnLayoutChangeListener mLayoutListener;
+
         private PartialCustomTabVersionCompatLegacy(Activity activity, Runnable positionUpdater) {
             super(activity, positionUpdater);
         }
@@ -239,5 +251,32 @@
             display.getSize(size);
             return size.y;
         }
+
+        @Override
+        boolean setImeStateCallback(Callback<Boolean> callback) {
+            View contentFrame = mActivity.findViewById(android.R.id.content);
+            if (callback == null && mLayoutListener != null) {
+                contentFrame.removeOnLayoutChangeListener(mLayoutListener);
+                mLayoutListener = null;
+                return true;
+            } else if (callback != null && mLayoutListener == null) {
+                // Ignores the callback if already added.
+                mLayoutListener =
+                        (view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+                    if (oldBottom - oldTop >= bottom - top) return;
+
+                    // Note that keyboard visibility might not always be correct - i.e. can be false
+                    // when it is visible. In worst case, tab is back to initial height and remains
+                    // hidden by the keyboard. Users either have to dismiss the keyboard, or expand
+                    // the tab (in non-fixed-height mode) to use it again.
+                    boolean imeVisible = KeyboardVisibilityDelegate.getInstance().isKeyboardShowing(
+                            mActivity, view);
+                    callback.onResult(imeVisible);
+                };
+                contentFrame.addOnLayoutChangeListener(mLayoutListener);
+                return true;
+            }
+            return false; // adding or removing did not happen
+        }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
index 15a207f..881d650 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
@@ -27,7 +27,6 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorSupplier;
 import org.chromium.components.external_intents.ExternalNavigationDelegate;
-import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.url.GURL;
@@ -114,12 +113,6 @@
     }
 
     @Override
-    public void loadUrlIfPossible(LoadUrlParams loadUrlParams) {
-        if (!hasValidTab()) return;
-        mTab.loadUrl(loadUrlParams);
-    }
-
-    @Override
     public boolean isApplicationInForeground() {
         return ApplicationStatus.getStateForApplication()
                 == ApplicationState.HAS_RUNNING_ACTIVITIES;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateClientImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateClientImpl.java
index 2840533b..f5437aef 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateClientImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateClientImpl.java
@@ -14,6 +14,7 @@
 import org.chromium.components.external_intents.InterceptNavigationDelegateClient;
 import org.chromium.components.external_intents.InterceptNavigationDelegateImpl;
 import org.chromium.components.external_intents.RedirectHandler;
+import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.WindowAndroid;
@@ -27,6 +28,10 @@
     private final TabObserver mTabObserver;
     private InterceptNavigationDelegateImpl mInterceptNavigationDelegate;
 
+    public static InterceptNavigationDelegateClientImpl createForTesting(Tab tab) {
+        return new InterceptNavigationDelegateClientImpl(tab);
+    }
+
     InterceptNavigationDelegateClientImpl(Tab tab) {
         mTab = (TabImpl) tab;
         mTabObserver = new EmptyTabObserver() {
@@ -135,4 +140,10 @@
         mTab.removeObserver(mTabObserver);
         mInterceptNavigationDelegate = null;
     }
+
+    @Override
+    public void loadUrlIfPossible(LoadUrlParams loadUrlParams) {
+        if (mTab.isDestroyed() || mTab.isClosing()) return;
+        mTab.loadUrl(loadUrlParams);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTabHelper.java
index 883795a..fca3664d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTabHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTabHelper.java
@@ -14,8 +14,14 @@
     private static final Class<InterceptNavigationDelegateTabHelper> USER_DATA_KEY =
             InterceptNavigationDelegateTabHelper.class;
 
-    private final InterceptNavigationDelegateImpl mInterceptNavigationDelegate;
-    private final InterceptNavigationDelegateClientImpl mInterceptNavigationDelegateClient;
+    private InterceptNavigationDelegateImpl mInterceptNavigationDelegate;
+    private InterceptNavigationDelegateClientImpl mInterceptNavigationDelegateClient;
+
+    public static void setDelegateForTesting(Tab tab, InterceptNavigationDelegateImpl delegate) {
+        InterceptNavigationDelegateTabHelper helper =
+                tab.getUserDataHost().getUserData(USER_DATA_KEY);
+        helper.mInterceptNavigationDelegate = delegate;
+    }
 
     public static void createForTab(Tab tab) {
         assert get(tab) == null;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
index 559d647..58f64e3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
@@ -69,6 +69,7 @@
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.init.AsyncInitializationActivity;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
+import org.chromium.chrome.browser.tab.InterceptNavigationDelegateClientImpl;
 import org.chromium.chrome.browser.tab.InterceptNavigationDelegateTabHelper;
 import org.chromium.chrome.browser.tab.RedirectHandlerTabHelper;
 import org.chromium.chrome.browser.tab.Tab;
@@ -78,6 +79,7 @@
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.components.embedder_support.util.UrlConstants;
+import org.chromium.components.external_intents.ExternalIntentsFeatures;
 import org.chromium.components.external_intents.ExternalNavigationHandler;
 import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResult;
 import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResultType;
@@ -160,6 +162,8 @@
             BASE_PATH + "navigation_to_cct_via_intent_uri.html";
     private static final String NAVIGATION_TO_FILE_SCHEME_FROM_INTENT_URI =
             BASE_PATH + "navigation_to_file_scheme_via_intent_uri.html";
+    private static final String FALLBACK_URL =
+            "https://play.google.com/store/apps/details?id=com.android.chrome";
     private static final String SUBFRAME_REDIRECT_WITH_PLAY_FALLBACK =
             BASE_PATH + "subframe_navigation_with_play_fallback.html";
     private static final String REDIRECT_TO_OTHER_BROWSER =
@@ -186,13 +190,11 @@
 
     private static class TestTabObserver extends EmptyTabObserver {
         private final CallbackHelper mFinishCallback;
-        private final CallbackHelper mFailCallback;
         private final CallbackHelper mDestroyedCallback;
 
-        TestTabObserver(final CallbackHelper finishCallback, final CallbackHelper failCallback,
-                final CallbackHelper destroyedCallback) {
+        TestTabObserver(
+                final CallbackHelper finishCallback, final CallbackHelper destroyedCallback) {
             mFinishCallback = finishCallback;
-            mFailCallback = failCallback;
             mDestroyedCallback = destroyedCallback;
         }
 
@@ -337,28 +339,28 @@
         });
     }
 
-    private @OverrideUrlLoadingResultType int loadUrlAndWaitForIntentUrl(
+    private OverrideUrlLoadingResult loadUrlAndWaitForIntentUrl(
             final String url, boolean needClick, boolean shouldLaunchExternalIntent) {
         return loadUrlAndWaitForIntentUrl(
                 url, needClick, false, shouldLaunchExternalIntent, url, true);
     }
 
-    private @OverrideUrlLoadingResultType int loadUrlAndWaitForIntentUrl(final String url,
+    private OverrideUrlLoadingResult loadUrlAndWaitForIntentUrl(final String url,
             boolean shouldLaunchExternalIntent, String expectedFinalUrl,
             @PageTransition int transition) {
         return loadUrlAndWaitForIntentUrl(url, false, false, shouldLaunchExternalIntent,
                 expectedFinalUrl, true, null, transition);
     }
 
-    private @OverrideUrlLoadingResultType int loadUrlAndWaitForIntentUrl(final String url,
-            boolean needClick, boolean createsNewTab, final boolean shouldLaunchExternalIntent,
+    private OverrideUrlLoadingResult loadUrlAndWaitForIntentUrl(final String url, boolean needClick,
+            boolean createsNewTab, final boolean shouldLaunchExternalIntent,
             final String expectedFinalUrl, final boolean shouldFailNavigation) {
         return loadUrlAndWaitForIntentUrl(url, needClick, createsNewTab, shouldLaunchExternalIntent,
                 expectedFinalUrl, shouldFailNavigation, null, PageTransition.LINK);
     }
 
-    private @OverrideUrlLoadingResultType int loadUrlAndWaitForIntentUrl(final String url,
-            boolean needClick, boolean createsNewTab, final boolean shouldLaunchExternalIntent,
+    private OverrideUrlLoadingResult loadUrlAndWaitForIntentUrl(final String url, boolean needClick,
+            boolean createsNewTab, final boolean shouldLaunchExternalIntent,
             final String expectedFinalUrl, final boolean shouldFailNavigation, String clickTargetId,
             @PageTransition int transition) {
         final CallbackHelper finishCallback = new CallbackHelper();
@@ -371,7 +373,7 @@
         final InterceptNavigationDelegateImpl[] latestDelegateHolder =
                 new InterceptNavigationDelegateImpl[1];
 
-        AtomicInteger lastResultValue = new AtomicInteger();
+        AtomicReference<OverrideUrlLoadingResult> lastResultValue = new AtomicReference<>();
 
         latestTabHolder[0] = tab;
         latestDelegateHolder[0] = getInterceptNavigationDelegate(tab);
@@ -380,24 +382,25 @@
                 (Pair<GURL, OverrideUrlLoadingResult> result) -> {
             if (result.first.getSpec().equals(url)) return;
             // Ignore the NO_OVERRIDE that comes asynchronously after clobbering the tab.
-            if (lastResultValue.get() == OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB
+            if (lastResultValue.get() != null
+                    && lastResultValue.get().getResultType()
+                            == OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB
                     && result.second.getResultType() == OverrideUrlLoadingResultType.NO_OVERRIDE) {
                 return;
             }
-            lastResultValue.set(result.second.getResultType());
+            lastResultValue.set(result.second);
         };
 
         latestDelegateHolder[0].setResultCallbackForTesting(resultCallback);
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            tab.addObserver(new TestTabObserver(finishCallback, failCallback, destroyedCallback));
+            tab.addObserver(new TestTabObserver(finishCallback, destroyedCallback));
 
             TabModelSelectorObserver selectorObserver = new TabModelSelectorObserver() {
                 @Override
                 public void onNewTabCreated(Tab newTab, @TabCreationState int creationState) {
                     Assert.assertTrue(createsNewTab);
                     newTabCallback.notifyCalled();
-                    newTab.addObserver(
-                            new TestTabObserver(finishCallback, failCallback, destroyedCallback));
+                    newTab.addObserver(new TestTabObserver(finishCallback, destroyedCallback));
                     latestTabHolder[0] = newTab;
                     latestDelegateHolder[0].setResultCallbackForTesting(null);
                     latestDelegateHolder[0] = getInterceptNavigationDelegate(newTab);
@@ -425,7 +428,7 @@
                 finishCallback.waitForCallback(0, 1, 20, TimeUnit.SECONDS);
             } catch (TimeoutException ex) {
                 Assert.fail();
-                return OverrideUrlLoadingResultType.NO_OVERRIDE;
+                return OverrideUrlLoadingResult.forNoOverride();
             }
         }
 
@@ -437,7 +440,7 @@
                     DOMUtils.clickNode(mActivityTestRule.getWebContents(), clickTargetId);
                 } catch (TimeoutException e) {
                     Assert.fail("Failed to click on the target node.");
-                    return OverrideUrlLoadingResultType.NO_OVERRIDE;
+                    return OverrideUrlLoadingResult.forNoOverride();
                 }
             }
         }
@@ -447,7 +450,7 @@
                 failCallback.waitForCallback(0, 1, 20, TimeUnit.SECONDS);
             } catch (TimeoutException ex) {
                 Assert.fail("Haven't received navigation failure of intents.");
-                return OverrideUrlLoadingResultType.NO_OVERRIDE;
+                return OverrideUrlLoadingResult.forNoOverride();
             }
         }
 
@@ -463,7 +466,7 @@
                     destroyedCallback.waitForCallback(0, 1, 20, TimeUnit.SECONDS);
                 } catch (TimeoutException ex) {
                     Assert.fail("Intercepted new tab wasn't destroyed.");
-                    return OverrideUrlLoadingResultType.NO_OVERRIDE;
+                    return OverrideUrlLoadingResult.forNoOverride();
                 }
             }
         }
@@ -477,7 +480,7 @@
                     finishCallback.waitForCallback(1, 1, 20, TimeUnit.SECONDS);
                 } catch (TimeoutException ex) {
                     Assert.fail("Fallback URL is not loaded");
-                    return OverrideUrlLoadingResultType.NO_OVERRIDE;
+                    return OverrideUrlLoadingResult.forNoOverride();
                 }
             }
         }
@@ -486,17 +489,18 @@
         // from the ExternalNavigationHandler. As a result, there is no guarantee
         // when url override result would come.
         CriteriaHelper.pollUiThread(() -> {
-            // Note that we do not distinguish between OVERRIDE_WITH_CLOBBERING_TAB
+            Criteria.checkThat(lastResultValue.get(), Matchers.notNullValue());
+            // Note that we do not distinguish between OVERRIDE_WITH_NAVIGATE_TAB
             // and NO_OVERRIDE since tab clobbering will eventually lead to NO_OVERRIDE.
             // in the tab. Rather, we check the final URL to distinguish between
             // fallback and normal navigation. See crbug.com/487364 for more.
             Tab latestTab = latestTabHolder[0];
             InterceptNavigationDelegateImpl delegate = latestDelegateHolder[0];
             if (shouldLaunchExternalIntent) {
-                Criteria.checkThat(lastResultValue.get(),
+                Criteria.checkThat(lastResultValue.get().getResultType(),
                         Matchers.is(OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT));
             } else {
-                Criteria.checkThat(lastResultValue.get(),
+                Criteria.checkThat(lastResultValue.get().getResultType(),
                         Matchers.not(OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT));
             }
             if (expectedFinalUrl == null) return;
@@ -619,12 +623,12 @@
                 .when(mSpyRedirectHandler)
                 .currentRealtime();
 
-        @OverrideUrlLoadingResultType
-        int result = loadUrlAndWaitForIntentUrl(
+        OverrideUrlLoadingResult result = loadUrlAndWaitForIntentUrl(
                 mTestServer.getURL(NAVIGATION_FROM_XHR_CALLBACK_AND_SHORT_TIMEOUT_PAGE), true,
                 false);
 
-        Assert.assertEquals(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION, result);
+        Assert.assertEquals(
+                OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION, result.getResultType());
 
         assertMessagePresent();
     }
@@ -645,7 +649,8 @@
 
     @Test
     @SmallTest
-    public void testNavigationWithFallbackURLInSubFrame() {
+    @Features.DisableFeatures({ExternalIntentsFeatures.EXTERNAL_NAVIGATION_SUBFRAME_REDIRECTS_NAME})
+    public void testNavigationWithFallbackURLInSubFrame_FallbackDisabled() {
         mActivityTestRule.startMainActivityOnBlankPage();
         // The replace_text parameters for NAVIGATION_WITH_FALLBACK_URL_PAGE, which is loaded in
         // the iframe in NAVIGATION_WITH_FALLBACK_URL_PARENT_FRAME_PAGE, have to go through the
@@ -664,10 +669,60 @@
                 + "&replace_text=" + Base64.encodeToString(paramBase64Value, Base64.URL_SAFE) + ":"
                 + Base64.encodeToString(base64FallbackUrl, Base64.URL_SAFE));
 
-        // Fallback URL from a subframe will not trigger main or sub frame navigation.
-        @OverrideUrlLoadingResultType
-        int result = loadUrlAndWaitForIntentUrl(originalUrl, true, false);
-        Assert.assertEquals(OverrideUrlLoadingResultType.NO_OVERRIDE, result);
+        OverrideUrlLoadingResult result = loadUrlAndWaitForIntentUrl(originalUrl, true, false);
+
+        Assert.assertEquals(
+                OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, result.getResultType());
+        Assert.assertEquals(fallbackUrl, result.getTargetUrl().getSpec());
+    }
+
+    @Test
+    @SmallTest
+    @Features.EnableFeatures({ExternalIntentsFeatures.EXTERNAL_NAVIGATION_SUBFRAME_REDIRECTS_NAME})
+    public void testNavigationWithFallbackURLInSubFrame_FallbackEnabled() throws Exception {
+        mActivityTestRule.startMainActivityOnBlankPage();
+        // The replace_text parameters for NAVIGATION_WITH_FALLBACK_URL_PAGE, which is loaded in
+        // the iframe in NAVIGATION_WITH_FALLBACK_URL_PARENT_FRAME_PAGE, have to go through the
+        // embedded test server twice and, as such, have to be base64-encoded twice.
+        String fallbackUrl = mTestServer.getURL(FALLBACK_LANDING_PATH);
+        byte[] paramBase64Name = ApiCompatibilityUtils.getBytesUtf8("PARAM_BASE64_NAME");
+        byte[] base64ParamFallbackUrl = Base64.encode(
+                ApiCompatibilityUtils.getBytesUtf8("PARAM_FALLBACK_URL"), Base64.URL_SAFE);
+        byte[] paramBase64Value = ApiCompatibilityUtils.getBytesUtf8("PARAM_BASE64_VALUE");
+        byte[] base64FallbackUrl =
+                Base64.encode(ApiCompatibilityUtils.getBytesUtf8(fallbackUrl), Base64.URL_SAFE);
+
+        String originalUrl = mTestServer.getURL(NAVIGATION_WITH_FALLBACK_URL_PARENT_FRAME_PAGE
+                + "?replace_text=" + Base64.encodeToString(paramBase64Name, Base64.URL_SAFE) + ":"
+                + Base64.encodeToString(base64ParamFallbackUrl, Base64.URL_SAFE)
+                + "&replace_text=" + Base64.encodeToString(paramBase64Value, Base64.URL_SAFE) + ":"
+                + Base64.encodeToString(base64FallbackUrl, Base64.URL_SAFE));
+
+        final Tab tab = mActivityTestRule.getActivity().getActivityTab();
+
+        final CallbackHelper subframeRedirect = new CallbackHelper();
+        EmptyTabObserver observer = new EmptyTabObserver() {
+            @Override
+            public void onDidStartNavigationInPrimaryMainFrame(
+                    Tab tab, NavigationHandle navigation) {
+                Assert.assertEquals(originalUrl, navigation.getUrl().getSpec());
+            }
+
+            @Override
+            public void onDidRedirectNavigation(Tab tab, NavigationHandle navigation) {
+                Assert.assertFalse(navigation.isInPrimaryMainFrame());
+                Assert.assertEquals(fallbackUrl, navigation.getUrl().getSpec());
+                subframeRedirect.notifyCalled();
+            }
+        };
+        TestThreadUtils.runOnUiThreadBlocking(() -> { tab.addObserver(observer); });
+
+        // Fallback URL from a subframe will not trigger main navigation.
+        OverrideUrlLoadingResult result =
+                loadUrlAndWaitForIntentUrl(originalUrl, true, false, false, originalUrl, false);
+        Assert.assertEquals(
+                OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, result.getResultType());
+        subframeRedirect.waitForFirst();
     }
 
     @Test
@@ -820,12 +875,75 @@
 
     @Test
     @LargeTest
-    public void testSubframeLoadCannotLaunchPlayApp() throws TimeoutException {
+    @Features.DisableFeatures({ExternalIntentsFeatures.EXTERNAL_NAVIGATION_SUBFRAME_REDIRECTS_NAME})
+    public void testSubframeLoadCannotLaunchPlayApp_FallbackDisabled() throws TimeoutException {
         mActivityTestRule.startMainActivityOnBlankPage();
-        @OverrideUrlLoadingResultType
-        int result = loadUrlAndWaitForIntentUrl(
+        // TODO(https://crbug.com/1365100): Verify the fallback URL is loaded once implemented.
+        OverrideUrlLoadingResult result = loadUrlAndWaitForIntentUrl(
                 mTestServer.getURL(SUBFRAME_REDIRECT_WITH_PLAY_FALLBACK), false, false);
-        Assert.assertEquals(OverrideUrlLoadingResultType.NO_OVERRIDE, result);
+        Assert.assertEquals(
+                OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, result.getResultType());
+        Assert.assertEquals(FALLBACK_URL, result.getTargetUrl().getSpec());
+    }
+
+    @Test
+    @LargeTest
+    @Features.EnableFeatures({ExternalIntentsFeatures.EXTERNAL_NAVIGATION_SUBFRAME_REDIRECTS_NAME})
+    public void testSubframeLoadCannotLaunchPlayApp_FallbackEnabled() throws TimeoutException {
+        String fallbackUrl = "https://play.google.com/store/apps/details?id=com.android.chrome";
+        String mainUrl = mTestServer.getURL(SUBFRAME_REDIRECT_WITH_PLAY_FALLBACK);
+        String redirectUrl = mTestServer.getURL(HELLO_PAGE);
+        mActivityTestRule.startMainActivityOnBlankPage();
+
+        final Tab tab = mActivityTestRule.getActivity().getActivityTab();
+
+        final CallbackHelper subframeExternalProtocol = new CallbackHelper();
+        final CallbackHelper subframeRedirect = new CallbackHelper();
+        EmptyTabObserver observer = new EmptyTabObserver() {
+            @Override
+            public void onDidStartNavigationInPrimaryMainFrame(
+                    Tab tab, NavigationHandle navigation) {
+                Assert.assertEquals(mainUrl, navigation.getUrl().getSpec());
+            }
+
+            @Override
+            public void onDidRedirectNavigation(Tab tab, NavigationHandle navigation) {
+                Assert.assertFalse(navigation.isInPrimaryMainFrame());
+                Assert.assertEquals(redirectUrl, navigation.getUrl().getSpec());
+                subframeRedirect.notifyCalled();
+            }
+        };
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            tab.addObserver(observer);
+
+            InterceptNavigationDelegateClientImpl client =
+                    InterceptNavigationDelegateClientImpl.createForTesting(tab);
+            InterceptNavigationDelegateImpl delegate = new InterceptNavigationDelegateImpl(client) {
+                @Override
+                public GURL handleSubframeExternalProtocol(GURL escapedUrl,
+                        @PageTransition int transition, boolean hasUserGesture,
+                        Origin initiatorOrigin) {
+                    GURL target = super.handleSubframeExternalProtocol(
+                            escapedUrl, transition, hasUserGesture, initiatorOrigin);
+                    Assert.assertEquals(fallbackUrl, target.getSpec());
+                    subframeExternalProtocol.notifyCalled();
+                    // We can't actually load the play store URL in tests.
+                    return new GURL(redirectUrl);
+                }
+            };
+            client.initializeWithDelegate(delegate);
+            delegate.setExternalNavigationHandler(
+                    new ExternalNavigationHandler(new ExternalNavigationDelegateImpl(tab)));
+            delegate.associateWithWebContents(tab.getWebContents());
+            InterceptNavigationDelegateTabHelper.setDelegateForTesting(tab, delegate);
+        });
+
+        OverrideUrlLoadingResult result =
+                loadUrlAndWaitForIntentUrl(mainUrl, false, false, false, mainUrl, false);
+        Assert.assertEquals(
+                OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, result.getResultType());
+        subframeExternalProtocol.waitForFirst();
+        subframeRedirect.waitForFirst();
     }
 
     private void runRedirectToOtherBrowserTest(Instrumentation.ActivityResult chooserResult) {
@@ -1154,10 +1272,10 @@
         mActivityTestRule.startMainActivityOnBlankPage();
 
         GURL url = new GURL(mTestServer.getURL(NAVIGATION_FROM_LONG_TIMEOUT));
-        @OverrideUrlLoadingResultType
-        int result = loadUrlAndWaitForIntentUrl(url.getSpec(), true, false);
+        OverrideUrlLoadingResult result = loadUrlAndWaitForIntentUrl(url.getSpec(), true, false);
 
-        Assert.assertEquals(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION, result);
+        Assert.assertEquals(
+                OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION, result.getResultType());
 
         assertMessagePresent();
     }
@@ -1168,9 +1286,10 @@
         mActivityTestRule.startMainActivityOnBlankPage();
 
         String url = mTestServer.getURL(NAVIGATION_FROM_TIMEOUT_PAGE);
-        @OverrideUrlLoadingResultType
-        int result = loadUrlAndWaitForIntentUrl(url, false, null, PageTransition.AUTO_BOOKMARK);
-        Assert.assertEquals(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION, result);
+        OverrideUrlLoadingResult result =
+                loadUrlAndWaitForIntentUrl(url, false, null, PageTransition.AUTO_BOOKMARK);
+        Assert.assertEquals(
+                OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION, result.getResultType());
         assertMessagePresent();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             TextView button = mActivityTestRule.getActivity().findViewById(
@@ -1198,10 +1317,10 @@
                 + Base64.encodeToString(
                         ApiCompatibilityUtils.getBytesUtf8(fallbackUrl), Base64.URL_SAFE));
 
-        @OverrideUrlLoadingResultType
-        int result = loadUrlAndWaitForIntentUrl(
+        OverrideUrlLoadingResult result = loadUrlAndWaitForIntentUrl(
                 originalUrl, false, fallbackUrl, PageTransition.AUTO_BOOKMARK);
-        Assert.assertEquals(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, result);
+        Assert.assertEquals(
+                OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, result.getResultType());
         Assert.assertNull(getCurrentExternalNavigationMessage());
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java
index c3486164..56aba373 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java
@@ -35,7 +35,6 @@
 import org.chromium.components.external_intents.ExternalNavigationParams;
 import org.chromium.components.external_intents.InterceptNavigationDelegateImpl;
 import org.chromium.content_public.browser.NavigationHandle;
-import org.chromium.content_public.browser.WebContentsObserver;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.content_public.browser.test.util.TouchCommon;
 import org.chromium.net.test.EmbeddedTestServer;
@@ -245,35 +244,4 @@
         Assert.assertEquals(2, mNavParamHistory.size());
         Assert.assertEquals(2, mExternalNavParamHistory.size());
     }
-
-    @Test
-    @MediumTest
-    public void testIframeUrlRedirection() throws TimeoutException {
-        // Will cause handleSubframeExternalProtocol to return this GURL.
-        mSubframeRedirectTarget = new GURL(mTestServer.getURL(HELLO_PAGE));
-        String mainFrameUrl = mTestServer.getURL(IFRAME_CONTAINER_PAGE);
-
-        final Tab tab = sActivityTestRule.getActivity().getActivityTab();
-
-        final CallbackHelper subframeRedirect = new CallbackHelper();
-        WebContentsObserver observer = new WebContentsObserver() {
-            @Override
-            public void didStartNavigationInPrimaryMainFrame(NavigationHandle navigation) {
-                Assert.assertEquals(mainFrameUrl, navigation.getUrl().getSpec());
-            }
-
-            @Override
-            public void didRedirectNavigation(NavigationHandle navigation) {
-                if (navigation.isInPrimaryMainFrame()) return;
-                Assert.assertEquals(mSubframeRedirectTarget, navigation.getUrl());
-                subframeRedirect.notifyCalled();
-            }
-        };
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { tab.getWebContents().addObserver(observer); });
-
-        sActivityTestRule.loadUrl(mainFrameUrl);
-        mSubframeExternalProtocolCalled.waitForFirst();
-        subframeRedirect.waitForFirst();
-    }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabHeightStrategyTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabHeightStrategyTest.java
index 1e19c8a..f9aa133 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabHeightStrategyTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabHeightStrategyTest.java
@@ -51,6 +51,7 @@
 import org.robolectric.shadows.ShadowLooper;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.MetricsUtils.HistogramDelta;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -622,6 +623,67 @@
     }
 
     @Test
+    @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.Q)
+    public void fixedHeightReactsToSoftKeyboardBelowR() {
+        PartialCustomTabHeightStrategy strategy = createPcctAtHeight(500, true);
+        assertTabIsAtInitialPos(getWindowAttributes());
+
+        strategy.onShowSoftInput(() -> {});
+        waitForAnimationToFinish();
+        assertTabIsFullHeight(getWindowAttributes());
+
+        strategy.onImeStateChanged(/*imeVisible=*/true);
+        assertTabIsFullHeight(getWindowAttributes());
+
+        strategy.onImeStateChanged(/*imeVisible=*/false);
+        waitForAnimationToFinish();
+        assertTabIsAtInitialPos(getWindowAttributes());
+    }
+
+    @Test
+    public void fixedHeightRotateWithSoftKeyboard() {
+        PartialCustomTabHeightStrategy strategy = createPcctAtHeight(500, true);
+        assertTabIsAtInitialPos(getWindowAttributes());
+
+        strategy.onShowSoftInput(() -> {});
+        waitForAnimationToFinish();
+        assertTabIsFullHeight(getWindowAttributes());
+
+        mPCCTTestRule.configLandscapeMode();
+        strategy.onConfigurationChanged(mPCCTTestRule.mConfiguration);
+        mPCCTTestRule.configPortraitMode();
+        strategy.onConfigurationChanged(mPCCTTestRule.mConfiguration);
+
+        assertTabIsAtInitialPos(getWindowAttributes());
+    }
+
+    @Test
+    public void fixedHeightRotateDuringFindInPage() {
+        PartialCustomTabHeightStrategy strategy = createPcctAtHeight(500, true);
+        strategy.setToolbarColorForTesting(PCCT_TOOLBAR_COLOR);
+        doReturn(FIND_TOOLBAR_COLOR)
+                .when(mPCCTTestRule.mResources)
+                .getColor(eq(R.color.find_in_page_background_color));
+        doReturn(mPCCTTestRule.mDragBarBackground).when(mPCCTTestRule.mDragBar).getBackground();
+        assertTabIsAtInitialPos(getWindowAttributes());
+
+        strategy.onFindToolbarShown();
+        waitForAnimationToFinish();
+        assertTabIsFullHeight(getWindowAttributes());
+
+        mPCCTTestRule.configLandscapeMode();
+        strategy.onConfigurationChanged(mPCCTTestRule.mConfiguration);
+        mPCCTTestRule.configPortraitMode();
+        strategy.onConfigurationChanged(mPCCTTestRule.mConfiguration);
+
+        // For fixed-height mode, move the tab back to initial height if the device was
+        // rotated while the tab was temporarily full-height due to Find-in-page feature
+        // expanding it automatically.
+        strategy.onFindToolbarHidden();
+        assertTabIsAtInitialPos(getWindowAttributes());
+    }
+
+    @Test
     public void moveUpFixedHeight() {
         PartialCustomTabHeightStrategy strategy = createPcctAtHeight(500, true);
         mPCCTTestRule.verifyWindowFlagsSet();
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 959ab56..e89f8c1a 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -6042,6 +6042,9 @@
   <message name="IDS_SUPERVISED_USER_OFFLINE_DESCRIPTION" desc="Description shown in the UI shown to supervised users when the network is not available.">
     Check your internet connection
   </message>
+  <message name="IDS_PARENT_ACCESS_ASK_IN_PERSON_BUTTON" desc="Button shown on the parent access dialog to ask a parent for approval in person.">
+    Ask in person
+  </message>
 
   <!-- Strings for gnubby U2FD authentication UI -->
   <message name="IDS_GNUBBY_NOTIFICATION_TITLE" desc="Title for notification informing user to press power button for gnubby U2FD.">
diff --git a/chrome/app/chromeos_strings_grdp/IDS_PARENT_ACCESS_ASK_IN_PERSON_BUTTON.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_PARENT_ACCESS_ASK_IN_PERSON_BUTTON.png.sha1
new file mode 100644
index 0000000..eba6700
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_PARENT_ACCESS_ASK_IN_PERSON_BUTTON.png.sha1
@@ -0,0 +1 @@
+202edd908265f37ab3e0f79fbd20743f2e148755
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index e1c16f89..3eb9aec4 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -556,8 +556,6 @@
     "gpu/gpu_mode_manager.cc",
     "gpu/gpu_mode_manager.h",
     "hang_monitor/hang_crash_dump.h",
-    "headless/headless_mode_util.cc",
-    "headless/headless_mode_util.h",
     "heavy_ad_intervention/heavy_ad_service_factory.cc",
     "heavy_ad_intervention/heavy_ad_service_factory.h",
     "history/chrome_history_backend_client.cc",
@@ -1927,6 +1925,7 @@
   public_deps = [
     "//base",
     "//chrome/browser/google",
+    "//chrome/browser/headless",
     "//chrome/common",
     "//chrome/common:buildflags",
     "//chrome/common:constants",
@@ -2159,7 +2158,6 @@
     "//components/live_caption:constants",
     "//components/live_caption:utils",
     "//components/lookalikes/core",
-    "//components/lookalikes/core:features",
     "//components/lookalikes/core:proto",
     "//components/lookalikes/core:safety_tips",
     "//components/memory_pressure",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 833dcfb..1e31a35d 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -113,7 +113,6 @@
 #include "components/language/core/common/language_experiments.h"
 #include "components/lens/buildflags.h"
 #include "components/lens/lens_features.h"
-#include "components/lookalikes/core/features.h"
 #include "components/messages/android/messages_feature.h"
 #include "components/mirroring/service/mirroring_features.h"
 #include "components/nacl/common/buildflags.h"
@@ -2842,26 +2841,6 @@
 
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-const FeatureEntry::FeatureParam kMaxOverlays1 = {features::kMaxOverlaysParam,
-                                                  "1"};
-const FeatureEntry::FeatureParam kMaxOverlays2 = {features::kMaxOverlaysParam,
-                                                  "2"};
-const FeatureEntry::FeatureParam kMaxOverlays3 = {features::kMaxOverlaysParam,
-                                                  "3"};
-const FeatureEntry::FeatureParam kMaxOverlays4 = {features::kMaxOverlaysParam,
-                                                  "4"};
-const FeatureEntry::FeatureParam kMaxOverlays5 = {features::kMaxOverlaysParam,
-                                                  "5"};
-const FeatureEntry::FeatureParam kMaxOverlays6 = {features::kMaxOverlaysParam,
-                                                  "6"};
-
-const FeatureEntry::FeatureVariation kUseMultipleOverlaysVariations[] = {
-    {"1", &kMaxOverlays1, 1, nullptr}, {"2", &kMaxOverlays2, 1, nullptr},
-    {"3", &kMaxOverlays3, 1, nullptr}, {"4", &kMaxOverlays4, 1, nullptr},
-    {"5", &kMaxOverlays5, 1, nullptr}, {"6", &kMaxOverlays6, 1, nullptr}};
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-
 #if BUILDFLAG(IS_ANDROID)
 const FeatureEntry::FeatureParam kGridTabSwitcherForTabletsPolished[] = {
     {"enable_launch_polish", "true"}};
@@ -3621,9 +3600,6 @@
     {"calendar-view-debug-mode", flag_descriptions::kCalendarModelDebugModeName,
      flag_descriptions::kCalendarModelDebugModeDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kCalendarModelDebugMode)},
-    {"captive-portal-ui-2022", flag_descriptions::kCaptivePortalUI2022Name,
-     flag_descriptions::kCaptivePortalUI2022Description, kOsCrOS,
-     FEATURE_VALUE_TYPE(ash::features::kCaptivePortalUI2022)},
     {"captive-portal-error-page",
      flag_descriptions::kCaptivePortalErrorPageName,
      flag_descriptions::kCaptivePortalErrorPageDescription, kOsCrOS,
@@ -6544,11 +6520,6 @@
      flag_descriptions::kChromeOSHWVBREncodingDescription, kOsCrOS | kOsLacros,
      FEATURE_VALUE_TYPE(media::kChromeOSHWVBREncoding)},
 #if defined(ARCH_CPU_ARM_FAMILY)
-    {"prefer-libyuv-image-processor",
-     flag_descriptions::kPreferLibYuvImageProcessorName,
-     flag_descriptions::kPreferLibYuvImageProcessorDescription,
-     kOsCrOS | kOsLacros,
-     FEATURE_VALUE_TYPE(media::kPreferLibYuvImageProcessor)},
     {"prefer-gl-image-processor",
      flag_descriptions::kPreferGLImageProcessorName,
      flag_descriptions::kPreferGLImageProcessorDescription, kOsCrOS | kOsLacros,
@@ -8519,14 +8490,6 @@
      FEATURE_VALUE_TYPE(ash::features::kVCPortraitRelighting)},
 #endif
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-    {"use-multiple-overlays", flag_descriptions::kUseMultipleOverlaysName,
-     flag_descriptions::kUseMultipleOverlaysDescription, kOsCrOS,
-     FEATURE_WITH_PARAMS_VALUE_TYPE(features::kUseMultipleOverlays,
-                                    kUseMultipleOverlaysVariations,
-                                    "UseMultipleOverlays")},
-#endif
-
 #if BUILDFLAG(IS_CHROMEOS)
     {"link-capturing-ui-update", flag_descriptions::kLinkCapturingUiUpdateName,
      flag_descriptions::kLinkCapturingUiUpdateDescription, kOsCrOS | kOsLacros,
diff --git a/chrome/browser/android/customtabs/tab_interaction_recorder_android.cc b/chrome/browser/android/customtabs/tab_interaction_recorder_android.cc
index 7795ffe21..862026f 100644
--- a/chrome/browser/android/customtabs/tab_interaction_recorder_android.cc
+++ b/chrome/browser/android/customtabs/tab_interaction_recorder_android.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/flags/android/chrome_feature_list.h"
 #include "components/autofill/content/browser/content_autofill_driver.h"
 #include "components/autofill/core/browser/autofill_manager.h"
+#include "content/public/browser/document_user_data.h"
 #include "content/public/browser/global_routing_id.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
@@ -25,6 +26,7 @@
 using autofill::AutofillManager;
 using base::android::JavaParamRef;
 using base::android::ScopedJavaLocalRef;
+using content::GlobalRenderFrameHostId;
 using content::RenderFrameHost;
 
 namespace {
@@ -36,13 +38,14 @@
     return nullptr;
   return autofill_driver->autofill_manager();
 }
-
 }  // namespace
 
 AutofillObserverImpl::AutofillObserverImpl(
+    GlobalRenderFrameHostId id,
     autofill::AutofillManager* autofill_manager,
     OnFormInteractionCallback form_interaction_callback)
-    : autofill_manager_(autofill_manager),
+    : global_id_(id),
+      autofill_manager_(autofill_manager),
       form_interaction_callback_(std::move(form_interaction_callback)) {
   autofill_manager->AddObserver(this);
 }
@@ -77,7 +80,22 @@
 
 void AutofillObserverImpl::OnFormInteraction() {
   Invalidate();
-  std::move(form_interaction_callback_).Run();
+  std::move(form_interaction_callback_).Run(global_id_);
+}
+
+DOCUMENT_USER_DATA_KEY_IMPL(FormInteractionData);
+
+FormInteractionData::~FormInteractionData() = default;
+
+FormInteractionData::FormInteractionData(RenderFrameHost* rfh)
+    : DocumentUserData<FormInteractionData>(rfh) {}
+
+void FormInteractionData::SetHasFormInteractionData() {
+  had_form_interaction_data_ = true;
+}
+
+bool FormInteractionData::GetHasFormInteractionData() {
+  return static_cast<jboolean>(had_form_interaction_data_);
 }
 
 TabInteractionRecorderAndroid::~TabInteractionRecorderAndroid() = default;
@@ -133,7 +151,10 @@
       .OnUserInteraction();
 }
 
-void TabInteractionRecorderAndroid::SetHasFormInteractions() {
+void TabInteractionRecorderAndroid::SetHasFormInteractions(
+    GlobalRenderFrameHostId id) {
+  FormInteractionData::GetForCurrentDocument(RenderFrameHost::FromID(id))
+      ->SetHasFormInteractionData();
   has_form_interactions_ = true;
   rfh_observer_map_.clear();
 }
@@ -150,9 +171,11 @@
   if (!autofill_manager)
     return;
 
+  FormInteractionData::CreateForCurrentDocument(render_frame_host);
+
   rfh_observer_map_[render_frame_host->GetGlobalId()] =
       std::make_unique<AutofillObserverImpl>(
-          autofill_manager,
+          render_frame_host->GetGlobalId(), autofill_manager,
           base::BindOnce(&TabInteractionRecorderAndroid::SetHasFormInteractions,
                          weak_factory_.GetWeakPtr()));
 }
diff --git a/chrome/browser/android/customtabs/tab_interaction_recorder_android.h b/chrome/browser/android/customtabs/tab_interaction_recorder_android.h
index 633bb9e..56ad49a 100644
--- a/chrome/browser/android/customtabs/tab_interaction_recorder_android.h
+++ b/chrome/browser/android/customtabs/tab_interaction_recorder_android.h
@@ -11,6 +11,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "components/autofill/core/browser/autofill_manager.h"
+#include "content/public/browser/document_user_data.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 #include "url/gurl.h"
@@ -20,9 +21,11 @@
 // Autofill observer impl for the TabInteractionRecorderAndroid to use.
 class AutofillObserverImpl : public autofill::AutofillManager::Observer {
  public:
-  using OnFormInteractionCallback = base::OnceCallback<void()>;
+  using OnFormInteractionCallback =
+      base::OnceCallback<void(content::GlobalRenderFrameHostId)>;
 
   explicit AutofillObserverImpl(
+      content::GlobalRenderFrameHostId id,
       autofill::AutofillManager* autofill_manager,
       OnFormInteractionCallback form_interaction_callback);
 
@@ -40,10 +43,29 @@
   void OnFormInteraction();
   void Invalidate();
 
+  content::GlobalRenderFrameHostId global_id_;
   raw_ptr<autofill::AutofillManager, DanglingUntriaged> autofill_manager_;
   OnFormInteractionCallback form_interaction_callback_;
 };
 
+// DocumentUserData stored inside each RenderFrameHost indicating whether
+// the hosting RFH experienced a form interaction.
+class FormInteractionData
+    : public content::DocumentUserData<FormInteractionData> {
+ public:
+  explicit FormInteractionData(content::RenderFrameHost* rfh);
+
+  ~FormInteractionData() override;
+  void SetHasFormInteractionData();
+  bool GetHasFormInteractionData();
+
+ private:
+  bool had_form_interaction_data_;
+
+  friend DocumentUserData;
+  DOCUMENT_USER_DATA_KEY_DECL();
+};
+
 // Class that record interaction from the web contents. The definition
 // of an "interaction" includes user's engagement with text inputs or selection
 // inputs, or changes in navigation stacks.
@@ -99,7 +121,7 @@
 
   friend class AutofillObserverImpl;
   void StartObservingFrame(content::RenderFrameHost* render_frame_host);
-  void SetHasFormInteractions();
+  void SetHasFormInteractions(content::GlobalRenderFrameHostId id);
 
   void ResetImpl();
 
diff --git a/chrome/browser/android/customtabs/tab_interaction_recorder_android_unittest.cc b/chrome/browser/android/customtabs/tab_interaction_recorder_android_unittest.cc
index ed810ab..6760065d9 100644
--- a/chrome/browser/android/customtabs/tab_interaction_recorder_android_unittest.cc
+++ b/chrome/browser/android/customtabs/tab_interaction_recorder_android_unittest.cc
@@ -23,6 +23,7 @@
 #include "components/autofill/core/common/autofill_tick_clock.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/test/navigation_simulator.h"
 #include "content/public/test/web_contents_tester.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -97,32 +98,37 @@
 };
 
 TEST_F(AutofillObserverImplTest, TestFormInteraction) {
-  base::MockOnceCallback<void()> callback;
-  AutofillObserverImpl obsever(autofill_manager(), callback.Get());
+  base::MockOnceCallback<void(content::GlobalRenderFrameHostId)> callback;
+  content::GlobalRenderFrameHostId id = content::GlobalRenderFrameHostId();
+  AutofillObserverImpl obsever(id, autofill_manager(), callback.Get());
 
-  EXPECT_CALL(callback, Run()).Times(1);
+  EXPECT_CALL(callback, Run(id)).Times(1);
   OnTextFieldDidChangeForAutofillManager(autofill_manager());
 
   // Observer should no longer get notified after the first interaction.
-  EXPECT_CALL(callback, Run()).Times(0);
+  EXPECT_CALL(callback, Run(id)).Times(0);
   OnTextFieldDidChangeForAutofillManager(autofill_manager());
 }
 
 TEST_F(AutofillObserverImplTest, TestNoFormInteraction) {
-  base::MockOnceCallback<void()> callback;
-  auto* observer = new AutofillObserverImpl(autofill_manager(), callback.Get());
+  content::GlobalRenderFrameHostId id = content::GlobalRenderFrameHostId();
+  base::MockOnceCallback<void(content::GlobalRenderFrameHostId)> callback;
+  auto* observer =
+      new AutofillObserverImpl(id, autofill_manager(), callback.Get());
 
-  EXPECT_CALL(callback, Run()).Times(0);
+  EXPECT_CALL(callback, Run(id)).Times(0);
   delete observer;
 }
 
 TEST_F(AutofillObserverImplTest, TestAutofillManagerDestroy) {
-  base::MockOnceCallback<void()> callback;
-  auto* observer = new AutofillObserverImpl(autofill_manager(), callback.Get());
+  content::GlobalRenderFrameHostId id = content::GlobalRenderFrameHostId();
+  base::MockOnceCallback<void(content::GlobalRenderFrameHostId)> callback;
+  auto* observer =
+      new AutofillObserverImpl(id, autofill_manager(), callback.Get());
 
   DestroyManager();
 
-  EXPECT_CALL(callback, Run()).Times(0);
+  EXPECT_CALL(callback, Run(id)).Times(0);
   delete observer;
 }
 
@@ -180,6 +186,9 @@
   EXPECT_FALSE(helper->has_form_interactions());
   OnTextFieldDidChangeForAutofillManager(autofill_manager());
   EXPECT_TRUE(helper->has_form_interactions());
+  EXPECT_TRUE(FormInteractionData::GetForCurrentDocument(
+                  contents->GetPrimaryMainFrame())
+                  ->FormInteractionData::GetHasFormInteractionData());
 
   JNIEnv* env = base::android::AttachCurrentThread();
   EXPECT_TRUE(helper->HadFormInteraction(env));
@@ -240,6 +249,10 @@
   // Simulate touch, text input, and navigation events.
   helper->DidGetUserInteraction(blink::WebTouchEvent());
   OnTextFieldDidChangeForAutofillManager(autofill_manager());
+  EXPECT_TRUE(FormInteractionData::GetForCurrentDocument(
+                  contents->GetPrimaryMainFrame())
+                  ->FormInteractionData::GetHasFormInteractionData());
+
   content::WebContentsTester::For(contents.get())
       ->NavigateAndCommit(GURL("https://bar.com"));
   task_environment()->RunUntilIdle();
diff --git a/chrome/browser/apps/app_service/browser_app_instance_tracker_browsertest.cc b/chrome/browser/apps/app_service/browser_app_instance_tracker_browsertest.cc
index 5e34339..15d7d752 100644
--- a/chrome/browser/apps/app_service/browser_app_instance_tracker_browsertest.cc
+++ b/chrome/browser/apps/app_service/browser_app_instance_tracker_browsertest.cc
@@ -54,7 +54,7 @@
 }
 
 base::UnguessableToken TestId(uint64_t id) {
-  return base::UnguessableToken::Deserialize(0, id);
+  return base::UnguessableToken::CreateForTesting(0, id);
 }
 
 // Make test sequence easier to scan
diff --git a/chrome/browser/apps/app_service/intent_util_unittest.cc b/chrome/browser/apps/app_service/intent_util_unittest.cc
index 5f21200..9c14567 100644
--- a/chrome/browser/apps/app_service/intent_util_unittest.cc
+++ b/chrome/browser/apps/app_service/intent_util_unittest.cc
@@ -214,40 +214,27 @@
 
 TEST_F(IntentUtilsTest, CreateIntentFiltersForChromeApp_FileHandlers) {
   // Foo app provides file handler for text/plain and all file types.
-  extensions::ExtensionBuilder foo_app;
-  foo_app.SetManifest(
-      extensions::DictionaryBuilder()
-          .Set("name", "Foo")
-          .Set("version", "1.0.0")
-          .Set("manifest_version", 2)
-          .Set("app", extensions::DictionaryBuilder()
-                          .Set("background",
-                               extensions::DictionaryBuilder()
-                                   .Set("scripts", extensions::ListBuilder()
-                                                       .Append("background.js")
-                                                       .Build())
-                                   .Build())
-                          .Build())
-          .Set(
-              "file_handlers",
-              extensions::DictionaryBuilder()
-                  .Set("any",
-                       extensions::DictionaryBuilder()
-                           .Set("types",
-                                extensions::ListBuilder().Append("*/*").Build())
-                           .Build())
-                  .Set("text",
-                       extensions::DictionaryBuilder()
-                           .Set("types", extensions::ListBuilder()
-                                             .Append("text/plain")
-                                             .Build())
-                           .Set("extensions",
-                                extensions::ListBuilder().Append("txt").Build())
-                           .Set("verb", "open_with")
-                           .Build())
-                  .Build())
-          .Build());
-  foo_app.SetID("abcdzxcv");
+  extensions::ExtensionBuilder foo_app("Foo");
+  static constexpr char kManifest[] = R"(
+    "manifest_version": 2,
+    "version": "1.0.0",
+    "app": {
+      "background": {
+        "scripts": ["background.js"]
+      }
+    },
+    "file_handlers": {
+      "any": {
+        "types": ["*/*"]
+      },
+      "text": {
+        "extensions": ["txt"],
+        "types": ["text/plain"],
+        "verb": "open_with"
+      }
+    }
+  )";
+  foo_app.AddJSON(kManifest).BuildManifest();
   scoped_refptr<const extensions::Extension> foo = foo_app.Build();
 
   IntentFilters filters = apps_util::CreateIntentFiltersForChromeApp(foo.get());
@@ -298,24 +285,15 @@
       extensions::api::app_runtime::ToString(
           extensions::api::app_runtime::ACTION_TYPE_NEW_NOTE);
   // Foo app has a note-taking action handler.
-  extensions::ExtensionBuilder foo_app;
-  foo_app.SetManifest(
-      extensions::DictionaryBuilder()
-          .Set("name", "Foo")
-          .Set("version", "1.0.0")
-          .Set("manifest_version", 2)
-          .Set("app", extensions::DictionaryBuilder()
-                          .Set("background",
-                               extensions::DictionaryBuilder()
-                                   .Set("scripts", extensions::ListBuilder()
-                                                       .Append("background.js")
-                                                       .Build())
-                                   .Build())
-                          .Build())
-          .Set("action_handlers",
-               extensions::ListBuilder().Append(note_action_handler).Build())
-          .Build());
-  foo_app.SetID("abcdefghzxcv");
+  extensions::ExtensionBuilder foo_app("Foo");
+  std::string manifest = base::StringPrintf(R"(
+    "manifest_version": 2,
+    "version": "1.0.0",
+    "action_handlers": ["%s"],
+    "app": {"background": {"scripts": ["background.js"]}}
+  )",
+                                            note_action_handler.c_str());
+  foo_app.AddJSON(manifest).BuildManifest();
   scoped_refptr<const extensions::Extension> foo = foo_app.Build();
 
   IntentFilters filters = apps_util::CreateIntentFiltersForChromeApp(foo.get());
@@ -337,44 +315,26 @@
 #if BUILDFLAG(IS_CHROMEOS)
 TEST_F(IntentUtilsTest, CreateIntentFiltersForExtension_FileHandlers) {
   // Foo extension provides file_browser_handlers for html and anything.
-  extensions::ExtensionBuilder foo_ext;
-  foo_ext.SetManifest(
-      extensions::DictionaryBuilder()
-          .Set("name", "Foo")
-          .Set("version", "1.0.0")
-          .Set("manifest_version", 2)
-          .Set(
-              "background",
-              extensions::DictionaryBuilder()
-                  .Set(
-                      "scripts",
-                      extensions::ListBuilder().Append("background.js").Build())
-                  .Set("persistent", false)
-                  .Build())
-          .Set(
-              "file_browser_handlers",
-              extensions::ListBuilder()
-                  .Append(
-                      extensions::DictionaryBuilder()
-                          .Set("id", "open")
-                          .Set("default_title", "Open me!")
-                          .Set("file_filters", extensions::ListBuilder()
-                                                   .Append("filesystem:*.html")
-                                                   .Build())
-                          .Build())
-                  .Append(extensions::DictionaryBuilder()
-                              .Set("id", "open_all")
-                              .Set("default_title", "Open anything!")
-                              .Set("file_filters", extensions::ListBuilder()
-                                                       .Append("filesystem:*.*")
-                                                       .Build())
-                              .Build())
-                  .Build())
-          .Set("permissions",
-               extensions::ListBuilder().Append("fileBrowserHandler").Build())
-          .Build());
-
-  foo_ext.SetID("abcdzxcv");
+  extensions::ExtensionBuilder foo_ext("Foo");
+  static constexpr char kManifest[] = R"(
+    "manifest_version": 2,
+    "permissions": ["fileBrowserHandler"],
+    "version": "1.0.0",
+    "background": {
+      "persistent": false,
+      "scripts": ["background.js"]
+    },
+    "file_browser_handlers": [ {
+      "default_title": "Open me!",
+      "file_filters": ["filesystem:*.html"],
+      "id": "open"
+    }, {
+      "default_title": "Open anything!",
+      "file_filters": ["filesystem:*.*"],
+      "id": "open_all"
+    }]
+  )";
+  foo_ext.AddJSON(kManifest).BuildManifest();
   scoped_refptr<const extensions::Extension> foo = foo_ext.Build();
 
   IntentFilters filters = apps_util::CreateIntentFiltersForExtension(foo.get());
diff --git a/chrome/browser/ash/accessibility/dictation_browsertest.cc b/chrome/browser/ash/accessibility/dictation_browsertest.cc
index 1925ac14..3e01cda 100644
--- a/chrome/browser/ash/accessibility/dictation_browsertest.cc
+++ b/chrome/browser/ash/accessibility/dictation_browsertest.cc
@@ -2088,12 +2088,7 @@
  protected:
   void SetUpCommandLine(base::CommandLine* command_line) override {
     DictationTest::SetUpCommandLine(command_line);
-
-    std::vector<base::test::FeatureRef> enabled_features;
-    enabled_features.emplace_back(features::kQsRevamp);
-    enabled_features.emplace_back(features::kQsRevampWip);
-    scoped_feature_list_.InitWithFeatures(
-        enabled_features, std::vector<base::test::FeatureRef>());
+    scoped_feature_list_.InitAndEnableFeature(features::kQsRevamp);
   }
 
   void SetUpOnMainThread() override {
diff --git a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
index 342f15b..f60db8c 100644
--- a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
+++ b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
@@ -350,8 +350,7 @@
 class NotificationCenterSpokenFeedbackTest : public LoggedInSpokenFeedbackTest {
  protected:
   NotificationCenterSpokenFeedbackTest() {
-    feature_list_.InitWithFeatures(
-        {features::kQsRevamp, features::kQsRevampWip}, {});
+    feature_list_.InitAndEnableFeature(features::kQsRevamp);
   }
   ~NotificationCenterSpokenFeedbackTest() override = default;
 
@@ -1747,8 +1746,9 @@
 
   // ScreenBacklightObserver:
   void OnBacklightsForcedOffChanged(bool backlights_forced_off) override {
-    if (backlights_forced_off_ == backlights_forced_off)
+    if (backlights_forced_off_ == backlights_forced_off) {
       return;
+    }
 
     backlights_forced_off_ = backlights_forced_off;
     if (run_loop_) {
@@ -1784,8 +1784,8 @@
   sm_.Call([this]() { SendKeyPressWithSearch(ui::VKEY_F7); });
   sm_.ExpectSpeech("Turn off screen?");
   sm_.ExpectSpeech("Dialog");
-  // TODO(crbug.com/1228418) - Improve the generation of summaries across ChromeOS.
-  // Expect the content to be spoken once it has been improved.
+  // TODO(crbug.com/1228418) - Improve the generation of summaries across
+  // ChromeOS. Expect the content to be spoken once it has been improved.
   /*sm_.ExpectSpeech(
       "Turn off screen? This improves privacy by turning off your screen so it "
       "isn’t visible to others. You can always turn the screen back on by "
@@ -1806,8 +1806,9 @@
   sm_.ExpectSpeech("Screen off");
   // Make sure Ash gets the backlight change request.
   sm_.Call([&observer = observer, backlights_setter = backlights_setter]() {
-    if (observer.backlights_forced_off())
+    if (observer.backlights_forced_off()) {
       return;
+    }
     observer.WaitForBacklightStateChange();
     EXPECT_TRUE(backlights_setter->backlights_forced_off());
   });
@@ -1816,8 +1817,9 @@
   sm_.ExpectNextSpeechIsNot("Continue");
   sm_.ExpectSpeech("Screen on");
   sm_.Call([&observer = observer, backlights_setter = backlights_setter]() {
-    if (!observer.backlights_forced_off())
+    if (!observer.backlights_forced_off()) {
       return;
+    }
     observer.WaitForBacklightStateChange();
     EXPECT_FALSE(backlights_setter->backlights_forced_off());
   });
@@ -1826,8 +1828,9 @@
   sm_.ExpectNextSpeechIsNot("Continue");
   sm_.ExpectSpeech("Screen off");
   sm_.Call([&observer = observer, backlights_setter = backlights_setter]() {
-    if (observer.backlights_forced_off())
+    if (observer.backlights_forced_off()) {
       return;
+    }
     observer.WaitForBacklightStateChange();
     EXPECT_TRUE(backlights_setter->backlights_forced_off());
   });
diff --git a/chrome/browser/ash/hats/hats_config.cc b/chrome/browser/ash/hats/hats_config.cc
index 347fd370..ad281dda 100644
--- a/chrome/browser/ash/hats/hats_config.cc
+++ b/chrome/browser/ash/hats/hats_config.cc
@@ -178,4 +178,13 @@
     prefs::kHatsBluetoothRevampCycleEndTs,  // cycle_end_timestamp_pref_name
 };
 
+// Privacy Hub Baseline experience survey -- shown 40 seconds after the user
+// stayed for more than 5 seconds on the Security and Privacy page.
+const HatsConfig kPrivacyHubBaselineSurvey = {
+    ::features::kHappinessTrackingPrivacyHubBaseline,  // feature
+    base::Days(1),                                     // new_device_threshold
+    prefs::kHatsPrivacyHubBaselineIsSelected,          // is_selected_pref_name
+    prefs::kHatsPrivacyHubBaselineCycleEndTs,  // cycle_end_timestamp_pref_name
+};
+
 }  // namespace ash
diff --git a/chrome/browser/ash/hats/hats_config.h b/chrome/browser/ash/hats/hats_config.h
index f517d37..5479edf 100644
--- a/chrome/browser/ash/hats/hats_config.h
+++ b/chrome/browser/ash/hats/hats_config.h
@@ -52,6 +52,7 @@
 extern const HatsConfig kHatsPhotosExperienceSurvey;
 extern const HatsConfig kHatsGeneralCameraSurvey;
 extern const HatsConfig kHatsBluetoothRevampSurvey;
+extern const HatsConfig kPrivacyHubBaselineSurvey;
 
 }  // namespace ash
 
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker.h b/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker.h
index 182a2fc..0ea3c05 100644
--- a/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker.h
+++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker.h
@@ -38,7 +38,7 @@
   // StartAdvertising().
   //
   // This interface is a simplification of
-  // location::nearby::connections::mojom::ConnectionLifecycleListener, for ease
+  // nearby::connections::mojom::ConnectionLifecycleListener, for ease
   // of client use.
   class ConnectionLifecycleListener {
    public:
diff --git a/chrome/browser/ash/nearby/nearby_dependencies_provider.cc b/chrome/browser/ash/nearby/nearby_dependencies_provider.cc
index 6c6461f..9e10366 100644
--- a/chrome/browser/ash/nearby/nearby_dependencies_provider.cc
+++ b/chrome/browser/ash/nearby/nearby_dependencies_provider.cc
@@ -121,7 +121,7 @@
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kNearbyShareVerboseLogging)) {
     dependencies->min_log_severity =
-        location::nearby::api::LogMessage::Severity::kVerbose;
+        ::nearby::api::LogMessage::Severity::kVerbose;
   }
 
   return dependencies;
diff --git a/chrome/browser/ash/nearby/nearby_process_manager_impl.cc b/chrome/browser/ash/nearby/nearby_process_manager_impl.cc
index cbcb0cf..b474d22 100644
--- a/chrome/browser/ash/nearby/nearby_process_manager_impl.cc
+++ b/chrome/browser/ash/nearby/nearby_process_manager_impl.cc
@@ -26,7 +26,7 @@
 
 void OnSharingShutDownComplete(
     mojo::Remote<sharing::mojom::Sharing> sharing,
-    mojo::SharedRemote<location::nearby::connections::mojom::NearbyConnections>
+    mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>
         connections,
     mojo::SharedRemote<sharing::mojom::NearbySharingDecoder> decoder) {
   NS_LOG(INFO) << "Asynchronous process shutdown complete.";
@@ -55,8 +55,8 @@
 }
 
 NearbyProcessManagerImpl::NearbyReferenceImpl::NearbyReferenceImpl(
-    const mojo::SharedRemote<
-        location::nearby::connections::mojom::NearbyConnections>& connections,
+    const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
+        connections,
     const mojo::SharedRemote<sharing::mojom::NearbySharingDecoder>& decoder,
     base::OnceClosure destructor_callback)
     : connections_(connections),
@@ -73,8 +73,7 @@
   std::move(destructor_callback_).Run();
 }
 
-const mojo::SharedRemote<
-    location::nearby::connections::mojom::NearbyConnections>&
+const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
 NearbyProcessManagerImpl::NearbyReferenceImpl::GetNearbyConnections() const {
   return connections_;
 }
@@ -157,9 +156,9 @@
 
   // Remotes for NearbyConnections and NearbySharingDecoder are bound on the
   // calling sequence by providing a null |bind_task_runner|.
-  mojo::PendingRemote<location::nearby::connections::mojom::NearbyConnections>
+  mojo::PendingRemote<::nearby::connections::mojom::NearbyConnections>
       connections;
-  mojo::PendingReceiver<location::nearby::connections::mojom::NearbyConnections>
+  mojo::PendingReceiver<::nearby::connections::mojom::NearbyConnections>
       connections_receiver = connections.InitWithNewPipeAndPassReceiver();
   connections_.Bind(std::move(connections), /*bind_task_runner=*/nullptr);
   connections_.set_disconnect_handler(
diff --git a/chrome/browser/ash/nearby/nearby_process_manager_impl.h b/chrome/browser/ash/nearby/nearby_process_manager_impl.h
index 04fae50..5505932 100644
--- a/chrome/browser/ash/nearby/nearby_process_manager_impl.h
+++ b/chrome/browser/ash/nearby/nearby_process_manager_impl.h
@@ -55,8 +55,7 @@
       : public NearbyProcessManager::NearbyProcessReference {
    public:
     NearbyReferenceImpl(
-        const mojo::SharedRemote<
-            location::nearby::connections::mojom::NearbyConnections>&
+        const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
             connections,
         const mojo::SharedRemote<sharing::mojom::NearbySharingDecoder>& decoder,
         base::OnceClosure destructor_callback);
@@ -64,13 +63,12 @@
 
    private:
     // NearbyProcessManager::NearbyProcessReference:
-    const mojo::SharedRemote<
-        location::nearby::connections::mojom::NearbyConnections>&
+    const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
     GetNearbyConnections() const override;
     const mojo::SharedRemote<sharing::mojom::NearbySharingDecoder>&
     GetNearbySharingDecoder() const override;
 
-    mojo::SharedRemote<location::nearby::connections::mojom::NearbyConnections>
+    mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>
         connections_;
     mojo::SharedRemote<sharing::mojom::NearbySharingDecoder> decoder_;
     base::OnceClosure destructor_callback_;
@@ -109,7 +107,7 @@
 
   // Implemented as SharedRemote because copies of these are intended to be used
   // by multiple clients.
-  mojo::SharedRemote<location::nearby::connections::mojom::NearbyConnections>
+  mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>
       connections_;
   mojo::SharedRemote<sharing::mojom::NearbySharingDecoder> decoder_;
 
diff --git a/chrome/browser/ash/nearby/nearby_process_manager_impl_unittest.cc b/chrome/browser/ash/nearby/nearby_process_manager_impl_unittest.cc
index 8d65e4ed..6016f1d 100644
--- a/chrome/browser/ash/nearby/nearby_process_manager_impl_unittest.cc
+++ b/chrome/browser/ash/nearby/nearby_process_manager_impl_unittest.cc
@@ -146,7 +146,7 @@
               std::move(cros_network_config_remote),
               std::move(firewall_hole_factory_remote),
               std::move(tcp_socket_factory_remote)),
-          location::nearby::api::LogMessage::Severity::kInfo);
+          ::nearby::api::LogMessage::Severity::kInfo);
     }
 
     void PrepareForShutdown() override { prepare_for_shutdown_count_++; }
diff --git a/chrome/browser/ash/net/network_portal_detector_impl_browsertest.cc b/chrome/browser/ash/net/network_portal_detector_impl_browsertest.cc
index 06536c0..9c7dccd8 100644
--- a/chrome/browser/ash/net/network_portal_detector_impl_browsertest.cc
+++ b/chrome/browser/ash/net/network_portal_detector_impl_browsertest.cc
@@ -6,7 +6,6 @@
 
 #include <memory>
 
-#include "ash/constants/ash_features.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/functional/bind.h"
@@ -14,9 +13,7 @@
 #include "base/location.h"
 #include "base/run_loop.h"
 #include "base/task/single_thread_task_runner.h"
-#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/ash/login/login_manager_test.h"
-#include "chrome/browser/ash/login/startup_utils.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/notifications/notification_display_service_tester.h"
 #include "chrome/browser/profiles/profile.h"
@@ -34,7 +31,6 @@
 #include "components/prefs/pref_service.h"
 #include "components/sync_preferences/pref_service_syncable.h"
 #include "content/public/test/browser_test.h"
-#include "content/public/test/test_utils.h"
 #include "dbus/object_path.h"
 #include "net/base/net_errors.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -97,19 +93,15 @@
       public captive_portal::CaptivePortalDetectorTestBase {
  public:
   NetworkPortalDetectorImplBrowserTest()
-      : LoginManagerTest(),
-        test_account_id_(
-            AccountId::FromUserEmailGaiaId(kTestUser, kTestUserGaiaId)),
-        network_portal_detector_(nullptr) {
-    feature_list_.InitAndDisableFeature({features::kCaptivePortalUI2022});
-  }
+      : test_account_id_(
+            AccountId::FromUserEmailGaiaId(kTestUser, kTestUserGaiaId)) {}
 
   NetworkPortalDetectorImplBrowserTest(
       const NetworkPortalDetectorImplBrowserTest&) = delete;
   NetworkPortalDetectorImplBrowserTest& operator=(
       const NetworkPortalDetectorImplBrowserTest&) = delete;
 
-  ~NetworkPortalDetectorImplBrowserTest() override {}
+  ~NetworkPortalDetectorImplBrowserTest() override = default;
 
   void TestPortalStateAndNotification(
       const char* shill_state,
@@ -120,7 +112,7 @@
       const std::u16string& expected_button_title,
       NetworkPortalDetector::CaptivePortalStatus portal_detector_status) {
     LoginUser(test_account_id_);
-    content::RunAllPendingInMessageLoop();
+    base::RunLoop().RunUntilIdle();
 
     EXPECT_FALSE(display_service_->GetNotification(kNotificationId));
 
@@ -215,99 +207,12 @@
  protected:
   AccountId test_account_id_;
   std::unique_ptr<NotificationDisplayServiceTester> display_service_;
-  NetworkPortalDetectorImpl* network_portal_detector_;
+  NetworkPortalDetectorImpl* network_portal_detector_ = nullptr;
   std::unique_ptr<NetworkPortalNotificationController>
       network_portal_notification_controller_;
-  base::test::ScopedFeatureList feature_list_;
 };
 
 IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTest,
-                       PRE_InSessionDetection) {
-  RegisterUser(test_account_id_);
-  StartupUtils::MarkOobeCompleted();
-}
-
-IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTest,
-                       InSessionDetection) {
-  TestPortalStateAndNotification(
-      shill::kStateRedirectFound, NetworkState::PortalState::kPortal,
-      /*set_portal_status_for_proxy_auth=*/false,
-      l10n_util::GetStringUTF16(IDS_PORTAL_DETECTION_NOTIFICATION_TITLE_WIFI),
-      l10n_util::GetStringFUTF16(IDS_PORTAL_DETECTION_NOTIFICATION_MESSAGE_WIFI,
-                                 u"wifi"),
-      u"", NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL);
-}
-
-class NetworkPortalDetectorImplBrowserTestIgnoreProxy
-    : public NetworkPortalDetectorImplBrowserTest,
-      public testing::WithParamInterface<bool> {
- public:
-  NetworkPortalDetectorImplBrowserTestIgnoreProxy()
-      : NetworkPortalDetectorImplBrowserTest() {}
-
-  NetworkPortalDetectorImplBrowserTestIgnoreProxy(
-      const NetworkPortalDetectorImplBrowserTestIgnoreProxy&) = delete;
-  NetworkPortalDetectorImplBrowserTestIgnoreProxy& operator=(
-      const NetworkPortalDetectorImplBrowserTestIgnoreProxy&) = delete;
-
- protected:
-  void TestImpl(const bool preference_value);
-};
-
-void NetworkPortalDetectorImplBrowserTestIgnoreProxy::TestImpl(
-    const bool preference_value) {
-  LoginUser(test_account_id_);
-  content::RunAllPendingInMessageLoop();
-
-  SetIgnoreNoNetworkForTesting();
-
-  ProfileManager::GetActiveUserProfile()->GetPrefs()->SetBoolean(
-      prefs::kCaptivePortalAuthenticationIgnoresProxy, preference_value);
-
-  // User connects to portalled wifi.
-  SetConnected(kWifiServicePath);
-  SetState(shill::kStateRedirectFound);
-
-  // Check that the network is behind a portal and a notification is displayed.
-  EXPECT_TRUE(display_service_->GetNotification(kNotificationId));
-  EXPECT_EQ(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL,
-            network_portal_detector::GetInstance()->GetCaptivePortalStatus());
-
-  display_service_->GetNotification(kNotificationId)
-      ->delegate()
-      ->Click(absl::nullopt, absl::nullopt);
-
-  content::RunAllPendingInMessageLoop();
-
-  EXPECT_EQ(preference_value,
-            network_portal_notification_controller_->IsDialogShownForTesting());
-}
-
-IN_PROC_BROWSER_TEST_P(NetworkPortalDetectorImplBrowserTestIgnoreProxy,
-                       PRE_TestWithPreference) {
-  RegisterUser(test_account_id_);
-  StartupUtils::MarkOobeCompleted();
-}
-
-IN_PROC_BROWSER_TEST_P(NetworkPortalDetectorImplBrowserTestIgnoreProxy,
-                       TestWithPreference) {
-  TestImpl(GetParam());
-}
-
-INSTANTIATE_TEST_SUITE_P(CaptivePortalAuthenticationIgnoresProxy,
-                         NetworkPortalDetectorImplBrowserTestIgnoreProxy,
-                         testing::Bool());
-
-class NetworkPortalDetectorImplBrowserTestUI2022Update
-    : public NetworkPortalDetectorImplBrowserTest {
- public:
-  NetworkPortalDetectorImplBrowserTestUI2022Update() {
-    feature_list_.Reset();
-    feature_list_.InitAndEnableFeature(features::kCaptivePortalUI2022);
-  }
-};
-
-IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTestUI2022Update,
                        InSessionDetectionRedirectFoundState) {
   TestPortalStateAndNotification(
       shill::kStateRedirectFound, NetworkState::PortalState::kPortal,
@@ -320,7 +225,7 @@
       NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL);
 }
 
-IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTestUI2022Update,
+IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTest,
                        InSessionDetectionPortalSuspectedState) {
   TestPortalStateAndNotification(
       shill::kStatePortalSuspected, NetworkState::PortalState::kPortalSuspected,
@@ -338,7 +243,7 @@
       NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE);
 }
 
-IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTestUI2022Update,
+IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTest,
                        InSessionDetectionProxyAuthRequiredState) {
   TestPortalStateAndNotification(
       shill::kStatePortalSuspected,
@@ -357,10 +262,10 @@
       NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE);
 }
 
-IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTestUI2022Update,
+IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTest,
                        PortalStateChangedBetweenPortalStates) {
   LoginUser(test_account_id_);
-  content::RunAllPendingInMessageLoop();
+  base::RunLoop().RunUntilIdle();
 
   // User connects to portalled wifi.
   SetConnected(kWifiServicePath);
@@ -405,10 +310,10 @@
                                        kNotificationId, /*by_user=*/true);
 }
 
-IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTestUI2022Update,
+IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTest,
                        ReconnectionNewNotification) {
   LoginUser(test_account_id_);
-  content::RunAllPendingInMessageLoop();
+  base::RunLoop().RunUntilIdle();
 
   // User connects to portalled wifi.
   SetConnected(kWifiServicePath);
@@ -425,10 +330,10 @@
   EXPECT_TRUE(display_service_->GetNotification(kNotificationId));
 }
 
-IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTestUI2022Update,
+IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTest,
                        UserDismissedNotificationNoNewNotification) {
   LoginUser(test_account_id_);
-  content::RunAllPendingInMessageLoop();
+  base::RunLoop().RunUntilIdle();
 
   // User connects to portalled wifi.
   SetConnected(kWifiServicePath);
@@ -444,4 +349,54 @@
   EXPECT_FALSE(display_service_->GetNotification(kNotificationId));
 }
 
+class NetworkPortalDetectorImplBrowserTestIgnoreProxy
+    : public NetworkPortalDetectorImplBrowserTest,
+      public testing::WithParamInterface<bool> {
+ public:
+  NetworkPortalDetectorImplBrowserTestIgnoreProxy() = default;
+
+  NetworkPortalDetectorImplBrowserTestIgnoreProxy(
+      const NetworkPortalDetectorImplBrowserTestIgnoreProxy&) = delete;
+  NetworkPortalDetectorImplBrowserTestIgnoreProxy& operator=(
+      const NetworkPortalDetectorImplBrowserTestIgnoreProxy&) = delete;
+
+ protected:
+  void TestImpl(const bool preference_value);
+};
+
+void NetworkPortalDetectorImplBrowserTestIgnoreProxy::TestImpl(
+    const bool preference_value) {
+  LoginUser(test_account_id_);
+  base::RunLoop().RunUntilIdle();
+
+  SetIgnoreNoNetworkForTesting();
+
+  ProfileManager::GetActiveUserProfile()->GetPrefs()->SetBoolean(
+      prefs::kCaptivePortalAuthenticationIgnoresProxy, preference_value);
+
+  // User connects to portalled wifi.
+  SetConnected(kWifiServicePath);
+  SetState(shill::kStateRedirectFound);
+
+  // Check that the network is behind a portal and a notification is displayed.
+  EXPECT_TRUE(display_service_->GetNotification(kNotificationId));
+  EXPECT_EQ(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL,
+            network_portal_detector::GetInstance()->GetCaptivePortalStatus());
+
+  display_service_->GetNotification(kNotificationId)
+      ->delegate()
+      ->Click(absl::nullopt, absl::nullopt);
+
+  base::RunLoop().RunUntilIdle();
+}
+
+IN_PROC_BROWSER_TEST_P(NetworkPortalDetectorImplBrowserTestIgnoreProxy,
+                       TestWithPreference) {
+  TestImpl(GetParam());
+}
+
+INSTANTIATE_TEST_SUITE_P(CaptivePortalAuthenticationIgnoresProxy,
+                         NetworkPortalDetectorImplBrowserTestIgnoreProxy,
+                         testing::Bool());
+
 }  // namespace ash
diff --git a/chrome/browser/ash/preferences.cc b/chrome/browser/ash/preferences.cc
index 0f5508c..0c355a4 100644
--- a/chrome/browser/ash/preferences.cc
+++ b/chrome/browser/ash/preferences.cc
@@ -469,6 +469,11 @@
 
   registry->RegisterBooleanPref(::prefs::kHatsBluetoothRevampIsSelected, false);
 
+  registry->RegisterBooleanPref(::prefs::kHatsPrivacyHubBaselineIsSelected,
+                                false);
+
+  registry->RegisterInt64Pref(::prefs::kHatsPrivacyHubBaselineCycleEndTs, 0);
+
   // Personalization HaTS survey prefs for avatar, screensaver, and wallpaper
   // features.
   registry->RegisterInt64Pref(
diff --git a/chrome/browser/ash/secure_channel/nearby_connection_broker_impl.cc b/chrome/browser/ash/secure_channel/nearby_connection_broker_impl.cc
index 6f9b639..fae9433 100644
--- a/chrome/browser/ash/secure_channel/nearby_connection_broker_impl.cc
+++ b/chrome/browser/ash/secure_channel/nearby_connection_broker_impl.cc
@@ -30,19 +30,19 @@
 namespace secure_channel {
 namespace {
 
-using ::location::nearby::connections::mojom::BytesPayload;
-using ::location::nearby::connections::mojom::ConnectionInfoPtr;
-using ::location::nearby::connections::mojom::ConnectionOptions;
-using ::location::nearby::connections::mojom::DiscoveredEndpointInfoPtr;
-using ::location::nearby::connections::mojom::Medium;
-using ::location::nearby::connections::mojom::MediumSelection;
-using ::location::nearby::connections::mojom::NearbyConnections;
-using ::location::nearby::connections::mojom::Payload;
-using ::location::nearby::connections::mojom::PayloadContent;
-using ::location::nearby::connections::mojom::PayloadPtr;
-using ::location::nearby::connections::mojom::PayloadStatus;
-using ::location::nearby::connections::mojom::PayloadTransferUpdatePtr;
-using ::location::nearby::connections::mojom::Status;
+using ::nearby::connections::mojom::BytesPayload;
+using ::nearby::connections::mojom::ConnectionInfoPtr;
+using ::nearby::connections::mojom::ConnectionOptions;
+using ::nearby::connections::mojom::DiscoveredEndpointInfoPtr;
+using ::nearby::connections::mojom::Medium;
+using ::nearby::connections::mojom::MediumSelection;
+using ::nearby::connections::mojom::NearbyConnections;
+using ::nearby::connections::mojom::Payload;
+using ::nearby::connections::mojom::PayloadContent;
+using ::nearby::connections::mojom::PayloadPtr;
+using ::nearby::connections::mojom::PayloadStatus;
+using ::nearby::connections::mojom::PayloadTransferUpdatePtr;
+using ::nearby::connections::mojom::Status;
 
 NearbyConnectionBrokerImpl::Factory* g_test_factory = nullptr;
 
@@ -633,7 +633,7 @@
 
 void NearbyConnectionBrokerImpl::OnPayloadTransferUpdate(
     const std::string& endpoint_id,
-    location::nearby::connections::mojom::PayloadTransferUpdatePtr update) {
+    ::nearby::connections::mojom::PayloadTransferUpdatePtr update) {
   if (!ash::features::IsPhoneHubCameraRollEnabled()) {
     return;
   }
diff --git a/chrome/browser/ash/secure_channel/nearby_connection_broker_impl.h b/chrome/browser/ash/secure_channel/nearby_connection_broker_impl.h
index 1aca352d..cb454543 100644
--- a/chrome/browser/ash/secure_channel/nearby_connection_broker_impl.h
+++ b/chrome/browser/ash/secure_channel/nearby_connection_broker_impl.h
@@ -38,8 +38,8 @@
 // performs cleanup if necessary.
 class NearbyConnectionBrokerImpl
     : public NearbyConnectionBroker,
-      public location::nearby::connections::mojom::ConnectionLifecycleListener,
-      public location::nearby::connections::mojom::PayloadListener {
+      public ::nearby::connections::mojom::ConnectionLifecycleListener,
+      public ::nearby::connections::mojom::PayloadListener {
  public:
   class Factory {
    public:
@@ -53,8 +53,7 @@
             file_payload_handler_receiver,
         mojo::PendingRemote<mojom::NearbyMessageReceiver>
             message_receiver_remote,
-        const mojo::SharedRemote<
-            location::nearby::connections::mojom::NearbyConnections>&
+        const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
             nearby_connections,
         base::OnceClosure on_connected_callback,
         base::OnceClosure on_disconnected_callback,
@@ -74,8 +73,7 @@
             file_payload_handler_receiver,
         mojo::PendingRemote<mojom::NearbyMessageReceiver>
             message_receiver_remote,
-        const mojo::SharedRemote<
-            location::nearby::connections::mojom::NearbyConnections>&
+        const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
             nearby_connections,
         base::OnceClosure on_connected_callback,
         base::OnceClosure on_disconnected_callback,
@@ -107,8 +105,7 @@
       mojo::PendingReceiver<mojom::NearbyFilePayloadHandler>
           file_payload_handler_receiver,
       mojo::PendingRemote<mojom::NearbyMessageReceiver> message_receiver_remote,
-      const mojo::SharedRemote<
-          location::nearby::connections::mojom::NearbyConnections>&
+      const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
           nearby_connections,
       base::OnceClosure on_connected_callback,
       base::OnceClosure on_disconnected_callback,
@@ -120,24 +117,22 @@
 
   void OnEndpointDiscovered(
       const std::string& endpoint_id,
-      location::nearby::connections::mojom::DiscoveredEndpointInfoPtr info);
+      ::nearby::connections::mojom::DiscoveredEndpointInfoPtr info);
   void OnDiscoveryFailure();
 
-  void OnRequestConnectionResult(
-      location::nearby::connections::mojom::Status status);
-  void OnAcceptConnectionResult(
-      location::nearby::connections::mojom::Status status);
+  void OnRequestConnectionResult(::nearby::connections::mojom::Status status);
+  void OnAcceptConnectionResult(::nearby::connections::mojom::Status status);
   void OnSendPayloadResult(SendMessageCallback callback,
-                           location::nearby::connections::mojom::Status status);
+                           ::nearby::connections::mojom::Status status);
   void OnDisconnectFromEndpointResult(
-      location::nearby::connections::mojom::Status status);
+      ::nearby::connections::mojom::Status status);
   void OnConnectionStatusChangeTimeout();
 
   void OnPayloadFileRegistered(
       int64_t payload_id,
       mojo::PendingRemote<mojom::FilePayloadListener> listener,
       RegisterPayloadFileCallback callback,
-      location::nearby::connections::mojom::Status status);
+      ::nearby::connections::mojom::Status status);
   void OnFilePayloadListenerDisconnect(int64_t payload_id);
   void CleanUpPendingFileTransfers();
 
@@ -155,37 +150,33 @@
       mojo::PendingRemote<mojom::FilePayloadListener> listener,
       RegisterPayloadFileCallback callback) override;
 
-  // location::nearby::connections::mojom::ConnectionLifecycleListener:
+  // ::nearby::connections::mojom::ConnectionLifecycleListener:
   void OnConnectionInitiated(
       const std::string& endpoint_id,
-      location::nearby::connections::mojom::ConnectionInfoPtr info) override;
+      ::nearby::connections::mojom::ConnectionInfoPtr info) override;
   void OnConnectionAccepted(const std::string& endpoint_id) override;
-  void OnConnectionRejected(
-      const std::string& endpoint_id,
-      location::nearby::connections::mojom::Status status) override;
+  void OnConnectionRejected(const std::string& endpoint_id,
+                            ::nearby::connections::mojom::Status status) override;
   void OnDisconnected(const std::string& endpoint_id) override;
-  void OnBandwidthChanged(
-      const std::string& endpoint_id,
-      location::nearby::connections::mojom::Medium medium) override;
+  void OnBandwidthChanged(const std::string& endpoint_id,
+                          ::nearby::connections::mojom::Medium medium) override;
 
-  // location::nearby::connections::mojom::PayloadListener:
+  // ::nearby::connections::mojom::PayloadListener:
   void OnPayloadReceived(
       const std::string& endpoint_id,
-      location::nearby::connections::mojom::PayloadPtr payload) override;
+      ::nearby::connections::mojom::PayloadPtr payload) override;
   void OnPayloadTransferUpdate(
       const std::string& endpoint_id,
-      location::nearby::connections::mojom::PayloadTransferUpdatePtr update)
-      override;
+      ::nearby::connections::mojom::PayloadTransferUpdatePtr update) override;
 
   NearbyEndpointFinder* endpoint_finder_;
-  mojo::SharedRemote<location::nearby::connections::mojom::NearbyConnections>
+  mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>
       nearby_connections_;
   std::unique_ptr<base::OneShotTimer> timer_;
 
-  mojo::Receiver<
-      location::nearby::connections::mojom::ConnectionLifecycleListener>
+  mojo::Receiver<::nearby::connections::mojom::ConnectionLifecycleListener>
       connection_lifecycle_listener_receiver_{this};
-  mojo::Receiver<location::nearby::connections::mojom::PayloadListener>
+  mojo::Receiver<::nearby::connections::mojom::PayloadListener>
       payload_listener_receiver_{this};
 
   ConnectionStatus connection_status_ = ConnectionStatus::kUninitialized;
diff --git a/chrome/browser/ash/secure_channel/nearby_connection_broker_impl_unittest.cc b/chrome/browser/ash/secure_channel/nearby_connection_broker_impl_unittest.cc
index c8cc715..2d70fe6 100644
--- a/chrome/browser/ash/secure_channel/nearby_connection_broker_impl_unittest.cc
+++ b/chrome/browser/ash/secure_channel/nearby_connection_broker_impl_unittest.cc
@@ -30,20 +30,20 @@
 namespace secure_channel {
 namespace {
 
-using ::location::nearby::connections::mojom::BytesPayload;
-using ::location::nearby::connections::mojom::ConnectionInfo;
-using ::location::nearby::connections::mojom::ConnectionLifecycleListener;
-using ::location::nearby::connections::mojom::ConnectionOptionsPtr;
-using ::location::nearby::connections::mojom::DiscoveredEndpointInfo;
-using ::location::nearby::connections::mojom::FilePayload;
-using ::location::nearby::connections::mojom::Payload;
-using ::location::nearby::connections::mojom::PayloadContent;
-using ::location::nearby::connections::mojom::PayloadListener;
-using ::location::nearby::connections::mojom::PayloadPtr;
-using ::location::nearby::connections::mojom::PayloadStatus;
-using ::location::nearby::connections::mojom::PayloadTransferUpdate;
-using ::location::nearby::connections::mojom::PayloadTransferUpdatePtr;
-using ::location::nearby::connections::mojom::Status;
+using ::nearby::connections::mojom::BytesPayload;
+using ::nearby::connections::mojom::ConnectionInfo;
+using ::nearby::connections::mojom::ConnectionLifecycleListener;
+using ::nearby::connections::mojom::ConnectionOptionsPtr;
+using ::nearby::connections::mojom::DiscoveredEndpointInfo;
+using ::nearby::connections::mojom::FilePayload;
+using ::nearby::connections::mojom::Payload;
+using ::nearby::connections::mojom::PayloadContent;
+using ::nearby::connections::mojom::PayloadListener;
+using ::nearby::connections::mojom::PayloadPtr;
+using ::nearby::connections::mojom::PayloadStatus;
+using ::nearby::connections::mojom::PayloadTransferUpdate;
+using ::nearby::connections::mojom::PayloadTransferUpdatePtr;
+using ::nearby::connections::mojom::Status;
 using ::testing::_;
 using ::testing::Invoke;
 
diff --git a/chrome/browser/ash/secure_channel/nearby_connector_impl_unittest.cc b/chrome/browser/ash/secure_channel/nearby_connector_impl_unittest.cc
index 888720a..63df725 100644
--- a/chrome/browser/ash/secure_channel/nearby_connector_impl_unittest.cc
+++ b/chrome/browser/ash/secure_channel/nearby_connector_impl_unittest.cc
@@ -42,8 +42,7 @@
  private:
   // NearbyEndpointFinderImpl::Factory:
   std::unique_ptr<NearbyEndpointFinder> CreateInstance(
-      const mojo::SharedRemote<
-          location::nearby::connections::mojom::NearbyConnections>&
+      const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
           nearby_connections) override {
     return std::make_unique<FakeNearbyEndpointFinder>();
   }
@@ -65,8 +64,7 @@
       mojo::PendingReceiver<mojom::NearbyFilePayloadHandler>
           file_payload_handler_receiver,
       mojo::PendingRemote<mojom::NearbyMessageReceiver> message_receiver_remote,
-      const mojo::SharedRemote<
-          location::nearby::connections::mojom::NearbyConnections>&
+      const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
           nearby_connections,
       base::OnceClosure on_connected_callback,
       base::OnceClosure on_disconnected_callback,
diff --git a/chrome/browser/ash/secure_channel/nearby_endpoint_finder.cc b/chrome/browser/ash/secure_channel/nearby_endpoint_finder.cc
index 42dff944..7fbba52 100644
--- a/chrome/browser/ash/secure_channel/nearby_endpoint_finder.cc
+++ b/chrome/browser/ash/secure_channel/nearby_endpoint_finder.cc
@@ -31,7 +31,7 @@
 
 void NearbyEndpointFinder::NotifyEndpointFound(
     const std::string& endpoint_id,
-    location::nearby::connections::mojom::DiscoveredEndpointInfoPtr info) {
+    ::nearby::connections::mojom::DiscoveredEndpointInfoPtr info) {
   std::move(success_callback_).Run(endpoint_id, std::move(info));
 }
 
diff --git a/chrome/browser/ash/secure_channel/nearby_endpoint_finder.h b/chrome/browser/ash/secure_channel/nearby_endpoint_finder.h
index 2c66005..e2b0dad 100644
--- a/chrome/browser/ash/secure_channel/nearby_endpoint_finder.h
+++ b/chrome/browser/ash/secure_channel/nearby_endpoint_finder.h
@@ -23,7 +23,7 @@
   // discovered endpoint.
   using EndpointCallback = base::OnceCallback<void(
       const std::string&,
-      location::nearby::connections::mojom::DiscoveredEndpointInfoPtr)>;
+      ::nearby::connections::mojom::DiscoveredEndpointInfoPtr)>;
 
   // Attempts to find an endpoint for the device with the provided Bluetooth
   // address, which is expected to be a 6-byte MAC address.
@@ -43,7 +43,7 @@
 
   void NotifyEndpointFound(
       const std::string& endpoint_id,
-      location::nearby::connections::mojom::DiscoveredEndpointInfoPtr info);
+      ::nearby::connections::mojom::DiscoveredEndpointInfoPtr info);
   void NotifyEndpointDiscoveryFailure();
 
   virtual void PerformFindEndpoint() = 0;
diff --git a/chrome/browser/ash/secure_channel/nearby_endpoint_finder_impl.cc b/chrome/browser/ash/secure_channel/nearby_endpoint_finder_impl.cc
index 1c89dd1..d5b5ee04 100644
--- a/chrome/browser/ash/secure_channel/nearby_endpoint_finder_impl.cc
+++ b/chrome/browser/ash/secure_channel/nearby_endpoint_finder_impl.cc
@@ -15,11 +15,11 @@
 namespace secure_channel {
 namespace {
 
-using ::location::nearby::connections::mojom::DiscoveredEndpointInfoPtr;
-using ::location::nearby::connections::mojom::DiscoveryOptions;
-using ::location::nearby::connections::mojom::MediumSelection;
-using ::location::nearby::connections::mojom::Status;
-using ::location::nearby::connections::mojom::Strategy;
+using ::nearby::connections::mojom::DiscoveredEndpointInfoPtr;
+using ::nearby::connections::mojom::DiscoveryOptions;
+using ::nearby::connections::mojom::MediumSelection;
+using ::nearby::connections::mojom::Status;
+using ::nearby::connections::mojom::Strategy;
 
 NearbyEndpointFinderImpl::Factory* g_test_factory = nullptr;
 
@@ -69,8 +69,7 @@
 
 // static
 std::unique_ptr<NearbyEndpointFinder> NearbyEndpointFinderImpl::Factory::Create(
-    const mojo::SharedRemote<
-        location::nearby::connections::mojom::NearbyConnections>&
+    const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
         nearby_connections) {
   if (g_test_factory)
     return g_test_factory->CreateInstance(nearby_connections);
@@ -85,8 +84,7 @@
 }
 
 NearbyEndpointFinderImpl::NearbyEndpointFinderImpl(
-    const mojo::SharedRemote<
-        location::nearby::connections::mojom::NearbyConnections>&
+    const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
         nearby_connections)
     : nearby_connections_(nearby_connections),
       endpoint_id_(GenerateEndpointId()) {}
@@ -162,7 +160,7 @@
 }
 
 void NearbyEndpointFinderImpl::OnStopDiscoveryResult(
-    location::nearby::connections::mojom::DiscoveredEndpointInfoPtr info,
+    ::nearby::connections::mojom::DiscoveredEndpointInfoPtr info,
     Status status) {
   util::RecordStopDiscoveryResult(status);
 
diff --git a/chrome/browser/ash/secure_channel/nearby_endpoint_finder_impl.h b/chrome/browser/ash/secure_channel/nearby_endpoint_finder_impl.h
index 69ec0c2..f7785e6 100644
--- a/chrome/browser/ash/secure_channel/nearby_endpoint_finder_impl.h
+++ b/chrome/browser/ash/secure_channel/nearby_endpoint_finder_impl.h
@@ -22,13 +22,12 @@
 //   (4) Stopping discovery.
 class NearbyEndpointFinderImpl
     : public NearbyEndpointFinder,
-      public location::nearby::connections::mojom::EndpointDiscoveryListener {
+      public ::nearby::connections::mojom::EndpointDiscoveryListener {
  public:
   class Factory {
    public:
     static std::unique_ptr<NearbyEndpointFinder> Create(
-        const mojo::SharedRemote<
-            location::nearby::connections::mojom::NearbyConnections>&
+        const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
             nearby_connections);
     static void SetFactoryForTesting(Factory* test_factory);
 
@@ -36,14 +35,12 @@
 
    protected:
     virtual std::unique_ptr<NearbyEndpointFinder> CreateInstance(
-        const mojo::SharedRemote<
-            location::nearby::connections::mojom::NearbyConnections>&
+        const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
             nearby_connections) = 0;
   };
 
   NearbyEndpointFinderImpl(
-      const mojo::SharedRemote<
-          location::nearby::connections::mojom::NearbyConnections>&
+      const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
           nearby_connections);
   ~NearbyEndpointFinderImpl() override;
 
@@ -53,26 +50,23 @@
   // NearbyEndpointFinder:
   void PerformFindEndpoint() override;
 
-  // location::nearby::connections::mojom::EndpointDiscoveryListener:
+  // ::nearby::connections::mojom::EndpointDiscoveryListener:
   void OnEndpointFound(
       const std::string& endpoint_id,
-      location::nearby::connections::mojom::DiscoveredEndpointInfoPtr info)
-      override;
+      ::nearby::connections::mojom::DiscoveredEndpointInfoPtr info) override;
   void OnEndpointLost(const std::string& endpoint_id) override {}
 
-  void OnStartDiscoveryResult(
-      location::nearby::connections::mojom::Status status);
+  void OnStartDiscoveryResult(::nearby::connections::mojom::Status status);
   void OnInjectBluetoothEndpointResult(
-      location::nearby::connections::mojom::Status status);
+      ::nearby::connections::mojom::Status status);
   void OnStopDiscoveryResult(
-      location::nearby::connections::mojom::DiscoveredEndpointInfoPtr info,
-      location::nearby::connections::mojom::Status status);
+      ::nearby::connections::mojom::DiscoveredEndpointInfoPtr info,
+      ::nearby::connections::mojom::Status status);
 
-  mojo::SharedRemote<location::nearby::connections::mojom::NearbyConnections>
+  mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>
       nearby_connections_;
 
-  mojo::Receiver<
-      location::nearby::connections::mojom::EndpointDiscoveryListener>
+  mojo::Receiver<::nearby::connections::mojom::EndpointDiscoveryListener>
       endpoint_discovery_listener_receiver_{this};
   bool is_discovery_active_ = false;
   std::string endpoint_id_;
diff --git a/chrome/browser/ash/secure_channel/nearby_endpoint_finder_impl_unittest.cc b/chrome/browser/ash/secure_channel/nearby_endpoint_finder_impl_unittest.cc
index d357c9e8..dd8eadd 100644
--- a/chrome/browser/ash/secure_channel/nearby_endpoint_finder_impl_unittest.cc
+++ b/chrome/browser/ash/secure_channel/nearby_endpoint_finder_impl_unittest.cc
@@ -20,10 +20,10 @@
 namespace secure_channel {
 namespace {
 
-using ::location::nearby::connections::mojom::DiscoveredEndpointInfo;
-using ::location::nearby::connections::mojom::DiscoveredEndpointInfoPtr;
-using ::location::nearby::connections::mojom::EndpointDiscoveryListener;
-using ::location::nearby::connections::mojom::Status;
+using ::nearby::connections::mojom::DiscoveredEndpointInfo;
+using ::nearby::connections::mojom::DiscoveredEndpointInfoPtr;
+using ::nearby::connections::mojom::EndpointDiscoveryListener;
+using ::nearby::connections::mojom::Status;
 using ::testing::_;
 using ::testing::Invoke;
 
diff --git a/chrome/browser/ash/secure_channel/util/histogram_util.cc b/chrome/browser/ash/secure_channel/util/histogram_util.cc
index 102c594..fe0c6c2 100644
--- a/chrome/browser/ash/secure_channel/util/histogram_util.cc
+++ b/chrome/browser/ash/secure_channel/util/histogram_util.cc
@@ -12,8 +12,7 @@
 
 namespace {
 
-using ::location::nearby::connections::mojom::Status;
-
+using ::nearby::connections::mojom::Status;
 }
 
 void RecordStartDiscoveryResult(Status status) {
@@ -57,7 +56,7 @@
 }
 
 void RecordRegisterPayloadFilesResult(
-    location::nearby::connections::mojom::Status status) {
+    ::nearby::connections::mojom::Status status) {
   base::UmaHistogramEnumeration(
       "MultiDevice.SecureChannel.Nearby.OperationResult.RegisterPayloadFiles",
       status);
diff --git a/chrome/browser/ash/secure_channel/util/histogram_util.h b/chrome/browser/ash/secure_channel/util/histogram_util.h
index 8e35af7..afeac36 100644
--- a/chrome/browser/ash/secure_channel/util/histogram_util.h
+++ b/chrome/browser/ash/secure_channel/util/histogram_util.h
@@ -12,22 +12,16 @@
 namespace util {
 
 // Logs the result of Nearby Connections API functions.
-void RecordStartDiscoveryResult(
-    location::nearby::connections::mojom::Status status);
-void RecordInjectEndpointResult(
-    location::nearby::connections::mojom::Status status);
-void RecordStopDiscoveryResult(
-    location::nearby::connections::mojom::Status status);
-void RecordRequestConnectionResult(
-    location::nearby::connections::mojom::Status status);
-void RecordAcceptConnectionResult(
-    location::nearby::connections::mojom::Status status);
-void RecordSendPayloadResult(
-    location::nearby::connections::mojom::Status status);
+void RecordStartDiscoveryResult(::nearby::connections::mojom::Status status);
+void RecordInjectEndpointResult(::nearby::connections::mojom::Status status);
+void RecordStopDiscoveryResult(::nearby::connections::mojom::Status status);
+void RecordRequestConnectionResult(::nearby::connections::mojom::Status status);
+void RecordAcceptConnectionResult(::nearby::connections::mojom::Status status);
+void RecordSendPayloadResult(::nearby::connections::mojom::Status status);
 void RecordDisconnectFromEndpointResult(
-    location::nearby::connections::mojom::Status status);
+    ::nearby::connections::mojom::Status status);
 void RecordRegisterPayloadFilesResult(
-    location::nearby::connections::mojom::Status status);
+    ::nearby::connections::mojom::Status status);
 
 // Enumeration of possible file payload transfer actions via Nearby Connection
 // library. Keep in sync with corresponding enum in
diff --git a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java
index e45deb1..e120bc0 100644
--- a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java
+++ b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java
@@ -37,13 +37,13 @@
             put(Type.VR_DELEGATE, 1);
             put(Type.AR_DELEGATE, 2);
             put(Type.SCENE_OVERLAY, 3);
-            put(Type.START_SURFACE_MEDIATOR, 4);
+            put(Type.START_SURFACE, 4);
             put(Type.SELECTION_POPUP, 5);
             put(Type.MANUAL_FILLING, 6);
             put(Type.FULLSCREEN, 7);
             put(Type.BOTTOM_SHEET, 8);
             put(Type.TAB_MODAL_HANDLER, 9);
-            put(Type.TAB_SWITCHER_TO_BROWSING, 10);
+            put(Type.TAB_SWITCHER, 10);
             put(Type.CLOSE_WATCHER, 11);
             put(Type.TAB_HISTORY, 12);
             put(Type.TAB_RETURN_TO_CHROME_START_SURFACE, 13);
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 163953e9..151f110 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -306,11 +306,14 @@
         <include name="IDR_PARENT_ACCESS_APP_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\parent_access\parent_access_app.js" use_base_dir="false" type="BINDATA" />
         <include name="IDR_PARENT_ACCESS_UI_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\parent_access\parent_access_ui.js" use_base_dir="false" type="BINDATA" />
         <include name="IDR_PARENT_ACCESS_AFTER_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\parent_access\parent_access_after.js" use_base_dir="false" type="BINDATA" />
+        <include name="IDR_PARENT_ACCESS_BEFORE_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\parent_access\parent_access_before.js" use_base_dir="false" type="BINDATA" />
         <include name="IDR_PARENT_ACCESS_WEBVIEW_MANAGER_JS" file="resources\chromeos\parent_access\webview_manager.js" type="BINDATA" />
         <include name="IDR_LOCAL_WEB_APPROVALS_AFTER_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\parent_access\flows\local_web_approvals_after.js" use_base_dir="false" type="BINDATA" />
         <include name="IDR_PARENT_ACCESS_CONTROLLER_JS" file="resources\chromeos\parent_access\parent_access_controller.js" type="BINDATA" />
         <include name="IDR_PARENT_ACCESS_UI_HANDLER_JS" file="resources\chromeos\parent_access\parent_access_ui_handler.js" type="BINDATA" />
         <include name="IDR_PARENT_ACCESS_UI_MOJOM_WEBUI_JS" file="${root_gen_dir}\mojom-webui\chrome\browser\ui\webui\ash\parent_access\parent_access_ui.mojom-webui.js" use_base_dir="false" type="BINDATA" />
+        <include name="IDR_PARENT_ACCESS_REQUEST_APPROVAL_SVG" file="resources\chromeos\parent_access\images\request_approval.svg" type="BINDATA" />
+        <include name="IDR_PARENT_ACCESS_REQUEST_APPROVAL_DARK_SVG" file="resources\chromeos\parent_access\images\request_approval_dark.svg" type="BINDATA" />
       </if>
       <if expr="safe_browsing_mode == 1">
         <include name="IDR_RESET_PASSWORD_HTML" file="resources\reset_password\reset_password.html" type="BINDATA" />
diff --git a/chrome/browser/browsing_data/incognito_browsing_data_browsertest.cc b/chrome/browser/browsing_data/incognito_browsing_data_browsertest.cc
index 99405ef..454dbd1 100644
--- a/chrome/browser/browsing_data/incognito_browsing_data_browsertest.cc
+++ b/chrome/browser/browsing_data/incognito_browsing_data_browsertest.cc
@@ -462,8 +462,15 @@
   TestSiteData("WebSql");
 }
 
+// TODO(crbug.com/1317431): WebSQL does not work on Fuchsia.
+#if BUILDFLAG(IS_FUCHSIA)
+#define MAYBE_EmptyWebSqlDeletion DISABLED_EmptyWebSqlDeletion
+#else
+#define MAYBE_EmptyWebSqlDeletion EmptyWebSqlDeletion
+#endif
 // Test that empty websql dbs are deleted correctly.
-IN_PROC_BROWSER_TEST_F(IncognitoBrowsingDataBrowserTest, EmptyWebSqlDeletion) {
+IN_PROC_BROWSER_TEST_F(IncognitoBrowsingDataBrowserTest,
+                       MAYBE_EmptyWebSqlDeletion) {
   TestEmptySiteData("WebSql");
 }
 
diff --git a/chrome/browser/dips/dips_database.cc b/chrome/browser/dips/dips_database.cc
index 8c2b728..9f895ec0 100644
--- a/chrome/browser/dips/dips_database.cc
+++ b/chrome/browser/dips/dips_database.cc
@@ -685,13 +685,8 @@
 
   GarbageCollect();
 
-  if (!ClearTimestamps(delete_begin, delete_end, type) ||
-      !AdjustFirstTimestamps(delete_begin, delete_end, type) ||
-      !AdjustLastTimestamps(delete_begin, delete_end, type)) {
-    return false;
-  }
-
-  return transaction.Commit();
+  return (ClearTimestamps(delete_begin, delete_end, type) &&
+          transaction.Commit());
 }
 
 bool DIPSDatabase::RemoveEventsBySite(bool preserve,
@@ -799,7 +794,9 @@
     }
   }
 
-  return RemoveEmptyRows();
+  return (RemoveEmptyRows() &&
+          AdjustFirstTimestamps(delete_begin, delete_end, type) &&
+          AdjustLastTimestamps(delete_begin, delete_end, type));
 }
 
 bool DIPSDatabase::AdjustFirstTimestamps(const base::Time& delete_begin,
@@ -810,6 +807,13 @@
     return false;
   ClearRowsWithExpiredInteractions();
 
+  if (delete_end == base::Time::Max()) {
+    // When `delete_end` is `base::Time::Max()`, any timestamp range that would
+    // be altered by the below queries should have already been removed by
+    // ClearTimestamps(), which MUST always be called before this method.
+    return true;
+  }
+
   if ((type & DIPSEventRemovalType::kHistory) ==
       DIPSEventRemovalType::kHistory) {
     static constexpr char kUpdateFirstInteractionSql[] =  // clang-format off
@@ -891,6 +895,13 @@
     return false;
   ClearRowsWithExpiredInteractions();
 
+  if (delete_begin == base::Time::Min()) {
+    // When `delete_begin` is `base::Time::Min()`, any timestamp range that
+    // would be altered by the below queries should have already been removed by
+    // ClearTimestamps(), which MUST always be called before this method.
+    return true;
+  }
+
   if ((type & DIPSEventRemovalType::kHistory) ==
       DIPSEventRemovalType::kHistory) {
     static constexpr char kUpdateLastInteractionSql[] =  // clang-format off
diff --git a/chrome/browser/dips/dips_database.h b/chrome/browser/dips/dips_database.h
index 3a81957..5321597 100644
--- a/chrome/browser/dips/dips_database.h
+++ b/chrome/browser/dips/dips_database.h
@@ -138,6 +138,7 @@
   size_t GetMaxEntries() const { return max_entries_; }
   size_t GetPurgeEntries() const { return purge_entries_; }
 
+  // Testing functions --------------------------------------------------
   void SetMaxEntriesForTesting(size_t entries) { max_entries_ = entries; }
   void SetPurgeEntriesForTesting(size_t entries) { purge_entries_ = entries; }
   void SetClockForTesting(base::Clock* clock) { clock_ = clock; }
@@ -154,13 +155,6 @@
   bool ClearTimestamps(const base::Time& delete_begin,
                        const base::Time& delete_end,
                        const DIPSEventRemovalType type);
-  bool AdjustFirstTimestamps(const base::Time& delete_begin,
-                             const base::Time& delete_end,
-                             const DIPSEventRemovalType type);
-  bool AdjustLastTimestamps(const base::Time& delete_begin,
-                            const base::Time& delete_end,
-                            const DIPSEventRemovalType type);
-
   bool ClearTimestampsBySite(bool preserve,
                              const std::vector<std::string>& sites,
                              const DIPSEventRemovalType type);
@@ -172,6 +166,15 @@
   // Callback for database errors.
   void DatabaseErrorCallback(int extended_error, sql::Statement* stmt);
 
+  // Only ClearTimestamps() should call this method.
+  bool AdjustFirstTimestamps(const base::Time& delete_begin,
+                             const base::Time& delete_end,
+                             const DIPSEventRemovalType type);
+  // Only ClearTimestamps() should call this method.
+  bool AdjustLastTimestamps(const base::Time& delete_begin,
+                            const base::Time& delete_end,
+                            const DIPSEventRemovalType type);
+
   // When the number of entries in the database exceeds |max_entries_|, purge
   // down to |max_entries_| - |purge_entries_|.
   size_t max_entries_ = 3500;
diff --git a/chrome/browser/feedback/android/family_info_feedback_source.h b/chrome/browser/feedback/android/family_info_feedback_source.h
index ecc8c77..7e1f766 100644
--- a/chrome/browser/feedback/android/family_info_feedback_source.h
+++ b/chrome/browser/feedback/android/family_info_feedback_source.h
@@ -39,6 +39,7 @@
 
  private:
   friend class FamilyInfoFeedbackSourceTest;
+  friend class FamilyInfoFeedbackSourceForChildFilterBehaviorTest;
 
   // FamilyInfoFetcher::Consumer implementation.
   void OnGetFamilyMembersSuccess(
diff --git a/chrome/browser/feedback/android/family_info_feedback_source_unittest.cc b/chrome/browser/feedback/android/family_info_feedback_source_unittest.cc
index 23e95ef..cc124a1 100644
--- a/chrome/browser/feedback/android/family_info_feedback_source_unittest.cc
+++ b/chrome/browser/feedback/android/family_info_feedback_source_unittest.cc
@@ -5,19 +5,27 @@
 #include "chrome/browser/feedback/android/family_info_feedback_source.h"
 
 #include <memory>
+#include <string>
+#include <tuple>
 
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
 #include "base/android/scoped_java_ref.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/flags/android/chrome_feature_list.h"
 #include "chrome/browser/profiles/profile_android.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
 #include "chrome/browser/signin/test_signin_client_builder.h"
+#include "chrome/browser/supervised_user/child_accounts/family_info_fetcher.h"
+#include "chrome/browser/supervised_user/supervised_user_denylist.h"
+#include "chrome/browser/supervised_user/supervised_user_service.h"
+#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
+#include "chrome/browser/supervised_user/supervised_user_url_filter.h"
 #include "chrome/test/test_support_jni_headers/FamilyInfoFeedbackSourceTestBridge_jni.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
-#include "components/signin/public/identity_manager/identity_test_utils.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -28,9 +36,156 @@
 namespace {
 
 const char kTestEmail[] = "test@gmail.com";
-
+const char kFeedbackTagFamilyMemberRole[] = "Family_Member_Role";
+const char kFeedbackTagParentalControlSitesChild[] =
+    "Parental_Control_Sites_Child";
 }  // namespace
 
+class FamilyInfoFeedbackSourceForChildFilterBehaviorTest
+    : public testing::TestWithParam<
+          std::tuple<SupervisedUserURLFilter::FilteringBehavior, bool>> {
+ public:
+  FamilyInfoFeedbackSourceForChildFilterBehaviorTest()
+      : env_(base::android::AttachCurrentThread()) {}
+
+  void SetUp() override {
+    TestingProfile::Builder builder;
+    builder.AddTestingFactory(
+        ChromeSigninClientFactory::GetInstance(),
+        base::BindRepeating(&signin::BuildTestSigninClient));
+    builder.SetIsSupervisedProfile();
+
+    role_ = FamilyInfoFetcher::FamilyMemberRole::CHILD;
+    profile_ = IdentityTestEnvironmentProfileAdaptor::
+        CreateProfileForIdentityTestEnvironment(builder);
+    identity_test_env_profile_adaptor_ =
+        std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile_.get());
+    j_feedback_source_ = CreateJavaObjectForTesting();
+    supervised_user_service_ =
+        SupervisedUserServiceFactory::GetForProfile(profile_.get());
+  }
+
+ protected:
+  signin::IdentityTestEnvironment* identity_test_env() {
+    return identity_test_env_profile_adaptor_->identity_test_env();
+  }
+
+  // Methods to access Java counterpart FamilyInfoFeedbackSource.
+  std::string GetFeedbackValue(std::string feedback_tag) {
+    const base::android::JavaRef<jstring>& j_value =
+        Java_FamilyInfoFeedbackSourceTestBridge_getValue(
+            env_,
+            base::android::JavaParamRef<jobject>(env_,
+                                                 j_feedback_source_.obj()),
+            base::android::ConvertUTF8ToJavaString(env_, feedback_tag));
+    return base::android::ConvertJavaStringToUTF8(env_, j_value);
+  }
+
+  void OnGetFamilyMembersSuccess(
+      base::WeakPtr<FamilyInfoFeedbackSource> feedback_source,
+      const std::vector<FamilyInfoFetcher::FamilyMember>& members) {
+    feedback_source->OnGetFamilyMembersSuccess(members);
+  }
+
+  // Creates a new instance of FamilyInfoFeedbackSource that is destroyed on
+  // completion of OnGetFamilyMembers* methods.
+  base::WeakPtr<FamilyInfoFeedbackSource> CreateFamilyInfoFeedbackSource() {
+    FamilyInfoFeedbackSource* source = new FamilyInfoFeedbackSource(
+        base::android::JavaParamRef<jobject>(env_, j_feedback_source_.obj()),
+        profile_.get());
+    return source->weak_factory_.GetWeakPtr();
+  }
+
+  // Returns the expected string representation of the Parental_Control_
+  // Sites_Parent PSD field that is included in the feedback log.
+  std::string GetFilterTypeAsString(
+      SupervisedUserURLFilter::FilteringBehavior behavior,
+      bool safe_sites_enabled) {
+    switch (behavior) {
+      case (SupervisedUserURLFilter::FilteringBehavior::BLOCK):
+        return "allow_certain_sites";
+      case (SupervisedUserURLFilter::FilteringBehavior::ALLOW):
+        if (safe_sites_enabled) {
+          return "block_mature_sites";
+        } else {
+          return "allow_all_sites";
+        }
+      case (SupervisedUserURLFilter::FilteringBehavior::INVALID):
+        return "";
+    }
+  }
+
+  FamilyInfoFetcher::FamilyMemberRole role_;
+  raw_ptr<SupervisedUserService> supervised_user_service_;
+  SupervisedUserDenylist deny_list_ = SupervisedUserDenylist();
+
+ private:
+  // Creates a Java instance of FamilyInfoFeedbackSource.
+  base::android::ScopedJavaLocalRef<jobject> CreateJavaObjectForTesting() {
+    ProfileAndroid* profile_android =
+        ProfileAndroid::FromProfile(profile_.get());
+    return Java_FamilyInfoFeedbackSourceTestBridge_createFamilyInfoFeedbackSource(
+        env_, base::android::JavaParamRef<jobject>(
+                  env_, profile_android->GetJavaObject().Release()));
+  }
+
+  content::BrowserTaskEnvironment task_environment_;
+  base::android::ScopedJavaLocalRef<jobject> j_feedback_source_;
+  raw_ptr<JNIEnv> env_;
+  std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
+      identity_test_env_profile_adaptor_;
+  std::unique_ptr<TestingProfile> profile_;
+};
+
+// Tests that the parental control sites value for a child user is recorded.
+TEST_P(FamilyInfoFeedbackSourceForChildFilterBehaviorTest,
+       GetChildFilteringBehaviour) {
+  base::test::ScopedFeatureList scoped_list;
+  scoped_list.InitAndEnableFeature(
+      chrome::android::kReportParentalControlSitesChild);
+
+  CoreAccountInfo primary_account =
+      identity_test_env()->MakePrimaryAccountAvailable(
+          kTestEmail, signin::ConsentLevel::kSignin);
+
+  SupervisedUserURLFilter::FilteringBehavior filtering_behavior =
+      std::get<0>(GetParam());
+  supervised_user_service_->GetURLFilter()->SetDefaultFilteringBehavior(
+      filtering_behavior);
+
+  bool safe_sites_enabled = std::get<1>(GetParam());
+  if (safe_sites_enabled) {
+    supervised_user_service_->GetURLFilter()->SetDenylist(&deny_list_);
+  }
+
+  std::vector<FamilyInfoFetcher::FamilyMember> members(
+      {FamilyInfoFetcher::FamilyMember(
+          primary_account.gaia, role_, "Name", kTestEmail,
+          /*profile_url=*/std::string(), /*profile_image_url=*/std::string())});
+
+  base::WeakPtr<FamilyInfoFeedbackSource> feedback_source =
+      CreateFamilyInfoFeedbackSource();
+  OnGetFamilyMembersSuccess(feedback_source, members);
+
+  std::string expected_filter =
+      GetFilterTypeAsString(filtering_behavior, safe_sites_enabled);
+  EXPECT_EQ(expected_filter,
+            GetFeedbackValue(kFeedbackTagParentalControlSitesChild));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    FilterBehaviourContainer,
+    FamilyInfoFeedbackSourceForChildFilterBehaviorTest,
+    ::testing::Values(
+        std::make_tuple(SupervisedUserURLFilter::FilteringBehavior::BLOCK,
+                        false),
+        std::make_tuple(SupervisedUserURLFilter::FilteringBehavior::BLOCK,
+                        true),
+        std::make_tuple(SupervisedUserURLFilter::FilteringBehavior::ALLOW,
+                        false),
+        std::make_tuple(SupervisedUserURLFilter::FilteringBehavior::ALLOW,
+                        true)));
+
 class FamilyInfoFeedbackSourceTest
     : public testing::TestWithParam<FamilyInfoFetcher::FamilyMemberRole> {
  public:
@@ -60,7 +215,8 @@
             env_,
             base::android::JavaParamRef<jobject>(env_,
                                                  j_feedback_source_.obj()),
-            base::android::ConvertUTF8ToJavaString(env_, "Family_Member_Role"));
+            base::android::ConvertUTF8ToJavaString(
+                env_, kFeedbackTagFamilyMemberRole));
     return base::android::ConvertJavaStringToUTF8(env_, j_value);
   }
 
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index daade1a..f6a7254 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -859,11 +859,6 @@
     "expiry_milestone": 114
   },
   {
-    "name": "captive-portal-ui-2022",
-    "owners": [ "michaelrygiel", "stevenjb", "cros-network-health-team@google.com" ],
-    "expiry_milestone": 110
-  },
-  {
     "name": "cast-streaming-hardware-h264",
     "owners": [ "jophba", "openscreen-eng" ],
     "expiry_milestone": 121
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 0c7aaed..66fa04b1 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -5900,13 +5900,6 @@
     "Enables the Quick Settings Network revamp, which updates Network Quick "
     "Settings UI and related infrastructure. See https://crbug.com/1169479.";
 
-const char kCaptivePortalUI2022Name[] =
-    "Enables the Captive Portal UI 2022 changes.";
-const char kCaptivePortalUI2022Description[] =
-    "Enables the Captive Portal UI 2022 changes, which includes updates to "
-    "notifications, network details page, quick settings, and portal signin "
-    "UI.";
-
 const char kCaptivePortalErrorPageName[] =
     "Enables Captive Portal error page suggestions.";
 const char kCaptivePortalErrorPageDescription[] =
@@ -5964,11 +5957,6 @@
     "timestamp) instead of the system audio/video devices, for debugging "
     "purposes.";
 
-const char kUseMultipleOverlaysName[] = "Use Multiple Overlays";
-const char kUseMultipleOverlaysDescription[] =
-    "Specifies the maximum number of quads that Chrome will attempt to promote"
-    " to overlays.";
-
 const char kUXStudy1Name[] = "UX Study 1";
 const char kUXStudy1Description[] = "Opt into a group for UX Study";
 
@@ -6260,10 +6248,6 @@
     "video is recorded in VBR encoding in MediaRecoder API automatically and "
     "WebCodecs API if configured so.";
 #if defined(ARCH_CPU_ARM_FAMILY)
-const char kPreferLibYuvImageProcessorName[] = "Prefer libYUV image processor";
-const char kPreferLibYuvImageProcessorDescription[] =
-    "Prefers the libYUV image processor for format conversion of video frames "
-    "over the hardware implementation";
 const char kPreferGLImageProcessorName[] = "Prefer GL image processor";
 const char kPreferGLImageProcessorDescription[] =
     "Prefers the GL image processor for format conversion of video frames over"
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index a51704c..dd285cc 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -3395,9 +3395,6 @@
 extern const char kQuickSettingsNetworkRevampName[];
 extern const char kQuickSettingsNetworkRevampDescription[];
 
-extern const char kCaptivePortalUI2022Name[];
-extern const char kCaptivePortalUI2022Description[];
-
 extern const char kCaptivePortalErrorPageName[];
 extern const char kCaptivePortalErrorPageDescription[];
 
@@ -3437,9 +3434,6 @@
 extern const char kUseFakeDeviceForMediaStreamName[];
 extern const char kUseFakeDeviceForMediaStreamDescription[];
 
-extern const char kUseMultipleOverlaysName[];
-extern const char kUseMultipleOverlaysDescription[];
-
 extern const char kUXStudy1Name[];
 extern const char kUXStudy1Description[];
 
@@ -3605,8 +3599,6 @@
 extern const char kChromeOSHWVBREncodingName[];
 extern const char kChromeOSHWVBREncodingDescription[];
 #if defined(ARCH_CPU_ARM_FAMILY)
-extern const char kPreferLibYuvImageProcessorName[];
-extern const char kPreferLibYuvImageProcessorDescription[];
 extern const char kPreferGLImageProcessorName[];
 extern const char kPreferGLImageProcessorDescription[];
 #endif  // defined(ARCH_CPU_ARM_FAMILY
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index 4cd03a66..a9aec27f 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -567,7 +567,7 @@
     public static final CachedFlag sCctResizable90MaximumHeight =
             new CachedFlag(CCT_RESIZABLE_90_MAXIMUM_HEIGHT, false);
     public static final CachedFlag sCctResizableForThirdParties =
-            new CachedFlag(CCT_RESIZABLE_FOR_THIRD_PARTIES, false);
+            new CachedFlag(CCT_RESIZABLE_FOR_THIRD_PARTIES, true);
     public static final CachedFlag sCctResizableSideSheet =
             new CachedFlag(CCT_RESIZABLE_SIDE_SHEET, false);
     public static final CachedFlag sCctRetainableStateInMemory =
diff --git a/chrome/browser/headless/BUILD.gn b/chrome/browser/headless/BUILD.gn
new file mode 100644
index 0000000..3fc559e
--- /dev/null
+++ b/chrome/browser/headless/BUILD.gn
@@ -0,0 +1,63 @@
+# 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/chrome_build.gni")
+import("//build/config/ozone.gni")
+import("//testing/test.gni")
+
+source_set("headless") {
+  sources = [
+    "headless_mode_util.cc",
+    "headless_mode_util.h",
+  ]
+
+  deps = [
+    "//base",
+    "//ui/gfx",
+  ]
+
+  if (is_linux) {
+    deps += [
+      "//ui/gl",
+      "//ui/ozone",
+    ]
+  }
+}
+
+if (!is_android) {
+  source_set("browser_tests") {
+    testonly = true
+    defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
+
+    sources = [
+      "headless_mode_browsertest.cc",
+      "headless_mode_browsertest.h",
+    ]
+
+    if (is_linux) {
+      sources += [ "headless_mode_browsertest_linux.cc" ]
+    }
+
+    if (is_win) {
+      sources += [ "headless_mode_browsertest_win.cc" ]
+    }
+
+    if (is_mac) {
+      sources += [ "headless_mode_browsertest_mac.mm" ]
+    }
+
+    deps = [
+      ":headless",
+      "//base",
+      "//chrome/browser",
+      "//chrome/test:test_support",
+      "//content/test:test_support",
+      "//testing/gtest",
+    ]
+
+    if (use_ozone && is_linux) {
+      deps += [ "//ui/ozone" ]
+    }
+  }
+}
diff --git a/chrome/browser/headless/headless_mode_util.cc b/chrome/browser/headless/headless_mode_util.cc
index fcf39bd..de1c3cb 100644
--- a/chrome/browser/headless/headless_mode_util.cc
+++ b/chrome/browser/headless/headless_mode_util.cc
@@ -15,8 +15,8 @@
 #include "base/base_switches.h"
 
 #if BUILDFLAG(IS_LINUX)
-#include "ui/gl/gl_switches.h"
-#include "ui/ozone/public/ozone_switches.h"
+#include "ui/gl/gl_switches.h"               // nogncheck
+#include "ui/ozone/public/ozone_switches.h"  // nogncheck
 #endif  // BUILDFLAG(IS_LINUX)
 
 namespace headless {
diff --git a/chrome/browser/lens/region_search/lens_region_search_controller.cc b/chrome/browser/lens/region_search/lens_region_search_controller.cc
index ac26b2b..211fe92f 100644
--- a/chrome/browser/lens/region_search/lens_region_search_controller.cc
+++ b/chrome/browser/lens/region_search/lens_region_search_controller.cc
@@ -222,18 +222,8 @@
   }
 
   if (is_google_default_search_provider_) {
-    // Do not show the side panel on region searches and modify the entry point
-    // if Lens fullscreen search features are enabled.
-    lens::EntryPoint entry_point =
-        lens::features::IsLensFullscreenSearchEnabled()
-            ? lens::EntryPoint::CHROME_FULLSCREEN_SEARCH_MENU_ITEM
-            : lens::EntryPoint::CHROME_REGION_SEARCH_MENU_ITEM;
-    core_tab_helper->SearchWithLens(
-        image, captured_image.Size(), entry_point,
-        /* is_region_search_request= */ true,
-        /* is_side_panel_enabled_for_feature= */
-        lens::features::IsLensSidePanelEnabledForRegionSearch(),
-        std::move(log_data));
+    core_tab_helper->RegionSearchWithLens(image, captured_image.Size(),
+                                          std::move(log_data));
   } else {
     core_tab_helper->SearchByImage(image, captured_image.Size());
   }
diff --git a/chrome/browser/lookalikes/lookalike_test_helper.cc b/chrome/browser/lookalikes/lookalike_test_helper.cc
index 9f849ad..dd9af88 100644
--- a/chrome/browser/lookalikes/lookalike_test_helper.cc
+++ b/chrome/browser/lookalikes/lookalike_test_helper.cc
@@ -29,10 +29,10 @@
   url_formatter::IDNSpoofChecker::SetTrieParamsForTesting(trie_params);
 
   // Use test top 500 domain skeletons instead of the actual list.
-  Top500DomainsParams top500_params{
+  lookalikes::Top500DomainsParams top500_params{
       test_top500_domains::kTop500EditDistanceSkeletons,
       test_top500_domains::kNumTop500EditDistanceSkeletons};
-  SetTop500DomainsParamsForTesting(top500_params);
+  lookalikes::SetTop500DomainsParamsForTesting(top500_params);
 
   lookalikes::InitializeSafetyTipConfig();
 }
@@ -40,7 +40,7 @@
 // static
 void LookalikeTestHelper::TearDownLookalikeTestParams() {
   url_formatter::IDNSpoofChecker::RestoreTrieParamsForTesting();
-  ResetTop500DomainsParamsForTesting();
+  lookalikes::ResetTop500DomainsParamsForTesting();
 }
 
 void LookalikeTestHelper::CheckSafetyTipUkmCount(
diff --git a/chrome/browser/lookalikes/lookalike_test_helper.h b/chrome/browser/lookalikes/lookalike_test_helper.h
index dcea4f0..a8a9884 100644
--- a/chrome/browser/lookalikes/lookalike_test_helper.h
+++ b/chrome/browser/lookalikes/lookalike_test_helper.h
@@ -30,6 +30,4 @@
   ukm::TestUkmRecorder* ukm_recorder_;
 };
 
-bool IsShowingSafetyTip();
-
 #endif
diff --git a/chrome/browser/lookalikes/lookalike_url_blocking_page.cc b/chrome/browser/lookalikes/lookalike_url_blocking_page.cc
index c5cd504e..d792a8e 100644
--- a/chrome/browser/lookalikes/lookalike_url_blocking_page.cc
+++ b/chrome/browser/lookalikes/lookalike_url_blocking_page.cc
@@ -17,6 +17,8 @@
 #include "content/public/browser/web_contents.h"
 #include "net/base/net_errors.h"
 
+using lookalikes::LookalikeUrlBlockingPageUserAction;
+using lookalikes::LookalikeUrlMatchType;
 using security_interstitials::MetricsHelper;
 
 // static
@@ -58,12 +60,12 @@
 
 void LookalikeUrlBlockingPage::PopulateInterstitialStrings(
     base::Value::Dict& load_time_data) {
-  PopulateLookalikeUrlBlockingPageStrings(load_time_data, safe_url_,
-                                          request_url());
+  lookalikes::PopulateLookalikeUrlBlockingPageStrings(load_time_data, safe_url_,
+                                                      request_url());
 }
 
 void LookalikeUrlBlockingPage::OnInterstitialClosing() {
-  ReportUkmForLookalikeUrlBlockingPageIfNeeded(
+  lookalikes::ReportUkmForLookalikeUrlBlockingPageIfNeeded(
       source_id_, match_type_, LookalikeUrlBlockingPageUserAction::kCloseOrBack,
       triggered_by_initial_url_);
 }
@@ -88,7 +90,7 @@
     case security_interstitials::CMD_DONT_PROCEED:
       controller()->metrics_helper()->RecordUserDecision(
           MetricsHelper::DONT_PROCEED);
-      ReportUkmForLookalikeUrlBlockingPageIfNeeded(
+      lookalikes::ReportUkmForLookalikeUrlBlockingPageIfNeeded(
           source_id_, match_type_,
           LookalikeUrlBlockingPageUserAction::kAcceptSuggestion,
           triggered_by_initial_url_);
@@ -103,7 +105,7 @@
     case security_interstitials::CMD_PROCEED:
       controller()->metrics_helper()->RecordUserDecision(
           MetricsHelper::PROCEED);
-      ReportUkmForLookalikeUrlBlockingPageIfNeeded(
+      lookalikes::ReportUkmForLookalikeUrlBlockingPageIfNeeded(
           source_id_, match_type_,
           LookalikeUrlBlockingPageUserAction::kClickThrough,
           triggered_by_initial_url_);
diff --git a/chrome/browser/lookalikes/lookalike_url_blocking_page.h b/chrome/browser/lookalikes/lookalike_url_blocking_page.h
index c8d100f..503969f 100644
--- a/chrome/browser/lookalikes/lookalike_url_blocking_page.h
+++ b/chrome/browser/lookalikes/lookalike_url_blocking_page.h
@@ -11,8 +11,7 @@
 #include "components/lookalikes/core/lookalike_url_util.h"
 #include "components/security_interstitials/content/security_interstitial_page.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
-
-class GURL;
+#include "url/gurl.h"
 
 // This class is responsible for showing/hiding the interstitial page that
 // occurs when a new domain is visited and it looks suspiciously like another
@@ -29,7 +28,7 @@
       const GURL& safe_url,
       const GURL& request_url,
       ukm::SourceId source_id,
-      LookalikeUrlMatchType match_type,
+      lookalikes::LookalikeUrlMatchType match_type,
       bool is_signed_exchange,
       bool triggered_by_initial_url,
       std::unique_ptr<
@@ -62,7 +61,7 @@
   // the default action on the interstitial takes the user to the new tab page.
   const GURL safe_url_;
   ukm::SourceId source_id_;
-  LookalikeUrlMatchType match_type_;
+  lookalikes::LookalikeUrlMatchType match_type_;
   // True if the throttle encountered a response with
   // is_signed_exchange_inner_response flag. Only checked in tests.
   const bool is_signed_exchange_;
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
index 00149474..ede7772 100644
--- a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
+++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
@@ -31,7 +31,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_selections.h"
 #include "chrome/common/channel_info.h"
-#include "components/lookalikes/core/features.h"
 #include "components/lookalikes/core/lookalike_url_ui_util.h"
 #include "components/lookalikes/core/lookalike_url_util.h"
 #include "components/lookalikes/core/safety_tips_config.h"
@@ -43,6 +42,11 @@
 #include "content/public/browser/navigation_handle.h"
 #include "third_party/blink/public/mojom/loader/referrer.mojom.h"
 
+using lookalikes::DomainInfo;
+using lookalikes::GetETLDPlusOne;
+using lookalikes::LookalikeActionType;
+using lookalikes::LookalikeUrlMatchType;
+
 namespace {
 
 typedef content::NavigationThrottle::ThrottleCheckResult ThrottleCheckResult;
@@ -314,10 +318,11 @@
     LookalikeUrlMatchType match_type,
     bool triggered_by_initial_url) {
   // Cancel the prerender to show an interstitial after activation.
-  if (navigation_handle()->IsInPrerenderedMainFrame())
+  if (navigation_handle()->IsInPrerenderedMainFrame()) {
     return content::NavigationThrottle::CANCEL;
+  }
 
-  RecordUMAFromMatchType(match_type);
+  lookalikes::RecordUMAFromMatchType(match_type);
 
   // Punycode interstitial doesn't have a target site, so safe_domain isn't
   // valid.
@@ -487,7 +492,7 @@
   DCHECK_NE(LookalikeUrlMatchType::kNone, match_type);
   DCHECK(action_type == LookalikeActionType::kRecordMetrics ||
          action_type == LookalikeActionType::kShowSafetyTip);
-  RecordUMAFromMatchType(match_type);
+  lookalikes::RecordUMAFromMatchType(match_type);
   RecordPerformCheckLatenciesForAllowedNavigation(
       perform_checks_start, is_lookalike_url_duration,
       total_get_domain_info_duration);
@@ -495,9 +500,9 @@
   // ...but only record interstitial UKM if we aren't going to show a safety
   // tip. Otherwise, we'll double record UKM, both here and in safety tips.
   if (action_type == LookalikeActionType::kRecordMetrics) {
-    RecordUkmForLookalikeUrlBlockingPage(
+    lookalikes::RecordUkmForLookalikeUrlBlockingPage(
         source_id, match_type,
-        LookalikeUrlBlockingPageUserAction::kInterstitialNotShown,
+        lookalikes::LookalikeUrlBlockingPageUserAction::kInterstitialNotShown,
         first_is_lookalike);
   }
   return NavigationThrottle::PROCEED;
@@ -518,7 +523,7 @@
   // Don't warn on non-public domains.
   if (net::HostStringIsLocalhost(url.host()) ||
       net::IsHostnameNonUnique(url.host()) ||
-      GetETLDPlusOne(url.host()).empty() || IsSafeTLD(url.host())) {
+      GetETLDPlusOne(url.host()).empty() || lookalikes::IsSafeTLD(url.host())) {
     return false;
   }
 
@@ -536,13 +541,13 @@
   }
 
   // If the host is allowlisted by policy, don't show any warning.
-  if (IsAllowedByEnterprisePolicy(profile_->GetPrefs(), url)) {
+  if (lookalikes::IsAllowedByEnterprisePolicy(profile_->GetPrefs(), url)) {
     return false;
   }
 
   // GetDomainInfo() is expensive, so do possible early-abort checks first.
   base::TimeTicks get_domain_info_start = base::TimeTicks::Now();
-  const DomainInfo navigated_domain = GetDomainInfo(url);
+  const DomainInfo navigated_domain = lookalikes::GetDomainInfo(url);
   *get_domain_info_duration = base::TimeTicks::Now() - get_domain_info_start;
 
   if (IsTopDomain(navigated_domain)) {
@@ -560,7 +565,7 @@
     return false;
   }
 
-  const LookalikeTargetAllowlistChecker in_target_allowlist =
+  const lookalikes::LookalikeTargetAllowlistChecker in_target_allowlist =
       base::BindRepeating(
           &lookalikes::IsTargetHostAllowlistedBySafetyTipsComponent, proto);
   std::string matched_domain;
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.h b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.h
index 0cb36fb..29f01c40 100644
--- a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.h
+++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.h
@@ -25,7 +25,9 @@
 
 class Profile;
 
+namespace lookalikes {
 struct DomainInfo;
+}
 
 // A feature to enable Prewarming the Lookalike check during navigation. URLs in
 // the redirect chain are queried while the request is on the wire instead of
@@ -69,13 +71,14 @@
   // Performs synchronous top domain and engaged site checks on the navigated
   // and redirected urls. Uses |engaged_sites| for the engaged site checks.
   ThrottleCheckResult PerformChecks(
-      const std::vector<DomainInfo>& engaged_sites);
+      const std::vector<lookalikes::DomainInfo>& engaged_sites);
 
   // A void-returning variant, only used with deferred throttle results (e.g.
   // when we need to fetch engaged sites list or digital asset link manifests).
   // |start| is the time at which the navigation was deferred, for metrics.
-  void PerformChecksDeferred(base::TimeTicks start,
-                             const std::vector<DomainInfo>& engaged_sites);
+  void PerformChecksDeferred(
+      base::TimeTicks start,
+      const std::vector<lookalikes::DomainInfo>& engaged_sites);
 
   // Returns whether |url| is a lookalike, setting |match_type| and
   // |suggested_url| appropriately. Used in PerformChecks() on a per-URL basis.
@@ -83,8 +86,8 @@
   // invoked. After invocation, it will hold the duration spent in
   // GetDomainInfo() if GetDomainInfo() was invoked.
   bool IsLookalikeUrl(const GURL& url,
-                      const std::vector<DomainInfo>& engaged_sites,
-                      LookalikeUrlMatchType* match_type,
+                      const std::vector<lookalikes::DomainInfo>& engaged_sites,
+                      lookalikes::LookalikeUrlMatchType* match_type,
                       GURL* suggested_url,
                       base::TimeDelta* get_domain_info_duration);
 
@@ -97,11 +100,12 @@
   // that suggests the user to go to |safe_domain| instead.
   // - Otherwise, it displays the punycode interstitial which doesn't suggest a
   // safe URL.
-  ThrottleCheckResult ShowInterstitial(const GURL& safe_domain,
-                                       const GURL& lookalike_domain,
-                                       ukm::SourceId source_id,
-                                       LookalikeUrlMatchType match_type,
-                                       bool triggered_by_initial_url);
+  ThrottleCheckResult ShowInterstitial(
+      const GURL& safe_domain,
+      const GURL& lookalike_domain,
+      ukm::SourceId source_id,
+      lookalikes::LookalikeUrlMatchType match_type,
+      bool triggered_by_initial_url);
 
   // Checks if a full page intersitial can be shown. This function checks if
   // the navigation isn't a prerender navigation.
@@ -109,7 +113,7 @@
       const GURL& safe_domain,
       const GURL& lookalike_domain,
       ukm::SourceId source_id,
-      LookalikeUrlMatchType match_type,
+      lookalikes::LookalikeUrlMatchType match_type,
       bool triggered_by_initial_url);
 
   // Kicks off a task to prewarm the lookalike checks for URLs in this
@@ -123,13 +127,13 @@
 
   // Used as a callback, calls |PrewarmLookalikeCheckSync()|.
   void PrewarmLookalikeCheckSyncWithSites(
-      const std::vector<DomainInfo>& engaged_sites);
+      const std::vector<lookalikes::DomainInfo>& engaged_sites);
 
   // Caches the lookalike check for |url| in |lookalike_cache_| if it has not
   // already been cached during the navigation.
   void PrewarmLookalikeCheckForURL(
       const GURL& url,
-      const std::vector<DomainInfo>& engaged_sites);
+      const std::vector<lookalikes::DomainInfo>& engaged_sites);
 
   raw_ptr<Profile> profile_;
   bool use_test_profile_ = false;
@@ -137,7 +141,8 @@
   // Cached results from checking if a URL host is a lookalike. Also stores the
   // match type and suggested url. The lifetime of |this| is scoped to a single
   // navigation, which leaves the results of this check relatively fresh.
-  std::map<std::string, std::tuple<bool, LookalikeUrlMatchType, GURL>>
+  std::map<std::string,
+           std::tuple<bool, lookalikes::LookalikeUrlMatchType, GURL>>
       lookalike_cache_;
 
   // The number of lookalike async checks started from |WillRedirect()|. Used
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc
index faec44d..4270c877 100644
--- a/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc
+++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc
@@ -27,7 +27,6 @@
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "components/lookalikes/core/features.h"
 #include "components/lookalikes/core/lookalike_url_util.h"
 #include "components/lookalikes/core/safety_tip_test_utils.h"
 #include "components/lookalikes/core/safety_tips_config.h"
@@ -63,9 +62,14 @@
 
 namespace {
 
+using lookalikes::LookalikeUrlMatchType;
+using lookalikes::NavigationSuggestionEvent;
 using security_interstitials::MetricsHelper;
 using security_interstitials::SecurityInterstitialCommand;
 using UkmEntry = ukm::builders::LookalikeUrl_NavigationSuggestion;
+using lookalikes::GetDomainInfo;
+using lookalikes::kInterstitialHistogramName;
+using lookalikes::LookalikeUrlBlockingPageUserAction;
 
 // An engagement score above MEDIUM.
 const int kHighEngagement = 20;
@@ -340,8 +344,8 @@
     ui_test_utils::HistoryEnumerator enumerator(browser->profile());
     EXPECT_FALSE(base::Contains(enumerator.urls(), navigated_url));
 
-    histograms.ExpectTotalCount(lookalikes::kHistogramName, 1);
-    histograms.ExpectBucketCount(lookalikes::kHistogramName, expected_event, 1);
+    histograms.ExpectTotalCount(kInterstitialHistogramName, 1);
+    histograms.ExpectBucketCount(kInterstitialHistogramName, expected_event, 1);
 
     histograms.ExpectTotalCount(kInterstitialDecisionMetric, 2);
     histograms.ExpectBucketCount(kInterstitialDecisionMetric,
@@ -377,8 +381,8 @@
         GURL(chrome::kChromeUINewTabURL),
         browser->tab_strip_model()->GetActiveWebContents()->GetVisibleURL());
 
-    histograms.ExpectTotalCount(lookalikes::kHistogramName, 1);
-    histograms.ExpectBucketCount(lookalikes::kHistogramName, expected_event, 1);
+    histograms.ExpectTotalCount(kInterstitialHistogramName, 1);
+    histograms.ExpectBucketCount(kInterstitialHistogramName, expected_event, 1);
 
     histograms.ExpectTotalCount(kInterstitialDecisionMetric, 2);
     histograms.ExpectBucketCount(kInterstitialDecisionMetric,
@@ -418,8 +422,8 @@
     ui_test_utils::HistoryEnumerator enumerator(browser->profile());
     EXPECT_TRUE(base::Contains(enumerator.urls(), navigated_url));
 
-    histograms->ExpectTotalCount(lookalikes::kHistogramName, 1);
-    histograms->ExpectBucketCount(lookalikes::kHistogramName, expected_event,
+    histograms->ExpectTotalCount(kInterstitialHistogramName, 1);
+    histograms->ExpectBucketCount(kInterstitialHistogramName, expected_event,
                                   1);
 
     histograms->ExpectTotalCount(kInterstitialDecisionMetric, 2);
@@ -644,8 +648,8 @@
 
   base::HistogramTester histograms;
   TestInterstitialNotShown(browser(), kNavigatedUrl);
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 1);
-  histograms.ExpectBucketCount(lookalikes::kHistogramName,
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 1);
+  histograms.ExpectBucketCount(kInterstitialHistogramName,
                                NavigationSuggestionEvent::kMatchSkeletonTop5k,
                                1);
 
@@ -799,9 +803,9 @@
   test_clock()->Advance(base::Hours(1));
 
   TestInterstitialNotShown(browser(), kNavigatedUrl);
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 1);
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 1);
   histograms.ExpectBucketCount(
-      lookalikes::kHistogramName,
+      kInterstitialHistogramName,
       NavigationSuggestionEvent::kMatchEditDistanceSiteEngagement, 1);
 
   // Navigate away so that safety tip metrics are recorded.
@@ -822,9 +826,9 @@
   SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement);
 
   TestInterstitialNotShown(browser(), kNavigatedUrl);
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 1);
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 1);
   histograms.ExpectBucketCount(
-      lookalikes::kHistogramName,
+      kInterstitialHistogramName,
       NavigationSuggestionEvent::kMatchCharacterSwapTop500, 1);
 
   // Navigate away so that safety tip metrics are recorded.
@@ -848,7 +852,7 @@
   test_clock()->Advance(base::Hours(1));
 
   TestInterstitialNotShown(browser(), kNavigatedUrl);
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 0);
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 0);
   test_helper()->CheckNoLookalikeUkm();
 }
 
@@ -867,8 +871,8 @@
   SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement);
 
   TestInterstitialNotShown(browser(), kNavigatedUrl);
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 1);
-  histograms.ExpectBucketCount(lookalikes::kHistogramName,
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 1);
+  histograms.ExpectBucketCount(kInterstitialHistogramName,
                                NavigationSuggestionEvent::kMatchEditDistance,
                                1);
 
@@ -893,7 +897,7 @@
   SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement);
 
   TestInterstitialNotShown(browser(), kNavigatedUrl);
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 0);
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 0);
   test_helper()->CheckNoLookalikeUkm();
 }
 
@@ -916,7 +920,7 @@
   test_clock()->Advance(base::Hours(1));
 
   TestInterstitialNotShown(browser(), kNavigatedUrl);
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 0);
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 0);
   test_helper()->CheckNoLookalikeUkm();
 }
 
@@ -1117,8 +1121,8 @@
 IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest,
                        AllowedByPolicy) {
   const GURL kNavigatedUrl = GetURL("xn--googl-fsa.com");
-  SetEnterpriseAllowlistForTesting(browser()->profile()->GetPrefs(),
-                                   {"xn--googl-fsa.com"});
+  lookalikes::SetEnterpriseAllowlistForTesting(browser()->profile()->GetPrefs(),
+                                               {"xn--googl-fsa.com"});
   SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement);
   TestInterstitialNotShown(browser(), kNavigatedUrl);
 
@@ -1209,7 +1213,7 @@
     base::HistogramTester histograms;
     test_clock()->Advance(base::Hours(1));
     TestInterstitialNotShown(incognito, kNavigatedUrl);
-    histograms.ExpectTotalCount(lookalikes::kHistogramName, 0);
+    histograms.ExpectTotalCount(kInterstitialHistogramName, 0);
   }
 
   // Now reverse the scores: Set low engagement in the main profile and high
@@ -1235,7 +1239,7 @@
     base::HistogramTester histograms;
     test_clock()->Advance(base::Hours(1));
     TestInterstitialNotShown(browser(), kNavigatedUrl);
-    histograms.ExpectTotalCount(lookalikes::kHistogramName, 0);
+    histograms.ExpectTotalCount(kInterstitialHistogramName, 0);
   }
 
   test_helper()->CheckSafetyTipUkmCount(0);
@@ -1252,7 +1256,7 @@
   SetEngagementScore(browser(), high_engagement_url, kHighEngagement);
   TestInterstitialNotShown(browser(), high_engagement_url);
 
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 0);
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 0);
   test_helper()->CheckNoLookalikeUkm();
 }
 
@@ -1268,7 +1272,7 @@
   SetEngagementScore(browser(), low_engagement_url, kLowEngagement);
   TestInterstitialNotShown(browser(), low_engagement_url);
 
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 0);
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 0);
   test_helper()->CheckNoLookalikeUkm();
 }
 
@@ -1289,7 +1293,7 @@
   SetEngagementScore(browser(), GURL("http://tést"), kHighEngagement);
   TestInterstitialNotShown(browser(), GetURL("tést.com"));
 
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 0);
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 0);
   test_helper()->CheckNoLookalikeUkm();
 }
 
@@ -1543,8 +1547,8 @@
 
   TestInterstitialNotShown(browser(), kNavigatedUrl);
 
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 1);
-  histograms.ExpectBucketCount(lookalikes::kHistogramName,
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 1);
+  histograms.ExpectBucketCount(kInterstitialHistogramName,
                                NavigationSuggestionEvent::kComboSquatting, 1);
 
   CheckInterstitialUkm({kNavigatedUrl}, "MatchType",
@@ -1566,9 +1570,9 @@
 
   TestInterstitialNotShown(browser(), kNavigatedUrl);
 
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 1);
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 1);
   histograms.ExpectBucketCount(
-      lookalikes::kHistogramName,
+      kInterstitialHistogramName,
       NavigationSuggestionEvent::kComboSquattingSiteEngagement, 1);
 
   CheckInterstitialUkm({kNavigatedUrl}, "MatchType",
diff --git a/chrome/browser/lookalikes/lookalike_url_service.cc b/chrome/browser/lookalikes/lookalike_url_service.cc
index 5844842..0b39f86 100644
--- a/chrome/browser/lookalikes/lookalike_url_service.cc
+++ b/chrome/browser/lookalikes/lookalike_url_service.cc
@@ -27,6 +27,8 @@
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/base/url_util.h"
 
+using lookalikes::DomainInfo;
+
 namespace {
 
 constexpr base::TimeDelta kEngagedSiteUpdateInterval = base::Seconds(60);
@@ -88,7 +90,7 @@
             detail.total_score, blink::mojom::EngagementLevel::MEDIUM)) {
       continue;
     }
-    const DomainInfo domain_info = GetDomainInfo(detail.origin);
+    const DomainInfo domain_info = lookalikes::GetDomainInfo(detail.origin);
     if (domain_info.domain_and_registry.empty()) {
       continue;
     }
diff --git a/chrome/browser/lookalikes/lookalike_url_service.h b/chrome/browser/lookalikes/lookalike_url_service.h
index 37e284c..ed5b2e2 100644
--- a/chrome/browser/lookalikes/lookalike_url_service.h
+++ b/chrome/browser/lookalikes/lookalike_url_service.h
@@ -38,7 +38,7 @@
   ~LookalikeUrlService() override;
 
   using EngagedSitesCallback =
-      base::OnceCallback<void(const std::vector<DomainInfo>&)>;
+      base::OnceCallback<void(const std::vector<lookalikes::DomainInfo>&)>;
 
   static LookalikeUrlService* Get(Profile* profile);
 
@@ -52,18 +52,20 @@
 
   // Returns the _current_ list of engaged sites, without updating them if
   // they're out of date.
-  const std::vector<DomainInfo> GetLatestEngagedSites() const;
+  const std::vector<lookalikes::DomainInfo> GetLatestEngagedSites() const;
 
   void SetClockForTesting(base::Clock* clock);
   base::Clock* clock() const { return clock_; }
 
  private:
-  void OnUpdateEngagedSitesCompleted(std::vector<DomainInfo> new_engaged_sites);
+  void OnUpdateEngagedSitesCompleted(
+      std::vector<lookalikes::DomainInfo> new_engaged_sites);
 
   raw_ptr<Profile> profile_;
   raw_ptr<base::Clock> clock_;
   base::Time last_engagement_fetch_time_;
-  std::vector<DomainInfo> engaged_sites_ GUARDED_BY_CONTEXT(sequence_checker_);
+  std::vector<lookalikes::DomainInfo> engaged_sites_
+      GUARDED_BY_CONTEXT(sequence_checker_);
 
   // Indicates that an update to the engaged sites list has been queued. Serves
   // to prevent enqueuing excessive updates.
diff --git a/chrome/browser/lookalikes/safety_tip_service.cc b/chrome/browser/lookalikes/safety_tip_service.cc
index ff561e2..239f213 100644
--- a/chrome/browser/lookalikes/safety_tip_service.cc
+++ b/chrome/browser/lookalikes/safety_tip_service.cc
@@ -28,6 +28,9 @@
 #include "services/metrics/public/cpp/ukm_source_id.h"
 #include "url/url_constants.h"
 
+using lookalikes::DomainInfo;
+using lookalikes::LookalikeUrlMatchType;
+
 namespace {
 
 using security_state::SafetyTipStatus;
@@ -73,7 +76,7 @@
                            const GURL& url,
                            const GURL& victim_url) {
   // Check any policy-set allowlist.
-  if (IsAllowedByEnterprisePolicy(profile->GetPrefs(), url)) {
+  if (lookalikes::IsAllowedByEnterprisePolicy(profile->GetPrefs(), url)) {
     return true;
   }
 
@@ -109,7 +112,7 @@
 
   std::string matched_domain;
   auto* config = lookalikes::GetSafetyTipsRemoteConfigProto();
-  const LookalikeTargetAllowlistChecker in_target_allowlist =
+  const lookalikes::LookalikeTargetAllowlistChecker in_target_allowlist =
       base::BindRepeating(
           &lookalikes::IsTargetHostAllowlistedBySafetyTipsComponent, config);
   if (!GetMatchingDomain(navigated_domain, engaged_sites, in_target_allowlist,
@@ -119,7 +122,7 @@
 
   if (GetActionForMatchType(
           config, chrome::GetChannel(), navigated_domain.domain_and_registry,
-          *match_type) == LookalikeActionType::kShowSafetyTip) {
+          *match_type) == lookalikes::LookalikeActionType::kShowSafetyTip) {
     *safe_url = GetSuggestedURL(*match_type, url, matched_domain);
     return true;
   }
@@ -179,7 +182,7 @@
     const std::vector<DomainInfo>& engaged_sites) {
   base::TimeTicks start = base::TimeTicks::Now();
 
-  const DomainInfo navigated_domain = GetDomainInfo(url);
+  const DomainInfo navigated_domain = lookalikes::GetDomainInfo(url);
 
   UMA_HISTOGRAM_TIMES("Security.SafetyTips.GetDomainInfoTime",
                       base::TimeTicks::Now() - start);
@@ -206,8 +209,8 @@
   // 2. Protect against bad false positives by allowing top domains and safe
   // TLDs. Empty domain_and_registry happens on private domains.
   if (navigated_domain.domain_and_registry.empty() ||
-      IsTopDomain(navigated_domain) ||
-      IsSafeTLD(navigated_domain.domain_and_registry)) {
+      lookalikes::IsTopDomain(navigated_domain) ||
+      lookalikes::IsSafeTLD(navigated_domain.domain_and_registry)) {
     done_checking_safety_tip_status = true;
   }
 
diff --git a/chrome/browser/lookalikes/safety_tip_service.h b/chrome/browser/lookalikes/safety_tip_service.h
index 9b9394eb..c17cb8a 100644
--- a/chrome/browser/lookalikes/safety_tip_service.h
+++ b/chrome/browser/lookalikes/safety_tip_service.h
@@ -19,7 +19,10 @@
 #include "url/origin.h"
 
 class Profile;
+
+namespace lookalikes {
 struct DomainInfo;
+}
 
 // Wrapper used to store the results of a safety tip check. Specifically, this
 // is passed to the callback given to GetSafetyTipStatus.  |url| is the URL
@@ -88,7 +91,7 @@
   void GetSafetyTipStatusWithEngagedSites(
       const GURL& url,
       SafetyTipCheckCallback callback,
-      const std::vector<DomainInfo>& engaged_sites);
+      const std::vector<lookalikes::DomainInfo>& engaged_sites);
 
   // Set of eTLD+1s that we've warned about, and the user has explicitly
   // ignored.  Used to avoid re-warning the user.
diff --git a/chrome/browser/lookalikes/safety_tip_web_contents_observer.cc b/chrome/browser/lookalikes/safety_tip_web_contents_observer.cc
index 432a5c9..49f2a8c 100644
--- a/chrome/browser/lookalikes/safety_tip_web_contents_observer.cc
+++ b/chrome/browser/lookalikes/safety_tip_web_contents_observer.cc
@@ -15,7 +15,6 @@
 #include "chrome/browser/lookalikes/safety_tip_service.h"
 #include "chrome/browser/lookalikes/safety_tip_ui.h"
 #include "chrome/browser/profiles/profile.h"
-#include "components/lookalikes/core/features.h"
 #include "components/lookalikes/core/lookalike_url_util.h"
 #include "components/security_state/core/security_state.h"
 #include "content/public/browser/navigation_entry.h"
@@ -115,8 +114,9 @@
     // This is assumed to mean that the user has clicked on a same-origin link
     // on a lookalike page, resulting in another lookalike navigation.
     suffix = "SameOrigin";
-  } else if (GetETLDPlusOne(committed_initiator_origin.value().host()) ==
-             GetETLDPlusOne(current_url.host())) {
+  } else if (lookalikes::GetETLDPlusOne(
+                 committed_initiator_origin.value().host()) ==
+             lookalikes::GetETLDPlusOne(current_url.host())) {
     // The user has clicked on a link on a page, and it's bumped to another
     // page on the same eTLD+1. If that happens and this is a non-none and
     // non-ignored status, that implies that the first eTLD+1 load didn't
diff --git a/chrome/browser/metrics/metrics_service_browsertest.cc b/chrome/browser/metrics/metrics_service_browsertest.cc
index cb11ddc..93e6f3c 100644
--- a/chrome/browser/metrics/metrics_service_browsertest.cc
+++ b/chrome/browser/metrics/metrics_service_browsertest.cc
@@ -164,10 +164,13 @@
       "Stability.Counts2", metrics::StabilityEventType::kRendererCrash, 0);
 }
 
-// Flaky on Linux. See http://crbug.com/131094
 // Child crashes fail the process on ASan (see crbug.com/411251,
 // crbug.com/368525).
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || defined(ADDRESS_SANITIZER)
+// Note to sheriffs: Do not disable these tests if they starts to flake. If
+// either of these tests start to fail then changes likely need to be made
+// elsewhere in crash processing, metrics analysis, and dashboards. Please
+// consult Stability Team before disabling.
+#if defined(ADDRESS_SANITIZER)
 #define MAYBE_CrashRenderers DISABLED_CrashRenderers
 #define MAYBE_CheckCrashRenderers DISABLED_CheckCrashRenderers
 #else
@@ -245,7 +248,7 @@
       "CrashExitCodes.Renderer",
       std::abs(static_cast<int32_t>(STATUS_BREAKPOINT)), 1);
 #elif BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-  VerifyRendererExitCodeIsSignal(histogram_tester, SIGTRAP);
+  VerifyRendererExitCodeIsSignal(histogram_tester, SIGSEGV);
 #endif
 }
 
diff --git a/chrome/browser/nearby_sharing/fake_nearby_connections_manager.cc b/chrome/browser/nearby_sharing/fake_nearby_connections_manager.cc
index 664e2c2..541e63f2 100644
--- a/chrome/browser/nearby_sharing/fake_nearby_connections_manager.cc
+++ b/chrome/browser/nearby_sharing/fake_nearby_connections_manager.cc
@@ -123,7 +123,7 @@
   auto it = payload_path_status_.find(payload_id);
   if (it == payload_path_status_.end()) {
     std::move(callback).Run(
-        location::nearby::connections::mojom::Status::kPayloadUnknown);
+        nearby::connections::mojom::Status::kPayloadUnknown);
     return;
   }
 
@@ -146,9 +146,8 @@
       GetRegisteredPayloadStatusListener(payload_id);
   if (listener) {
     listener->OnStatusUpdate(
-        location::nearby::connections::mojom::PayloadTransferUpdate::New(
-            payload_id,
-            location::nearby::connections::mojom::PayloadStatus::kCanceled,
+        nearby::connections::mojom::PayloadTransferUpdate::New(
+            payload_id, nearby::connections::mojom::PayloadStatus::kCanceled,
             /*total_bytes=*/0,
             /*bytes_transferred=*/0),
         /*upgraded_medium=*/absl::nullopt);
@@ -195,7 +194,7 @@
 
 void FakeNearbyConnectionsManager::OnEndpointFound(
     const std::string& endpoint_id,
-    location::nearby::connections::mojom::DiscoveredEndpointInfoPtr info) {
+    nearby::connections::mojom::DiscoveredEndpointInfoPtr info) {
   if (!discovery_listener_)
     return;
 
diff --git a/chrome/browser/nearby_sharing/fake_nearby_connections_manager.h b/chrome/browser/nearby_sharing/fake_nearby_connections_manager.h
index 2cb2f0e9..d6284f9 100644
--- a/chrome/browser/nearby_sharing/fake_nearby_connections_manager.h
+++ b/chrome/browser/nearby_sharing/fake_nearby_connections_manager.h
@@ -22,7 +22,7 @@
 // Fake NearbyConnectionsManager for testing.
 class FakeNearbyConnectionsManager
     : public NearbyConnectionsManager,
-      public location::nearby::connections::mojom::EndpointDiscoveryListener {
+      public nearby::connections::mojom::EndpointDiscoveryListener {
  public:
   FakeNearbyConnectionsManager();
   ~FakeNearbyConnectionsManager() override;
@@ -68,8 +68,7 @@
   // mojom::EndpointDiscoveryListener:
   void OnEndpointFound(
       const std::string& endpoint_id,
-      location::nearby::connections::mojom::DiscoveredEndpointInfoPtr info)
-      override;
+      nearby::connections::mojom::DiscoveredEndpointInfoPtr info) override;
   void OnEndpointLost(const std::string& endpoint_id) override;
 
   // Testing methods
diff --git a/chrome/browser/nearby_sharing/nearby_connection_impl.h b/chrome/browser/nearby_sharing/nearby_connection_impl.h
index 761a39c..ff722c50 100644
--- a/chrome/browser/nearby_sharing/nearby_connection_impl.h
+++ b/chrome/browser/nearby_sharing/nearby_connection_impl.h
@@ -31,8 +31,8 @@
   void WriteMessage(std::vector<uint8_t> bytes);
 
  private:
-  using PayloadContent = location::nearby::connections::mojom::PayloadContent;
-  using BytesPayload = location::nearby::connections::mojom::BytesPayload;
+  using PayloadContent = nearby::connections::mojom::PayloadContent;
+  using BytesPayload = nearby::connections::mojom::BytesPayload;
 
   SEQUENCE_CHECKER(sequence_checker_);
 
diff --git a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc b/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc
index 155e87e..a21da262 100644
--- a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc
+++ b/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc
@@ -23,8 +23,8 @@
 
 const char kFastAdvertisementServiceUuid[] =
     "0000fef3-0000-1000-8000-00805f9b34fb";
-const location::nearby::connections::mojom::Strategy kStrategy =
-    location::nearby::connections::mojom::Strategy::kP2pPointToPoint;
+const nearby::connections::mojom::Strategy kStrategy =
+    nearby::connections::mojom::Strategy::kP2pPointToPoint;
 
 bool ShouldUseInternet(DataUsage data_usage, PowerLevel power_level) {
   // We won't use internet if the user requested we don't.
@@ -82,7 +82,7 @@
 }
 
 std::string MediumSelectionToString(
-    const location::nearby::connections::mojom::MediumSelection& mediums) {
+    const nearby::connections::mojom::MediumSelection& mediums) {
   std::stringstream ss;
   ss << "{";
   if (mediums.bluetooth)
@@ -124,7 +124,7 @@
   DCHECK(listener);
   DCHECK(!incoming_connection_listener_);
 
-  location::nearby::connections::mojom::NearbyConnections* nearby_connections =
+  nearby::connections::mojom::NearbyConnections* nearby_connections =
       GetNearbyConnections();
   if (!nearby_connections) {
     std::move(callback).Run(ConnectionsStatus::kError);
@@ -194,7 +194,7 @@
   DCHECK(listener);
   DCHECK(!discovery_listener_);
 
-  location::nearby::connections::mojom::NearbyConnections* nearby_connections =
+  nearby::connections::mojom::NearbyConnections* nearby_connections =
       GetNearbyConnections();
   if (!nearby_connections) {
     std::move(callback).Run(ConnectionsStatus::kError);
@@ -722,7 +722,7 @@
       payload_it->second->content->get_bytes()->bytes);
 }
 
-location::nearby::connections::mojom::NearbyConnections*
+nearby::connections::mojom::NearbyConnections*
 NearbyConnectionsManagerImpl::GetNearbyConnections() {
   if (!process_reference_) {
     process_reference_ = process_manager_->GetNearbyProcessReference(
@@ -736,7 +736,7 @@
     }
   }
 
-  location::nearby::connections::mojom::NearbyConnections* nearby_connections =
+  nearby::connections::mojom::NearbyConnections* nearby_connections =
       process_reference_->GetNearbyConnections().get();
 
   if (!nearby_connections)
@@ -776,7 +776,7 @@
   pending_outgoing_connections_.clear();
 }
 
-absl::optional<location::nearby::connections::mojom::Medium>
+absl::optional<nearby::connections::mojom::Medium>
 NearbyConnectionsManagerImpl::GetUpgradedMedium(
     const std::string& endpoint_id) const {
   const auto it = current_upgraded_mediums_.find(endpoint_id);
diff --git a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.h b/chrome/browser/nearby_sharing/nearby_connections_manager_impl.h
index c2a7e8a..d5cbb7a 100644
--- a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.h
+++ b/chrome/browser/nearby_sharing/nearby_connections_manager_impl.h
@@ -25,9 +25,9 @@
 // Concrete NearbyConnectionsManager implementation.
 class NearbyConnectionsManagerImpl
     : public NearbyConnectionsManager,
-      public location::nearby::connections::mojom::EndpointDiscoveryListener,
-      public location::nearby::connections::mojom::ConnectionLifecycleListener,
-      public location::nearby::connections::mojom::PayloadListener {
+      public nearby::connections::mojom::EndpointDiscoveryListener,
+      public nearby::connections::mojom::ConnectionLifecycleListener,
+      public nearby::connections::mojom::PayloadListener {
  public:
   NearbyConnectionsManagerImpl(
       ash::nearby::NearbyProcessManager* process_manager,
@@ -73,29 +73,25 @@
   base::WeakPtr<NearbyConnectionsManager> GetWeakPtr() override;
 
  private:
-  using AdvertisingOptions =
-      location::nearby::connections::mojom::AdvertisingOptions;
-  using ConnectionInfoPtr =
-      location::nearby::connections::mojom::ConnectionInfoPtr;
-  using ConnectionOptions =
-      location::nearby::connections::mojom::ConnectionOptions;
+  using AdvertisingOptions = nearby::connections::mojom::AdvertisingOptions;
+  using ConnectionInfoPtr = nearby::connections::mojom::ConnectionInfoPtr;
+  using ConnectionOptions = nearby::connections::mojom::ConnectionOptions;
   using ConnectionLifecycleListener =
-      location::nearby::connections::mojom::ConnectionLifecycleListener;
+      nearby::connections::mojom::ConnectionLifecycleListener;
   using DiscoveredEndpointInfoPtr =
-      location::nearby::connections::mojom::DiscoveredEndpointInfoPtr;
-  using DiscoveryOptions =
-      location::nearby::connections::mojom::DiscoveryOptions;
+      nearby::connections::mojom::DiscoveredEndpointInfoPtr;
+  using DiscoveryOptions = nearby::connections::mojom::DiscoveryOptions;
   using EndpointDiscoveryListener =
-      location::nearby::connections::mojom::EndpointDiscoveryListener;
-  using MediumSelection = location::nearby::connections::mojom::MediumSelection;
-  using PayloadListener = location::nearby::connections::mojom::PayloadListener;
+      nearby::connections::mojom::EndpointDiscoveryListener;
+  using MediumSelection = nearby::connections::mojom::MediumSelection;
+  using PayloadListener = nearby::connections::mojom::PayloadListener;
   using PayloadTransferUpdate =
-      location::nearby::connections::mojom::PayloadTransferUpdate;
-  using PayloadStatus = location::nearby::connections::mojom::PayloadStatus;
+      nearby::connections::mojom::PayloadTransferUpdate;
+  using PayloadStatus = nearby::connections::mojom::PayloadStatus;
   using PayloadTransferUpdatePtr =
-      location::nearby::connections::mojom::PayloadTransferUpdatePtr;
-  using Status = location::nearby::connections::mojom::Status;
-  using Medium = location::nearby::connections::mojom::Medium;
+      nearby::connections::mojom::PayloadTransferUpdatePtr;
+  using Status = nearby::connections::mojom::Status;
+  using Medium = nearby::connections::mojom::Medium;
 
   FRIEND_TEST_ALL_PREFIXES(NearbyConnectionsManagerImplTest,
                            DiscoveryProcessStopped);
@@ -127,8 +123,7 @@
   void OnNearbyProcessStopped(
       ash::nearby::NearbyProcessManager::NearbyProcessShutdownReason
           shutdown_reason);
-  location::nearby::connections::mojom::NearbyConnections*
-  GetNearbyConnections();
+  nearby::connections::mojom::NearbyConnections* GetNearbyConnections();
   void Reset();
 
   void OnFileCreated(int64_t payload_id,
diff --git a/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc
index ddac898..266676f 100644
--- a/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc
+++ b/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc
@@ -29,8 +29,8 @@
 namespace {
 
 const char kServiceId[] = "NearbySharing";
-const location::nearby::connections::mojom::Strategy kStrategy =
-    location::nearby::connections::mojom::Strategy::kP2pPointToPoint;
+const nearby::connections::mojom::Strategy kStrategy =
+    nearby::connections::mojom::Strategy::kP2pPointToPoint;
 const char kEndpointId[] = "endpoint_id";
 const char kRemoteEndpointId[] = "remote_endpoint_id";
 const char kEndpointInfo[] = {0x0d, 0x07, 0x07, 0x07, 0x07};
@@ -81,19 +81,18 @@
 
 }  // namespace
 
-using Status = location::nearby::connections::mojom::Status;
+using Status = nearby::connections::mojom::Status;
 using DiscoveredEndpointInfo =
-    location::nearby::connections::mojom::DiscoveredEndpointInfo;
-using ConnectionInfo = location::nearby::connections::mojom::ConnectionInfo;
-using Medium = location::nearby::connections::mojom::Medium;
-using MediumSelection = location::nearby::connections::mojom::MediumSelection;
-using PayloadContent = location::nearby::connections::mojom::PayloadContent;
-using PayloadStatus = location::nearby::connections::mojom::PayloadStatus;
-using PayloadTransferUpdate =
-    location::nearby::connections::mojom::PayloadTransferUpdate;
-using Payload = location::nearby::connections::mojom::Payload;
-using BytesPayload = location::nearby::connections::mojom::BytesPayload;
-using FilePayload = location::nearby::connections::mojom::FilePayload;
+    nearby::connections::mojom::DiscoveredEndpointInfo;
+using ConnectionInfo = nearby::connections::mojom::ConnectionInfo;
+using Medium = nearby::connections::mojom::Medium;
+using MediumSelection = nearby::connections::mojom::MediumSelection;
+using PayloadContent = nearby::connections::mojom::PayloadContent;
+using PayloadStatus = nearby::connections::mojom::PayloadStatus;
+using PayloadTransferUpdate = nearby::connections::mojom::PayloadTransferUpdate;
+using Payload = nearby::connections::mojom::Payload;
+using BytesPayload = nearby::connections::mojom::BytesPayload;
+using FilePayload = nearby::connections::mojom::FilePayload;
 
 class MockDiscoveryListener
     : public NearbyConnectionsManager::DiscoveryListener {
diff --git a/chrome/browser/nearby_sharing/nearby_file_handler.h b/chrome/browser/nearby_sharing/nearby_file_handler.h
index ecfe93d..31131d9 100644
--- a/chrome/browser/nearby_sharing/nearby_file_handler.h
+++ b/chrome/browser/nearby_sharing/nearby_file_handler.h
@@ -27,7 +27,7 @@
     base::File input_file;
     base::File output_file;
   };
-  using PayloadPtr = location::nearby::connections::mojom::PayloadPtr;
+  using PayloadPtr = nearby::connections::mojom::PayloadPtr;
   using OpenFilesCallback = base::OnceCallback<void(std::vector<FileInfo>)>;
   using CreateFileCallback = base::OnceCallback<void(CreateFileResult)>;
   using GetUniquePathCallback = base::OnceCallback<void(base::FilePath)>;
diff --git a/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc b/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc
index 87680289..897825a 100644
--- a/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc
+++ b/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc
@@ -213,48 +213,46 @@
 
 StartAdvertisingFailureReason
 NearbyConnectionsStatusToStartAdvertisingFailureReason(
-    location::nearby::connections::mojom::Status status) {
+    nearby::connections::mojom::Status status) {
   switch (status) {
-    case location::nearby::connections::mojom::Status::kError:
+    case nearby::connections::mojom::Status::kError:
       return StartAdvertisingFailureReason::kError;
-    case location::nearby::connections::mojom::Status::kOutOfOrderApiCall:
+    case nearby::connections::mojom::Status::kOutOfOrderApiCall:
       return StartAdvertisingFailureReason::kOutOfOrderApiCall;
-    case location::nearby::connections::mojom::Status::
-        kAlreadyHaveActiveStrategy:
+    case nearby::connections::mojom::Status::kAlreadyHaveActiveStrategy:
       return StartAdvertisingFailureReason::kAlreadyHaveActiveStrategy;
-    case location::nearby::connections::mojom::Status::kAlreadyAdvertising:
+    case nearby::connections::mojom::Status::kAlreadyAdvertising:
       return StartAdvertisingFailureReason::kAlreadyAdvertising;
-    case location::nearby::connections::mojom::Status::kBluetoothError:
+    case nearby::connections::mojom::Status::kBluetoothError:
       return StartAdvertisingFailureReason::kBluetoothError;
-    case location::nearby::connections::mojom::Status::kBleError:
+    case nearby::connections::mojom::Status::kBleError:
       return StartAdvertisingFailureReason::kBleError;
-    case location::nearby::connections::mojom::Status::kWifiLanError:
+    case nearby::connections::mojom::Status::kWifiLanError:
       return StartAdvertisingFailureReason::kWifiLanError;
-    case location::nearby::connections::mojom::Status::kSuccess:
+    case nearby::connections::mojom::Status::kSuccess:
       NOTREACHED();
       [[fallthrough]];
-    case location::nearby::connections::mojom::Status::kAlreadyDiscovering:
-    case location::nearby::connections::mojom::Status::kEndpointIOError:
-    case location::nearby::connections::mojom::Status::kEndpointUnknown:
-    case location::nearby::connections::mojom::Status::kConnectionRejected:
-    case location::nearby::connections::mojom::Status::
-        kAlreadyConnectedToEndpoint:
-    case location::nearby::connections::mojom::Status::kNotConnectedToEndpoint:
-    case location::nearby::connections::mojom::Status::kPayloadUnknown:
+    case nearby::connections::mojom::Status::kAlreadyDiscovering:
+    case nearby::connections::mojom::Status::kEndpointIOError:
+    case nearby::connections::mojom::Status::kEndpointUnknown:
+    case nearby::connections::mojom::Status::kConnectionRejected:
+    case nearby::connections::mojom::Status::kAlreadyConnectedToEndpoint:
+    case nearby::connections::mojom::Status::kNotConnectedToEndpoint:
+    case nearby::connections::mojom::Status::kPayloadUnknown:
       return StartAdvertisingFailureReason::kUnknown;
   }
 }
 
 FinalStatus PayloadStatusToFinalStatus(
-    location::nearby::connections::mojom::PayloadStatus status) {
+    nearby::connections::mojom::PayloadStatus status) {
   switch (status) {
-    case location::nearby::connections::mojom::PayloadStatus::kSuccess:
+    case nearby::connections::mojom::PayloadStatus::kSuccess:
       return FinalStatus::kSuccess;
-    case location::nearby::connections::mojom::PayloadStatus::kFailure:
+    case nearby::connections::mojom::PayloadStatus::kFailure:
       return FinalStatus::kFailure;
-    case location::nearby::connections::mojom::PayloadStatus::kCanceled:
+    case nearby::connections::mojom::PayloadStatus::kCanceled:
       return FinalStatus::kCanceled;
-    case location::nearby::connections::mojom::PayloadStatus::kInProgress:
+    case nearby::connections::mojom::PayloadStatus::kInProgress:
       NOTREACHED();
       return FinalStatus::kFailure;
   }
@@ -283,77 +281,75 @@
 }
 
 std::string GetPayloadStatusSubcategoryName(
-    location::nearby::connections::mojom::PayloadStatus status) {
+    nearby::connections::mojom::PayloadStatus status) {
   switch (status) {
-    case location::nearby::connections::mojom::PayloadStatus::kSuccess:
+    case nearby::connections::mojom::PayloadStatus::kSuccess:
       return ".Succeeded";
-    case location::nearby::connections::mojom::PayloadStatus::kFailure:
+    case nearby::connections::mojom::PayloadStatus::kFailure:
       return ".Failed";
-    case location::nearby::connections::mojom::PayloadStatus::kCanceled:
+    case nearby::connections::mojom::PayloadStatus::kCanceled:
       return ".Cancelled";
-    case location::nearby::connections::mojom::PayloadStatus::kInProgress:
+    case nearby::connections::mojom::PayloadStatus::kInProgress:
       NOTREACHED();
       return ".Failed";
   }
 }
 
 std::string GetUpgradedMediumSubcategoryName(
-    absl::optional<location::nearby::connections::mojom::Medium>
-        last_upgraded_medium) {
+    absl::optional<nearby::connections::mojom::Medium> last_upgraded_medium) {
   if (!last_upgraded_medium) {
     return ".NoMediumUpgrade";
   }
 
   switch (*last_upgraded_medium) {
-    case location::nearby::connections::mojom::Medium::kWebRtc:
+    case nearby::connections::mojom::Medium::kWebRtc:
       return ".WebRtcUpgrade";
-    case location::nearby::connections::mojom::Medium::kWifiLan:
+    case nearby::connections::mojom::Medium::kWifiLan:
       return ".WifiLanUpgrade";
-    case location::nearby::connections::mojom::Medium::kUnknown:
-    case location::nearby::connections::mojom::Medium::kMdns:
-    case location::nearby::connections::mojom::Medium::kBluetooth:
-    case location::nearby::connections::mojom::Medium::kWifiHotspot:
-    case location::nearby::connections::mojom::Medium::kBle:
-    case location::nearby::connections::mojom::Medium::kWifiAware:
-    case location::nearby::connections::mojom::Medium::kNfc:
-    case location::nearby::connections::mojom::Medium::kWifiDirect:
-    case location::nearby::connections::mojom::Medium::kBleL2Cap:
-    case location::nearby::connections::mojom::Medium::kUsb:
+    case nearby::connections::mojom::Medium::kUnknown:
+    case nearby::connections::mojom::Medium::kMdns:
+    case nearby::connections::mojom::Medium::kBluetooth:
+    case nearby::connections::mojom::Medium::kWifiHotspot:
+    case nearby::connections::mojom::Medium::kBle:
+    case nearby::connections::mojom::Medium::kWifiAware:
+    case nearby::connections::mojom::Medium::kNfc:
+    case nearby::connections::mojom::Medium::kWifiDirect:
+    case nearby::connections::mojom::Medium::kBleL2Cap:
+    case nearby::connections::mojom::Medium::kUsb:
       return ".UnknownMediumUpgrade";
   }
 }
 
 UpgradedMedium GetUpgradedMediumForMetrics(
-    absl::optional<location::nearby::connections::mojom::Medium>
-        last_upgraded_medium) {
+    absl::optional<nearby::connections::mojom::Medium> last_upgraded_medium) {
   if (!last_upgraded_medium) {
     return UpgradedMedium::kNoUpgrade;
   }
 
   switch (*last_upgraded_medium) {
-    case location::nearby::connections::mojom::Medium::kUnknown:
+    case nearby::connections::mojom::Medium::kUnknown:
       return UpgradedMedium::kUnknown;
-    case location::nearby::connections::mojom::Medium::kMdns:
+    case nearby::connections::mojom::Medium::kMdns:
       return UpgradedMedium::kMdns;
-    case location::nearby::connections::mojom::Medium::kBluetooth:
+    case nearby::connections::mojom::Medium::kBluetooth:
       return UpgradedMedium::kBluetooth;
-    case location::nearby::connections::mojom::Medium::kWifiHotspot:
+    case nearby::connections::mojom::Medium::kWifiHotspot:
       return UpgradedMedium::kWifiHotspot;
-    case location::nearby::connections::mojom::Medium::kBle:
+    case nearby::connections::mojom::Medium::kBle:
       return UpgradedMedium::kBle;
-    case location::nearby::connections::mojom::Medium::kWifiLan:
+    case nearby::connections::mojom::Medium::kWifiLan:
       return UpgradedMedium::kWifiLan;
-    case location::nearby::connections::mojom::Medium::kWifiAware:
+    case nearby::connections::mojom::Medium::kWifiAware:
       return UpgradedMedium::kWifiAware;
-    case location::nearby::connections::mojom::Medium::kNfc:
+    case nearby::connections::mojom::Medium::kNfc:
       return UpgradedMedium::kNfc;
-    case location::nearby::connections::mojom::Medium::kWifiDirect:
+    case nearby::connections::mojom::Medium::kWifiDirect:
       return UpgradedMedium::kWifiDirect;
-    case location::nearby::connections::mojom::Medium::kWebRtc:
+    case nearby::connections::mojom::Medium::kWebRtc:
       return UpgradedMedium::kWebRtc;
-    case location::nearby::connections::mojom::Medium::kBleL2Cap:
+    case nearby::connections::mojom::Medium::kBleL2Cap:
       return UpgradedMedium::kBleL2Cap;
-    case location::nearby::connections::mojom::Medium::kUsb:
+    case nearby::connections::mojom::Medium::kUsb:
       return UpgradedMedium::kUsb;
   }
 }
@@ -361,7 +357,7 @@
 void RecordNearbySharePayloadAttachmentTypeMetric(
     AttachmentType type,
     bool is_incoming,
-    location::nearby::connections::mojom::PayloadStatus status) {
+    nearby::connections::mojom::PayloadStatus status) {
   const std::string prefix = "Nearby.Share.Payload.AttachmentType";
   base::UmaHistogramEnumeration(prefix, type);
   base::UmaHistogramEnumeration(
@@ -436,7 +432,7 @@
 void RecordNearbySharePayloadFileAttachmentTypeMetric(
     sharing::mojom::FileMetadata::Type type,
     bool is_incoming,
-    location::nearby::connections::mojom::PayloadStatus status) {
+    nearby::connections::mojom::PayloadStatus status) {
   RecordNearbySharePayloadAttachmentTypeMetric(
       FileMetadataTypeToAttachmentType(type), is_incoming, status);
 }
@@ -444,14 +440,14 @@
 void RecordNearbySharePayloadTextAttachmentTypeMetric(
     sharing::mojom::TextMetadata::Type type,
     bool is_incoming,
-    location::nearby::connections::mojom::PayloadStatus status) {
+    nearby::connections::mojom::PayloadStatus status) {
   RecordNearbySharePayloadAttachmentTypeMetric(
       TextMetadataTypeToAttachmentType(type), is_incoming, status);
 }
 
 void RecordNearbySharePayloadWifiCredentialsAttachmentTypeMetric(
     bool is_incoming,
-    location::nearby::connections::mojom::PayloadStatus status) {
+    nearby::connections::mojom::PayloadStatus status) {
   RecordNearbySharePayloadAttachmentTypeMetric(AttachmentType::kWifiCredentials,
                                                is_incoming, status);
 }
@@ -491,10 +487,9 @@
 }
 
 void RecordNearbySharePayloadFinalStatusMetric(
-    location::nearby::connections::mojom::PayloadStatus status,
-    absl::optional<location::nearby::connections::mojom::Medium> medium) {
-  DCHECK_NE(status,
-            location::nearby::connections::mojom::PayloadStatus::kInProgress);
+    nearby::connections::mojom::PayloadStatus status,
+    absl::optional<nearby::connections::mojom::Medium> medium) {
+  DCHECK_NE(status, nearby::connections::mojom::PayloadStatus::kInProgress);
   base::UmaHistogramEnumeration("Nearby.Share.Payload.FinalStatus",
                                 PayloadStatusToFinalStatus(status));
   base::UmaHistogramEnumeration("Nearby.Share.Payload.FinalStatus" +
@@ -503,7 +498,7 @@
 }
 
 void RecordNearbySharePayloadMediumMetric(
-    absl::optional<location::nearby::connections::mojom::Medium> medium,
+    absl::optional<nearby::connections::mojom::Medium> medium,
     nearby_share::mojom::ShareTargetType type,
     uint64_t num_bytes_transferred) {
   base::UmaHistogramEnumeration("Nearby.Share.Payload.Medium",
@@ -538,12 +533,10 @@
 void RecordNearbySharePayloadSizeMetric(
     bool is_incoming,
     nearby_share::mojom::ShareTargetType type,
-    absl::optional<location::nearby::connections::mojom::Medium>
-        last_upgraded_medium,
-    location::nearby::connections::mojom::PayloadStatus status,
+    absl::optional<nearby::connections::mojom::Medium> last_upgraded_medium,
+    nearby::connections::mojom::PayloadStatus status,
     uint64_t payload_size_bytes) {
-  DCHECK_NE(status,
-            location::nearby::connections::mojom::PayloadStatus::kInProgress);
+  DCHECK_NE(status, nearby::connections::mojom::PayloadStatus::kInProgress);
 
   int kilobytes =
       base::saturated_cast<int>(payload_size_bytes / kBytesPerKilobyte);
@@ -564,13 +557,11 @@
 void RecordNearbySharePayloadTransferRateMetric(
     bool is_incoming,
     nearby_share::mojom::ShareTargetType type,
-    absl::optional<location::nearby::connections::mojom::Medium>
-        last_upgraded_medium,
-    location::nearby::connections::mojom::PayloadStatus status,
+    absl::optional<nearby::connections::mojom::Medium> last_upgraded_medium,
+    nearby::connections::mojom::PayloadStatus status,
     uint64_t transferred_payload_bytes,
     base::TimeDelta time_elapsed) {
-  DCHECK_NE(status,
-            location::nearby::connections::mojom::PayloadStatus::kInProgress);
+  DCHECK_NE(status, nearby::connections::mojom::PayloadStatus::kInProgress);
 
   int kilobytes_per_second = base::saturated_cast<int>(base::ClampDiv(
       base::ClampDiv(transferred_payload_bytes, time_elapsed.InSecondsF()),
@@ -591,11 +582,10 @@
 
 void RecordNearbyShareStartAdvertisingResultMetric(
     bool is_high_visibility,
-    location::nearby::connections::mojom::Status status) {
+    nearby::connections::mojom::Status status) {
   const std::string mode_suffix =
       is_high_visibility ? ".HighVisibility" : ".BLE";
-  const bool success =
-      status == location::nearby::connections::mojom::Status::kSuccess;
+  const bool success = status == nearby::connections::mojom::Status::kSuccess;
 
   const std::string result_prefix = "Nearby.Share.StartAdvertising.Result";
   base::UmaHistogramBoolean(result_prefix, success);
diff --git a/chrome/browser/nearby_sharing/nearby_share_metrics_logger.h b/chrome/browser/nearby_sharing/nearby_share_metrics_logger.h
index d0a2657..a33c4d7 100644
--- a/chrome/browser/nearby_sharing/nearby_share_metrics_logger.h
+++ b/chrome/browser/nearby_sharing/nearby_share_metrics_logger.h
@@ -62,16 +62,16 @@
 void RecordNearbySharePayloadFileAttachmentTypeMetric(
     sharing::mojom::FileMetadata::Type type,
     bool is_incoming,
-    location::nearby::connections::mojom::PayloadStatus status);
+    nearby::connections::mojom::PayloadStatus status);
 
 void RecordNearbySharePayloadTextAttachmentTypeMetric(
     sharing::mojom::TextMetadata::Type type,
     bool is_incoming,
-    location::nearby::connections::mojom::PayloadStatus status);
+    nearby::connections::mojom::PayloadStatus status);
 
 void RecordNearbySharePayloadWifiCredentialsAttachmentTypeMetric(
     bool is_incoming,
-    location::nearby::connections::mojom::PayloadStatus status);
+    nearby::connections::mojom::PayloadStatus status);
 
 void RecordNearbySharePayloadFileOperationMetrics(
     Profile* profile,
@@ -80,11 +80,11 @@
     const bool success);
 
 void RecordNearbySharePayloadFinalStatusMetric(
-    location::nearby::connections::mojom::PayloadStatus status,
-    absl::optional<location::nearby::connections::mojom::Medium> medium);
+    nearby::connections::mojom::PayloadStatus status,
+    absl::optional<nearby::connections::mojom::Medium> medium);
 
 void RecordNearbySharePayloadMediumMetric(
-    absl::optional<location::nearby::connections::mojom::Medium> medium,
+    absl::optional<nearby::connections::mojom::Medium> medium,
     nearby_share::mojom::ShareTargetType type,
     uint64_t num_bytes_transferred);
 
@@ -96,23 +96,21 @@
 void RecordNearbySharePayloadSizeMetric(
     bool is_incoming,
     nearby_share::mojom::ShareTargetType type,
-    absl::optional<location::nearby::connections::mojom::Medium>
-        last_upgraded_medium,
-    location::nearby::connections::mojom::PayloadStatus status,
+    absl::optional<nearby::connections::mojom::Medium> last_upgraded_medium,
+    nearby::connections::mojom::PayloadStatus status,
     uint64_t payload_size_bytes);
 
 void RecordNearbySharePayloadTransferRateMetric(
     bool is_incoming,
     nearby_share::mojom::ShareTargetType type,
-    absl::optional<location::nearby::connections::mojom::Medium>
-        last_upgraded_medium,
-    location::nearby::connections::mojom::PayloadStatus status,
+    absl::optional<nearby::connections::mojom::Medium> last_upgraded_medium,
+    nearby::connections::mojom::PayloadStatus status,
     uint64_t transferred_payload_bytes,
     base::TimeDelta time_elapsed);
 
 void RecordNearbyShareStartAdvertisingResultMetric(
     bool is_high_visibility,
-    location::nearby::connections::mojom::Status status);
+    nearby::connections::mojom::Status status);
 
 void RecordNearbyShareTransferFinalStatusMetric(
     NearbyShareFeatureUsageMetrics* feature_usage_metrics,
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
index 4412d80..c9867d0 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
@@ -2499,8 +2499,7 @@
 void NearbySharingServiceImpl::OnUniquePathFetched(
     int64_t attachment_id,
     int64_t payload_id,
-    base::OnceCallback<void(location::nearby::connections::mojom::Status)>
-        callback,
+    base::OnceCallback<void(nearby::connections::mojom::Status)> callback,
     base::FilePath path) {
   attachment_info_map_[attachment_id].file_path = path;
   nearby_connections_manager_->RegisterPayloadPath(payload_id, path,
@@ -2510,8 +2509,8 @@
 void NearbySharingServiceImpl::OnPayloadPathRegistered(
     base::ScopedClosureRunner closure_runner,
     bool* aggregated_success,
-    location::nearby::connections::mojom::Status status) {
-  if (status != location::nearby::connections::mojom::Status::kSuccess)
+    ::nearby::connections::mojom::Status status) {
+  if (status != ::nearby::connections::mojom::Status::kSuccess)
     *aggregated_success = false;
 }
 
@@ -2840,7 +2839,7 @@
     return;
   }
 
-  std::vector<location::nearby::connections::mojom::PayloadPtr> payloads;
+  std::vector<nearby::connections::mojom::PayloadPtr> payloads;
   payloads.reserve(files.size());
 
   for (size_t i = 0; i < files.size(); ++i) {
@@ -2849,21 +2848,20 @@
     base::File& file = files[i].file;
     int64_t payload_id = GeneratePayloadId();
     SetAttachmentPayloadId(attachment, payload_id);
-    payloads.push_back(location::nearby::connections::mojom::Payload::New(
+    payloads.push_back(nearby::connections::mojom::Payload::New(
         payload_id,
-        location::nearby::connections::mojom::PayloadContent::NewFile(
-            location::nearby::connections::mojom::FilePayload::New(
-                std::move(file)))));
+        nearby::connections::mojom::PayloadContent::NewFile(
+            nearby::connections::mojom::FilePayload::New(std::move(file)))));
   }
 
   info->set_file_payloads(std::move(payloads));
   std::move(callback).Run(std::move(share_target), /*success=*/true);
 }
 
-std::vector<location::nearby::connections::mojom::PayloadPtr>
+std::vector<nearby::connections::mojom::PayloadPtr>
 NearbySharingServiceImpl::CreateTextPayloads(
     const std::vector<TextAttachment>& attachments) {
-  std::vector<location::nearby::connections::mojom::PayloadPtr> payloads;
+  std::vector<nearby::connections::mojom::PayloadPtr> payloads;
   payloads.reserve(attachments.size());
   for (const TextAttachment& attachment : attachments) {
     const std::string& body = attachment.text_body();
@@ -2871,11 +2869,10 @@
 
     int64_t payload_id = GeneratePayloadId();
     SetAttachmentPayloadId(attachment, payload_id);
-    payloads.push_back(location::nearby::connections::mojom::Payload::New(
+    payloads.push_back(nearby::connections::mojom::Payload::New(
         payload_id,
-        location::nearby::connections::mojom::PayloadContent::NewBytes(
-            location::nearby::connections::mojom::BytesPayload::New(
-                std::move(bytes)))));
+        nearby::connections::mojom::PayloadContent::NewBytes(
+            nearby::connections::mojom::BytesPayload::New(std::move(bytes)))));
   }
   return payloads;
 }
@@ -3906,7 +3903,7 @@
       return false;
     }
 
-    location::nearby::connections::mojom::Payload* incoming_payload =
+    nearby::connections::mojom::Payload* incoming_payload =
         nearby_connections_manager_->GetIncomingPayload(*payload_id);
     if (!incoming_payload || !incoming_payload->content ||
         !incoming_payload->content->is_file()) {
@@ -3927,7 +3924,7 @@
       return false;
     }
 
-    location::nearby::connections::mojom::Payload* incoming_payload =
+    nearby::connections::mojom::Payload* incoming_payload =
         nearby_connections_manager_->GetIncomingPayload(*payload_id);
     if (!incoming_payload || !incoming_payload->content ||
         !incoming_payload->content->is_bytes()) {
@@ -3962,7 +3959,7 @@
       return false;
     }
 
-    location::nearby::connections::mojom::Payload* incoming_payload =
+    nearby::connections::mojom::Payload* incoming_payload =
         nearby_connections_manager_->GetIncomingPayload(*payload_id);
     if (!incoming_payload || !incoming_payload->content ||
         !incoming_payload->content->is_bytes()) {
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
index ad04d51..bc572b66 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
@@ -268,13 +268,11 @@
   void OnUniquePathFetched(
       int64_t attachment_id,
       int64_t payload_id,
-      base::OnceCallback<void(location::nearby::connections::mojom::Status)>
-          callback,
+      base::OnceCallback<void(nearby::connections::mojom::Status)> callback,
       base::FilePath path);
-  void OnPayloadPathRegistered(
-      base::ScopedClosureRunner closure_runner,
-      bool* aggregated_success,
-      location::nearby::connections::mojom::Status status);
+  void OnPayloadPathRegistered(base::ScopedClosureRunner closure_runner,
+                               bool* aggregated_success,
+                               nearby::connections::mojom::Status status);
   void OnPayloadPathsRegistered(const ShareTarget& share_target,
                                 std::unique_ptr<bool> aggregated_success,
                                 StatusCodesCallback status_codes_callback);
@@ -293,8 +291,8 @@
   void OnOpenFiles(ShareTarget share_target,
                    base::OnceCallback<void(ShareTarget, bool)> callback,
                    std::vector<NearbyFileHandler::FileInfo> files);
-  std::vector<location::nearby::connections::mojom::PayloadPtr>
-  CreateTextPayloads(const std::vector<TextAttachment>& attachments);
+  std::vector<nearby::connections::mojom::PayloadPtr> CreateTextPayloads(
+      const std::vector<TextAttachment>& attachments);
 
   void WriteResponse(
       NearbyConnection& connection,
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
index 28c301e2..feaeefd 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
@@ -355,8 +355,7 @@
   return base::PathExists(file_path);
 }
 
-location::nearby::connections::mojom::PayloadPtr GetFilePayloadPtr(
-    int64_t payload_id) {
+nearby::connections::mojom::PayloadPtr GetFilePayloadPtr(int64_t payload_id) {
   base::ScopedAllowBlockingForTesting allow_blocking;
   base::FilePath path;
   base::CreateTemporaryFile(&path);
@@ -364,32 +363,31 @@
                             base::File::Flags::FLAG_READ |
                             base::File::Flags::FLAG_WRITE);
 
-  return location::nearby::connections::mojom::Payload::New(
-      payload_id, location::nearby::connections::mojom::PayloadContent::NewFile(
-                      location::nearby::connections::mojom::FilePayload::New(
-                          std::move(file))));
+  return nearby::connections::mojom::Payload::New(
+      payload_id,
+      nearby::connections::mojom::PayloadContent::NewFile(
+          nearby::connections::mojom::FilePayload::New(std::move(file))));
 }
 
-location::nearby::connections::mojom::PayloadPtr GetTextPayloadPtr(
+nearby::connections::mojom::PayloadPtr GetTextPayloadPtr(
     int64_t payload_id,
     const std::string& text) {
-  return location::nearby::connections::mojom::Payload::New(
-      payload_id,
-      location::nearby::connections::mojom::PayloadContent::NewBytes(
-          location::nearby::connections::mojom::BytesPayload::New(
-              std::vector<uint8_t>(text.begin(), text.end()))));
+  return nearby::connections::mojom::Payload::New(
+      payload_id, nearby::connections::mojom::PayloadContent::NewBytes(
+                      nearby::connections::mojom::BytesPayload::New(
+                          std::vector<uint8_t>(text.begin(), text.end()))));
 }
 
-location::nearby::connections::mojom::PayloadPtr GetWifiPayloadPtr(
+nearby::connections::mojom::PayloadPtr GetWifiPayloadPtr(
     int64_t payload_id,
     const std::string& password) {
   sharing::nearby::WifiCredentials credentials_proto;
   credentials_proto.set_password(password);
   const std::string& proto_string = credentials_proto.SerializeAsString();
-  return location::nearby::connections::mojom::Payload::New(
+  return nearby::connections::mojom::Payload::New(
       payload_id,
-      location::nearby::connections::mojom::PayloadContent::NewBytes(
-          location::nearby::connections::mojom::BytesPayload::New(
+      nearby::connections::mojom::PayloadContent::NewBytes(
+          nearby::connections::mojom::BytesPayload::New(
               std::vector<uint8_t>(proto_string.begin(), proto_string.end()))));
 }
 
@@ -970,9 +968,8 @@
           run_loop.Quit();
         });
     fake_nearby_connections_manager_->OnEndpointFound(
-        kEndpointId,
-        location::nearby::connections::mojom::DiscoveredEndpointInfo::New(
-            kValidV1EndpointInfo, kServiceId));
+        kEndpointId, nearby::connections::mojom::DiscoveredEndpointInfo::New(
+                         kValidV1EndpointInfo, kServiceId));
     ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1,
                                              /*success=*/true);
     run_loop.Run();
@@ -1140,9 +1137,9 @@
                           success_run_loop.QuitClosure());
     ASSERT_TRUE(info.listener);
     info.listener->OnStatusUpdate(
-        location::nearby::connections::mojom::PayloadTransferUpdate::New(
+        nearby::connections::mojom::PayloadTransferUpdate::New(
             info.payload_id,
-            location::nearby::connections::mojom::PayloadStatus::kSuccess,
+            nearby::connections::mojom::PayloadStatus::kSuccess,
             /*total_bytes=*/strlen(kTextPayload),
             /*bytes_transferred=*/strlen(kTextPayload)),
         /*upgraded_medium=*/absl::nullopt);
@@ -1161,9 +1158,8 @@
 
   void FindEndpoint(const std::string& endpoint_id) {
     fake_nearby_connections_manager_->OnEndpointFound(
-        endpoint_id,
-        location::nearby::connections::mojom::DiscoveredEndpointInfo::New(
-            kValidV1EndpointInfo, kServiceId));
+        endpoint_id, nearby::connections::mojom::DiscoveredEndpointInfo::New(
+                         kValidV1EndpointInfo, kServiceId));
   }
 
   void LoseEndpoint(const std::string& endpoint_id) {
@@ -1175,7 +1171,7 @@
   void SuccessfullyReceiveTransfer() {
     for (int64_t payload_id : kValidIntroductionFramePayloadIds) {
       fake_nearby_connections_manager_->SetPayloadPathStatus(
-          payload_id, location::nearby::connections::mojom::Status::kSuccess);
+          payload_id, nearby::connections::mojom::Status::kSuccess);
     }
 
     NiceMock<MockTransferUpdateCallback> callback;
@@ -1233,9 +1229,9 @@
             run_loop_progress.Quit();
           }));
 
-      location::nearby::connections::mojom::PayloadTransferUpdatePtr payload =
-          location::nearby::connections::mojom::PayloadTransferUpdate::New(
-              id, location::nearby::connections::mojom::PayloadStatus::kSuccess,
+      nearby::connections::mojom::PayloadTransferUpdatePtr payload =
+          nearby::connections::mojom::PayloadTransferUpdate::New(
+              id, nearby::connections::mojom::PayloadStatus::kSuccess,
               /*total_bytes=*/kPayloadSize,
               /*bytes_transferred=*/kPayloadSize);
       listener->OnStatusUpdate(std::move(payload),
@@ -1289,10 +1285,9 @@
             kFilePayloadId);
     ASSERT_TRUE(listener);
 
-    location::nearby::connections::mojom::PayloadTransferUpdatePtr payload =
-        location::nearby::connections::mojom::PayloadTransferUpdate::New(
-            kFilePayloadId,
-            location::nearby::connections::mojom::PayloadStatus::kSuccess,
+    nearby::connections::mojom::PayloadTransferUpdatePtr payload =
+        nearby::connections::mojom::PayloadTransferUpdate::New(
+            kFilePayloadId, nearby::connections::mojom::PayloadStatus::kSuccess,
             /*total_bytes=*/kPayloadSize,
             /*bytes_transferred=*/kPayloadSize);
     listener->OnStatusUpdate(std::move(payload),
@@ -1317,10 +1312,10 @@
   }
 
   void ReceiveBadWifiPayload(
-      location::nearby::connections::mojom::PayloadPtr wifi_payload) {
+      nearby::connections::mojom::PayloadPtr wifi_payload) {
     for (int64_t payload_id : kValidIntroductionFramePayloadIds) {
       fake_nearby_connections_manager_->SetPayloadPathStatus(
-          payload_id, location::nearby::connections::mojom::Status::kSuccess);
+          payload_id, nearby::connections::mojom::Status::kSuccess);
     }
 
     NiceMock<MockTransferUpdateCallback> callback;
@@ -1375,9 +1370,9 @@
             run_loop_progress.Quit();
           }));
 
-      location::nearby::connections::mojom::PayloadTransferUpdatePtr payload =
-          location::nearby::connections::mojom::PayloadTransferUpdate::New(
-              id, location::nearby::connections::mojom::PayloadStatus::kSuccess,
+      nearby::connections::mojom::PayloadTransferUpdatePtr payload =
+          nearby::connections::mojom::PayloadTransferUpdate::New(
+              id, nearby::connections::mojom::PayloadStatus::kSuccess,
               /*total_bytes=*/kPayloadSize,
               /*bytes_transferred=*/kPayloadSize);
       listener->OnStatusUpdate(std::move(payload),
@@ -1407,10 +1402,9 @@
             kFilePayloadId);
     ASSERT_TRUE(listener);
 
-    location::nearby::connections::mojom::PayloadTransferUpdatePtr payload =
-        location::nearby::connections::mojom::PayloadTransferUpdate::New(
-            kFilePayloadId,
-            location::nearby::connections::mojom::PayloadStatus::kSuccess,
+    nearby::connections::mojom::PayloadTransferUpdatePtr payload =
+        nearby::connections::mojom::PayloadTransferUpdate::New(
+            kFilePayloadId, nearby::connections::mojom::PayloadStatus::kSuccess,
             /*total_bytes=*/kPayloadSize,
             /*bytes_transferred=*/kPayloadSize);
     listener->OnStatusUpdate(std::move(payload),
@@ -1977,9 +1971,8 @@
         run_loop.Quit();
       });
   fake_nearby_connections_manager_->OnEndpointFound(
-      kEndpointId,
-      location::nearby::connections::mojom::DiscoveredEndpointInfo::New(
-          kValidV1EndpointInfo, kServiceId));
+      kEndpointId, nearby::connections::mojom::DiscoveredEndpointInfo::New(
+                       kValidV1EndpointInfo, kServiceId));
   ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1,
                                            /*success=*/true);
   run_loop.Run();
@@ -2042,9 +2035,8 @@
         run_loop.Quit();
       });
   fake_nearby_connections_manager_->OnEndpointFound(
-      kEndpointId,
-      location::nearby::connections::mojom::DiscoveredEndpointInfo::New(
-          kValidV1EndpointInfo, kServiceId));
+      kEndpointId, nearby::connections::mojom::DiscoveredEndpointInfo::New(
+                       kValidV1EndpointInfo, kServiceId));
   ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1,
                                            /*success=*/false);
   run_loop.Run();
@@ -3219,7 +3211,7 @@
 TEST_P(NearbySharingServiceImplTest,
        AcceptValidShareTarget_RegisterPayloadError) {
   fake_nearby_connections_manager_->SetPayloadPathStatus(
-      kFilePayloadId, location::nearby::connections::mojom::Status::kError);
+      kFilePayloadId, nearby::connections::mojom::Status::kError);
   NiceMock<MockTransferUpdateCallback> callback;
   ShareTarget share_target = SetUpIncomingConnection(callback);
 
@@ -3261,7 +3253,7 @@
 TEST_P(NearbySharingServiceImplTest, AcceptValidShareTarget) {
   for (int64_t payload_id : kValidIntroductionFramePayloadIds) {
     fake_nearby_connections_manager_->SetPayloadPathStatus(
-        payload_id, location::nearby::connections::mojom::Status::kSuccess);
+        payload_id, nearby::connections::mojom::Status::kSuccess);
   }
 
   NiceMock<MockTransferUpdateCallback> callback;
@@ -3316,15 +3308,15 @@
 }
 
 TEST_P(NearbySharingServiceImplTest, AcceptValidShareTarget_NoWifiPayload) {
-  ReceiveBadWifiPayload(location::nearby::connections::mojom::Payload::New());
+  ReceiveBadWifiPayload(nearby::connections::mojom::Payload::New());
 }
 
 TEST_P(NearbySharingServiceImplTest,
        AcceptValidShareTarget_WifiPayloadBytesEmpty) {
-  ReceiveBadWifiPayload(location::nearby::connections::mojom::Payload::New(
+  ReceiveBadWifiPayload(nearby::connections::mojom::Payload::New(
       kWifiCredentialsPayloadId,
-      location::nearby::connections::mojom::PayloadContent::NewBytes(
-          location::nearby::connections::mojom::BytesPayload::New(
+      nearby::connections::mojom::PayloadContent::NewBytes(
+          nearby::connections::mojom::BytesPayload::New(
               std::vector<uint8_t>()))));
 }
 
@@ -3332,12 +3324,11 @@
        AcceptValidShareTarget_NoCredentialsInProto) {
   const std::string& proto_string = "Random string that's not a proto";
 
-  ReceiveBadWifiPayload(location::nearby::connections::mojom::Payload::New(
+  ReceiveBadWifiPayload(nearby::connections::mojom::Payload::New(
       kWifiCredentialsPayloadId,
-      location::nearby::connections::mojom::PayloadContent::NewBytes(
-          location::nearby::connections::mojom::BytesPayload::New(
-              std::vector<uint8_t>(proto_string.begin(),
-                                   proto_string.end())))));
+      nearby::connections::mojom::PayloadContent::NewBytes(
+          nearby::connections::mojom::BytesPayload::New(std::vector<uint8_t>(
+              proto_string.begin(), proto_string.end())))));
 }
 
 TEST_P(NearbySharingServiceImplTest,
@@ -3347,12 +3338,11 @@
   credentials_proto.set_hidden_ssid(false);
   const std::string& proto_string = credentials_proto.SerializeAsString();
 
-  ReceiveBadWifiPayload(location::nearby::connections::mojom::Payload::New(
+  ReceiveBadWifiPayload(nearby::connections::mojom::Payload::New(
       kWifiCredentialsPayloadId,
-      location::nearby::connections::mojom::PayloadContent::NewBytes(
-          location::nearby::connections::mojom::BytesPayload::New(
-              std::vector<uint8_t>(proto_string.begin(),
-                                   proto_string.end())))));
+      nearby::connections::mojom::PayloadContent::NewBytes(
+          nearby::connections::mojom::BytesPayload::New(std::vector<uint8_t>(
+              proto_string.begin(), proto_string.end())))));
 }
 
 TEST_P(NearbySharingServiceImplTest, AcceptValidShareTarget_HiddenNetwork) {
@@ -3361,19 +3351,18 @@
   credentials_proto.set_hidden_ssid(true);
   const std::string& proto_string = credentials_proto.SerializeAsString();
 
-  ReceiveBadWifiPayload(location::nearby::connections::mojom::Payload::New(
+  ReceiveBadWifiPayload(nearby::connections::mojom::Payload::New(
       kWifiCredentialsPayloadId,
-      location::nearby::connections::mojom::PayloadContent::NewBytes(
-          location::nearby::connections::mojom::BytesPayload::New(
-              std::vector<uint8_t>(proto_string.begin(),
-                                   proto_string.end())))));
+      nearby::connections::mojom::PayloadContent::NewBytes(
+          nearby::connections::mojom::BytesPayload::New(std::vector<uint8_t>(
+              proto_string.begin(), proto_string.end())))));
 }
 
 TEST_P(NearbySharingServiceImplTest,
        AcceptValidShareTarget_PayloadSuccessful_IncomingPayloadNotFound) {
   for (int64_t payload_id : kValidIntroductionFramePayloadIds) {
     fake_nearby_connections_manager_->SetPayloadPathStatus(
-        payload_id, location::nearby::connections::mojom::Status::kSuccess);
+        payload_id, nearby::connections::mojom::Status::kSuccess);
   }
 
   NiceMock<MockTransferUpdateCallback> callback;
@@ -3428,9 +3417,9 @@
           run_loop_progress.Quit();
         }));
 
-    location::nearby::connections::mojom::PayloadTransferUpdatePtr payload =
-        location::nearby::connections::mojom::PayloadTransferUpdate::New(
-            id, location::nearby::connections::mojom::PayloadStatus::kSuccess,
+    nearby::connections::mojom::PayloadTransferUpdatePtr payload =
+        nearby::connections::mojom::PayloadTransferUpdate::New(
+            id, nearby::connections::mojom::PayloadStatus::kSuccess,
             /*total_bytes=*/kPayloadSize,
             /*bytes_transferred=*/kPayloadSize);
     listener->OnStatusUpdate(std::move(payload),
@@ -3462,10 +3451,9 @@
           kFilePayloadId);
   ASSERT_TRUE(listener);
 
-  location::nearby::connections::mojom::PayloadTransferUpdatePtr payload =
-      location::nearby::connections::mojom::PayloadTransferUpdate::New(
-          kFilePayloadId,
-          location::nearby::connections::mojom::PayloadStatus::kSuccess,
+  nearby::connections::mojom::PayloadTransferUpdatePtr payload =
+      nearby::connections::mojom::PayloadTransferUpdate::New(
+          kFilePayloadId, nearby::connections::mojom::PayloadStatus::kSuccess,
           /*total_bytes=*/kPayloadSize,
           /*bytes_transferred=*/kPayloadSize);
   listener->OnStatusUpdate(std::move(payload),
@@ -3492,7 +3480,7 @@
 TEST_P(NearbySharingServiceImplTest, AcceptValidShareTarget_PayloadFailed) {
   for (int64_t payload_id : kValidIntroductionFramePayloadIds) {
     fake_nearby_connections_manager_->SetPayloadPathStatus(
-        payload_id, location::nearby::connections::mojom::Status::kSuccess);
+        payload_id, nearby::connections::mojom::Status::kSuccess);
   }
 
   NiceMock<MockTransferUpdateCallback> callback;
@@ -3536,10 +3524,9 @@
             run_loop_failure.Quit();
           }));
 
-  location::nearby::connections::mojom::PayloadTransferUpdatePtr payload =
-      location::nearby::connections::mojom::PayloadTransferUpdate::New(
-          kFilePayloadId,
-          location::nearby::connections::mojom::PayloadStatus::kFailure,
+  nearby::connections::mojom::PayloadTransferUpdatePtr payload =
+      nearby::connections::mojom::PayloadTransferUpdate::New(
+          kFilePayloadId, nearby::connections::mojom::PayloadStatus::kFailure,
           /*total_bytes=*/kPayloadSize,
           /*bytes_transferred=*/kPayloadSize);
   listener->OnStatusUpdate(std::move(payload),
@@ -3566,7 +3553,7 @@
 TEST_P(NearbySharingServiceImplTest, AcceptValidShareTarget_PayloadCancelled) {
   for (int64_t payload_id : kValidIntroductionFramePayloadIds) {
     fake_nearby_connections_manager_->SetPayloadPathStatus(
-        payload_id, location::nearby::connections::mojom::Status::kSuccess);
+        payload_id, nearby::connections::mojom::Status::kSuccess);
   }
 
   NiceMock<MockTransferUpdateCallback> callback;
@@ -3610,10 +3597,9 @@
             run_loop_failure.Quit();
           }));
 
-  location::nearby::connections::mojom::PayloadTransferUpdatePtr payload =
-      location::nearby::connections::mojom::PayloadTransferUpdate::New(
-          kFilePayloadId,
-          location::nearby::connections::mojom::PayloadStatus::kCanceled,
+  nearby::connections::mojom::PayloadTransferUpdatePtr payload =
+      nearby::connections::mojom::PayloadTransferUpdate::New(
+          kFilePayloadId, nearby::connections::mojom::PayloadStatus::kCanceled,
           /*total_bytes=*/kPayloadSize,
           /*bytes_transferred=*/kPayloadSize);
   listener->OnStatusUpdate(std::move(payload),
@@ -5268,7 +5254,7 @@
 TEST_P(NearbySharingServiceImplTest, SelfShareAutoAccept) {
   for (int64_t payload_id : kValidIntroductionFramePayloadIds) {
     fake_nearby_connections_manager_->SetPayloadPathStatus(
-        payload_id, location::nearby::connections::mojom::Status::kSuccess);
+        payload_id, nearby::connections::mojom::Status::kSuccess);
   }
 
   // We create an incoming connection corresponding to a certificate where the
diff --git a/chrome/browser/nearby_sharing/outgoing_share_target_info.h b/chrome/browser/nearby_sharing/outgoing_share_target_info.h
index e203921..9a2673c 100644
--- a/chrome/browser/nearby_sharing/outgoing_share_target_info.h
+++ b/chrome/browser/nearby_sharing/outgoing_share_target_info.h
@@ -15,7 +15,7 @@
 // A description of the outgoing connection to a remote device.
 class OutgoingShareTargetInfo : public ShareTargetInfo {
  public:
-  using PayloadPtr = location::nearby::connections::mojom::PayloadPtr;
+  using PayloadPtr = ::nearby::connections::mojom::PayloadPtr;
 
   OutgoingShareTargetInfo();
   OutgoingShareTargetInfo(OutgoingShareTargetInfo&&);
diff --git a/chrome/browser/nearby_sharing/payload_tracker.cc b/chrome/browser/nearby_sharing/payload_tracker.cc
index 1ce71c0..6492925 100644
--- a/chrome/browser/nearby_sharing/payload_tracker.cc
+++ b/chrome/browser/nearby_sharing/payload_tracker.cc
@@ -109,8 +109,7 @@
         (GetTotalTransferred() >= total_transfer_size_) ? true : false;
     if (is_transfer_complete) {
       NS_LOG(VERBOSE) << __func__ << ": All payloads are complete.";
-      EmitFinalMetrics(
-          location::nearby::connections::mojom::PayloadStatus::kSuccess);
+      EmitFinalMetrics(nearby::connections::mojom::PayloadStatus::kSuccess);
       update_callback_.Run(share_target_,
                            TransferMetadataBuilder()
                                .set_status(TransferMetadata::Status::kComplete)
@@ -120,8 +119,7 @@
     }
 
     NS_LOG(VERBOSE) << __func__ << ": Payloads incomplete.";
-    EmitFinalMetrics(
-        location::nearby::connections::mojom::PayloadStatus::kFailure);
+    EmitFinalMetrics(nearby::connections::mojom::PayloadStatus::kFailure);
     update_callback_.Run(
         share_target_,
         TransferMetadataBuilder()
@@ -134,8 +132,7 @@
 
   if (IsCancelled()) {
     NS_LOG(VERBOSE) << __func__ << ": Payloads cancelled.";
-    EmitFinalMetrics(
-        location::nearby::connections::mojom::PayloadStatus::kCanceled);
+    EmitFinalMetrics(nearby::connections::mojom::PayloadStatus::kCanceled);
     update_callback_.Run(share_target_,
                          TransferMetadataBuilder()
                              .set_status(TransferMetadata::Status::kCancelled)
@@ -145,8 +142,7 @@
 
   if (HasFailed()) {
     NS_LOG(VERBOSE) << __func__ << ": Payloads failed.";
-    EmitFinalMetrics(
-        location::nearby::connections::mojom::PayloadStatus::kFailure);
+    EmitFinalMetrics(nearby::connections::mojom::PayloadStatus::kFailure);
     update_callback_.Run(share_target_,
                          TransferMetadataBuilder()
                              .set_status(TransferMetadata::Status::kFailed)
@@ -175,7 +171,7 @@
 bool PayloadTracker::IsComplete() const {
   for (const auto& state : payload_state_) {
     if (state.second.status !=
-        location::nearby::connections::mojom::PayloadStatus::kSuccess) {
+        nearby::connections::mojom::PayloadStatus::kSuccess) {
       return false;
     }
   }
@@ -185,7 +181,7 @@
 bool PayloadTracker::IsCancelled() const {
   for (const auto& state : payload_state_) {
     if (state.second.status ==
-        location::nearby::connections::mojom::PayloadStatus::kCanceled) {
+        nearby::connections::mojom::PayloadStatus::kCanceled) {
       return true;
     }
   }
@@ -195,7 +191,7 @@
 bool PayloadTracker::HasFailed() const {
   for (const auto& state : payload_state_) {
     if (state.second.status ==
-        location::nearby::connections::mojom::PayloadStatus::kFailure) {
+        nearby::connections::mojom::PayloadStatus::kFailure) {
       return true;
     }
   }
@@ -220,9 +216,8 @@
 }
 
 void PayloadTracker::EmitFinalMetrics(
-    location::nearby::connections::mojom::PayloadStatus status) const {
-  DCHECK_NE(status,
-            location::nearby::connections::mojom::PayloadStatus::kInProgress);
+    nearby::connections::mojom::PayloadStatus status) const {
+  DCHECK_NE(status, nearby::connections::mojom::PayloadStatus::kInProgress);
   RecordNearbySharePayloadFinalStatusMetric(status, last_upgraded_medium_);
   RecordNearbySharePayloadMediumMetric(
       last_upgraded_medium_, share_target_.type, GetTotalTransferred());
diff --git a/chrome/browser/nearby_sharing/payload_tracker.h b/chrome/browser/nearby_sharing/payload_tracker.h
index be1b58e..536ea5b 100644
--- a/chrome/browser/nearby_sharing/payload_tracker.h
+++ b/chrome/browser/nearby_sharing/payload_tracker.h
@@ -37,8 +37,8 @@
 
     uint64_t amount_transferred = 0;
     const uint64_t total_size;
-    location::nearby::connections::mojom::PayloadStatus status =
-        location::nearby::connections::mojom::PayloadStatus::kInProgress;
+    nearby::connections::mojom::PayloadStatus status =
+        nearby::connections::mojom::PayloadStatus::kInProgress;
   };
 
   void OnTransferUpdate();
@@ -50,8 +50,7 @@
   uint64_t GetTotalTransferred() const;
   double CalculateProgressPercent() const;
 
-  void EmitFinalMetrics(
-      location::nearby::connections::mojom::PayloadStatus status) const;
+  void EmitFinalMetrics(nearby::connections::mojom::PayloadStatus status) const;
 
   ShareTarget share_target_;
   base::RepeatingCallback<void(ShareTarget, TransferMetadata)> update_callback_;
diff --git a/chrome/browser/nearby_sharing/payload_tracker_unittest.cc b/chrome/browser/nearby_sharing/payload_tracker_unittest.cc
index be67ffa..8063c83 100644
--- a/chrome/browser/nearby_sharing/payload_tracker_unittest.cc
+++ b/chrome/browser/nearby_sharing/payload_tracker_unittest.cc
@@ -94,21 +94,18 @@
   MockUpdateCallback& callback() { return callback_; }
 
   void MarkSuccessful(int payload_id) {
-    UpdatePayloadStatus(
-        payload_id,
-        location::nearby::connections::mojom::PayloadStatus::kSuccess);
+    UpdatePayloadStatus(payload_id,
+                        nearby::connections::mojom::PayloadStatus::kSuccess);
   }
 
   void MarkCancelled(int payload_id) {
-    UpdatePayloadStatus(
-        payload_id,
-        location::nearby::connections::mojom::PayloadStatus::kCanceled);
+    UpdatePayloadStatus(payload_id,
+                        nearby::connections::mojom::PayloadStatus::kCanceled);
   }
 
   void MarkFailure(int payload_id) {
-    UpdatePayloadStatus(
-        payload_id,
-        location::nearby::connections::mojom::PayloadStatus::kFailure);
+    UpdatePayloadStatus(payload_id,
+                        nearby::connections::mojom::PayloadStatus::kFailure);
   }
 
   void WaitBetweenUpdates() {
@@ -116,16 +113,14 @@
   }
 
  private:
-  void UpdatePayloadStatus(
-      int payload_id,
-      location::nearby::connections::mojom::PayloadStatus status) {
-    location::nearby::connections::mojom::PayloadTransferUpdatePtr payload =
-        location::nearby::connections::mojom::PayloadTransferUpdate::New(
+  void UpdatePayloadStatus(int payload_id,
+                           nearby::connections::mojom::PayloadStatus status) {
+    nearby::connections::mojom::PayloadTransferUpdatePtr payload =
+        nearby::connections::mojom::PayloadTransferUpdate::New(
             payload_id, status,
             /*total_bytes=*/kTotalSize, /*bytes_transferred=*/kTotalSize);
     payload_tracker_->OnStatusUpdate(
-        std::move(payload),
-        location::nearby::connections::mojom::Medium::kWebRtc);
+        std::move(payload), nearby::connections::mojom::Medium::kWebRtc);
   }
 
   content::BrowserTaskEnvironment task_environment_;
diff --git a/chrome/browser/nearby_sharing/public/cpp/nearby_connections_manager.h b/chrome/browser/nearby_sharing/public/cpp/nearby_connections_manager.h
index a29b63b..8867e02 100644
--- a/chrome/browser/nearby_sharing/public/cpp/nearby_connections_manager.h
+++ b/chrome/browser/nearby_sharing/public/cpp/nearby_connections_manager.h
@@ -20,9 +20,9 @@
 // A wrapper around the Nearby Connections mojo API.
 class NearbyConnectionsManager {
  public:
-  using Payload = location::nearby::connections::mojom::Payload;
-  using PayloadPtr = location::nearby::connections::mojom::PayloadPtr;
-  using ConnectionsStatus = location::nearby::connections::mojom::Status;
+  using Payload = nearby::connections::mojom::Payload;
+  using PayloadPtr = nearby::connections::mojom::PayloadPtr;
+  using ConnectionsStatus = nearby::connections::mojom::Status;
   using ConnectionsCallback =
       base::OnceCallback<void(ConnectionsStatus status)>;
   using NearbyConnectionCallback = base::OnceCallback<void(NearbyConnection*)>;
@@ -57,9 +57,9 @@
   // outgoing).
   class PayloadStatusListener {
    public:
-    using Medium = location::nearby::connections::mojom::Medium;
+    using Medium = nearby::connections::mojom::Medium;
     using PayloadTransferUpdatePtr =
-        location::nearby::connections::mojom::PayloadTransferUpdatePtr;
+        nearby::connections::mojom::PayloadTransferUpdatePtr;
 
     PayloadStatusListener();
     virtual ~PayloadStatusListener();
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
index 8fc4ce75..15ee9c7 100644
--- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
+++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
@@ -42,7 +42,7 @@
 class PredictionManager;
 class PredictionManagerBrowserTestBase;
 class PredictionModelDownloadClient;
-class PredictionModelStoreBrowserTest;
+class PredictionModelStoreBrowserTestBase;
 class PushNotificationManager;
 class TabUrlProvider;
 class TopHostProvider;
@@ -143,7 +143,7 @@
   friend class OptimizationGuideWebContentsObserver;
   friend class optimization_guide::PredictionManagerBrowserTestBase;
   friend class optimization_guide::PredictionModelDownloadClient;
-  friend class optimization_guide::PredictionModelStoreBrowserTest;
+  friend class optimization_guide::PredictionModelStoreBrowserTestBase;
   friend class optimization_guide::android::OptimizationGuideBridge;
 
   // Initializes |this|.
diff --git a/chrome/browser/optimization_guide/prediction/prediction_model_store_browsertest.cc b/chrome/browser/optimization_guide/prediction/prediction_model_store_browsertest.cc
index cf8b40e..114abff 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_model_store_browsertest.cc
+++ b/chrome/browser/optimization_guide/prediction/prediction_model_store_browsertest.cc
@@ -64,25 +64,25 @@
 
 }  // namespace
 
-class PredictionModelStoreBrowserTest : public InProcessBrowserTest {
+class PredictionModelStoreBrowserTestBase : public InProcessBrowserTest {
  public:
-  PredictionModelStoreBrowserTest() = default;
-  ~PredictionModelStoreBrowserTest() override = default;
+  PredictionModelStoreBrowserTestBase() = default;
+  ~PredictionModelStoreBrowserTestBase() override = default;
 
-  PredictionModelStoreBrowserTest(const PredictionModelStoreBrowserTest&) =
-      delete;
-  PredictionModelStoreBrowserTest& operator=(
-      const PredictionModelStoreBrowserTest&) = delete;
+  PredictionModelStoreBrowserTestBase(
+      const PredictionModelStoreBrowserTestBase&) = delete;
+  PredictionModelStoreBrowserTestBase& operator=(
+      const PredictionModelStoreBrowserTestBase&) = delete;
 
   void SetUp() override {
-    scoped_feature_list_.InitWithFeatures(
-        {{features::kOptimizationGuideInstallWideModelStore}}, {});
+    InitializeFeatureList();
+
     models_server_ = std::make_unique<net::EmbeddedTestServer>(
         net::EmbeddedTestServer::TYPE_HTTPS);
     models_server_->ServeFilesFromSourceDirectory(
         "chrome/test/data/optimization_guide");
     models_server_->RegisterRequestHandler(base::BindRepeating(
-        &PredictionModelStoreBrowserTest::HandleGetModelsRequest,
+        &PredictionModelStoreBrowserTestBase::HandleGetModelsRequest,
         base::Unretained(this)));
 
     ASSERT_TRUE(models_server_->Start());
@@ -201,6 +201,9 @@
     return std::move(response);
   }
 
+  // Virtualize for testing different feature configurations.
+  virtual void InitializeFeatureList() = 0;
+
   base::test::ScopedFeatureList scoped_feature_list_;
   GURL model_file_url_;
   std::unique_ptr<net::EmbeddedTestServer> download_server_;
@@ -211,6 +214,23 @@
   absl::optional<proto::ModelCacheKey> server_model_cache_key_;
 };
 
+class PredictionModelStoreBrowserTest
+    : public PredictionModelStoreBrowserTestBase {
+ public:
+  PredictionModelStoreBrowserTest() = default;
+  ~PredictionModelStoreBrowserTest() override = default;
+
+  PredictionModelStoreBrowserTest(const PredictionModelStoreBrowserTest&) =
+      delete;
+  PredictionModelStoreBrowserTest& operator=(
+      const PredictionModelStoreBrowserTest&) = delete;
+
+  void InitializeFeatureList() override {
+    scoped_feature_list_.InitWithFeatures(
+        {{features::kOptimizationGuideInstallWideModelStore}}, {});
+  }
+};
+
 IN_PROC_BROWSER_TEST_F(PredictionModelStoreBrowserTest, TestRegularProfile) {
   ModelFileObserver model_file_observer;
   RegisterAndWaitForModelUpdate(&model_file_observer);
@@ -491,4 +511,71 @@
       model_file_observer_foo.model_info()->GetModelFilePath().IsAbsolute());
 }
 
+class PredictionModelStoreMigrationBrowserTest
+    : public PredictionModelStoreBrowserTestBase {
+ public:
+  PredictionModelStoreMigrationBrowserTest() = default;
+  ~PredictionModelStoreMigrationBrowserTest() override = default;
+
+  PredictionModelStoreMigrationBrowserTest(
+      const PredictionModelStoreMigrationBrowserTest&) = delete;
+  PredictionModelStoreMigrationBrowserTest& operator=(
+      const PredictionModelStoreMigrationBrowserTest&) = delete;
+
+  void InitializeFeatureList() override {
+    base::StringPiece test_name =
+        ::testing::UnitTest::GetInstance()->current_test_info()->name();
+
+    if (base::StartsWith(test_name, "PRE_PRE_")) {
+      // First stage of migration. Old model store is active.
+      scoped_feature_list_.InitAndDisableFeature(
+          features::kOptimizationGuideInstallWideModelStore);
+    } else if (base::StartsWith(test_name, "PRE_")) {
+      // Second stage of migration. New model store is active.
+      scoped_feature_list_.InitAndEnableFeature(
+          features::kOptimizationGuideInstallWideModelStore);
+    } else {
+      // Last stage of migration. Old model store is active.
+      scoped_feature_list_.InitAndDisableFeature(
+          features::kOptimizationGuideInstallWideModelStore);
+    }
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(PredictionModelStoreMigrationBrowserTest,
+                       PRE_PRE_MigrationOldToNewToOldStore) {
+  EXPECT_FALSE(features::IsInstallWideModelStoreEnabled());
+  ModelFileObserver model_file_observer;
+  RegisterAndWaitForModelUpdate(&model_file_observer);
+
+  // The model will be downloaded by the old model store.
+  histogram_tester_.ExpectUniqueSample(
+      "OptimizationGuide.PredictionModelDownloadManager.DownloadStatus",
+      PredictionModelDownloadStatus::kSuccess, 1);
+}
+
+IN_PROC_BROWSER_TEST_F(PredictionModelStoreMigrationBrowserTest,
+                       PRE_MigrationOldToNewToOldStore) {
+  EXPECT_TRUE(features::IsInstallWideModelStoreEnabled());
+  ModelFileObserver model_file_observer;
+  RegisterAndWaitForModelUpdate(&model_file_observer);
+
+  // The model will be downloaded by the new model store.
+  histogram_tester_.ExpectUniqueSample(
+      "OptimizationGuide.PredictionModelDownloadManager.DownloadStatus",
+      PredictionModelDownloadStatus::kSuccess, 1);
+}
+
+IN_PROC_BROWSER_TEST_F(PredictionModelStoreMigrationBrowserTest,
+                       MigrationOldToNewToOldStore) {
+  EXPECT_FALSE(features::IsInstallWideModelStoreEnabled());
+  ModelFileObserver model_file_observer;
+  RegisterAndWaitForModelUpdate(&model_file_observer);
+
+  // The model saved in the old model store will be used, and no download will
+  // happen.
+  histogram_tester_.ExpectTotalCount(
+      "OptimizationGuide.PredictionModelDownloadManager.DownloadStatus", 0);
+}
+
 }  // namespace optimization_guide
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index 47aa69f..ad3e579 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -3606,9 +3606,7 @@
     return;
   core_tab_helper->SearchWithLens(
       render_frame_host, params().src_url,
-      lens::EntryPoint::CHROME_SEARCH_WITH_GOOGLE_LENS_CONTEXT_MENU_ITEM,
-      /* is_side_panel_enabled_for_feature= */
-      lens::features::IsLensSidePanelEnabled());
+      lens::EntryPoint::CHROME_SEARCH_WITH_GOOGLE_LENS_CONTEXT_MENU_ITEM);
 }
 
 void RenderViewContextMenu::ExecAddANote() {
diff --git a/chrome/browser/resources/bookmarks/app.ts b/chrome/browser/resources/bookmarks/app.ts
index 1317674f..6fde599 100644
--- a/chrome/browser/resources/bookmarks/app.ts
+++ b/chrome/browser/resources/bookmarks/app.ts
@@ -239,6 +239,10 @@
   override _scrollHandler() {
     this.toolbarShadow_ = this.scrollTarget!.scrollTop !== 0;
   }
+
+  getDndManagerForTesting(): DndManager|null {
+    return this.dndManager_;
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/bookmarks/debouncer.ts b/chrome/browser/resources/bookmarks/debouncer.ts
index 5c51c51f..f30a95b3 100644
--- a/chrome/browser/resources/bookmarks/debouncer.ts
+++ b/chrome/browser/resources/bookmarks/debouncer.ts
@@ -5,6 +5,8 @@
 import {assert} from 'chrome://resources/js/assert_ts.js';
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
 
+import {TimerProxy} from './types.js';
+
 /**
  * @fileoverview A debouncer which fires the given callback after a delay. The
  * delay can be refreshed by calling restartTimeout. Resetting the timeout with
@@ -14,7 +16,7 @@
 export class Debouncer {
   private callback_: () => void;
   private timer_: number|null = null;
-  private timerProxy_: Window;
+  private timerProxy_: TimerProxy;
   private boundTimerCallback_: () => void;
   private isDone_: boolean = false;
   private promiseResolver_: PromiseResolver<void>;
diff --git a/chrome/browser/resources/bookmarks/dnd_manager.ts b/chrome/browser/resources/bookmarks/dnd_manager.ts
index 682d5bd..e53efbb 100644
--- a/chrome/browser/resources/bookmarks/dnd_manager.ts
+++ b/chrome/browser/resources/bookmarks/dnd_manager.ts
@@ -10,11 +10,12 @@
 
 import {changeFolderOpen, deselectItems, selectItem} from './actions.js';
 import {highlightUpdatedItems, trackUpdatedItems} from './api_listener.js';
+import {BookmarkManagerApiProxyImpl} from './bookmark_manager_api_proxy.js';
 import {DropPosition, ROOT_NODE_ID} from './constants.js';
 import {Debouncer} from './debouncer.js';
 import {BookmarksFolderNodeElement} from './folder_node.js';
 import {Store} from './store.js';
-import {BookmarkElement, BookmarkNode, DragData, DropDestination, NodeMap, ObjectMap} from './types.js';
+import {BookmarkElement, BookmarkNode, DragData, DropDestination, NodeMap, ObjectMap, TimerProxy} from './types.js';
 import {canEditNode, canReorderChildren, getDisplayedList, hasChildFolders, isShowingSearch, normalizeNode} from './util.js';
 
 interface NormalizedDragData {
@@ -191,7 +192,7 @@
   private removeDropIndicatorTimeoutId_: number|null;
   private lastIndicatorElement_: BookmarkElement|null;
   private lastIndicatorClassName_: string|null;
-  timerProxy: Window;
+  timerProxy: TimerProxy;
 
   constructor() {
     this.removeDropIndicatorTimeoutId_ = null;
@@ -268,7 +269,7 @@
   private dropIndicator_: DropIndicator|null;
   private eventTracker_: EventTracker = new EventTracker();
   private autoExpander_: AutoExpander|null;
-  private timerProxy_: any;
+  private timerProxy_: TimerProxy;
   private lastPointerWasTouch_: boolean;
 
   constructor() {
@@ -298,7 +299,7 @@
     this.eventTracker_.add(document, 'mousedown', () => this.onMouseDown_());
     this.eventTracker_.add(document, 'touchstart', () => this.onTouchStart_());
 
-    chrome.bookmarkManagerPrivate.onDragEnter.addListener(
+    BookmarkManagerApiProxyImpl.getInstance().onDragEnter.addListener(
         this.handleChromeDragEnter_.bind(this));
     chrome.bookmarkManagerPrivate.onDragLeave.addListener(
         this.clearDragData_.bind(this));
@@ -350,7 +351,7 @@
     const dragNodeIndex = draggedNodes.indexOf(dragElement.itemId);
     assert(dragNodeIndex !== -1);
 
-    chrome.bookmarkManagerPrivate.startDrag(
+    BookmarkManagerApiProxyImpl.getInstance().startDrag(
         draggedNodes, dragNodeIndex, this.lastPointerWasTouch_,
         (e as DragEvent).clientX, (e as DragEvent).clientY);
   }
@@ -376,7 +377,8 @@
         trackUpdatedItems();
       }
 
-      chrome.bookmarkManagerPrivate.drop(dropInfo.parentId, index)
+      BookmarkManagerApiProxyImpl.getInstance()
+          .drop(dropInfo.parentId, index)
           .then(shouldHighlight ? highlightUpdatedItems : undefined);
     }
     this.clearDragData_();
@@ -663,8 +665,12 @@
         isBookmarkList(dropDestination.element);
   }
 
-  setTimerProxyForTesting(timerProxy: any) {
+  setTimerProxyForTesting(timerProxy: TimerProxy) {
     this.timerProxy_ = timerProxy;
     this.dropIndicator_!.timerProxy = timerProxy;
   }
+
+  getDragInfoForTesting(): DragInfo|null {
+    return this.dragInfo_;
+  }
 }
diff --git a/chrome/browser/resources/bookmarks/types.ts b/chrome/browser/resources/bookmarks/types.ts
index 9add7ff2..3ea2fd5 100644
--- a/chrome/browser/resources/bookmarks/types.ts
+++ b/chrome/browser/resources/bookmarks/types.ts
@@ -91,3 +91,5 @@
   elements: chrome.bookmarks.BookmarkTreeNode[]|null = null;
   sameProfile: boolean = false;
 }
+
+export type TimerProxy = Pick<Window, 'setTimeout'|'clearTimeout'>;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/tts_background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/tts_background.js
index 138f006..755417c 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/tts_background.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/tts_background.js
@@ -82,14 +82,8 @@
     TtsBackground.primary.updateVoice('', () => {
       // Ensure this announcement doesn't get cut off by speech triggered by
       // updateFromPrefs_().
-      // Copy properties from Personality.ANNOTATION and add the
-      // doNotInterrupt property.
-      const speechProperties = {};
-      const sourceProperties = Personality.ANNOTATION || {};
-      for (const [key, value] of Object.entries(sourceProperties)) {
-        speechProperties[key] = value;
-      }
-      speechProperties['doNotInterrupt'] = true;
+      const speechProperties = {...Personality.ANNOTATION};
+      speechProperties.doNotInterrupt = true;
 
       ChromeVox.tts.speak(
           Msgs.getMsg('announce_tts_default_settings'), QueueMode.FLUSH,
diff --git a/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn
index 0fa1601..6af04ac 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn
@@ -51,6 +51,7 @@
     "repeated_event_handler.js",
     "repeated_tree_change_handler.js",
     "sentence_utils.js",
+    "settings.js",
     "string_util.js",
     "testing/accessibility_test_base.js",
     "testing/test_node_generator.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/common/settings.js b/chrome/browser/resources/chromeos/accessibility/common/settings.js
new file mode 100644
index 0000000..aa363e3
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/common/settings.js
@@ -0,0 +1,133 @@
+// 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 Class to handle accessing/storing/caching prefs data.
+ */
+const PrefObject = chrome.settingsPrivate.PrefObject;
+
+export class Settings {
+  /**
+   * @param {!Array<string>} keys The settings keys the extension cares about.
+   * @private
+   */
+  constructor(keys) {
+    /** @private {Object<string, !Array<!Function>>} */
+    this.listeners_ = {};
+    /** @private {?Object<string, PrefObject>} */
+    this.prefs_ = null;
+
+    keys.forEach(key => this.listeners_[key] = []);
+    chrome.settingsPrivate.onPrefsChanged.addListener(
+        updates => this.update_(updates));
+  }
+
+  /**
+   * @param {!Array<string>} keys The settings keys the extension cares about.
+   */
+  static async init(keys) {
+    if (Settings.instance) {
+      throw new Error(
+          'Settings.init() should be called at most once in each ' +
+          'browser context.');
+    }
+
+    Settings.instance = new Settings(keys);
+    await Settings.instance.initialFetch_();
+  }
+
+  /**
+   * Adds a callback to listen to changes to one or more preferences.
+   * The callback will be called immediately if there is a value set.
+   * @param {string|!Array<string>} keys The settings keys being listened to.
+   * @param {!Function} listener The callback when the value changes.
+   */
+  static addListener(keys, listener) {
+    if (typeof keys === 'string') {
+      keys = [keys];
+    }
+
+    for (const key of keys) {
+      Settings.instance.addListener_(key, listener);
+    }
+  }
+
+  /**
+   * @param {string} key
+   * @return {?PrefObject}
+   */
+  static get(key) {
+    Settings.instance.validate_(key);
+    return Settings.instance.prefs_[key];
+  }
+
+  // ============ Private methods ============
+
+  /**
+   * @param {string} key The settings key being listened to.
+   * @param {!Function} listener The callback when the value changes.
+   * @private
+   */
+  addListener_(key, listener) {
+    this.validate_(key);
+    this.listeners_[key].push(listener);
+
+    if (this.prefs_[key] !== null) {
+      listener(this.prefs_[key]);
+    }
+  }
+
+  /** @private */
+  async initialFetch_() {
+    const prefs = await new Promise(
+        resolve => chrome.settingsPrivate.getAllPrefs(resolve));
+    this.prefs_ = prefs.filter(pref => this.isTracked_(pref.key));
+  }
+
+  /**
+   * @param {string} key
+   * @private
+   */
+  isTracked_(key) {
+    // Because we assign to this.prefs_ in initialFetch_(), use listeners_ as
+    // the official source of truth on what keys are in scope.
+    return key in this.listeners_;
+  }
+
+  /**
+   * @param {!Array<!PrefObject>} updates
+   * @private
+   */
+  update_(updates) {
+    for (const pref of updates) {
+      if (!this.isTracked_(pref.key)) {
+        continue;
+      }
+
+      const oldValue = this.prefs_[pref.key].value;
+      if (oldValue === pref.value) {
+        continue;
+      }
+
+      this.prefs_[pref.key] = pref;
+      this.listeners_[pref.key].forEach(listener => listener(pref.value));
+    }
+  }
+
+  /**
+   * @param {string} key
+   * @private
+   */
+  validate_(key) {
+    if (this.prefs_ === null) {
+      throw new Error('Cannot access Settings until init() has resolved.');
+    }
+    if (!this.isTracked_(key)) {
+      throw new Error('Prefs key "' + key + '" is not being tracked.');
+    }
+  }
+}
+
+/** @private {Settings} */
+Settings.instance;
diff --git a/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.html b/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.html
index f53f155..b601673 100644
--- a/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.html
+++ b/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.html
@@ -76,14 +76,12 @@
       warning$="[[showRestrictedConnectivity_(managedProperties_)]]">
     [[getStateText_(managedProperties_)]]
   </div>
-  <template is="dom-if" if="[[isCaptivePortalUI2022Enabled_]]">
-    <cr-button class="signin-button" id="signinButton" on-click="onSigninTap_"
-        hidden$="[[!showSignin_(managedProperties_)]]"
-        disabled="[[disableSignin_(managedProperties_, disabled_)]]">
-      <div class="signin-icon cr-icon icon-external"></div>
-      $i18n{networkButtonSignin}
-    </cr-button>
-  </template>
+  <cr-button class="signin-button" id="signinButton" on-click="onSigninTap_"
+      hidden$="[[!showSignin_(managedProperties_)]]"
+      disabled="[[disableSignin_(managedProperties_, disabled_)]]">
+    <div class="signin-icon cr-icon icon-external"></div>
+    $i18n{networkButtonSignin}
+  </cr-button>
   <cr-button on-click="onForgetTap_"
       hidden$="[[!showForget_(managedProperties_)]]"
       disabled="[[disabled_]]">
@@ -230,4 +228,4 @@
       </network-property-list-mojo>
     </div>
   </template>
-</template>
\ No newline at end of file
+</template>
diff --git a/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.js b/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.js
index 61d6042..48d1a870 100644
--- a/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.js
+++ b/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.js
@@ -79,17 +79,6 @@
             loadTimeData.getBoolean('showTechnologyBadge');
       },
     },
-    /**
-     * Return true if captivePortalUI2022 feature flag is enabled.
-     * @private
-     */
-    isCaptivePortalUI2022Enabled_: {
-      type: Boolean,
-      value() {
-        return loadTimeData.valueExists('captivePortalUI2022') &&
-            loadTimeData.getBoolean('captivePortalUI2022');
-      },
-    },
 
     /**
      * Whether network configuration properties sections should be shown. The
@@ -355,8 +344,7 @@
       return '';
     }
 
-    if (this.isCaptivePortalUI2022Enabled_ &&
-        OncMojo.connectionStateIsConnected(managedProperties.connectionState)) {
+    if (OncMojo.connectionStateIsConnected(managedProperties.connectionState)) {
       if (this.isPortalState_(managedProperties.portalState)) {
         return this.i18n('networkListItemSignIn');
       }
@@ -410,11 +398,6 @@
    * @private
    */
   showConnectedState_(managedProperties) {
-    // Only check that state is connected if feature flag is disabled.
-    if (!this.isCaptivePortalUI2022Enabled_) {
-      return this.isConnectedState_(managedProperties);
-    }
-
     return this.isConnectedState_(managedProperties) &&
         !this.isRestrictedConnectivity_(managedProperties);
   },
@@ -427,10 +410,6 @@
    * @private
    */
   showRestrictedConnectivity_(managedProperties) {
-    // Do not show warning color if feature flag is disabled.
-    if (!this.isCaptivePortalUI2022Enabled_) {
-      return false;
-    }
     if (!managedProperties) {
       return false;
     }
@@ -548,9 +527,6 @@
    * @private
    */
   showSignin_(managedProperties) {
-    if (!this.isCaptivePortalUI2022Enabled_) {
-      return false;
-    }
     if (!managedProperties) {
       return false;
     }
@@ -567,9 +543,6 @@
    * @private
    */
   disableSignin_(managedProperties) {
-    if (!this.isCaptivePortalUI2022Enabled_) {
-      return true;
-    }
     if (this.disabled_ || !managedProperties) {
       return true;
     }
diff --git a/chrome/browser/resources/chromeos/parent_access/BUILD.gn b/chrome/browser/resources/chromeos/parent_access/BUILD.gn
index ab528e5..5e8d347f 100644
--- a/chrome/browser/resources/chromeos/parent_access/BUILD.gn
+++ b/chrome/browser/resources/chromeos/parent_access/BUILD.gn
@@ -20,6 +20,7 @@
   deps = [
     ":parent_access_after",
     ":parent_access_app",
+    ":parent_access_before",
     ":parent_access_controller",
     ":parent_access_ui",
     ":parent_access_ui_handler",
@@ -38,9 +39,18 @@
       [ "//ui/webui/resources/cr_elements/cr_button/cr_button_externs.js" ]
 }
 
+js_library("parent_access_before") {
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+  externs_list =
+      [ "//ui/webui/resources/cr_elements/cr_button/cr_button_externs.js" ]
+}
+
 js_library("parent_access_app") {
   deps = [
     ":parent_access_after",
+    ":parent_access_before",
     ":parent_access_ui",
     ":parent_access_ui_handler",
     "//chrome/browser/resources/chromeos/supervision:supervised_user_error",
@@ -84,6 +94,7 @@
   js_files = [
     "parent_access_after.js",
     "parent_access_app.js",
+    "parent_access_before.js",
     "parent_access_ui.js",
   ]
 }
diff --git a/chrome/browser/resources/chromeos/parent_access/images/request_approval.svg b/chrome/browser/resources/chromeos/parent_access/images/request_approval.svg
new file mode 100644
index 0000000..ec60e0b
--- /dev/null
+++ b/chrome/browser/resources/chromeos/parent_access/images/request_approval.svg
@@ -0,0 +1 @@
+<svg width="224" height="224" viewBox="0 0 224 224" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><path d="M79.108 205.546c-48.664-12.62-70.19-68.16-59.058-111.222C31.185 51.27 75.444 19.71 124.11 32.34c48.664 12.62 81.185 58.943 70.053 102.006-11.132 43.062-66.398 83.832-115.053 71.208l-.003-.009Z" fill="#F2F2F2"/><path d="m107.077 55.103-54.793 11.27c-16.813 3.458-27.64 19.891-24.181 36.704l11.27 54.793c3.458 16.813 19.891 27.639 36.704 24.181l54.793-11.27c16.813-3.458 27.639-19.891 24.181-36.704l-11.27-54.793c-3.458-16.813-19.891-27.64-36.704-24.181Z" fill="#C2E7FF"/><path d="M92.55 102.457c5.725-3.327 7.668-10.664 4.341-16.388-3.326-5.724-10.663-7.668-16.387-4.341s-7.668 10.664-4.341 16.388c3.327 5.724 10.664 7.667 16.388 4.341Z" fill="#3998D3"/><path fill-rule="evenodd" clip-rule="evenodd" d="M80.68 82.03c-5.557 3.23-7.444 10.353-4.215 15.91 3.23 5.557 10.353 7.444 15.91 4.214 5.557-3.23 7.443-10.352 4.214-15.91-3.23-5.556-10.352-7.443-15.91-4.213Zm-4.82 16.262c-3.424-5.892-1.423-13.443 4.468-16.867 5.891-3.423 13.442-1.423 16.866 4.468 3.424 5.891 1.424 13.443-4.468 16.866-5.89 3.424-13.442 1.424-16.866-4.467Z" fill="#000"/><path d="M89.022 107.891c-11.853 1.863-29 8.628-25.573 30.336 1.675 10.586 6.912 16.316 13.174 19.129 4.746 2.117 10.056 2.663 14.913 2.461 2.966-.148 5.221-2.802 4.759-5.768-.4-2.57-2.707-4.314-5.313-4.176-6.257.336-10.251-1.058-12.788-3.083 3.132-6.083 9.97-8.415 15.499-9.289 5.528-.875 12.745-.757 17.594 4.021 1.817 1.813 3.345 4.242 4.266 7.538.27.921 1.511 1.145 2.173.429 4.094-4.569 6.484-11.215 5.009-20.574-3.469-21.75-21.867-22.9-33.72-21.037l.007.013Zm4.057 25.671c-4.346.685-8.46-2.314-9.145-6.66-.684-4.345 2.315-8.46 6.66-9.144 4.345-.685 8.46 2.314 9.144 6.66.685 4.345-2.314 8.46-6.66 9.144Z" fill="#3998D3"/><path fill-rule="evenodd" clip-rule="evenodd" d="M88.868 107.561a.328.328 0 0 1 .093-.028c5.954-.936 13.593-1.124 20.195 1.687 6.631 2.822 12.172 8.651 13.925 19.64 1.49 9.452-.922 16.207-5.095 20.863l-.003.003c-.82.887-2.409.652-2.766-.567l-.001-.005c-.905-3.238-2.402-5.614-4.175-7.384-4.724-4.653-11.79-4.794-17.294-3.923-5.424.858-11.996 3.111-15.106 8.847 2.463 1.862 6.314 3.152 12.322 2.83 2.773-.147 5.249 1.71 5.678 4.472.496 3.178-1.922 6.012-5.087 6.17h-.003c-4.89.204-10.258-.344-15.07-2.491h-.002c-6.376-2.864-11.684-8.698-13.375-19.393-1.732-10.968 1.737-18.208 7.172-22.929 5.382-4.674 12.656-6.847 18.592-7.792Zm.301.648a.362.362 0 0 1-.092.028c-5.899.927-13.074 3.069-18.342 7.645-5.245 4.555-8.636 11.55-6.94 22.29 1.657 10.478 6.824 16.103 12.97 18.864 4.68 2.088 9.93 2.632 14.755 2.431 2.766-.139 4.859-2.612 4.43-5.364h-.001c-.37-2.38-2.508-4.01-4.948-3.88-6.316.338-10.403-1.067-13.025-3.16a.35.35 0 0 1-.093-.433c3.213-6.24 10.203-8.597 15.755-9.475 5.553-.878 12.92-.784 17.895 4.117l.002.002c1.86 1.856 3.418 4.338 4.354 7.69.184.62 1.074.832 1.578.289 4.016-4.482 6.383-11.019 4.922-20.283-1.716-10.762-7.108-16.383-13.507-19.106-6.391-2.721-13.83-2.569-19.713-1.655Zm1.48 9.895c-4.155.654-7.023 4.59-6.369 8.744.654 4.155 4.59 7.023 8.744 6.368 4.155-.654 7.023-4.59 6.369-8.744-.655-4.155-4.59-7.023-8.745-6.368Zm-7.06 8.853c-.715-4.537 2.415-8.83 6.95-9.545 4.537-.715 8.83 2.415 9.545 6.951.715 4.537-2.415 8.83-6.95 9.545-4.537.715-8.83-2.415-9.546-6.951Z" fill="#000"/><path d="M65.363 182.723c-12.748-1.837-23.597-11.462-26.335-24.788l-11.263-54.786c-1.695-8.226-.083-16.611 4.544-23.623 4.617-7.014 11.693-11.804 19.918-13.498l54.786-11.264c16.982-3.495 33.627 7.48 37.123 24.453l11.273 54.787c3.495 16.981-7.48 33.627-24.452 37.123l-.072-.344.072.344L76.17 182.4a31.417 31.417 0 0 1-10.787.326l-.02-.003ZM117.691 55.12a30.748 30.748 0 0 0-10.543.32L52.361 66.714c-8.038 1.65-14.957 6.342-19.47 13.198-4.515 6.857-6.09 15.056-4.44 23.104l11.273 54.787c3.419 16.597 19.695 27.327 36.292 23.908l54.787-11.273c16.597-3.419 27.328-19.695 23.909-36.292l-11.274-54.787c-2.68-13.026-13.285-22.444-25.747-24.239Z" fill="#000"/><path d="m183.184 33.593-39.949-5.643C131.497 26.294 115.901 44.89 109 54.5l-2 .5c-3 17 8.989 32.453 25.455 34.779l1.022.144-1.022 9.48c-.344 2.432 2.252 4.189 4.383 2.973l1.948-1.048s44.109-68.12 44.398-67.735Z" fill="#000"/><path d="m183.184 33.593-39.949-5.643c-16.45-2.323-31.686 9.128-34.011 25.594-2.324 16.45 9.127 31.686 25.593 34.012l1.022.144-1.45 10.27c-.344 2.432 2.252 4.189 4.383 2.973l18.12-10.285 17.86 2.522c16.451 2.324 31.687-9.127 34.012-25.593 2.324-16.45-9.127-31.687-25.593-34.012l.013.018Z" fill="#1B6EF3"/><path fill-rule="evenodd" clip-rule="evenodd" d="M183.967 34.053c15.819 2.692 26.707 17.509 24.451 33.485-2.299 16.274-17.358 27.592-33.617 25.296l-17.978-2.54-18.224 10.344c-1.879 1.072-4.166-.476-3.864-2.62l1.5-10.616-1.369-.193c-16.274-2.299-27.592-17.357-25.296-33.616 2.299-16.275 17.358-27.593 33.617-25.296l40.783 5.76-.003-.004Zm-1.569-.925-.014-.018.836.118c16.657 2.353 28.241 17.766 25.891 34.408-2.353 16.657-17.766 28.241-34.408 25.89l-17.742-2.505-18.016 10.226c-2.383 1.359-5.287-.606-4.903-3.326l1.402-9.923-.676-.096c-16.657-2.353-28.241-17.766-25.891-34.407 2.353-16.658 17.766-28.242 34.407-25.891l39.114 5.524Z" fill="#000"/><path d="M140.337 64.353a6.32 6.32 0 1 1 1.768-12.516 6.32 6.32 0 0 1-1.768 12.516ZM158.151 66.87a6.32 6.32 0 1 1 1.768-12.517 6.32 6.32 0 0 1-1.768 12.516ZM175.964 69.385a6.32 6.32 0 1 1 1.768-12.516 6.32 6.32 0 0 1-1.768 12.516Z" fill="#ECF3FE"/><path fill-rule="evenodd" clip-rule="evenodd" d="M169.184 186.798a.35.35 0 0 1-.482-.114l-10-16.134a.35.35 0 0 1 .595-.369l10 16.135a.35.35 0 0 1-.113.482ZM194.624 149.846a.35.35 0 0 1-.356.344l-21.555-.378a.35.35 0 0 1 .012-.7l21.556.378a.349.349 0 0 1 .343.356ZM196.301 175.539a.35.35 0 0 1-.467.164l-29.985-14.387a.35.35 0 0 1 .302-.632l29.985 14.388a.35.35 0 0 1 .165.467Z" fill="#000"/></g><defs><clipPath id="a"><rect width="224" height="224" rx="28" fill="#fff"/></clipPath></defs></svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/parent_access/images/request_approval_dark.svg b/chrome/browser/resources/chromeos/parent_access/images/request_approval_dark.svg
new file mode 100644
index 0000000..47218b2
--- /dev/null
+++ b/chrome/browser/resources/chromeos/parent_access/images/request_approval_dark.svg
@@ -0,0 +1 @@
+<svg width="224" height="224" viewBox="0 0 224 224" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><path d="M79.108 205.546c-48.664-12.62-70.19-68.16-59.058-111.222C31.185 51.27 75.444 19.71 124.11 32.34c48.664 12.62 81.185 58.943 70.053 102.006-11.132 43.062-66.398 83.832-115.053 71.208l-.003-.009Z" fill="#474747"/><path d="m107.077 55.103-54.793 11.27c-16.813 3.458-27.64 19.891-24.181 36.704l11.27 54.793c3.458 16.813 19.891 27.639 36.704 24.181l54.793-11.27c16.813-3.458 27.639-19.891 24.181-36.704l-11.27-54.793c-3.458-16.813-19.891-27.64-36.704-24.181Z" fill="#00639B"/><path d="M92.55 102.457c5.725-3.327 7.668-10.664 4.341-16.388-3.326-5.724-10.663-7.668-16.387-4.341s-7.668 10.664-4.341 16.388c3.327 5.724 10.664 7.667 16.388 4.341Z" fill="#7FCFFF"/><path fill-rule="evenodd" clip-rule="evenodd" d="M80.68 82.03c-5.557 3.23-7.444 10.353-4.215 15.91 3.23 5.557 10.353 7.444 15.91 4.214 5.557-3.23 7.443-10.352 4.214-15.91-3.23-5.556-10.352-7.443-15.91-4.213Zm-4.82 16.262c-3.424-5.892-1.423-13.443 4.468-16.867 5.891-3.423 13.442-1.423 16.866 4.468 3.424 5.891 1.424 13.443-4.468 16.866-5.89 3.424-13.442 1.424-16.866-4.467Z" fill="#000"/><path d="M89.022 107.891c-11.853 1.863-29 8.628-25.573 30.336 1.675 10.586 6.912 16.316 13.174 19.129 4.746 2.117 10.056 2.663 14.913 2.461 2.966-.148 5.221-2.802 4.759-5.768-.4-2.57-2.707-4.314-5.313-4.176-6.257.336-10.251-1.058-12.788-3.083 3.132-6.083 9.97-8.415 15.499-9.289 5.528-.875 12.745-.757 17.594 4.021 1.817 1.813 3.345 4.242 4.266 7.538.27.921 1.511 1.145 2.173.429 4.094-4.569 6.484-11.215 5.009-20.574-3.469-21.75-21.867-22.9-33.72-21.037l.007.013Zm4.057 25.671c-4.346.685-8.46-2.314-9.145-6.66-.684-4.345 2.315-8.46 6.66-9.144 4.345-.685 8.46 2.314 9.144 6.66.685 4.345-2.314 8.46-6.66 9.144Z" fill="#7FCFFF"/><path fill-rule="evenodd" clip-rule="evenodd" d="M88.868 107.561a.328.328 0 0 1 .093-.028c5.954-.936 13.593-1.124 20.195 1.687 6.631 2.822 12.172 8.651 13.925 19.64 1.49 9.452-.922 16.207-5.095 20.863l-.003.003c-.82.887-2.409.652-2.766-.567l-.001-.005c-.905-3.238-2.402-5.614-4.175-7.384-4.724-4.653-11.79-4.794-17.294-3.923-5.424.858-11.996 3.111-15.106 8.847 2.463 1.862 6.314 3.152 12.322 2.83 2.773-.147 5.249 1.71 5.678 4.472.496 3.178-1.922 6.012-5.087 6.17h-.003c-4.89.204-10.258-.344-15.07-2.491h-.002c-6.376-2.864-11.684-8.698-13.375-19.393-1.732-10.968 1.737-18.208 7.172-22.929 5.382-4.674 12.656-6.847 18.592-7.792Zm.301.648a.362.362 0 0 1-.092.028c-5.899.927-13.074 3.069-18.342 7.645-5.245 4.555-8.636 11.55-6.94 22.29 1.657 10.478 6.824 16.103 12.97 18.864 4.68 2.088 9.93 2.632 14.755 2.431 2.766-.139 4.859-2.612 4.43-5.364h-.001c-.37-2.38-2.508-4.01-4.948-3.88-6.316.338-10.403-1.067-13.025-3.16a.35.35 0 0 1-.093-.433c3.213-6.24 10.203-8.597 15.755-9.475 5.553-.878 12.92-.784 17.895 4.117l.002.002c1.86 1.856 3.418 4.338 4.354 7.69.184.62 1.074.832 1.578.289 4.016-4.482 6.383-11.019 4.922-20.283-1.716-10.762-7.108-16.383-13.507-19.106-6.391-2.721-13.83-2.569-19.713-1.655Zm1.48 9.895c-4.155.654-7.023 4.59-6.369 8.744.654 4.155 4.59 7.023 8.744 6.368 4.155-.654 7.023-4.59 6.369-8.744-.655-4.155-4.59-7.023-8.745-6.368Zm-7.06 8.853c-.715-4.537 2.415-8.83 6.95-9.545 4.537-.715 8.83 2.415 9.545 6.951.715 4.537-2.415 8.83-6.95 9.545-4.537.715-8.83-2.415-9.546-6.951Z" fill="#000"/><path d="M65.363 182.723c-12.748-1.837-23.597-11.462-26.335-24.788l-11.263-54.786c-1.695-8.226-.083-16.611 4.544-23.623 4.617-7.014 11.693-11.804 19.918-13.498l54.786-11.264c16.982-3.495 33.627 7.48 37.123 24.453l11.273 54.787c3.495 16.981-7.48 33.627-24.452 37.123l-.072-.344.072.344L76.17 182.4a31.417 31.417 0 0 1-10.787.326l-.02-.003ZM117.691 55.12a30.748 30.748 0 0 0-10.543.32L52.361 66.714c-8.038 1.65-14.957 6.342-19.47 13.198-4.515 6.857-6.09 15.056-4.44 23.104l11.273 54.787c3.419 16.597 19.695 27.327 36.292 23.908l54.787-11.273c16.597-3.419 27.328-19.695 23.909-36.292l-11.274-54.787c-2.68-13.026-13.285-22.444-25.747-24.239Z" fill="#000"/><path d="m183.184 33.593-39.949-5.643C131.497 26.294 115.901 44.89 109 54.5l-2 .5c-3 17 8.989 32.453 25.455 34.779l1.022.144-1.022 9.48c-.344 2.432 2.252 4.189 4.383 2.973l1.948-1.048s44.109-68.12 44.398-67.735Z" fill="#000"/><path d="m183.184 33.593-39.949-5.643c-16.45-2.323-31.686 9.128-34.011 25.594-2.324 16.45 9.127 31.686 25.593 34.012l1.022.144-1.45 10.27c-.344 2.432 2.252 4.189 4.383 2.973l18.12-10.285 17.86 2.522c16.451 2.324 31.687-9.127 34.012-25.593 2.324-16.45-9.127-31.687-25.593-34.012l.013.018Z" fill="#4C8DF6"/><path fill-rule="evenodd" clip-rule="evenodd" d="M183.967 34.053c15.819 2.692 26.707 17.509 24.451 33.485-2.299 16.274-17.358 27.592-33.617 25.296l-17.978-2.54-18.224 10.344c-1.879 1.072-4.166-.476-3.864-2.62l1.5-10.616-1.369-.193c-16.274-2.299-27.592-17.357-25.296-33.616 2.299-16.275 17.358-27.593 33.617-25.296l40.783 5.76-.003-.004Zm-1.569-.925-.014-.018.836.118c16.657 2.353 28.241 17.766 25.891 34.408-2.353 16.657-17.766 28.241-34.408 25.89l-17.742-2.505-18.016 10.226c-2.383 1.359-5.287-.606-4.903-3.326l1.402-9.923-.676-.096c-16.657-2.353-28.241-17.766-25.891-34.407 2.353-16.658 17.766-28.242 34.407-25.891l39.114 5.524Z" fill="#000"/><path d="M140.337 64.353a6.32 6.32 0 1 1 1.768-12.516 6.32 6.32 0 0 1-1.768 12.516ZM158.151 66.87a6.32 6.32 0 1 1 1.768-12.517 6.32 6.32 0 0 1-1.768 12.516ZM175.964 69.385a6.32 6.32 0 1 1 1.768-12.516 6.32 6.32 0 0 1-1.768 12.516Z" fill="#0842A0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M169.184 186.798a.35.35 0 0 1-.482-.114l-10-16.134a.35.35 0 0 1 .595-.369l10 16.135a.35.35 0 0 1-.113.482ZM194.624 149.846a.35.35 0 0 1-.356.344l-21.555-.378a.35.35 0 0 1 .012-.7l21.556.378a.349.349 0 0 1 .343.356ZM196.301 175.539a.35.35 0 0 1-.467.164l-29.985-14.387a.35.35 0 0 1 .302-.632l29.985 14.388a.35.35 0 0 1 .165.467Z" fill="#FDFCFB"/></g><defs><clipPath id="a"><rect width="224" height="224" rx="28" fill="#fff"/></clipPath></defs></svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/parent_access/parent_access_app.html b/chrome/browser/resources/chromeos/parent_access/parent_access_app.html
index 84bed38..aa9fd85 100644
--- a/chrome/browser/resources/chromeos/parent_access/parent_access_app.html
+++ b/chrome/browser/resources/chromeos/parent_access/parent_access_app.html
@@ -1,4 +1,6 @@
 <cr-view-manager id="viewManager">
+    <parent-access-before id="parent-access-before" slot="view">
+    </parent-access-before>
     <parent-access-ui id="parent-access-ui" slot="view">
     </parent-access-ui>
     <parent-access-after id="parent-access-after" slot="view">
diff --git a/chrome/browser/resources/chromeos/parent_access/parent_access_app.js b/chrome/browser/resources/chromeos/parent_access/parent_access_app.js
index 44d6db4..702c18d 100644
--- a/chrome/browser/resources/chromeos/parent_access/parent_access_app.js
+++ b/chrome/browser/resources/chromeos/parent_access/parent_access_app.js
@@ -7,9 +7,10 @@
 // into |loadTimeData|.
 import './strings.m.js';
 import './parent_access_after.js';
+import './parent_access_before.js';
+import './parent_access_ui.js';
 import './supervision/supervised_user_error.js';
 import './supervision/supervised_user_offline.js';
-import './parent_access_ui.js';
 import 'chrome://resources/cr_elements/cr_view_manager/cr_view_manager.js';
 
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
@@ -19,7 +20,8 @@
 
 /** @enum {string} */
 export const Screens = {
-  ONLINE_FLOW: 'parent-access-ui',
+  AUTHENTICATION_FLOW: 'parent-access-ui',
+  BEFORE_FLOW: 'parent-access-before',
   AFTER_FLOW: 'parent-access-after',
   ERROR: 'supervised-user-error',
   OFFLINE: 'supervised-user-offline',
@@ -42,7 +44,7 @@
        */
       currentScreen_: {
         type: Screens,
-        value: Screens.ONLINE_FLOW,
+        value: Screens.AUTHENTICATION_FLOW,
       },
     };
   }
@@ -57,13 +59,19 @@
       this.shadowRoot.querySelector('parent-access-after').onShowAfterScreen();
     });
 
+    this.addEventListener('show-authentication-flow', () => {
+      this.currentScreen_ = Screens.AUTHENTICATION_FLOW;
+      /** @type {CrViewManagerElement} */ (this.$.viewManager)
+          .switchView(this.currentScreen_);
+    });
+
     this.addEventListener('show-error', () => {
       this.onError_();
     });
 
     window.addEventListener('online', () => {
       if (this.currentScreen_ !== Screens.ERROR) {
-        this.currentScreen_ = Screens.ONLINE_FLOW;
+        this.currentScreen_ = this.getInitialScreen_();
         /** @type {CrViewManagerElement} */ (this.$.viewManager)
             .switchView(this.currentScreen_);
       }
@@ -78,11 +86,17 @@
     });
 
     this.currentScreen_ =
-        navigator.onLine ? Screens.ONLINE_FLOW : Screens.OFFLINE;
+        navigator.onLine ? this.getInitialScreen_() : Screens.OFFLINE;
     /** @type {CrViewManagerElement} */ (this.$.viewManager)
         .switchView(this.currentScreen_);
   }
 
+  getInitialScreen_() {
+    // TODO(b/262448394): Implement logic to check if the before screen should
+    // be shown instead of the authentication flow.
+    return Screens.AUTHENTICATION_FLOW;
+  }
+
   /**
    * Shows an error screen, which is a terminal state for the flow.
    * @private
diff --git a/chrome/browser/resources/chromeos/parent_access/parent_access_before.html b/chrome/browser/resources/chromeos/parent_access/parent_access_before.html
new file mode 100644
index 0000000..3fed7535
--- /dev/null
+++ b/chrome/browser/resources/chromeos/parent_access/parent_access_before.html
@@ -0,0 +1,42 @@
+<style>
+  .action-button {
+    margin-inline-start: 8px;
+  }
+
+  #before-screen {
+    background-color: var(--cros-bg-color-elevation-1);
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+    justify-content: flex-start;
+    padding: 26px 24px 20px;
+  }
+
+  #before-screen-buttons {
+    display: flex;
+    /* Allows the button that appears first visually to be last in tab order */
+    flex-direction: row-reverse;
+    margin-top: auto; /* position at end of flexbox */
+    width: 100%;
+  }
+
+  #illustration {
+    height: 96px;
+    width: 96px;
+  }
+</style>
+
+<div id="before-screen">
+  <picture>
+    <source srcset="images/request_approval_dark.svg"
+        media="(prefers-color-scheme: dark)">
+    <img src="images/request_approval.svg" id="illustration">
+  </picture>
+  <div id="befpre-screen-body" aria-live="polite"></div>
+  <div id="before-screen-buttons">
+    <cr-button class="action-button" on-click="showParentAccessUI_">
+      $i18n{askInPersonButtonText}
+    </cr-button>
+  </div>
+</div>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/parent_access/parent_access_before.js b/chrome/browser/resources/chromeos/parent_access/parent_access_before.js
new file mode 100644
index 0000000..8d89f9e
--- /dev/null
+++ b/chrome/browser/resources/chromeos/parent_access/parent_access_before.js
@@ -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.
+
+import 'chrome://resources/cr_elements/cr_button/cr_button.js';
+
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+class ParentAccessBefore extends PolymerElement {
+  constructor() {
+    super();
+  }
+
+  static get is() {
+    return 'parent-access-before';
+  }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
+
+  /** @override */
+  ready() {
+    super.ready();
+  }
+
+  /** @private */
+  showParentAccessUI_() {
+    this.dispatchEvent(new CustomEvent('show-authentication-flow', {
+      bubbles: true,
+      composed: true,
+    }));
+  }
+}
+
+customElements.define(ParentAccessBefore.is, ParentAccessBefore);
diff --git a/chrome/browser/resources/chromeos/supervision/OWNERS b/chrome/browser/resources/chromeos/supervision/OWNERS
new file mode 100644
index 0000000..faa42f3a
--- /dev/null
+++ b/chrome/browser/resources/chromeos/supervision/OWNERS
@@ -0,0 +1 @@
+file://components/supervised_user/OWNERS
diff --git a/chrome/browser/resources/extensions/manager.ts b/chrome/browser/resources/extensions/manager.ts
index 6cd9f75..81fe22a 100644
--- a/chrome/browser/resources/extensions/manager.ts
+++ b/chrome/browser/resources/extensions/manager.ts
@@ -31,6 +31,7 @@
 import {CrViewManagerElement} from 'chrome://resources/cr_elements/cr_view_manager/cr_view_manager.js';
 import {assert, assertNotReached} from 'chrome://resources/js/assert_ts.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
+import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {ActivityLogExtensionPlaceholder} from './activity_log/activity_log.js';
@@ -227,6 +228,7 @@
   private installWarnings_: string[]|null;
   private showOptionsDialog_: boolean;
   private fromActivityLog_: boolean;
+  private pageInitializedResolver_: PromiseResolver<void>;
 
   // <if expr="chromeos_ash">
   private kioskEnabled_: boolean;
@@ -250,6 +252,12 @@
      * listener can be removed when this element is detached (happens in tests).
      */
     this.navigationListener_ = null;
+
+    /**
+     * A promise resolver for any external files waiting for initPage_ to be
+     * called after the extensions info has been fetched.
+     */
+    this.pageInitializedResolver_ = new PromiseResolver();
   }
 
   override ready() {
@@ -310,12 +318,21 @@
   }
 
   /**
+   * @return the promise of `pageInitializedResolver_` so tests can wait for the
+   * page to be initialized.
+   */
+  whenPageInitializedForTest(): Promise<void> {
+    return this.pageInitializedResolver_.promise;
+  }
+
+  /**
    * Initializes the page to reflect what's specified in the url so that if
    * the user visits chrome://extensions/?id=..., we land on the proper page.
    */
   private initPage_() {
     this.didInitPage_ = true;
     this.changePage_(navigation.getCurrentPage());
+    this.pageInitializedResolver_.resolve();
   }
 
   private onItemStateChanged_(eventData: chrome.developerPrivate.EventData) {
diff --git a/chrome/browser/resources/new_tab_page/app.ts b/chrome/browser/resources/new_tab_page/app.ts
index 0e5bff5c..6f2ebdfb 100644
--- a/chrome/browser/resources/new_tab_page/app.ts
+++ b/chrome/browser/resources/new_tab_page/app.ts
@@ -324,8 +324,7 @@
   private pageHandler_: PageHandlerRemote;
   private backgroundManager_: BackgroundManager;
   private setThemeListenerId_: number|null = null;
-  private customizeChromeSidePanelVisibilityChangedListener_: number|null =
-      null;
+  private setCustomizeChromeSidePanelVisibilityListener_: number|null = null;
   private eventTracker_: EventTracker = new EventTracker();
   private shouldPrintPerformance_: boolean;
   private backgroundImageLoadStartEpoch_: number;
@@ -366,10 +365,9 @@
           performance.measure('theme-set');
           this.theme_ = theme;
         });
-    this.customizeChromeSidePanelVisibilityChangedListener_ =
-        this.callbackRouter_.customizeChromeSidePanelVisibilityChanged
-            .addListener(
-                this.onCustomizeChromeSidePanelVisibilityChanged_.bind(this));
+    this.setCustomizeChromeSidePanelVisibilityListener_ =
+        this.callbackRouter_.setCustomizeChromeSidePanelVisibility.addListener(
+            this.onCustomizeChromeSidePanelVisibilityChanged_.bind(this));
     this.eventTracker_.add(window, 'message', (event: MessageEvent) => {
       const data = event.data;
       // Something in OneGoogleBar is sending a message that is received here.
@@ -409,7 +407,7 @@
     super.disconnectedCallback();
     this.callbackRouter_.removeListener(this.setThemeListenerId_!);
     this.callbackRouter_.removeListener(
-        this.customizeChromeSidePanelVisibilityChangedListener_!);
+        this.setCustomizeChromeSidePanelVisibilityListener_!);
     this.eventTracker_.removeAll();
   }
 
diff --git a/chrome/browser/resources/settings/chromeos/device_page/audio.html b/chrome/browser/resources/settings/chromeos/device_page/audio.html
index 922509b3..e2de3f1 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/audio.html
+++ b/chrome/browser/resources/settings/chromeos/device_page/audio.html
@@ -72,39 +72,6 @@
   <div id="output">
     <h2 id="audioOutputTitle">$i18n{audioOutputTitle}</h2>
     <div id="audioOutputSubsection" class="subsection">
-      <div id="outputVolumeSubsection" class="settings-box">
-        <div class="start settings-box-text" id="audioOutputVolumeLabel">
-          $i18n{audioVolumeTitle}
-        </div>
-        <!-- TODO(crbug.com/1092970): Update to new UI once approved. -->
-        <div class="audio-output-options-container">
-          <div class="audio-mute-button-container">
-            <cr-icon-button class="audio-mute-button"
-                id="audioOutputMuteButton" iron-icon="settings:volume-up-off"
-                on-click="onOutputMuteButtonClicked">
-            </cr-icon-button>
-          </div>
-          <div class="audio-slider-wrapper" id="audioOutputSliderWrapper">
-            <!-- TODO(crbug.com/1092970): Change icons to buttons. -->
-            <iron-icon id="audioOutputSliderVolumeDownIcon"
-                icon="settings:volume-down">
-            </iron-icon>
-            <cr-slider class="audio-output-slider"
-                id ="outputVolumeSlider"
-                min="0"
-                max="100"
-                disabled="[[isOutputVolumeSliderDisabled_(
-                    audioSystemProperties_.outputMuteState
-                  )]]"
-                value="[[audioSystemProperties_.outputVolumePercent]]"
-                on-cr-slider-value-changed="onOutputVolumeSliderChanged_">
-            </cr-slider>
-            <iron-icon id="audioOutputSliderVolumeUpIcon"
-                icon="settings:volume-up">
-            </iron-icon>
-          </div>
-        </div>
-      </div>
       <div id="outputDeviceSubsection" class="settings-box">
         <div class="start settings-box-text" id="audioOutputDeviceLabel">
           $i18n{audioDeviceTitle}
@@ -120,6 +87,32 @@
           </template>
         </select>
       </div>
+      <div id="outputVolumeSubsection" class="settings-box">
+        <div class="start settings-box-text" id="audioOutputVolumeLabel">
+          $i18n{audioVolumeTitle}
+        </div>
+        <!-- TODO(crbug.com/1092970): Update to new UI once approved. -->
+        <div class="audio-output-options-container">
+          <div class="audio-mute-button-container">
+            <cr-icon-button class="audio-mute-button"
+                id="audioOutputMuteButton" iron-icon="settings:volume-up-off"
+                on-click="onOutputMuteButtonClicked">
+            </cr-icon-button>
+          </div>
+          <div class="audio-slider-wrapper" id="audioOutputSliderWrapper">
+            <cr-slider class="audio-output-slider"
+                id ="outputVolumeSlider"
+                min="0"
+                max="100"
+                disabled="[[isOutputVolumeSliderDisabled_(
+                    audioSystemProperties_.outputMuteState
+                  )]]"
+                value="[[audioSystemProperties_.outputVolumePercent]]"
+                on-cr-slider-value-changed="onOutputVolumeSliderChanged_">
+            </cr-slider>
+          </div>
+        </div>
+      </div>
     </div>
     <!--TODO(b/260277007): Replace placeholder text when localization strings
       available. Add styling. -->
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.html b/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.html
index f213dd0a..6115e0ab 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.html
+++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.html
@@ -90,14 +90,12 @@
       </cr-policy-indicator>
     </template>
   </div>
-  <template is="dom-if" if="[[isCaptivePortalUI2022Enabled_]]">
-    <cr-button class="signin-button" id="signinButton" on-click="onSigninTap_"
+  <cr-button class="signin-button" id="signinButton" on-click="onSigninTap_"
       hidden$="[[!showSignin_(managedProperties_)]]"
       disabled="[[disableSignin_(managedProperties_, disabled_)]]">
-      <div class="signin-icon cr-icon icon-external"></div>
+    <div class="signin-icon cr-icon icon-external"></div>
       $i18n{networkButtonSignin}
-    </cr-button>
-  </template>
+  </cr-button>
   <cr-button id="forgetButton" on-click="onForgetTap_"
       hidden$="[[!showForget_(managedProperties_)]]"
       disabled="[[disableForget_(managedProperties_,
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.ts b/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.ts
index 3937f1b..87d4810 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.ts
+++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.ts
@@ -291,14 +291,6 @@
         },
       },
 
-      isCaptivePortalUI2022Enabled_: {
-        type: Boolean,
-        value() {
-          return loadTimeData.valueExists('captivePortalUI2022') &&
-              loadTimeData.getBoolean('captivePortalUI2022');
-        },
-      },
-
       isApnRevampEnabled_: {
         type: Boolean,
         value() {
@@ -380,7 +372,6 @@
   private hiddenPref_: chrome.settingsPrivate.PrefObject<boolean>;
   private ipAddress_: string;
   private isApnRevampEnabled_: boolean;
-  private isCaptivePortalUI2022Enabled_: boolean;
   private isSecondaryUser_: boolean;
   private isTrafficCountersEnabled_: boolean;
   private isWifiSyncEnabled_: boolean;
@@ -1069,8 +1060,7 @@
           this.i18n('networkOutOfRange');
     }
 
-    if (this.isCaptivePortalUI2022Enabled_ &&
-        OncMojo.connectionStateIsConnected(managedProperties.connectionState)) {
+    if (OncMojo.connectionStateIsConnected(managedProperties.connectionState)) {
       if (this.isPortalState_(managedProperties.portalState)) {
         return this.i18n('networkListItemSignIn');
       }
@@ -1107,22 +1097,12 @@
 
   private showConnectedState_(managedProperties: ManagedProperties|
                               undefined): boolean {
-    // Only check that state is connected if feature flag is disabled.
-    if (!this.isCaptivePortalUI2022Enabled_) {
-      return this.isConnectedState_(managedProperties);
-    }
-
     return this.isConnectedState_(managedProperties) &&
         !this.isRestrictedConnectivity_(managedProperties);
   }
 
   private showRestrictedConnectivity_(managedProperties: ManagedProperties|
                                       undefined): boolean {
-    // Do not show warning color if feature flag is disabled.
-    if (!this.isCaptivePortalUI2022Enabled_) {
-      return false;
-    }
-
     if (!managedProperties) {
       return false;
     }
@@ -1249,9 +1229,6 @@
   }
 
   private showSignin_(managedProperties: ManagedProperties|undefined): boolean {
-    if (!this.isCaptivePortalUI2022Enabled_) {
-      return false;
-    }
     if (!managedProperties) {
       return false;
     }
@@ -1329,9 +1306,6 @@
 
   private disableSignin_(managedProperties: ManagedProperties|
                          undefined): boolean {
-    if (!this.isCaptivePortalUI2022Enabled_) {
-      return true;
-    }
     if (this.disabled_ || !managedProperties) {
       return true;
     }
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.ts b/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.ts
index ffdc621..242b61b 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.ts
+++ b/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.ts
@@ -96,17 +96,6 @@
         },
       },
 
-      /**
-       * Return true if captivePortalUI2022 feature flag is enabled.
-       */
-      isCaptivePortalUI2022Enabled_: {
-        type: Boolean,
-        value() {
-          return loadTimeData.valueExists('captivePortalUI2022') &&
-              loadTimeData.getBoolean('captivePortalUI2022');
-        },
-      },
-
       globalPolicy: Object,
     };
   }
@@ -118,7 +107,6 @@
   networkTitleText: string|undefined;
   tetherDeviceState: OncMojo.DeviceStateProperties|undefined;
   private browserProxy_: InternetPageBrowserProxy;
-  private isCaptivePortalUI2022Enabled_: boolean;
   private showTechnologyBadge_: boolean;
 
   constructor() {
@@ -141,8 +129,7 @@
       return this.i18n('internetDeviceBusy');
     }
 
-    if (this.isCaptivePortalUI2022Enabled_ &&
-        this.isPortalState_(this.activeNetworkState!.portalState)) {
+    if (this.isPortalState_(this.activeNetworkState!.portalState)) {
       return this.i18n('networkListItemSignIn');
     }
 
@@ -236,8 +223,7 @@
   private getNetworkStateClass_(
       activeNetworkState: OncMojo.NetworkStateProperties|undefined,
       deviceState: OncMojo.DeviceStateProperties|undefined): string {
-    if ((this.isCaptivePortalUI2022Enabled_ &&
-         this.isPortalState_(activeNetworkState!.portalState)) ||
+    if ((this.isPortalState_(activeNetworkState!.portalState)) ||
         this.shouldShowLockedWarningMessage_(deviceState)) {
       return 'warning-message';
     }
@@ -468,9 +454,7 @@
             });
         this.dispatchEvent(deviceEnabledToggledEvent);
       }
-    } else if (
-        this.isCaptivePortalUI2022Enabled_ &&
-        this.isPortalState_(this.activeNetworkState!.portalState)) {
+    } else if (this.isPortalState_(this.activeNetworkState!.portalState)) {
       this.browserProxy_.showPortalSignin(this.activeNetworkState!.guid);
     } else if (this.shouldShowSubpage_(
                    this.deviceState, this.networkStateList)) {
@@ -553,8 +537,7 @@
     }
 
     // Item is actionable if tapping should show the user to the portal signin.
-    if (this.isCaptivePortalUI2022Enabled_ &&
-        this.isPortalState_(this.activeNetworkState!.portalState)) {
+    if (this.isPortalState_(this.activeNetworkState!.portalState)) {
       return true;
     }
 
@@ -606,8 +589,7 @@
     if (this.networkTitleText) {
       return this.networkTitleText;
     }
-    if (this.isCaptivePortalUI2022Enabled_ &&
-        this.isPortalState_(this.activeNetworkState!.portalState)) {
+    if (this.isPortalState_(this.activeNetworkState!.portalState)) {
       const stateText = this.getConnectionStateText_(this.activeNetworkState);
       if (stateText) {
         return stateText;
diff --git a/chrome/browser/resources/side_panel/bookmarks/BUILD.gn b/chrome/browser/resources/side_panel/bookmarks/BUILD.gn
index df7d5c42..07d54a1 100644
--- a/chrome/browser/resources/side_panel/bookmarks/BUILD.gn
+++ b/chrome/browser/resources/side_panel/bookmarks/BUILD.gn
@@ -21,7 +21,6 @@
     "bookmark_folder.ts",
     "bookmarks_list.ts",
     "commerce/shopping_list.ts",
-    "power_bookmark_chip.ts",
     "power_bookmark_row.ts",
     "power_bookmarks_context_menu.ts",
     "power_bookmarks_list.ts",
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmark_chip.html b/chrome/browser/resources/side_panel/bookmarks/power_bookmark_chip.html
deleted file mode 100644
index 968d7abe..0000000
--- a/chrome/browser/resources/side_panel/bookmarks/power_bookmark_chip.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<style>
-  :host {
-    --power-bookmark-chip-background: var(--google-grey-100);
-    --power-bookmark-chip-icon-color: var(--cr-secondary-text-color);
-  }
-
-  @media (prefers-color-scheme: dark) {
-    :host {
-      --power-bookmark-chip-background: var(--google-grey-800);
-      --power-bookmark-chip-icon-color: var(--google-grey-100);
-    }
-  }
-
-  :host ::slotted(iron-icon) {
-    --power-bookmark-chip-icon-size: 13px;
-    color: var(--power-bookmark-chip-icon-color);
-    height: var(--power-bookmark-chip-icon-size);
-    width: var(--power-bookmark-chip-icon-size);
-  }
-
-  .chip {
-    background-color: var(--power-bookmark-chip-background);
-    border-radius: 12px;
-    color: var(--cr-secondary-text-color);
-    display: flex;
-    flex-direction: row;
-    font-size: var(--mwb-secondary-text-font-size);
-    gap: 4px;
-    padding: 2px 6px;
-  }
-</style>
-<div id="chip" class="chip">
-  <slot></slot>
-</div>
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmark_chip.ts b/chrome/browser/resources/side_panel/bookmarks/power_bookmark_chip.ts
deleted file mode 100644
index 235d57c..0000000
--- a/chrome/browser/resources/side_panel/bookmarks/power_bookmark_chip.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'chrome://resources/cr_elements/mwb_shared_vars.css.js';
-import 'chrome://resources/cr_elements/cr_shared_vars.css.js';
-
-import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-import {getTemplate} from './power_bookmark_chip.html.js';
-
-export interface PowerBookmarkChipElement {
-  $: {
-    chip: HTMLDivElement,
-  };
-}
-
-export class PowerBookmarkChipElement extends PolymerElement {
-  static get is() {
-    return 'power-bookmark-chip';
-  }
-
-  static get template() {
-    return getTemplate();
-  }
-
-  static get properties() {
-    return {};
-  }
-}
-
-declare global {
-  interface HTMLElementTagNameMap {
-    'power-bookmark-chip': PowerBookmarkChipElement;
-  }
-}
-
-customElements.define(PowerBookmarkChipElement.is, PowerBookmarkChipElement);
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmark_row.ts b/chrome/browser/resources/side_panel/bookmarks/power_bookmark_row.ts
index c556bbc..1e5f406 100644
--- a/chrome/browser/resources/side_panel/bookmarks/power_bookmark_row.ts
+++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmark_row.ts
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import './power_bookmark_chip.js';
 import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js';
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
 import 'chrome://resources/cr_elements/cr_input/cr_input.js';
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html
index a6ee703..90ab2f5 100644
--- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html
+++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html
@@ -5,9 +5,6 @@
     --disabled-text-color: var(--google-grey-600);
     --edit-footer-background: var(--google-grey-50);
     --label-selected-color: var(--google-blue-50);
-    --price-tracking-chip-background: var(--google-green-50);
-    --price-tracking-discount-color: var(--google-green-800);
-    --price-tracking-original-color: var(--cr-secondary-text-color);
   }
 
   @media (prefers-color-scheme: dark) {
@@ -15,9 +12,6 @@
       --border-color: var(--google-grey-700);
       --disabled-text-color: var(--google-grey-500);
       --edit-footer-background: var(--google-grey-900-white-4-percent);
-      --price-tracking-chip-background: var(--google-green-900);
-      --price-tracking-discount-color: white;
-      --price-tracking-original-color: var(--google-green-200);
     }
   }
 
@@ -66,10 +60,6 @@
     overflow-y: auto;
   }
 
-  .chip-discounted {
-    --power-bookmark-chip-background: var(--price-tracking-chip-background);
-  }
-
   .column {
     display: flex;
     flex-direction: column;
@@ -80,49 +70,10 @@
     gap: 4px;
   }
 
-  .edit-description {
-    align-items: center;
-    color: var(--cr-secondary-text-color);
-    display: flex;
-    gap: 8px;
-  }
-
-  .edit-footer {
-    background-color: var(--edit-footer-background);
-    color: var(--cr-secondary-text-color);
-    display: flex;
-    justify-content: space-between;
-    padding: 14px;
-  }
-
-  .edit-icons {
-    display: flex;
-    gap: 16px;
-  }
-
   sp-empty-state[guest] {
     margin-top: 66px;
   }
 
-  .footer-or-empty-state {
-    border-top: 1px solid var(--border-color);
-  }
-
-  .footer-or-empty-state[empty] {
-    align-items: center;
-    border: none;
-    display: flex;
-    flex-direction: column;
-  }
-
-  .footer-or-empty-state:not([empty]) .footer-button {
-    margin: 8px;
-  }
-
-  .footer-button[disabled] > .label-icon {
-    color: var(--disabled-text-color);
-  }
-
   .heading-row {
     align-items: center;
     display: flex;
@@ -148,10 +99,6 @@
     gap: 8px;
   }
 
-  .icon-discounted {
-    color: var(--price-tracking-discount-color);
-  }
-
   .label {
     align-items: center;
     background-color: transparent;
@@ -178,10 +125,6 @@
     background-color: var(--google-grey-100);
   }
 
-  .label-icon {
-    color: var(--cr-link-color);
-  }
-
   .label-row {
     display: flex;
     flex-direction: row;
@@ -213,6 +156,27 @@
     background-color: var(--cr-active-background-color);
     box-shadow: none;
   }
+
+  cr-toolbar-selection-overlay {
+    --cr-toolbar-selection-overlay-padding: 16px;
+    background: var(--edit-footer-background);
+    color: var(--cr-secondary-text-color);
+    font-size: 12px;
+  }
+
+  cr-toolbar-selection-overlay::part(clearIcon) {
+    --cr-icon-button-icon-size: 16px;
+    height: 24px;
+    margin-inline-end: 8px;
+    margin-inline-start: -6px;
+    width: 24px;
+  }
+
+  @media (prefers-color-scheme: dark) {
+    cr-toolbar-selection-overlay {
+      background: var(--google-grey-900-white-4-percent);
+    }
+  }
 </style>
 
 <div class="column" id="powerBookmarksContainer">
@@ -274,65 +238,55 @@
         <div slot="chips">
           <template is="dom-if"
               if="[[isPriceTracked_(item, showPriceTracking_)]]" restamp>
-            <template is="dom-if" if="[[showDiscountedPrice_(item)]]" restamp>
-              <power-bookmark-chip class="chip-discounted">
-                <iron-icon icon="bookmarks:price-tracking"
-                    class="icon-discounted"></iron-icon>
-                <div class="price-discounted">[[getCurrentPrice_(item)]]</div>
-                <div class="price-original">[[getPreviousPrice_(item)]]</div>
-              </power-bookmark-chip>
-            </template>
-            <template is="dom-if" if="[[!showDiscountedPrice_(item)]]" restamp>
-              <power-bookmark-chip>
-                <iron-icon icon="bookmarks:price-tracking"></iron-icon>
-                <div>[[getCurrentPrice_(item)]]</div>
-              </power-bookmark-chip>
-            </template>
+            <sp-label updated="[[showDiscountedPrice_(item)]]">
+              <iron-icon icon="bookmarks:price-tracking"></iron-icon>
+              <div>[[getCurrentPrice_(item)]]</div>
+              <div slot="previous-label"
+                  hidden$="[[!showDiscountedPrice_(item)]]">
+                [[getPreviousPrice_(item)]]
+              </div>
+            </sp-label>
           </template>
         </div>
       </power-bookmark-row>
     </template>
   </div>
-  <div class="footer-or-empty-state" empty$="[[!shownBookmarks_.length]]">
-    <sp-empty-state
-        hidden="[[shownBookmarks_.length]]"
-        guest$="[[guestMode_]]"
-        image-path="./images/bookmarks_empty.svg"
-        dark-image-path="./images/bookmarks_empty_dark.svg"
-        heading="[[getEmptyTitle_()]]"
-        body="[[getEmptyBody_()]]">
-    </sp-empty-state>
 
-    <cr-button class="footer-button"
+  <sp-empty-state
+      hidden="[[shownBookmarks_.length]]"
+      guest$="[[guestMode_]]"
+      image-path="./images/bookmarks_empty.svg"
+      dark-image-path="./images/bookmarks_empty_dark.svg"
+      heading="[[getEmptyTitle_()]]"
+      body="[[getEmptyBody_()]]">
+  </sp-empty-state>
+  <sp-footer
+      pinned="[[shouldPinFooter_(shownBookmarks_.length)]]">
+    <cr-button
         hidden="[[hideAddTabButton_(editing_)]]"
         on-click="onAddTabClicked_"
         disabled="[[!canAddCurrentUrl_(shownBookmarks_.*, activeFolderPath_.*,
                      currentUrl_)]]">
-      <iron-icon slot="prefix-icon" icon="bookmarks:add-tab" class="label-icon">
-      </iron-icon>
+      <iron-icon slot="prefix-icon" icon="bookmarks:add-tab"></iron-icon>
       $i18n{addCurrentTab}
     </cr-button>
-    <div class="edit-footer" hidden="[[!editing_]]">
-      <div class="edit-description">
-        <cr-icon-button iron-icon="cr:close"
-            aria-label="$i18n{cancelA11yLabel}"
-            on-click="onBulkEditClicked_"></cr-icon-button>
-        [[getSelectedDescription_(selectedBookmarks_.*)]]
-      </div>
-      <div class="edit-icons">
-        <cr-icon-button iron-icon="bookmarks:delete"
-            disabled="[[!selectedBookmarks_.length]]"
-            title="$i18n{tooltipDelete}" aria-label="$i18n{tooltipDelete}"
-            on-click="onDeleteClicked_">
-        </cr-icon-button>
-        <cr-icon-button iron-icon="cr:more-vert"
-            disabled="[[!selectedBookmarks_.length]]"
-            title="$i18n{tooltipMore}" aria-label="$i18n{tooltipMore}"
-            on-click="onEditMenuClicked_">
-        </cr-icon-button>
-      </div>
-    </div>
-  </div>
+
+    <cr-toolbar-selection-overlay show="[[editing_]]"
+        cancel-label="$i18n{cancelA11yLabel}"
+        selection-label="[[getSelectedDescription_(selectedBookmarks_.*)]]"
+        on-clear-selected-items="onBulkEditClicked_">
+      <cr-icon-button iron-icon="bookmarks:delete"
+          disabled="[[!selectedBookmarks_.length]]"
+          title="$i18n{tooltipDelete}" aria-label="$i18n{tooltipDelete}"
+          on-click="onDeleteClicked_">
+      </cr-icon-button>
+      <cr-icon-button iron-icon="cr:more-vert"
+          disabled="[[!selectedBookmarks_.length]]"
+          title="$i18n{tooltipMore}" aria-label="$i18n{tooltipMore}"
+          on-click="onEditMenuClicked_">
+      </cr-icon-button>
+    </cr-toolbar-selection-overlay>
+  </sp-footer>
 </div>
 
 <cr-action-menu id="sortMenu">
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts
index bd490d1..8e97fb3 100644
--- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts
+++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts
@@ -5,16 +5,18 @@
 import '../strings.m.js';
 import './commerce/shopping_list.js';
 import './icons.html.js';
-import './power_bookmark_chip.js';
 import './power_bookmarks_context_menu.js';
 import './power_bookmark_row.js';
 import '//bookmarks-side-panel.top-chrome/shared/sp_empty_state.js';
+import '//bookmarks-side-panel.top-chrome/shared/sp_footer.js';
+import '//bookmarks-side-panel.top-chrome/shared/sp_label.js';
 import '//resources/cr_elements/cr_action_menu/cr_action_menu.js';
 import '//resources/cr_elements/cr_button/cr_button.js';
 import '//resources/cr_elements/cr_icon_button/cr_icon_button.js';
 import '//resources/cr_elements/cr_lazy_render/cr_lazy_render.js';
 import '//resources/cr_elements/cr_toast/cr_toast.js';
 import '//resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js';
+import '//resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.js';
 import '//resources/cr_elements/icons.html.js';
 
 import {getInstance as getAnnouncerInstance} from '//resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
@@ -868,6 +870,10 @@
     chrome.metricsPrivate.recordUserAction(
         'Commerce.PriceTracking.SidePanel.TrackedProductsShown');
   }
+
+  private shouldPinFooter_(): boolean {
+    return this.shownBookmarks_.length > 0;
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/side_panel/shared/BUILD.gn b/chrome/browser/resources/side_panel/shared/BUILD.gn
index 38af1f1b..41f0aec 100644
--- a/chrome/browser/resources/side_panel/shared/BUILD.gn
+++ b/chrome/browser/resources/side_panel/shared/BUILD.gn
@@ -10,7 +10,11 @@
   grd_prefix = "side_panel_shared"
   grd_resource_path_prefix = "shared"
 
-  web_component_files = [ "sp_empty_state.ts" ]
+  web_component_files = [
+    "sp_empty_state.ts",
+    "sp_footer.ts",
+    "sp_label.ts",
+  ]
 
   ts_composite = true
   ts_deps = [
diff --git a/chrome/browser/resources/side_panel/shared/sp_footer.html b/chrome/browser/resources/side_panel/shared/sp_footer.html
new file mode 100644
index 0000000..73eb6d04
--- /dev/null
+++ b/chrome/browser/resources/side_panel/shared/sp_footer.html
@@ -0,0 +1,18 @@
+<style>
+  :host {
+    display: flex;
+    justify-content: center;
+  }
+
+  :host([pinned]) {
+    border-top: var(--cr-hairline);
+    box-sizing: border-box;
+    display: block;
+    flex-shrink: 0;
+    height: 48px;
+    margin-block-start: auto;
+    padding: 8px;
+    position: relative;
+  }
+</style>
+<slot></slot>
diff --git a/chrome/browser/resources/side_panel/shared/sp_footer.ts b/chrome/browser/resources/side_panel/shared/sp_footer.ts
new file mode 100644
index 0000000..4d3ced1
--- /dev/null
+++ b/chrome/browser/resources/side_panel/shared/sp_footer.ts
@@ -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.
+
+/**
+ * @fileoverview A toolbar that rests with its content horizontally centered or
+ * pushes itself to the bottom of a flex parent when [pinned].
+ */
+
+import '//resources/cr_elements/cr_shared_vars.css.js';
+
+import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {getTemplate} from './sp_footer.html.js';
+
+export class SpFooterElement extends PolymerElement {
+  static get is() {
+    return 'sp-footer';
+  }
+
+  static get template() {
+    return getTemplate();
+  }
+
+  static get properties() {
+    return {
+      pinned: {
+        type: Boolean,
+        reflectToAttribute: true,
+        value: false,
+      },
+    };
+  }
+
+  pinned: boolean;
+
+  override ready() {
+    super.ready();
+    this.setAttribute('role', 'toolbar');
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'sp-footer': SpFooterElement;
+  }
+}
+
+customElements.define(SpFooterElement.is, SpFooterElement);
diff --git a/chrome/browser/resources/side_panel/shared/sp_label.html b/chrome/browser/resources/side_panel/shared/sp_label.html
new file mode 100644
index 0000000..029d4859
--- /dev/null
+++ b/chrome/browser/resources/side_panel/shared/sp_label.html
@@ -0,0 +1,79 @@
+<style>
+  :host {
+    background: var(--google-grey-100);
+    border-radius: 100px;
+    color: var(--cr-secondary-text-color);
+    display: inline-flex;
+    flex-direction: row;
+    font-size: 12px;
+    gap: 4px;
+    line-height: 16px;
+    padding: 2px 8px 2px 6px;
+  }
+
+  :host([actionable]:hover) {
+    background: var(--google-blue-100);
+    color: var(--google-blue-600);
+  }
+
+  :host([updated]) {
+    background: var(--google-green-50);
+    color: var(--google-green-800);
+    font-weight: 500;
+  }
+
+  :host([updated][actionable]:hover) {
+    background: var(--google-green-200);
+    color: var(--google-green-900);
+  }
+
+  ::slotted(iron-icon) {
+    color: inherit;
+    height: 12px;
+    width: 12px;
+  }
+
+  ::slotted([slot=previous-label]) {
+    color: var(--cr-secondary-text-color);
+    font-weight: 400;
+    text-decoration: line-through;
+  }
+
+  :host([updated][actionable]:hover) ::slotted([slot=previous-label]) {
+    color: var(--google-grey-800);
+  }
+
+  @media (prefers-color-scheme: dark) {
+    :host {
+      background: var(--google-grey-800);
+      color: white;
+    }
+
+    :host([actionable]:hover) {
+      background: var(--google-blue-300);
+      color: var(--google-grey-900);
+    }
+
+    :host([updated]) {
+      background: var(--google-green-900);
+      color: white;
+    }
+
+    :host([updated]) ::slotted([slot=previous-label]) {
+      color: var(--google-green-200);
+    }
+
+    :host([updated][actionable]:hover) {
+      background: linear-gradient(
+          0deg, rgba(0, 0, 0, 0.16), rgba(0, 0, 0, 0.16)),
+          var(--google-green-900);
+      color: white;
+    }
+
+    :host([updated][actionable]:hover) ::slotted([slot=previous-label]) {
+      color: var(--google-green-200);
+    }
+  }
+</style>
+<slot></slot>
+<slot name="previous-label"></slot>
diff --git a/chrome/browser/resources/side_panel/shared/sp_label.ts b/chrome/browser/resources/side_panel/shared/sp_label.ts
new file mode 100644
index 0000000..7f8d483
--- /dev/null
+++ b/chrome/browser/resources/side_panel/shared/sp_label.ts
@@ -0,0 +1,61 @@
+// 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 A label component that is used to denote additional information
+ * or an updated state.
+ */
+
+import '//resources/cr_elements/cr_shared_vars.css.js';
+
+import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {getTemplate} from './sp_label.html.js';
+
+export class SpLabel extends PolymerElement {
+  static get is() {
+    return 'sp-label';
+  }
+
+  static get template() {
+    return getTemplate();
+  }
+
+  static get properties() {
+    return {
+      actionable: {
+        type: Boolean,
+        reflectToAttribute: true,
+        value: false,
+        observer: 'onActionableChanged_',
+      },
+      updated: {
+        type: Boolean,
+        reflectToAttribute: true,
+        value: false,
+      },
+    };
+  }
+
+  actionable: boolean;
+  updated: boolean;
+
+  private onActionableChanged_() {
+    if (this.actionable) {
+      this.setAttribute('tabindex', '1');
+      this.setAttribute('role', 'button');
+    } else {
+      this.removeAttribute('tabindex');
+      this.removeAttribute('role');
+    }
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'sp-label': SpLabel;
+  }
+}
+
+customElements.define(SpLabel.is, SpLabel);
diff --git a/chrome/browser/sessions/tab_restore_browsertest.cc b/chrome/browser/sessions/tab_restore_browsertest.cc
index 66c6f16..800dccf 100644
--- a/chrome/browser/sessions/tab_restore_browsertest.cc
+++ b/chrome/browser/sessions/tab_restore_browsertest.cc
@@ -1609,13 +1609,40 @@
             browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
 }
 
-// Check that TabManager.TimeSinceTablosedUntilRestored histogram is not
+// Check that TabRestore.Tab.TimeBetweenClosedAndRestored histogram is recorded
+// on tab restore.
+IN_PROC_BROWSER_TEST_F(TabRestoreTest,
+                       TimeBetweenTabClosedAndRestoredRecorded) {
+  base::HistogramTester histogram_tester;
+  const char kTimeBetweenTabClosedAndRestored[] =
+      "TabRestore.Tab.TimeBetweenClosedAndRestored";
+
+  int starting_tab_count = browser()->tab_strip_model()->count();
+  AddSomeTabs(browser(), 3);
+
+  // Close the tab in the middle.
+  int closed_tab_index = starting_tab_count + 1;
+  CloseTab(closed_tab_index);
+
+  EXPECT_EQ(
+      histogram_tester.GetAllSamples(kTimeBetweenTabClosedAndRestored).size(),
+      0U);
+
+  // Restore the tab. This should record the kTimeBetweenTabClosedAndRestored
+  // histogram.
+  RestoreTab(0, closed_tab_index);
+  EXPECT_EQ(
+      histogram_tester.GetAllSamples(kTimeBetweenTabClosedAndRestored).size(),
+      1U);
+}
+
+// Check that TabRestore.Window.TimeBetweenClosedAndRestored histogram is
 // recorded on window restore.
 IN_PROC_BROWSER_TEST_F(TabRestoreTest,
-                       TimeSinceTabClosedNotRecordedOnWindowRestore) {
+                       TimeBetweenWindowClosedAndRestoredRecorded) {
   base::HistogramTester histogram_tester;
-  const char kTimeSinceTabClosedUntilRestored[] =
-      "TabManager.TimeSinceTabClosedUntilRestored";
+  const char kTimeBetweenWindowClosedAndRestored[] =
+      "TabRestore.Window.TimeBetweenClosedAndRestored";
 
   // Create a new window.
   ui_test_utils::NavigateToURLWithDisposition(
@@ -1634,20 +1661,42 @@
   // Close the window.
   CloseBrowserSynchronously(browser());
 
-  EXPECT_EQ(
-      histogram_tester.GetAllSamples(kTimeSinceTabClosedUntilRestored).size(),
-      0U);
+  EXPECT_EQ(histogram_tester.GetAllSamples(kTimeBetweenWindowClosedAndRestored)
+                .size(),
+            0U);
 
-  // Restore the window.
+  // Restore the window. This should record kTimeBetweenWindowClosedAndRestored
+  // histogram.
   content::WindowedNotificationObserver load_stop_observer(
       content::NOTIFICATION_LOAD_STOP,
       content::NotificationService::AllSources());
   chrome::RestoreTab(active_browser_list_->get(0));
 
-  // Check that TabManager.TimeSinceTablosedUntilRestored was not recorded.
+  EXPECT_EQ(histogram_tester.GetAllSamples(kTimeBetweenWindowClosedAndRestored)
+                .size(),
+            1U);
+}
+
+// // Check that TabRestore.Group.TimeBetweenClosedAndRestored histogram is
+// recorded on group restore.
+IN_PROC_BROWSER_TEST_F(TabRestoreTest,
+                       TimeBetweenGroupClosedAndRestoredRecorded) {
+  base::HistogramTester histogram_tester;
+  const char kTimeBetweenGroupClosedAndRestored[] =
+      "TabRestore.Group.TimeBetweenClosedAndRestored";
+
+  AddSomeTabs(browser(), 3);
+  tab_groups::TabGroupId group =
+      browser()->tab_strip_model()->AddToNewGroup({1, 2});
+  CloseGroup(group);
+
+  // Restore closed group. This should record kTimeBetweenGroupClosedAndRestored
+  // histogram.
+  ASSERT_NO_FATAL_FAILURE(RestoreGroup(group, 0, 1));
+
   EXPECT_EQ(
-      histogram_tester.GetAllSamples(kTimeSinceTabClosedUntilRestored).size(),
-      0U);
+      histogram_tester.GetAllSamples(kTimeBetweenGroupClosedAndRestored).size(),
+      1U);
 }
 
 IN_PROC_BROWSER_TEST_F(TabRestoreTest, PRE_PRE_RestoreAfterMultipleRestarts) {
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 6f5e2243..c2c04e3 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -115,6 +115,7 @@
     "interventions/intervention_infobar_delegate.cc",
     "interventions/intervention_infobar_delegate.h",
     "javascript_dialogs/chrome_javascript_app_modal_dialog_view_factory.h",
+    "lens/lens_core_tab_side_panel_helper.h",
     "login/login_handler.cc",
     "login/login_handler.h",
     "login/login_navigation_throttle.cc",
@@ -210,6 +211,7 @@
     "ui_features.h",
     "uninstall_browser_prompt.h",
     "view_ids.h",
+    "views/side_panel/lens/lens_core_tab_side_panel_helper.cc",
     "webauthn/authenticator_request_dialog.h",
     "webid/account_selection_view.h",
     "webid/identity_dialog_controller.cc",
@@ -365,6 +367,7 @@
   # have the same dependencies. Once browser_ui is untangled from
   # browser, then we can clean up these dependencies.
   public_deps = [
+    "//chrome/browser/headless",
     "//components/dom_distiller/core",
     "//components/paint_preview/buildflags",
     "//components/safe_browsing:buildflags",
diff --git a/chrome/browser/ui/ash/network/network_portal_notification_controller.cc b/chrome/browser/ui/ash/network/network_portal_notification_controller.cc
index 9c346dd5..150a775 100644
--- a/chrome/browser/ui/ash/network/network_portal_notification_controller.cc
+++ b/chrome/browser/ui/ash/network/network_portal_notification_controller.cc
@@ -43,7 +43,7 @@
 
 const char kNotifierNetworkPortalDetector[] = "ash.network.portal-detector";
 
-std::unique_ptr<message_center::Notification> CreatePost2022Notification(
+std::unique_ptr<message_center::Notification> CreateNotification(
     const NetworkState* network,
     scoped_refptr<message_center::NotificationDelegate> delegate,
     message_center::NotifierId notifier_id,
@@ -94,30 +94,6 @@
   return notification;
 }
 
-std::unique_ptr<message_center::Notification> CreatePre2022Notification(
-    const NetworkState* network,
-    scoped_refptr<message_center::NotificationDelegate> delegate,
-    message_center::NotifierId notifier_id,
-    bool is_wifi) {
-  std::unique_ptr<message_center::Notification> notification =
-      CreateSystemNotificationPtr(
-          message_center::NOTIFICATION_TYPE_SIMPLE,
-          NetworkPortalNotificationController::kNotificationId,
-          l10n_util::GetStringUTF16(
-              is_wifi ? IDS_PORTAL_DETECTION_NOTIFICATION_TITLE_WIFI
-                      : IDS_PORTAL_DETECTION_NOTIFICATION_TITLE_WIRED),
-          l10n_util::GetStringFUTF16(
-              is_wifi ? IDS_PORTAL_DETECTION_NOTIFICATION_MESSAGE_WIFI
-                      : IDS_PORTAL_DETECTION_NOTIFICATION_MESSAGE_WIRED,
-              base::UTF8ToUTF16(network->name())),
-          /*display_source=*/std::u16string(), /*origin_url=*/GURL(),
-          notifier_id, message_center::RichNotificationData(),
-          std::move(delegate), kNotificationCaptivePortalIcon,
-          message_center::SystemNotificationWarningLevel::WARNING);
-  notification->set_never_timeout(true);
-  return notification;
-}
-
 void CloseNotification() {
   SystemNotificationHelper::GetInstance()->Close(
       NetworkPortalNotificationController::kNotificationId);
@@ -246,13 +222,8 @@
       NotificationCatalogName::kNetworkPortalDetector);
   bool is_wifi = NetworkTypePattern::WiFi().MatchesType(network->type());
   std::unique_ptr<message_center::Notification> notification;
-  if (features::IsCaptivePortalUI2022Enabled()) {
-    notification = CreatePost2022Notification(
-        network, notification_delegate, notifier_id, is_wifi, portal_state);
-  } else {
-    notification = CreatePre2022Notification(network, notification_delegate,
-                                             notifier_id, is_wifi);
-  }
+  notification = CreateNotification(network, notification_delegate, notifier_id,
+                                    is_wifi, portal_state);
   return notification;
 }
 
@@ -260,8 +231,4 @@
   ignore_no_network_for_testing_ = true;
 }
 
-bool NetworkPortalNotificationController::IsDialogShownForTesting() const {
-  return signin_controller_ && signin_controller_->DialogIsShown();
-}
-
 }  // namespace ash
diff --git a/chrome/browser/ui/ash/network/network_portal_notification_controller.h b/chrome/browser/ui/ash/network/network_portal_notification_controller.h
index 4a939e4..40bcb9d 100644
--- a/chrome/browser/ui/ash/network/network_portal_notification_controller.h
+++ b/chrome/browser/ui/ash/network/network_portal_notification_controller.h
@@ -47,8 +47,6 @@
   // Ignores "No network" errors in browser tests.
   void SetIgnoreNoNetworkForTesting();
 
-  bool IsDialogShownForTesting() const;
-
  private:
   friend NetworkPortalNotificationControllerTest;
 
diff --git a/chrome/browser/ui/ash/network/network_portal_signin_controller.cc b/chrome/browser/ui/ash/network/network_portal_signin_controller.cc
index c4f5e3d..4a9e7b1 100644
--- a/chrome/browser/ui/ash/network/network_portal_signin_controller.cc
+++ b/chrome/browser/ui/ash/network/network_portal_signin_controller.cc
@@ -99,9 +99,6 @@
     case SigninMode::kSigninDialog:
       ShowDialog(ProfileHelper::GetSigninProfile(), url);
       break;
-    case SigninMode::kSingletonTab:
-      ShowSingletonTab(ProfileManager::GetActiveUserProfile(), url);
-      break;
     case SigninMode::kNormalTab:
       ShowTab(ProfileManager::GetActiveUserProfile(), url);
       break;
@@ -137,17 +134,6 @@
     return SigninMode::kSigninDialog;
   }
 
-  if (!ash::features::IsCaptivePortalUI2022Enabled()) {
-    if (profile->GetPrefs()->GetBoolean(
-            prefs::kCaptivePortalAuthenticationIgnoresProxy)) {
-      // If allowed, use an incognito dialog to ignore any proxies.
-      return SigninMode::kSigninDialog;
-    }
-    return SigninMode::kSingletonTab;
-  }
-
-  NET_LOG(DEBUG) << "GetSigninMode: 2022 UI Enabled";
-
   // This pref defaults to true but may be set to false by policy.
   // Note: Generally we always want to show the portal signin UI in an incognito
   // tab to avoid providing cookies, see b/245578628 for details.
@@ -232,9 +218,6 @@
     case NetworkPortalSigninController::SigninMode::kSigninDialog:
       stream << "Signin Dialog";
       break;
-    case NetworkPortalSigninController::SigninMode::kSingletonTab:
-      stream << "Singleton Tab";
-      break;
     case NetworkPortalSigninController::SigninMode::kNormalTab:
       stream << "Normal Tab";
       break;
diff --git a/chrome/browser/ui/ash/network/network_portal_signin_controller.h b/chrome/browser/ui/ash/network/network_portal_signin_controller.h
index facab69..8be6b52 100644
--- a/chrome/browser/ui/ash/network/network_portal_signin_controller.h
+++ b/chrome/browser/ui/ash/network/network_portal_signin_controller.h
@@ -18,11 +18,7 @@
   enum class SigninMode {
     // Show in a dialog window using the signin (oobe/login) profile.
     kSigninDialog = 1,
-    // Show in a singleton tab (i.e. reuse a tab with the same URL if it exists)
-    // using the active user profile. In practice since the signin page will
-    // immediately redirect, this will behave the same as kNormalTab unless
-    // the probe URL fails to redirect.
-    kSingletonTab = 2,
+    // kSingletonTab (2) was deprecated in M110
     // Show in a new tab using the active user profile.
     kNormalTab = 3,
     // Show in a new tab in an OTR window with the portal signin profile.
diff --git a/chrome/browser/ui/ash/network/network_portal_signin_controller_unittest.cc b/chrome/browser/ui/ash/network/network_portal_signin_controller_unittest.cc
index cc1fd6f0..11f4c57 100644
--- a/chrome/browser/ui/ash/network/network_portal_signin_controller_unittest.cc
+++ b/chrome/browser/ui/ash/network/network_portal_signin_controller_unittest.cc
@@ -6,10 +6,8 @@
 
 #include <memory>
 
-#include "ash/constants/ash_features.h"
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
@@ -78,9 +76,7 @@
 
 class NetworkPortalSigninControllerTest : public testing::Test {
  public:
-  NetworkPortalSigninControllerTest() {
-    feature_list_.InitAndDisableFeature({features::kCaptivePortalUI2022});
-  }
+  NetworkPortalSigninControllerTest() = default;
   NetworkPortalSigninControllerTest(const NetworkPortalSigninControllerTest&) =
       delete;
   NetworkPortalSigninControllerTest& operator=(
@@ -187,7 +183,6 @@
   std::unique_ptr<FakeChromeUserManager> user_manager_;
   TestingProfileManager test_profile_manager_{
       TestingBrowserProcess::GetGlobal()};
-  base::test::ScopedFeatureList feature_list_;
 };
 
 TEST_F(NetworkPortalSigninControllerTest, LoginScreen) {
@@ -201,73 +196,14 @@
       AccountId::FromUserEmail("fake_user@test"));
   user_manager_->LoginUser(user->GetAccountId());
 
+  std::string expected_url = SetProbeUrl(kTestPortalUrl);
   ShowSignin();
-  EXPECT_FALSE(controller_->dialog_url().empty());
+  EXPECT_EQ(controller_->tab_url(), expected_url);
+  EXPECT_TRUE(controller_->profile()->IsOffTheRecord());
 }
 
 TEST_F(NetworkPortalSigninControllerTest, AuthenticationIgnoresProxyTrue) {
   SimulateLogin();
-  // kCaptivePortalAuthenticationIgnoresProxy defaults to true
-  ShowSignin();
-  EXPECT_FALSE(controller_->dialog_url().empty());
-}
-
-TEST_F(NetworkPortalSigninControllerTest, AuthenticationIgnoresProxyFalse) {
-  SimulateLogin();
-  GetPrefs()->SetBoolean(prefs::kCaptivePortalAuthenticationIgnoresProxy,
-                         false);
-  ShowSignin();
-  EXPECT_FALSE(controller_->singleton_tab_url().empty());
-}
-
-TEST_F(NetworkPortalSigninControllerTest, ProbeUrl) {
-  SimulateLogin();
-  std::string expected_url = SetProbeUrl(kTestPortalUrl);
-  ShowSignin();
-  EXPECT_EQ(controller_->dialog_url(), expected_url);
-}
-
-TEST_F(NetworkPortalSigninControllerTest, NoProbeUrl) {
-  SimulateLogin();
-  std::string expected_url = SetProbeUrl(std::string());
-  ShowSignin();
-  EXPECT_EQ(controller_->dialog_url(), expected_url);
-}
-
-class NetworkPortalSigninControllerTest2022Update
-    : public NetworkPortalSigninControllerTest {
- public:
-  NetworkPortalSigninControllerTest2022Update() {
-    feature_list_.Reset();
-    feature_list_.InitAndEnableFeature(features::kCaptivePortalUI2022);
-  }
-};
-
-TEST_F(NetworkPortalSigninControllerTest2022Update, LoginScreen) {
-  ShowSignin();
-  EXPECT_FALSE(controller_->dialog_url().empty());
-}
-
-TEST_F(NetworkPortalSigninControllerTest2022Update, NoProxy) {
-  SimulateLogin();
-  std::string expected_url = SetProbeUrl(kTestPortalUrl);
-  ShowSignin();
-  EXPECT_EQ(controller_->tab_url(), expected_url);
-  EXPECT_TRUE(controller_->profile()->IsOffTheRecord());
-}
-
-TEST_F(NetworkPortalSigninControllerTest2022Update, ProxyDirect) {
-  SimulateLogin();
-  std::string expected_url = SetProbeUrl(kTestPortalUrl);
-  SetNetworkProxyDirect();
-  ShowSignin();
-  EXPECT_EQ(controller_->tab_url(), expected_url);
-  EXPECT_TRUE(controller_->profile()->IsOffTheRecord());
-}
-
-TEST_F(NetworkPortalSigninControllerTest2022Update,
-       AuthenticationIgnoresProxyTrue) {
-  SimulateLogin();
   std::string expected_url = SetProbeUrl(kTestPortalUrl);
   SetNetworkProxy();
   // kCaptivePortalAuthenticationIgnoresProxy defaults to true
@@ -276,8 +212,7 @@
   EXPECT_TRUE(controller_->profile()->IsOffTheRecord());
 }
 
-TEST_F(NetworkPortalSigninControllerTest2022Update,
-       AuthenticationIgnoresProxyFalse) {
+TEST_F(NetworkPortalSigninControllerTest, AuthenticationIgnoresProxyFalse) {
   SimulateLogin();
   std::string expected_url = SetProbeUrl(kTestPortalUrl);
   SetNetworkProxy();
@@ -288,7 +223,39 @@
   EXPECT_FALSE(controller_->profile()->IsOffTheRecord());
 }
 
-TEST_F(NetworkPortalSigninControllerTest2022Update,
+TEST_F(NetworkPortalSigninControllerTest, ProbeUrl) {
+  SimulateLogin();
+  std::string expected_url = SetProbeUrl(kTestPortalUrl);
+  ShowSignin();
+  EXPECT_EQ(controller_->tab_url(), expected_url);
+  EXPECT_TRUE(controller_->profile()->IsOffTheRecord());
+}
+
+TEST_F(NetworkPortalSigninControllerTest, NoProbeUrl) {
+  SimulateLogin();
+  std::string expected_url = SetProbeUrl(std::string());
+  ShowSignin();
+  EXPECT_EQ(controller_->tab_url(), expected_url);
+}
+
+TEST_F(NetworkPortalSigninControllerTest, NoProxy) {
+  SimulateLogin();
+  std::string expected_url = SetProbeUrl(kTestPortalUrl);
+  ShowSignin();
+  EXPECT_EQ(controller_->tab_url(), expected_url);
+  EXPECT_TRUE(controller_->profile()->IsOffTheRecord());
+}
+
+TEST_F(NetworkPortalSigninControllerTest, ProxyDirect) {
+  SimulateLogin();
+  std::string expected_url = SetProbeUrl(kTestPortalUrl);
+  SetNetworkProxyDirect();
+  ShowSignin();
+  EXPECT_EQ(controller_->tab_url(), expected_url);
+  EXPECT_TRUE(controller_->profile()->IsOffTheRecord());
+}
+
+TEST_F(NetworkPortalSigninControllerTest,
        AuthenticationIgnoresProxyFalseOTRDisabled) {
   SimulateLogin();
   std::string expected_url = SetProbeUrl(kTestPortalUrl);
@@ -299,7 +266,7 @@
   EXPECT_EQ(controller_->dialog_url(), expected_url);
 }
 
-TEST_F(NetworkPortalSigninControllerTest2022Update, ProxyPref) {
+TEST_F(NetworkPortalSigninControllerTest, ProxyPref) {
   SimulateLogin();
   std::string expected_url = SetProbeUrl(kTestPortalUrl);
   base::Value::Dict proxy_config;
@@ -311,14 +278,7 @@
   EXPECT_TRUE(controller_->profile()->IsOffTheRecord());
 }
 
-TEST_F(NetworkPortalSigninControllerTest2022Update, NoProbeUrl) {
-  SimulateLogin();
-  std::string expected_url = SetProbeUrl(std::string());
-  ShowSignin();
-  EXPECT_EQ(controller_->tab_url(), expected_url);
-}
-
-TEST_F(NetworkPortalSigninControllerTest2022Update, IsNewOTRProfile) {
+TEST_F(NetworkPortalSigninControllerTest, IsNewOTRProfile) {
   SimulateLogin();
   std::string expected_url = SetProbeUrl(kTestPortalUrl);
   ShowSignin();
@@ -332,7 +292,7 @@
   EXPECT_TRUE(controller_->profile()->IsOffTheRecord());
 }
 
-TEST_F(NetworkPortalSigninControllerTest2022Update, GuestLogin) {
+TEST_F(NetworkPortalSigninControllerTest, GuestLogin) {
   SimulateLoginAsGuest();
   std::string expected_url = SetProbeUrl(kTestPortalUrl);
   ShowSignin();
@@ -340,7 +300,7 @@
   EXPECT_TRUE(controller_->profile()->IsOffTheRecord());
 }
 
-TEST_F(NetworkPortalSigninControllerTest2022Update, Metrics) {
+TEST_F(NetworkPortalSigninControllerTest, Metrics) {
   base::HistogramTester histogram_tester;
   SimulateLogin();
   std::string expected_url = SetProbeUrl(std::string());
diff --git a/chrome/browser/ui/ash/system_tray_client_impl_browsertest.cc b/chrome/browser/ui/ash/system_tray_client_impl_browsertest.cc
index 6a69220dfc..42710ee 100644
--- a/chrome/browser/ui/ash/system_tray_client_impl_browsertest.cc
+++ b/chrome/browser/ui/ash/system_tray_client_impl_browsertest.cc
@@ -79,8 +79,7 @@
  public:
   SystemTrayClientEnterpriseTest() {
     if (GetParam()) {
-      feature_list_.InitWithFeatures(
-          {ash::features::kQsRevamp, ash::features::kQsRevampWip}, {});
+      feature_list_.InitAndEnableFeature(ash::features::kQsRevamp);
     }
   }
 
diff --git a/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc b/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc
index c2a77c1..1a2dba5 100644
--- a/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc
+++ b/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc
@@ -96,14 +96,9 @@
  protected:
   SystemTrayTrayCastMediaRouterChromeOSTest() {
     if (IsQsRevampEnabled()) {
-      feature_list_.InitWithFeatures(
-          /*enabled_features=*/{ash::features::kQsRevamp,
-                                ash::features::kQsRevampWip},
-          /*disabled_features=*/{});
+      feature_list_.InitAndEnableFeature(ash::features::kQsRevamp);
     } else {
-      feature_list_.InitWithFeatures(
-          /*enabled_features=*/{}, /*disabled_features=*/{
-              ash::features::kQsRevamp, ash::features::kQsRevampWip});
+      feature_list_.InitAndDisableFeature(ash::features::kQsRevamp);
     }
   }
 
@@ -127,8 +122,9 @@
     message_center::NotificationList::Notifications notification_set =
         message_center::MessageCenter::Get()->GetVisibleNotifications();
     for (auto* notification : notification_set) {
-      if (notification->id() == kNotificationId)
+      if (notification->id() == kNotificationId) {
         return notification->title();
+      }
     }
     return std::u16string();
   }
@@ -283,14 +279,9 @@
  public:
   SystemTrayTrayCastAccessCodeChromeOSTest() {
     if (IsQsRevampEnabled()) {
-      feature_list_.InitWithFeatures(
-          /*enabled_features=*/{ash::features::kQsRevamp,
-                                ash::features::kQsRevampWip},
-          /*disabled_features=*/{});
+      feature_list_.InitAndEnableFeature(ash::features::kQsRevamp);
     } else {
-      feature_list_.InitWithFeatures(
-          /*enabled_features=*/{}, /*disabled_features=*/{
-              ash::features::kQsRevamp, ash::features::kQsRevampWip});
+      feature_list_.InitAndDisableFeature(ash::features::kQsRevamp);
     }
 
     // Use consumer emails to avoid having to fake a policy fetch.
diff --git a/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller.h b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller.h
index f7d6494..3616501 100644
--- a/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller.h
+++ b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller.h
@@ -72,6 +72,10 @@
   // Sets the currently selected challenge option id based on which
   // challenge option radio button is selected in the Card Authentication
   // Selection Dialog View.
+  // TODO(crbug.com/1392939): Refactor this function to
+  // `SetSelectedChallengeOptionForId()`, which should take in a
+  // `selected_challenge_option_id`, and set the currently selected challenge
+  // option in the class based on this id.
   virtual void SetSelectedChallengeOptionId(
       const CardUnmaskChallengeOption::ChallengeOptionId&
           selected_challenge_option_id) = 0;
diff --git a/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.cc b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.cc
index f3efca73..1e71995 100644
--- a/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.cc
+++ b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.cc
@@ -140,11 +140,11 @@
     OnOkButtonClicked() {
   DCHECK(!selected_challenge_option_id_.value().empty());
 
-  auto selected_challenge_option = std::find_if(
-      challenge_options_.begin(), challenge_options_.end(),
-      [this](const CardUnmaskChallengeOption challenge_option) {
-        return challenge_option.id == selected_challenge_option_id_;
-      });
+  // TODO(crbug.com/1392939): Remove this lambda once we refactor
+  // `SetSelectedChallengeOptionId()` to `SetSelectedChallengeOptionForId()`.
+  auto selected_challenge_option =
+      base::ranges::find(challenge_options_, selected_challenge_option_id_,
+                         &CardUnmaskChallengeOption::id);
 
   DCHECK(selected_challenge_option != challenge_options_.end());
   selected_challenge_option_type_ = (*selected_challenge_option).type;
@@ -241,10 +241,23 @@
 std::u16string
 CardUnmaskAuthenticationSelectionDialogControllerImpl::GetOkButtonLabel()
     const {
-  return l10n_util::GetStringUTF16(
-      GetChallengeOptions().size() > 1
-          ? IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_OK_BUTTON_LABEL_CONTINUE
-          : IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_OK_BUTTON_LABEL_SEND);
+  // TODO(crbug.com/1392939): Remove this lambda once we refactor
+  // `SetSelectedChallengeOptionId()` to `SetSelectedChallengeOptionForId()`.
+  auto selected_challenge_option =
+      base::ranges::find(challenge_options_, selected_challenge_option_id_,
+                         &CardUnmaskChallengeOption::id);
+
+  switch (selected_challenge_option->type) {
+    case CardUnmaskChallengeOptionType::kSmsOtp:
+      return l10n_util::GetStringUTF16(
+          IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_OK_BUTTON_LABEL_SEND);
+    case CardUnmaskChallengeOptionType::kCvc:
+      return l10n_util::GetStringUTF16(
+          IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_OK_BUTTON_LABEL_CONTINUE);
+    case CardUnmaskChallengeOptionType::kUnknownType:
+      NOTREACHED();
+      return std::u16string();
+  }
 }
 
 std::u16string
diff --git a/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.h b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.h
index 89b41624..75a455f 100644
--- a/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.h
+++ b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.h
@@ -90,11 +90,6 @@
   friend class content::WebContentsUserData<
       CardUnmaskAuthenticationSelectionDialogControllerImpl>;
 
-  // The currently unique identifier of the challenge option selected in the
-  // Card Authentication Selection Dialog View.
-  CardUnmaskChallengeOption::ChallengeOptionId selected_challenge_option_id_ =
-      CardUnmaskChallengeOption::ChallengeOptionId();
-
   // Contains all of the challenge options an issuer has for the user.
   std::vector<CardUnmaskChallengeOption> challenge_options_;
 
@@ -108,11 +103,25 @@
   base::OnceClosure cancel_unmasking_closure_;
 
   // Tracks whether a challenge option was selected in the current
-  // |dialog_view_|.
+  // `dialog_view_`.
+  // TODO(crbug.com/1392939): Rename this to `challenge_option_accepted_`, as it
+  // only gets set when the user clicks the accept button after selecting a
+  // challenge option.
   bool challenge_option_selected_ = false;
 
+  // The currently unique identifier of the challenge option selected in the
+  // Card Authentication Selection Dialog View.
+  // TODO(crbug.com/1392939): Remove this and just add a
+  // `selected_challenge_option_` object once we refactor
+  // `SetSelectedChallengeOptionId()` to `SetSelectedChallengeOptionForId()`.
+  CardUnmaskChallengeOption::ChallengeOptionId selected_challenge_option_id_ =
+      CardUnmaskChallengeOption::ChallengeOptionId();
+
   // Contains the challenge option type selected by the user. Currently only
   // kCvc and kSmsOtp are supported.
+  // TODO(crbug.com/1392939): Remove this and just add a
+  // `selected_challenge_option_` object once we refactor
+  // `SetSelectedChallengeOptionId()` to `SetSelectedChallengeOptionForId()`.
   CardUnmaskChallengeOptionType selected_challenge_option_type_ =
       CardUnmaskChallengeOptionType::kUnknownType;
 
diff --git a/chrome/browser/ui/lens/lens_core_tab_side_panel_helper.h b/chrome/browser/ui/lens/lens_core_tab_side_panel_helper.h
new file mode 100644
index 0000000..26dedc9
--- /dev/null
+++ b/chrome/browser/ui/lens/lens_core_tab_side_panel_helper.h
@@ -0,0 +1,41 @@
+// 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_LENS_LENS_CORE_TAB_SIDE_PANEL_HELPER_H_
+#define CHROME_BROWSER_UI_LENS_LENS_CORE_TAB_SIDE_PANEL_HELPER_H_
+
+#include "components/search_engines/template_url_service.h"
+#include "content/public/browser/web_contents.h"
+
+namespace lens {
+
+namespace internal {
+// Returns if the v2 unified side panel is enabled.
+// This checks all the basic requirements for the side panel to be enabled.
+bool IsSidePanelEnabled(content::WebContents* web_contents);
+
+// Helper to return if the web contents are viewed in a progressive web app.
+bool IsInProgressiveWebApp(content::WebContents* web_contents);
+
+// Helper to return the template url service from the given web contents.
+TemplateURLService* GetTemplateURLService(content::WebContents* web_contents);
+
+}  // namespace internal
+
+// Returns if the v2 unified side panel is enabled when Google is the default
+// search engine.
+bool IsSidePanelEnabledForLens(content::WebContents* web_contents);
+
+// Returns if the v2 unified side panel is enabled when Google is the default
+// search engine for lens region search.
+bool IsSidePanelEnabledForLensRegionSearch(content::WebContents* web_contents);
+
+// Returns if the v2 unified side panel is enabled when Google is NOT the
+// default search engine. The third party search engines needs to opt-in to the
+// side panel experience so this checks those flags.
+bool IsSidePanelEnabledFor3PDse(content::WebContents* web_contents);
+
+}  // namespace lens
+
+#endif  // CHROME_BROWSER_UI_LENS_LENS_CORE_TAB_SIDE_PANEL_HELPER_H_
diff --git a/chrome/browser/ui/quick_answers/ui/user_consent_view.cc b/chrome/browser/ui/quick_answers/ui/user_consent_view.cc
index 67ceaea..547a97e 100644
--- a/chrome/browser/ui/quick_answers/ui/user_consent_view.cc
+++ b/chrome/browser/ui/quick_answers/ui/user_consent_view.cc
@@ -350,7 +350,14 @@
     y = anchor_view_bounds_.bottom() + kMarginDip;
   }
   gfx::Rect bounds({x, y}, size);
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  // For Ash, convert the position relative to the screen.
+  // For Lacros, `bounds` is already relative to the toplevel window and the
+  // position will be calculated on server side.
   wm::ConvertRectFromScreen(GetWidget()->GetNativeWindow()->parent(), &bounds);
+#endif
+
   GetWidget()->SetBounds(bounds);
 }
 
diff --git a/chrome/browser/ui/tab_contents/core_tab_helper.cc b/chrome/browser/ui/tab_contents/core_tab_helper.cc
index 274341b..97f9103 100644
--- a/chrome/browser/ui/tab_contents/core_tab_helper.cc
+++ b/chrome/browser/ui/tab_contents/core_tab_helper.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/browser_command_controller.h"
+#include "chrome/browser/ui/lens/lens_core_tab_side_panel_helper.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/common/chrome_render_frame.mojom.h"
 #include "chrome/common/chrome_switches.h"
@@ -101,10 +102,8 @@
 
 void CoreTabHelper::SearchWithLens(content::RenderFrameHost* render_frame_host,
                                    const GURL& src_url,
-                                   lens::EntryPoint entry_point,
-                                   bool is_side_panel_enabled_for_feature) {
-  bool use_side_panel =
-      is_side_panel_enabled_for_feature && IsSidePanelEnabled();
+                                   lens::EntryPoint entry_point) {
+  bool use_side_panel = lens::IsSidePanelEnabledForLens(web_contents());
 
   SearchByImageImpl(render_frame_host, src_url, kImageSearchThumbnailMinSize,
                     lens::features::GetMaxPixelsForImageSearch(),
@@ -125,53 +124,21 @@
   return template_url_service;
 }
 
-bool CoreTabHelper::IsInProgressiveWebApp() {
-#if !BUILDFLAG(IS_ANDROID)
-  Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
-  return browser && (browser->is_type_app() || browser->is_type_app_popup());
-#else
-  return false;
-#endif  // !BUILDFLAG(IS_ANDROID)
-}
-
-bool CoreTabHelper::IsSidePanelEnabled() {
-#if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
-  return GetTemplateURLService()
-             ->IsSideImageSearchSupportedForDefaultSearchProvider() &&
-         !IsInProgressiveWebApp();
-#else
-  return false;
-#endif
-}
-
-bool CoreTabHelper::IsSidePanelEnabledFor3PDse() {
-  return IsSidePanelEnabled() &&
-         !search::DefaultSearchProviderIsGoogle(GetTemplateURLService()) &&
-         lens::features::GetEnableImageSearchUnifiedSidePanelFor3PDse();
-}
-
-void CoreTabHelper::SearchWithLens(gfx::Image image,
-                                   const gfx::Size& image_original_size,
-                                   lens::EntryPoint entry_point,
-                                   bool is_region_search_request,
-                                   bool is_side_panel_enabled_for_feature) {
-  SearchWithLens(image, image_original_size, entry_point,
-                 is_region_search_request, is_side_panel_enabled_for_feature,
-                 std::vector<lens::mojom::LatencyLogPtr>());
-}
-
-void CoreTabHelper::SearchWithLens(
+void CoreTabHelper::RegionSearchWithLens(
     gfx::Image image,
     const gfx::Size& image_original_size,
-    lens::EntryPoint entry_point,
-    bool is_region_search_request,
-    bool is_side_panel_enabled_for_feature,
     std::vector<lens::mojom::LatencyLogPtr> log_data) {
-  bool use_side_panel =
-      is_side_panel_enabled_for_feature && IsSidePanelEnabled();
+  // Do not show the side panel on region searches and modify the entry point
+  // if Lens fullscreen search features are enabled.
   bool is_full_screen_region_search_request =
-      is_region_search_request &&
       lens::features::IsLensFullscreenSearchEnabled();
+  lens::EntryPoint entry_point =
+      is_full_screen_region_search_request
+          ? lens::EntryPoint::CHROME_FULLSCREEN_SEARCH_MENU_ITEM
+          : lens::EntryPoint::CHROME_REGION_SEARCH_MENU_ITEM;
+  bool use_side_panel =
+      lens::IsSidePanelEnabledForLensRegionSearch(web_contents());
+
   auto lens_query_params = lens::GetQueryParametersForLensRequest(
       entry_point, use_side_panel,
       /* is_full_screen_region_search_request= */
@@ -185,14 +152,14 @@
   SearchByImageImpl(render_frame_host, src_url, kImageSearchThumbnailMinSize,
                     kImageSearchThumbnailMaxWidth,
                     kImageSearchThumbnailMaxHeight, std::string(),
-                    IsSidePanelEnabledFor3PDse());
+                    lens::IsSidePanelEnabledFor3PDse(web_contents()));
 }
 
 void CoreTabHelper::SearchByImage(const gfx::Image& image,
                                   const gfx::Size& image_original_size) {
   SearchByImageImpl(image, image_original_size,
                     /*additional_query_params=*/std::string(),
-                    IsSidePanelEnabledFor3PDse(),
+                    lens::IsSidePanelEnabledFor3PDse(web_contents()),
                     std::vector<lens::mojom::LatencyLogPtr>());
 }
 
@@ -491,6 +458,7 @@
                      ->GenerateSideImageSearchURLForDefaultSearchProvider(
                          search_url, kUnifiedSidePanelVersion);
   }
+
   PostContentToURL(post_content, search_url, use_side_panel);
 }
 
diff --git a/chrome/browser/ui/tab_contents/core_tab_helper.h b/chrome/browser/ui/tab_contents/core_tab_helper.h
index ed31334..fbf90c0 100644
--- a/chrome/browser/ui/tab_contents/core_tab_helper.h
+++ b/chrome/browser/ui/tab_contents/core_tab_helper.h
@@ -40,39 +40,20 @@
   void UpdateContentRestrictions(int content_restrictions);
 
   // Open the Lens standalone experience for the image that triggered the
-  // context menu. If |is_side_panel_enabled_for_feature| is true and if the
-  // google lens supports opening requests in side panel, then the request will
-  // open in the side panel instead of new tab.
+  // context menu. If the google lens supports opening requests in side panel,
+  // then the request will open in the side panel instead of new tab.
   void SearchWithLens(content::RenderFrameHost* render_frame_host,
                       const GURL& src_url,
-                      lens::EntryPoint entry_point,
-                      bool is_side_panel_enabled_for_feature);
+                      lens::EntryPoint entry_point);
 
   // Open the Lens experience for an image. Used for sending the bitmap selected
   // via Lens Region Search. |image_original_size| is specified in case of
   // resizing that happens prior to passing the image to |CoreTabHelper|. If
-  // |is_side_panel_enabled_for_feature| is true and if the search engine
-  // supports opening requests in side panel, then the request will open in the
-  // side panel instead of a new tab.
-  // TODO (b/257281671): remove when /screenshot is cleaned up
-  void SearchWithLens(gfx::Image image,
-                      const gfx::Size& image_original_size,
-                      lens::EntryPoint entry_point,
-                      bool is_region_search_request,
-                      bool is_side_panel_enabled_for_feature);
-
-  // Open the Lens experience for an image. Used for sending the bitmap selected
-  // via Lens Region Search. |image_original_size| is specified in case of
-  // resizing that happens prior to passing the image to |CoreTabHelper|. If
-  // |is_side_panel_enabled_for_feature| is true and if the search engine
-  // supports opening requests in side panel, then the request will open in the
-  // side panel instead of a new tab.
-  void SearchWithLens(gfx::Image image,
-                      const gfx::Size& image_original_size,
-                      lens::EntryPoint entry_point,
-                      bool is_region_search_request,
-                      bool is_side_panel_enabled_for_feature,
-                      std::vector<lens::mojom::LatencyLogPtr> log_data);
+  // the search engine supports opening requests in side panel, then the request
+  // will open in the side panel instead of a new tab.
+  void RegionSearchWithLens(gfx::Image image,
+                            const gfx::Size& image_original_size,
+                            std::vector<lens::mojom::LatencyLogPtr> log_data);
 
   // Perform an image search for the image that triggered the context menu.  The
   // |src_url| is passed to the search request and is not used directly to fetch
@@ -131,14 +112,6 @@
   // Web App
   bool IsInProgressiveWebApp();
 
-  // Helper function to check if side panel is enabled for current browser
-  // context
-  bool IsSidePanelEnabled();
-
-  // Helper function to check if the side panel is enabled for third party
-  // default search engines (3PDSE).
-  bool IsSidePanelEnabledFor3PDse();
-
   // Posts the bytes and content type to the specified URL If |use_side_panel|
   // is true, the content will open in a side panel, otherwise it will open in
   // a new tab.
diff --git a/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view.cc b/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view.cc
index 5d337cc..a587335 100644
--- a/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view.cc
+++ b/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view.cc
@@ -27,9 +27,14 @@
         CardUnmaskAuthenticationSelectionDialogController* controller)
     : controller_(controller) {
   SetShowTitle(true);
-  SetButtonLabel(ui::DIALOG_BUTTON_OK, controller_->GetOkButtonLabel());
+
+  // Set the cancel button label now because it is constant throughout the
+  // view's lifecycle. The ok button label will be set later once we have more
+  // details on the challenge options that will be displayed in the dialog,
+  // since the label can change based on the challenge options.
   SetButtonLabel(ui::DIALOG_BUTTON_CANCEL,
                  GetDialogButtonLabel(ui::DIALOG_BUTTON_CANCEL));
+
   SetModalType(ui::MODAL_TYPE_CHILD);
   SetShowCloseButton(false);
   set_fixed_width(ChromeLayoutProvider::Get()->GetDistanceMetric(
@@ -158,7 +163,6 @@
       // checked.
       if (it == challenge_options.begin()) {
         challenge_option_radio_button->SetChecked(true);
-        controller_->SetSelectedChallengeOptionId((*it).id);
       }
 
       // Only add padding and another row if it isn't the last challenge option
@@ -182,7 +186,7 @@
 
     // Since there's only one challenge option, the selected challenge
     // option id will always be the first one.
-    controller_->SetSelectedChallengeOptionId(challenge_options[0].id);
+    OnChallengeOptionSelected(challenge_options[0].id);
 
     AddChallengeOptionDetails(challenge_options[0], challenge_options_section);
   }
@@ -226,15 +230,22 @@
       controller_->GetProgressLabel()));
 }
 
+void CardUnmaskAuthenticationSelectionDialogView::OnChallengeOptionSelected(
+    const CardUnmaskChallengeOption::ChallengeOptionId&
+        selected_challenge_option_id) {
+  controller_->SetSelectedChallengeOptionId(selected_challenge_option_id);
+  SetButtonLabel(ui::DIALOG_BUTTON_OK, controller_->GetOkButtonLabel());
+}
+
 std::unique_ptr<views::RadioButton>
 CardUnmaskAuthenticationSelectionDialogView::CreateChallengeOptionRadioButton(
     CardUnmaskChallengeOption challenge_option) {
   auto radio_button = std::make_unique<views::RadioButton>();
   radio_button_checked_changed_subscriptions_.push_back(
       radio_button->AddCheckedChangedCallback(base::BindRepeating(
-          &CardUnmaskAuthenticationSelectionDialogController::
-              SetSelectedChallengeOptionId,
-          base::Unretained(controller_), challenge_option.id)));
+          &CardUnmaskAuthenticationSelectionDialogView::
+              OnChallengeOptionSelected,
+          weak_ptr_factory_.GetWeakPtr(), challenge_option.id)));
   radio_button->SetAccessibleName(
       controller_->GetAuthenticationModeLabel(challenge_option) + u". " +
       challenge_option.challenge_info);
diff --git a/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view.h b/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view.h
index 9d7ab32..fc3bc56 100644
--- a/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view.h
+++ b/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view.h
@@ -61,8 +61,11 @@
   void ReplaceContentWithProgressThrobber();
 
   // Sets the selected challenge option id in the
-  // CardUnmaskAuthenticationSelectionDialogController.
-  void SetSelectedChallengeOptionId(std::string selected_challenge_option_id);
+  // CardUnmaskAuthenticationSelectionDialogController, as well as updates the
+  // accept button text based on the challenge option.
+  void OnChallengeOptionSelected(
+      const CardUnmaskChallengeOption::ChallengeOptionId&
+          selected_challenge_option_id);
 
   // Creates a radio button with a callback to SetSelectedChallengeOptionId.
   std::unique_ptr<views::RadioButton> CreateChallengeOptionRadioButton(
@@ -78,6 +81,9 @@
   // used.
   std::vector<base::CallbackListSubscription>
       radio_button_checked_changed_subscriptions_;
+
+  base::WeakPtrFactory<CardUnmaskAuthenticationSelectionDialogView>
+      weak_ptr_factory_{this};
 };
 
 }  // namespace autofill
diff --git a/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc b/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc
index 8ceaacf..e9e5917 100644
--- a/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc
@@ -35,7 +35,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "components/lookalikes/core/features.h"
 #include "components/lookalikes/core/lookalike_url_util.h"
 #include "components/lookalikes/core/safety_tip_test_utils.h"
 #include "components/lookalikes/core/safety_tips.pb.h"
@@ -70,6 +69,9 @@
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_observer.h"
 
+using lookalikes::kInterstitialHistogramName;
+using lookalikes::NavigationSuggestionEvent;
+
 namespace {
 
 enum class UIStatus {
@@ -255,7 +257,7 @@
 
     LookalikeTestHelper::SetUpLookalikeTestParams();
     // Check that the test top domain list contains google.
-    ASSERT_TRUE(IsTopDomain(GetDomainInfo("google.com")));
+    ASSERT_TRUE(IsTopDomain(lookalikes::GetDomainInfo("google.com")));
 
     InProcessBrowserTest::SetUpOnMainThread();
   }
@@ -556,7 +558,7 @@
       // This doesn't show a safety tip.
       "g0ogle.com"};
 
-  SetEnterpriseAllowlistForTesting(
+  lookalikes::SetEnterpriseAllowlistForTesting(
       browser()->profile()->GetPrefs(),
       {"accounts1-google.com", "bla.accounts2-google.com", "g0ogle.com"});
 
@@ -958,7 +960,7 @@
   NavigateToURL(browser(), kNavigatedUrl, WindowOpenDisposition::CURRENT_TAB);
   EXPECT_FALSE(IsUIShowing());
 
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 0);
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 0);
 
   // TODO(crbug.com/1401102): This shouldn't record metrics.
   test_helper()->CheckSafetyTipUkmCount(1);
@@ -971,7 +973,7 @@
 IN_PROC_BROWSER_TEST_F(
     SafetyTipPageInfoBubbleViewBrowserTest,
     DoesntTriggerOnCharacterSwap_TopSiteWithDifferentRegistry) {
-  ASSERT_TRUE(IsTopDomain(GetDomainInfo("google.rs")));
+  ASSERT_TRUE(IsTopDomain(lookalikes::GetDomainInfo("google.rs")));
 
   base::HistogramTester histograms;
   // google.sr is within one character swap of google.rs which is a top domain.
@@ -986,7 +988,7 @@
   // recorded.
   EXPECT_FALSE(IsUIShowing());
 
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 0);
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 0);
   test_helper()->CheckNoLookalikeUkm();
 }
 
@@ -1241,8 +1243,8 @@
 
   // Make sure that the UI isn't showing but interstitial histogram is recorded.
   ASSERT_FALSE(IsUIShowing());
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 1);
-  histograms.ExpectBucketCount(lookalikes::kHistogramName,
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 1);
+  histograms.ExpectBucketCount(kInterstitialHistogramName,
                                NavigationSuggestionEvent::kComboSquatting, 1);
 
   ASSERT_NO_FATAL_FAILURE(CheckPageInfoDoesNotShowSafetyTipInfo(browser()));
@@ -1395,8 +1397,8 @@
   histograms.ExpectBucketCount(kSafetyTipShownHistogram,
                                security_state::SafetyTipStatus::kLookalike, 1);
   // Lookalike throttle also records an entry for all heuristic matches.
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 1);
-  histograms.ExpectBucketCount(lookalikes::kHistogramName,
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 1);
+  histograms.ExpectBucketCount(kInterstitialHistogramName,
                                NavigationSuggestionEvent::kComboSquatting, 1);
 
   // Make sure that the UI is now showing, and that no UKM data has been
@@ -1455,7 +1457,7 @@
   // Make sure that the UI is not showing, and that no histogram has been
   // recorded.
   ASSERT_FALSE(IsUIShowing());
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 0);
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 0);
 
   // TODO(crbug.com/1401102): This shouldn't record a UKM.
   test_helper()->CheckSafetyTipUkmCount(1);
@@ -1481,8 +1483,8 @@
   histograms.ExpectBucketCount(kSafetyTipShownHistogram,
                                security_state::SafetyTipStatus::kLookalike, 1);
   // Lookalike throttle always records an entry for heuristic matches.
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 1);
-  histograms.ExpectBucketCount(lookalikes::kHistogramName,
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 1);
+  histograms.ExpectBucketCount(kInterstitialHistogramName,
                                NavigationSuggestionEvent::kComboSquatting, 1);
 
   // Make sure that the UI is now showing, and that no UKM data has been
@@ -1541,9 +1543,9 @@
                                security_state::SafetyTipStatus::kLookalike, 1);
   // Lookalike navigation throttle always records an entry for heuristic
   // matches.
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 1);
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 1);
   histograms.ExpectBucketCount(
-      lookalikes::kHistogramName,
+      kInterstitialHistogramName,
       NavigationSuggestionEvent::kComboSquattingSiteEngagement, 1);
 
   // Make sure that the UI is now showing, and that no UKM data has been
@@ -1593,8 +1595,8 @@
 
   NavigateToURL(browser(), kNavigatedUrl, WindowOpenDisposition::CURRENT_TAB);
 
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 1);
-  histograms.ExpectBucketCount(lookalikes::kHistogramName,
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 1);
+  histograms.ExpectBucketCount(kInterstitialHistogramName,
                                NavigationSuggestionEvent::kComboSquatting, 1);
 
   // Make sure that the UI is not showing, and that no safety tip UKM has been
@@ -1618,9 +1620,9 @@
 
   NavigateToURL(browser(), kNavigatedUrl, WindowOpenDisposition::CURRENT_TAB);
 
-  histograms.ExpectTotalCount(lookalikes::kHistogramName, 1);
+  histograms.ExpectTotalCount(kInterstitialHistogramName, 1);
   histograms.ExpectBucketCount(
-      lookalikes::kHistogramName,
+      kInterstitialHistogramName,
       NavigationSuggestionEvent::kComboSquattingSiteEngagement, 1);
 
   // Make sure that the UI is not showing, and that no safety tip UKM has been
diff --git a/chrome/browser/ui/views/side_panel/lens/lens_core_tab_side_panel_helper.cc b/chrome/browser/ui/views/side_panel/lens/lens_core_tab_side_panel_helper.cc
new file mode 100644
index 0000000..80a99c1
--- /dev/null
+++ b/chrome/browser/ui/views/side_panel/lens/lens_core_tab_side_panel_helper.cc
@@ -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.
+
+#include "chrome/browser/ui/lens/lens_core_tab_side_panel_helper.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "components/lens/buildflags.h"
+#include "components/lens/lens_features.h"
+#include "components/search/search.h"
+#include "extensions/buildflags/buildflags.h"
+
+#if BUILDFLAG(IS_ANDROID)
+#include "chrome/browser/android/tab_android.h"
+#else
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
+#endif  // BUILDFLAG(IS_ANDROID)
+
+namespace lens {
+namespace internal {
+
+bool IsSidePanelEnabled(content::WebContents* web_contents) {
+#if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+  return GetTemplateURLService(web_contents)
+             ->IsSideImageSearchSupportedForDefaultSearchProvider() &&
+         !IsInProgressiveWebApp(web_contents);
+#else
+  return false;
+#endif
+}
+
+bool IsInProgressiveWebApp(content::WebContents* web_contents) {
+#if !BUILDFLAG(IS_ANDROID)
+  Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
+  return browser && (browser->is_type_app() || browser->is_type_app_popup());
+#else
+  return false;
+#endif  // !BUILDFLAG(IS_ANDROID)
+}
+
+TemplateURLService* GetTemplateURLService(content::WebContents* web_contents) {
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  DCHECK(profile);
+  TemplateURLService* template_url_service =
+      TemplateURLServiceFactory::GetForProfile(profile);
+  DCHECK(template_url_service);
+  return template_url_service;
+}
+
+}  // namespace internal
+
+bool IsSidePanelEnabledForLens(content::WebContents* web_contents) {
+  return search::DefaultSearchProviderIsGoogle(
+             lens::internal::GetTemplateURLService(web_contents)) &&
+         lens::internal::IsSidePanelEnabled(web_contents) &&
+         lens::features::IsLensSidePanelEnabled();
+}
+
+bool IsSidePanelEnabledForLensRegionSearch(content::WebContents* web_contents) {
+  return IsSidePanelEnabledForLens(web_contents) &&
+         lens::features::IsLensSidePanelEnabledForRegionSearch();
+}
+
+bool IsSidePanelEnabledFor3PDse(content::WebContents* web_contents) {
+  return lens::internal::IsSidePanelEnabled(web_contents) &&
+         !search::DefaultSearchProviderIsGoogle(
+             lens::internal::GetTemplateURLService(web_contents)) &&
+         lens::features::GetEnableImageSearchUnifiedSidePanelFor3PDse();
+}
+
+}  // namespace lens
diff --git a/chrome/browser/ui/views/side_panel/lens/lens_core_tab_side_panel_helper_browsertest.cc b/chrome/browser/ui/views/side_panel/lens/lens_core_tab_side_panel_helper_browsertest.cc
new file mode 100644
index 0000000..e91b8bc
--- /dev/null
+++ b/chrome/browser/ui/views/side_panel/lens/lens_core_tab_side_panel_helper_browsertest.cc
@@ -0,0 +1,383 @@
+// 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/search_engines/template_url_service_factory.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/lens/lens_core_tab_side_panel_helper.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/search_test_utils.h"
+#include "components/lens/buildflags.h"
+#include "components/lens/lens_features.h"
+#include "components/search_engines/template_url_service.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "extensions/buildflags/buildflags.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace lens {
+class LensCoreTabSidePanelHelperBrowserTest : public InProcessBrowserTest {
+ protected:
+  void SetUp() override {
+    // The test server must start first, so that we know the port that the test
+    // server is using.
+    ASSERT_TRUE(embedded_test_server()->Start());
+    base::test::ScopedFeatureList feature_list;
+    feature_list.InitWithFeaturesAndParameters(
+        {
+            {lens::features::kLensStandalone,
+             {{lens::features::kEnableSidePanelForLens.name, "true"}}},
+        },
+        {});
+
+    InProcessBrowserTest::SetUp();
+  }
+
+  GURL GetImageSearchURL() {
+    constexpr char kImageSearchURL[] = "/imagesearch?p=somepayload";
+    return embedded_test_server()->GetURL(kImageSearchURL);
+  }
+
+  void SetGoogleToOptOutOfSidePanel() {
+    TemplateURLService* model =
+        TemplateURLServiceFactory::GetForProfile(browser()->profile());
+    ASSERT_TRUE(model);
+    search_test_utils::WaitForTemplateURLServiceToLoad(model);
+    ASSERT_TRUE(model->loaded());
+    TemplateURLData data;
+    data.side_image_search_param = "";
+    // This should trigger DefaultSearchProviderIsGoogle to true.
+    data.SetURL("http://www.google.com/");
+
+    TemplateURL* template_url = model->Add(std::make_unique<TemplateURL>(data));
+    ASSERT_TRUE(template_url);
+    model->SetUserSelectedDefaultSearchProvider(template_url);
+  }
+
+  void Setup3PImageSearchEngine(bool support_side_panel) {
+    constexpr char kSearchURL[] = "/search?q={searchTerms}";
+    TemplateURLService* model =
+        TemplateURLServiceFactory::GetForProfile(browser()->profile());
+    ASSERT_TRUE(model);
+    search_test_utils::WaitForTemplateURLServiceToLoad(model);
+    ASSERT_TRUE(model->loaded());
+
+    TemplateURLData data;
+    data.SetURL(embedded_test_server()->GetURL(kSearchURL).spec());
+    data.side_image_search_param = support_side_panel ? "sideimagesearch" : "";
+
+    TemplateURL* template_url = model->Add(std::make_unique<TemplateURL>(data));
+    ASSERT_TRUE(template_url);
+    model->SetUserSelectedDefaultSearchProvider(template_url);
+  }
+
+  content::WebContents* GetBrowserWebContents() {
+    return BrowserView::GetBrowserViewForBrowser(browser())
+        ->GetActiveWebContents();
+  }
+
+  content::WebContents* GetPwaWebContents() {
+    // Creates a Progressive Web App and set it to the default browser
+    Browser* pwa_browser = InProcessBrowserTest::CreateBrowserForApp(
+        "test_app", browser()->profile());
+    CloseBrowserSynchronously(browser());
+    SelectFirstBrowser();
+
+    EXPECT_TRUE(pwa_browser->is_type_app());
+
+    return BrowserView::GetBrowserViewForBrowser(pwa_browser)
+        ->GetActiveWebContents();
+  }
+};
+
+#if BUILDFLAG(IS_ANDROID)
+IN_PROC_BROWSER_TEST_F(LensCoreTabSidePanelHelperBrowserTest,
+                       IsSidePanelEnabledForLensReturnsFalseForAndroid) {
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledForLens(web_contents));
+}
+#endif  // BUILDFLAG(IS_ANDROID)
+
+#if !BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+IN_PROC_BROWSER_TEST_F(
+    LensCoreTabSidePanelHelperBrowserTest,
+    IsSidePanelEnabledForLensReturnsFalseIfGoogleBrandedFeaturesAreDisabled) {
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledForLens(web_contents));
+}
+#endif  // !BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+
+#if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+//  IsSidePanelEnabledForLens
+IN_PROC_BROWSER_TEST_F(LensCoreTabSidePanelHelperBrowserTest,
+                       IsSidePanelEnabledForLensReturnsFalseForPwa) {
+  auto* pwa_web_contents = GetPwaWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledForLens(pwa_web_contents));
+}
+
+IN_PROC_BROWSER_TEST_F(LensCoreTabSidePanelHelperBrowserTest,
+                       IsSidePanelEnabledForLensReturnsTrueForBrowser) {
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_TRUE(lens::IsSidePanelEnabledForLens(web_contents));
+}
+
+IN_PROC_BROWSER_TEST_F(
+    LensCoreTabSidePanelHelperBrowserTest,
+    IsSidePanelEnabledForLensReturnsFalseForBrowserIfOptedOutInTemplateUrl) {
+  SetGoogleToOptOutOfSidePanel();
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledForLens(web_contents));
+}
+
+IN_PROC_BROWSER_TEST_F(LensCoreTabSidePanelHelperBrowserTest,
+                       IsSidePanelEnabledForLensReturnsFalseFor3PDse) {
+  Setup3PImageSearchEngine(/*support_side_panel*/ true);
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledForLens(web_contents));
+}
+#endif  // BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+
+class LensCoreTabSidePanelHelperLensStandaloneDisabled
+    : public LensCoreTabSidePanelHelperBrowserTest {
+ protected:
+  void SetUp() override {
+    // The test server must start first, so that we know the port that the
+    // server is using.
+    ASSERT_TRUE(embedded_test_server()->Start());
+    base::test::ScopedFeatureList feature_list;
+    feature_list.InitWithFeaturesAndParameters(
+        {{}, {}}, {{lens::features::kLensStandalone}});
+    InProcessBrowserTest::SetUp();
+  }
+};
+
+#if BUILDFLAG(IS_ANDROID)
+IN_PROC_BROWSER_TEST_F(LensCoreTabSidePanelHelperLensStandaloneDisabled,
+                       IsSidePanelEnabledForLensReturnsFalseForAndroid) {
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledForLens(web_contents));
+}
+#endif  // BUILDFLAG(IS_ANDROID)
+
+#if !BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+IN_PROC_BROWSER_TEST_F(
+    LensCoreTabSidePanelHelperLensStandaloneDisabled,
+    IsSidePanelEnabledForLensReturnsFalseIfGoogleBrandedFeaturesAreDisabled) {
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledForLens(web_contents));
+}
+#endif  // !BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+
+#if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+IN_PROC_BROWSER_TEST_F(LensCoreTabSidePanelHelperLensStandaloneDisabled,
+                       IsSidePanelEnabledForLensReturnsFalse) {
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledForLens(web_contents));
+}
+
+IN_PROC_BROWSER_TEST_F(LensCoreTabSidePanelHelperLensStandaloneDisabled,
+                       IsSidePanelEnabledForLensRegionSearchReturnsFalse) {
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledForLensRegionSearch(web_contents));
+}
+
+IN_PROC_BROWSER_TEST_F(LensCoreTabSidePanelHelperLensStandaloneDisabled,
+                       IsSidePanelEnabledForLensReturnsFalseForPwa) {
+  auto* web_contents = GetPwaWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledForLens(web_contents));
+}
+#endif  // BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+
+class LensCoreTabSidePanelHelperRegionSearchBrowserTest
+    : public LensCoreTabSidePanelHelperBrowserTest {
+ protected:
+  void SetUp() override {
+    // The test server must start first, so that we know the port that the
+    // server is using.
+    ASSERT_TRUE(embedded_test_server()->Start());
+    base::test::ScopedFeatureList feature_list;
+    feature_list.InitWithFeaturesAndParameters(
+        {
+            {lens::features::kLensStandalone,
+             {{lens::features::kEnableSidePanelForLens.name, "true"},
+              {lens::features::kHomepageURLForLens.name,
+               GetLensRegionSearchURL().spec()}}},
+
+        },
+        {});
+    InProcessBrowserTest::SetUp();
+  }
+
+  GURL GetLensRegionSearchURL() {
+    static const std::string kLensRegionSearchURL =
+        lens::features::GetHomepageURLForLens() + "upload?ep=crs";
+    return GURL(kLensRegionSearchURL);
+  }
+};
+
+#if BUILDFLAG(IS_ANDROID)
+IN_PROC_BROWSER_TEST_F(
+    LensCoreTabSidePanelHelperRegionSearchBrowserTest,
+    IsSidePanelEnabledForLensRegionSearchReturnsFalseForAndroid) {
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledForLensRegionSearch(web_contents));
+}
+#endif  // BUILDFLAG(IS_ANDROID)
+
+#if !BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+IN_PROC_BROWSER_TEST_F(
+    LensCoreTabSidePanelHelperRegionSearchBrowserTest,
+    IsSidePanelEnabledForLensRegionSearchReturnsFalseIfGoogleBrandedFeaturesAreDisabled) {
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledForLensRegionSearch(web_contents));
+}
+#endif  // !BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+
+#if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+// IsSidePanelEnabledForLensRegionSearch
+IN_PROC_BROWSER_TEST_F(
+    LensCoreTabSidePanelHelperRegionSearchBrowserTest,
+    IsSidePanelEnabledForLensRegionSearchReturnsTrueIfEnabled) {
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_TRUE(lens::IsSidePanelEnabledForLensRegionSearch(web_contents));
+}
+
+IN_PROC_BROWSER_TEST_F(
+    LensCoreTabSidePanelHelperRegionSearchBrowserTest,
+    IsSidePanelEnabledForLensRegionSearchReturnsFalseForPwa) {
+  auto* web_contents = GetPwaWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledForLensRegionSearch(web_contents));
+}
+
+IN_PROC_BROWSER_TEST_F(
+    LensCoreTabSidePanelHelperRegionSearchBrowserTest,
+    IsSidePanelEnabledForLensRegionSearchReturnsFalseIfOptedOutInTemplateUrl) {
+  SetGoogleToOptOutOfSidePanel();
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledForLensRegionSearch(web_contents));
+}
+
+IN_PROC_BROWSER_TEST_F(
+    LensCoreTabSidePanelHelperRegionSearchBrowserTest,
+    IsSidePanelEnabledForLensRegionSearchReturnsFalseFor3PDse) {
+  Setup3PImageSearchEngine(/*support_side_panel*/ true);
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledForLensRegionSearch(web_contents));
+}
+
+#endif  // BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+
+class LensCoreTabSidePanelHelper3PDseEnabled
+    : public LensCoreTabSidePanelHelperBrowserTest {
+ protected:
+  void SetUp() override {
+    // The test server must start first, so that we know the port that the
+    // server is using.
+    ASSERT_TRUE(embedded_test_server()->Start());
+
+    base::test::ScopedFeatureList features;
+    features.InitWithFeaturesAndParameters(
+        {{lens::features::kEnableImageSearchSidePanelFor3PDse, {{}}}}, {});
+
+    InProcessBrowserTest::SetUp();
+  }
+};
+
+#if BUILDFLAG(IS_ANDROID)
+IN_PROC_BROWSER_TEST_F(LensCoreTabSidePanelHelper3PDseEnabled,
+                       IsSidePanelEnabledFor3PDseReturnsFalseForAndroid) {
+  Setup3PImageSearchEngine(/*support_side_panel*/ true);
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledFor3PDse(web_contents));
+}
+#endif  // BUILDFLAG(IS_ANDROID)
+
+#if !BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+IN_PROC_BROWSER_TEST_F(
+    LensCoreTabSidePanelHelper3PDseEnabled,
+    IsSidePanelEnabledFor3PDseReturnsFalseIfGoogleBrandedFeaturesAreDisabled) {
+  Setup3PImageSearchEngine(/*support_side_panel*/ true);
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledFor3PDse(web_contents));
+}
+#endif  // !BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+
+#if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+
+//  IsSidePanelEnabledFor3PDse
+IN_PROC_BROWSER_TEST_F(LensCoreTabSidePanelHelper3PDseEnabled,
+                       IsSidePanelEnabledFor3PDseReturnsTrue) {
+  Setup3PImageSearchEngine(/*support_side_panel*/ true);
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_TRUE(lens::IsSidePanelEnabledFor3PDse(web_contents));
+}
+
+IN_PROC_BROWSER_TEST_F(LensCoreTabSidePanelHelper3PDseEnabled,
+                       IsSidePanelEnabledFor3PDseReturnsFalseIf3POptedOut) {
+  Setup3PImageSearchEngine(/*support_side_panel*/ false);
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledFor3PDse(web_contents));
+}
+
+IN_PROC_BROWSER_TEST_F(LensCoreTabSidePanelHelper3PDseEnabled,
+                       IsSidePanelEnabledFor3PDseReturnsFalseForPwa) {
+  Setup3PImageSearchEngine(/*support_side_panel*/ true);
+  auto* pwa_web_contents = GetPwaWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledFor3PDse(pwa_web_contents));
+}
+
+IN_PROC_BROWSER_TEST_F(LensCoreTabSidePanelHelper3PDseEnabled,
+                       IsSidePanelEnabledFor3PDseReturnsFalseForGoogle) {
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledFor3PDse(web_contents));
+}
+class LensCoreTabSidePanelHelper3PDseDisabledUsingFlag
+    : public LensCoreTabSidePanelHelperBrowserTest {
+ protected:
+  void SetUp() override {
+    // The test server must start first, so that we know the port that the
+    // server is using.
+    ASSERT_TRUE(embedded_test_server()->Start());
+
+    base::test::ScopedFeatureList features;
+    features.InitWithFeaturesAndParameters(
+        {{}, {}}, {{lens::features::kEnableImageSearchSidePanelFor3PDse}});
+
+    InProcessBrowserTest::SetUp();
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(LensCoreTabSidePanelHelper3PDseDisabledUsingFlag,
+                       IsSidePanelEnabledFor3PDseReturnsFalse) {
+  Setup3PImageSearchEngine(/*support_side_panel*/ true);
+  auto* web_contents = GetBrowserWebContents();
+
+  EXPECT_FALSE(lens::IsSidePanelEnabledFor3PDse(web_contents));
+}
+#endif  // BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+}  // namespace lens
diff --git a/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator_browsertest.cc b/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator_browsertest.cc
index a6fe6b2..4d83f56 100644
--- a/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator_browsertest.cc
+++ b/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator_browsertest.cc
@@ -52,8 +52,11 @@
 namespace {
 
 constexpr char kCloseAction[] = "LensUnifiedSidePanel.HideSidePanel";
-constexpr char kExpectedSidePanelContentUrlRegex[] =
-    ".*ep=ccm&re=dcsp&s=4&st=\\d+&p=somepayload&sideimagesearch=1";
+constexpr char kExpectedLensSidePanelContentUrlRegex[] =
+    ".*ep=ccm&re=dcsp&s=4&st=\\d+&lm=.+&p=somepayload&ep=ccmupload&"
+    "sideimagesearch=1";
+constexpr char kExpected3PDseSidePanelContentUrlRegex[] =
+    ".*p=somepayload&sideimagesearch=1";
 constexpr char kExpectedNewTabContentUrlRegex[] = ".*p=somepayload";
 
 // Maintains image search test state. In particular, note that |menu_observer_|
@@ -79,13 +82,18 @@
     InProcessBrowserTest::SetUp();
   }
 
-  void SetupUnifiedSidePanel() {
+  void SetupUnifiedSidePanel(bool for_google = true) {
     SetupAndLoadValidImagePage();
     // Ensures that the lens side panel coordinator is open and is valid when
     // running the search.
     lens::CreateLensUnifiedSidePanelEntryForTesting(browser());
     // The browser should open a side panel with the image.
-    AttemptLensImageSearch();
+
+    if (for_google) {
+      AttemptLensImageSearch();
+    } else {
+      Attempt3pDseImageSearch();
+    }
 
     // We need to verify the contents before opening the side panel.
     content::WebContents* contents =
@@ -206,8 +214,7 @@
 };
 
 IN_PROC_BROWSER_TEST_F(SearchImageWithUnifiedSidePanel,
-                       ImageSearchWithValidImageOpensUnifiedSidePanel) {
-  SetupImageSearchEngine();
+                       ImageSearchWithValidImageOpensUnifiedSidePanelForLens) {
   SetupUnifiedSidePanel();
   EXPECT_TRUE(GetUnifiedSidePanel()->GetVisible());
 
@@ -223,11 +230,31 @@
   EXPECT_TRUE(GetLensSidePanelCoordinator()->IsLaunchButtonEnabledForTesting());
   // Match the query parameters, without the value of start_time.
   EXPECT_THAT(side_panel_content,
-              testing::MatchesRegex(kExpectedSidePanelContentUrlRegex));
+              testing::MatchesRegex(kExpectedLensSidePanelContentUrlRegex));
   ExpectThatRequestContainsImageData(contents);
 }
 
 IN_PROC_BROWSER_TEST_F(SearchImageWithUnifiedSidePanel,
+                       ImageSearchWithValidImageOpensUnifiedSidePanelFor3PDse) {
+  SetupImageSearchEngine();
+  SetupUnifiedSidePanel(/**for_google*/ false);
+  EXPECT_TRUE(GetUnifiedSidePanel()->GetVisible());
+
+  content::WebContents* contents =
+      lens::GetLensUnifiedSidePanelWebContentsForTesting(browser());
+
+  std::string expected_content = GetImageSearchURL().GetContent();
+  std::string side_panel_content = contents->GetLastCommittedURL().GetContent();
+  // Match strings up to the query.
+  std::size_t query_start_pos = side_panel_content.find("?");
+  EXPECT_EQ(expected_content.substr(0, query_start_pos),
+            side_panel_content.substr(0, query_start_pos));
+  EXPECT_TRUE(GetLensSidePanelCoordinator()->IsLaunchButtonEnabledForTesting());
+  EXPECT_THAT(side_panel_content,
+              testing::MatchesRegex(kExpected3PDseSidePanelContentUrlRegex));
+}
+
+IN_PROC_BROWSER_TEST_F(SearchImageWithUnifiedSidePanel,
                        EnablesOpenInNewTabForLensErrorUrl) {
   SetupUnifiedSidePanel();
   EXPECT_TRUE(GetUnifiedSidePanel()->GetVisible());
@@ -430,27 +457,4 @@
   std::string side_panel_content = contents->GetLastCommittedURL().GetContent();
   EXPECT_NE(side_panel_content, new_tab_content);
 }
-
-IN_PROC_BROWSER_TEST_F(SearchImageWithSidePanel3PDseDisabled,
-                       ImageSearchForLensWithValidImageOpensInSidePanel) {
-  SetupImageSearchEngine();
-  SetupUnifiedSidePanel();
-  EXPECT_TRUE(GetUnifiedSidePanel()->GetVisible());
-
-  content::WebContents* contents =
-      lens::GetLensUnifiedSidePanelWebContentsForTesting(browser());
-
-  std::string expected_content = GetLensImageSearchURL().GetContent();
-  std::string side_panel_content = contents->GetLastCommittedURL().GetContent();
-  // Match strings up to the query.
-  std::size_t query_start_pos = side_panel_content.find("?");
-  EXPECT_EQ(expected_content.substr(0, query_start_pos),
-            side_panel_content.substr(0, query_start_pos));
-  EXPECT_TRUE(GetLensSidePanelCoordinator()->IsLaunchButtonEnabledForTesting());
-  // Match the query parameters, without the value of start_time.
-  EXPECT_THAT(side_panel_content,
-              testing::MatchesRegex(kExpectedSidePanelContentUrlRegex));
-  ExpectThatRequestContainsImageData(contents);
-}
-
 }  // namespace
diff --git a/chrome/browser/ui/views/user_education/browser_user_education_service.cc b/chrome/browser/ui/views/user_education/browser_user_education_service.cc
index d2897db..4e67a04 100644
--- a/chrome/browser/ui/views/user_education/browser_user_education_service.cc
+++ b/chrome/browser/ui/views/user_education/browser_user_education_service.cc
@@ -35,10 +35,14 @@
 #include "components/user_education/common/tutorial_registry.h"
 #include "components/user_education/views/help_bubble_delegate.h"
 #include "components/user_education/views/help_bubble_factory_views.h"
+#include "components/user_education/webui/floating_webui_help_bubble_factory.h"
+#include "components/user_education/webui/help_bubble_handler.h"
 #include "components/user_education/webui/help_bubble_webui.h"
+#include "components/user_education/webui/tracked_element_webui.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/interaction/element_identifier.h"
 #include "ui/base/interaction/element_tracker.h"
+#include "ui/base/interaction/framework_specific_implementation.h"
 #include "ui/base/interaction/interaction_sequence.h"
 #include "ui/color/color_id.h"
 #include "ui/views/interaction/element_tracker_views.h"
@@ -119,6 +123,43 @@
   }
 };
 
+// Help bubble factory that can show a floating (Views-based) help bubble on a
+// WebUI element, but only for non-tab WebUI.
+class FloatingWebUIHelpBubbleFactoryBrowser
+    : public user_education::FloatingWebUIHelpBubbleFactory {
+ public:
+  explicit FloatingWebUIHelpBubbleFactoryBrowser(
+      const user_education::HelpBubbleDelegate* delegate)
+      : FloatingWebUIHelpBubbleFactory(delegate) {}
+  ~FloatingWebUIHelpBubbleFactoryBrowser() override = default;
+
+  DECLARE_FRAMEWORK_SPECIFIC_METADATA()
+
+  // HelpBubbleFactoryWebUIViews:
+  bool CanBuildBubbleForTrackedElement(
+      const ui::TrackedElement* element) const override {
+    if (!element->IsA<user_education::TrackedElementWebUI>()) {
+      return false;
+    }
+
+    // If this is a WebUI in a tab, then don't use this factory.
+    const auto* contents = element->AsA<user_education::TrackedElementWebUI>()
+                               ->handler()
+                               ->GetWebContents();
+    // Note: this checks all tabs for their WebContents.
+    if (chrome::FindBrowserWithWebContents(contents)) {
+      return false;
+    }
+
+    // Ensure that this WebUI fulfils the requirements for a floating help
+    // bubble.
+    return FloatingWebUIHelpBubbleFactory::CanBuildBubbleForTrackedElement(
+        element);
+  }
+};
+
+DEFINE_FRAMEWORK_SPECIFIC_METADATA(FloatingWebUIHelpBubbleFactoryBrowser)
+
 }  // namespace
 
 const char kTabGroupTutorialId[] = "Tab Group Tutorial";
@@ -137,6 +178,9 @@
   const user_education::HelpBubbleDelegate* const delegate =
       GetHelpBubbleDelegate();
   registry.MaybeRegister<user_education::HelpBubbleFactoryViews>(delegate);
+  // Try to create a floating bubble first, if it's allowed.
+  registry.MaybeRegister<FloatingWebUIHelpBubbleFactoryBrowser>(delegate);
+  // Fall back to in-WebUI help bubble if the floating bubble doesn't apply.
   registry.MaybeRegister<user_education::HelpBubbleFactoryWebUI>();
 #if BUILDFLAG(IS_MAC)
   registry.MaybeRegister<user_education::HelpBubbleFactoryMac>(delegate);
@@ -480,7 +524,7 @@
         0, IDS_TUTORIAL_SIDE_PANEL_READING_LIST_ADD_TAB,
         ui::InteractionSequence::StepType::kShown,
         kAddCurrentTabToReadingListElementId, std::string(),
-        HelpBubbleArrow::kTopLeft, ui::CustomElementEventType(), absl::nullopt,
+        HelpBubbleArrow::kRightTop, ui::CustomElementEventType(), absl::nullopt,
         /* transition_only_on_event =*/false,
         user_education::TutorialDescription::NameElementsCallback(),
         TutorialDescription::ContextMode::kAny);
@@ -506,7 +550,7 @@
     TutorialDescription::Step mark_as_read_step(
         0, IDS_TUTORIAL_SIDE_PANEL_READING_LIST_MARK_READ,
         ui::InteractionSequence::StepType::kShown, ui::ElementIdentifier(),
-        kReadingListItemElementName, HelpBubbleArrow::kTopLeft);
+        kReadingListItemElementName, HelpBubbleArrow::kRightTop);
     side_panel_description.steps.emplace_back(mark_as_read_step);
 
     TutorialDescription::Step detect_mark_as_read_step(
diff --git a/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc b/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc
new file mode 100644
index 0000000..48d9f2c
--- /dev/null
+++ b/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc
@@ -0,0 +1,140 @@
+// 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 <utility>
+
+#include "base/callback_forward.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/bind.h"
+#include "build/build_config.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_element_identifiers.h"
+#include "chrome/browser/ui/side_search/side_search_config.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/side_panel/side_panel_entry.h"
+#include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "chrome/browser/ui/views/user_education/browser_feature_promo_controller.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/interaction/interaction_test_util_browser.h"
+#include "chrome/test/interaction/interactive_browser_test.h"
+#include "chrome/test/interaction/widget_focus_waiter.h"
+#include "components/user_education/common/help_bubble_factory_registry.h"
+#include "components/user_education/common/help_bubble_params.h"
+#include "components/user_education/views/help_bubble_view.h"
+#include "components/user_education/webui/floating_webui_help_bubble_factory.h"
+#include "components/user_education/webui/help_bubble_webui.h"
+#include "content/public/test/browser_test.h"
+#include "ui/base/interaction/element_identifier.h"
+#include "ui/base/interaction/element_tracker.h"
+#include "ui/views/interaction/element_tracker_views.h"
+#include "ui/views/test/widget_test.h"
+
+namespace {
+constexpr char16_t kBubbleBodyText[] = u"Bubble body text.";
+constexpr char16_t kBubbleButtonText[] = u"Button";
+constexpr char16_t kCloseButtonAltText[] = u"Close";
+}  // namespace
+
+class HelpBubbleFactoryWebUIInteractiveUiTest : public InteractiveBrowserTest {
+ public:
+  HelpBubbleFactoryWebUIInteractiveUiTest() = default;
+  ~HelpBubbleFactoryWebUIInteractiveUiTest() override = default;
+
+  void SetUpOnMainThread() override {
+    InteractiveBrowserTest::SetUpOnMainThread();
+    // TODO(crbug.com/1399570): this is a workaround for a side search bug that
+    // can randomly close the side panel.
+    auto* config = SideSearchConfig::Get(browser()->profile());
+    config->set_skip_on_template_url_changed_for_testing(true);
+  }
+
+  auto ShowHelpBubble(ElementSpecifier element) {
+    return InAnyContext(
+        AfterShow(
+            element,
+            base::BindLambdaForTesting(
+                [this](ui::InteractionSequence* seq, ui::TrackedElement* el) {
+                  help_bubble_ = GetHelpBubbleFactory()->CreateHelpBubble(
+                      el, GetHelpBubbleParams());
+                  if (!help_bubble_) {
+                    LOG(ERROR) << "Failed to create help bubble.";
+                    seq->FailForTesting();
+                  }
+                }))
+            .SetDescription("ShowHelpBubble"));
+  }
+
+ protected:
+  std::unique_ptr<user_education::HelpBubble> help_bubble_;
+
+ private:
+  static user_education::HelpBubbleParams GetHelpBubbleParams() {
+    user_education::HelpBubbleButtonParams button_params;
+    button_params.is_default = true;
+    button_params.text = kBubbleButtonText;
+    button_params.callback = base::DoNothing();
+    user_education::HelpBubbleParams params;
+    params.body_text = kBubbleBodyText;
+    params.close_button_alt_text = kCloseButtonAltText;
+    params.buttons.emplace_back(std::move(button_params));
+    return params;
+  }
+
+  user_education::HelpBubbleFactoryRegistry* GetHelpBubbleFactory() {
+    auto* const controller = browser()->window()->GetFeaturePromoController();
+    return static_cast<BrowserFeaturePromoController*>(controller)
+        ->bubble_factory_registry();
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(HelpBubbleFactoryWebUIInteractiveUiTest,
+                       ShowFloatingHelpBubble) {
+  RunTestSequence(
+      // Click on the toolbar button to show the side panel.
+      PressButton(kSidePanelButtonElementId), WaitForShow(kSidePanelElementId),
+      FlushEvents(),
+      SelectDropdownItem(kSidePanelComboboxElementId,
+                         static_cast<int>(SidePanelEntry::Id::kReadingList)),
+      ShowHelpBubble(kAddCurrentTabToReadingListElementId),
+
+      // Expect the help bubble to display with the correct parameters.
+      CheckView(user_education::HelpBubbleView::kHelpBubbleElementIdForTesting,
+                base::BindOnce([](user_education::HelpBubbleView* bubble) {
+                  return bubble->GetDefaultButtonForTesting()->GetText() ==
+                         kBubbleButtonText;
+                })),
+
+      // Expect the bubble to overlap the side panel slightly, as the anchor
+      // element is not flush with the edge of the side panel.
+      CheckView(user_education::HelpBubbleView::kHelpBubbleElementIdForTesting,
+                base::BindOnce(
+                    [](ui::ElementContext context, views::View* bubble) {
+                      const gfx::Rect bubble_rect =
+                          bubble->GetWidget()->GetWindowBoundsInScreen();
+                      const gfx::Rect side_panel_rect =
+                          views::ElementTrackerViews::GetInstance()
+                              ->GetFirstMatchingView(kSidePanelElementId,
+                                                     context)
+                              ->GetBoundsInScreen();
+                      return bubble_rect.Intersects(side_panel_rect);
+                    },
+                    browser()->window()->GetElementContext())));
+}
+
+IN_PROC_BROWSER_TEST_F(HelpBubbleFactoryWebUIInteractiveUiTest,
+                       ShowEmbeddedHelpBubble) {
+  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kBrowserTabId);
+  static const DeepQuery kPathToHelpBubbleBody = {"user-education-internals",
+                                                  "help-bubble", "#topBody"};
+  RunTestSequence(InstrumentTab(kBrowserTabId),
+                  NavigateWebContents(
+                      kBrowserTabId, GURL("chrome://internals/user-education")),
+                  ShowHelpBubble(kWebUIIPHDemoElementIdentifier),
+                  CheckJsResultAt(kBrowserTabId, kPathToHelpBubbleBody,
+                                  "(el) => el.innerText",
+                                  base::UTF16ToUTF8(kBubbleBodyText)));
+}
diff --git a/chrome/browser/ui/views/user_education/help_bubble_view_interactive_uitest.cc b/chrome/browser/ui/views/user_education/help_bubble_view_interactive_uitest.cc
index 400476d1..1b77556 100644
--- a/chrome/browser/ui/views/user_education/help_bubble_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/user_education/help_bubble_view_interactive_uitest.cc
@@ -65,7 +65,7 @@
                 testing::Ne(nullptr)),
       WithView(kAppMenuButtonElementId,
                base::BindLambdaForTesting([this](views::View* button) {
-                 new HelpBubbleView(GetHelpBubbleDelegate(), button,
+                 new HelpBubbleView(GetHelpBubbleDelegate(), {button},
                                     GetBubbleParams());
                })),
       WaitForShow(HelpBubbleView::kHelpBubbleElementIdForTesting),
@@ -112,7 +112,7 @@
                   // bubble.
                   HelpBubbleParams params;
                   params.body_text = u"foo";
-                  new HelpBubbleView(GetHelpBubbleDelegate(), AsView(element),
+                  new HelpBubbleView(GetHelpBubbleDelegate(), {AsView(element)},
                                      std::move(params));
                 })),
       // Activate the help bubble. This should not cause the editor to close.
@@ -159,7 +159,7 @@
   RunTestSequence(
       WithView(kAppMenuButtonElementId,
                base::BindLambdaForTesting([&](views::View* button) {
-                 new HelpBubbleView(GetHelpBubbleDelegate(), button,
+                 new HelpBubbleView(GetHelpBubbleDelegate(), {button},
                                     std::move(params));
                })),
       CheckViewProperty(HelpBubbleView::kDefaultButtonIdForTesting,
diff --git a/chrome/browser/ui/views/user_education/help_bubble_view_timeout_unittest.cc b/chrome/browser/ui/views/user_education/help_bubble_view_timeout_unittest.cc
index c0446b9b..55173037 100644
--- a/chrome/browser/ui/views/user_education/help_bubble_view_timeout_unittest.cc
+++ b/chrome/browser/ui/views/user_education/help_bubble_view_timeout_unittest.cc
@@ -55,7 +55,7 @@
 
   TestHelpBubbleView* CreateHelpBubbleView(HelpBubbleParams params) {
     return new TestHelpBubbleView(GetHelpBubbleDelegate(),
-                                  browser_view()->contents_container(),
+                                  {browser_view()->contents_container()},
                                   std::move(params));
   }
 };
diff --git a/chrome/browser/ui/webui/ash/internet_detail_dialog.cc b/chrome/browser/ui/webui/ash/internet_detail_dialog.cc
index 59de53d..7409cb6 100644
--- a/chrome/browser/ui/webui/ash/internet_detail_dialog.cc
+++ b/chrome/browser/ui/webui/ash/internet_detail_dialog.cc
@@ -172,8 +172,6 @@
       Profile::FromWebUI(web_ui), chrome::kChromeUIInternetDetailDialogHost);
   source->AddBoolean("showTechnologyBadge",
                      !features::IsSeparateNetworkIconsEnabled());
-  source->AddBoolean("captivePortalUI2022",
-                     features::IsCaptivePortalUI2022Enabled());
   source->AddBoolean("apnRevamp", features::IsApnRevampEnabled());
   cellular_setup::AddNonStringLoadTimeData(source);
   AddInternetStrings(source);
diff --git a/chrome/browser/ui/webui/ash/parent_access/parent_access_ui.cc b/chrome/browser/ui/webui/ash/parent_access/parent_access_ui.cc
index eedcf84..f47b057 100644
--- a/chrome/browser/ui/webui/ash/parent_access/parent_access_ui.cc
+++ b/chrome/browser/ui/webui/ash/parent_access/parent_access_ui.cc
@@ -81,12 +81,18 @@
   source->AddResourcePath("parent_access_after.js", IDR_PARENT_ACCESS_AFTER_JS);
   source->AddResourcePath("flows/local_web_approvals_after.js",
                           IDR_LOCAL_WEB_APPROVALS_AFTER_JS);
+  source->AddResourcePath("parent_access_before.js",
+                          IDR_PARENT_ACCESS_BEFORE_JS);
   source->AddResourcePath("parent_access_ui.mojom-webui.js",
                           IDR_PARENT_ACCESS_UI_MOJOM_WEBUI_JS);
   source->AddResourcePath("webview_manager.js",
                           IDR_PARENT_ACCESS_WEBVIEW_MANAGER_JS);
   source->AddResourcePaths(
       base::make_span(kSupervisionResources, kSupervisionResourcesSize));
+  source->AddResourcePath("images/request_approval.svg",
+                          IDR_PARENT_ACCESS_REQUEST_APPROVAL_SVG);
+  source->AddResourcePath("images/request_approval_dark.svg",
+                          IDR_PARENT_ACCESS_REQUEST_APPROVAL_DARK_SVG);
 
   source->UseStringsJs();
   source->SetDefaultResource(IDR_PARENT_ACCESS_HTML);
@@ -95,6 +101,7 @@
       {"pageTitle", IDS_PARENT_ACCESS_PAGE_TITLE},
       {"approveButtonText", IDS_PARENT_ACCESS_AFTER_APPROVE_BUTTON},
       {"denyButtonText", IDS_PARENT_ACCESS_AFTER_DENY_BUTTON},
+      {"askInPersonButtonText", IDS_PARENT_ACCESS_ASK_IN_PERSON_BUTTON},
       {"localWebApprovalsAfterTitle",
        IDS_PARENT_ACCESS_LOCAL_WEB_APPROVALS_AFTER_TITLE},
       {"localWebApprovalsAfterSubtitle",
diff --git a/chrome/browser/ui/webui/internals/internals_ui.cc b/chrome/browser/ui/webui/internals/internals_ui.cc
index 5920dd1..2e7649e 100644
--- a/chrome/browser/ui/webui/internals/internals_ui.cc
+++ b/chrome/browser/ui/webui/internals/internals_ui.cc
@@ -144,8 +144,7 @@
     mojo::PendingReceiver<help_bubble::mojom::HelpBubbleHandler>
         pending_handler) {
   help_bubble_handler_ = std::make_unique<user_education::HelpBubbleHandler>(
-      std::move(pending_handler), std::move(pending_client),
-      web_ui()->GetWebContents(),
+      std::move(pending_handler), std::move(pending_client), this,
       std::vector<ui::ElementIdentifier>{kWebUIIPHDemoElementIdentifier});
 }
 
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
index 9a41461..e6d46e7 100644
--- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
+++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -253,7 +253,8 @@
   }
   return std::make_unique<LookalikeUrlBlockingPage>(
       web_contents, safe_url, request_url, ukm::kInvalidSourceId,
-      LookalikeUrlMatchType::kNone, false, /*triggered_by_initial_url=*/false,
+      lookalikes::LookalikeUrlMatchType::kNone, false,
+      /*triggered_by_initial_url=*/false,
       std::make_unique<LookalikeUrlControllerClient>(web_contents, request_url,
                                                      safe_url));
 }
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom b/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom
index 89d5a3e..998b04f 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom
@@ -324,8 +324,8 @@
 
 // WebUI-side handler for requests from the browser.
 interface Page {
-  // Called when the customize chrome side panel is shown/hidden.
-  CustomizeChromeSidePanelVisibilityChanged(bool visible);
+  // Sets Customize Chrome Side Panel visibility to |visible|.
+  SetCustomizeChromeSidePanelVisibility(bool visible);
   // Sets the current theme.
   SetTheme(Theme theme);
   // Disables the modules in |ids|. If |all|, disables all modules and passes an
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
index de6fada..4527968 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
@@ -166,6 +166,8 @@
   theme->background_color = color_provider.GetColor(kColorNewTabPageBackground);
   const bool remove_scrim =
       base::FeatureList::IsEnabled(ntp_features::kNtpRemoveScrim);
+  const bool theme_has_custom_image =
+      theme_provider->HasCustomImage(IDR_THEME_NTP_BACKGROUND);
   SkColor text_color;
   if (custom_background.has_value()) {
     text_color = color_provider.GetColor(kColorNewTabPageTextUnthemed);
@@ -210,10 +212,9 @@
       theme_service->UsingAutogeneratedTheme() &&
       theme->background_color != SK_ColorWHITE;
   auto background_image = new_tab_page::mojom::BackgroundImage::New();
-  if (custom_background.has_value()) {
-    theme->is_custom_background = true;
-    background_image->url = custom_background->custom_background_url;
-  } else if (theme_provider->HasCustomImage(IDR_THEME_NTP_BACKGROUND)) {
+  const bool side_panel_enabled = customize_chrome::IsSidePanelEnabled();
+  if (theme_has_custom_image &&
+      (!custom_background.has_value() || side_panel_enabled)) {
     theme->is_custom_background = false;
     most_visited->use_title_pill = !remove_scrim;
     auto theme_id = theme_service->GetThemeID();
@@ -261,6 +262,9 @@
     } else {
       background_image->position_y = "center";
     }
+  } else if (custom_background.has_value()) {
+    theme->is_custom_background = true;
+    background_image->url = custom_background->custom_background_url;
   } else {
     background_image = nullptr;
   }
@@ -278,8 +282,7 @@
   // set while a GWS theme with a bundled image is concurrently enabled (see
   // crbug.com/1329556 and crbug.com/1329552).
   if (base::FeatureList::IsEnabled(ntp_features::kCwsScrimRemoval) &&
-      !custom_background.has_value() &&
-      theme_provider->HasCustomImage(IDR_THEME_NTP_BACKGROUND)) {
+      !custom_background.has_value() && theme_has_custom_image) {
     if (ShouldForceDarkForegroundColorsForLogoAndOGB(theme_service)) {
       theme->is_dark = false;
       theme->logo_color =
@@ -290,7 +293,8 @@
   }
 
   theme->background_image = std::move(background_image);
-  if (custom_background.has_value()) {
+  if (custom_background.has_value() &&
+      (!side_panel_enabled || !theme_has_custom_image)) {
     theme->background_image_attribution_1 =
         custom_background->custom_background_attribution_line_1;
     theme->background_image_attribution_2 =
@@ -487,7 +491,7 @@
         CustomizeChromeTabHelper::FromWebContents(web_contents_);
     // Lifetime is tied to NewTabPageUI which owns the NewTabPageHandler.
     DCHECK(customize_chrome_tab_helper);
-    page_->CustomizeChromeSidePanelVisibilityChanged(
+    page_->SetCustomizeChromeSidePanelVisibility(
         customize_chrome_tab_helper->IsCustomizeChromeEntryShowing());
     customize_chrome_tab_helper->SetCallback(base::BindRepeating(
         &NewTabPageHandler::NotifyCustomizeChromeSidePanelVisibilityChanged,
@@ -1313,5 +1317,5 @@
 
 void NewTabPageHandler::NotifyCustomizeChromeSidePanelVisibilityChanged(
     bool is_open) {
-  page_->CustomizeChromeSidePanelVisibilityChanged(is_open);
+  page_->SetCustomizeChromeSidePanelVisibility(is_open);
 }
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler_unittest.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler_unittest.cc
index 32db977f..bfaf4536 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler_unittest.cc
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler_unittest.cc
@@ -28,6 +28,7 @@
 #include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/browser/ui/hats/hats_service_factory.h"
 #include "chrome/browser/ui/hats/mock_hats_service.h"
+#include "chrome/browser/ui/side_panel/customize_chrome/customize_chrome_tab_helper.h"
 #include "chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom.h"
 #include "chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h"
 #include "chrome/browser/ui/webui/webui_util.h"
@@ -86,7 +87,7 @@
   MOCK_METHOD1(SetTheme, void(new_tab_page::mojom::ThemePtr));
   MOCK_METHOD2(SetDisabledModules, void(bool, const std::vector<std::string>&));
   MOCK_METHOD1(SetModulesFreVisibility, void(bool));
-  MOCK_METHOD1(CustomizeChromeSidePanelVisibilityChanged, void(bool));
+  MOCK_METHOD1(SetCustomizeChromeSidePanelVisibility, void(bool));
   MOCK_METHOD1(SetPromo, void(new_tab_page::mojom::PromoPtr));
 
   mojo::Receiver<new_tab_page::mojom::Page> receiver_{this};
@@ -222,6 +223,10 @@
     web_contents_->SetColorProviderSource(&mock_color_provider_source_);
     const std::vector<std::pair<const std::string, int>> module_id_names = {
         {"recipe_tasks", IDS_NTP_MODULES_RECIPE_TASKS_SENTENCE}};
+    CustomizeChromeTabHelper::CreateForWebContents(web_contents_.get());
+    auto* customize_chrome_tab_helper_ =
+        CustomizeChromeTabHelper::FromWebContents(web_contents_.get());
+    EXPECT_FALSE(customize_chrome_tab_helper_->IsCustomizeChromeEntryShowing());
     handler_ = std::make_unique<NewTabPageHandler>(
         mojo::PendingReceiver<new_tab_page::mojom::PageHandler>(),
         mock_page_.BindAndGetRemote(), profile_.get(),
@@ -292,7 +297,7 @@
 
 class NewTabPageHandlerThemeTest
     : public NewTabPageHandlerTest,
-      public ::testing::WithParamInterface<std::tuple<bool, bool>> {
+      public ::testing::WithParamInterface<std::tuple<bool, bool, bool>> {
  public:
   NewTabPageHandlerThemeTest() {
     std::vector<base::test::FeatureRef> enabled_features;
@@ -310,12 +315,19 @@
       disabled_features.push_back(ntp_features::kNtpComprehensiveTheming);
     }
 
+    if (CustomizeChromeSidePanel()) {
+      enabled_features.push_back(ntp_features::kCustomizeChromeSidePanel);
+    } else {
+      disabled_features.push_back(ntp_features::kCustomizeChromeSidePanel);
+    }
+
     feature_list_.InitWithFeatures(std::move(enabled_features),
                                    std::move(disabled_features));
   }
 
   bool RemoveScrim() const { return std::get<0>(GetParam()); }
   bool ComprehensiveTheme() const { return std::get<1>(GetParam()); }
+  bool CustomizeChromeSidePanel() const { return std::get<2>(GetParam()); }
 
  private:
   base::test::ScopedFeatureList feature_list_;
@@ -428,6 +440,8 @@
   custom_background.collection_id = "baz collection";
   ON_CALL(mock_ntp_custom_background_service_, GetCustomBackground())
       .WillByDefault(testing::Return(absl::make_optional(custom_background)));
+  ON_CALL(mock_theme_provider_, HasCustomImage(IDR_THEME_NTP_BACKGROUND))
+      .WillByDefault(testing::Return(true));
   mock_color_provider_source_.SetColor(kColorNewTabPageBackground,
                                        SkColorSetRGB(0, 0, 1));
   mock_color_provider_source_.SetColor(kColorNewTabPageTextUnthemed,
@@ -444,15 +458,24 @@
   mock_page_.FlushForTesting();
 
   ASSERT_TRUE(theme);
-  EXPECT_TRUE(theme->is_custom_background);
-  EXPECT_EQ(SkColorSetRGB(0, 0, 1), theme->background_color);
-  EXPECT_EQ(SkColorSetRGB(0, 0, 2), theme->text_color);
-  EXPECT_EQ(SkColorSetRGB(0, 0, 3), theme->logo_color);
-  EXPECT_EQ("https://foo.com/img.png", theme->background_image->url);
-  EXPECT_EQ("foo line", theme->background_image_attribution_1);
-  EXPECT_EQ("bar line", theme->background_image_attribution_2);
-  EXPECT_EQ("https://foo.com/action", theme->background_image_attribution_url);
-  EXPECT_EQ("baz collection", theme->daily_refresh_collection_id);
+  if (CustomizeChromeSidePanel()) {
+    EXPECT_FALSE(theme->is_custom_background);
+    EXPECT_FALSE(theme->background_image_attribution_1.has_value());
+    EXPECT_FALSE(theme->background_image_attribution_2.has_value());
+    EXPECT_FALSE(theme->background_image_attribution_url.has_value());
+  } else {
+    ASSERT_TRUE(theme);
+    EXPECT_TRUE(theme->is_custom_background);
+    EXPECT_EQ(SkColorSetRGB(0, 0, 1), theme->background_color);
+    EXPECT_EQ(SkColorSetRGB(0, 0, 2), theme->text_color);
+    EXPECT_EQ(SkColorSetRGB(0, 0, 3), theme->logo_color);
+    EXPECT_EQ("https://foo.com/img.png", theme->background_image->url);
+    EXPECT_EQ("foo line", theme->background_image_attribution_1);
+    EXPECT_EQ("bar line", theme->background_image_attribution_2);
+    EXPECT_EQ("https://foo.com/action",
+              theme->background_image_attribution_url);
+    EXPECT_EQ("baz collection", theme->daily_refresh_collection_id);
+  }
   if (RemoveScrim()) {
     EXPECT_TRUE(theme->background_image->scrim_display.has_value());
     EXPECT_EQ("none", theme->background_image->scrim_display.value());
@@ -470,6 +493,7 @@
 INSTANTIATE_TEST_SUITE_P(All,
                          NewTabPageHandlerThemeTest,
                          ::testing::Combine(::testing::Bool(),
+                                            ::testing::Bool(),
                                             ::testing::Bool()));
 
 TEST_F(NewTabPageHandlerTest, Histograms) {
diff --git a/chrome/browser/ui/webui/settings/ash/internet_section.cc b/chrome/browser/ui/webui/settings/ash/internet_section.cc
index c24a0fc2..e9dd330 100644
--- a/chrome/browser/ui/webui/settings/ash/internet_section.cc
+++ b/chrome/browser/ui/webui/settings/ash/internet_section.cc
@@ -993,8 +993,6 @@
           features::kCellularBypassESimInstallationConnectivityCheck));
   html_source->AddBoolean("showTechnologyBadge",
                           !ash::features::IsSeparateNetworkIconsEnabled());
-  html_source->AddBoolean("captivePortalUI2022",
-                          ash::features::IsCaptivePortalUI2022Enabled());
   html_source->AddBoolean(
       "showMeteredToggle",
       base::FeatureList::IsEnabled(::features::kMeteredShowToggle));
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc
index ab599c3..7dde577b 100644
--- a/chrome/browser/ui/webui/settings/settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -569,7 +569,7 @@
     mojo::PendingRemote<help_bubble::mojom::HelpBubbleClient> client,
     mojo::PendingReceiver<help_bubble::mojom::HelpBubbleHandler> handler) {
   help_bubble_handler_ = std::make_unique<user_education::HelpBubbleHandler>(
-      std::move(handler), std::move(client), web_ui()->GetWebContents(),
+      std::move(handler), std::move(client), this,
       std::vector<ui::ElementIdentifier>{kEnhancedProtectionSettingElementId});
 }
 
diff --git a/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.cc b/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.cc
index 0af3804..83c8558 100644
--- a/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.cc
+++ b/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.cc
@@ -110,7 +110,7 @@
     mojo::PendingRemote<help_bubble::mojom::HelpBubbleClient> client,
     mojo::PendingReceiver<help_bubble::mojom::HelpBubbleHandler> handler) {
   help_bubble_handler_ = std::make_unique<user_education::HelpBubbleHandler>(
-      std::move(handler), std::move(client), web_ui()->GetWebContents(),
+      std::move(handler), std::move(client), this,
       std::vector<ui::ElementIdentifier>{
           kAddCurrentTabToReadingListElementId,
           kSidePanelReadingListUnreadElementId,
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index dfeb413..40081fd 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1673611163-051d12ced78f2e551009bac52c211dd060679b73.profdata
+chrome-linux-main-1673632771-e97dded35603a7fa2d7ba6d9afae0de2d47d88a7.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 1261ca6..d1b88902 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1673611163-f5a1aa70de6d58d74322555720851aa4d8ecd3f9.profdata
+chrome-mac-main-1673632771-466da0ebaa24790e8a6996b035ccecaefabdec6c.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index ad07eb4c..481d6dba 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1673621965-a306175d10f04a7a84323a9b181698eec49fe756.profdata
+chrome-win32-main-1673632771-ad9a0a79648bfd8118599cd6e889463bd930619a.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index c82330a5..2c92042 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1673621965-d40a509be491361eace657324fa40d4a7bdfa5da.profdata
+chrome-win64-main-1673632771-4811fa5794771759c6e2a7831f8ff0b07d04df2f.profdata
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index e515228..753ed45 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -542,7 +542,7 @@
 // survey.
 BASE_FEATURE(kHappinessTrackingSystemBluetoothRevamp,
              "HappinessTrackingSystemBluetoothRevamp",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 // Enables or disables the Happiness Tracking System for the Ent survey.
 BASE_FEATURE(kHappinessTrackingSystemEnt,
              "HappinessTrackingSystemEnt",
@@ -603,6 +603,10 @@
 BASE_FEATURE(kHappinessTrackingGeneralCamera,
              "HappinessTrackingGeneralCamera",
              base::FEATURE_DISABLED_BY_DEFAULT);
+// Enables the Happiness Tracking System for Privacy Hub baseline survey.
+BASE_FEATURE(kHappinessTrackingPrivacyHubBaseline,
+             "HappinessTrackingPrivacyHubBaseline",
+             base::FEATURE_DISABLED_BY_DEFAULT);
 #endif
 
 // Hides the origin text from showing up briefly in WebApp windows.
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index c730265..6cab61d 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -359,6 +359,9 @@
 COMPONENT_EXPORT(CHROME_FEATURES)
 BASE_DECLARE_FEATURE(kHappinessTrackingGeneralCamera);
 
+COMPONENT_EXPORT(CHROME_FEATURES)
+BASE_DECLARE_FEATURE(kHappinessTrackingPrivacyHubBaseline);
+
 #endif
 
 COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kHideWebAppOriginText);
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 3988de74..83baf815 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -927,6 +927,16 @@
 // survey.
 const char kHatsGeneralCameraIsSelected[] = "hats_general_camera_is_selected";
 
+// A boolean pref. Indicated if the device is selected for the Privacy Hub
+// baseline survey.
+const char kHatsPrivacyHubBaselineIsSelected[] =
+    "hats_privacy_hub_baseline_is_selected";
+
+// An int64 pref. This is the timestamp, microseconds after epoch, that
+// indicated the end of the most recent Privacy Hub baseline cycle.
+const char kHatsPrivacyHubBaselineCycleEndTs[] =
+    "hats_privacy_hub_baseline_end_timestamp";
+
 // A boolean pref. Indicates if we've already shown a notification to inform the
 // current user about the quick unlock feature.
 const char kPinUnlockFeatureNotificationShown[] =
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 021a5d8..f9b08d9 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -318,6 +318,8 @@
 extern const char kHatsPhotosExperienceIsSelected[];
 extern const char kHatsGeneralCameraIsSelected[];
 extern const char kHatsGeneralCameraSurveyCycleEndTs[];
+extern const char kHatsPrivacyHubBaselineIsSelected[];
+extern const char kHatsPrivacyHubBaselineCycleEndTs[];
 extern const char kEolStatus[];
 extern const char kEndOfLifeDate[];
 extern const char kEolNotificationDismissed[];
diff --git a/chrome/services/sharing/nearby/nearby_connections.cc b/chrome/services/sharing/nearby/nearby_connections.cc
index 388ae4f..91dc07e 100644
--- a/chrome/services/sharing/nearby/nearby_connections.cc
+++ b/chrome/services/sharing/nearby/nearby_connections.cc
@@ -19,7 +19,7 @@
 #include "services/network/public/mojom/p2p.mojom.h"
 #include "third_party/nearby/src/connections/core.h"
 
-namespace location::nearby::connections {
+namespace nearby::connections {
 
 namespace {
 
@@ -91,11 +91,11 @@
 
 NearbyConnections::NearbyConnections(
     mojo::PendingReceiver<mojom::NearbyConnections> nearby_connections,
-    location::nearby::api::LogMessage::Severity min_log_severity,
+    nearby::api::LogMessage::Severity min_log_severity,
     base::OnceClosure on_disconnect)
     : nearby_connections_(this, std::move(nearby_connections)),
       thread_task_runner_(base::SingleThreadTaskRunner::GetCurrentDefault()) {
-  location::nearby::api::LogMessage::SetMinLogSeverity(min_log_severity);
+  nearby::api::LogMessage::SetMinLogSeverity(min_log_severity);
 
   nearby_connections_.set_disconnect_handler(std::move(on_disconnect));
 
@@ -520,4 +520,4 @@
   service_controller_router_ = std::move(service_controller_router);
 }
 
-}  // namespace location::nearby::connections
+}  // namespace nearby::connections
diff --git a/chrome/services/sharing/nearby/nearby_connections.h b/chrome/services/sharing/nearby/nearby_connections.h
index 1aab01293..c3ab4d0 100644
--- a/chrome/services/sharing/nearby/nearby_connections.h
+++ b/chrome/services/sharing/nearby/nearby_connections.h
@@ -32,7 +32,7 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/nearby/src/connections/implementation/service_controller_router.h"
 
-namespace location::nearby::connections {
+namespace nearby::connections {
 
 class Core;
 
@@ -51,7 +51,7 @@
   // destroy this instance.
   NearbyConnections(
       mojo::PendingReceiver<mojom::NearbyConnections> nearby_connections,
-      location::nearby::api::LogMessage::Severity min_log_severity,
+      nearby::api::LogMessage::Severity min_log_severity,
       base::OnceClosure on_disconnect);
 
   NearbyConnections(const NearbyConnections&) = delete;
@@ -164,6 +164,6 @@
   base::WeakPtrFactory<NearbyConnections> weak_ptr_factory_{this};
 };
 
-}  // namespace location::nearby::connections
+}  // namespace nearby::connections
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_NEARBY_CONNECTIONS_H_
diff --git a/chrome/services/sharing/nearby/nearby_connections_conversions.cc b/chrome/services/sharing/nearby/nearby_connections_conversions.cc
index 7b27b54..e89466b 100644
--- a/chrome/services/sharing/nearby/nearby_connections_conversions.cc
+++ b/chrome/services/sharing/nearby/nearby_connections_conversions.cc
@@ -12,7 +12,6 @@
 #include "chromeos/ash/services/nearby/public/mojom/nearby_connections.mojom.h"
 #include "chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom.h"
 
-namespace location {
 namespace nearby {
 namespace connections {
 
@@ -142,4 +141,3 @@
 
 }  // namespace connections
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/nearby_connections_conversions.h b/chrome/services/sharing/nearby/nearby_connections_conversions.h
index 09046e0..614ed5c5 100644
--- a/chrome/services/sharing/nearby/nearby_connections_conversions.h
+++ b/chrome/services/sharing/nearby/nearby_connections_conversions.h
@@ -13,7 +13,6 @@
 #include "chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom-forward.h"
 #include "third_party/nearby/src/connections/params.h"
 
-namespace location {
 namespace nearby {
 namespace connections {
 
@@ -38,6 +37,5 @@
 
 }  // namespace connections
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_NEARBY_CONNECTIONS_CONVERSIONS_H_
diff --git a/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.cc b/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.cc
index 2b471b1..f1b3791a 100644
--- a/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.cc
+++ b/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.cc
@@ -11,7 +11,6 @@
 #include "third_party/nearby/src/internal/platform/exception.h"
 #include "third_party/nearby/src/internal/platform/input_stream.h"
 
-namespace location {
 namespace nearby {
 namespace connections {
 
@@ -103,4 +102,3 @@
 
 }  // namespace connections
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.h b/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.h
index 0b0d8f6..6ebbb81c0 100644
--- a/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.h
+++ b/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.h
@@ -11,7 +11,6 @@
 #include "third_party/nearby/src/connections/payload.h"
 #include "third_party/nearby/src/internal/platform/byte_array.h"
 
-namespace location {
 namespace nearby {
 namespace connections {
 
@@ -68,6 +67,5 @@
 
 }  // namespace connections
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_NEARBY_CONNECTIONS_STREAM_BUFFER_MANAGER_H_
diff --git a/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager_unittest.cc b/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager_unittest.cc
index f1703da..f4dee2e 100644
--- a/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager_unittest.cc
+++ b/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager_unittest.cc
@@ -10,7 +10,6 @@
 #include "third_party/nearby/src/internal/platform/exception.h"
 #include "third_party/nearby/src/internal/platform/input_stream.h"
 
-namespace location {
 namespace nearby {
 namespace connections {
 namespace {
@@ -149,4 +148,3 @@
 
 }  // namespace connections
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/nearby_connections_unittest.cc b/chrome/services/sharing/nearby/nearby_connections_unittest.cc
index 8788b5f..16e892e 100644
--- a/chrome/services/sharing/nearby/nearby_connections_unittest.cc
+++ b/chrome/services/sharing/nearby/nearby_connections_unittest.cc
@@ -38,7 +38,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/nearby/src/connections/implementation/mock_service_controller_router.h"
 
-namespace location {
 namespace nearby {
 namespace connections {
 
@@ -208,7 +207,7 @@
 
     nearby_connections_ = std::make_unique<NearbyConnections>(
         remote_.BindNewPipeAndPassReceiver(),
-        location::nearby::api::LogMessage::Severity::kInfo,
+        nearby::api::LogMessage::Severity::kInfo,
         base::BindOnce(&NearbyConnectionsTest::OnDisconnect,
                        base::Unretained(this)));
     nearby_connections_->SetServiceControllerRouterForTesting(
@@ -1321,4 +1320,3 @@
 
 }  // namespace connections
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/nearby_shared_remotes.cc b/chrome/services/sharing/nearby/nearby_shared_remotes.cc
index 4e51183..937bd30 100644
--- a/chrome/services/sharing/nearby/nearby_shared_remotes.cc
+++ b/chrome/services/sharing/nearby/nearby_shared_remotes.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/services/sharing/nearby/nearby_shared_remotes.h"
 
-namespace location::nearby {
+namespace nearby {
 
 namespace {
 
@@ -27,4 +27,4 @@
 NearbySharedRemotes::NearbySharedRemotes() = default;
 NearbySharedRemotes::~NearbySharedRemotes() = default;
 
-}  // namespace location::nearby
+}  // namespace nearby
diff --git a/chrome/services/sharing/nearby/nearby_shared_remotes.h b/chrome/services/sharing/nearby/nearby_shared_remotes.h
index 02b69a6..6be3b09 100644
--- a/chrome/services/sharing/nearby/nearby_shared_remotes.h
+++ b/chrome/services/sharing/nearby/nearby_shared_remotes.h
@@ -15,7 +15,7 @@
 #include "mojo/public/cpp/bindings/shared_remote.h"
 #include "services/network/public/mojom/p2p.mojom.h"
 
-namespace location::nearby {
+namespace nearby {
 
 // Container for the SharedRemote objects required by Nearby Connections and
 // Nearby Presence.
@@ -41,6 +41,6 @@
   mojo::SharedRemote<sharing::mojom::TcpSocketFactory> tcp_socket_factory;
 };
 
-}  // namespace location::nearby
+}  // namespace nearby
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_NEARBY_SHARED_REMOTES_H_
diff --git a/chrome/services/sharing/nearby/platform.cc b/chrome/services/sharing/nearby/platform.cc
index 6da9b77d..cbd04d3 100644
--- a/chrome/services/sharing/nearby/platform.cc
+++ b/chrome/services/sharing/nearby/platform.cc
@@ -49,7 +49,7 @@
 #include "third_party/nearby/src/internal/platform/implementation/wifi_direct.h"
 #include "third_party/nearby/src/internal/platform/implementation/wifi_hotspot.h"
 
-namespace location::nearby::api {
+namespace nearby::api {
 
 int GetCurrentTid() {
   // SubmittableExecutor and ScheduledExecutor does not own a thread pool
@@ -114,8 +114,8 @@
 
 std::unique_ptr<BluetoothAdapter>
 ImplementationPlatform::CreateBluetoothAdapter() {
-  location::nearby::NearbySharedRemotes* nearby_shared_remotes =
-      location::nearby::NearbySharedRemotes::GetInstance();
+  nearby::NearbySharedRemotes* nearby_shared_remotes =
+      nearby::NearbySharedRemotes::GetInstance();
   if (nearby_shared_remotes &&
       nearby_shared_remotes->bluetooth_adapter.is_bound()) {
     return std::make_unique<chrome::BluetoothAdapter>(
@@ -180,8 +180,8 @@
 std::unique_ptr<BluetoothClassicMedium>
 ImplementationPlatform::CreateBluetoothClassicMedium(
     api::BluetoothAdapter& adapter) {
-  location::nearby::NearbySharedRemotes* nearby_shared_remotes =
-      location::nearby::NearbySharedRemotes::GetInstance();
+  nearby::NearbySharedRemotes* nearby_shared_remotes =
+      nearby::NearbySharedRemotes::GetInstance();
   // Ignore the provided |adapter| argument; it is a reference to the object
   // created by ImplementationPlatform::CreateBluetoothAdapter(). Instead,
   // directly use the cached bluetooth::mojom::Adapter.
@@ -195,8 +195,8 @@
 
 std::unique_ptr<BleMedium> ImplementationPlatform::CreateBleMedium(
     api::BluetoothAdapter& adapter) {
-  location::nearby::NearbySharedRemotes* nearby_shared_remotes =
-      location::nearby::NearbySharedRemotes::GetInstance();
+  nearby::NearbySharedRemotes* nearby_shared_remotes =
+      nearby::NearbySharedRemotes::GetInstance();
   // Ignore the provided |adapter| argument; it is a reference to the object
   // created by ImplementationPlatform::CreateBluetoothAdapter(). Instead,
   // directly use the cached bluetooth::mojom::Adapter.
@@ -234,8 +234,8 @@
 }
 
 std::unique_ptr<WifiLanMedium> ImplementationPlatform::CreateWifiLanMedium() {
-  location::nearby::NearbySharedRemotes* nearby_shared_remotes =
-      location::nearby::NearbySharedRemotes::GetInstance();
+  nearby::NearbySharedRemotes* nearby_shared_remotes =
+      nearby::NearbySharedRemotes::GetInstance();
   if (!nearby_shared_remotes) {
     return nullptr;
   }
@@ -272,8 +272,8 @@
 }
 
 std::unique_ptr<WebRtcMedium> ImplementationPlatform::CreateWebRtcMedium() {
-  location::nearby::NearbySharedRemotes* nearby_shared_remotes =
-      location::nearby::NearbySharedRemotes::GetInstance();
+  nearby::NearbySharedRemotes* nearby_shared_remotes =
+      nearby::NearbySharedRemotes::GetInstance();
 
   if (!nearby_shared_remotes) {
     LOG(ERROR) << "No NearbySharedRemotes instance. Returning null medium.";
@@ -336,4 +336,4 @@
       static_cast<chrome::Mutex*>(mutex));
 }
 
-}  // namespace location::nearby::api
+}  // namespace nearby::api
diff --git a/chrome/services/sharing/nearby/platform/atomic_boolean.cc b/chrome/services/sharing/nearby/platform/atomic_boolean.cc
index ba58c68e..dd096b3b2 100644
--- a/chrome/services/sharing/nearby/platform/atomic_boolean.cc
+++ b/chrome/services/sharing/nearby/platform/atomic_boolean.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/services/sharing/nearby/platform/atomic_boolean.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -22,4 +21,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/atomic_boolean.h b/chrome/services/sharing/nearby/platform/atomic_boolean.h
index 84847d0..53b3396 100644
--- a/chrome/services/sharing/nearby/platform/atomic_boolean.h
+++ b/chrome/services/sharing/nearby/platform/atomic_boolean.h
@@ -9,7 +9,6 @@
 
 #include "third_party/nearby/src/internal/platform/implementation/atomic_boolean.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -32,6 +31,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_ATOMIC_BOOLEAN_H_
diff --git a/chrome/services/sharing/nearby/platform/atomic_boolean_unittest.cc b/chrome/services/sharing/nearby/platform/atomic_boolean_unittest.cc
index 303eebf..4c9e2a0 100644
--- a/chrome/services/sharing/nearby/platform/atomic_boolean_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/atomic_boolean_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/test/task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -95,4 +94,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/atomic_uint32.cc b/chrome/services/sharing/nearby/platform/atomic_uint32.cc
index e16bd14..72e8af1 100644
--- a/chrome/services/sharing/nearby/platform/atomic_uint32.cc
+++ b/chrome/services/sharing/nearby/platform/atomic_uint32.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/services/sharing/nearby/platform/atomic_uint32.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -23,4 +22,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/atomic_uint32.h b/chrome/services/sharing/nearby/platform/atomic_uint32.h
index 362d009e..54a49c9 100644
--- a/chrome/services/sharing/nearby/platform/atomic_uint32.h
+++ b/chrome/services/sharing/nearby/platform/atomic_uint32.h
@@ -9,7 +9,6 @@
 
 #include "third_party/nearby/src/internal/platform/implementation/atomic_reference.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -32,6 +31,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_ATOMIC_UINT32_H_
diff --git a/chrome/services/sharing/nearby/platform/atomic_uint32_unittest.cc b/chrome/services/sharing/nearby/platform/atomic_uint32_unittest.cc
index 7cf87fe..dfde2bf 100644
--- a/chrome/services/sharing/nearby/platform/atomic_uint32_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/atomic_uint32_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/test/task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -80,4 +79,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/bidirectional_stream.cc b/chrome/services/sharing/nearby/platform/bidirectional_stream.cc
index 2419b8e4..53ed574 100644
--- a/chrome/services/sharing/nearby/platform/bidirectional_stream.cc
+++ b/chrome/services/sharing/nearby/platform/bidirectional_stream.cc
@@ -10,7 +10,6 @@
 #include "chrome/services/sharing/nearby/platform/input_stream_impl.h"
 #include "chrome/services/sharing/nearby/platform/output_stream_impl.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -82,4 +81,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/bidirectional_stream.h b/chrome/services/sharing/nearby/platform/bidirectional_stream.h
index 63a2c0e..b368f3b 100644
--- a/chrome/services/sharing/nearby/platform/bidirectional_stream.h
+++ b/chrome/services/sharing/nearby/platform/bidirectional_stream.h
@@ -17,7 +17,6 @@
 class SequencedTaskRunner;
 }  // namespace base
 
-namespace location {
 namespace nearby {
 
 class InputStream;
@@ -59,6 +58,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_BIDIRECTIONAL_STREAM_H_
diff --git a/chrome/services/sharing/nearby/platform/bidirectional_stream_unittest.cc b/chrome/services/sharing/nearby/platform/bidirectional_stream_unittest.cc
index 2ef4326..312de78 100644
--- a/chrome/services/sharing/nearby/platform/bidirectional_stream_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/bidirectional_stream_unittest.cc
@@ -20,7 +20,6 @@
 #include "chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -134,4 +133,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/ble_medium.cc b/chrome/services/sharing/nearby/platform/ble_medium.cc
index af44592..781051e87 100644
--- a/chrome/services/sharing/nearby/platform/ble_medium.cc
+++ b/chrome/services/sharing/nearby/platform/ble_medium.cc
@@ -8,7 +8,6 @@
 #include "base/metrics/histogram_functions.h"
 #include "chrome/services/sharing/nearby/platform/bluetooth_device.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -400,4 +399,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/ble_medium.h b/chrome/services/sharing/nearby/platform/ble_medium.h
index 34cd8b5..29791e7 100644
--- a/chrome/services/sharing/nearby/platform/ble_medium.h
+++ b/chrome/services/sharing/nearby/platform/ble_medium.h
@@ -14,7 +14,6 @@
 #include "mojo/public/cpp/bindings/shared_remote.h"
 #include "third_party/nearby/src/internal/platform/implementation/ble.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -112,6 +111,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_BLE_MEDIUM_H_
diff --git a/chrome/services/sharing/nearby/platform/ble_medium_unittest.cc b/chrome/services/sharing/nearby/platform/ble_medium_unittest.cc
index 333aca3b..6d6f451 100644
--- a/chrome/services/sharing/nearby/platform/ble_medium_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/ble_medium_unittest.cc
@@ -18,7 +18,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -365,4 +364,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/ble_peripheral.cc b/chrome/services/sharing/nearby/platform/ble_peripheral.cc
index 6b5916a..9cad91d 100644
--- a/chrome/services/sharing/nearby/platform/ble_peripheral.cc
+++ b/chrome/services/sharing/nearby/platform/ble_peripheral.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/services/sharing/nearby/platform/ble_peripheral.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -57,4 +56,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/ble_peripheral.h b/chrome/services/sharing/nearby/platform/ble_peripheral.h
index a932c0a..e6485e7 100644
--- a/chrome/services/sharing/nearby/platform/ble_peripheral.h
+++ b/chrome/services/sharing/nearby/platform/ble_peripheral.h
@@ -12,7 +12,6 @@
 #include "device/bluetooth/public/mojom/adapter.mojom.h"
 #include "third_party/nearby/src/internal/platform/implementation/ble.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -45,6 +44,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_BLE_PERIPHERAL_H_
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_adapter.cc b/chrome/services/sharing/nearby/platform/bluetooth_adapter.cc
index bb428dc..14b61d2 100644
--- a/chrome/services/sharing/nearby/platform/bluetooth_adapter.cc
+++ b/chrome/services/sharing/nearby/platform/bluetooth_adapter.cc
@@ -5,7 +5,6 @@
 #include "chrome/services/sharing/nearby/platform/bluetooth_adapter.h"
 #include "base/metrics/histogram_functions.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -93,4 +92,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_adapter.h b/chrome/services/sharing/nearby/platform/bluetooth_adapter.h
index eda985d3..f23265d 100644
--- a/chrome/services/sharing/nearby/platform/bluetooth_adapter.h
+++ b/chrome/services/sharing/nearby/platform/bluetooth_adapter.h
@@ -11,7 +11,6 @@
 #include "mojo/public/cpp/bindings/shared_remote.h"
 #include "third_party/nearby/src/internal/platform/implementation/bluetooth_adapter.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -43,6 +42,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_BLUETOOTH_ADAPTER_H_
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_adapter_unittest.cc b/chrome/services/sharing/nearby/platform/bluetooth_adapter_unittest.cc
index 7627b454..c313464 100644
--- a/chrome/services/sharing/nearby/platform/bluetooth_adapter_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/bluetooth_adapter_unittest.cc
@@ -15,7 +15,6 @@
 #include "mojo/public/cpp/bindings/shared_remote.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -130,4 +129,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_classic_medium.cc b/chrome/services/sharing/nearby/platform/bluetooth_classic_medium.cc
index fc2c1fc..fab53a7 100644
--- a/chrome/services/sharing/nearby/platform/bluetooth_classic_medium.cc
+++ b/chrome/services/sharing/nearby/platform/bluetooth_classic_medium.cc
@@ -11,7 +11,6 @@
 #include "chrome/services/sharing/nearby/platform/bluetooth_socket.h"
 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -310,4 +309,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_classic_medium.h b/chrome/services/sharing/nearby/platform/bluetooth_classic_medium.h
index 5a61acc..f7b6e2ee4 100644
--- a/chrome/services/sharing/nearby/platform/bluetooth_classic_medium.h
+++ b/chrome/services/sharing/nearby/platform/bluetooth_classic_medium.h
@@ -17,7 +17,6 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/nearby/src/internal/platform/implementation/bluetooth_classic.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -80,6 +79,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_BLUETOOTH_CLASSIC_MEDIUM_H_
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_classic_medium_unittest.cc b/chrome/services/sharing/nearby/platform/bluetooth_classic_medium_unittest.cc
index b99abd5..16e61bf 100644
--- a/chrome/services/sharing/nearby/platform/bluetooth_classic_medium_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/bluetooth_classic_medium_unittest.cc
@@ -16,7 +16,6 @@
 #include "mojo/public/cpp/bindings/shared_remote.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -326,4 +325,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_device.cc b/chrome/services/sharing/nearby/platform/bluetooth_device.cc
index 7b88c7c..a19ace0 100644
--- a/chrome/services/sharing/nearby/platform/bluetooth_device.cc
+++ b/chrome/services/sharing/nearby/platform/bluetooth_device.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/services/sharing/nearby/platform/bluetooth_device.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -34,4 +33,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_device.h b/chrome/services/sharing/nearby/platform/bluetooth_device.h
index 16dda75..0c289f7 100644
--- a/chrome/services/sharing/nearby/platform/bluetooth_device.h
+++ b/chrome/services/sharing/nearby/platform/bluetooth_device.h
@@ -12,7 +12,6 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/nearby/src/internal/platform/implementation/bluetooth_classic.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -48,6 +47,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_BLUETOOTH_DEVICE_H_
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_server_socket.cc b/chrome/services/sharing/nearby/platform/bluetooth_server_socket.cc
index b41ce33..ce83c60 100644
--- a/chrome/services/sharing/nearby/platform/bluetooth_server_socket.cc
+++ b/chrome/services/sharing/nearby/platform/bluetooth_server_socket.cc
@@ -10,7 +10,6 @@
 #include "chrome/services/sharing/nearby/platform/bluetooth_socket.h"
 #include "third_party/nearby/src/internal/platform/exception.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -63,4 +62,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_server_socket.h b/chrome/services/sharing/nearby/platform/bluetooth_server_socket.h
index 6e6bca6..b6679a7 100644
--- a/chrome/services/sharing/nearby/platform/bluetooth_server_socket.h
+++ b/chrome/services/sharing/nearby/platform/bluetooth_server_socket.h
@@ -13,7 +13,6 @@
 #include "mojo/public/cpp/bindings/shared_remote.h"
 #include "third_party/nearby/src/internal/platform/implementation/bluetooth_classic.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -45,6 +44,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_BLUETOOTH_SERVER_SOCKET_H_
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_server_socket_unittest.cc b/chrome/services/sharing/nearby/platform/bluetooth_server_socket_unittest.cc
index 9f3ecc1..1687c4c 100644
--- a/chrome/services/sharing/nearby/platform/bluetooth_server_socket_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/bluetooth_server_socket_unittest.cc
@@ -19,7 +19,6 @@
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -220,4 +219,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_socket.cc b/chrome/services/sharing/nearby/platform/bluetooth_socket.cc
index fd262f8..1314675 100644
--- a/chrome/services/sharing/nearby/platform/bluetooth_socket.cc
+++ b/chrome/services/sharing/nearby/platform/bluetooth_socket.cc
@@ -8,7 +8,6 @@
 #include "base/task/thread_pool.h"
 #include "chrome/services/sharing/nearby/platform/bidirectional_stream.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -83,4 +82,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_socket.h b/chrome/services/sharing/nearby/platform/bluetooth_socket.h
index 8e348a3..33366e8 100644
--- a/chrome/services/sharing/nearby/platform/bluetooth_socket.h
+++ b/chrome/services/sharing/nearby/platform/bluetooth_socket.h
@@ -18,7 +18,6 @@
 class SequencedTaskRunner;
 }  // namespace base
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -84,6 +83,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_BLUETOOTH_SOCKET_H_
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_socket_unittest.cc b/chrome/services/sharing/nearby/platform/bluetooth_socket_unittest.cc
index 0e3734e7..d4969bd 100644
--- a/chrome/services/sharing/nearby/platform/bluetooth_socket_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/bluetooth_socket_unittest.cc
@@ -18,7 +18,6 @@
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -174,4 +173,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/condition_variable.cc b/chrome/services/sharing/nearby/platform/condition_variable.cc
index a086d9f..4595b06 100644
--- a/chrome/services/sharing/nearby/platform/condition_variable.cc
+++ b/chrome/services/sharing/nearby/platform/condition_variable.cc
@@ -7,7 +7,6 @@
 #include "base/time/time.h"
 #include "chrome/services/sharing/nearby/platform/mutex.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -33,4 +32,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/condition_variable.h b/chrome/services/sharing/nearby/platform/condition_variable.h
index 079c316..4281823 100644
--- a/chrome/services/sharing/nearby/platform/condition_variable.h
+++ b/chrome/services/sharing/nearby/platform/condition_variable.h
@@ -9,7 +9,6 @@
 #include "third_party/abseil-cpp/absl/time/time.h"
 #include "third_party/nearby/src/internal/platform/implementation/condition_variable.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -36,6 +35,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_CONDITION_VARIABLE_H_
diff --git a/chrome/services/sharing/nearby/platform/condition_variable_unittest.cc b/chrome/services/sharing/nearby/platform/condition_variable_unittest.cc
index bc4a189..25d2f43 100644
--- a/chrome/services/sharing/nearby/platform/condition_variable_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/condition_variable_unittest.cc
@@ -19,7 +19,6 @@
 #include "chrome/services/sharing/nearby/platform/mutex.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -125,4 +124,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/count_down_latch.cc b/chrome/services/sharing/nearby/platform/count_down_latch.cc
index f7d8b8c..8657d10 100644
--- a/chrome/services/sharing/nearby/platform/count_down_latch.cc
+++ b/chrome/services/sharing/nearby/platform/count_down_latch.cc
@@ -6,7 +6,6 @@
 
 #include "base/time/time.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -42,4 +41,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/count_down_latch.h b/chrome/services/sharing/nearby/platform/count_down_latch.h
index 92ee186..7d5f6d0 100644
--- a/chrome/services/sharing/nearby/platform/count_down_latch.h
+++ b/chrome/services/sharing/nearby/platform/count_down_latch.h
@@ -10,7 +10,6 @@
 #include "third_party/abseil-cpp/absl/time/time.h"
 #include "third_party/nearby/src/internal/platform/implementation/count_down_latch.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -35,6 +34,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_COUNT_DOWN_LATCH_H_
diff --git a/chrome/services/sharing/nearby/platform/count_down_latch_unittest.cc b/chrome/services/sharing/nearby/platform/count_down_latch_unittest.cc
index 5a525036..1686cbb 100644
--- a/chrome/services/sharing/nearby/platform/count_down_latch_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/count_down_latch_unittest.cc
@@ -22,7 +22,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -217,4 +216,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/crypto.cc b/chrome/services/sharing/nearby/platform/crypto.cc
index 5420c800c..1ac508d 100644
--- a/chrome/services/sharing/nearby/platform/crypto.cc
+++ b/chrome/services/sharing/nearby/platform/crypto.cc
@@ -11,7 +11,6 @@
 
 #include <vector>
 
-namespace location {
 namespace nearby {
 
 void Crypto::Init() {}
@@ -33,4 +32,3 @@
 }
 
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/crypto_unittest.cc b/chrome/services/sharing/nearby/platform/crypto_unittest.cc
index 46d84bb..c598555 100644
--- a/chrome/services/sharing/nearby/platform/crypto_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/crypto_unittest.cc
@@ -6,7 +6,6 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 
 TEST(CryptoTest, Md5GeneratesHash) {
@@ -33,4 +32,3 @@
 }
 
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/input_file.cc b/chrome/services/sharing/nearby/platform/input_file.cc
index 815ed88..fc31f6d 100644
--- a/chrome/services/sharing/nearby/platform/input_file.cc
+++ b/chrome/services/sharing/nearby/platform/input_file.cc
@@ -8,7 +8,6 @@
 
 #include "base/logging.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -59,4 +58,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/input_file.h b/chrome/services/sharing/nearby/platform/input_file.h
index b95e2e77..02f8a261 100644
--- a/chrome/services/sharing/nearby/platform/input_file.h
+++ b/chrome/services/sharing/nearby/platform/input_file.h
@@ -8,7 +8,6 @@
 #include "base/files/file.h"
 #include "third_party/nearby/src/internal/platform/implementation/input_file.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -37,6 +36,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_INPUT_FILE_H_
diff --git a/chrome/services/sharing/nearby/platform/input_file_unittest.cc b/chrome/services/sharing/nearby/platform/input_file_unittest.cc
index 5bb0549..f30ab16 100644
--- a/chrome/services/sharing/nearby/platform/input_file_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/input_file_unittest.cc
@@ -13,7 +13,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -142,4 +141,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/input_stream_impl.cc b/chrome/services/sharing/nearby/platform/input_stream_impl.cc
index 64e1f4c..296cdaf 100644
--- a/chrome/services/sharing/nearby/platform/input_stream_impl.cc
+++ b/chrome/services/sharing/nearby/platform/input_stream_impl.cc
@@ -7,7 +7,6 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/task/sequenced_task_runner.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -186,4 +185,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/input_stream_impl.h b/chrome/services/sharing/nearby/platform/input_stream_impl.h
index 16ba760..3e8f4f4d 100644
--- a/chrome/services/sharing/nearby/platform/input_stream_impl.h
+++ b/chrome/services/sharing/nearby/platform/input_stream_impl.h
@@ -21,7 +21,6 @@
 class SequencedTaskRunner;
 }  // namespace base
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -74,6 +73,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_INPUT_STREAM_IMPL_H_
diff --git a/chrome/services/sharing/nearby/platform/input_stream_impl_unittest.cc b/chrome/services/sharing/nearby/platform/input_stream_impl_unittest.cc
index d39e012..e533b57 100644
--- a/chrome/services/sharing/nearby/platform/input_stream_impl_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/input_stream_impl_unittest.cc
@@ -18,7 +18,6 @@
 #include "chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -222,4 +221,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/log_message.cc b/chrome/services/sharing/nearby/platform/log_message.cc
index d7fac52..f31c6dc 100644
--- a/chrome/services/sharing/nearby/platform/log_message.cc
+++ b/chrome/services/sharing/nearby/platform/log_message.cc
@@ -8,7 +8,6 @@
 
 #include "base/strings/stringprintf.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -61,4 +60,3 @@
 
 }  // namespace api
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/log_message.h b/chrome/services/sharing/nearby/platform/log_message.h
index 7a2e3c1..3dcdad6 100644
--- a/chrome/services/sharing/nearby/platform/log_message.h
+++ b/chrome/services/sharing/nearby/platform/log_message.h
@@ -8,7 +8,6 @@
 #include "base/logging.h"
 #include "third_party/nearby/src/internal/platform/implementation/log_message.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -31,6 +30,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_LOG_MESSAGE_H_
diff --git a/chrome/services/sharing/nearby/platform/multi_thread_executor_unittest.cc b/chrome/services/sharing/nearby/platform/multi_thread_executor_unittest.cc
index 60f8cdd..9cf78a3c 100644
--- a/chrome/services/sharing/nearby/platform/multi_thread_executor_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/multi_thread_executor_unittest.cc
@@ -20,7 +20,6 @@
 #include "base/unguessable_token.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -199,4 +198,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/mutex.cc b/chrome/services/sharing/nearby/platform/mutex.cc
index fc0bb25..a0ba422 100644
--- a/chrome/services/sharing/nearby/platform/mutex.cc
+++ b/chrome/services/sharing/nearby/platform/mutex.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/services/sharing/nearby/platform/mutex.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -22,4 +21,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/mutex.h b/chrome/services/sharing/nearby/platform/mutex.h
index 8047184..7ea3435 100644
--- a/chrome/services/sharing/nearby/platform/mutex.h
+++ b/chrome/services/sharing/nearby/platform/mutex.h
@@ -8,7 +8,6 @@
 #include "base/synchronization/lock.h"
 #include "third_party/nearby/src/internal/platform/implementation/mutex.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -32,6 +31,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_MUTEX_H_
diff --git a/chrome/services/sharing/nearby/platform/mutex_unittest.cc b/chrome/services/sharing/nearby/platform/mutex_unittest.cc
index cf1da99..eef05e0 100644
--- a/chrome/services/sharing/nearby/platform/mutex_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/mutex_unittest.cc
@@ -16,7 +16,6 @@
 #include "base/unguessable_token.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -94,4 +93,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/output_file.cc b/chrome/services/sharing/nearby/platform/output_file.cc
index 9dd03a1d..fef8b62 100644
--- a/chrome/services/sharing/nearby/platform/output_file.cc
+++ b/chrome/services/sharing/nearby/platform/output_file.cc
@@ -6,7 +6,6 @@
 
 #include "base/numerics/safe_conversions.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -44,4 +43,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/output_file.h b/chrome/services/sharing/nearby/platform/output_file.h
index 0916625..04e70bea 100644
--- a/chrome/services/sharing/nearby/platform/output_file.h
+++ b/chrome/services/sharing/nearby/platform/output_file.h
@@ -8,7 +8,6 @@
 #include "base/files/file.h"
 #include "third_party/nearby/src/internal/platform/implementation/output_file.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -32,6 +31,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_OUTPUT_FILE_H_
diff --git a/chrome/services/sharing/nearby/platform/output_stream_impl.cc b/chrome/services/sharing/nearby/platform/output_stream_impl.cc
index ed2ec9e..f7eb195f 100644
--- a/chrome/services/sharing/nearby/platform/output_stream_impl.cc
+++ b/chrome/services/sharing/nearby/platform/output_stream_impl.cc
@@ -7,7 +7,6 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/task/sequenced_task_runner.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -183,4 +182,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/output_stream_impl.h b/chrome/services/sharing/nearby/platform/output_stream_impl.h
index 1992f030..7abad4e 100644
--- a/chrome/services/sharing/nearby/platform/output_stream_impl.h
+++ b/chrome/services/sharing/nearby/platform/output_stream_impl.h
@@ -21,7 +21,6 @@
 class SequencedTaskRunner;
 }  // namespace base
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -75,6 +74,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_OUTPUT_STREAM_IMPL_H_
diff --git a/chrome/services/sharing/nearby/platform/output_stream_impl_unittest.cc b/chrome/services/sharing/nearby/platform/output_stream_impl_unittest.cc
index 47d0cf9..c8a7a46 100644
--- a/chrome/services/sharing/nearby/platform/output_stream_impl_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/output_stream_impl_unittest.cc
@@ -19,7 +19,6 @@
 #include "chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -220,4 +219,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/recursive_mutex.cc b/chrome/services/sharing/nearby/platform/recursive_mutex.cc
index eb70853..60e78bf 100644
--- a/chrome/services/sharing/nearby/platform/recursive_mutex.cc
+++ b/chrome/services/sharing/nearby/platform/recursive_mutex.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/services/sharing/nearby/platform/recursive_mutex.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -61,4 +60,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/recursive_mutex.h b/chrome/services/sharing/nearby/platform/recursive_mutex.h
index 83b54196..96e8937b 100644
--- a/chrome/services/sharing/nearby/platform/recursive_mutex.h
+++ b/chrome/services/sharing/nearby/platform/recursive_mutex.h
@@ -10,7 +10,6 @@
 #include "base/threading/platform_thread.h"
 #include "third_party/nearby/src/internal/platform/implementation/mutex.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -45,6 +44,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_RECURSIVE_MUTEX_H_
diff --git a/chrome/services/sharing/nearby/platform/recursive_mutex_unittest.cc b/chrome/services/sharing/nearby/platform/recursive_mutex_unittest.cc
index bbcaa72..6c14582 100644
--- a/chrome/services/sharing/nearby/platform/recursive_mutex_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/recursive_mutex_unittest.cc
@@ -16,7 +16,6 @@
 #include "base/unguessable_token.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -159,4 +158,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/scheduled_executor.cc b/chrome/services/sharing/nearby/platform/scheduled_executor.cc
index 089f096..83baca2d 100644
--- a/chrome/services/sharing/nearby/platform/scheduled_executor.cc
+++ b/chrome/services/sharing/nearby/platform/scheduled_executor.cc
@@ -14,7 +14,6 @@
 #include "base/timer/timer.h"
 #include "chrome/services/sharing/nearby/platform/atomic_boolean.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -185,4 +184,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/scheduled_executor.h b/chrome/services/sharing/nearby/platform/scheduled_executor.h
index 40d9b93..12539d06 100644
--- a/chrome/services/sharing/nearby/platform/scheduled_executor.h
+++ b/chrome/services/sharing/nearby/platform/scheduled_executor.h
@@ -18,7 +18,6 @@
 #include "third_party/abseil-cpp/absl/time/time.h"
 #include "third_party/nearby/src/internal/platform/implementation/scheduled_executor.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -86,6 +85,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_SCHEDULED_EXECUTOR_H_
diff --git a/chrome/services/sharing/nearby/platform/scheduled_executor_unittest.cc b/chrome/services/sharing/nearby/platform/scheduled_executor_unittest.cc
index 3d57d72..7e626e80 100644
--- a/chrome/services/sharing/nearby/platform/scheduled_executor_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/scheduled_executor_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/unguessable_token.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -232,4 +231,3 @@
 }
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/single_thread_executor_unittest.cc b/chrome/services/sharing/nearby/platform/single_thread_executor_unittest.cc
index 66af219..fadd703 100644
--- a/chrome/services/sharing/nearby/platform/single_thread_executor_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/single_thread_executor_unittest.cc
@@ -15,7 +15,6 @@
 #include "base/unguessable_token.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -92,4 +91,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/submittable_executor.cc b/chrome/services/sharing/nearby/platform/submittable_executor.cc
index 6d961e0..813b8ab5c 100644
--- a/chrome/services/sharing/nearby/platform/submittable_executor.cc
+++ b/chrome/services/sharing/nearby/platform/submittable_executor.cc
@@ -9,7 +9,6 @@
 #include "base/threading/scoped_blocking_call.h"
 #include "base/threading/thread_restrictions.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -94,4 +93,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/submittable_executor.h b/chrome/services/sharing/nearby/platform/submittable_executor.h
index dfc27e18..1af8324 100644
--- a/chrome/services/sharing/nearby/platform/submittable_executor.h
+++ b/chrome/services/sharing/nearby/platform/submittable_executor.h
@@ -14,7 +14,6 @@
 #include "chrome/services/sharing/nearby/platform/atomic_boolean.h"
 #include "third_party/nearby/src/internal/platform/implementation/submittable_executor.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -53,6 +52,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_SUBMITTABLE_EXECUTOR_H_
diff --git a/chrome/services/sharing/nearby/platform/system_clock.cc b/chrome/services/sharing/nearby/platform/system_clock.cc
index 3cf3bfc..cd30c69a 100644
--- a/chrome/services/sharing/nearby/platform/system_clock.cc
+++ b/chrome/services/sharing/nearby/platform/system_clock.cc
@@ -19,7 +19,6 @@
 #include "base/system/sys_info.h"
 #endif  // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_POSIX)
 
-namespace location {
 namespace nearby {
 
 void SystemClock::Init() {}
@@ -50,4 +49,3 @@
 }
 
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/webrtc.cc b/chrome/services/sharing/nearby/platform/webrtc.cc
index 74b1755..86b52d4 100644
--- a/chrome/services/sharing/nearby/platform/webrtc.cc
+++ b/chrome/services/sharing/nearby/platform/webrtc.cc
@@ -24,7 +24,6 @@
 #include "third_party/webrtc_overrides/task_queue_factory.h"
 #include "unicode/locid.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -155,7 +154,7 @@
  public:
   WebRtcSignalingMessengerImpl(
       const std::string& self_id,
-      const connections::LocationHint& location_hint,
+      const location::nearby::connections::LocationHint& location_hint,
       const mojo::SharedRemote<sharing::mojom::WebRtcSignalingMessenger>&
           messenger)
       : self_id_(self_id),
@@ -275,7 +274,7 @@
  private:
   bool receiving_messages_ = false;
   std::string self_id_;
-  connections::LocationHint location_hint_;
+  location::nearby::connections::LocationHint location_hint_;
   // This is received and stored on a successful StartReceiveMessages(). We
   // choose to not bind right away because multiple threads end up
   // creating/calling/destroying WebRtcSignalingMessengerImpl by the design
@@ -546,11 +545,10 @@
 std::unique_ptr<api::WebRtcSignalingMessenger>
 WebRtcMedium::GetSignalingMessenger(
     absl::string_view self_id,
-    const connections::LocationHint& location_hint) {
+    const location::nearby::connections::LocationHint& location_hint) {
   return std::make_unique<WebRtcSignalingMessengerImpl>(
       std::string(self_id), location_hint, webrtc_signaling_messenger_);
 }
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/webrtc.h b/chrome/services/sharing/nearby/platform/webrtc.h
index 84b998e..686c76d00 100644
--- a/chrome/services/sharing/nearby/platform/webrtc.h
+++ b/chrome/services/sharing/nearby/platform/webrtc.h
@@ -26,7 +26,6 @@
 class IpcPacketSocketFactory;
 }  // namespace sharing
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -52,7 +51,7 @@
                             PeerConnectionCallback callback) override;
   std::unique_ptr<api::WebRtcSignalingMessenger> GetSignalingMessenger(
       absl::string_view self_id,
-      const connections::LocationHint& location_hint) override;
+      const location::nearby::connections::LocationHint& location_hint) override;
 
  private:
   void FetchIceServers(webrtc::PeerConnectionObserver* observer,
@@ -110,6 +109,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_WEBRTC_H_
diff --git a/chrome/services/sharing/nearby/platform/webrtc_test.cc b/chrome/services/sharing/nearby/platform/webrtc_test.cc
index bbb3a9c..1e372b64 100644
--- a/chrome/services/sharing/nearby/platform/webrtc_test.cc
+++ b/chrome/services/sharing/nearby/platform/webrtc_test.cc
@@ -13,7 +13,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "unicode/locid.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 namespace {
@@ -78,27 +77,27 @@
     return mojo_impl_;
   }
 
-  connections::LocationHint GetCountryCodeLocationHint(
+  location::nearby::connections::LocationHint GetCountryCodeLocationHint(
       const std::string& country_code) {
-    auto location_hint = connections::LocationHint();
+    auto location_hint = location::nearby::connections::LocationHint();
     location_hint.set_location(country_code);
     location_hint.set_format(
-        connections::LocationStandard_Format_ISO_3166_1_ALPHA_2);
+        location::nearby::connections::LocationStandard_Format_ISO_3166_1_ALPHA_2);
     return location_hint;
   }
 
-  connections::LocationHint GetCallingCodeLocationHint(
+  location::nearby::connections::LocationHint GetCallingCodeLocationHint(
       const std::string& calling_code) {
-    auto location_hint = connections::LocationHint();
+    auto location_hint = location::nearby::connections::LocationHint();
     location_hint.set_location(calling_code);
-    location_hint.set_format(connections::LocationStandard_Format_E164_CALLING);
+    location_hint.set_format(location::nearby::connections::LocationStandard_Format_E164_CALLING);
     return location_hint;
   }
 
-  connections::LocationHint GetUnknownLocationHint() {
-    auto location_hint = connections::LocationHint();
+  location::nearby::connections::LocationHint GetUnknownLocationHint() {
+    auto location_hint = location::nearby::connections::LocationHint();
     location_hint.set_location("");
-    location_hint.set_format(connections::LocationStandard_Format_UNKNOWN);
+    location_hint.set_format(location::nearby::connections::LocationStandard_Format_UNKNOWN);
     return location_hint;
   }
 
@@ -380,4 +379,3 @@
 }  // namespace
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_medium.cc b/chrome/services/sharing/nearby/platform/wifi_lan_medium.cc
index f331c46..22e434b 100644
--- a/chrome/services/sharing/nearby/platform/wifi_lan_medium.cc
+++ b/chrome/services/sharing/nearby/platform/wifi_lan_medium.cc
@@ -19,7 +19,6 @@
 #include "net/base/net_errors.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -544,4 +543,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_medium.h b/chrome/services/sharing/nearby/platform/wifi_lan_medium.h
index f461abbc..5803111 100644
--- a/chrome/services/sharing/nearby/platform/wifi_lan_medium.h
+++ b/chrome/services/sharing/nearby/platform/wifi_lan_medium.h
@@ -36,7 +36,6 @@
 class WaitableEvent;
 }  // namespace base
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -194,6 +193,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_WIFI_LAN_MEDIUM_H_
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_medium_unittest.cc b/chrome/services/sharing/nearby/platform/wifi_lan_medium_unittest.cc
index 17d8ba5c..a5bbb6a 100644
--- a/chrome/services/sharing/nearby/platform/wifi_lan_medium_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/wifi_lan_medium_unittest.cc
@@ -39,7 +39,6 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -586,4 +585,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.cc b/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.cc
index e3da019c..e7c127a 100644
--- a/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.cc
+++ b/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.cc
@@ -12,7 +12,6 @@
 #include "base/task/thread_pool.h"
 #include "net/base/net_errors.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -239,4 +238,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.h b/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.h
index f7da957e..eb0fa2b 100644
--- a/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.h
+++ b/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.h
@@ -25,7 +25,6 @@
 class WaitableEvent;
 }  // namespace base
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -118,6 +117,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_WIFI_LAN_SERVER_SOCKET_H_
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_server_socket_unittest.cc b/chrome/services/sharing/nearby/platform/wifi_lan_server_socket_unittest.cc
index 9ff8ac4..72d3c62 100644
--- a/chrome/services/sharing/nearby/platform/wifi_lan_server_socket_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/wifi_lan_server_socket_unittest.cc
@@ -23,7 +23,6 @@
 #include "services/network/public/mojom/tcp_socket.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -279,4 +278,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_socket.cc b/chrome/services/sharing/nearby/platform/wifi_lan_socket.cc
index d6061a2..d919b84 100644
--- a/chrome/services/sharing/nearby/platform/wifi_lan_socket.cc
+++ b/chrome/services/sharing/nearby/platform/wifi_lan_socket.cc
@@ -8,7 +8,6 @@
 #include "base/task/thread_pool.h"
 #include "chrome/services/sharing/nearby/platform/bidirectional_stream.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -94,4 +93,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_socket.h b/chrome/services/sharing/nearby/platform/wifi_lan_socket.h
index 92e7ef1..dd0a462 100644
--- a/chrome/services/sharing/nearby/platform/wifi_lan_socket.h
+++ b/chrome/services/sharing/nearby/platform/wifi_lan_socket.h
@@ -18,7 +18,6 @@
 class SequencedTaskRunner;
 }  // namespace base
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -74,6 +73,5 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
 
 #endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_WIFI_LAN_SOCKET_H_
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_socket_unittest.cc b/chrome/services/sharing/nearby/platform/wifi_lan_socket_unittest.cc
index b065878..e9c4298 100644
--- a/chrome/services/sharing/nearby/platform/wifi_lan_socket_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/wifi_lan_socket_unittest.cc
@@ -15,7 +15,6 @@
 #include "services/network/public/mojom/tcp_socket.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace location {
 namespace nearby {
 namespace chrome {
 
@@ -127,4 +126,3 @@
 
 }  // namespace chrome
 }  // namespace nearby
-}  // namespace location
diff --git a/chrome/services/sharing/sharing_impl.cc b/chrome/services/sharing/sharing_impl.cc
index 0331763..a19b8c9 100644
--- a/chrome/services/sharing/sharing_impl.cc
+++ b/chrome/services/sharing/sharing_impl.cc
@@ -35,8 +35,7 @@
   DCHECK(!nearby_connections_);
   DCHECK(!nearby_decoder_);
 
-  location::nearby::api::LogMessage::Severity min_log_severity =
-      deps->min_log_severity;
+  nearby::api::LogMessage::Severity min_log_severity = deps->min_log_severity;
 
   InitializeNearbySharedRemotes(std::move(deps));
 
@@ -55,7 +54,7 @@
 }
 
 void SharingImpl::DoShutDown(bool is_expected) {
-  location::nearby::NearbySharedRemotes::SetInstance(nullptr);
+  nearby::NearbySharedRemotes::SetInstance(nullptr);
 
   if (!nearby_connections_ && !nearby_decoder_)
     return;
@@ -81,10 +80,8 @@
 }
 
 void SharingImpl::InitializeNearbySharedRemotes(NearbyDependenciesPtr deps) {
-  nearby_shared_remotes_ =
-      std::make_unique<location::nearby::NearbySharedRemotes>();
-  location::nearby::NearbySharedRemotes::SetInstance(
-      nearby_shared_remotes_.get());
+  nearby_shared_remotes_ = std::make_unique<nearby::NearbySharedRemotes>();
+  nearby::NearbySharedRemotes::SetInstance(nearby_shared_remotes_.get());
 
   if (deps->bluetooth_adapter) {
     nearby_shared_remotes_->bluetooth_adapter.Bind(
diff --git a/chrome/services/sharing/sharing_impl.h b/chrome/services/sharing/sharing_impl.h
index 77f5b875..c71a370 100644
--- a/chrome/services/sharing/sharing_impl.h
+++ b/chrome/services/sharing/sharing_impl.h
@@ -22,9 +22,9 @@
 #include "services/network/public/mojom/mdns_responder.mojom-forward.h"
 #include "services/network/public/mojom/p2p.mojom-forward.h"
 
-namespace location::nearby::connections {
+namespace nearby::connections {
 class NearbyConnections;
-}  // namespace location::nearby::connections
+}  // namespace nearby::connections
 
 namespace sharing {
 
@@ -32,9 +32,8 @@
 
 class SharingImpl : public mojom::Sharing {
  public:
-  using NearbyConnectionsMojom =
-      location::nearby::connections::mojom::NearbyConnections;
-  using NearbyConnections = location::nearby::connections::NearbyConnections;
+  using NearbyConnectionsMojom = nearby::connections::mojom::NearbyConnections;
+  using NearbyConnections = nearby::connections::NearbyConnections;
   using NearbyDependenciesPtr = sharing::mojom::NearbyDependenciesPtr;
 
   SharingImpl(mojo::PendingReceiver<mojom::Sharing> receiver,
@@ -78,7 +77,7 @@
   mojo::Receiver<mojom::Sharing> receiver_;
   const scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
 
-  std::unique_ptr<location::nearby::NearbySharedRemotes> nearby_shared_remotes_;
+  std::unique_ptr<nearby::NearbySharedRemotes> nearby_shared_remotes_;
 
   std::unique_ptr<NearbyConnections> nearby_connections_;
 
diff --git a/chrome/services/sharing/sharing_impl_unittest.cc b/chrome/services/sharing/sharing_impl_unittest.cc
index 211b6df..e9b3f17 100644
--- a/chrome/services/sharing/sharing_impl_unittest.cc
+++ b/chrome/services/sharing/sharing_impl_unittest.cc
@@ -83,8 +83,7 @@
   }
 
   void Connect(
-      mojo::PendingReceiver<
-          location::nearby::connections::mojom::NearbyConnections>
+      mojo::PendingReceiver<nearby::connections::mojom::NearbyConnections>
           connections_receiver,
       mojo::PendingReceiver<sharing::mojom::NearbySharingDecoder>
           decoder_receiver,
@@ -110,7 +109,7 @@
     auto dependencies = sharing::mojom::NearbyDependencies::New(
         std::move(bluetooth_adapter), std::move(webrtc_dependencies),
         std::move(wifilan_dependencies),
-        location::nearby::api::LogMessage::Severity::kInfo);
+        nearby::api::LogMessage::Severity::kInfo);
     base::RunLoop run_loop;
     service_->Connect(std::move(dependencies), std::move(connections_receiver),
                       std::move(decoder_receiver));
@@ -142,8 +141,7 @@
   mojo::Remote<mojom::Sharing> remote_;
   std::unique_ptr<SharingImpl> service_;
 
-  mojo::Remote<location::nearby::connections::mojom::NearbyConnections>
-      connections_;
+  mojo::Remote<nearby::connections::mojom::NearbyConnections> connections_;
   mojo::Remote<sharing::mojom::NearbySharingDecoder> decoder_;
   bluetooth::FakeAdapter bluetooth_adapter_;
   sharing::MockWebRtcDependencies webrtc_dependencies_;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 6d97190..90d084a 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1256,6 +1256,7 @@
       "//chrome/browser/dips:browser_tests",
       "//chrome/browser/favicon",
       "//chrome/browser/first_party_sets",
+      "//chrome/browser/headless:browser_tests",
       "//chrome/browser/image_decoder:browser_tests",
       "//chrome/browser/media/router:media_router_feature",
       "//chrome/browser/media/router:test_support",
@@ -1363,7 +1364,6 @@
       "//components/live_caption",
       "//components/live_caption:constants",
       "//components/lookalikes/core",
-      "//components/lookalikes/core:features",
       "//components/lookalikes/core:proto",
       "//components/lookalikes/core:safety_tips",
       "//components/media_router/common/providers/cast/channel",
@@ -1792,8 +1792,6 @@
       "../browser/first_run/first_run_browsertest.cc",
       "../browser/geolocation/geolocation_browsertest.cc",
       "../browser/guest_view/mime_handler_view/chrome_mime_handler_view_browsertest.cc",
-      "../browser/headless/headless_mode_browsertest.cc",
-      "../browser/headless/headless_mode_browsertest.h",
       "../browser/heavy_ad_intervention/heavy_ad_helper_browsertest.cc",
       "../browser/hid/hid_browsertest.cc",
       "../browser/history/history_browsertest.cc",
@@ -2248,6 +2246,7 @@
       "../browser/ui/views/sharing/shared_clipboard_browsertest.cc",
       "../browser/ui/views/sharing/sharing_browsertest.cc",
       "../browser/ui/views/sharing/sharing_browsertest.h",
+      "../browser/ui/views/side_panel/lens/lens_core_tab_side_panel_helper_browsertest.cc",
       "../browser/ui/views/tab_search_bubble_host_browsertest.cc",
       "../browser/ui/views/tabs/tab_search_button_browsertest.cc",
       "../browser/ui/views/tabs/tab_strip_browsertest.cc",
@@ -2545,7 +2544,6 @@
     if (is_linux) {
       sources += [
         "../browser/chrome_main_process_singleton_browsertest.cc",
-        "../browser/headless/headless_mode_browsertest_linux.cc",
         "../browser/process_singleton_browsertest.cc",
       ]
     }
@@ -2557,7 +2555,6 @@
         "../browser/enterprise/platform_auth/platform_auth_policy_observer_browsertest.cc",
         "../browser/enterprise/platform_auth/platform_auth_provider_manager_browsertest.cc",
         "../browser/font_prewarmer_tab_helper_browsertest.cc",
-        "../browser/headless/headless_mode_browsertest_win.cc",
         "../browser/importer/edge_importer_browsertest_win.cc",
         "../browser/importer/ie_importer_browsertest_win.cc",
         "../browser/net/chrome_mojo_proxy_resolver_win_browsertest.cc",
@@ -2614,7 +2611,6 @@
         "../browser/apps/app_shim/app_shim_listener_browsertest_mac.mm",
         "../browser/apps/app_shim/test/app_shim_listener_test_api_mac.cc",
         "../browser/apps/app_shim/test/app_shim_listener_test_api_mac.h",
-        "../browser/headless/headless_mode_browsertest_mac.mm",
         "../browser/mac/auth_session_request_browsertest.mm",
         "../browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_browsertest.mm",
         "../browser/spellchecker/spell_check_host_chrome_impl_mac_browsertest.cc",
@@ -5958,7 +5954,6 @@
     "//components/leveldb_proto:test_support",
     "//components/live_caption:constants",
     "//components/lookalikes/core",
-    "//components/lookalikes/core:features",
     "//components/lookalikes/core:safety_tips",
     "//components/media_router/common/providers/cast/channel",
     "//components/media_router/common/providers/cast/channel:test_support",
@@ -9844,6 +9839,7 @@
         "../browser/ui/views/user_education/feature_promo_snooze_interactive_uitest.cc",
         "../browser/ui/views/user_education/help_bubble_factory_registry_interactive_uitest.cc",
         "../browser/ui/views/user_education/help_bubble_factory_views_interactive_uitest.cc",
+        "../browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc",
         "../browser/ui/views/user_education/help_bubble_view_interactive_uitest.cc",
         "../browser/ui/views/user_education/tutorial_interactive_uitest.cc",
         "interaction/interaction_sequence_interactive_uitest.cc",
@@ -9863,6 +9859,7 @@
         "//components/optimization_guide/proto:optimization_guide_proto",
         "//components/performance_manager:performance_manager",
         "//components/user_education/views",
+        "//components/user_education/webui",
         "//ui/base/dragdrop:types",
         "//ui/base/dragdrop/mojom",
         "//ui/views",
diff --git a/chrome/test/data/webui/bookmarks/BUILD.gn b/chrome/test/data/webui/bookmarks/BUILD.gn
index 3879bf2..731a3a8 100644
--- a/chrome/test/data/webui/bookmarks/BUILD.gn
+++ b/chrome/test/data/webui/bookmarks/BUILD.gn
@@ -9,11 +9,11 @@
 
   files = [
     "actions_test.ts",
-    "app_test.js",
+    "app_test.ts",
     "bookmarks_focus_test.js",
     "command_manager_test.js",
     "dialog_focus_manager_test.js",
-    "dnd_manager_test.js",
+    "dnd_manager_test.ts",
     "edit_dialog_test.ts",
     "extension_api_test.ts",
     "extension_api_test_edit_disabled.ts",
@@ -25,7 +25,7 @@
     "policy_test.ts",
     "reducers_test.ts",
     "router_test.ts",
-    "store_test.js",
+    "store_test.ts",
     "test_bookmark_manager_api_proxy.ts",
     "test_bookmarks_api_proxy.ts",
     "test_browser_proxy.ts",
diff --git a/chrome/test/data/webui/bookmarks/app_test.js b/chrome/test/data/webui/bookmarks/app_test.ts
similarity index 76%
rename from chrome/test/data/webui/bookmarks/app_test.js
rename to chrome/test/data/webui/bookmarks/app_test.ts
index c16c078..ca38f292 100644
--- a/chrome/test/data/webui/bookmarks/app_test.js
+++ b/chrome/test/data/webui/bookmarks/app_test.ts
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {BookmarksApiProxyImpl, HIDE_FOCUS_RING_ATTRIBUTE, LOCAL_STORAGE_FOLDER_STATE_KEY, LOCAL_STORAGE_TREE_WIDTH_KEY} from 'chrome://bookmarks/bookmarks.js';
+import {BookmarksApiProxyImpl, BookmarksAppElement, BookmarksItemElement, HIDE_FOCUS_RING_ATTRIBUTE, LOCAL_STORAGE_FOLDER_STATE_KEY, LOCAL_STORAGE_TREE_WIDTH_KEY} from 'chrome://bookmarks/bookmarks.js';
 import {isMac} from 'chrome://resources/js/platform.js';
 import {getDeepActiveElement} from 'chrome://resources/js/util_ts.js';
 import {down, keyDownOn, pressAndReleaseKeyOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
+import {assertDeepEquals, assertEquals, assertNotEquals} from 'chrome://webui-test/chai_assert.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
 import {TestBookmarksApiProxy} from './test_bookmarks_api_proxy.js';
@@ -13,9 +14,9 @@
 import {createFolder, normalizeIterable, replaceBody} from './test_util.js';
 
 suite('<bookmarks-app>', function() {
-  let app;
-  let store;
-  let testBookmarksApiProxy;
+  let app: BookmarksAppElement;
+  let store: TestStore;
+  let testBookmarksApiProxy: TestBookmarksApiProxy;
 
   function resetStore() {
     store = new TestStore({});
@@ -46,7 +47,7 @@
   });
 
   test('write and load closed folder state', async function() {
-    const folderOpenStateList = [['1', true]];
+    const folderOpenStateList = [['1', true] as const];
     const folderOpenState = new Map(folderOpenStateList);
     store.data.folderOpenState = folderOpenState;
     store.notifyObservers();
@@ -67,7 +68,9 @@
   });
 
   test('write and load sidebar width', async function() {
-    assertEquals(getComputedStyle(app.$.sidebar).width, app.sidebarWidth_);
+    assertEquals(
+        getComputedStyle(app.$.sidebar).width,
+        app.shadowRoot!.querySelector('bookmarks-toolbar')!.sidebarWidth);
 
     const sidebarWidth = '500px';
     app.$.sidebar.style.width = sidebarWidth;
@@ -83,9 +86,10 @@
   });
 
   test('focus ring hides and restores', async function() {
-    const list = app.shadowRoot.querySelector('bookmarks-list');
+    const list = app.shadowRoot!.querySelector('bookmarks-list');
     await flushTasks();
-    const item = list.root.querySelectorAll('bookmarks-item')[0];
+    const item = list!.root!.querySelectorAll('bookmarks-item')[0] as
+        BookmarksItemElement;
     const getFocusAttribute = () => app.getAttribute(HIDE_FOCUS_RING_ATTRIBUTE);
 
     assertEquals(null, getFocusAttribute());
@@ -103,10 +107,11 @@
   });
 
   test('when find shortcut is invoked, focus on search input', () => {
-    const searchInput = app.shadowRoot.querySelector('bookmarks-toolbar')
-                            .searchField.getSearchInput();
+    const searchInput =
+        app.shadowRoot!.querySelector(
+                           'bookmarks-toolbar')!.searchField.getSearchInput();
     assertNotEquals(searchInput, getDeepActiveElement());
-    pressAndReleaseKeyOn(document.body, '', isMac ? 'meta' : 'ctrl', 'f');
+    pressAndReleaseKeyOn(document.body, 0, isMac ? 'meta' : 'ctrl', 'f');
     assertEquals(searchInput, getDeepActiveElement());
   });
 });
diff --git a/chrome/test/data/webui/bookmarks/dnd_manager_test.js b/chrome/test/data/webui/bookmarks/dnd_manager_test.js
deleted file mode 100644
index b34417b..0000000
--- a/chrome/test/data/webui/bookmarks/dnd_manager_test.js
+++ /dev/null
@@ -1,583 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {BrowserProxyImpl, changeFolderOpen, DragInfo, DropPosition, setDebouncerForTesting} from 'chrome://bookmarks/bookmarks.js';
-import {middleOfNode, topLeftOfNode} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
-import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-import {TestBookmarksBrowserProxy} from './test_browser_proxy.js';
-import {TestStore} from './test_store.js';
-import {TestTimerProxy} from './test_timer_proxy.js';
-import {createFolder, createItem, findFolderNode, getAllFoldersOpenState, normalizeIterable, replaceBody, testTree} from './test_util.js';
-
-suite('drag and drop', function() {
-  let app;
-  let list;
-  let rootFolderNode;
-  let store;
-  let dndManager;
-
-  const DRAG_STYLE = {
-    NONE: 0,
-    ON: 1,
-    ABOVE: 2,
-    BELOW: 3,
-  };
-
-  function getFolderNode(id) {
-    return findFolderNode(rootFolderNode, id);
-  }
-
-  function getListItem(id) {
-    const items = list.root.querySelectorAll('bookmarks-item');
-    for (let i = 0; i < items.length; i++) {
-      if (items[i].itemId === id) {
-        return items[i];
-      }
-    }
-  }
-
-  function dispatchDragEvent(type, node, xy) {
-    xy = xy || middleOfNode(node);
-    const props = {
-      bubbles: true,
-      cancelable: true,
-      composed: true,
-      clientX: xy.x,
-      clientY: xy.y,
-      // Make this a primary input.
-      buttons: 1,
-    };
-    const e = new DragEvent(type, props);
-    node.dispatchEvent(e);
-  }
-
-  function assertDragStyle(bookmarkElement, style) {
-    const dragStyles = {};
-    dragStyles[DRAG_STYLE.ON] = 'drag-on';
-    dragStyles[DRAG_STYLE.ABOVE] = 'drag-above';
-    dragStyles[DRAG_STYLE.BELOW] = 'drag-below';
-
-    const classList = bookmarkElement.getDropTarget().classList;
-    Object.keys(dragStyles).forEach(dragStyle => {
-      assertEquals(
-          dragStyle === style.toString(),
-          classList.contains(dragStyles[dragStyle]),
-          dragStyles[dragStyle] +
-              (dragStyle === style.toString() ? ' missing' : ' found') +
-              ' in classList ' + classList);
-    });
-  }
-
-  function createDragData(ids, sameProfile) {
-    return {
-      elements: ids.map(id => store.data.nodes[id]),
-      sameProfile: sameProfile === undefined ? true : sameProfile,
-    };
-  }
-
-  function simulateDragStart(dragElement) {
-    dispatchDragEvent('dragstart', dragElement);
-    move(dragElement, topLeftOfNode(dragElement));
-  }
-
-  function move(target, dest) {
-    dispatchDragEvent('dragover', target, dest || middleOfNode(target));
-  }
-
-  function getDragIds() {
-    return dndManager.dragInfo_.dragData.elements.map((x) => x.id);
-  }
-
-  setup(function() {
-    const nodes = testTree(
-        createFolder(
-            '1',
-            [
-              createFolder(
-                  '11',
-                  [
-                    createFolder(
-                        '111',
-                        [
-                          createItem('1111'),
-                        ]),
-                    createFolder('112', []),
-                  ]),
-              createItem('12'),
-              createItem('13'),
-              createFolder('14', []),
-              createFolder('15', []),
-            ]),
-        createFolder('2', []));
-    store = new TestStore({
-      nodes: nodes,
-      folderOpenState: getAllFoldersOpenState(nodes),
-      selectedFolder: '1',
-    });
-    store.replaceSingleton();
-
-    chrome.bookmarkManagerPrivate.startDrag = function(
-        idList, dragNodeIndex, isFromTouch) {
-      dndManager.dragInfo_.setNativeDragData(createDragData(idList));
-    };
-
-    const testBrowserProxy = new TestBookmarksBrowserProxy();
-    BrowserProxyImpl.setInstance(testBrowserProxy);
-    app = document.createElement('bookmarks-app');
-    replaceBody(app);
-    list = app.shadowRoot.querySelector('bookmarks-list');
-    rootFolderNode = app.shadowRoot.querySelector('bookmarks-folder-node');
-    dndManager = app.dndManager_;
-    dndManager.setTimerProxyForTesting(new TestTimerProxy());
-
-    // Wait for the API listener to call the browser proxy, since this
-    // indicates initialization is done.
-    return testBrowserProxy.whenCalled('getIncognitoAvailability').then(() => {
-      flush();
-    });
-  });
-
-  test('dragInfo isDraggingFolderToDescendant', function() {
-    const dragInfo = new DragInfo();
-    const nodes = store.data.nodes;
-    dragInfo.setNativeDragData(createDragData(['11']));
-    assertTrue(dragInfo.isDraggingFolderToDescendant('111', nodes));
-    assertFalse(dragInfo.isDraggingFolderToDescendant('1', nodes));
-    assertFalse(dragInfo.isDraggingFolderToDescendant('2', nodes));
-
-    dragInfo.setNativeDragData(createDragData(['1']));
-    assertTrue(dragInfo.isDraggingFolderToDescendant('14', nodes));
-    assertTrue(dragInfo.isDraggingFolderToDescendant('111', nodes));
-    assertFalse(dragInfo.isDraggingFolderToDescendant('2', nodes));
-  });
-
-  test('drag in list', function() {
-    const dragElement = getListItem('13');
-    let dragTarget = getListItem('12');
-
-    simulateDragStart(dragElement);
-
-    assertDeepEquals(['13'], getDragIds());
-
-    // Bookmark items cannot be dragged onto other items.
-    move(dragTarget, topLeftOfNode(dragTarget));
-    assertEquals(
-        DropPosition.ABOVE,
-        dndManager.calculateValidDropPositions_(dragTarget));
-    assertDragStyle(dragTarget, DRAG_STYLE.ABOVE);
-
-    move(document.body);
-    assertDragStyle(dragTarget, DRAG_STYLE.NONE);
-
-    // Bookmark items can be dragged onto folders.
-    dragTarget = getListItem('11');
-    move(dragTarget);
-    assertEquals(
-        DropPosition.ON | DropPosition.ABOVE | DropPosition.BELOW,
-        dndManager.calculateValidDropPositions_(dragTarget));
-    assertDragStyle(dragTarget, DRAG_STYLE.ON);
-
-    // There are no valid drop locations for dragging an item onto itself.
-    assertEquals(
-        DropPosition.NONE,
-        dndManager.calculateValidDropPositions_(dragElement));
-    move(dragElement);
-
-    assertDragStyle(dragTarget, DRAG_STYLE.NONE);
-    assertDragStyle(dragElement, DRAG_STYLE.NONE);
-  });
-
-  test('reorder folder nodes', function() {
-    const dragElement = getFolderNode('112');
-    const dragTarget = getFolderNode('111');
-
-    simulateDragStart(dragElement);
-
-    assertEquals(
-        DropPosition.ON | DropPosition.ABOVE,
-        dndManager.calculateValidDropPositions_(dragTarget));
-
-    move(dragTarget, topLeftOfNode(dragTarget));
-    assertDragStyle(dragTarget, DRAG_STYLE.ABOVE);
-  });
-
-  test('drag an item into a sidebar folder', function() {
-    const dragElement = getListItem('13');
-    let dragTarget = getFolderNode('2');
-    simulateDragStart(dragElement);
-
-    // Items can only be dragged onto sidebar folders, not above or below.
-    assertEquals(
-        DropPosition.ON, dndManager.calculateValidDropPositions_(dragTarget));
-
-    move(dragTarget);
-    assertDragStyle(dragTarget, DRAG_STYLE.ON);
-
-    // Items cannot be dragged onto their parent folders.
-    dragTarget = getFolderNode('1');
-    move(dragTarget);
-    assertDragStyle(dragTarget, DRAG_STYLE.NONE);
-  });
-
-  test('drag a folder into a descendant', function() {
-    const dragElement = getFolderNode('11');
-    const dragTarget = getFolderNode('112');
-
-    // Folders cannot be dragged into their descendants.
-    simulateDragStart(dragElement);
-    assertEquals(
-        DropPosition.NONE, dndManager.calculateValidDropPositions_(dragTarget));
-
-    move(dragTarget);
-
-    assertDragStyle(dragTarget, DRAG_STYLE.NONE);
-  });
-
-  test('drag item into sidebar folder with descendants', function() {
-    const dragElement = getFolderNode('15');
-    const dragTarget = getFolderNode('11');
-
-    simulateDragStart(dragElement);
-
-    // Drags below an open folder are not allowed.
-    assertEquals(
-        DropPosition.ON | DropPosition.ABOVE,
-        dndManager.calculateValidDropPositions_(dragTarget));
-
-    move(dragTarget);
-
-    assertDragStyle(dragTarget, DRAG_STYLE.ON);
-
-    dispatchDragEvent('dragend', dragElement);
-    assertDragStyle(dragTarget, DRAG_STYLE.NONE);
-
-    store.data.folderOpenState.set('11', false);
-    store.notifyObservers();
-
-    simulateDragStart(dragElement);
-
-    // Drags below a closed folder are allowed.
-    assertEquals(
-        DropPosition.ON | DropPosition.ABOVE | DropPosition.BELOW,
-        dndManager.calculateValidDropPositions_(dragTarget));
-  });
-
-  test('drag multiple list items', function() {
-    // Dragging multiple items.
-    store.data.selection.items = new Set(['13', '15']);
-    let dragElement = getListItem('13');
-    simulateDragStart(dragElement);
-    assertDeepEquals(['13', '15'], getDragIds());
-
-    // The dragged items should not be allowed to be dragged around any selected
-    // item.
-    assertEquals(
-        DropPosition.NONE,
-        dndManager.calculateValidDropPositions_(getListItem('13')));
-    assertEquals(
-        DropPosition.ON,
-        dndManager.calculateValidDropPositions_(getListItem('14')));
-    assertEquals(
-        DropPosition.NONE,
-        dndManager.calculateValidDropPositions_(getListItem('15')));
-    dispatchDragEvent('dragend', dragElement);
-
-    // Dragging an unselected item should only drag the unselected item.
-    dragElement = getListItem('14');
-    simulateDragStart(dragElement);
-    assertDeepEquals(['14'], getDragIds());
-    dispatchDragEvent('dragend', dragElement);
-
-    // Dragging a folder node should only drag the node.
-    dragElement = getListItem('11');
-    simulateDragStart(dragElement);
-    assertDeepEquals(['11'], getDragIds());
-  });
-
-  test('drag multiple list items preserve displaying order', function() {
-    // Dragging multiple items with different selection order.
-    store.data.selection.items = new Set(['15', '13']);
-    const dragElement = getListItem('13');
-    simulateDragStart(dragElement);
-    assertDeepEquals(['13', '15'], getDragIds());
-  });
-
-  test('bookmarks from different profiles', function() {
-    dndManager.handleChromeDragEnter_(createDragData(['11'], false));
-
-    // All positions should be allowed even with the same bookmark id if the
-    // drag element is from a different profile.
-    assertEquals(
-        DropPosition.ON | DropPosition.ABOVE | DropPosition.BELOW,
-        dndManager.calculateValidDropPositions_(getListItem('11')));
-
-    // Folders from other profiles should be able to be dragged into
-    // descendants in this profile.
-    assertEquals(
-        DropPosition.ON | DropPosition.ABOVE | DropPosition.BELOW,
-        dndManager.calculateValidDropPositions_(getFolderNode('112')));
-  });
-
-  test('drag from sidebar to list', function() {
-    const dragElement = getFolderNode('112');
-    const dragTarget = getListItem('13');
-
-    // Drag a folder onto the list.
-    simulateDragStart(dragElement);
-    assertDeepEquals(['112'], getDragIds());
-
-    move(dragTarget, topLeftOfNode(dragTarget));
-    assertDragStyle(dragTarget, DRAG_STYLE.ABOVE);
-
-    dispatchDragEvent('dragend', dragTarget);
-
-    // Folders should not be able to dragged onto themselves in the list.
-    dndManager.handleChromeDragEnter_(createDragData(['11']));
-    assertEquals(
-        DropPosition.NONE,
-        dndManager.calculateValidDropPositions_(getListItem('11')));
-
-    // Ancestors should not be able to be dragged onto descendant
-    // displayed lists.
-    store.data.selectedFolder = '111';
-    store.notifyObservers();
-    flush();
-
-    dndManager.handleChromeDragEnter_(createDragData(['11']));
-    assertEquals(
-        DropPosition.NONE,
-        dndManager.calculateValidDropPositions_(getListItem('1111')));
-  });
-
-  test('drags with search', function() {
-    store.data.search.term = 'Asgore';
-    store.data.search.results = ['11', '13', '2'];
-    store.data.selectedFolder = null;
-    store.notifyObservers();
-
-    // Search results should not be able to be dragged onto, but can be dragged
-    // from.
-    dndManager.handleChromeDragEnter_(createDragData(['2']));
-    assertEquals(
-        DropPosition.NONE,
-        dndManager.calculateValidDropPositions_(getListItem('13')));
-
-    // Drags onto folders should work as per usual.
-    assertEquals(
-        DropPosition.ON | DropPosition.ABOVE | DropPosition.BELOW,
-        dndManager.calculateValidDropPositions_(getFolderNode('112')));
-
-    // Drags onto an empty search list do nothing.
-    store.data.search.results = [];
-    store.notifyObservers();
-    assertEquals(
-        DropPosition.NONE, dndManager.calculateValidDropPositions_(list));
-  });
-
-  // This is a regression test for https://crbug.com/974525.
-  test(
-      'drag bookmark that is not in selected folder but in search result',
-      function() {
-        store.data.search.term = 'Asgore';
-        store.data.search.results = ['11', '13', '2'];
-        store.data.selectedFolder = null;
-        store.notifyObservers();
-
-        simulateDragStart(getListItem('13'));
-
-        assertDeepEquals(['13'], getDragIds());
-      });
-
-  test('calculateDropInfo_', function() {
-    function assertDropInfo(parentId, index, element, position) {
-      assertDeepEquals(
-          {parentId: parentId, index: index},
-          dndManager.calculateDropInfo_(
-              {element: element, position: position}));
-    }
-
-    // Drops onto the list.
-    assertDropInfo('1', 0, getListItem('11'), DropPosition.ABOVE);
-    assertDropInfo('1', 2, getListItem('12'), DropPosition.BELOW);
-    assertDropInfo('13', -1, getListItem('13'), DropPosition.ON);
-
-    // Drops onto the sidebar.
-    assertDropInfo('1', 4, getFolderNode('15'), DropPosition.ABOVE);
-    assertDropInfo('1', 5, getFolderNode('15'), DropPosition.BELOW);
-    assertDropInfo('111', -1, getFolderNode('111'), DropPosition.ON);
-  });
-
-  test('simple native drop end to end', function() {
-    let dropParentId;
-    let dropIndex;
-    chrome.bookmarkManagerPrivate.drop = function(parentId, index) {
-      dropParentId = parentId;
-      dropIndex = index;
-      return Promise.resolve();
-    };
-
-    setDebouncerForTesting();
-
-    const dragElement = getListItem('13');
-    const dragTarget = getListItem('12');
-
-    simulateDragStart(dragElement);
-    assertDeepEquals(['13'], getDragIds());
-
-    dispatchDragEvent('dragover', dragTarget, topLeftOfNode(dragTarget));
-    assertDragStyle(dragTarget, DRAG_STYLE.ABOVE);
-
-    dispatchDragEvent('drop', dragTarget);
-    assertEquals('1', dropParentId);
-    assertEquals(1, dropIndex);
-
-    dispatchDragEvent('dragend', dragTarget);
-    assertDragStyle(dragTarget, DRAG_STYLE.NONE);
-  });
-
-  test('auto expander', function() {
-    const timerProxy = new TestTimerProxy();
-    timerProxy.immediatelyResolveTimeouts = false;
-
-    const autoExpander = dndManager.autoExpander_;
-    autoExpander.debouncer_.timerProxy_ = timerProxy;
-
-    store.data.folderOpenState.set('11', false);
-    store.notifyObservers();
-    flush();
-
-    const dragElement = getFolderNode('14');
-    let dragTarget = getFolderNode('15');
-
-    simulateDragStart(dragElement);
-
-    // Dragging onto folders without children doesn't update the auto expander.
-    move(dragTarget);
-    assertEquals(null, autoExpander.lastElement_);
-
-    // Dragging onto open folders doesn't update the auto expander.
-    dragTarget = getFolderNode('1');
-    move(dragTarget);
-    assertEquals(null, autoExpander.lastElement_);
-
-    // Dragging onto a closed folder with children updates the auto expander.
-    dragTarget = getFolderNode('11');
-    move(dragTarget);
-    assertEquals(dragTarget, autoExpander.lastElement_);
-
-    // Dragging onto another item resets the auto expander.
-    dragTarget = getFolderNode('1');
-    move(dragTarget);
-    assertEquals(null, autoExpander.lastElement_);
-
-    // Dragging onto the list resets the auto expander.
-    dragTarget = getFolderNode('11');
-    move(dragTarget);
-    assertEquals(dragTarget, autoExpander.lastElement_);
-
-    dragTarget = list;
-    move(dragTarget);
-    assertEquals(null, autoExpander.lastElement_);
-
-    // Moving the mouse resets the delay.
-    dragTarget = getFolderNode('11');
-    move(dragTarget);
-    assertEquals(dragTarget, autoExpander.lastElement_);
-    const oldTimer = autoExpander.debouncer_.timer_;
-
-    move(dragTarget);
-    assertNotEquals(oldTimer, autoExpander.debouncer_.timer_);
-
-    // Auto expands after expand delay.
-    timerProxy.runTimeoutFn(autoExpander.debouncer_.timer_);
-    assertDeepEquals(changeFolderOpen('11', true), store.lastAction);
-    assertEquals(null, autoExpander.lastElement_);
-  });
-
-  test('drag onto empty list', function() {
-    store.data.selectedFolder = '14';
-    store.notifyObservers();
-
-    const dragElement = getFolderNode('15');
-    const dragTarget = list;
-
-    // Dragging onto an empty list.
-    simulateDragStart(dragElement);
-
-    move(dragTarget);
-    assertEquals(
-        DropPosition.ON, dndManager.calculateValidDropPositions_(dragTarget));
-    assertDragStyle(dragTarget, DRAG_STYLE.ON);
-
-    dispatchDragEvent('dragend', dragTarget);
-
-    // Dragging onto a non-empty list.
-    store.data.selectedFolder = '11';
-    store.notifyObservers();
-
-    simulateDragStart(dragElement);
-
-    move(dragTarget);
-    assertEquals(
-        DropPosition.NONE, dndManager.calculateValidDropPositions_(dragTarget));
-    assertDragStyle(dragTarget, DRAG_STYLE.NONE);
-  });
-
-  test('drag item selects/deselects items', function() {
-    store.setReducersEnabled(true);
-
-    store.data.selection.items = new Set(['13', '15']);
-    store.notifyObservers();
-
-    // Dragging an item not in the selection selects the dragged item and
-    // deselects the previous selection.
-    let dragElement = getListItem('14');
-    simulateDragStart(dragElement);
-    assertDeepEquals(['14'], normalizeIterable(store.data.selection.items));
-    dispatchDragEvent('dragend', dragElement);
-
-    // Dragging a folder node deselects any selected items in the bookmark list.
-    dragElement = getFolderNode('15');
-    simulateDragStart(dragElement);
-    assertDeepEquals([], normalizeIterable(store.data.selection.items));
-    dispatchDragEvent('dragend', dragElement);
-  });
-
-  test('cannot drag items when editing is disabled', function() {
-    store.data.prefs.canEdit = false;
-    store.notifyObservers();
-
-    const dragElement = getFolderNode('11');
-    simulateDragStart(dragElement);
-    assertFalse(dndManager.dragInfo_.isDragValid());
-  });
-
-  test('cannot start dragging unmodifiable items', function() {
-    store.data.nodes['2'].unmodifiable = 'managed';
-    store.notifyObservers();
-
-    let dragElement = getFolderNode('1');
-    simulateDragStart(dragElement);
-    assertFalse(dndManager.dragInfo_.isDragValid());
-
-    dragElement = getFolderNode('2');
-    simulateDragStart(dragElement);
-    assertFalse(dndManager.dragInfo_.isDragValid());
-  });
-
-  test('cannot drag onto folders with unmodifiable children', function() {
-    store.data.nodes['2'].unmodifiable = 'managed';
-    store.notifyObservers();
-
-    const dragElement = getListItem('12');
-    simulateDragStart(dragElement);
-
-    // Can't drag onto the unmodifiable node.
-    const dragTarget = getFolderNode('2');
-    move(dragTarget);
-    assertEquals(
-        DropPosition.NONE, dndManager.calculateValidDropPositions_(dragTarget));
-  });
-});
diff --git a/chrome/test/data/webui/bookmarks/dnd_manager_test.ts b/chrome/test/data/webui/bookmarks/dnd_manager_test.ts
new file mode 100644
index 0000000..371c5962
--- /dev/null
+++ b/chrome/test/data/webui/bookmarks/dnd_manager_test.ts
@@ -0,0 +1,561 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {BookmarkElement, BookmarkManagerApiProxyImpl, BookmarksAppElement, BookmarksFolderNodeElement, BookmarksListElement, BrowserProxyImpl, DndManager, DragInfo, setDebouncerForTesting} from 'chrome://bookmarks/bookmarks.js';
+import {assertNotReached} from 'chrome://resources/js/assert_ts.js';
+import {middleOfNode, topLeftOfNode} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+
+import {TestBookmarkManagerApiProxy} from './test_bookmark_manager_api_proxy.js';
+import {TestBookmarksBrowserProxy} from './test_browser_proxy.js';
+import {TestStore} from './test_store.js';
+import {TestTimerProxy} from './test_timer_proxy.js';
+import {createFolder, createItem, findFolderNode, getAllFoldersOpenState, normalizeIterable, replaceBody, testTree} from './test_util.js';
+
+suite('drag and drop', function() {
+  let app: BookmarksAppElement;
+  let list: BookmarksListElement;
+  let rootFolderNode: BookmarksFolderNodeElement;
+  let store: TestStore;
+  let dndManager: DndManager;
+  let bookmarkManagerApi: TestBookmarkManagerApiProxy;
+
+  enum DragStyle {
+    NONE = 0,
+    ON = 1,
+    ABOVE = 2,
+    BELOW = 3,
+  }
+
+  function getFolderNode(id: string) {
+    return findFolderNode(rootFolderNode, id) as BookmarkElement;
+  }
+
+  function getListItem(id: string) {
+    const items = list.root!.querySelectorAll('bookmarks-item');
+    for (let i = 0; i < items.length; i++) {
+      if (items[i]!.itemId === id) {
+        return items[i] as BookmarkElement;
+      }
+    }
+    assertNotReached();
+  }
+
+  function dispatchDragEvent(
+      type: string, node: HTMLElement, xy?: {x: number, y: number}) {
+    xy = xy || middleOfNode(node);
+    const props = {
+      bubbles: true,
+      cancelable: true,
+      composed: true,
+      clientX: xy!.x,
+      clientY: xy!.y,
+      // Make this a primary input.
+      buttons: 1,
+    };
+    const e = new DragEvent(type, props);
+    node.dispatchEvent(e);
+  }
+
+  function bottomRightOfNode(target: HTMLElement) {
+    const rect = target.getBoundingClientRect();
+    return {y: rect.top + rect.height, x: rect.left + rect.width};
+  }
+
+  function assertDragStyle(bookmarkElement: BookmarkElement, style: DragStyle) {
+    const dragStyles: {[key: string]: string} = {};
+    dragStyles[DragStyle.ON] = 'drag-on';
+    dragStyles[DragStyle.ABOVE] = 'drag-above';
+    dragStyles[DragStyle.BELOW] = 'drag-below';
+
+    const classList = bookmarkElement.getDropTarget()!.classList;
+    Object.entries(dragStyles).forEach(([dragStyle, value]) => {
+      assertEquals(
+          dragStyle === style.toString(), classList.contains(value),
+          value + (dragStyle === style.toString() ? ' missing' : ' found') +
+              ' in classList ' + classList);
+    });
+  }
+
+  function createDragData(ids: string[], sameProfile: boolean = true) {
+    return {
+      elements: ids.map(
+          id => store.data.nodes[id] as chrome.bookmarks.BookmarkTreeNode),
+      sameProfile: sameProfile,
+    };
+  }
+
+  async function simulateDragStart(dragElement: HTMLElement) {
+    dispatchDragEvent('dragstart', dragElement);
+    const idList = await bookmarkManagerApi.whenCalled('startDrag');
+    bookmarkManagerApi.resetResolver('startDrag');
+    dndManager.getDragInfoForTesting()!.setNativeDragData(
+        createDragData(idList));
+    move(dragElement, topLeftOfNode(dragElement));
+  }
+
+  function move(target: HTMLElement, dest?: {x: number, y: number}) {
+    dispatchDragEvent('dragover', target, dest || middleOfNode(target));
+  }
+
+  function getDragIds() {
+    return dndManager.getDragInfoForTesting()!.dragData!.elements.map(
+        (x) => x.id);
+  }
+
+  setup(function() {
+    const nodes = testTree(
+        createFolder(
+            '1',
+            [
+              createFolder(
+                  '11',
+                  [
+                    createFolder(
+                        '111',
+                        [
+                          createItem('1111'),
+                        ]),
+                    createFolder('112', []),
+                  ]),
+              createItem('12'),
+              createItem('13'),
+              createFolder('14', []),
+              createFolder('15', []),
+            ]),
+        createFolder('2', []));
+    store = new TestStore({
+      nodes: nodes,
+      folderOpenState: getAllFoldersOpenState(nodes),
+      selectedFolder: '1',
+    });
+    store.replaceSingleton();
+
+    bookmarkManagerApi = new TestBookmarkManagerApiProxy();
+    BookmarkManagerApiProxyImpl.setInstance(bookmarkManagerApi);
+
+    const testBrowserProxy = new TestBookmarksBrowserProxy();
+    BrowserProxyImpl.setInstance(testBrowserProxy);
+    app = document.createElement('bookmarks-app');
+    replaceBody(app);
+    list =
+        app.shadowRoot!.querySelector('bookmarks-list') as BookmarksListElement;
+    rootFolderNode = app.shadowRoot!.querySelector('bookmarks-folder-node') as
+        BookmarksFolderNodeElement;
+    dndManager = app.getDndManagerForTesting() as DndManager;
+    dndManager!.setTimerProxyForTesting(new TestTimerProxy());
+
+    // Wait for the API listener to call the browser proxy, since this
+    // indicates initialization is done.
+    return testBrowserProxy.whenCalled('getIncognitoAvailability').then(() => {
+      flush();
+    });
+  });
+
+  test('dragInfo isDraggingFolderToDescendant', function() {
+    const dragInfo = new DragInfo();
+    const nodes = store.data.nodes;
+    dragInfo.setNativeDragData(createDragData(['11']));
+    assertTrue(dragInfo.isDraggingFolderToDescendant('111', nodes));
+    assertFalse(dragInfo.isDraggingFolderToDescendant('1', nodes));
+    assertFalse(dragInfo.isDraggingFolderToDescendant('2', nodes));
+
+    dragInfo.setNativeDragData(createDragData(['1']));
+    assertTrue(dragInfo.isDraggingFolderToDescendant('14', nodes));
+    assertTrue(dragInfo.isDraggingFolderToDescendant('111', nodes));
+    assertFalse(dragInfo.isDraggingFolderToDescendant('2', nodes));
+  });
+
+  test('drag in list', async function() {
+    const dragElement = getListItem('13');
+    let dragTarget = getListItem('12');
+
+    await simulateDragStart(dragElement);
+
+    assertDeepEquals(['13'], getDragIds());
+
+    // Bookmark items cannot be dragged onto other items.
+    move(dragTarget, topLeftOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ABOVE);
+
+    move(document.body);
+    assertDragStyle(dragTarget, DragStyle.NONE);
+
+    // Bookmark items can be dragged onto folders.
+    dragTarget = getListItem('11');
+    move(dragTarget, topLeftOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ABOVE);
+
+    move(dragTarget, middleOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ON);
+
+    move(dragTarget, bottomRightOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.BELOW);
+
+    // There are no valid drop locations for dragging an item onto itself.
+    move(dragElement);
+
+    assertDragStyle(dragTarget, DragStyle.NONE);
+    assertDragStyle(dragElement, DragStyle.NONE);
+  });
+
+  test('reorder folder nodes', async function() {
+    const dragElement = getFolderNode('112');
+    const dragTarget = getFolderNode('111');
+
+    await simulateDragStart(dragElement);
+
+    move(dragTarget, topLeftOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ABOVE);
+
+    move(dragTarget, bottomRightOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ON);
+  });
+
+  test('drag an item into a sidebar folder', async function() {
+    const dragElement = getListItem('13');
+    let dragTarget = getFolderNode('2');
+    await simulateDragStart(dragElement);
+
+    // Items can only be dragged onto sidebar folders, not above or below.
+    move(dragTarget, topLeftOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ON);
+
+    move(dragTarget, middleOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ON);
+
+    move(dragTarget, bottomRightOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ON);
+
+    // Items cannot be dragged onto their parent folders.
+    dragTarget = getFolderNode('1');
+    move(dragTarget);
+    assertDragStyle(dragTarget, DragStyle.NONE);
+  });
+
+  test('drag a folder into a descendant', async function() {
+    const dragElement = getFolderNode('11');
+    const dragTarget = getFolderNode('112');
+
+    // Folders cannot be dragged into their descendants.
+    await simulateDragStart(dragElement);
+
+    move(dragTarget);
+
+    assertDragStyle(dragTarget, DragStyle.NONE);
+  });
+
+  test('drag item into sidebar folder with descendants', async function() {
+    const dragElement = getFolderNode('15');
+    const dragTarget = getFolderNode('11');
+
+    await simulateDragStart(dragElement);
+
+    // Drags below an open folder are not allowed.
+    move(dragTarget, middleOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ON);
+
+    move(dragTarget, bottomRightOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ON);
+
+    move(dragTarget, topLeftOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ABOVE);
+
+    dispatchDragEvent('dragend', dragElement);
+    assertDragStyle(dragTarget, DragStyle.NONE);
+
+    store.data.folderOpenState.set('11', false);
+    store.notifyObservers();
+
+    await simulateDragStart(dragElement);
+
+    // Drags below a closed folder are allowed.
+    move(dragTarget, bottomRightOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.BELOW);
+  });
+
+  test('drag multiple list items', async function() {
+    // Dragging multiple items.
+    store.data.selection.items = new Set(['13', '15']);
+    let dragElement = getListItem('13');
+    await simulateDragStart(dragElement);
+    assertDeepEquals(['13', '15'], getDragIds());
+
+    // The dragged items should not be allowed to be dragged around any selected
+    // item.
+    let dragTarget = getListItem('13');
+    move(dragTarget);
+    assertDragStyle(dragTarget, DragStyle.NONE);
+
+    dragTarget = getListItem('14');
+    move(dragTarget);
+    assertDragStyle(dragTarget, DragStyle.ON);
+
+    dragTarget = getListItem('15');
+    move(dragTarget);
+    assertDragStyle(dragTarget, DragStyle.NONE);
+
+    dispatchDragEvent('dragend', dragElement);
+
+    // Dragging an unselected item should only drag the unselected item.
+    dragElement = getListItem('14');
+    await simulateDragStart(dragElement);
+    assertDeepEquals(['14'], getDragIds());
+    dispatchDragEvent('dragend', dragElement);
+
+    // Dragging a folder node should only drag the node.
+    dragElement = getListItem('11');
+    await simulateDragStart(dragElement);
+    assertDeepEquals(['11'], getDragIds());
+  });
+
+  test('drag multiple list items preserve displaying order', async function() {
+    // Dragging multiple items with different selection order.
+    store.data.selection.items = new Set(['15', '13']);
+    const dragElement = getListItem('13');
+    await simulateDragStart(dragElement);
+    assertDeepEquals(['13', '15'], getDragIds());
+  });
+
+  test('bookmarks from different profiles', function() {
+    bookmarkManagerApi.onDragEnter.callListeners(createDragData(['11'], false));
+
+    // All positions should be allowed even with the same bookmark id if the
+    // drag element is from a different profile.
+    let dragTarget = getListItem('11');
+    move(dragTarget, topLeftOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ABOVE);
+
+    move(dragTarget, middleOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ON);
+
+    move(dragTarget, bottomRightOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.BELOW);
+
+    // Folders from other profiles should be able to be dragged into
+    // descendants in this profile.
+    dragTarget = getFolderNode('112');
+    move(dragTarget, topLeftOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ABOVE);
+
+    move(dragTarget, middleOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ON);
+
+    move(dragTarget, bottomRightOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.BELOW);
+  });
+
+  test('drag from sidebar to list', async function() {
+    let dragElement = getFolderNode('112');
+    let dragTarget = getListItem('13');
+
+    // Drag a folder onto the list.
+    await simulateDragStart(dragElement);
+    assertDeepEquals(['112'], getDragIds());
+
+    move(dragTarget, topLeftOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ABOVE);
+
+    dispatchDragEvent('dragend', dragTarget);
+
+    // Folders should not be able to dragged onto themselves in the list.
+    bookmarkManagerApi.onDragEnter.callListeners(createDragData(['11']));
+    dragElement = getListItem('11');
+    move(dragElement);
+    assertDragStyle(dragElement, DragStyle.NONE);
+
+    // Ancestors should not be able to be dragged onto descendant
+    // displayed lists.
+    store.data.selectedFolder = '111';
+    store.notifyObservers();
+    flush();
+
+    bookmarkManagerApi.onDragEnter.callListeners(createDragData(['11']));
+    dragTarget = getListItem('1111');
+    move(dragTarget);
+    assertDragStyle(dragTarget, DragStyle.NONE);
+  });
+
+  test('drags with search', function() {
+    store.data.search.term = 'Asgore';
+    store.data.search.results = ['11', '13', '2'];
+    store.data.selectedFolder = '';
+    store.notifyObservers();
+
+    // Search results should not be able to be dragged onto, but can be dragged
+    // from.
+    bookmarkManagerApi.onDragEnter.callListeners(createDragData(['2']));
+    let dragTarget = getListItem('13');
+    move(dragTarget);
+    assertDragStyle(dragTarget, DragStyle.NONE);
+
+    // Drags onto folders should work as per usual.
+    dragTarget = getFolderNode('112');
+    move(dragTarget, topLeftOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ABOVE);
+
+    move(dragTarget, middleOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ON);
+
+    move(dragTarget, bottomRightOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.BELOW);
+  });
+
+  // This is a regression test for https://crbug.com/974525.
+  test(
+      'drag bookmark that is not in selected folder but in search result',
+      async function() {
+        store.data.search.term = 'Asgore';
+        store.data.search.results = ['11', '13', '2'];
+        store.data.selectedFolder = '';
+        store.notifyObservers();
+
+        await simulateDragStart(getListItem('13'));
+
+        assertDeepEquals(['13'], getDragIds());
+      });
+
+  test('simple native drop end to end', async function() {
+    const dragElement = getListItem('13');
+    const dragTarget = getListItem('12');
+
+    await simulateDragStart(dragElement);
+    assertDeepEquals(['13'], getDragIds());
+
+    dispatchDragEvent('dragover', dragTarget, topLeftOfNode(dragTarget));
+    assertDragStyle(dragTarget, DragStyle.ABOVE);
+
+    setDebouncerForTesting();
+    dispatchDragEvent('drop', dragTarget);
+
+    const [dropParentId, dropIndex] =
+        await bookmarkManagerApi.whenCalled('drop');
+
+    assertEquals('1', dropParentId);
+    assertEquals(1, dropIndex);
+
+    dispatchDragEvent('dragend', dragTarget);
+    assertDragStyle(dragTarget, DragStyle.NONE);
+  });
+
+  /* Test is disabled because auto-expander functionality
+     is currently broken (https://crbug.com/1406349)
+
+  test('auto expander', async function() {
+    const timerProxy = new TestTimerProxy();
+    timerProxy.immediatelyResolveTimeouts = false;
+
+    const autoExpander = dndManager.autoExpander_;
+    autoExpander.debouncer_.timerProxy_ = timerProxy;
+
+    store.data.folderOpenState.set('11', false);
+    store.notifyObservers();
+    flush();
+
+    const dragElement = getFolderNode('14');
+    let dragTarget = getFolderNode('15');
+
+    simulateDragStart(dragElement);
+
+    // Dragging onto folders without children doesn't update the auto expander.
+    move(dragTarget);
+    assertEquals(null, autoExpander.lastElement_);
+
+    // Dragging onto open folders doesn't update the auto expander.
+    dragTarget = getFolderNode('1');
+    move(dragTarget);
+    assertEquals(null, autoExpander.lastElement_);
+
+    // Dragging onto a closed folder with children updates the auto expander.
+    dragTarget = getFolderNode('11');
+    move(dragTarget);
+    assertEquals(dragTarget, autoExpander.lastElement_);
+
+    // Dragging onto another item resets the auto expander.
+    dragTarget = getFolderNode('1');
+    move(dragTarget);
+    assertEquals(null, autoExpander.lastElement_);
+
+    // Dragging onto the list resets the auto expander.
+    dragTarget = getFolderNode('11');
+    move(dragTarget);
+    assertEquals(dragTarget, autoExpander.lastElement_);
+
+    dragTarget = list;
+    move(dragTarget);
+    assertEquals(null, autoExpander.lastElement_);
+
+    // Moving the mouse resets the delay.
+    dragTarget = getFolderNode('11');
+    move(dragTarget);
+    assertEquals(dragTarget, autoExpander.lastElement_);
+    const oldTimer = autoExpander.debouncer_.timer_;
+
+    move(dragTarget);
+    assertNotEquals(oldTimer, autoExpander.debouncer_.timer_);
+
+    // Auto expands after expand delay.
+    timerProxy.runTimeoutFn(autoExpander.debouncer_.timer_);
+    assertDeepEquals(changeFolderOpen('11', true), store.lastAction);
+    assertEquals(null, autoExpander.lastElement_);
+  });
+  */
+
+  test('drag item selects/deselects items', async function() {
+    store.setReducersEnabled(true);
+
+    store.data.selection.items = new Set(['13', '15']);
+    store.notifyObservers();
+
+    // Dragging an item not in the selection selects the dragged item and
+    // deselects the previous selection.
+    let dragElement = getListItem('14');
+    await simulateDragStart(dragElement);
+    assertDeepEquals(['14'], normalizeIterable(store.data.selection.items));
+    dispatchDragEvent('dragend', dragElement);
+
+    // Dragging a folder node deselects any selected items in the bookmark list.
+    dragElement = getFolderNode('15');
+    await simulateDragStart(dragElement);
+    assertDeepEquals([], normalizeIterable(store.data.selection.items));
+    dispatchDragEvent('dragend', dragElement);
+  });
+
+  test('cannot drag items when editing is disabled', async function() {
+    store.data.prefs.canEdit = false;
+    store.notifyObservers();
+
+    const dragElement = getFolderNode('11');
+
+    dispatchDragEvent('dragstart', dragElement);
+    assertFalse(dndManager.getDragInfoForTesting()!.isDragValid());
+  });
+
+  test('cannot start dragging unmodifiable items', async function() {
+    store.data.nodes['2']!.unmodifiable = 'managed';
+    store.notifyObservers();
+
+    let dragElement = getFolderNode('1');
+    dispatchDragEvent('dragstart', dragElement);
+    assertFalse(dndManager.getDragInfoForTesting()!.isDragValid());
+
+    dragElement = getFolderNode('2');
+    dispatchDragEvent('dragstart', dragElement);
+    assertFalse(dndManager.getDragInfoForTesting()!.isDragValid());
+  });
+
+  test('cannot drag onto folders with unmodifiable children', async function() {
+    store.data.nodes['2']!.unmodifiable = 'managed';
+    store.notifyObservers();
+
+    const dragElement = getListItem('12');
+    await simulateDragStart(dragElement);
+
+    // Can't drag onto the unmodifiable node.
+    const dragTarget = getFolderNode('2');
+    move(dragTarget);
+    assertDragStyle(dragTarget, DragStyle.NONE);
+  });
+});
diff --git a/chrome/test/data/webui/bookmarks/store_test.js b/chrome/test/data/webui/bookmarks/store_test.js
deleted file mode 100644
index 1458c6f..0000000
--- a/chrome/test/data/webui/bookmarks/store_test.js
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {removeBookmark, Store, StoreClientMixin} from 'chrome://bookmarks/bookmarks.js';
-import {flush, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {TestStore} from './test_store.js';
-import {createFolder, createItem, getAllFoldersOpenState, replaceBody, testTree} from './test_util.js';
-
-suite('bookmarks.Store', function() {
-  let store;
-
-  setup(function() {
-    const nodes = testTree(createFolder('1', [
-      createItem('11'),
-      createItem('12'),
-      createItem('13'),
-    ]));
-    store = new TestStore({
-      nodes: nodes,
-      folderOpenState: getAllFoldersOpenState(nodes),
-    });
-    store.setReducersEnabled(true);
-    store.replaceSingleton();
-  });
-
-  test('batch mode disables updates', function() {
-    let lastStateChange = null;
-    const observer = {
-      onStateChanged: function(state) {
-        lastStateChange = state;
-      },
-    };
-
-    store.addObserver(observer);
-    store.beginBatchUpdate();
-
-    store.dispatch(removeBookmark('11', '1', 0, store.data.nodes));
-    assertEquals(null, lastStateChange);
-    store.dispatch(removeBookmark('12', '1', 0, store.data.nodes));
-    assertEquals(null, lastStateChange);
-
-    store.endBatchUpdate();
-    assertDeepEquals(['13'], lastStateChange.nodes['1'].children);
-  });
-});
-
-suite('bookmarks.StoreClientMixin', function() {
-  let store;
-  let client;
-
-  function update(newState) {
-    store.notifyObservers_(newState);
-    flush();
-  }
-
-  function getRenderedItems() {
-    return Array.from(client.root.querySelectorAll('.item'))
-        .map((div) => div.textContent.trim());
-  }
-
-  suiteSetup(function() {
-    const TestStoreClientBase = StoreClientMixin(PolymerElement);
-    class TestStoreClient extends TestStoreClientBase {
-      static get template() {
-        return html`
-          <template is="dom-repeat" items="[[items]]">
-            <div class="item">[[item]]</div>
-          </template>
-        `;
-      }
-
-      static get properties() {
-        return {
-          items: {
-            type: Array,
-            observer: 'itemsChanged_',
-          },
-        };
-      }
-
-      connectedCallback() {
-        super.connectedCallback();
-        this.hasChanged = false;
-        this.watch('items', function(state) {
-          return state.items;
-        });
-        this.updateFromStore();
-      }
-
-      itemsChanged_(newItems, oldItems) {
-        if (oldItems) {
-          this.hasChanged = true;
-        }
-      }
-    }
-
-    customElements.define('test-store-client', TestStoreClient);
-  });
-
-  setup(function() {
-    document.body.innerHTML = window.trustedTypes.emptyHTML;
-
-    // Reset store instance:
-    Store.setInstance(new Store());
-    store = Store.getInstance();
-    store.init({
-      items: ['apple', 'banana', 'cantaloupe'],
-      count: 3,
-    });
-
-    client = document.createElement('test-store-client');
-    document.body.appendChild(client);
-    flush();
-  });
-
-  test('renders initial data', function() {
-    assertDeepEquals(['apple', 'banana', 'cantaloupe'], getRenderedItems());
-  });
-
-  test('renders changes to watched state', function() {
-    const newItems = ['apple', 'banana', 'courgette', 'durian'];
-    const newState = Object.assign({}, store.data, {
-      items: newItems,
-    });
-    update(newState);
-
-    assertTrue(client.hasChanged);
-    assertDeepEquals(newItems, getRenderedItems());
-  });
-
-  test('ignores changes to other subtrees', function() {
-    const newState = Object.assign({}, store.data, {count: 2});
-    update(newState);
-
-    assertFalse(client.hasChanged);
-  });
-});
diff --git a/chrome/test/data/webui/bookmarks/store_test.ts b/chrome/test/data/webui/bookmarks/store_test.ts
new file mode 100644
index 0000000..2c24d03
--- /dev/null
+++ b/chrome/test/data/webui/bookmarks/store_test.ts
@@ -0,0 +1,152 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {BookmarksPageState, createEmptyState, NodeMap, removeBookmark, Store, StoreClientMixin} from 'chrome://bookmarks/bookmarks.js';
+import {flush, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+
+import {TestStore} from './test_store.js';
+import {createFolder, createItem, getAllFoldersOpenState, testTree} from './test_util.js';
+
+const TestStoreClientBase = StoreClientMixin(PolymerElement);
+
+class TestStoreClient extends TestStoreClientBase {
+  hasChanged: boolean = false;
+
+  static get template() {
+    return html`
+      <template is="dom-repeat" items="[[toArray(items)]]">
+        <div class="item">[[item]]</div>
+      </template>
+    `;
+  }
+
+  static get properties() {
+    return {
+      items: {
+        type: Object,
+        observer: 'itemsChanged',
+      },
+    };
+  }
+
+  toArray(items: NodeMap) {
+    return Object.values(items).map(value => value.id);
+  }
+
+  override connectedCallback() {
+    super.connectedCallback();
+    this.watch('items', function(state) {
+      return state.nodes;
+    });
+    this.updateFromStore();
+  }
+
+  itemsChanged(_newItems: NodeMap, oldItems?: NodeMap) {
+    if (oldItems) {
+      this.hasChanged = true;
+    }
+  }
+}
+
+customElements.define('test-store-client', TestStoreClient);
+
+suite('bookmarks.Store', function() {
+  let store: TestStore;
+
+  setup(function() {
+    const nodes = testTree(createFolder('1', [
+      createItem('11'),
+      createItem('12'),
+      createItem('13'),
+    ]));
+    store = new TestStore({
+      nodes: nodes,
+      folderOpenState: getAllFoldersOpenState(nodes),
+    });
+    store.setReducersEnabled(true);
+    store.replaceSingleton();
+  });
+
+  test('batch mode disables updates', function() {
+    let lastStateChange: BookmarksPageState|null = null;
+    const observer = {
+      onStateChanged: function(state: BookmarksPageState) {
+        lastStateChange = state;
+      },
+    };
+
+    store.addObserver(observer);
+    store.beginBatchUpdate();
+
+    store.dispatch(removeBookmark('11', '1', 0, store.data.nodes));
+    assertEquals(null, lastStateChange);
+    store.dispatch(removeBookmark('12', '1', 0, store.data.nodes));
+    assertEquals(null, lastStateChange);
+
+    store.endBatchUpdate();
+    assertDeepEquals(['13'], lastStateChange!.nodes['1']!.children);
+  });
+});
+
+suite('bookmarks.StoreClientMixin', function() {
+  let store: Store;
+  let client: TestStoreClient;
+
+  function update(newState: BookmarksPageState) {
+    store.data = newState;
+    store.endBatchUpdate();
+    flush();
+  }
+
+  function getRenderedItems() {
+    return Array.from(client.shadowRoot!.querySelectorAll('.item'))
+        .map((div) => div.textContent!.trim());
+  }
+
+  setup(function() {
+    document.body.innerHTML = window.trustedTypes!.emptyHTML;
+
+    // Reset store instance:
+    Store.setInstance(new Store());
+    store = Store.getInstance();
+    const state = createEmptyState();
+    state.nodes = testTree(createFolder('1', [
+      createItem('11'),
+      createItem('12'),
+      createItem('13'),
+    ]));
+    store.init(state);
+
+    client = document.createElement('test-store-client') as TestStoreClient;
+    document.body.appendChild(client);
+    flush();
+  });
+
+  test('renders initial data', function() {
+    assertDeepEquals(['0', '1', '11', '12', '13'], getRenderedItems());
+  });
+
+  test('renders changes to watched state', function() {
+    assertFalse(client.hasChanged);
+    const newItems = testTree(createFolder('1', [
+      createItem('11'),
+      createItem('12'),
+    ]));
+    const newState = Object.assign({}, store.data, {
+      nodes: newItems,
+    });
+    update(newState);
+
+    assertTrue(client.hasChanged);
+    assertDeepEquals(['0', '1', '11', '12'], getRenderedItems());
+  });
+
+  test('ignores changes to other subtrees', function() {
+    const newState = Object.assign({}, store.data, {selectedFolder: 'foo'});
+    update(newState);
+
+    assertFalse(client.hasChanged);
+  });
+});
diff --git a/chrome/test/data/webui/chromeos/internet_detail_dialog_test.js b/chrome/test/data/webui/chromeos/internet_detail_dialog_test.js
index 6c7fc33f..329af08 100644
--- a/chrome/test/data/webui/chromeos/internet_detail_dialog_test.js
+++ b/chrome/test/data/webui/chromeos/internet_detail_dialog_test.js
@@ -69,9 +69,8 @@
     mojoApi_.resetForTest();
   });
 
-  async function init(captive_portal_2022) {
+  async function init() {
     internetDetailDialog = document.createElement('internet-detail-dialog');
-    internetDetailDialog.isCaptivePortalUI2022Enabled_ = captive_portal_2022;
     document.body.appendChild(internetDetailDialog);
     await flushAsync();
   }
@@ -129,7 +128,7 @@
       wifiNetwork.portalState = PortalState.kPortal;
 
       mojoApi_.setManagedPropertiesForTest(wifiNetwork);
-      init(/*captive_portal_2022=*/ true);
+      init();
       return flushAsync().then(() => {
         const networkStateText =
             internetDetailDialog.shadowRoot.querySelector(`#networkState`);
@@ -153,7 +152,7 @@
       wifiNetwork.portalState = PortalState.kNoInternet;
 
       mojoApi_.setManagedPropertiesForTest(wifiNetwork);
-      init(/*captive_portal_2022=*/ true);
+      init();
       return flushAsync().then(() => {
         const networkStateText =
             internetDetailDialog.shadowRoot.querySelector(`#networkState`);
@@ -178,7 +177,7 @@
       wifiNetwork.portalState = PortalState.kProxyAuthRequired;
 
       mojoApi_.setManagedPropertiesForTest(wifiNetwork);
-      init(/*captive_portal_2022=*/ true);
+      init();
       return flushAsync().then(() => {
         const networkStateText =
             internetDetailDialog.shadowRoot.querySelector(`#networkState`);
@@ -192,30 +191,6 @@
         assertFalse(signinButton.disabled);
       });
     });
-
-    test('WiFi in a portal portalState and feature flag disabled', function() {
-      mojoApi_.setNetworkTypeEnabledState(NetworkType.kWiFi, true);
-      const wifiNetwork = getManagedProperties(NetworkType.kWiFi, 'wifi_user');
-      wifiNetwork.source = OncSource.kUser;
-      wifiNetwork.connectable = true;
-      wifiNetwork.connectionState = ConnectionStateType.kPortal;
-      wifiNetwork.portalState = PortalState.kPortal;
-
-      mojoApi_.setManagedPropertiesForTest(wifiNetwork);
-      init(/*captive_portal_2022=*/ false);
-      return flushAsync().then(() => {
-        const networkStateText =
-            internetDetailDialog.shadowRoot.querySelector(`#networkState`);
-        assertTrue(networkStateText.hasAttribute('connected'));
-        assertEquals(
-            networkStateText.textContent.trim(),
-            internetDetailDialog.i18n('OncConnected'));
-        const signinButton =
-            internetDetailDialog.shadowRoot.querySelector(`#signinButton`);
-        // Button does not exist because feature flag is disabled.
-        assertTrue(!signinButton);
-      });
-    });
   });
 
   test('Network not on active sim, hide configurations', async () => {
diff --git a/chrome/test/data/webui/chromeos/parent_access/parent_access_app_test.js b/chrome/test/data/webui/chromeos/parent_access/parent_access_app_test.js
index 0cc8c304..7ce8d7ac 100644
--- a/chrome/test/data/webui/chromeos/parent_access/parent_access_app_test.js
+++ b/chrome/test/data/webui/chromeos/parent_access/parent_access_app_test.js
@@ -49,7 +49,8 @@
         await flushTasks();
 
         // Verify online flow is showing and switch to the after screen.
-        assertEquals(parentAccessApp.currentScreen_, Screens.ONLINE_FLOW);
+        assertEquals(
+            parentAccessApp.currentScreen_, Screens.AUTHENTICATION_FLOW);
         parentAccessApp.dispatchEvent(new CustomEvent('show-after'));
         await flushTasks();
 
@@ -94,7 +95,7 @@
     await flushTasks();
 
     // Verify online flow is showing
-    assertEquals(parentAccessApp.currentScreen_, Screens.ONLINE_FLOW);
+    assertEquals(parentAccessApp.currentScreen_, Screens.AUTHENTICATION_FLOW);
 
     // Verify offline screen shows when window triggers offline event
     window.dispatchEvent(new Event('offline'));
@@ -105,7 +106,7 @@
     // offline
     window.dispatchEvent(new Event('online'));
     await flushTasks();
-    assertEquals(parentAccessApp.currentScreen_, Screens.ONLINE_FLOW);
+    assertEquals(parentAccessApp.currentScreen_, Screens.AUTHENTICATION_FLOW);
   });
 
   test(parent_access_app_tests.TestNames.TestErrorStateIsTerminal, async () => {
diff --git a/chrome/test/data/webui/chromeos/shortcut_customization/text_accelerator_test.ts b/chrome/test/data/webui/chromeos/shortcut_customization/text_accelerator_test.ts
index f19e503..5740ee9 100644
--- a/chrome/test/data/webui/chromeos/shortcut_customization/text_accelerator_test.ts
+++ b/chrome/test/data/webui/chromeos/shortcut_customization/text_accelerator_test.ts
@@ -5,28 +5,19 @@
 import 'chrome://shortcut-customization/js/text_accelerator.js';
 import 'chrome://webui-test/mojo_webui_test_support.js';
 
-import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {IronIconElement} from 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import {InputKeyElement, KeyInputState} from 'chrome://shortcut-customization/js/input_key.js';
 import {mojoString16ToString, stringToMojoString16} from 'chrome://shortcut-customization/js/mojo_utils.js';
 import {TextAcceleratorPart, TextAcceleratorPartType} from 'chrome://shortcut-customization/js/shortcut_types.js';
 import {TextAcceleratorElement} from 'chrome://shortcut-customization/js/text_accelerator.js';
-import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
 function createTextAcceleratorPart(
     text: string, type: TextAcceleratorPartType): TextAcceleratorPart {
   return {text: stringToMojoString16(text), type};
 }
 
-export function initTextAcceleratorElement(parts: TextAcceleratorPart[] = []):
-    TextAcceleratorElement {
-  const element: TextAcceleratorElement =
-      document.createElement('text-accelerator');
-  element.parts = parts;
-  document.body.appendChild(element);
-  flush();
-  return element;
-}
-
 suite('textAcceleratorTest', function() {
   let textAccelElement: TextAcceleratorElement|null = null;
 
@@ -39,6 +30,18 @@
     return getTextWrapperEl().querySelectorAll('input-key');
   }
 
+  function getAllPlainTextParts(): NodeListOf<HTMLSpanElement> {
+    return getTextWrapperEl().querySelectorAll('span');
+  }
+
+  function getAllDelimiterParts(): NodeListOf<IronIconElement> {
+    return getTextWrapperEl().querySelectorAll('#delimiter-icon');
+  }
+
+  setup(() => {
+    document.body.innerHTML = window.trustedTypes!.emptyHTML;
+  });
+
   teardown(() => {
     if (textAccelElement) {
       textAccelElement.remove();
@@ -46,42 +49,67 @@
     textAccelElement = null;
   });
 
-  test('TextAcceleratorPartsSingleModifier', () => {
+  function initTextAcceleratorElement(parts: TextAcceleratorPart[] = []):
+      Promise<void> {
+    textAccelElement = document.createElement('text-accelerator');
+    textAccelElement.parts = parts;
+    document.body.appendChild(textAccelElement);
+    return flushTasks();
+  }
+
+
+  test('TextAcceleratorPartsSingleModifier', async () => {
     const ctrlKey =
         createTextAcceleratorPart('ctrl', TextAcceleratorPartType.kModifier);
-    textAccelElement = initTextAcceleratorElement([ctrlKey]);
-    assertEquals(1, textAccelElement.parts.length);
+    await initTextAcceleratorElement([ctrlKey]);
+    assertEquals(1, getTextWrapperEl().children.length);
+    assertEquals(1, textAccelElement!.parts.length);
     const inputKey = getAllInputKeys()[0];
     assertEquals(inputKey!.key, mojoString16ToString(ctrlKey.text));
     assertEquals(inputKey!.keyState, KeyInputState.MODIFIER_SELECTED);
   });
 
-  test('TextAcceleratorPartsSingleKey', () => {
+  test('TextAcceleratorPartsSingleKey', async () => {
     const bKey = createTextAcceleratorPart('b', TextAcceleratorPartType.kKey);
-    textAccelElement = initTextAcceleratorElement([bKey]);
-    assertEquals(1, textAccelElement.parts.length);
+    await initTextAcceleratorElement([bKey]);
+    assertEquals(1, getTextWrapperEl().children.length);
+    assertEquals(1, textAccelElement!.parts.length);
     const inputKey = getAllInputKeys()[0];
     assertEquals(inputKey!.key, mojoString16ToString(bKey.text));
     assertEquals(inputKey!.keyState, KeyInputState.ALPHANUMERIC_SELECTED);
   });
 
-  test('TextAcceleratorPartsPlainText', () => {
+  test('TextAcceleratorPartsPlainText', async () => {
     const plainText = createTextAcceleratorPart(
         'Some text', TextAcceleratorPartType.kPlainText);
-    textAccelElement = initTextAcceleratorElement([plainText]);
-    assertEquals(1, textAccelElement.parts.length);
-    assertEquals(
-        getTextWrapperEl().innerText, mojoString16ToString(plainText.text));
+    await initTextAcceleratorElement([plainText]);
+    assertEquals(1, getTextWrapperEl().children.length);
+    const part = getAllPlainTextParts()[0];
+    assertEquals(1, textAccelElement!.parts.length);
+    assertEquals(part!.innerText, mojoString16ToString(plainText.text));
   });
 
-  test('TextAcceleratorPartsAll', () => {
+  test('TextAcceleratorPartsDelimiter', async () => {
+    const delimiter =
+        createTextAcceleratorPart('+', TextAcceleratorPartType.kDelimiter);
+    await initTextAcceleratorElement([delimiter]);
+    assertEquals(1, getTextWrapperEl().children.length);
+    const delimiterPart = getAllDelimiterParts()[0];
+    assertEquals(1, textAccelElement!.parts.length);
+    assertEquals(delimiterPart!.icon, 'shortcut-customization-keys:plus');
+  });
+
+  test('TextAcceleratorPartsAll', async () => {
     const ctrlKey =
         createTextAcceleratorPart('ctrl', TextAcceleratorPartType.kModifier);
     const bKey = createTextAcceleratorPart('b', TextAcceleratorPartType.kKey);
     const plainText = createTextAcceleratorPart(
         'Some text', TextAcceleratorPartType.kPlainText);
-    textAccelElement = initTextAcceleratorElement([ctrlKey, bKey, plainText]);
-    assertEquals(3, textAccelElement.parts.length);
+    const delimiter =
+        createTextAcceleratorPart('+', TextAcceleratorPartType.kDelimiter);
+    await initTextAcceleratorElement([ctrlKey, bKey, plainText, delimiter]);
+    assertEquals(4, getTextWrapperEl().children.length);
+    assertEquals(4, textAccelElement!.parts.length);
 
     const [ctrlInputKey, bInputKey] = getAllInputKeys();
     assertEquals(ctrlInputKey!.key, mojoString16ToString(ctrlKey.text));
@@ -89,7 +117,10 @@
 
     assertEquals(bInputKey!.key, mojoString16ToString(bKey.text));
     assertEquals(bInputKey!.keyState, KeyInputState.ALPHANUMERIC_SELECTED);
-    assertTrue(getTextWrapperEl().innerText.includes(
-        mojoString16ToString(plainText.text)));
+    const part = getAllPlainTextParts()[0];
+    assertEquals(part!.innerText, mojoString16ToString(plainText.text));
+
+    const delimiterPart = getAllDelimiterParts()[0];
+    assertEquals(delimiterPart!.icon, 'shortcut-customization-keys:plus');
   });
 });
diff --git a/chrome/test/data/webui/cr_components/chromeos/network/network_list_item_test.js b/chrome/test/data/webui/cr_components/chromeos/network/network_list_item_test.js
index 310bdd0..9103dc4 100644
--- a/chrome/test/data/webui/cr_components/chromeos/network/network_list_item_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/network/network_list_item_test.js
@@ -737,7 +737,7 @@
       });
 
   suite('Portal', function() {
-    function initWithPortalState(flagEnabled, portalState) {
+    function initWithPortalState(portalState) {
       const managedProperties =
           OncMojo.getDefaultManagedProperties(NetworkType.kWiFi, 'wifiguid');
       managedProperties.source = OncSource.kUser;
@@ -747,28 +747,13 @@
           OncMojo.managedPropertiesToNetworkState(managedProperties);
       networkState.portalState = portalState;
       networkState.connectionState = ConnectionStateType.kPortal;
-      listItem.isCaptivePortalUI2022Enabled_ = flagEnabled;
       listItem.item = networkState;
       flush();
     }
 
-    test('kPortal portalState flag disabled', async () => {
-      init();
-      initWithPortalState(false /* flagEnabled */, PortalState.kPortal);
-      const getNetworkStateText = () => {
-        const element = listItem.$$('#networkStateText');
-        return element ? element.textContent.trim() : '';
-      };
-      assertNotEquals(
-          getNetworkStateText(), listItem.i18n('networkListItemSignIn'));
-      assertFalse(
-          listItem.$$('#networkStateText').classList.contains('warning'));
-      assertTrue(!!listItem.$$('#networkStateText').hasAttribute('active'));
-    });
-
     test('kPortal portalState show sign in description', async () => {
       init();
-      initWithPortalState(true /* flagEnabled */, PortalState.kPortal);
+      initWithPortalState(PortalState.kPortal);
       const getNetworkStateText = () => {
         const element = listItem.$$('#networkStateText');
         return element ? element.textContent.trim() : '';
@@ -782,8 +767,7 @@
 
     test('kPortalProxyAuth portalState show sign in description', async () => {
       init();
-      initWithPortalState(
-          true /* flagEnabled */, PortalState.kProxyAuthRequired);
+      initWithPortalState(PortalState.kProxyAuthRequired);
       const getNetworkStateText = () => {
         const element = listItem.$$('#networkStateText');
         return element ? element.textContent.trim() : '';
@@ -799,8 +783,7 @@
         'kPortalSuspected portalState show limited connectivity description',
         async () => {
           init();
-          initWithPortalState(
-              true /* flagEnabled */, PortalState.kPortalSuspected);
+          initWithPortalState(PortalState.kPortalSuspected);
           const getNetworkStateText = () => {
             const element = listItem.$$('#networkStateText');
             return element ? element.textContent.trim() : '';
@@ -818,7 +801,7 @@
         'kNoInternet portalState show no connectivity description',
         async () => {
           init();
-          initWithPortalState(true /* flagEnabled */, PortalState.kNoInternet);
+          initWithPortalState(PortalState.kNoInternet);
           const getNetworkStateText = () => {
             const element = listItem.$$('#networkStateText');
             return element ? element.textContent.trim() : '';
diff --git a/chrome/test/data/webui/extensions/a11y/extensions_a11y_test.js b/chrome/test/data/webui/extensions/a11y/extensions_a11y_test.js
index 7c1d1f5..ecb546f 100644
--- a/chrome/test/data/webui/extensions/a11y/extensions_a11y_test.js
+++ b/chrome/test/data/webui/extensions/a11y/extensions_a11y_test.js
@@ -32,6 +32,13 @@
     ];
   }
 
+  /** @override */
+  setUp() {
+    const runTest = this.deferRunTest(WhenTestDone.DEFAULT);
+    const manager = document.querySelector('extensions-manager');
+    manager.whenPageInitializedForTest().then(runTest);
+  }
+
   // Default accessibility audit options. Specify in test definition to use.
   static get axeOptions() {
     return {
@@ -130,10 +137,6 @@
 CrExtensionsA11yTestWithMultipleExensions = class extends CrExtensionsA11yTest {
   /** @override */
   testGenPreamble() {
-    // (crbug.com/1397832): Flaky on mac builder.
-    GEN('#if BUILDFLAG(IS_MAC)');
-    GEN('#define DISABLED_All');
-    GEN('#endif');
     GEN('  InstallGoodExtension();');
     GEN('  InstallPackagedApp();');
     GEN('  InstallHostedApp();');
diff --git a/chrome/test/data/webui/new_tab_page/app_test.ts b/chrome/test/data/webui/new_tab_page/app_test.ts
index 0254c51..edf4116d 100644
--- a/chrome/test/data/webui/new_tab_page/app_test.ts
+++ b/chrome/test/data/webui/new_tab_page/app_test.ts
@@ -653,7 +653,7 @@
 
     test('clicking customize button hides side panel', async () => {
       // Act.
-      callbackRouterRemote.customizeChromeSidePanelVisibilityChanged(true);
+      callbackRouterRemote.setCustomizeChromeSidePanelVisibility(true);
       await callbackRouterRemote.$.flushForTesting();
       $$<HTMLElement>(app, '#customizeButton')!.click();
 
diff --git a/chrome/test/data/webui/settings/chromeos/internet_detail_page_tests.js b/chrome/test/data/webui/settings/chromeos/internet_detail_page_tests.js
index ac5a27a8..46c82499 100644
--- a/chrome/test/data/webui/settings/chromeos/internet_detail_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/internet_detail_page_tests.js
@@ -240,7 +240,6 @@
 
       mojoApi_.setManagedPropertiesForTest(wifiNetwork);
 
-      internetDetailPage.isCaptivePortalUI2022Enabled_ = true;
       internetDetailPage.init('wifi_user_guid', 'WiFi', 'wifi_user');
       return flushAsync().then(() => {
         const networkStateText =
@@ -268,7 +267,6 @@
 
       mojoApi_.setManagedPropertiesForTest(wifiNetwork);
 
-      internetDetailPage.isCaptivePortalUI2022Enabled_ = true;
       internetDetailPage.init('wifi_user_guid', 'WiFi', 'wifi_user');
       return flushAsync().then(() => {
         const networkStateText =
@@ -296,7 +294,6 @@
 
       mojoApi_.setManagedPropertiesForTest(wifiNetwork);
 
-      internetDetailPage.isCaptivePortalUI2022Enabled_ = true;
       internetDetailPage.init('wifi_user_guid', 'WiFi', 'wifi_user');
       return flushAsync().then(() => {
         const networkStateText =
@@ -324,7 +321,6 @@
 
       mojoApi_.setManagedPropertiesForTest(wifiNetwork);
 
-      internetDetailPage.isCaptivePortalUI2022Enabled_ = true;
       internetDetailPage.init('wifi_user_guid', 'WiFi', 'wifi_user');
       return flushAsync().then(() => {
         const networkStateText =
@@ -340,37 +336,6 @@
       });
     });
 
-    test(
-        'WiFi in a portal portalState with the feature flag disabled',
-        function() {
-          init();
-          mojoApi_.resetForTest();
-          mojoApi_.setNetworkTypeEnabledState(NetworkType.kWiFi, true);
-          const wifiNetwork =
-              getManagedProperties(NetworkType.kWiFi, 'wifi_user');
-          wifiNetwork.source = OncSource.kUser;
-          wifiNetwork.connectable = true;
-          wifiNetwork.connectionState = ConnectionStateType.kPortal;
-          wifiNetwork.portalState = PortalState.kProxyAuthRequired;
-
-          mojoApi_.setManagedPropertiesForTest(wifiNetwork);
-
-          internetDetailPage.isCaptivePortalUI2022Enabled_ = false;
-          internetDetailPage.init('wifi_user_guid', 'WiFi', 'wifi_user');
-          return flushAsync().then(() => {
-            const networkStateText =
-                internetDetailPage.shadowRoot.querySelector(`#networkState`);
-            assertTrue(networkStateText.hasAttribute('connected'));
-            assertEquals(
-                networkStateText.textContent.trim(),
-                internetDetailPage.i18n('OncConnected'));
-            const signinButton =
-                internetDetailPage.shadowRoot.querySelector(`#signinButton`);
-            // Button does not exist because feature flag is disabled.
-            assertTrue(!signinButton);
-          });
-        });
-
     test('Hidden toggle enabled', function() {
       init();
       mojoApi_.resetForTest();
diff --git a/chrome/test/data/webui/settings/chromeos/network_summary_item_test.js b/chrome/test/data/webui/settings/chromeos/network_summary_item_test.js
index e99fc70..59f41a4 100644
--- a/chrome/test/data/webui/settings/chromeos/network_summary_item_test.js
+++ b/chrome/test/data/webui/settings/chromeos/network_summary_item_test.js
@@ -257,12 +257,11 @@
     const testName = 'test_name';
     const testGuid = '0001';
 
-    function initWithPortalState(flagEnabled, portalState) {
+    function initWithPortalState(portalState) {
       browserProxy = new TestInternetPageBrowserProxy();
       netSummaryItem.browserProxy_ = browserProxy;
 
       netSummaryItem.setProperties({
-        isCaptivePortalUI2022Enabled_: flagEnabled,
         deviceState: {
           deviceState: DeviceStateType.kEnabled,
           inhibitReason: InhibitReason.kNotInhibited,
@@ -293,7 +292,7 @@
     test(
         'kPortal shows signin text and opens portal signin on click',
         function() {
-          initWithPortalState(true /* flagEnabled */, PortalState.kPortal);
+          initWithPortalState(PortalState.kPortal);
           assertTrue(netSummaryItem.shadowRoot.querySelector('#networkState')
                          .classList.contains('warning-message'));
           assertFalse(netSummaryItem.shadowRoot.querySelector('#networkState')
@@ -321,7 +320,7 @@
           const showNetworksFiredPromise =
               eventToPromise('show-networks', netSummaryItem);
 
-          initWithPortalState(true /* flagEnabled */, PortalState.kPortal);
+          initWithPortalState(PortalState.kPortal);
           assertTrue(netSummaryItem.shadowRoot.querySelector('#networkState')
                          .classList.contains('warning-message'));
           assertFalse(netSummaryItem.shadowRoot.querySelector('#networkState')
@@ -344,8 +343,7 @@
     test(
         'kProxyAuthRequired shows signin text and opens portal signin on click',
         function() {
-          initWithPortalState(
-              true /* flagEnabled */, PortalState.kProxyAuthRequired);
+          initWithPortalState(PortalState.kProxyAuthRequired);
           assertTrue(netSummaryItem.shadowRoot.querySelector('#networkState')
                          .classList.contains('warning-message'));
           assertFalse(netSummaryItem.shadowRoot.querySelector('#networkState')
@@ -366,45 +364,5 @@
                 assertEquals(testGuid, guid);
               });
         });
-
-    test('kPortal does not show sign in when flag is disabled', function() {
-      initWithPortalState(false /* flagEnabled */, PortalState.kPortal);
-      assertFalse(netSummaryItem.shadowRoot.querySelector('#networkState')
-                      .classList.contains('warning-message'));
-      assertTrue(netSummaryItem.shadowRoot.querySelector('#networkState')
-                     .classList.contains('network-state'));
-      assertNotEquals(
-          netSummaryItem.getNetworkStateText_(),
-          netSummaryItem.i18n('networkListItemSignIn'));
-      assertNotEquals(netSummaryItem.getTitleText_(), testName);
-
-      // Verify clicking network summary item does not open portal signin
-      const networkSummaryItemRow =
-          netSummaryItem.shadowRoot.querySelector('#networkSummaryItemRow');
-      assertTrue(!!networkSummaryItemRow);
-      networkSummaryItemRow.click();
-      assertEquals(browserProxy.getCallCount('showPortalSignin'), 0);
-    });
-
-    test(
-        'kProxyAuthRequired does not show sign in when flag is disabled',
-        function() {
-          initWithPortalState(
-              false /* flagEnabled */, PortalState.kProxyAuthRequired);
-          assertFalse(netSummaryItem.shadowRoot.querySelector('#networkState')
-                          .classList.contains('warning-message'));
-          assertTrue(netSummaryItem.shadowRoot.querySelector('#networkState')
-                         .classList.contains('network-state'));
-          assertNotEquals(
-              netSummaryItem.getNetworkStateText_(),
-              netSummaryItem.i18n('networkListItemSignIn'));
-          assertNotEquals(netSummaryItem.getTitleText_(), testName);
-          // Verify clicking network summary item does not open portal signin
-          const networkSummaryItemRow =
-              netSummaryItem.shadowRoot.querySelector('#networkSummaryItemRow');
-          assertTrue(!!networkSummaryItemRow);
-          networkSummaryItemRow.click();
-          assertEquals(browserProxy.getCallCount('showPortalSignin'), 0);
-        });
   });
 });
diff --git a/chromeos/ash/services/nearby/public/cpp/fake_nearby_process_manager.cc b/chromeos/ash/services/nearby/public/cpp/fake_nearby_process_manager.cc
index be203fb..6a2eed9 100644
--- a/chromeos/ash/services/nearby/public/cpp/fake_nearby_process_manager.cc
+++ b/chromeos/ash/services/nearby/public/cpp/fake_nearby_process_manager.cc
@@ -15,8 +15,7 @@
 
 FakeNearbyProcessManager::FakeNearbyProcessReference::
     FakeNearbyProcessReference(
-        const mojo::SharedRemote<
-            location::nearby::connections::mojom::NearbyConnections>&
+        const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
             connections,
         const mojo::SharedRemote<sharing::mojom::NearbySharingDecoder>& decoder,
         base::OnceClosure destructor_callback)
@@ -29,8 +28,7 @@
   std::move(destructor_callback_).Run();
 }
 
-const mojo::SharedRemote<
-    location::nearby::connections::mojom::NearbyConnections>&
+const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
 FakeNearbyProcessManager::FakeNearbyProcessReference::GetNearbyConnections()
     const {
   return connections_;
diff --git a/chromeos/ash/services/nearby/public/cpp/fake_nearby_process_manager.h b/chromeos/ash/services/nearby/public/cpp/fake_nearby_process_manager.h
index 9775519..396db86 100644
--- a/chromeos/ash/services/nearby/public/cpp/fake_nearby_process_manager.h
+++ b/chromeos/ash/services/nearby/public/cpp/fake_nearby_process_manager.h
@@ -44,8 +44,7 @@
       : public NearbyProcessManager::NearbyProcessReference {
    public:
     FakeNearbyProcessReference(
-        const mojo::SharedRemote<
-            location::nearby::connections::mojom::NearbyConnections>&
+        const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
             connections,
         const mojo::SharedRemote<sharing::mojom::NearbySharingDecoder>& decoder,
         base::OnceClosure destructor_callback);
@@ -53,13 +52,12 @@
 
    private:
     // NearbyProcessManager::NearbyProcessReference:
-    const mojo::SharedRemote<
-        location::nearby::connections::mojom::NearbyConnections>&
+    const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>&
     GetNearbyConnections() const override;
     const mojo::SharedRemote<sharing::mojom::NearbySharingDecoder>&
     GetNearbySharingDecoder() const override;
 
-    mojo::SharedRemote<location::nearby::connections::mojom::NearbyConnections>
+    mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>
         connections_;
     mojo::SharedRemote<sharing::mojom::NearbySharingDecoder> decoder_;
     base::OnceClosure destructor_callback_;
@@ -80,7 +78,7 @@
   std::unique_ptr<MockNearbySharingDecoder> active_decoder_;
 
   // Unbound if no outstanding references exist.
-  mojo::SharedRemote<location::nearby::connections::mojom::NearbyConnections>
+  mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>
       connections_remote_;
   mojo::SharedRemote<sharing::mojom::NearbySharingDecoder> decoder_remote_;
 
diff --git a/chromeos/ash/services/nearby/public/cpp/mock_nearby_connections.h b/chromeos/ash/services/nearby/public/cpp/mock_nearby_connections.h
index d54c9ca..3e0833717 100644
--- a/chromeos/ash/services/nearby/public/cpp/mock_nearby_connections.h
+++ b/chromeos/ash/services/nearby/public/cpp/mock_nearby_connections.h
@@ -11,20 +11,16 @@
 #include "mojo/public/cpp/bindings/shared_remote.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
-using NearbyConnectionsMojom =
-    location::nearby::connections::mojom::NearbyConnections;
-using AdvertisingOptionsPtr =
-    location::nearby::connections::mojom::AdvertisingOptionsPtr;
+using NearbyConnectionsMojom = ::nearby::connections::mojom::NearbyConnections;
+using AdvertisingOptionsPtr = ::nearby::connections::mojom::AdvertisingOptionsPtr;
 using ConnectionLifecycleListener =
-    location::nearby::connections::mojom::ConnectionLifecycleListener;
-using ConnectionOptionsPtr =
-    location::nearby::connections::mojom::ConnectionOptionsPtr;
-using DiscoveryOptionsPtr =
-    location::nearby::connections::mojom::DiscoveryOptionsPtr;
+    ::nearby::connections::mojom::ConnectionLifecycleListener;
+using ConnectionOptionsPtr = ::nearby::connections::mojom::ConnectionOptionsPtr;
+using DiscoveryOptionsPtr = ::nearby::connections::mojom::DiscoveryOptionsPtr;
 using EndpointDiscoveryListener =
-    location::nearby::connections::mojom::EndpointDiscoveryListener;
-using PayloadListener = location::nearby::connections::mojom::PayloadListener;
-using PayloadPtr = location::nearby::connections::mojom::PayloadPtr;
+    ::nearby::connections::mojom::EndpointDiscoveryListener;
+using PayloadListener = ::nearby::connections::mojom::PayloadListener;
+using PayloadPtr = ::nearby::connections::mojom::PayloadPtr;
 
 namespace ash {
 namespace nearby {
diff --git a/chromeos/ash/services/nearby/public/cpp/mock_nearby_process_manager.h b/chromeos/ash/services/nearby/public/cpp/mock_nearby_process_manager.h
index 129ed918..6e62601 100644
--- a/chromeos/ash/services/nearby/public/cpp/mock_nearby_process_manager.h
+++ b/chromeos/ash/services/nearby/public/cpp/mock_nearby_process_manager.h
@@ -25,7 +25,7 @@
     ~MockNearbyProcessReference() override;
 
     MOCK_METHOD(const mojo::SharedRemote<
-                    location::nearby::connections::mojom::NearbyConnections>&,
+                    ::nearby::connections::mojom::NearbyConnections>&,
                 GetNearbyConnections,
                 (),
                 (const, override));
diff --git a/chromeos/ash/services/nearby/public/cpp/nearby_process_manager.h b/chromeos/ash/services/nearby/public/cpp/nearby_process_manager.h
index 6a1bff22..c83cf2c 100644
--- a/chromeos/ash/services/nearby/public/cpp/nearby_process_manager.h
+++ b/chromeos/ash/services/nearby/public/cpp/nearby_process_manager.h
@@ -23,7 +23,7 @@
    public:
     virtual ~NearbyProcessReference() = default;
     virtual const mojo::SharedRemote<
-        location::nearby::connections::mojom::NearbyConnections>&
+        ::nearby::connections::mojom::NearbyConnections>&
     GetNearbyConnections() const = 0;
     virtual const mojo::SharedRemote<sharing::mojom::NearbySharingDecoder>&
     GetNearbySharingDecoder() const = 0;
diff --git a/chromeos/ash/services/nearby/public/mojom/BUILD.gn b/chromeos/ash/services/nearby/public/mojom/BUILD.gn
index 17ad363..ebd4500 100644
--- a/chromeos/ash/services/nearby/public/mojom/BUILD.gn
+++ b/chromeos/ash/services/nearby/public/mojom/BUILD.gn
@@ -41,8 +41,8 @@
     {
       types = [
         {
-          mojom = "location.nearby.connections.mojom.LogSeverity"
-          cpp = "location::nearby::api::LogMessage::Severity"
+          mojom = "nearby.connections.mojom.LogSeverity"
+          cpp = "nearby::api::LogMessage::Severity"
         },
       ]
       traits_headers = [ "nearby_connections_mojom_traits.h" ]
diff --git a/chromeos/ash/services/nearby/public/mojom/nearby_connections.mojom b/chromeos/ash/services/nearby/public/mojom/nearby_connections.mojom
index 0243f7b..ae917f2 100644
--- a/chromeos/ash/services/nearby/public/mojom/nearby_connections.mojom
+++ b/chromeos/ash/services/nearby/public/mojom/nearby_connections.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.
 
-module location.nearby.connections.mojom;
+module nearby.connections.mojom;
 
 import "chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom";
 import "mojo/public/mojom/base/file.mojom";
diff --git a/chromeos/ash/services/nearby/public/mojom/nearby_connections_mojom_traits.cc b/chromeos/ash/services/nearby/public/mojom/nearby_connections_mojom_traits.cc
index af5230fe..7f604ee8 100644
--- a/chromeos/ash/services/nearby/public/mojom/nearby_connections_mojom_traits.cc
+++ b/chromeos/ash/services/nearby/public/mojom/nearby_connections_mojom_traits.cc
@@ -6,46 +6,46 @@
 
 namespace mojo {
 
-location::nearby::connections::mojom::LogSeverity
-EnumTraits<location::nearby::connections::mojom::LogSeverity,
-           location::nearby::api::LogMessage::Severity>::
-    ToMojom(location::nearby::api::LogMessage::Severity input) {
+nearby::connections::mojom::LogSeverity
+EnumTraits<nearby::connections::mojom::LogSeverity,
+           nearby::api::LogMessage::Severity>::
+    ToMojom(nearby::api::LogMessage::Severity input) {
   switch (input) {
-    case location::nearby::api::LogMessage::Severity::kVerbose:
-      return location::nearby::connections::mojom::LogSeverity::kVerbose;
-    case location::nearby::api::LogMessage::Severity::kInfo:
-      return location::nearby::connections::mojom::LogSeverity::kInfo;
-    case location::nearby::api::LogMessage::Severity::kWarning:
-      return location::nearby::connections::mojom::LogSeverity::kWarning;
-    case location::nearby::api::LogMessage::Severity::kError:
-      return location::nearby::connections::mojom::LogSeverity::kError;
-    case location::nearby::api::LogMessage::Severity::kFatal:
-      return location::nearby::connections::mojom::LogSeverity::kFatal;
+    case nearby::api::LogMessage::Severity::kVerbose:
+      return nearby::connections::mojom::LogSeverity::kVerbose;
+    case nearby::api::LogMessage::Severity::kInfo:
+      return nearby::connections::mojom::LogSeverity::kInfo;
+    case nearby::api::LogMessage::Severity::kWarning:
+      return nearby::connections::mojom::LogSeverity::kWarning;
+    case nearby::api::LogMessage::Severity::kError:
+      return nearby::connections::mojom::LogSeverity::kError;
+    case nearby::api::LogMessage::Severity::kFatal:
+      return nearby::connections::mojom::LogSeverity::kFatal;
   }
 
   NOTREACHED();
-  return location::nearby::connections::mojom::LogSeverity::kInfo;
+  return nearby::connections::mojom::LogSeverity::kInfo;
 }
 
-bool EnumTraits<location::nearby::connections::mojom::LogSeverity,
-                location::nearby::api::LogMessage::Severity>::
-    FromMojom(location::nearby::connections::mojom::LogSeverity input,
-              location::nearby::api::LogMessage::Severity* out) {
+bool EnumTraits<nearby::connections::mojom::LogSeverity,
+                nearby::api::LogMessage::Severity>::
+    FromMojom(nearby::connections::mojom::LogSeverity input,
+              nearby::api::LogMessage::Severity* out) {
   switch (input) {
-    case location::nearby::connections::mojom::LogSeverity::kVerbose:
-      *out = location::nearby::api::LogMessage::Severity::kVerbose;
+    case nearby::connections::mojom::LogSeverity::kVerbose:
+      *out = nearby::api::LogMessage::Severity::kVerbose;
       return true;
-    case location::nearby::connections::mojom::LogSeverity::kInfo:
-      *out = location::nearby::api::LogMessage::Severity::kInfo;
+    case nearby::connections::mojom::LogSeverity::kInfo:
+      *out = nearby::api::LogMessage::Severity::kInfo;
       return true;
-    case location::nearby::connections::mojom::LogSeverity::kWarning:
-      *out = location::nearby::api::LogMessage::Severity::kWarning;
+    case nearby::connections::mojom::LogSeverity::kWarning:
+      *out = nearby::api::LogMessage::Severity::kWarning;
       return true;
-    case location::nearby::connections::mojom::LogSeverity::kError:
-      *out = location::nearby::api::LogMessage::Severity::kError;
+    case nearby::connections::mojom::LogSeverity::kError:
+      *out = nearby::api::LogMessage::Severity::kError;
       return true;
-    case location::nearby::connections::mojom::LogSeverity::kFatal:
-      *out = location::nearby::api::LogMessage::Severity::kFatal;
+    case nearby::connections::mojom::LogSeverity::kFatal:
+      *out = nearby::api::LogMessage::Severity::kFatal;
       return true;
   }
 
diff --git a/chromeos/ash/services/nearby/public/mojom/nearby_connections_mojom_traits.h b/chromeos/ash/services/nearby/public/mojom/nearby_connections_mojom_traits.h
index 83034f9..a1d5c93 100644
--- a/chromeos/ash/services/nearby/public/mojom/nearby_connections_mojom_traits.h
+++ b/chromeos/ash/services/nearby/public/mojom/nearby_connections_mojom_traits.h
@@ -11,13 +11,13 @@
 namespace mojo {
 
 template <>
-class EnumTraits<location::nearby::connections::mojom::LogSeverity,
-                 location::nearby::api::LogMessage::Severity> {
+class EnumTraits<nearby::connections::mojom::LogSeverity,
+                 nearby::api::LogMessage::Severity> {
  public:
-  static location::nearby::connections::mojom::LogSeverity ToMojom(
-      location::nearby::api::LogMessage::Severity input);
-  static bool FromMojom(location::nearby::connections::mojom::LogSeverity input,
-                        location::nearby::api::LogMessage::Severity* out);
+  static nearby::connections::mojom::LogSeverity ToMojom(
+      nearby::api::LogMessage::Severity input);
+  static bool FromMojom(nearby::connections::mojom::LogSeverity input,
+                        nearby::api::LogMessage::Severity* out);
 };
 
 }  // namespace mojo
diff --git a/chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom b/chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom
index b17c2811..76aced5 100644
--- a/chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom
+++ b/chromeos/ash/services/nearby/public/mojom/nearby_connections_types.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.
 
-module location.nearby.connections.mojom;
+module nearby.connections.mojom;
 
 import "device/bluetooth/public/mojom/uuid.mojom";
 import "mojo/public/mojom/base/file.mojom";
@@ -278,7 +278,7 @@
 // Log severity levels. This is passed as a member of
 // NearbyConnectionsDependencies to set the minimum log level in the Nearby
 // Connections library. Entries should be kept in sync with the values in
-// location::nearby::api::LogMessage::Severity.
+// nearby::api::LogMessage::Severity.
 enum LogSeverity {
   kVerbose = -1,
   kInfo = 0,
diff --git a/chromeos/ash/services/nearby/public/mojom/sharing.mojom b/chromeos/ash/services/nearby/public/mojom/sharing.mojom
index 382a73a..29623c2 100644
--- a/chromeos/ash/services/nearby/public/mojom/sharing.mojom
+++ b/chromeos/ash/services/nearby/public/mojom/sharing.mojom
@@ -38,8 +38,8 @@
   // Null if the WifiLan feature flag is disabled.
   WifiLanDependencies? wifilan_dependencies;
 
-  location.nearby.connections.mojom.LogSeverity min_log_severity =
-      location.nearby.connections.mojom.LogSeverity.kInfo;
+  nearby.connections.mojom.LogSeverity min_log_severity =
+      nearby.connections.mojom.LogSeverity.kInfo;
 };
 
 // Interface for sharing related services. Lives in a sandboxed utility process
@@ -54,7 +54,7 @@
   Connect(
       NearbyDependencies deps,
       pending_receiver<
-          location.nearby.connections.mojom.NearbyConnections>
+          nearby.connections.mojom.NearbyConnections>
               nearby_connections,
       pending_receiver<sharing.mojom.NearbySharingDecoder>
           decoder);
diff --git a/chromeos/crosapi/mojom/clipboard_history.mojom b/chromeos/crosapi/mojom/clipboard_history.mojom
index 6bde198..8d24d7b 100644
--- a/chromeos/crosapi/mojom/clipboard_history.mojom
+++ b/chromeos/crosapi/mojom/clipboard_history.mojom
@@ -22,7 +22,9 @@
   // Shown by the virtual keyboard.
   kVirtualKeyboard,
   // Used as a default value in case of version skew.
-  [Default] kUnknown
+  [Default] kUnknown,
+  // Shown by a toast.
+  [MinVersion=1] kToast,
 };
 
 // This interface is implemented by Ash-Chrome.
diff --git a/codelabs/threading_and_scheduling/README.md b/codelabs/threading_and_scheduling/README.md
index 82f6231e..b61a547 100644
--- a/codelabs/threading_and_scheduling/README.md
+++ b/codelabs/threading_and_scheduling/README.md
@@ -76,7 +76,7 @@
 which represents a new physical thread. Then we explicitly post tasks back and
 forth between the main and secondary thread, via a cross-thread `TaskRunner`.
 
-[1]: https://chromium.googlesource.com/chromium/src/+/refs/heads/main/codelabs/cpp101/codelab.md#part-3_threads-and-task-runners
+[1]: https://chromium.googlesource.com/chromium/src/+/refs/heads/main/codelabs/cpp101/README.md#part-3_threads-and-task-runners
 [2]: https://source.chromium.org/chromium/chromium/src/+/main:base/task/sequence_manager/sequence_manager.h;l=122-125;drc=c70927109b0861ba4642416cb4689b4bf9d25ad0
 [3]: https://source.chromium.org/chromium/chromium/src/+/main:base/task/sequence_manager/task_queue.cc;l=246;drc=566a5d280c3f78e073c435a5218021ce15d1f004
 [4]: https://source.chromium.org/chromium/chromium/src/+/main:base/task/sequence_manager/task_queue_impl.cc;l=1132;drc=74e2db96056dd0265b7e527a58b50036c07d7031
diff --git a/components/autofill/content/browser/form_forest_unittest.cc b/components/autofill/content/browser/form_forest_unittest.cc
index 8babee6..590736be 100644
--- a/components/autofill/content/browser/form_forest_unittest.cc
+++ b/components/autofill/content/browser/form_forest_unittest.cc
@@ -1652,7 +1652,7 @@
   auto x = std::make_unique<FrameData>(test::MakeLocalFrameToken());
   auto xx = std::make_unique<FrameData>(test::MakeLocalFrameToken());
   auto y = std::make_unique<FrameData>(
-      LocalFrameToken(base::UnguessableToken::Deserialize(
+      LocalFrameToken(base::UnguessableToken::CreateForTesting(
           x->frame_token->GetHighForSerialization() + 1,
           x->frame_token->GetLowForSerialization() + 1)));
   ASSERT_TRUE(x->frame_token < y->frame_token);
diff --git a/components/autofill/core/browser/autofill_suggestion_generator.cc b/components/autofill/core/browser/autofill_suggestion_generator.cc
index a155a61..04ff8fd2 100644
--- a/components/autofill/core/browser/autofill_suggestion_generator.cc
+++ b/components/autofill/core/browser/autofill_suggestion_generator.cc
@@ -627,6 +627,7 @@
         Suggestion::Text(credit_card.ObfuscatedNumberWithVisibleLastFourDigits(
             GetObfuscationLength()))};
   }
+
   // E.g. "Product Description/Nickname/Network  ••••1234, expires on 01/25".
   return {Suggestion::Text(
       credit_card.CardIdentifierStringAndDescriptiveExpiration(app_locale))};
@@ -662,43 +663,37 @@
     // displayed on a single row. The minor_text and the labels are
     // concatenated, so we have: String 1 = main_text, String 2 = minor_text +
     // labels.
-    // For the card number field, suggestion = virtual card label + card name +
-    // last 4 digits.
-    if (type.GetStorableType() == CREDIT_CARD_NUMBER) {
-      if (ShouldSplitCardNameAndLastFourDigits()) {
-        // Before: main_text = card name, minor_text = last 4 digits, labels =
-        // expiration date.
-        // We add the virtual card label as a prefix to the main_text.
-        // After: main_text = virtual card label + card name, minor_text = last
-        // 4 digits, labels = expiration date.
-        suggestion.main_text.value = base::StrCat(
-            {VIRTUAL_CARD_LABEL, u"  ", suggestion.main_text.value});
-      } else {
-        // Before: main_text = card name + last 4 digits, minor_text = null,
-        // labels = expiration date.
-        // The main_text is assigned to the minor_text, and the virtual card
-        // label is shown as the main_text.
-        // After: main_text = virtual card label, minor_text = card name + last
-        // 4 digits, minor_text = null, labels = expiration date.
-        suggestion.minor_text.value = suggestion.main_text.value;
-        suggestion.main_text.value = VIRTUAL_CARD_LABEL;
-      }
-      // The expiration date is not shown, so it is removed.
-      suggestion.labels = {};
+    // There is a limit on the size of the keyboard accessory chips. When the
+    // suggestion content exceeds this limit, the card name or the cardholder
+    // name can be truncated, the last 4 digits should never be truncated.
+    // Contents in the main_text are automatically truncated from the right end
+    // on the Android side when the size limit is exceeded, so the card name and
+    // the cardholder name is appended to the main_text.
+    // Here we modify the `Suggestion` members to make it suitable for showing
+    // on the keyboard accessory.
+    // Card number field:
+    // Before: main_text = card name, minor_text = last 4 digits, labels =
+    // expiration date.
+    // After: main_text = virtual card label + card name, minor_text = last 4
+    // digits, labels = null.
+    // Cardholder name field:
+    // Before: main_text = cardholder name, minor_text = null, labels = last 4
+    // digits.
+    // After: main_text = virtual card label + cardholder name, minor_text =
+    // null, labels = last 4 digits.
+    if (ShouldSplitCardNameAndLastFourDigits()) {
+      suggestion.main_text.value =
+          base::StrCat({VIRTUAL_CARD_LABEL, u"  ", suggestion.main_text.value});
     } else {
-      // For the cardholder name field, suggestion = virtual card label +
-      // cardholder name + last 4 digits.
-      // Before: main_text = cardholder name, minor_text = null, labels = last 4
-      // digits.
-      // The main_text is assigned to the minor_text, and the virtual card label
-      // is shown as the main_text.
-      // After: main_text = virtual card label, minor_text = cardholder name,
-      // labels = last 4 digits.
       suggestion.minor_text.value = suggestion.main_text.value;
       suggestion.main_text.value = VIRTUAL_CARD_LABEL;
     }
-    // Desktop/Android dropdown.
-  } else {
+    if (type.GetStorableType() == CREDIT_CARD_NUMBER) {
+      // The expiration date is not shown for the card number field, so it is
+      // removed.
+      suggestion.labels = {};
+    }
+  } else {  // Desktop/Android dropdown.
     if (type.GetStorableType() == CREDIT_CARD_NUMBER) {
       // If the focused field is a credit card number field, reset all labels
       // and populate only the virtual card text.
diff --git a/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc b/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc
index dadd50f0..31459b0 100644
--- a/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc
+++ b/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc
@@ -795,11 +795,10 @@
 
   if (keyboard_accessory_enabled()) {
     // For the keyboard accessory, the "Virtual card" label is added as a prefix
-    // to the cardholder name, and the label is added as the suffix.
+    // to the cardholder name.
     EXPECT_EQ(virtual_card_name_field_suggestion.main_text.value,
-              u"Virtual card");
-    EXPECT_EQ(virtual_card_name_field_suggestion.minor_text.value,
-              u"Elvis Presley");
+              u"Virtual card  Elvis Presley");
+    EXPECT_EQ(virtual_card_name_field_suggestion.minor_text.value, u"");
   } else {
     // On other platforms, the cardholder name is shown on the first line.
     EXPECT_EQ(virtual_card_name_field_suggestion.main_text.value,
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc
index d071c16..9a42e84 100644
--- a/components/autofill/core/browser/autofill_test_utils.cc
+++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -103,7 +103,7 @@
 }
 
 LocalFrameToken AutofillEnvironment::NextLocalFrameToken() {
-  return LocalFrameToken(base::UnguessableToken::Deserialize(
+  return LocalFrameToken(base::UnguessableToken::CreateForTesting(
       ++local_frame_token_counter_high_, ++local_frame_token_counter_low_));
 }
 
@@ -120,7 +120,8 @@
     return LocalFrameToken(
         AutofillEnvironment::GetCurrent().NextLocalFrameToken());
   } else {
-    return LocalFrameToken(base::UnguessableToken::Deserialize(98765, 43210));
+    return LocalFrameToken(
+        base::UnguessableToken::CreateForTesting(98765, 43210));
   }
 }
 
diff --git a/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java b/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java
index cc01ede9..30a6057a 100644
--- a/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java
+++ b/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java
@@ -298,6 +298,14 @@
         return true;
     }
 
+    @Override
+    public boolean onHoverEvent(MotionEvent event) {
+        // https://crbug.com/1297267 Consume hover events to prevent talkback from reading items
+        // behind the bottom sheet, in particular when the client has its own scrim lifecycle.
+        super.onHoverEvent(event);
+        return true;
+    }
+
     /**
      * Adds layout change listeners to the views that the bottom sheet depends on. Namely the
      * heights of the root view and control container are important as they are used in many of the
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/BackPressHandler.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/BackPressHandler.java
index 7162127..ac77c25 100644
--- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/BackPressHandler.java
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/BackPressHandler.java
@@ -24,25 +24,24 @@
     // - tools/metrics/histograms/enums.xml: <enum name="BackPressConsumer">
     // - chrome/browser/back_press/android/.../BackPressManager.java: sMetricsMap
     @IntDef({Type.TEXT_BUBBLE, Type.VR_DELEGATE, Type.AR_DELEGATE, Type.SCENE_OVERLAY,
-            Type.START_SURFACE_MEDIATOR, Type.SELECTION_POPUP, Type.MANUAL_FILLING,
-            Type.TAB_MODAL_HANDLER, Type.FULLSCREEN, Type.TAB_SWITCHER_TO_BROWSING,
-            Type.CLOSE_WATCHER, Type.FIND_TOOLBAR, Type.LOCATION_BAR, Type.TAB_HISTORY,
-            Type.TAB_RETURN_TO_CHROME_START_SURFACE, Type.BOTTOM_SHEET, Type.SHOW_READING_LIST,
-            Type.MINIMIZE_APP_AND_CLOSE_TAB})
+            Type.START_SURFACE, Type.SELECTION_POPUP, Type.MANUAL_FILLING, Type.TAB_MODAL_HANDLER,
+            Type.FULLSCREEN, Type.TAB_SWITCHER, Type.CLOSE_WATCHER, Type.FIND_TOOLBAR,
+            Type.LOCATION_BAR, Type.TAB_HISTORY, Type.TAB_RETURN_TO_CHROME_START_SURFACE,
+            Type.BOTTOM_SHEET, Type.SHOW_READING_LIST, Type.MINIMIZE_APP_AND_CLOSE_TAB})
     @Retention(RetentionPolicy.SOURCE)
     @interface Type {
         int TEXT_BUBBLE = 0;
         int VR_DELEGATE = 1;
         int AR_DELEGATE = 2;
         int SCENE_OVERLAY = 3;
-        int START_SURFACE_MEDIATOR = 4;
+        int START_SURFACE = 4;
         int SELECTION_POPUP = 5;
         int MANUAL_FILLING = 6;
         int FULLSCREEN = 7;
         int BOTTOM_SHEET = 8;
         int LOCATION_BAR = 9;
         int TAB_MODAL_HANDLER = 10;
-        int TAB_SWITCHER_TO_BROWSING = 11; // Removed.
+        int TAB_SWITCHER = 11;
         int CLOSE_WATCHER = 12;
         int FIND_TOOLBAR = 13;
         int TAB_HISTORY = 14;
diff --git a/components/cast_streaming/browser/BUILD.gn b/components/cast_streaming/browser/BUILD.gn
index ecada3ca..2d8f10d 100644
--- a/components/cast_streaming/browser/BUILD.gn
+++ b/components/cast_streaming/browser/BUILD.gn
@@ -101,6 +101,7 @@
       ":core",
       ":network_context",
       "//components/cast/message_port",
+      "//components/cast_streaming/public",
       "//components/cast_streaming/public:config_conversions",
       "//components/openscreen_platform",
       "//mojo/public/cpp/bindings",
diff --git a/components/cast_streaming/browser/public/receiver_session.h b/components/cast_streaming/browser/public/receiver_session.h
index 8e8c6e4..02ccddb 100644
--- a/components/cast_streaming/browser/public/receiver_session.h
+++ b/components/cast_streaming/browser/public/receiver_session.h
@@ -88,17 +88,15 @@
 
   // Schedules a call to begin streaming, following initial internal
   // initialization of the component. Following this initialization, audio
-  // and/or video frames will be sent over a Mojo channel.
-  // NOTE: Depending on the media::Renderer currently being used for media
-  // playback, additional steps may be required to begin playback. If the
-  // |PlaybackCommandForwardingRenderer| is being used, the below overload is
-  // recommended instead.
+  // and/or video frames will be sent over a Mojo channel. May only be called
+  // when remoting is NOT enabled.
   virtual void StartStreamingAsync(
       mojo::AssociatedRemote<mojom::DemuxerConnector> demuxer_connector) = 0;
 
   // As above, but also sets the |renderer_controller| to be used to control a
   // renderer-process |PlaybackCommandForwardingRenderer|. This control may then
   // be done through the RenderControls returned by GetRendererControls() below.
+  // May only be called when Remoting IS enabled.
   virtual void StartStreamingAsync(
       mojo::AssociatedRemote<mojom::DemuxerConnector> demuxer_connector,
       mojo::AssociatedRemote<mojom::RendererController>
diff --git a/components/cast_streaming/browser/receiver_session_impl.cc b/components/cast_streaming/browser/receiver_session_impl.cc
index dc63a9f..c31db31 100644
--- a/components/cast_streaming/browser/receiver_session_impl.cc
+++ b/components/cast_streaming/browser/receiver_session_impl.cc
@@ -7,6 +7,7 @@
 #include "base/task/sequenced_task_runner.h"
 #include "components/cast_streaming/browser/public/network_context_getter.h"
 #include "components/cast_streaming/browser/receiver_config_conversions.h"
+#include "components/cast_streaming/public/features.h"
 #include "media/base/audio_decoder_config.h"
 #include "media/base/video_decoder_config.h"
 
@@ -48,6 +49,26 @@
 
 void ReceiverSessionImpl::StartStreamingAsync(
     mojo::AssociatedRemote<mojom::DemuxerConnector> demuxer_connector) {
+  DCHECK(!IsCastRemotingEnabled());
+  StartStreamingAsyncInternal(std::move(demuxer_connector));
+}
+
+void ReceiverSessionImpl::StartStreamingAsync(
+    mojo::AssociatedRemote<mojom::DemuxerConnector> demuxer_connector,
+    mojo::AssociatedRemote<mojom::RendererController> renderer_controller) {
+  DCHECK(IsCastRemotingEnabled());
+  DCHECK(!renderer_control_config_);
+  external_renderer_controls_ =
+      std::make_unique<RendererControllerImpl>(base::BindOnce(
+          &ReceiverSessionImpl::OnMojoDisconnect, weak_factory_.GetWeakPtr()));
+  renderer_control_config_.emplace(std::move(renderer_controller),
+                                   external_renderer_controls_->Bind());
+
+  StartStreamingAsyncInternal(std::move(demuxer_connector));
+}
+
+void ReceiverSessionImpl::StartStreamingAsyncInternal(
+    mojo::AssociatedRemote<mojom::DemuxerConnector> demuxer_connector) {
   DCHECK(HasNetworkContextGetter());
 
   DVLOG(1) << __func__;
@@ -59,19 +80,6 @@
       &ReceiverSessionImpl::OnMojoDisconnect, weak_factory_.GetWeakPtr()));
 }
 
-void ReceiverSessionImpl::StartStreamingAsync(
-    mojo::AssociatedRemote<mojom::DemuxerConnector> demuxer_connector,
-    mojo::AssociatedRemote<mojom::RendererController> renderer_controller) {
-  DCHECK(!renderer_control_config_);
-  external_renderer_controls_ =
-      std::make_unique<RendererControllerImpl>(base::BindOnce(
-          &ReceiverSessionImpl::OnMojoDisconnect, weak_factory_.GetWeakPtr()));
-  renderer_control_config_.emplace(std::move(renderer_controller),
-                                   external_renderer_controls_->Bind());
-
-  StartStreamingAsync(std::move(demuxer_connector));
-}
-
 ReceiverSession::RendererController*
 ReceiverSessionImpl::GetRendererControls() {
   DCHECK(external_renderer_controls_);
diff --git a/components/cast_streaming/browser/receiver_session_impl.h b/components/cast_streaming/browser/receiver_session_impl.h
index f6c93c8..933c94d 100644
--- a/components/cast_streaming/browser/receiver_session_impl.h
+++ b/components/cast_streaming/browser/receiver_session_impl.h
@@ -65,6 +65,11 @@
     mojo::Remote<media::mojom::Renderer> renderer_controls_;
   };
 
+  // Helper function to execute code shared between the two implementations of
+  // StartStreamingAsync().
+  void StartStreamingAsyncInternal(
+      mojo::AssociatedRemote<mojom::DemuxerConnector> demuxer_connector);
+
   void PreloadBuffersAndStartPlayback();
 
   // Handler for |demuxer_connector_| disconnect.
diff --git a/components/cast_streaming/browser/stream_consumer.cc b/components/cast_streaming/browser/stream_consumer.cc
index 38ed7c8..41ccc562 100644
--- a/components/cast_streaming/browser/stream_consumer.cc
+++ b/components/cast_streaming/browser/stream_consumer.cc
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "base/task/sequenced_task_runner.h"
+#include "components/cast_streaming/public/features.h"
 #include "media/base/media_util.h"
 
 namespace cast_streaming {
@@ -176,11 +177,15 @@
                              .count());
 
   // Some senders do not send an initial playout time of 0. To work around this,
-  // a playout offset is added here.
-  if (playout_offset_ == base::TimeDelta::Max()) {
-    playout_offset_ = playout_time;
+  // a playout offset is added here. This is only required on mirroring sessions
+  // - and will in fact break remoting where timestamps by design do NOT begin
+  // at zero.
+  if (!IsCastRemotingEnabled()) {
+    if (playout_offset_ == base::TimeDelta::Max()) {
+      playout_offset_ = playout_time;
+    }
+    playout_time -= playout_offset_;
   }
-  playout_time -= playout_offset_;
 
   DVLOG(3) << "[ssrc:" << receiver_->ssrc() << "] "
            << "Received new frame. Timestamp: " << playout_time
diff --git a/components/external_intents/android/external_intents_features.cc b/components/external_intents/android/external_intents_features.cc
index e5478c0..8f695d6 100644
--- a/components/external_intents/android/external_intents_features.cc
+++ b/components/external_intents/android/external_intents_features.cc
@@ -18,7 +18,8 @@
 
 // Array of features exposed through the Java ExternalIntentsFeatures API.
 const base::Feature* kFeaturesExposedToJava[] = {
-    &kBlockExternalFormSubmitWithoutGesture, &kExternalNavigationDebugLogs};
+    &kBlockExternalFormSubmitWithoutGesture, &kExternalNavigationDebugLogs,
+    &kExternalNavigationSubframeRedirects};
 
 }  // namespace
 
@@ -34,6 +35,10 @@
              "ExternalNavigationDebugLogs",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kExternalNavigationSubframeRedirects,
+             "ExternalNavigationSubframeRedirects",
+             base::FEATURE_ENABLED_BY_DEFAULT);
+
 static jlong JNI_ExternalIntentsFeatures_GetFeature(JNIEnv* env, jint ordinal) {
   return reinterpret_cast<jlong>(kFeaturesExposedToJava[ordinal]);
 }
diff --git a/components/external_intents/android/external_intents_features.h b/components/external_intents/android/external_intents_features.h
index b3ecd4d9..bab62ff 100644
--- a/components/external_intents/android/external_intents_features.h
+++ b/components/external_intents/android/external_intents_features.h
@@ -12,6 +12,7 @@
 // Alphabetical:
 BASE_DECLARE_FEATURE(kBlockExternalFormSubmitWithoutGesture);
 BASE_DECLARE_FEATURE(kExternalNavigationDebugLogs);
+BASE_DECLARE_FEATURE(kExternalNavigationSubframeRedirects);
 
 }  // namespace external_intents
 
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalIntentsFeatures.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalIntentsFeatures.java
index 99e1a64..fddd0dd0 100644
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalIntentsFeatures.java
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalIntentsFeatures.java
@@ -20,6 +20,8 @@
     public static final String BLOCK_EXTERNAL_FORM_SUBMIT_WITHOUT_GESTURE_NAME =
             "BlockExternalFormSubmitWithoutGesture";
     public static final String EXTERNAL_NAVIGATION_DEBUG_LOGS_NAME = "ExternalNavigationDebugLogs";
+    public static final String EXTERNAL_NAVIGATION_SUBFRAME_REDIRECTS_NAME =
+            "ExternalNavigationSubframeRedirects";
 
     public static final ExternalIntentsFeatures BLOCK_EXTERNAL_FORM_SUBMIT_WITHOUT_GESTURE =
             new ExternalIntentsFeatures(0, BLOCK_EXTERNAL_FORM_SUBMIT_WITHOUT_GESTURE_NAME);
@@ -27,6 +29,9 @@
     public static final ExternalIntentsFeatures EXTERNAL_NAVIGATION_DEBUG_LOGS =
             new ExternalIntentsFeatures(1, EXTERNAL_NAVIGATION_DEBUG_LOGS_NAME);
 
+    public static final ExternalIntentsFeatures EXTERNAL_NAVIGATION_SUBFRAME_REDIRECTS =
+            new ExternalIntentsFeatures(2, EXTERNAL_NAVIGATION_SUBFRAME_REDIRECTS_NAME);
+
     private final int mOrdinal;
 
     private ExternalIntentsFeatures(int ordinal, String name) {
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java
index 9045ab2..842e0b2 100644
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java
@@ -10,7 +10,6 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.supplier.Supplier;
-import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.url.GURL;
@@ -43,13 +42,6 @@
      */
     boolean shouldDisableExternalIntentRequestsForUrl(GURL url);
 
-    /**
-     * Loads a URL as specified by |loadUrlParams| if possible. May fail in exceptional conditions
-     * (e.g., if there is no valid tab).
-     * @param loadUrlParams parameters of the URL to be loaded
-     */
-    void loadUrlIfPossible(LoadUrlParams loadUrlParams);
-
     /** Adds a window id to the intent, if necessary. */
     void maybeSetWindowId(Intent intent);
 
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
index 4a1bd84..537f654a 100644
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
@@ -44,14 +44,16 @@
 import org.chromium.base.Log;
 import org.chromium.base.PackageManagerUtils;
 import org.chromium.base.PathUtils;
+import org.chromium.base.RequiredCallback;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.Supplier;
-import org.chromium.base.task.PostTask;
 import org.chromium.build.BuildConfig;
 import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.components.embedder_support.util.UrlUtilities;
 import org.chromium.components.embedder_support.util.UrlUtilitiesJni;
+import org.chromium.components.external_intents.ExternalNavigationParams.AsyncActionTakenParams;
+import org.chromium.components.messages.DismissReason;
 import org.chromium.components.messages.MessageBannerProperties;
 import org.chromium.components.messages.MessageDispatcher;
 import org.chromium.components.messages.MessageDispatcherProvider;
@@ -60,12 +62,8 @@
 import org.chromium.components.messages.PrimaryActionClickBehavior;
 import org.chromium.components.webapk.lib.client.ChromeWebApkHostSignature;
 import org.chromium.components.webapk.lib.client.WebApkValidator;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.common.ContentUrlConstants;
-import org.chromium.content_public.common.Referrer;
-import org.chromium.network.mojom.ReferrerPolicy;
 import org.chromium.ui.base.MimeTypeUtils;
 import org.chromium.ui.base.PageTransition;
 import org.chromium.ui.base.WindowAndroid;
@@ -284,15 +282,15 @@
      * should be removed from the IntDef{} if an alternate solution for that bug is found.
      */
     @IntDef({OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT,
-            OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB,
+            OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB,
             OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
             OverrideUrlLoadingResultType.NO_OVERRIDE, OverrideUrlLoadingResultType.NUM_ENTRIES})
     @Retention(RetentionPolicy.SOURCE)
     public @interface OverrideUrlLoadingResultType {
         /* We should override the URL loading and launch an intent. */
         int OVERRIDE_WITH_EXTERNAL_INTENT = 0;
-        /* We should override the URL loading and clobber the current tab. */
-        int OVERRIDE_WITH_CLOBBERING_TAB = 1;
+        /* We should override the URL loading and perform a new navigation in the current tab. */
+        int OVERRIDE_WITH_NAVIGATE_TAB = 1;
         /* We should override the URL loading.  The desired action will be determined
          * asynchronously (e.g. by requiring user confirmation). */
         int OVERRIDE_WITH_ASYNC_ACTION = 2;
@@ -332,10 +330,20 @@
 
         boolean mWasExternalFallbackUrlLaunch;
 
+        GURL mTargetUrl;
+        ExternalNavigationParams mExternalNavigationParams;
+
         private OverrideUrlLoadingResult(@OverrideUrlLoadingResultType int resultType) {
             this(resultType, OverrideUrlLoadingAsyncActionType.NO_ASYNC_ACTION, false);
         }
 
+        private OverrideUrlLoadingResult(GURL targetUrl, ExternalNavigationParams params) {
+            this(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB,
+                    OverrideUrlLoadingAsyncActionType.NO_ASYNC_ACTION, false);
+            mTargetUrl = targetUrl;
+            mExternalNavigationParams = params;
+        }
+
         private OverrideUrlLoadingResult(@OverrideUrlLoadingResultType int resultType,
                 @OverrideUrlLoadingAsyncActionType int asyncActionType,
                 boolean wasExternalFallbackUrlLaunch) {
@@ -367,6 +375,16 @@
             return mWasExternalFallbackUrlLaunch;
         }
 
+        public GURL getTargetUrl() {
+            assert mResultType == OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB;
+            return mTargetUrl;
+        }
+
+        public ExternalNavigationParams getExternalNavigationParams() {
+            assert mResultType == OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB;
+            return mExternalNavigationParams;
+        }
+
         /**
          * Use this result when an asynchronous action needs to be carried out before deciding
          * whether to block the external navigation.
@@ -389,11 +407,11 @@
 
         /**
          * Use this result when the current external navigation should be blocked and a new
-         * navigation will be started in the Tab, clobbering the previous one.
+         * navigation will be started in the Tab, replacing the previous one.
          */
-        public static OverrideUrlLoadingResult forClobberingTab() {
-            return new OverrideUrlLoadingResult(
-                    OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB);
+        public static OverrideUrlLoadingResult forNavigateTab(
+                GURL targetUrl, ExternalNavigationParams params) {
+            return new OverrideUrlLoadingResult(targetUrl, params);
         }
 
         /**
@@ -477,6 +495,9 @@
         if (debug()) printDebugShouldOverrideUrlLoadingResultType(result);
         if (isIntentUrl) captureIntentSchemeMetrics(result, browserFallbackUrl);
 
+        if (result.getResultType() == OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION) {
+            params.onAsyncActionStarted();
+        }
         return result;
     }
 
@@ -528,14 +549,6 @@
             }
         }
 
-        // For subframes, we don't support fallback url for now. If we ever do implement this, be
-        // careful to prevent sandbox escapes.
-        // http://crbug.com/364522.
-        if (!params.isMainFrame()) {
-            if (debug()) Log.i(TAG, "Don't support fallback url in subframes");
-            return OverrideUrlLoadingResult.forNoOverride();
-        }
-
         // NOTE: any further redirection from fall-back URL should not override URL loading.
         // Otherwise, it can be used in chain for fingerprinting multiple app installation
         // status in one shot. In order to prevent this scenario, we notify redirection
@@ -545,9 +558,9 @@
                             .getAndClearShouldNotBlockOverrideUrlLoadingOnCurrentRedirectionChain()) {
             params.getRedirectHandler().setShouldNotOverrideUrlLoadingOnCurrentRedirectChain();
         }
-        if (debug()) Log.i(TAG, "clobberCurrentTab called");
-        return clobberCurrentTab(
-                browserFallbackUrl, params.getReferrerUrl(), params.isRendererInitiated());
+
+        if (debug()) Log.i(TAG, "redirecting to fallback URL");
+        return OverrideUrlLoadingResult.forNavigateTab(browserFallbackUrl, params);
     }
 
     private void printDebugShouldOverrideUrlLoadingResultType(OverrideUrlLoadingResult result) {
@@ -556,8 +569,8 @@
             case OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT:
                 resultString = "OVERRIDE_WITH_EXTERNAL_INTENT";
                 break;
-            case OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB:
-                resultString = "OVERRIDE_WITH_CLOBBERING_TAB";
+            case OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB:
+                resultString = "OVERRIDE_WITH_NAVIGATE_TAB";
                 break;
             case OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION:
                 resultString = "OVERRIDE_WITH_ASYNC_ACTION";
@@ -585,7 +598,7 @@
                 case OverrideUrlLoadingResultType.NO_OVERRIDE:
                     value = IntentUriNavigationResult.NO_FALLBACK_NO_OVERRIDE;
                     break;
-                case OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB:
+                case OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB:
                     // Quirk of incognito intent scheme URLs synchronously clobbering the tab with
                     // the target URL when the dialog can't be shown.
                     value = IntentUriNavigationResult.NO_FALLBACK_NO_OVERRIDE;
@@ -609,7 +622,7 @@
                 case OverrideUrlLoadingResultType.NO_OVERRIDE:
                     value = IntentUriNavigationResult.WITH_FALLBACK_NO_OVERRIDE;
                     break;
-                case OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB:
+                case OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB:
                     value = IntentUriNavigationResult.WITH_FALLBACK_USED_FALLBACK;
                     break;
                 default:
@@ -739,22 +752,16 @@
             public void onRequestPermissionsResult(String[] permissions, int[] grantResults) {
                 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED
                         && mDelegate.hasValidTab()) {
-                    if (params.isMainFrame()
-                            && params.getAsyncActionTakenInMainFrameCallback() != null) {
-                        params.getAsyncActionTakenInMainFrameCallback().onResult(
-                                new ExternalNavigationParams.AsyncActionTakenParams(
-                                        false, true, params));
+                    if (params.getRequiredAsyncActionTakenCallback() != null) {
+                        params.getRequiredAsyncActionTakenCallback().onResult(
+                                AsyncActionTakenParams.forNavigate(params.getUrl(), params));
                     }
-                    clobberCurrentTab(
-                            params.getUrl(), params.getReferrerUrl(), params.isRendererInitiated());
                 } else {
                     // TODO(tedchoc): Show an indication to the user that the navigation failed
                     //                instead of silently dropping it on the floor.
-                    if (params.isMainFrame()
-                            && params.getAsyncActionTakenInMainFrameCallback() != null) {
-                        params.getAsyncActionTakenInMainFrameCallback().onResult(
-                                new ExternalNavigationParams.AsyncActionTakenParams(
-                                        true, false, params));
+                    if (params.getRequiredAsyncActionTakenCallback() != null) {
+                        params.getRequiredAsyncActionTakenCallback().onResult(
+                                AsyncActionTakenParams.forNoAction());
                     }
                 }
             }
@@ -764,46 +771,6 @@
                 new String[] {permissionNeeded}, permissionCallback);
     }
 
-    /**
-     * Clobber the current tab and try not to pass an intent when it should be handled internally
-     * so that we can deliver HTTP referrer information safely.
-     *
-     * @param url The new URL after clobbering the current tab.
-     * @param referrerUrl The HTTP referrer URL.
-     * @param initiatorOrigin The Origin the navigation intiated from.
-     * @return OverrideUrlLoadingResultType (if the tab has been clobbered, or we're launching an
-     *         intent.)
-     */
-    @VisibleForTesting
-    protected OverrideUrlLoadingResult clobberCurrentTab(
-            GURL url, GURL referrerUrl, boolean isRendererInitiated) {
-        int transitionType = PageTransition.LINK;
-        final LoadUrlParams loadUrlParams = new LoadUrlParams(url, transitionType);
-        if (!referrerUrl.isEmpty()) {
-            Referrer referrer = new Referrer(referrerUrl.getSpec(), ReferrerPolicy.ALWAYS);
-            loadUrlParams.setReferrer(referrer);
-        }
-        // Ideally this navigation would be part of the navigation chain that triggered it and get,
-        // the correct SameSite cookie behavior, but this is impractical as Tab clobbering is
-        // frequently async and would require complex changes that are probably not worth doing for
-        // fallback URLs. Instead, we treat the navigation as coming from an opaque Origin so that
-        // SameSite cookies aren't mistakenly sent.
-        loadUrlParams.setIsRendererInitiated(isRendererInitiated);
-        loadUrlParams.setInitiatorOrigin(Origin.createOpaqueOrigin());
-
-        assert mDelegate.hasValidTab() : "clobberCurrentTab was called with an empty tab.";
-        // Loading URL will start a new navigation which cancels the current one
-        // that this clobbering is being done for. It leads to UAF. To avoid that,
-        // we're loading URL asynchronously. See https://crbug.com/732260.
-        PostTask.postTask(UiThreadTaskTraits.DEFAULT, new Runnable() {
-            @Override
-            public void run() {
-                mDelegate.loadUrlIfPossible(loadUrlParams);
-            }
-        });
-        return OverrideUrlLoadingResult.forClobberingTab();
-    }
-
     // https://crbug.com/1232514: On Android S, since WebAPKs aren't verified apps they are
     // never launched as the result of a suitable Intent, the user's default browser will be
     // opened instead. As a temporary solution, have Chrome launch the WebAPK.
@@ -1364,11 +1331,10 @@
         if (shouldLaunch) {
             try {
                 startActivity(intent);
-                if (params.isMainFrame()
-                        && params.getAsyncActionTakenInMainFrameCallback() != null) {
-                    params.getAsyncActionTakenInMainFrameCallback().onResult(
-                            new ExternalNavigationParams.AsyncActionTakenParams(
-                                    mDelegate.canCloseTabOnIncognitoIntentLaunch(), false, params));
+                if (params.getRequiredAsyncActionTakenCallback() != null) {
+                    params.getRequiredAsyncActionTakenCallback().onResult(
+                            AsyncActionTakenParams.forExternalIntentLaunched(
+                                    mDelegate.canCloseTabOnIncognitoIntentLaunch(), params));
                 }
                 return;
             } catch (ActivityNotFoundException e) {
@@ -1379,17 +1345,17 @@
         }
 
         OverrideUrlLoadingResult result = handleFallbackUrl(params, intent, fallbackUrl, false);
-        if (params.isMainFrame() && params.getAsyncActionTakenInMainFrameCallback() != null) {
+        if (params.getRequiredAsyncActionTakenCallback() != null) {
             if (result.getResultType() == OverrideUrlLoadingResultType.NO_OVERRIDE) {
                 // There was no fallback URL and we can't handle the URL the intent was targeting.
                 // In this case we'll return to the last committed URL.
-                params.getAsyncActionTakenInMainFrameCallback().onResult(
-                        new ExternalNavigationParams.AsyncActionTakenParams(false, false, params));
+                params.getRequiredAsyncActionTakenCallback().onResult(
+                        AsyncActionTakenParams.forNoAction());
             } else {
                 assert result.getResultType()
-                        == OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB;
-                params.getAsyncActionTakenInMainFrameCallback().onResult(
-                        new ExternalNavigationParams.AsyncActionTakenParams(false, true, params));
+                        == OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB;
+                params.getRequiredAsyncActionTakenCallback().onResult(
+                        AsyncActionTakenParams.forNavigate(result.getTargetUrl(), params));
             }
         }
     }
@@ -1616,8 +1582,7 @@
         }
 
         return startActivity(targetIntent, requiresIntentChooser, resolvingInfos, resolveActivity,
-                browserFallbackUrl, intentDataUrl, params.getReferrerUrl(),
-                params.getInitiatorOrigin(), params.isRendererInitiated());
+                browserFallbackUrl, intentDataUrl, params);
     }
 
     // https://crbug.com/1249964
@@ -1949,7 +1914,7 @@
      * @param intent The intent we want to send.
      */
     private void startActivity(Intent intent) {
-        startActivity(intent, false, null, null, null, null, null, null, false);
+        startActivity(intent, false, null, null, null, null, null);
     }
 
     /**
@@ -1965,15 +1930,12 @@
      * @param resolveActivity The resolving Activity |intent| matches against.
      * @param browserFallbackUrl The fallback URL if the user chooses not to leave this app.
      * @param intentDataUrl The URL |intent| is targeting.
-     * @param referrerUrl The referrer for the navigation.
-     * @param initiatorOrigin The Origin that initiated the navigation, if any.
-     * @param isRendererInitiated True if the navigation was renderer initiated.
+     * @param params The ExternalNavigationParams for the navigation.
      * @returns The OverrideUrlLoadingResult for starting (or not starting) the Activity.
      */
     protected OverrideUrlLoadingResult startActivity(Intent intent, boolean requiresIntentChooser,
             QueryIntentActivitiesSupplier resolvingInfos, ResolveActivitySupplier resolveActivity,
-            GURL browserFallbackUrl, GURL intentDataUrl, GURL referrerUrl, Origin initiatorOrigin,
-            boolean isRendererInitiated) {
+            GURL browserFallbackUrl, GURL intentDataUrl, ExternalNavigationParams params) {
         // Only touches disk on Kitkat. See http://crbug.com/617725 for more context.
         StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
         try {
@@ -1985,8 +1947,7 @@
             }
             if (requiresIntentChooser) {
                 return startActivityWithChooser(intent, resolvingInfos, resolveActivity,
-                        browserFallbackUrl, intentDataUrl, referrerUrl, context, initiatorOrigin,
-                        isRendererInitiated);
+                        browserFallbackUrl, intentDataUrl, params, context);
             }
             return doStartActivity(intent, context);
         } catch (SecurityException e) {
@@ -2020,8 +1981,8 @@
     @SuppressWarnings({"UseCompatLoadingForDrawables", "DiscouragedApi"})
     private OverrideUrlLoadingResult startActivityWithChooser(final Intent intent,
             QueryIntentActivitiesSupplier resolvingInfos, ResolveActivitySupplier resolveActivity,
-            GURL browserFallbackUrl, GURL intentDataUrl, GURL referrerUrl, Context context,
-            Origin initiatorOrigin, boolean isRendererInitiated) {
+            GURL browserFallbackUrl, GURL intentDataUrl, final ExternalNavigationParams params,
+            Context context) {
         ResolveInfo intentResolveInfo = resolveActivity.get();
         // If this is null, then the intent was only previously matching
         // non-default filters, so just drop it.
@@ -2076,8 +2037,14 @@
                 pickerIntent, new WindowAndroid.IntentCallback() {
                     @Override
                     public void onIntentCompleted(int resultCode, Intent data) {
+                        RequiredCallback<AsyncActionTakenParams> callback =
+                                params.getRequiredAsyncActionTakenCallback();
+                        assert callback != null;
                         // If |data| is null, the user backed out of the intent chooser.
-                        if (data == null) return;
+                        if (data == null) {
+                            callback.onResult(AsyncActionTakenParams.forNoAction());
+                            return;
+                        }
 
                         // Quirk of how we use the ActivityChooser - if the embedding app is
                         // chosen we get an intent back with ACTION_CREATE_SHORTCUT.
@@ -2089,10 +2056,13 @@
                             // matches what would have happened had the regular chooser dialog shown
                             // up and the user selected this app.
                             if (UrlUtilities.isAcceptedScheme(intentDataUrl)) {
-                                clobberCurrentTab(intentDataUrl, referrerUrl, isRendererInitiated);
+                                callback.onResult(
+                                        AsyncActionTakenParams.forNavigate(intentDataUrl, params));
                             } else if (!browserFallbackUrl.isEmpty()) {
-                                clobberCurrentTab(
-                                        browserFallbackUrl, referrerUrl, isRendererInitiated);
+                                callback.onResult(AsyncActionTakenParams.forNavigate(
+                                        browserFallbackUrl, params));
+                            } else {
+                                callback.onResult(AsyncActionTakenParams.forNoAction());
                             }
                             return;
                         }
@@ -2102,6 +2072,8 @@
                         intent.setSelector(null);
                         intent.setPackage(data.getComponent().getPackageName());
                         startActivity(intent);
+                        callback.onResult(
+                                AsyncActionTakenParams.forExternalIntentLaunched(true, params));
                     }
                 }, null);
         return OverrideUrlLoadingResult.forAsyncAction(
@@ -2180,13 +2152,21 @@
                         .with(MessageBannerProperties.ON_PRIMARY_ACTION,
                                 () -> {
                                     startActivity(targetIntent);
-                                    if (params.getAsyncActionTakenInMainFrameCallback() != null) {
-                                        params.getAsyncActionTakenInMainFrameCallback().onResult(
-                                                new ExternalNavigationParams.AsyncActionTakenParams(
-                                                        true, false, params));
+                                    if (params.getRequiredAsyncActionTakenCallback() != null) {
+                                        params.getRequiredAsyncActionTakenCallback().onResult(
+                                                AsyncActionTakenParams.forExternalIntentLaunched(
+                                                        true, params));
                                     }
                                     return PrimaryActionClickBehavior.DISMISS_IMMEDIATELY;
                                 })
+                        .with(MessageBannerProperties.ON_DISMISSED,
+                                (dismissReason) -> {
+                                    if (dismissReason == DismissReason.PRIMARY_ACTION) return;
+                                    if (params.getRequiredAsyncActionTakenCallback() != null) {
+                                        params.getRequiredAsyncActionTakenCallback().onResult(
+                                                AsyncActionTakenParams.forNoAction());
+                                    }
+                                })
                         .build();
         messageDispatcher.enqueueMessage(message, webContents, MessageScopeType.NAVIGATION, false);
         return OverrideUrlLoadingResult.forAsyncAction(
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationParams.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationParams.java
index 890b35b6..05e8a583 100644
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationParams.java
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationParams.java
@@ -4,37 +4,76 @@
 
 package org.chromium.components.external_intents;
 
+import androidx.annotation.IntDef;
 import androidx.annotation.Nullable;
 
 import org.chromium.base.Callback;
+import org.chromium.base.RequiredCallback;
 import org.chromium.ui.base.PageTransition;
 import org.chromium.url.GURL;
 import org.chromium.url.Origin;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * A container object for passing navigation parameters to {@link ExternalNavigationHandler}.
  */
 public class ExternalNavigationParams {
     /**
-     * A container for parameters passed to the AsyncActionTakenInMainFrameCallback.
+     * A container for parameters passed to the AsyncActionTakenCallback.
      */
     public static class AsyncActionTakenParams {
+        @IntDef({AsyncActionTakenType.NO_ACTION, AsyncActionTakenType.EXTERNAL_INTENT_LAUNCHED,
+                AsyncActionTakenType.NAVIGATE})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface AsyncActionTakenType {
+            /* Action was cancelled/rejected. */
+            int NO_ACTION = 0;
+            /* An external intent was launched as a result of the action. */
+            int EXTERNAL_INTENT_LAUNCHED = 1;
+            /* A navigation should occur as the result of the action */
+            int NAVIGATE = 2;
+        }
+
+        @AsyncActionTakenType
+        public int actionType;
+
         // Whether the async action taken allows the tab to be closed.
         public boolean canCloseTab;
 
-        // Whether the tab will be clobbered as a result of this async action.
-        public boolean willClobberTab;
-
         public ExternalNavigationParams externalNavigationParams;
 
-        public AsyncActionTakenParams(
-                boolean canCloseTab, boolean willClobberTab, ExternalNavigationParams params) {
-            this.canCloseTab = canCloseTab;
-            this.willClobberTab = willClobberTab;
-            this.externalNavigationParams = params;
+        public GURL targetUrl;
 
-            // We can't both close the tab and clobber it.
-            assert !willClobberTab || !canCloseTab;
+        private AsyncActionTakenParams() {
+            this.actionType = AsyncActionTakenType.NO_ACTION;
+        }
+
+        private AsyncActionTakenParams(GURL targetUrl, ExternalNavigationParams params) {
+            this.actionType = AsyncActionTakenType.NAVIGATE;
+            this.targetUrl = targetUrl;
+            this.externalNavigationParams = params;
+        }
+
+        private AsyncActionTakenParams(boolean canCloseTab, ExternalNavigationParams params) {
+            this.actionType = AsyncActionTakenType.EXTERNAL_INTENT_LAUNCHED;
+            this.canCloseTab = canCloseTab;
+            this.externalNavigationParams = params;
+        }
+
+        public static AsyncActionTakenParams forNoAction() {
+            return new AsyncActionTakenParams();
+        }
+
+        public static AsyncActionTakenParams forNavigate(
+                GURL targetUrl, ExternalNavigationParams params) {
+            return new AsyncActionTakenParams(targetUrl, params);
+        }
+
+        public static AsyncActionTakenParams forExternalIntentLaunched(
+                boolean canCloseTab, ExternalNavigationParams params) {
+            return new AsyncActionTakenParams(canCloseTab, params);
         }
     }
 
@@ -51,17 +90,20 @@
     private final boolean mIsMainFrame;
     private final String mNativeClientPackageName;
     private final boolean mHasUserGesture;
-    private final Callback<AsyncActionTakenParams> mAsyncActionTakenInMainFrameCallback;
+    private final Callback<AsyncActionTakenParams> mAsyncActionTakenCallback;
     private boolean mIsRendererInitiated;
     private Origin mInitiatorOrigin;
 
+    // Populated when an async action is taken, ensuring the callback gets called.
+    private RequiredCallback<AsyncActionTakenParams> mRequiredAsyncActionTakenCallback;
+
     private ExternalNavigationParams(GURL url, boolean isIncognito, GURL referrerUrl,
             int pageTransition, boolean isRedirect, boolean appMustBeInForeground,
             RedirectHandler redirectHandler, boolean openInNewTab,
             boolean isBackgroundTabNavigation, boolean intentLaunchesAllowedInBackgroundTabs,
             boolean isMainFrame, String nativeClientPackageName, boolean hasUserGesture,
-            Callback<AsyncActionTakenParams> asyncActionTakenInMainFrameCallback,
-            boolean isRendererInitiated, @Nullable Origin initiatorOrigin) {
+            Callback<AsyncActionTakenParams> asyncActionTakenCallback, boolean isRendererInitiated,
+            @Nullable Origin initiatorOrigin) {
         mUrl = url;
         assert mUrl != null;
         mIsIncognito = isIncognito;
@@ -76,11 +118,17 @@
         mIsMainFrame = isMainFrame;
         mNativeClientPackageName = nativeClientPackageName;
         mHasUserGesture = hasUserGesture;
-        mAsyncActionTakenInMainFrameCallback = asyncActionTakenInMainFrameCallback;
+        mAsyncActionTakenCallback = asyncActionTakenCallback;
         mIsRendererInitiated = isRendererInitiated;
         mInitiatorOrigin = initiatorOrigin;
     }
 
+    public void onAsyncActionStarted() {
+        if (mAsyncActionTakenCallback != null) {
+            mRequiredAsyncActionTakenCallback = new RequiredCallback(mAsyncActionTakenCallback);
+        }
+    }
+
     /** @return The URL to potentially open externally. */
     public GURL getUrl() {
         return mUrl;
@@ -155,8 +203,8 @@
     /**
      * @return A callback to be run when an async action is taken.
      */
-    public Callback<AsyncActionTakenParams> getAsyncActionTakenInMainFrameCallback() {
-        return mAsyncActionTakenInMainFrameCallback;
+    public RequiredCallback<AsyncActionTakenParams> getRequiredAsyncActionTakenCallback() {
+        return mRequiredAsyncActionTakenCallback;
     }
 
     /**
@@ -196,7 +244,7 @@
         private boolean mIsMainFrame;
         private String mNativeClientPackageName;
         private boolean mHasUserGesture;
-        private Callback<AsyncActionTakenParams> mAsyncActionTakenInMainFrameCallback;
+        private Callback<AsyncActionTakenParams> mAsyncActionTakenCallback;
         private boolean mIsRendererInitiated;
         private Origin mInitiatorOrigin;
 
@@ -265,8 +313,8 @@
         /**
          * Sets the callback to be run when an async action is taken.
          */
-        public Builder setAsyncActionTakenInMainFrameCallback(Callback<AsyncActionTakenParams> v) {
-            mAsyncActionTakenInMainFrameCallback = v;
+        public Builder setAsyncActionTakenCallback(Callback<AsyncActionTakenParams> v) {
+            mAsyncActionTakenCallback = v;
             return this;
         }
 
@@ -292,7 +340,7 @@
                     mIsRedirect, mApplicationMustBeInForeground, mRedirectHandler, mOpenInNewTab,
                     mIsBackgroundTabNavigation, mIntentLaunchesAllowedInBackgroundTabs,
                     mIsMainFrame, mNativeClientPackageName, mHasUserGesture,
-                    mAsyncActionTakenInMainFrameCallback, mIsRendererInitiated, mInitiatorOrigin);
+                    mAsyncActionTakenCallback, mIsRendererInitiated, mInitiatorOrigin);
         }
     }
 }
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateClient.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateClient.java
index 334b8c75..eb8b259d 100644
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateClient.java
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateClient.java
@@ -7,6 +7,7 @@
 import android.app.Activity;
 
 import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResult;
+import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.WebContents;
 
@@ -61,4 +62,11 @@
      * |navigationHandle|. |overrideUrlLoadingResult| specifies the decision. */
     void onDecisionReachedForNavigation(
             NavigationHandle navigationHandle, OverrideUrlLoadingResult overrideUrlLoadingResult);
+
+    /**
+     * Loads a URL as specified by |loadUrlParams| if possible. May fail in exceptional conditions
+     * (e.g., if there is no valid tab).
+     * @param loadUrlParams parameters of the URL to be loaded
+     */
+    void loadUrlIfPossible(LoadUrlParams loadUrlParams);
 }
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java
index 4e92df0..3dab3ee 100644
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java
@@ -20,11 +20,14 @@
 import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResultType;
 import org.chromium.components.external_intents.ExternalNavigationParams.AsyncActionTakenParams;
 import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
+import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.NavigationController;
 import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.common.ConsoleMessageLevel;
+import org.chromium.content_public.common.Referrer;
+import org.chromium.network.mojom.ReferrerPolicy;
 import org.chromium.ui.base.PageTransition;
 import org.chromium.url.GURL;
 import org.chromium.url.Origin;
@@ -155,16 +158,17 @@
                 navigationHandle.hasUserGesture(), navigationHandle.isRendererInitiated(),
                 navigationHandle.getReferrerUrl(), navigationHandle.isInPrimaryMainFrame(),
                 navigationHandle.getInitiatorOrigin(), navigationHandle.isExternalProtocol(),
-                mClient.areIntentLaunchesAllowedInHiddenTabsForNavigation(navigationHandle));
+                mClient.areIntentLaunchesAllowedInHiddenTabsForNavigation(navigationHandle),
+                this::onDidAsyncActionInMainFrame);
 
         mClient.onDecisionReachedForNavigation(navigationHandle, result);
 
         switch (result.getResultType()) {
             case OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT:
-                onDidFinishMainFrameUrlOverriding(true, false, escapedUrl);
+                onDidFinishMainFrameIntentLaunch(true, escapedUrl);
                 return true;
-            case OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB:
-                mShouldClearRedirectHistoryForTabClobbering = true;
+            case OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB:
+                clobberMainFrame(result.getTargetUrl(), result.getExternalNavigationParams());
                 return true;
             case OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION:
                 return true;
@@ -197,15 +201,19 @@
                 transition, false /* isRedirect */, hasUserGesture, true /* isRendererInitiated */,
                 GURL.emptyGURL() /* referrerUrl */, false /* isInPrimaryMainFrame */,
                 initiatorOrigin, true /* isExternalProtocol */,
-                false /* areIntentLaunchesAllowedInHiddenTabsForNavigation */);
+                false /* areIntentLaunchesAllowedInHiddenTabsForNavigation */,
+                this::onDidAsyncActionInSubFrame);
 
         switch (result.getResultType()) {
             case OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT:
                 return null;
-            case OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB:
-                // TODO(https://crbug.com/1365100): Pass the clobbering URL to native and do a
-                // redirect rather than clobbering the tab.
-                return null;
+            case OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB:
+                if (ExternalIntentsFeatures.EXTERNAL_NAVIGATION_SUBFRAME_REDIRECTS.isEnabled()) {
+                    assert result.getTargetUrl() != null;
+                    return result.getTargetUrl();
+                } else {
+                    return null;
+                }
             case OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION:
                 return null;
             case OverrideUrlLoadingResultType.NO_OVERRIDE:
@@ -219,7 +227,8 @@
             GURL escapedUrl, @PageTransition int pageTransition, boolean isRedirect,
             boolean hasUserGesture, boolean isRendererInitiated, GURL referrerUrl,
             boolean isInPrimaryMainFrame, Origin initiatorOrigin, boolean isExternalProtocol,
-            boolean areIntentLaunchesAllowedInHiddenTabsForNavigation) {
+            boolean areIntentLaunchesAllowedInHiddenTabsForNavigation,
+            Callback<AsyncActionTakenParams> asyncActionTakenCallback) {
         redirectHandler.updateNewUrlLoading(pageTransition, isRedirect, hasUserGesture,
                 mClient.getLastUserInteractionTime(), getLastCommittedEntryIndex(),
                 isInitialNavigation(), isRendererInitiated);
@@ -245,7 +254,7 @@
                         .setHasUserGesture(hasUserGesture)
                         .setIsRendererInitiated(isRendererInitiated)
                         .setInitiatorOrigin(initiatorOrigin)
-                        .setAsyncActionTakenInMainFrameCallback(this::onDidTakeMainFrameAsyncAction)
+                        .setAsyncActionTakenCallback(asyncActionTakenCallback)
                         .build();
 
         OverrideUrlLoadingResult result = mExternalNavHandler.shouldOverrideUrlLoading(params);
@@ -319,19 +328,26 @@
         return false;
     }
 
-    private void onDidTakeMainFrameAsyncAction(AsyncActionTakenParams params) {
-        onDidFinishMainFrameUrlOverriding(params.canCloseTab, params.willClobberTab,
-                params.externalNavigationParams.getUrl());
+    private void onDidAsyncActionInMainFrame(AsyncActionTakenParams params) {
+        switch (params.actionType) {
+            case AsyncActionTakenParams.AsyncActionTakenType.NAVIGATE:
+                clobberMainFrame(params.targetUrl, params.externalNavigationParams);
+                break;
+            case AsyncActionTakenParams.AsyncActionTakenType.EXTERNAL_INTENT_LAUNCHED:
+                onDidFinishMainFrameIntentLaunch(
+                        params.canCloseTab, params.externalNavigationParams.getUrl());
+                break;
+            default: // NO_ACTION
+                break;
+        }
     }
 
-    /**
-     * Called when Chrome decides to override URL loading and launch an intent or an asynchronous
-     * action.
-     */
-    private void onDidFinishMainFrameUrlOverriding(
-            boolean canCloseTab, boolean willClobberTab, GURL escapedUrl) {
-        if (mClient.getWebContents() == null) return;
+    private void onDidAsyncActionInSubFrame(AsyncActionTakenParams params) {
+        // TODO(https://crbug.com/1365100): Implement navigate action.
+    }
 
+    private void onDidFinishMainFrameIntentLaunch(boolean canCloseTab, GURL escapedUrl) {
+        if (mClient.getWebContents() == null) return;
         boolean shouldCloseTab = canCloseTab && isTabOnInitialNavigationChain();
 
         @MainFrameIntentLaunch
@@ -389,16 +405,41 @@
                 mClient.getOrCreateRedirectHandler()
                         .getLastCommittedEntryIndexBeforeStartingNavigation();
         if (getLastCommittedEntryIndex() <= lastCommittedEntryIndexBeforeNavigation) return;
-        if (willClobberTab) {
-            mShouldClearRedirectHistoryForTabClobbering = true;
-        } else {
-            // http://crbug/426679 : we want to go back to the last committed entry index which
-            // was saved before this navigation, and remove the empty entries from the
-            // navigation history.
-            mClearAllForwardHistoryRequired = true;
-            mClient.getWebContents().getNavigationController().goToNavigationIndex(
-                    lastCommittedEntryIndexBeforeNavigation);
+
+        // http://crbug/426679 : we want to go back to the last committed entry index which
+        // was saved before this navigation, and remove the empty entries from the
+        // navigation history.
+        mClearAllForwardHistoryRequired = true;
+        mClient.getWebContents().getNavigationController().goToNavigationIndex(
+                lastCommittedEntryIndexBeforeNavigation);
+    }
+
+    private void clobberMainFrame(GURL targetUrl, ExternalNavigationParams params) {
+        int transitionType = PageTransition.LINK;
+        final LoadUrlParams loadUrlParams = new LoadUrlParams(targetUrl, transitionType);
+        if (!params.getReferrerUrl().isEmpty()) {
+            Referrer referrer =
+                    new Referrer(params.getReferrerUrl().getSpec(), ReferrerPolicy.ALWAYS);
+            loadUrlParams.setReferrer(referrer);
         }
+        // Ideally this navigation would be part of the navigation chain that triggered it and get,
+        // the correct SameSite cookie behavior, but this is impractical as Tab clobbering is
+        // frequently async and would require complex changes that are probably not worth doing for
+        // fallback URLs. Instead, we treat the navigation as coming from an opaque Origin so that
+        // SameSite cookies aren't mistakenly sent.
+        loadUrlParams.setIsRendererInitiated(params.isRendererInitiated());
+        loadUrlParams.setInitiatorOrigin(Origin.createOpaqueOrigin());
+
+        // Loading URL will start a new navigation which cancels the current one
+        // that this clobbering is being done for. It leads to UAF. To avoid that,
+        // we're loading URL asynchronously. See https://crbug.com/732260.
+        PostTask.postTask(UiThreadTaskTraits.DEFAULT, new Runnable() {
+            @Override
+            public void run() {
+                mClient.loadUrlIfPossible(loadUrlParams);
+            }
+        });
+        mShouldClearRedirectHistoryForTabClobbering = true;
     }
 
     private void logBlockedNavigationToDevToolsConsole(GURL url) {
diff --git a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
index 44acd30..dfb6a65 100644
--- a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
+++ b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
@@ -52,14 +52,14 @@
 import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingAsyncActionType;
 import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResult;
 import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResultType;
-import org.chromium.content_public.browser.LoadUrlParams;
+import org.chromium.components.external_intents.ExternalNavigationParams.AsyncActionTakenParams;
+import org.chromium.components.external_intents.ExternalNavigationParams.AsyncActionTakenParams.AsyncActionTakenType;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
 import org.chromium.ui.base.PageTransition;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.test.util.BlankUiTestActivity;
 import org.chromium.url.GURL;
-import org.chromium.url.Origin;
 
 import java.net.URISyntaxException;
 import java.util.ArrayList;
@@ -331,6 +331,9 @@
                 .withRedirectHandler(handler)
                 .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
                         OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH, IGNORE);
+        // Callback won't have been run for the Message.
+        mUrlHandler.mAsyncActionCallback.onResult(AsyncActionTakenParams.forNoAction());
+
         checkUrl("http://youtube.com")
                 .withPageTransition(PageTransition.FORM_SUBMIT)
                 .withIsRedirect(true)
@@ -514,6 +517,8 @@
                 .withRedirectHandler(redirectHandler)
                 .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
                         OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH, IGNORE);
+        // Callback won't have been run for the Message.
+        mUrlHandler.mAsyncActionCallback.onResult(AsyncActionTakenParams.forNoAction());
 
         // http://crbug.com/709217
         redirectHandler.updateNewUrlLoading(
@@ -527,6 +532,8 @@
                 .withRedirectHandler(redirectHandler)
                 .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
                         OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH, IGNORE);
+        // Callback won't have been run for the Message.
+        mUrlHandler.mAsyncActionCallback.onResult(AsyncActionTakenParams.forNoAction());
 
         // If a user types an external protocol, it may as well ask to leave Chrome.
         redirectHandler.updateNewUrlLoading(PageTransition.TYPED, false, false, 0, 0, false, false);
@@ -536,6 +543,8 @@
                 .withRedirectHandler(redirectHandler)
                 .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
                         OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH, IGNORE);
+        // Callback won't have been run for the Message.
+        mUrlHandler.mAsyncActionCallback.onResult(AsyncActionTakenParams.forNoAction());
     }
 
     @Test
@@ -583,7 +592,7 @@
                 .withIsRendererInitiated(false)
                 .withIsRedirect(true)
                 .withChromeAppInForegroundRequired(true)
-                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE);
     }
 
     @Test
@@ -864,7 +873,7 @@
         mDelegate.setCanLoadUrlInTab(false);
         checkUrl(INTENT_URL_FOR_SELF_CUSTOM_TABS)
                 .withIsIncognito(true)
-                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE);
         Assert.assertNull(mUrlHandler.mStartActivityIntent);
         Assert.assertEquals("http://example.com/", mUrlHandler.mNewUrlAfterClobbering);
     }
@@ -886,14 +895,14 @@
         mDelegate.setCanLoadUrlInTab(false);
         checkUrl(INTENT_URL_FOR_SELF)
                 .withIsIncognito(true)
-                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE);
         Assert.assertNull(mUrlHandler.mStartActivityIntent);
         Assert.assertEquals("http://example.com/", mUrlHandler.mNewUrlAfterClobbering);
 
         mUrlHandler.mResolveInfoContainsSelf = false;
         checkUrl(INTENT_URL_FOR_SELF)
                 .withIsIncognito(true)
-                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE);
         Assert.assertNull(mUrlHandler.mStartActivityIntent);
         Assert.assertEquals(YOUTUBE_URL, mUrlHandler.mNewUrlAfterClobbering);
     }
@@ -950,6 +959,9 @@
 
         Assert.assertNull(mUrlHandler.mNewUrlAfterClobbering);
         Assert.assertNull(mUrlHandler.mReferrerUrlForClobbering);
+
+        // Callback won't have been run for the mocked AlertDialog.
+        mUrlHandler.mAsyncActionCallback.onResult(AsyncActionTakenParams.forNoAction());
     }
 
     @Test
@@ -975,7 +987,7 @@
         mDelegate.add(new IntentActivity(IMDB_WEBPAGE_FOR_TOM_HANKS, TEXT_APP_1_PACKAGE_NAME));
         checkUrl(INTENT_URL_WITH_FALLBACK_URL)
                 .withReferrer(SEARCH_RESULT_URL_FOR_TOM_HANKS)
-                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE);
         Assert.assertNull(mUrlHandler.mStartActivityIntent);
         Assert.assertEquals(IMDB_WEBPAGE_FOR_TOM_HANKS, mUrlHandler.mNewUrlAfterClobbering);
         Assert.assertEquals(SEARCH_RESULT_URL_FOR_TOM_HANKS, mUrlHandler.mReferrerUrlForClobbering);
@@ -991,7 +1003,7 @@
         // the current tab.
         checkUrl(INTENT_URL_WITH_FALLBACK_URL)
                 .withReferrer(SEARCH_RESULT_URL_FOR_TOM_HANKS)
-                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE);
 
         Assert.assertNull(mUrlHandler.mStartActivityIntent);
         Assert.assertEquals(IMDB_WEBPAGE_FOR_TOM_HANKS, mUrlHandler.mNewUrlAfterClobbering);
@@ -1027,7 +1039,7 @@
                 + "S." + ExternalNavigationHandler.EXTRA_BROWSER_FALLBACK_URL + "="
                 + "https://play.google.com/store/search?q=pub:imdb;end";
         checkUrl(intentBadUrl)
-                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE);
     }
 
     @Test
@@ -1084,7 +1096,8 @@
                         mUrlHandler.mStartActivityIntent.getDataString());
             });
         } finally {
-            if (mUrlHandler.mShownIncognitoAlertDialog != null) {
+            if (mUrlHandler.mShownIncognitoAlertDialog != null
+                    && mUrlHandler.mShownIncognitoAlertDialog.isShowing()) {
                 mUrlHandler.mShownIncognitoAlertDialog.cancel();
             }
             activity.finish();
@@ -1320,17 +1333,19 @@
         Assert.assertEquals("market://details?id=com.imdb.mobile&referrer=mypage",
                 mUrlHandler.mStartActivityIntent.getDataString());
 
+        String fallbackUrl = "https://play.google.com/store/search?q=pub:imdb";
         redirectHandler = RedirectHandler.create();
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, true, 0, 0, false, true);
         String intentBadUrl = "intent:///name/nm0000158#Intent;scheme=imdb;package=com.imdb.mobile;"
-                + "S." + ExternalNavigationHandler.EXTRA_BROWSER_FALLBACK_URL + "="
-                + "https://play.google.com/store/search?q=pub:imdb;end";
+                + "S." + ExternalNavigationHandler.EXTRA_BROWSER_FALLBACK_URL + "=" + fallbackUrl
+                + ";end";
         checkUrl(intentBadUrl)
                 .withIsMainFrame(false)
                 .withHasUserGesture(true)
                 .withRedirectHandler(redirectHandler)
                 .withPageTransition(PageTransition.LINK)
-                .expecting(OverrideUrlLoadingResultType.NO_OVERRIDE, IGNORE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE);
+        Assert.assertEquals(fallbackUrl, mUrlHandler.mNewUrlAfterClobbering);
     }
 
     @Test
@@ -1365,7 +1380,7 @@
 
     @Test
     @SmallTest
-    public void testFallbackUrl_DontFallbackForAutoSubframe() {
+    public void testFallbackUrl_FallbackForAutoSubframe() {
         // IMDB app isn't installed.
         mDelegate.setCanResolveActivityForExternalSchemes(false);
 
@@ -1381,7 +1396,8 @@
                 .withRedirectHandler(redirectHandler)
                 .withPageTransition(PageTransition.AUTO_SUBFRAME)
                 .withReferrer(SEARCH_RESULT_URL_FOR_TOM_HANKS)
-                .expecting(OverrideUrlLoadingResultType.NO_OVERRIDE, IGNORE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE);
+        Assert.assertEquals(IMDB_WEBPAGE_FOR_TOM_HANKS, mUrlHandler.mNewUrlAfterClobbering);
     }
 
     @Test
@@ -1397,7 +1413,7 @@
                 .withRedirectHandler(redirectHandler)
                 .withPageTransition(PageTransition.LINK)
                 .withReferrer(SEARCH_RESULT_URL_FOR_TOM_HANKS)
-                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE);
     }
 
     @Test
@@ -1409,7 +1425,7 @@
         // Fallback URL should work even when package name isn't given.
         checkUrl(INTENT_URL_WITH_FALLBACK_URL_WITHOUT_PACKAGE_NAME)
                 .withReferrer(SEARCH_RESULT_URL_FOR_TOM_HANKS)
-                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE);
 
         Assert.assertNull(mUrlHandler.mStartActivityIntent);
         Assert.assertEquals(IMDB_WEBPAGE_FOR_TOM_HANKS, mUrlHandler.mNewUrlAfterClobbering);
@@ -1425,7 +1441,7 @@
         checkUrl(INTENT_URL_WITH_FALLBACK_URL)
                 .withReferrer(SEARCH_RESULT_URL_FOR_TOM_HANKS)
                 .withIsIncognito(true)
-                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE);
 
         Assert.assertNull(mUrlHandler.mStartActivityIntent);
         Assert.assertEquals(IMDB_WEBPAGE_FOR_TOM_HANKS, mUrlHandler.mNewUrlAfterClobbering);
@@ -1450,6 +1466,9 @@
         Assert.assertTrue(invokedIntent.getData().toString().startsWith("market://"));
         Assert.assertEquals(null, mUrlHandler.mNewUrlAfterClobbering);
         Assert.assertEquals(null, mUrlHandler.mReferrerUrlForClobbering);
+
+        // Callback won't have been run with the mocked AlertDialog.
+        mUrlHandler.mAsyncActionCallback.onResult(AsyncActionTakenParams.forNoAction());
     }
 
     @Test
@@ -1469,7 +1488,7 @@
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, false, 0, 0, false, true);
         checkUrl(INTENT_URL_WITH_FALLBACK_URL_WITHOUT_PACKAGE_NAME)
                 .withRedirectHandler(redirectHandler)
-                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE);
 
         // Now the user opens a link.
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, true, 0, 1, false, true);
@@ -1490,7 +1509,7 @@
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, true, 0, 0, false, true);
         checkUrl(INTENT_URL_WITH_CHAIN_FALLBACK_URL)
                 .withRedirectHandler(redirectHandler)
-                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE);
 
         // As a result of intent resolution fallback, we have clobberred the current tab.
         // The fall-back URL was HTTP-schemed, but it was effectively redirected to a new intent
@@ -1511,7 +1530,7 @@
                 PageTransition.LINK, false, true, lastUserInteractionTimeInMillis, 1, false, true);
         checkUrl(INTENT_URL_WITH_FALLBACK_URL)
                 .withRedirectHandler(redirectHandler)
-                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE);
     }
 
     @Test
@@ -1846,6 +1865,8 @@
                 .withIsRendererInitiated(false)
                 .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
                         OverrideUrlLoadingAsyncActionType.UI_GATING_BROWSER_NAVIGATION, START_FILE);
+        // Callback won't have been run for the Permission check.
+        mUrlHandler.mAsyncActionCallback.onResult(AsyncActionTakenParams.forNoAction());
     }
 
     @Test
@@ -1887,6 +1908,8 @@
                 .withIsRendererInitiated(false)
                 .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
                         OverrideUrlLoadingAsyncActionType.UI_GATING_BROWSER_NAVIGATION, START_FILE);
+        // Callback won't have been run for the Permission dialog.
+        mUrlHandler.mAsyncActionCallback.onResult(AsyncActionTakenParams.forNoAction());
     }
 
     @Test
@@ -2067,6 +2090,9 @@
                         OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH, START_INCOGNITO);
 
         Assert.assertTrue(mUrlHandler.mStartIncognitoIntentCalled);
+
+        // Callback won't have been run with the mocked AlertDialog.
+        mUrlHandler.mAsyncActionCallback.onResult(AsyncActionTakenParams.forNoAction());
     }
 
     @Test
@@ -2110,6 +2136,9 @@
                         OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH, START_INCOGNITO);
         Assert.assertTrue(mDelegate.maybeSetRequestMetadataCalled);
         Assert.assertTrue(mUrlHandler.mStartIncognitoIntentCalled);
+
+        // Callback won't have been run with the mocked AlertDialog.
+        mUrlHandler.mAsyncActionCallback.onResult(AsyncActionTakenParams.forNoAction());
     }
 
     @Test
@@ -2605,6 +2634,7 @@
         public boolean mRequiresIntentChooser;
         private boolean mSendIntentsForReal;
         public boolean mExpectingMessage;
+        public Callback<AsyncActionTakenParams> mAsyncActionCallback;
 
         public ExternalNavigationHandlerForTesting(ExternalNavigationDelegate delegate) {
             super(delegate);
@@ -2659,14 +2689,6 @@
         }
 
         @Override
-        protected OverrideUrlLoadingResult clobberCurrentTab(
-                GURL url, GURL referrerUrl, boolean isRendererInitiated) {
-            mNewUrlAfterClobbering = url.getSpec();
-            mReferrerUrlForClobbering = referrerUrl.getSpec();
-            return OverrideUrlLoadingResult.forClobberingTab();
-        }
-
-        @Override
         public boolean isYoutubePairingCode(GURL url) {
             return super.isYoutubePairingCode(url);
         }
@@ -2680,14 +2702,12 @@
         protected OverrideUrlLoadingResult startActivity(Intent intent,
                 boolean requiresIntentChooser, QueryIntentActivitiesSupplier resolvingInfos,
                 ResolveActivitySupplier resolveActivity, GURL browserFallbackUrl,
-                GURL intentDataUrl, GURL referrerUrl, Origin initiatorOrigin,
-                boolean isRendererInitiated) {
+                GURL intentDataUrl, ExternalNavigationParams params) {
             mStartActivityIntent = intent;
             mRequiresIntentChooser = requiresIntentChooser;
             if (mSendIntentsForReal) {
                 return super.startActivity(intent, requiresIntentChooser, resolvingInfos,
-                        resolveActivity, browserFallbackUrl, intentDataUrl, referrerUrl,
-                        initiatorOrigin, isRendererInitiated);
+                        resolveActivity, browserFallbackUrl, intentDataUrl, params);
             }
             return OverrideUrlLoadingResult.forExternalIntent();
         }
@@ -2809,9 +2829,6 @@
         }
 
         @Override
-        public void loadUrlIfPossible(LoadUrlParams loadUrlParams) {}
-
-        @Override
         public void maybeSetWindowId(Intent intent) {}
 
         @Override
@@ -3091,6 +3108,16 @@
             mDelegate.reset();
             mUrlHandler.reset();
 
+            Callback<AsyncActionTakenParams> callback = new Callback<AsyncActionTakenParams>() {
+                @Override
+                public void onResult(AsyncActionTakenParams params) {
+                    if (params.actionType == AsyncActionTakenType.NAVIGATE) {
+                        mUrlHandler.mNewUrlAfterClobbering = params.targetUrl.getSpec();
+                        mUrlHandler.mReferrerUrlForClobbering =
+                                params.externalNavigationParams.getReferrerUrl().getSpec();
+                    }
+                }
+            };
             ExternalNavigationParams params =
                     new ExternalNavigationParams
                             .Builder(new GURL(mUrl), mIsIncognito, new GURL(mReferrerUrl),
@@ -3104,8 +3131,19 @@
                             .setNativeClientPackageName(mDelegate.getReferrerWebappPackageName())
                             .setHasUserGesture(mHasUserGesture)
                             .setIsRendererInitiated(mIsRendererInitiated)
+                            .setAsyncActionTakenCallback(callback)
                             .build();
             OverrideUrlLoadingResult result = mUrlHandler.shouldOverrideUrlLoading(params);
+
+            if (result.getResultType() == OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB) {
+                mUrlHandler.mNewUrlAfterClobbering = result.mTargetUrl.getSpec();
+                mUrlHandler.mReferrerUrlForClobbering =
+                        result.mExternalNavigationParams.getReferrerUrl().getSpec();
+            }
+            if (result.getResultType() == OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION) {
+                mUrlHandler.mAsyncActionCallback = params.getRequiredAsyncActionTakenCallback();
+            }
+
             boolean startActivityCalled = false;
             boolean startWebApkCalled = false;
 
diff --git a/components/feature_engagement/public/event_constants.cc b/components/feature_engagement/public/event_constants.cc
index 84840bed..80a930b 100644
--- a/components/feature_engagement/public/event_constants.cc
+++ b/components/feature_engagement/public/event_constants.cc
@@ -69,6 +69,16 @@
 const char kDefaultSiteViewUsed[] = "default_site_view_used";
 const char kOverflowMenuNoHorizontalScrollOrAction[] =
     "overflow_menu_no_horizontal_scroll_or_action";
+const char kDefaultBrowserPromoShown[] = "default_browser_promo_shown";
+const char kBlueDotPromoCriterionMet[] = "blue_dot_promo_criterion_met";
+const char kBlueDotPromoEligibilityMet[] = "blue_dot_promo_eligibility_met";
+const char kBlueDotPromoOverflowMenuShown[] =
+    "blue_dot_promo_overflow_menu_shown";
+const char kBlueDotPromoSettingsShown[] = "blue_dot_promo_settings_shown";
+const char kBlueDotPromoOverflowMenuDismissed[] =
+    "blue_dot_promo_overflow_menu_dismissed";
+const char kBlueDotPromoSettingsDismissed[] =
+    "blue_dot_promo_settings_dismissed";
 #endif  // BUILDFLAG(IS_IOS)
 
 #if BUILDFLAG(IS_ANDROID)
diff --git a/components/feature_engagement/public/event_constants.h b/components/feature_engagement/public/event_constants.h
index eebae89..3fa5688 100644
--- a/components/feature_engagement/public/event_constants.h
+++ b/components/feature_engagement/public/event_constants.h
@@ -123,6 +123,33 @@
 // without taking an action.
 extern const char kOverflowMenuNoHorizontalScrollOrAction[];
 
+// The user has been shown a default browser promo.
+extern const char kDefaultBrowserPromoShown[];
+
+// The user has taken an action that is a criterion towards becoming eligible to
+// be shown the blue dot default browser promo.
+extern const char kBlueDotPromoCriterionMet[];
+
+// The user has met all criteria and has become eligible to be shown the blue
+// dot default browser promo.
+extern const char kBlueDotPromoEligibilityMet[];
+
+// The user has been shown the blue dot default browser promo on the overflow
+// carousel.
+extern const char kBlueDotPromoOverflowMenuShown[];
+
+// The user has been shown the blue dot default browser promo on the settings
+// row.
+extern const char kBlueDotPromoSettingsShown[];
+
+// The user has dismissed the blue dot default browser promo on the overflow
+// carousel.
+extern const char kBlueDotPromoOverflowMenuDismissed[];
+
+// The user has dismissed the blue dot default browser promo on the settings
+// row.
+extern const char kBlueDotPromoSettingsDismissed[];
+
 #endif  // BUILDFLAG(IS_IOS)
 
 // Android.
diff --git a/components/feature_engagement/public/feature_configurations.cc b/components/feature_engagement/public/feature_configurations.cc
index 93b259f..20a44ed 100644
--- a/components/feature_engagement/public/feature_configurations.cc
+++ b/components/feature_engagement/public/feature_configurations.cc
@@ -1099,6 +1099,71 @@
         EventConfig("price_notifications_used", Comparator(EQUAL, 0), 7, 7);
     return config;
   }
+
+  if (kIPHiOSDefaultBrowserBadgeEligibilityFeature.name == feature->name) {
+    // A config for a shadow feature that is used to activate two other features
+    // (kIPHiOSDefaultBrowserOverflowMenuBadgeFeature and
+    // kIPHiOSDefaultBrowserSettingsBadgeFeature) which will enable a blue
+    // notification badge to be shown to users at two different locations to
+    // help bring their attention to the default browser settings page.
+
+    absl::optional<FeatureConfig> config = FeatureConfig();
+    config->valid = true;
+    config->availability = Comparator(ANY, 0);
+    config->session_rate = Comparator(EQUAL, 0);
+    config->trigger = EventConfig("blue_dot_promo_eligibility_met",
+                                  Comparator(EQUAL, 0), 360, 360);
+    config->used = EventConfig("blue_dot_promo_criterion_met",
+                               Comparator(GREATER_THAN_OR_EQUAL, 1), 30, 360);
+    config->event_configs.insert(EventConfig("default_browser_promo_shown",
+                                             Comparator(EQUAL, 0), 30, 360));
+    return config;
+  }
+
+  if (kIPHiOSDefaultBrowserOverflowMenuBadgeFeature.name == feature->name) {
+    // A config to allow a user to be shown the blue dot promo on the carousel.
+    // It depends on kIPHiOSDefaultBrowserBadgeEligibilityFeature to have deemed
+    // users eligible, and adds more constraints to decide when to stop showing
+    // the promo to the user.
+
+    absl::optional<FeatureConfig> config = FeatureConfig();
+    config->valid = true;
+    config->availability = Comparator(ANY, 0);
+    config->session_rate = Comparator(ANY, 0);
+    config->used = EventConfig("blue_dot_promo_overflow_menu_dismissed",
+                               Comparator(EQUAL, 0), 30, 360);
+    config->trigger = EventConfig("blue_dot_promo_overflow_menu_shown",
+                                  Comparator(LESS_THAN_OR_EQUAL, 2), 360, 360);
+    config->event_configs.insert(
+        EventConfig("blue_dot_promo_eligibility_met",
+                    Comparator(GREATER_THAN_OR_EQUAL, 1), 30, 360));
+    config->event_configs.insert(EventConfig("default_browser_promo_shown",
+                                             Comparator(EQUAL, 0), 30, 360));
+    return config;
+  }
+
+  if (kIPHiOSDefaultBrowserSettingsBadgeFeature.name == feature->name) {
+    // A config to allow a user to be shown the blue dot promo in the default
+    // browser settings row item. It depends on
+    // kIPHiOSDefaultBrowserBadgeEligibilityFeature to have deemed users
+    // eligible, and adds more constraints to decide when to stop showing the
+    // promo.
+
+    absl::optional<FeatureConfig> config = FeatureConfig();
+    config->valid = true;
+    config->availability = Comparator(ANY, 0);
+    config->session_rate = Comparator(ANY, 0);
+    config->used = EventConfig("blue_dot_promo_settings_dismissed",
+                               Comparator(EQUAL, 0), 30, 360);
+    config->trigger = EventConfig("blue_dot_promo_settings_shown",
+                                  Comparator(LESS_THAN_OR_EQUAL, 2), 360, 360);
+    config->event_configs.insert(
+        EventConfig("blue_dot_promo_eligibility_met",
+                    Comparator(GREATER_THAN_OR_EQUAL, 1), 30, 360));
+    config->event_configs.insert(EventConfig("default_browser_promo_shown",
+                                             Comparator(EQUAL, 0), 30, 360));
+    return config;
+  }
 #endif  // BUILDFLAG(IS_IOS)
 
   if (kIPHDummyFeature.name == feature->name) {
diff --git a/components/feature_engagement/public/feature_constants.cc b/components/feature_engagement/public/feature_constants.cc
index 5116bfef..2e0e4a59 100644
--- a/components/feature_engagement/public/feature_constants.cc
+++ b/components/feature_engagement/public/feature_constants.cc
@@ -418,6 +418,15 @@
 BASE_FEATURE(kIPHPriceNotificationsWhileBrowsingFeature,
              "IPH_PriceNotificationsWhileBrowsing",
              base::FEATURE_DISABLED_BY_DEFAULT);
+BASE_FEATURE(kIPHiOSDefaultBrowserBadgeEligibilityFeature,
+             "IPH_iOSDefaultBrowserBadgeEligibility",
+             base::FEATURE_ENABLED_BY_DEFAULT);
+BASE_FEATURE(kIPHiOSDefaultBrowserOverflowMenuBadgeFeature,
+             "IPH_iOSDefaultBrowserOverflowMenuBadge",
+             base::FEATURE_ENABLED_BY_DEFAULT);
+BASE_FEATURE(kIPHiOSDefaultBrowserSettingsBadgeFeature,
+             "IPH_iOSDefaultBrowserSettingsBadge",
+             base::FEATURE_ENABLED_BY_DEFAULT);
 #endif  // BUILDFLAG(IS_IOS)
 
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \
diff --git a/components/feature_engagement/public/feature_constants.h b/components/feature_engagement/public/feature_constants.h
index 9c4c9c8..68b6914 100644
--- a/components/feature_engagement/public/feature_constants.h
+++ b/components/feature_engagement/public/feature_constants.h
@@ -177,6 +177,9 @@
 BASE_DECLARE_FEATURE(kIPHFollowWhileBrowsingFeature);
 BASE_DECLARE_FEATURE(kIPHOverflowMenuTipFeature);
 BASE_DECLARE_FEATURE(kIPHPriceNotificationsWhileBrowsingFeature);
+BASE_DECLARE_FEATURE(kIPHiOSDefaultBrowserBadgeEligibilityFeature);
+BASE_DECLARE_FEATURE(kIPHiOSDefaultBrowserOverflowMenuBadgeFeature);
+BASE_DECLARE_FEATURE(kIPHiOSDefaultBrowserSettingsBadgeFeature);
 #endif  // BUILDFLAG(IS_IOS)
 
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \
diff --git a/components/feature_engagement/public/feature_list.cc b/components/feature_engagement/public/feature_list.cc
index 6b3134c..9b0a9c7 100644
--- a/components/feature_engagement/public/feature_list.cc
+++ b/components/feature_engagement/public/feature_list.cc
@@ -120,6 +120,9 @@
     &kIPHFollowWhileBrowsingFeature,
     &kIPHOverflowMenuTipFeature,
     &kIPHPriceNotificationsWhileBrowsingFeature,
+    &kIPHiOSDefaultBrowserBadgeEligibilityFeature,
+    &kIPHiOSDefaultBrowserOverflowMenuBadgeFeature,
+    &kIPHiOSDefaultBrowserSettingsBadgeFeature,
 #endif  // BUILDFLAG(IS_IOS)
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \
     BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA)
diff --git a/components/feature_engagement/public/feature_list.h b/components/feature_engagement/public/feature_list.h
index dd574b8..8ad4360 100644
--- a/components/feature_engagement/public/feature_list.h
+++ b/components/feature_engagement/public/feature_list.h
@@ -219,6 +219,12 @@
 DEFINE_VARIATION_PARAM(kIPHOverflowMenuTipFeature, "IPH_OverflowMenuTip");
 DEFINE_VARIATION_PARAM(kIPHPriceNotificationsWhileBrowsingFeature,
                        "IPHPriceNotificationsWhileBrowsing");
+DEFINE_VARIATION_PARAM(kIPHiOSDefaultBrowserBadgeEligibilityFeature,
+                       "IPH_iOSDefaultBrowserBadgeEligibility");
+DEFINE_VARIATION_PARAM(kIPHiOSDefaultBrowserOverflowMenuBadgeFeature,
+                       "IPH_iOSDefaultBrowserOverflowMenuBadge");
+DEFINE_VARIATION_PARAM(kIPHiOSDefaultBrowserSettingsBadgeFeature,
+                       "IPH_iOSDefaultBrowserSettingsBadge");
 #endif  // BUILDFLAG(IS_IOS)
 
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \
@@ -380,6 +386,9 @@
         VARIATION_ENTRY(kIPHFollowWhileBrowsingFeature),
         VARIATION_ENTRY(kIPHOverflowMenuTipFeature),
         VARIATION_ENTRY(kIPHPriceNotificationsWhileBrowsingFeature),
+        VARIATION_ENTRY(kIPHiOSDefaultBrowserBadgeEligibilityFeature),
+        VARIATION_ENTRY(kIPHiOSDefaultBrowserOverflowMenuBadgeFeature),
+        VARIATION_ENTRY(kIPHiOSDefaultBrowserSettingsBadgeFeature),
 #elif BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
     BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA)
         VARIATION_ENTRY(kIPHBatterySaverModeFeature),
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc
index 41e0e11..650602f 100644
--- a/components/history/core/browser/history_backend.cc
+++ b/components/history/core/browser/history_backend.cc
@@ -407,7 +407,7 @@
         db_->MayContainForeignVisits()) {
       // If the History Sync data type is disabled, but there are foreign visits
       // left (because it was previously enabled), then clean them up now.
-      DeleteAllForeignVisits();
+      DeleteAllForeignVisitsAndResetIsKnownToSync();
     } else if (db_->GetDeleteForeignVisitsUntilId() != kInvalidVisitID) {
       // A deletion of foreign visits was still ongoing during the previous
       // browser shutdown. Continue it.
@@ -777,6 +777,24 @@
   }
 }
 
+void HistoryBackend::MarkVisitAsKnownToSync(VisitID visit_id) {
+  if (!db_) {
+    return;
+  }
+
+  VisitRow visit_row;
+  if (db_->GetRowForVisit(visit_id, &visit_row)) {
+    visit_row.is_known_to_sync = true;
+
+    if (db_->UpdateVisitRow(visit_row)) {
+      db_->SetKnownToSyncVisitsExist(true);
+    }
+
+    // Purposely don't call `NotifyVisitUpdated()` here, because this change
+    // itself is de minimis and triggered by the sync history backend observer.
+  }
+}
+
 bool HistoryBackend::IsUntypedIntranetHost(const GURL& url) {
   if (!url.SchemeIs(url::kHttpScheme) && !url.SchemeIs(url::kHttpsScheme) &&
       !url.SchemeIs(url::kFtpScheme))
@@ -1668,39 +1686,44 @@
   return db_->UpdateVisitRow(row);
 }
 
-bool HistoryBackend::DeleteAllForeignVisits() {
+void HistoryBackend::DeleteAllForeignVisitsAndResetIsKnownToSync() {
   if (!db_)
-    return false;
+    return;
 
-  if (!db_->MayContainForeignVisits()) {
-    // The DB doesn't contain any foreign visits, or all the foreign visits are
-    // already scheduled for deletion - nothing to do.
-    return true;
+  if (db_->KnownToSyncVisitsExist()) {
+    db_->SetKnownToSyncVisitsExist(false);
+    // It might be bad performance that we do a full table scan setting a bit
+    // right before we delete all the foreign visits. In practice, I bet it
+    // doesn't matter, since sync turnoffs are rare, and sequencing this after
+    // completing the foreign visit deletion adds code complexity.
+    db_->SetAllVisitsAsNotKnownToSync();
   }
 
-  bool already_running =
-      db_->GetDeleteForeignVisitsUntilId() != kInvalidVisitID;
+  // Skip this if the DB doesn't contain any foreign visits, or all the foreign
+  // visits are already scheduled for deletion - nothing to do.
+  if (db_->MayContainForeignVisits()) {
+    bool already_running =
+        db_->GetDeleteForeignVisitsUntilId() != kInvalidVisitID;
 
-  // Set the max-foreign-visit-to-delete to the current max visit ID in the DB.
-  // This ensures that any visits added in the future (after the
-  // DeleteAllForeignVisits() call) will not be affected. (This matters if Sync
-  // gets enabled again, and starts adding foreign visits again, before the
-  // deletion process has completed.)
-  VisitID max_visit_to_delete = db_->GetMaxVisitIDInUse();
-  db_->SetDeleteForeignVisitsUntilId(max_visit_to_delete);
-  // Already set the "may contain foreign visits" bit to false, since all the
-  // existing foreign visits are about to be deleted. This ensures that the bit
-  // can be safely set to true again if new foreign visits are added, even
-  // before the deletion completes.
-  db_->SetMayContainForeignVisits(false);
+    // Set the max-foreign-visit-to-delete to the current max visit ID in the
+    // DB. This ensures that any visits added in the future (after the
+    // DeleteAllForeignVisits() call) will not be affected. (This matters if
+    // Sync gets enabled again, and starts adding foreign visits again, before
+    // the deletion process has completed.)
+    VisitID max_visit_to_delete = db_->GetMaxVisitIDInUse();
+    db_->SetDeleteForeignVisitsUntilId(max_visit_to_delete);
+    // Already set the "may contain foreign visits" bit to false, since all the
+    // existing foreign visits are about to be deleted. This ensures that the
+    // bit can be safely set to true again if new foreign visits are added, even
+    // before the deletion completes.
+    db_->SetMayContainForeignVisits(false);
 
-  // Only schedule a deletion task if there isn't one already running. If there
-  // is one already running, it'll pick up the new limit automatically.
-  if (!already_running) {
-    StartDeletingForeignVisits();
+    // Only schedule a deletion task if there isn't one already running. If
+    // there is one already running, it'll pick up the new limit automatically.
+    if (!already_running) {
+      StartDeletingForeignVisits();
+    }
   }
-
-  return true;
 }
 
 bool HistoryBackend::RemoveVisits(const VisitVector& visits) {
diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h
index 88c0451..bf4281e 100644
--- a/components/history/core/browser/history_backend.h
+++ b/components/history/core/browser/history_backend.h
@@ -631,7 +631,9 @@
   // Even though the process is async, only visits that already exist at the
   // time this is called will be deleted. Visits added afterwards will *not* be
   // deleted.
-  bool DeleteAllForeignVisits() override;
+  // This method also resets the `is_known_to_sync` bit for all visits, local
+  // and foreign.
+  void DeleteAllForeignVisitsAndResetIsKnownToSync() override;
 
   bool RemoveVisits(const VisitVector& visits);
 
@@ -813,6 +815,9 @@
   // Updates the visit_duration information in visits table.
   void UpdateVisitDuration(VisitID visit_id, const base::Time end_ts);
 
+  // Flags this visit's `is_known_to_sync` true.
+  void MarkVisitAsKnownToSync(VisitID visit_id) override;
+
   // Returns whether `url` is on an untyped intranet host.
   bool IsUntypedIntranetHost(const GURL& url);
 
diff --git a/components/history/core/browser/history_backend_unittest.cc b/components/history/core/browser/history_backend_unittest.cc
index 41ff680..fff4564 100644
--- a/components/history/core/browser/history_backend_unittest.cc
+++ b/components/history/core/browser/history_backend_unittest.cc
@@ -170,6 +170,7 @@
   using HistoryBackend::DeleteAllHistory;
   using HistoryBackend::DeleteFTSIndexDatabases;
   using HistoryBackend::HistoryBackend;
+  using HistoryBackend::MarkVisitAsKnownToSync;
   using HistoryBackend::UpdateVisitDuration;
 
   using HistoryBackend::db_;
@@ -2842,6 +2843,31 @@
   ASSERT_TRUE(backend_->RemoveVisits(visits1));
 }
 
+TEST_F(HistoryBackendTest, MarkVisitAsKnownToSync) {
+  // This unit test will test adding and deleting visit details information.
+  ASSERT_TRUE(backend_.get());
+
+  GURL url1("http://www.cnn.com");
+  std::vector<VisitInfo> visit_info1;
+  base::Time start_ts = base::Time::Now() - base::Days(5);
+  visit_info1.emplace_back(start_ts, ui::PAGE_TRANSITION_LINK);
+
+  // Add the visit and verify it doesn't start as being known to sync.
+  backend_->AddVisits(url1, visit_info1, SOURCE_BROWSED);
+  VisitVector visits1;
+  URLRow row;
+  URLID url_id1 = backend_->db()->GetRowForURL(url1, &row);
+  ASSERT_TRUE(backend_->db()->GetVisitsForURL(url_id1, &visits1));
+  ASSERT_EQ(1U, visits1.size());
+  EXPECT_FALSE(visits1[0].is_known_to_sync);
+
+  // Mark that visit as being known to sync, and read it back.
+  backend_->MarkVisitAsKnownToSync(visits1[0].visit_id);
+  ASSERT_TRUE(backend_->db()->GetVisitsForURL(url_id1, &visits1));
+  ASSERT_EQ(1U, visits1.size());
+  EXPECT_TRUE(visits1[0].is_known_to_sync);
+}
+
 // Test for migration of adding visit_duration column.
 TEST_F(HistoryBackendTest, MigrationVisitDuration) {
   ASSERT_TRUE(backend_.get());
@@ -4380,7 +4406,7 @@
   }
 
   // Main test body: Instruct backend to delete foreign visits.
-  backend_->DeleteAllForeignVisits();
+  backend_->DeleteAllForeignVisitsAndResetIsKnownToSync();
   // The deletions happens asynchronously, so wait for it to complete.
   task_environment_.RunUntilIdle();
 
@@ -4429,7 +4455,7 @@
   }
 
   // Instruct the backend to delete foreign visits.
-  backend_->DeleteAllForeignVisits();
+  backend_->DeleteAllForeignVisitsAndResetIsKnownToSync();
 
   // Wait for the deletions to happen.
   task_environment_.RunUntilIdle();
@@ -4473,7 +4499,7 @@
   }
 
   // Instruct the backend to delete foreign visits.
-  backend_->DeleteAllForeignVisits();
+  backend_->DeleteAllForeignVisitsAndResetIsKnownToSync();
 
   // Before the actual (async) deletion happens, add some more foreign visits.
   // These should *not* be affected by the previous DeleteAllForeignVisits()
@@ -4509,4 +4535,64 @@
   }
 }
 
+TEST_F(HistoryBackendTest, DeleteAllForeignVisitsResetsIsKnownToSyncFlag) {
+  const ui::PageTransition kLink = ui::PageTransitionFromInt(
+      ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CHAIN_START |
+      ui::PAGE_TRANSITION_CHAIN_END);
+
+  const base::Time initial_time = base::Time::Now();
+
+  // Setup: Add two local visits.
+  VisitID local_visit_id1 =
+      backend_
+          ->AddPageVisit(GURL("https://local1.url"), base::Time::Now(),
+                         /*referring_visit=*/kInvalidVisitID, kLink,
+                         /*hidden=*/false, SOURCE_BROWSED,
+                         /*should_increment_typed_count=*/false,
+                         /*opener_visit=*/kInvalidVisitID)
+          .second;
+
+  task_environment_.FastForwardBy(base::Seconds(1));
+
+  // Modify local visit 2 to have `is_known_to_sync` as true.
+  VisitID local_visit_id2 =
+      backend_
+          ->AddPageVisit(GURL("https://local2.url"), base::Time::Now(),
+                         /*referring_visit=*/kInvalidVisitID, kLink,
+                         /*hidden=*/false, SOURCE_BROWSED,
+                         /*should_increment_typed_count=*/false,
+                         /*opener_visit=*/kInvalidVisitID)
+          .second;
+  backend_->MarkVisitAsKnownToSync(local_visit_id2);
+
+  task_environment_.FastForwardBy(base::Seconds(1));
+
+  // Setup finished - verify that the visits exist, and one is known to sync.
+  {
+    VisitVector visits;
+    backend_->db()->GetAllVisitsInRange(initial_time, base::Time::Now(),
+                                        /*max_results=*/5, &visits);
+    ASSERT_THAT(visits, ElementsAre(HasVisitID(local_visit_id1),
+                                    HasVisitID(local_visit_id2)));
+    ASSERT_FALSE(visits[0].is_known_to_sync);
+    ASSERT_TRUE(visits[1].is_known_to_sync);
+  }
+
+  // Main test body: Instruct backend to reset all `is_known_to_sync` flags.
+  backend_->DeleteAllForeignVisitsAndResetIsKnownToSync();
+  // The deletions happens asynchronously, so wait for it to complete.
+  task_environment_.RunUntilIdle();
+
+  // Make sure the local visits are now no longer known to sync.
+  {
+    VisitVector visits;
+    backend_->db()->GetAllVisitsInRange(initial_time, base::Time::Now(),
+                                        /*max_results=*/5, &visits);
+    ASSERT_THAT(visits, ElementsAre(HasVisitID(local_visit_id1),
+                                    HasVisitID(local_visit_id2)));
+    EXPECT_FALSE(visits[0].is_known_to_sync);
+    EXPECT_FALSE(visits[1].is_known_to_sync);
+  }
+}
+
 }  // namespace history
diff --git a/components/history/core/browser/history_database.cc b/components/history/core/browser/history_database.cc
index 4fb936d..96be8968 100644
--- a/components/history/core/browser/history_database.cc
+++ b/components/history/core/browser/history_database.cc
@@ -44,6 +44,7 @@
 const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold";
 const char kMayContainForeignVisits[] = "may_contain_foreign_visits";
 const char kDeleteForeignVisitsUntilId[] = "delete_foreign_visits_until_id";
+const char kKnownToSyncVisitsExist[] = "known_to_sync_visits_exist";
 
 // Logs a migration failure to UMA and logging. The return value will be
 // what to return from ::Init (to simplify the call sites). Migration failures
@@ -471,6 +472,16 @@
   meta_table_.SetValue(kDeleteForeignVisitsUntilId, visit_id);
 }
 
+bool HistoryDatabase::KnownToSyncVisitsExist() {
+  int result = false;
+  meta_table_.GetValue(kKnownToSyncVisitsExist, &result);
+  return result != 0;
+}
+
+void HistoryDatabase::SetKnownToSyncVisitsExist(bool exist) {
+  meta_table_.SetValue(kKnownToSyncVisitsExist, exist ? 1 : 0);
+}
+
 TypedURLSyncMetadataDatabase* HistoryDatabase::GetTypedURLMetadataDB() {
   return &typed_url_metadata_db_;
 }
diff --git a/components/history/core/browser/history_database.h b/components/history/core/browser/history_database.h
index d0d1156..d557ced 100644
--- a/components/history/core/browser/history_database.h
+++ b/components/history/core/browser/history_database.h
@@ -180,6 +180,13 @@
   VisitID GetDeleteForeignVisitsUntilId();
   void SetDeleteForeignVisitsUntilId(VisitID visit_id);
 
+  // Retrieves/updates the bit that indicates whether the DB may contain any
+  // visits known to sync.
+  // TODO(crbug.com/1365291): After syncer::HISTORY has launched, consider
+  // whether this bit is still required.
+  bool KnownToSyncVisitsExist();
+  void SetKnownToSyncVisitsExist(bool exist);
+
   // Sync metadata storage ----------------------------------------------------
 
   // Returns the sub-database used for storing Sync metadata for Typed URLs.
diff --git a/components/history/core/browser/sync/history_backend_for_sync.h b/components/history/core/browser/sync/history_backend_for_sync.h
index 03864b13..797f677 100644
--- a/components/history/core/browser/sync/history_backend_for_sync.h
+++ b/components/history/core/browser/sync/history_backend_for_sync.h
@@ -59,7 +59,8 @@
 
   virtual std::vector<GURL> GetFaviconURLsForURL(const GURL& page_url) = 0;
 
-  virtual bool DeleteAllForeignVisits() = 0;
+  virtual void MarkVisitAsKnownToSync(VisitID visit_id) = 0;
+  virtual void DeleteAllForeignVisitsAndResetIsKnownToSync() = 0;
 
   virtual void AddObserver(HistoryBackendObserver* observer) = 0;
   virtual void RemoveObserver(HistoryBackendObserver* observer) = 0;
diff --git a/components/history/core/browser/sync/history_sync_bridge.cc b/components/history/core/browser/sync/history_sync_bridge.cc
index c5bb2ee9..03d2f648 100644
--- a/components/history/core/browser/sync/history_sync_bridge.cc
+++ b/components/history/core/browser/sync/history_sync_bridge.cc
@@ -607,7 +607,7 @@
   if (delete_metadata_change_list) {
     // A non-null `delete_metadata_change_list` indicates that Sync is being
     // turned off only permanently. Delete all foreign visits from the DB.
-    history_backend_->DeleteAllForeignVisits();
+    history_backend_->DeleteAllForeignVisitsAndResetIsKnownToSync();
   }
 
   ModelTypeSyncBridge::ApplyStopSyncChanges(
@@ -810,9 +810,9 @@
   // is a workaround to still clear foreign history in that case. Remove once
   // that bug is fixed.
   if (sync_transport_state_ == syncer::SyncService::TransportState::DISABLED) {
-    // DeleteAllForeignVisits() is cheap if there is no foreign history in the
-    // DB, so it's okay to call this somewhat too often.
-    history_backend_->DeleteAllForeignVisits();
+    // This is cheap if there is no foreign history in the DB, so it's okay to
+    // call this somewhat too often.
+    history_backend_->DeleteAllForeignVisitsAndResetIsKnownToSync();
   }
 }
 
diff --git a/components/history/core/browser/sync/test_history_backend_for_sync.cc b/components/history/core/browser/sync/test_history_backend_for_sync.cc
index 3490638..88b85c8 100644
--- a/components/history/core/browser/sync/test_history_backend_for_sync.cc
+++ b/components/history/core/browser/sync/test_history_backend_for_sync.cc
@@ -289,11 +289,22 @@
   return {};
 }
 
-bool TestHistoryBackendForSync::DeleteAllForeignVisits() {
+void TestHistoryBackendForSync::MarkVisitAsKnownToSync(VisitID visit_id) {
+  for (auto& visit : visits_) {
+    if (visit.visit_id == visit_id) {
+      // This persists into the vector because we're operating on a reference.
+      visit.is_known_to_sync = true;
+    }
+  }
+}
+
+void TestHistoryBackendForSync::DeleteAllForeignVisitsAndResetIsKnownToSync() {
   ++delete_all_foreign_visits_call_count_;
 
   for (auto it = visits_.begin(); it != visits_.end();) {
-    const VisitRow& visit = *it;
+    VisitRow& visit = *it;
+    visit.is_known_to_sync = false;
+
     if (visit.originator_cache_guid.empty()) {
       // Local visit, leave it.
       ++it;
@@ -308,7 +319,6 @@
       // but currently isn't necessary for the unit tests that use this class.
     }
   }
-  return true;
 }
 
 void TestHistoryBackendForSync::AddObserver(HistoryBackendObserver* observer) {
diff --git a/components/history/core/browser/sync/test_history_backend_for_sync.h b/components/history/core/browser/sync/test_history_backend_for_sync.h
index 770cd067..03a0c312 100644
--- a/components/history/core/browser/sync/test_history_backend_for_sync.h
+++ b/components/history/core/browser/sync/test_history_backend_for_sync.h
@@ -70,7 +70,8 @@
                                     VisitID referrer_id,
                                     VisitID opener_id) override;
   std::vector<GURL> GetFaviconURLsForURL(const GURL& page_url) override;
-  bool DeleteAllForeignVisits() override;
+  void MarkVisitAsKnownToSync(VisitID visit_id) override;
+  void DeleteAllForeignVisitsAndResetIsKnownToSync() override;
   void AddObserver(HistoryBackendObserver* observer) override;
   void RemoveObserver(HistoryBackendObserver* observer) override;
 
diff --git a/components/history/core/browser/visit_database.cc b/components/history/core/browser/visit_database.cc
index 54d5178..9cdd157e 100644
--- a/components/history/core/browser/visit_database.cc
+++ b/components/history/core/browser/visit_database.cc
@@ -465,6 +465,12 @@
   return statement.Run();
 }
 
+bool VisitDatabase::SetAllVisitsAsNotKnownToSync() {
+  sql::Statement statement(
+      GetDB().GetUniqueStatement("UPDATE visits SET is_known_to_sync=0"));
+  return statement.Run();
+}
+
 bool VisitDatabase::GetVisitsForURL(URLID url_id, VisitVector* visits) {
   visits->clear();
 
diff --git a/components/history/core/browser/visit_database.h b/components/history/core/browser/visit_database.h
index e65537d..5ea0d8a 100644
--- a/components/history/core/browser/visit_database.h
+++ b/components/history/core/browser/visit_database.h
@@ -72,6 +72,12 @@
   // VisitID as the key. The visit must exist. Returns true on success.
   bool UpdateVisitRow(const VisitRow& visit);
 
+  // Marks ALL visits as NOT known to sync. This is called when Sync is turned
+  // off by the user or disabled via feature flag. Visits can be marked as known
+  // to sync again when Sync is re-enabled. This is used to flag which visits
+  // have permission to fetch URL-keyed metadata.
+  bool SetAllVisitsAsNotKnownToSync();
+
   // Fills in the given vector with all of the visits for the given page ID,
   // sorted in ascending order of date. Returns true on success (although there
   // may still be no matches).
diff --git a/components/history/core/browser/visit_database_unittest.cc b/components/history/core/browser/visit_database_unittest.cc
index 39f1dae..f028f1c 100644
--- a/components/history/core/browser/visit_database_unittest.cc
+++ b/components/history/core/browser/visit_database_unittest.cc
@@ -161,6 +161,59 @@
   EXPECT_TRUE(IsVisitInfoEqual(modification, final));
 }
 
+TEST_F(VisitDatabaseTest, IsKnownToSync) {
+  // Insert three rows, VisitIDs 1, 2, and 3.
+  for (VisitID i = 1; i <= 3; i++) {
+    VisitRow original(i, Time::Now(), 23, ui::PageTransitionFromInt(0), 19,
+                      false, 0);
+    AddVisit(&original, SOURCE_BROWSED);
+    ASSERT_EQ(i, original.visit_id);  // Verifies that we added 1, 2, and 3
+  }
+
+  // Set 2 and 3 to be `is_known_to_sync`.
+  {
+    VisitRow visit2;
+    ASSERT_TRUE(GetRowForVisit(2, &visit2));
+    EXPECT_FALSE(visit2.is_known_to_sync);
+    visit2.is_known_to_sync = true;
+    ASSERT_TRUE(UpdateVisitRow(visit2));
+
+    VisitRow visit3;
+    ASSERT_TRUE(GetRowForVisit(3, &visit3));
+    EXPECT_FALSE(visit3.is_known_to_sync);
+    visit3.is_known_to_sync = true;
+    ASSERT_TRUE(UpdateVisitRow(visit3));
+  }
+
+  // Verify the new expected values for all visits.
+  {
+    VisitRow visit1;
+    ASSERT_TRUE(GetRowForVisit(1, &visit1));
+    EXPECT_FALSE(visit1.is_known_to_sync);
+    VisitRow visit2;
+    ASSERT_TRUE(GetRowForVisit(2, &visit2));
+    EXPECT_TRUE(visit2.is_known_to_sync);
+    VisitRow visit3;
+    ASSERT_TRUE(GetRowForVisit(3, &visit3));
+    EXPECT_TRUE(visit3.is_known_to_sync);
+  }
+
+  // Now clear out all `is_known_to_sync` bits and verify that worked.
+  {
+    SetAllVisitsAsNotKnownToSync();
+
+    VisitRow visit1;
+    ASSERT_TRUE(GetRowForVisit(2, &visit1));
+    EXPECT_FALSE(visit1.is_known_to_sync);
+    VisitRow visit2;
+    ASSERT_TRUE(GetRowForVisit(2, &visit2));
+    EXPECT_FALSE(visit2.is_known_to_sync);
+    VisitRow visit3;
+    ASSERT_TRUE(GetRowForVisit(3, &visit3));
+    EXPECT_FALSE(visit3.is_known_to_sync);
+  }
+}
+
 // TODO(brettw) write test for GetMostRecentVisitForURL!
 
 namespace {
diff --git a/components/history_clusters/core/BUILD.gn b/components/history_clusters/core/BUILD.gn
index e157bc6..53840bc 100644
--- a/components/history_clusters/core/BUILD.gn
+++ b/components/history_clusters/core/BUILD.gn
@@ -8,8 +8,6 @@
 
 static_library("core") {
   sources = [
-    "category_cluster_finalizer.cc",
-    "category_cluster_finalizer.h",
     "cluster_finalizer.h",
     "cluster_metrics_utils.cc",
     "cluster_metrics_utils.h",
@@ -98,7 +96,6 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
-    "category_cluster_finalizer_unittest.cc",
     "clusterer_unittest.cc",
     "config_unittest.cc",
     "content_annotations_cluster_processor_unittest.cc",
diff --git a/components/history_clusters/core/category_cluster_finalizer.cc b/components/history_clusters/core/category_cluster_finalizer.cc
deleted file mode 100644
index 3606878..0000000
--- a/components/history_clusters/core/category_cluster_finalizer.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/history_clusters/core/category_cluster_finalizer.h"
-
-#include "components/history/core/browser/history_types.h"
-#include "components/history_clusters/core/cluster_metrics_utils.h"
-#include "components/history_clusters/core/config.h"
-#include "components/history_clusters/core/on_device_clustering_features.h"
-#include "components/history_clusters/core/on_device_clustering_util.h"
-
-namespace history_clusters {
-
-CategoryClusterFinalizer::CategoryClusterFinalizer() = default;
-CategoryClusterFinalizer::~CategoryClusterFinalizer() = default;
-
-void CategoryClusterFinalizer::FinalizeCluster(history::Cluster& cluster) {
-  const base::flat_set<std::string>& categories_for_filtering =
-      GetConfig().categories_for_filtering;
-  size_t interesting_visit_cnt = 0;
-
-  ScopedFilterClusterMetricsRecorder metrics_recorder("Category");
-  for (const auto& visit : cluster.visits) {
-    for (const auto& category : visit.annotated_visit.content_annotations
-                                    .model_annotations.categories) {
-      if (categories_for_filtering.find(category.id) !=
-          categories_for_filtering.end()) {
-        interesting_visit_cnt++;
-        break;
-      }
-    }
-
-    if (interesting_visit_cnt >=
-        GetConfig().number_interesting_visits_filter_threshold) {
-      return;
-    }
-  }
-
-  // If we check all the visits in the cluster and all have categories that are
-  // not representative of Journeys, then it's probably not interesting so we
-  // can hide it.
-  cluster.should_show_on_prominent_ui_surfaces = false;
-  metrics_recorder.set_was_filtered(true);
-}
-
-}  // namespace history_clusters
diff --git a/components/history_clusters/core/category_cluster_finalizer.h b/components/history_clusters/core/category_cluster_finalizer.h
deleted file mode 100644
index cfac610..0000000
--- a/components/history_clusters/core/category_cluster_finalizer.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_HISTORY_CLUSTERS_CORE_CATEGORY_CLUSTER_FINALIZER_H_
-#define COMPONENTS_HISTORY_CLUSTERS_CORE_CATEGORY_CLUSTER_FINALIZER_H_
-
-#include "components/history_clusters/core/cluster_finalizer.h"
-
-namespace history_clusters {
-
-// A ClusterFinalizer that determines whether a cluster represents a complex
-// task or not based on the categories associated with its visits.
-class CategoryClusterFinalizer : public ClusterFinalizer {
- public:
-  explicit CategoryClusterFinalizer();
-  ~CategoryClusterFinalizer() override;
-
-  // ClusterFinalizer:
-  void FinalizeCluster(history::Cluster& cluster) override;
-};
-
-}  // namespace history_clusters
-
-#endif  // COMPONENTS_HISTORY_CLUSTERS_CORE_CATEGORY_CLUSTER_FINALIZER_H_
diff --git a/components/history_clusters/core/category_cluster_finalizer_unittest.cc b/components/history_clusters/core/category_cluster_finalizer_unittest.cc
deleted file mode 100644
index 881b281c..0000000
--- a/components/history_clusters/core/category_cluster_finalizer_unittest.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/history_clusters/core/category_cluster_finalizer.h"
-
-#include "base/test/metrics/histogram_tester.h"
-#include "base/test/task_environment.h"
-#include "components/history_clusters/core/clustering_test_utils.h"
-#include "components/history_clusters/core/config.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace history_clusters {
-namespace {
-
-class CategoryClusterFinalizerTest : public ::testing::Test {
- public:
-  void SetUp() override {
-    cluster_finalizer_ = std::make_unique<CategoryClusterFinalizer>();
-
-    config_.categories_for_filtering = {"verycomplex", "alsocomplex"};
-    config_.number_interesting_visits_filter_threshold = 2;
-    SetConfigForTesting(config_);
-  }
-
-  void TearDown() override { cluster_finalizer_.reset(); }
-
-  void FinalizeCluster(history::Cluster& cluster) {
-    cluster_finalizer_->FinalizeCluster(cluster);
-  }
-
- private:
-  Config config_;
-  std::unique_ptr<CategoryClusterFinalizer> cluster_finalizer_;
-  base::test::TaskEnvironment task_environment_;
-};
-
-TEST_F(CategoryClusterFinalizerTest, FilterOnlyNonInterestingCategories) {
-  base::HistogramTester histogram_tester;
-  history::ClusterVisit visit = testing::CreateClusterVisit(
-      testing::CreateDefaultAnnotatedVisit(1, GURL("https://bar.com/")));
-  visit.annotated_visit.content_annotations.model_annotations.categories
-      .emplace_back("mundane", 80);
-
-  history::ClusterVisit visit2 = testing::CreateClusterVisit(
-      testing::CreateDefaultAnnotatedVisit(2, GURL("https://bar.com/")));
-  visit2.duplicate_visits.emplace_back(
-      testing::ClusterVisitToDuplicateClusterVisit(visit));
-  visit2.annotated_visit.content_annotations.model_annotations.categories
-      .emplace_back("alsomundane", 90);
-
-  history::Cluster cluster;
-  cluster.visits = {visit2};
-  FinalizeCluster(cluster);
-  EXPECT_FALSE(cluster.should_show_on_prominent_ui_surfaces);
-  histogram_tester.ExpectUniqueSample(
-      "History.Clusters.Backend.WasClusterFiltered.Category", true, 1);
-}
-
-TEST_F(CategoryClusterFinalizerTest, HideClusterWithOnlyOneInterestingVisit) {
-  base::HistogramTester histogram_tester;
-  history::ClusterVisit visit = testing::CreateClusterVisit(
-      testing::CreateDefaultAnnotatedVisit(1, GURL("https://bar.com/")));
-  visit.annotated_visit.content_annotations.model_annotations.categories
-      .emplace_back("verycomplex", 80);
-
-  history::ClusterVisit visit2 = testing::CreateClusterVisit(
-      testing::CreateDefaultAnnotatedVisit(2, GURL("https://bar.com/")));
-  visit2.duplicate_visits.emplace_back(
-      testing::ClusterVisitToDuplicateClusterVisit(visit));
-  visit2.annotated_visit.content_annotations.model_annotations.categories
-      .emplace_back("alsomundane", 90);
-
-  history::Cluster cluster;
-  cluster.visits = {visit2};
-  FinalizeCluster(cluster);
-  EXPECT_FALSE(cluster.should_show_on_prominent_ui_surfaces);
-  histogram_tester.ExpectUniqueSample(
-      "History.Clusters.Backend.WasClusterFiltered.Category", true, 1);
-}
-
-TEST_F(CategoryClusterFinalizerTest,
-       KeepClusterWithAtLeastTwoInterestingVisits) {
-  base::HistogramTester histogram_tester;
-  history::ClusterVisit visit = testing::CreateClusterVisit(
-      testing::CreateDefaultAnnotatedVisit(1, GURL("https://bar.com/")));
-  visit.annotated_visit.content_annotations.model_annotations.categories
-      .emplace_back("alsocomplex", 90);
-
-  history::ClusterVisit visit2 = testing::CreateClusterVisit(
-      testing::CreateDefaultAnnotatedVisit(2, GURL("https://bar.com/")));
-  visit2.annotated_visit.content_annotations.model_annotations.categories
-      .emplace_back("verymundane", 80);
-
-  history::ClusterVisit visit3 = testing::CreateClusterVisit(
-      testing::CreateDefaultAnnotatedVisit(3, GURL("https://foo.com/")));
-  visit3.duplicate_visits.emplace_back(
-      testing::ClusterVisitToDuplicateClusterVisit(visit));
-  visit3.annotated_visit.content_annotations.model_annotations.categories
-      .emplace_back("verycomplex", 80);
-
-  history::Cluster cluster;
-  cluster.visits = {visit, visit2, visit3};
-  FinalizeCluster(cluster);
-  EXPECT_TRUE(cluster.should_show_on_prominent_ui_surfaces);
-  histogram_tester.ExpectUniqueSample(
-      "History.Clusters.Backend.WasClusterFiltered.Category", false, 1);
-}
-
-}  // namespace
-}  // namespace history_clusters
diff --git a/components/history_clusters/core/config.cc b/components/history_clusters/core/config.cc
index c484f02..b8339a0 100644
--- a/components/history_clusters/core/config.cc
+++ b/components/history_clusters/core/config.cc
@@ -269,15 +269,6 @@
             number_interesting_visits_filter_threshold);
   }
 
-  // The `kJourneysCategoryFiltering` feature and child params.
-  {
-    should_use_categories_to_filter_on_prominent_ui_surfaces =
-        base::FeatureList::IsEnabled(
-            features::kOnDeviceClusteringCategoryFiltering);
-
-    categories_for_filtering = JourneysCategoryFilteringAllowlist();
-  }
-
   // The `kUseEngagementScoreCache` feature and child params.
   {
     engagement_score_cache_size = GetFieldTrialParamByFeatureAsInt(
@@ -442,23 +433,6 @@
              : base::flat_set<std::string>(blocklist.begin(), blocklist.end());
 }
 
-base::flat_set<std::string> JourneysCategoryFilteringAllowlist() {
-  const base::FeatureParam<std::string> kJourneysCategoryFilteringAllowlist{
-      &features::kOnDeviceClusteringCategoryFiltering,
-      "categories_filtering_allowlist", ""};
-  std::string allowlist_string = kJourneysCategoryFilteringAllowlist.Get();
-  if (allowlist_string.empty())
-    return {};
-
-  auto allowlist = base::SplitString(allowlist_string, ",",
-                                     base::WhitespaceHandling::TRIM_WHITESPACE,
-                                     base::SplitResult::SPLIT_WANT_NONEMPTY);
-
-  return allowlist.empty()
-             ? base::flat_set<std::string>()
-             : base::flat_set<std::string>(allowlist.begin(), allowlist.end());
-}
-
 base::flat_set<std::string> JourneysMidBlocklist() {
   const base::FeatureParam<std::string> kJourneysMidBlocklist{
       &internal::kHistoryClustersKeywordFiltering, "JourneysMidBlocklist", ""};
diff --git a/components/history_clusters/core/config.h b/components/history_clusters/core/config.h
index f82c3a4..a2a0c82 100644
--- a/components/history_clusters/core/config.h
+++ b/components/history_clusters/core/config.h
@@ -269,17 +269,6 @@
   // on the zero state UI).
   size_t number_interesting_visits_filter_threshold = 1;
 
-  // The `kJourneysCategoryFiltering` feature and child params.
-
-  // Whether to determine whether to show/hide clusters on prominent UI surfaces
-  // based on categories annotated for a visit.
-  bool should_use_categories_to_filter_on_prominent_ui_surfaces = false;
-
-  // The category IDs used for filtering. These should represent categories that
-  // are repesentatitive of Journeys that we think the user is likely to want to
-  // re-engage with.
-  base::flat_set<std::string> categories_for_filtering;
-
   // The `kOnDeviceClusteringContentClustering` feature and child params.
 
   // Returns whether content clustering is enabled and
@@ -411,10 +400,6 @@
 // clustering.
 base::flat_set<std::string> JourneysCollectionContentClusteringBlocklist();
 
-// Returns the set of categories that should be used to filter for whether a
-// user is likely to re-engage with a cluster.
-base::flat_set<std::string> JourneysCategoryFilteringAllowlist();
-
 // Returns the set of mids that should be blocked from being used by the
 // clustering backend, particularly for potential keywords used for omnibox
 // triggering.
diff --git a/components/history_clusters/core/on_device_clustering_backend.cc b/components/history_clusters/core/on_device_clustering_backend.cc
index 466742b4..162644c 100644
--- a/components/history_clusters/core/on_device_clustering_backend.cc
+++ b/components/history_clusters/core/on_device_clustering_backend.cc
@@ -16,7 +16,6 @@
 #include "base/task/thread_pool.h"
 #include "base/timer/elapsed_timer.h"
 #include "components/history/core/browser/history_types.h"
-#include "components/history_clusters/core/category_cluster_finalizer.h"
 #include "components/history_clusters/core/config.h"
 #include "components/history_clusters/core/content_annotations_cluster_processor.h"
 #include "components/history_clusters/core/content_visibility_cluster_finalizer.h"
@@ -572,9 +571,6 @@
   if (engagement_score_provider_is_valid) {
     cluster_finalizers.push_back(std::make_unique<NoisyClusterFinalizer>());
   }
-  if (GetConfig().should_use_categories_to_filter_on_prominent_ui_surfaces) {
-    cluster_finalizers.push_back(std::make_unique<CategoryClusterFinalizer>());
-  }
 
   for (auto& cluster : clusters) {
     // Initially set this default to true since the finalizers will only set the
diff --git a/components/history_clusters/core/on_device_clustering_features.cc b/components/history_clusters/core/on_device_clustering_features.cc
index 6cd40e1..62bfc53 100644
--- a/components/history_clusters/core/on_device_clustering_features.cc
+++ b/components/history_clusters/core/on_device_clustering_features.cc
@@ -34,10 +34,6 @@
              "JourneysKeywordFiltering",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
-BASE_FEATURE(kOnDeviceClusteringCategoryFiltering,
-             "JourneysCategoryFiltering",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
 BASE_FEATURE(kOnDeviceClusteringVisitRanking,
              "JourneysOnDeviceClusteringVisitRanking",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/components/history_clusters/core/on_device_clustering_features.h b/components/history_clusters/core/on_device_clustering_features.h
index d72b27b..c508212 100644
--- a/components/history_clusters/core/on_device_clustering_features.h
+++ b/components/history_clusters/core/on_device_clustering_features.h
@@ -29,9 +29,6 @@
 // Specifies how keywords get filtered and added to a cluster.
 BASE_DECLARE_FEATURE(kOnDeviceClusteringKeywordFiltering);
 
-// Specifies how categories get used for filtering.
-BASE_DECLARE_FEATURE(kOnDeviceClusteringCategoryFiltering);
-
 // Specifies how visits within clusters are ranked.
 BASE_DECLARE_FEATURE(kOnDeviceClusteringVisitRanking);
 
diff --git a/components/lookalikes/core/BUILD.gn b/components/lookalikes/core/BUILD.gn
index c4502c71..6b3f610 100644
--- a/components/lookalikes/core/BUILD.gn
+++ b/components/lookalikes/core/BUILD.gn
@@ -12,7 +12,6 @@
     "lookalike_url_util.h",
   ]
   deps = [
-    ":features",
     ":proto",
     ":safety_tips",
     "//base",
@@ -58,7 +57,6 @@
 
   deps = [
     ":core",
-    ":features",
     ":proto",
     ":safety_tips",
     "//components/version_info:channel",
@@ -67,18 +65,6 @@
   ]
 }
 
-component("features") {
-  output_name = "lookalikes_features"
-  defines = [ "IS_LOOKALIKES_FEATURES_IMPL" ]
-
-  sources = [
-    "features.cc",
-    "features.h",
-  ]
-
-  deps = [ "//base" ]
-}
-
 proto_library("proto") {
   sources = [ "safety_tips.proto" ]
 }
diff --git a/components/lookalikes/core/DEPS b/components/lookalikes/core/DEPS
index 9d638c9..923ff4d 100644
--- a/components/lookalikes/core/DEPS
+++ b/components/lookalikes/core/DEPS
@@ -1,8 +1,4 @@
 include_rules = [
-  # This code is shared with ios, so content/ dependencies
-  # should not be introduced.
-  "-content",
-  "-ios/web",
   "+components/safe_browsing/core",
   "+third_party/re2",
   "+url",
diff --git a/components/lookalikes/core/features.cc b/components/lookalikes/core/features.cc
deleted file mode 100644
index 6e23975..0000000
--- a/components/lookalikes/core/features.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/lookalikes/core/features.h"
-
-namespace lookalikes {
-namespace features {
-
-BASE_FEATURE(kDetectComboSquattingLookalikes,
-             "ComboSquattingLookalikes",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
-}  // namespace features
-}  // namespace lookalikes
diff --git a/components/lookalikes/core/features.h b/components/lookalikes/core/features.h
deleted file mode 100644
index 9671e6b..0000000
--- a/components/lookalikes/core/features.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_LOOKALIKES_CORE_FEATURES_H_
-#define COMPONENTS_LOOKALIKES_CORE_FEATURES_H_
-
-#include "base/component_export.h"
-#include "base/feature_list.h"
-
-namespace lookalikes {
-namespace features {
-
-// This feature enables warnings for Combo Squatting heuristic.
-COMPONENT_EXPORT(LOOKALIKES_FEATURES)
-BASE_DECLARE_FEATURE(kDetectComboSquattingLookalikes);
-
-}  // namespace features
-}  // namespace lookalikes
-
-#endif  // COMPONENTS_LOOKALIKES_CORE_FEATURES_H_
diff --git a/components/lookalikes/core/lookalike_url_ui_util.cc b/components/lookalikes/core/lookalike_url_ui_util.cc
index c291d3f..6a26643 100644
--- a/components/lookalikes/core/lookalike_url_ui_util.cc
+++ b/components/lookalikes/core/lookalike_url_ui_util.cc
@@ -12,6 +12,8 @@
 #include "services/metrics/public/cpp/ukm_recorder.h"
 #include "ui/base/l10n/l10n_util.h"
 
+namespace lookalikes {
+
 void RecordUkmForLookalikeUrlBlockingPage(
     ukm::SourceId source_id,
     LookalikeUrlMatchType match_type,
@@ -113,3 +115,5 @@
 
   load_time_data.Set("type", "LOOKALIKE");
 }
+
+}  // namespace lookalikes
diff --git a/components/lookalikes/core/lookalike_url_ui_util.h b/components/lookalikes/core/lookalike_url_ui_util.h
index c49bbf9..4555f5f 100644
--- a/components/lookalikes/core/lookalike_url_ui_util.h
+++ b/components/lookalikes/core/lookalike_url_ui_util.h
@@ -12,6 +12,8 @@
 class Value;
 }  // namespace base
 
+namespace lookalikes {
+
 // Allow easier reporting of UKM when no interstitial is shown.
 void RecordUkmForLookalikeUrlBlockingPage(
     ukm::SourceId source_id,
@@ -34,4 +36,6 @@
 // Values added to get shared interstitial HTML to play nice.
 void PopulateStringsForSharedHTML(base::Value::Dict& load_time_data);
 
+}  // namespace lookalikes
+
 #endif  // COMPONENTS_LOOKALIKES_CORE_LOOKALIKE_URL_UI_UTIL_H_
diff --git a/components/lookalikes/core/lookalike_url_util.cc b/components/lookalikes/core/lookalike_url_util.cc
index 821aa26..e9e8fec 100644
--- a/components/lookalikes/core/lookalike_url_util.cc
+++ b/components/lookalikes/core/lookalike_url_util.cc
@@ -30,28 +30,15 @@
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/base/url_util.h"
 
-namespace lookalikes {
-
-const char kHistogramName[] = "NavigationSuggestion.Event2";
-
-void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
-  registry->RegisterListPref(prefs::kLookalikeWarningAllowlistDomains);
-}
-
-std::string GetConsoleMessage(const GURL& lookalike_url,
-                              bool is_new_heuristic) {
-  const char* const kNewHeuristicMessage =
-      "Future Chrome versions will show a warning on this domain name.\n";
-  return base::StringPrintf(
-      "Chrome has determined that %s could be fake or fraudulent.\n\n"
-      "%s"
-      "If you believe this is shown in error please visit "
-      "https://g.co/chrome/lookalike-warnings",
-      lookalike_url.host().c_str(),
-      is_new_heuristic ? kNewHeuristicMessage : "");
-}
-
-}  // namespace lookalikes
+using lookalikes::ComboSquattingParams;
+using lookalikes::DomainInfo;
+using lookalikes::GetDomainInfo;
+using lookalikes::HasOneCharacterSwap;
+using lookalikes::IsEditDistanceAtMostOne;
+using lookalikes::LookalikeTargetAllowlistChecker;
+using lookalikes::LookalikeUrlMatchType;
+using lookalikes::NavigationSuggestionEvent;
+using lookalikes::Top500DomainsParams;
 
 namespace {
 
@@ -352,7 +339,7 @@
 }
 
 void RecordEvent(NavigationSuggestionEvent event) {
-  UMA_HISTOGRAM_ENUMERATION(lookalikes::kHistogramName, event);
+  UMA_HISTOGRAM_ENUMERATION(lookalikes::kInterstitialHistogramName, event);
 }
 
 // Returns the parts of the domain that are separated by "." or "-", not
@@ -727,6 +714,27 @@
 
 }  // namespace
 
+namespace lookalikes {
+
+const char kInterstitialHistogramName[] = "NavigationSuggestion.Event2";
+
+void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
+  registry->RegisterListPref(prefs::kLookalikeWarningAllowlistDomains);
+}
+
+std::string GetConsoleMessage(const GURL& lookalike_url,
+                              bool is_new_heuristic) {
+  const char* const kNewHeuristicMessage =
+      "Future Chrome versions will show a warning on this domain name.\n";
+  return base::StringPrintf(
+      "Chrome has determined that %s could be fake or fraudulent.\n\n"
+      "%s"
+      "If you believe this is shown in error please visit "
+      "https://g.co/chrome/lookalike-warnings",
+      lookalike_url.host().c_str(),
+      is_new_heuristic ? kNewHeuristicMessage : "");
+}
+
 DomainInfo::DomainInfo(
     const std::string& arg_hostname,
     const std::string& arg_domain_and_registry,
@@ -1551,3 +1559,5 @@
   }
   return suggested_url;
 }
+
+}  // namespace lookalikes
diff --git a/components/lookalikes/core/lookalike_url_util.h b/components/lookalikes/core/lookalike_url_util.h
index cba1ec2..a4bc2f5 100644
--- a/components/lookalikes/core/lookalike_url_util.h
+++ b/components/lookalikes/core/lookalike_url_util.h
@@ -16,10 +16,10 @@
 #include "components/version_info/channel.h"
 #include "url/gurl.h"
 
-class GURL;
-
 namespace lookalikes {
-extern const char kHistogramName[];
+
+// Name of the histogram recorded by the interstitial for lookalike match types.
+extern const char kInterstitialHistogramName[];
 
 // Register applicable preferences with the provided registry.
 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
@@ -29,10 +29,6 @@
 // heuristic that's not fully launched and it has an extra line about future
 // behavior of Chrome.
 std::string GetConsoleMessage(const GURL& lookalike_url, bool is_new_heuristic);
-}
-
-using LookalikeTargetAllowlistChecker =
-    base::RepeatingCallback<bool(const std::string&)>;
 
 // Used for |GetTargetEmbeddingType| return value. It shows if the target
 // embedding triggers on the input domain, and if it does, what type of warning
@@ -216,6 +212,12 @@
 // which doesn't have a notion of private registries.
 std::string GetETLDPlusOne(const std::string& hostname);
 
+// Records an interstitial histogram entry for the given match type.
+void RecordUMAFromMatchType(LookalikeUrlMatchType match_type);
+
+using LookalikeTargetAllowlistChecker =
+    base::RepeatingCallback<bool(const std::string&)>;
+
 // Returns true if a domain is visually similar to the hostname of |url|. The
 // matching domain can be a top domain or an engaged site. Similarity
 // check is made using both visual skeleton and edit distance comparison.  If
@@ -229,8 +231,6 @@
     std::string* matched_domain,
     LookalikeUrlMatchType* match_type);
 
-void RecordUMAFromMatchType(LookalikeUrlMatchType match_type);
-
 // Checks to see if a URL is a target embedding lookalike. This function sets
 // |safe_hostname| to the url of the embedded target domain. See the unit tests
 // for what qualifies as target embedding.
@@ -330,4 +330,6 @@
                      const GURL& navigated_url,
                      const std::string& matched_hostname);
 
+}  // namespace lookalikes
+
 #endif  // COMPONENTS_LOOKALIKES_CORE_LOOKALIKE_URL_UTIL_H_
diff --git a/components/lookalikes/core/lookalike_url_util_unittest.cc b/components/lookalikes/core/lookalike_url_util_unittest.cc
index 58a40824..2404d391 100644
--- a/components/lookalikes/core/lookalike_url_util_unittest.cc
+++ b/components/lookalikes/core/lookalike_url_util_unittest.cc
@@ -6,12 +6,18 @@
 
 #include "base/functional/bind.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/lookalikes/core/features.h"
 #include "components/lookalikes/core/safety_tip_test_utils.h"
 #include "components/lookalikes/core/safety_tips_config.h"
 #include "components/version_info/channel.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using lookalikes::ComboSquattingParams;
+using lookalikes::ComboSquattingType;
+using lookalikes::DomainInfo;
+using lookalikes::GetDomainInfo;
+using lookalikes::IsHeuristicEnabledForHostname;
+using lookalikes::LookalikeUrlMatchType;
+using lookalikes::TargetEmbeddingType;
 using version_info::Channel;
 
 namespace {
@@ -95,9 +101,9 @@
       {L"google.com", L"goooglé.com", false},
   };
   for (const TestCase& test_case : kTestCases) {
-    bool result =
-        IsEditDistanceAtMostOne(base::WideToUTF16(test_case.domain),
-                                base::WideToUTF16(test_case.top_domain));
+    bool result = lookalikes::IsEditDistanceAtMostOne(
+        base::WideToUTF16(test_case.domain),
+        base::WideToUTF16(test_case.top_domain));
     EXPECT_EQ(test_case.expected, result)
         << "when comparing " << test_case.domain << " with "
         << test_case.top_domain;
@@ -453,13 +459,11 @@
   EXPECT_EQ(embedding_type, TargetEmbeddingType::kNone);
 }
 
-struct GetETLDPlusOneTestCase {
-  const std::string hostname;
-  const std::string expected_etldp1;
-};
-
 TEST(LookalikeUrlUtilTest, GetETLDPlusOneHandlesSpecialRegistries) {
-  const std::vector<GetETLDPlusOneTestCase> kTestCases = {
+  const struct GetETLDPlusOneTestCase {
+    const std::string hostname;
+    const std::string expected_etldp1;
+  } kTestCases[] = {
       // Trivial test cases for public registries.
       {"google.com", "google.com"},
       {"www.google.com", "google.com"},
@@ -473,7 +477,8 @@
   };
 
   for (auto& test_case : kTestCases) {
-    EXPECT_EQ(GetETLDPlusOne(test_case.hostname), test_case.expected_etldp1);
+    EXPECT_EQ(lookalikes::GetETLDPlusOne(test_case.hostname),
+              test_case.expected_etldp1);
   }
 }
 
@@ -513,15 +518,15 @@
                     {L"gmail.com", L"gmailc.om", true},
                     {L"gmailc.om", L"gmail.com", true}};
   for (const TestCase& test_case : kTestCases) {
-    bool result = HasOneCharacterSwap(base::WideToUTF16(test_case.str1),
-                                      base::WideToUTF16(test_case.str2));
+    bool result = lookalikes::HasOneCharacterSwap(
+        base::WideToUTF16(test_case.str1), base::WideToUTF16(test_case.str2));
     EXPECT_EQ(test_case.expected, result)
         << "when comparing " << test_case.str1 << " with " << test_case.str2;
   }
 }
 
 TEST(LookalikeUrlUtilTest, GetSuggestedURL) {
-  struct TestCase {
+  const struct TestCase {
     const LookalikeUrlMatchType match_type;
     const GURL navigated_url;
     const std::string matched_hostname;
@@ -658,9 +663,11 @@
 class ComboSquattingTest : public testing::Test {
  protected:
   void SetUp() override {
-    SetComboSquattingParamsForTesting(kComboSquattingParams);
+    lookalikes::SetComboSquattingParamsForTesting(kComboSquattingParams);
   }
-  void TearDown() override { ResetComboSquattingParamsForTesting(); }
+  void TearDown() override {
+    lookalikes::ResetComboSquattingParamsForTesting();
+  }
 };
 
 // Test for Combo Squatting check of domains.
diff --git a/components/lookalikes/core/safety_tip_test_utils.cc b/components/lookalikes/core/safety_tip_test_utils.cc
index 6958380c..eb6a72e 100644
--- a/components/lookalikes/core/safety_tip_test_utils.cc
+++ b/components/lookalikes/core/safety_tip_test_utils.cc
@@ -4,10 +4,6 @@
 
 #include "components/lookalikes/core/safety_tip_test_utils.h"
 
-#include <algorithm>
-#include <memory>
-#include <utility>
-
 #include "components/lookalikes/core/safety_tips_config.h"
 
 namespace lookalikes {
@@ -28,25 +24,6 @@
   SetSafetyTipsRemoteConfigProto(GetOrCreateSafetyTipsConfig());
 }
 
-void SetSafetyTipPatternsWithFlagType(std::vector<std::string> patterns,
-                                      reputation::FlaggedPage::FlagType type) {
-  auto config_proto = GetOrCreateSafetyTipsConfig();
-  config_proto->clear_flagged_page();
-
-  std::sort(patterns.begin(), patterns.end());
-  for (const auto& pattern : patterns) {
-    reputation::FlaggedPage* page = config_proto->add_flagged_page();
-    page->set_pattern(pattern);
-    page->set_type(type);
-  }
-
-  SetSafetyTipsRemoteConfigProto(std::move(config_proto));
-}
-
-void SetSafetyTipBadRepPatterns(std::vector<std::string> patterns) {
-  SetSafetyTipPatternsWithFlagType(patterns, reputation::FlaggedPage::BAD_REP);
-}
-
 void SetSafetyTipAllowlistPatterns(std::vector<std::string> patterns,
                                    std::vector<std::string> target_patterns,
                                    std::vector<std::string> common_words) {
diff --git a/components/lookalikes/core/safety_tip_test_utils.h b/components/lookalikes/core/safety_tip_test_utils.h
index 605d797..904e7fcf 100644
--- a/components/lookalikes/core/safety_tip_test_utils.h
+++ b/components/lookalikes/core/safety_tip_test_utils.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_LOOKALIKES_CORE_SAFETY_TIP_TEST_UTILS_H_
 #define COMPONENTS_LOOKALIKES_CORE_SAFETY_TIP_TEST_UTILS_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -29,18 +30,18 @@
                                    std::vector<std::string> target_patterns,
                                    std::vector<std::string> common_words);
 
-// Adds a launch config for the given heuristic with the given percentage. See
-// the proto definition for the meaning of various launch percentage values.
-void AddSafetyTipHeuristicLaunchConfigForTesting(
-    reputation::HeuristicLaunchConfig::Heuristic heuristic,
-    int launch_percentage);
-
 // Ensure that the allowlist has been initialized. This is important as some
 // code (e.g. the elision policy) is fail-open (i.e. it won't elide without an
 // initialized allowlist). This is convenience wrapper around
 // SetSafetyTipAllowlistPatterns().
 void InitializeBlankLookalikeAllowlistForTesting();
 
+// Adds a launch config for the given heuristic with the given percentage. See
+// the proto definition for the meaning of various launch percentage values.
+void AddSafetyTipHeuristicLaunchConfigForTesting(
+    reputation::HeuristicLaunchConfig::Heuristic heuristic,
+    int launch_percentage);
+
 }  // namespace lookalikes
 
 #endif  // COMPONENTS_LOOKALIKES_CORE_SAFETY_TIP_TEST_UTILS_H_
diff --git a/components/lookalikes/core/safety_tips_config.cc b/components/lookalikes/core/safety_tips_config.cc
index 64cf81e..d315d45 100644
--- a/components/lookalikes/core/safety_tips_config.cc
+++ b/components/lookalikes/core/safety_tips_config.cc
@@ -114,13 +114,11 @@
 
 }  // namespace
 
-// static
 void SetSafetyTipsRemoteConfigProto(
     std::unique_ptr<reputation::SafetyTipsConfig> proto) {
   SafetyTipsConfigSingleton::GetInstance().SetProto(std::move(proto));
 }
 
-// static
 const reputation::SafetyTipsConfig* GetSafetyTipsRemoteConfigProto() {
   return SafetyTipsConfigSingleton::GetInstance().GetProto();
 }
diff --git a/components/optimization_guide/core/prediction_manager.h b/components/optimization_guide/core/prediction_manager.h
index 431bb87f..6b2b6fb 100644
--- a/components/optimization_guide/core/prediction_manager.h
+++ b/components/optimization_guide/core/prediction_manager.h
@@ -158,7 +158,7 @@
 
  private:
   friend class PredictionManagerTestBase;
-  friend class PredictionModelStoreBrowserTest;
+  friend class PredictionModelStoreBrowserTestBase;
 
   // Called on construction to initialize the prediction model.
   // |background_dowload_service_provider| can provide the
diff --git a/components/password_manager/content/browser/content_password_manager_driver_unittest.cc b/components/password_manager/content/browser/content_password_manager_driver_unittest.cc
index 3d8433d..35c519d56 100644
--- a/components/password_manager/content/browser/content_password_manager_driver_unittest.cc
+++ b/components/password_manager/content/browser/content_password_manager_driver_unittest.cc
@@ -153,7 +153,7 @@
   form_on_page.signon_realm = "https://foo.com/";
   form_on_page.scheme = PasswordForm::Scheme::kHtml;
   form_on_page.form_data.host_frame = autofill::LocalFrameToken(
-      base::UnguessableToken::Deserialize(98765, 43210));
+      base::UnguessableToken::CreateForTesting(98765, 43210));
 
   // Create an exact match in the database.
   PasswordForm preferred_match = form_on_page;
diff --git a/components/password_manager/core/browser/password_form_filling_unittest.cc b/components/password_manager/core/browser/password_form_filling_unittest.cc
index bb1e211..53070cc9 100644
--- a/components/password_manager/core/browser/password_form_filling_unittest.cc
+++ b/components/password_manager/core/browser/password_form_filling_unittest.cc
@@ -742,7 +742,7 @@
   // Set renderer id related fields.
   FormData form_data;
   form_data.host_frame = autofill::LocalFrameToken(
-      base::UnguessableToken::Deserialize(98765, 43210));
+      base::UnguessableToken::CreateForTesting(98765, 43210));
   form_data.unique_renderer_id = FormRendererId(42);
   form_data.is_form_tag = true;
   form_on_page.form_data = form_data;
diff --git a/components/services/storage/service_worker/service_worker_database_unittest.cc b/components/services/storage/service_worker/service_worker_database_unittest.cc
index 45d8de1..2040592 100644
--- a/components/services/storage/service_worker/service_worker_database_unittest.cc
+++ b/components/services/storage/service_worker/service_worker_database_unittest.cc
@@ -483,8 +483,8 @@
   // Keys with nonces should always be gettable.
   GURL origin7 = GURL("https://example.org");
   base::UnguessableToken token = base::UnguessableToken::Create();
-  blink::StorageKey key7 =
-      blink::StorageKey::CreateWithNonce(url::Origin::Create(origin7), token);
+  blink::StorageKey key7 = blink::StorageKey::CreateWithNonceForTesting(
+      url::Origin::Create(origin7), token);
   RegistrationData data7;
   data7.registration_id = 789;
   data7.scope = URL(origin7, "/hoge");
@@ -815,7 +815,7 @@
   RegistrationData data7;
   data7.registration_id = 700;
   data7.scope = URL(origin7, "/hoge");
-  data7.key = blink::StorageKey::CreateWithNonce(
+  data7.key = blink::StorageKey::CreateWithNonceForTesting(
       url::Origin::Create(data7.scope), token);
   data7.script = URL(origin7, "/script7.js");
   data7.version_id = 7000;
diff --git a/components/sessions/core/tab_restore_service_helper.cc b/components/sessions/core/tab_restore_service_helper.cc
index e34b2823..2d9c182 100644
--- a/components/sessions/core/tab_restore_service_helper.cc
+++ b/components/sessions/core/tab_restore_service_helper.cc
@@ -447,6 +447,13 @@
   switch (entry.type) {
     case TabRestoreService::TAB: {
       auto& tab = static_cast<const Tab&>(entry);
+
+      if (tab.timestamp != base::Time() &&
+          !tab.timestamp.ToDeltaSinceWindowsEpoch().is_zero()) {
+        UMA_HISTOGRAM_LONG_TIMES("TabRestore.Tab.TimeBetweenClosedAndRestored",
+                                 TimeNow() - tab.timestamp);
+      }
+
       LiveTab* restored_tab = nullptr;
       context = RestoreTab(tab, context, disposition, &restored_tab);
       live_tabs.push_back(restored_tab);
@@ -457,6 +464,13 @@
       LiveTabContext* current_context = context;
       auto& window = static_cast<Window&>(entry);
 
+      if (window.timestamp != base::Time() &&
+          !window.timestamp.ToDeltaSinceWindowsEpoch().is_zero()) {
+        UMA_HISTOGRAM_LONG_TIMES(
+            "TabRestore.Window.TimeBetweenClosedAndRestored",
+            TimeNow() - window.timestamp);
+      }
+
       // When restoring a window, either the entire window can be restored, or a
       // single tab within it. If the entry's ID matches the one to restore, or
       // the entry corresponds to an application, then the entire window will be
@@ -579,6 +593,13 @@
     case TabRestoreService::GROUP: {
       auto& group = static_cast<Group&>(entry);
 
+      if (group.timestamp != base::Time() &&
+          !group.timestamp.ToDeltaSinceWindowsEpoch().is_zero()) {
+        UMA_HISTOGRAM_LONG_TIMES(
+            "TabRestore.Group.TimeBetweenClosedAndRestored",
+            TimeNow() - group.timestamp);
+      }
+
       // When restoring a group, either the entire group can be restored, or a
       // single tab within it. If the entry's ID matches the one to restore,
       // then the entire group will be restored.
diff --git a/components/user_education/views/help_bubble_factory_mac.mm b/components/user_education/views/help_bubble_factory_mac.mm
index 37a03e1b..5684e2b9 100644
--- a/components/user_education/views/help_bubble_factory_mac.mm
+++ b/components/user_education/views/help_bubble_factory_mac.mm
@@ -29,18 +29,21 @@
   views::Widget* const widget =
       views::ElementTrackerViews::GetInstance()->GetWidgetForContext(
           element_mac->context());
-  auto* const anchor_view = widget->GetRootView();
-  gfx::Rect anchor_rect = element_mac->GetScreenBounds();
+
+  // Because the exact location of the menu item cannot be determined, an arrow
+  // is not shown on the bubble.
+  internal::HelpBubbleAnchorParams anchor;
+  anchor.show_arrow = false;
+  anchor.view = widget->GetRootView();
+  anchor.rect = element_mac->GetScreenBounds();
 
   // We don't want the bubble to be flush with either the side or top of the
   // Mac native menu, because it looks funny.
   constexpr auto kMacMenuInsets = gfx::Insets::VH(10, -5);
-  anchor_rect.Inset(kMacMenuInsets);
+  anchor.rect->Inset(kMacMenuInsets);
 
-  return base::WrapUnique(
-      new HelpBubbleViews(new HelpBubbleView(delegate_, anchor_view,
-                                             std::move(params), anchor_rect),
-                          element));
+  return base::WrapUnique(new HelpBubbleViews(
+      new HelpBubbleView(delegate_, anchor, std::move(params)), element));
 }
 
 bool HelpBubbleFactoryMac::CanBuildBubbleForTrackedElement(
diff --git a/components/user_education/views/help_bubble_factory_views.cc b/components/user_education/views/help_bubble_factory_views.cc
index f655aefb..6242b217 100644
--- a/components/user_education/views/help_bubble_factory_views.cc
+++ b/components/user_education/views/help_bubble_factory_views.cc
@@ -184,11 +184,24 @@
 std::unique_ptr<HelpBubble> HelpBubbleFactoryViews::CreateBubble(
     ui::TrackedElement* element,
     HelpBubbleParams params) {
-  views::View* const anchor_view =
-      element->AsA<views::TrackedElementViews>()->view();
-  anchor_view->SetProperty(kHasInProductHelpPromoKey, true);
+  internal::HelpBubbleAnchorParams anchor;
+  anchor.view = element->AsA<views::TrackedElementViews>()->view();
+  return CreateBubbleImpl(element, anchor, std::move(params));
+}
+
+bool HelpBubbleFactoryViews::CanBuildBubbleForTrackedElement(
+    const ui::TrackedElement* element) const {
+  return element->IsA<views::TrackedElementViews>();
+}
+
+std::unique_ptr<HelpBubble> HelpBubbleFactoryViews::CreateBubbleImpl(
+    ui::TrackedElement* element,
+    const internal::HelpBubbleAnchorParams& anchor,
+    HelpBubbleParams params,
+    absl::optional<gfx::Rect> anchor_rect) {
+  anchor.view->SetProperty(kHasInProductHelpPromoKey, true);
   auto result = base::WrapUnique(new HelpBubbleViews(
-      new HelpBubbleView(delegate_, anchor_view, std::move(params)), element));
+      new HelpBubbleView(delegate_, anchor, std::move(params)), element));
   for (const auto& accelerator :
        delegate_->GetPaneNavigationAccelerators(element)) {
     result->bubble_view()->GetFocusManager()->RegisterAccelerator(
@@ -198,9 +211,4 @@
   return result;
 }
 
-bool HelpBubbleFactoryViews::CanBuildBubbleForTrackedElement(
-    const ui::TrackedElement* element) const {
-  return element->IsA<views::TrackedElementViews>();
-}
-
 }  // namespace user_education
diff --git a/components/user_education/views/help_bubble_factory_views.h b/components/user_education/views/help_bubble_factory_views.h
index d2145b9..55f0f7c 100644
--- a/components/user_education/views/help_bubble_factory_views.h
+++ b/components/user_education/views/help_bubble_factory_views.h
@@ -24,8 +24,12 @@
 
 namespace user_education {
 
-class HelpBubbleView;
 class HelpBubbleDelegate;
+class HelpBubbleView;
+
+namespace internal {
+struct HelpBubbleAnchorParams;
+}
 
 // Views-specific implementation of the help bubble.
 //
@@ -98,6 +102,13 @@
   bool CanBuildBubbleForTrackedElement(
       const ui::TrackedElement* element) const override;
 
+ protected:
+  std::unique_ptr<HelpBubble> CreateBubbleImpl(
+      ui::TrackedElement* element,
+      const internal::HelpBubbleAnchorParams& anchor,
+      HelpBubbleParams params,
+      absl::optional<gfx::Rect> anchor_rect = absl::nullopt);
+
  private:
   base::raw_ptr<const HelpBubbleDelegate> delegate_;
 };
diff --git a/components/user_education/views/help_bubble_view.cc b/components/user_education/views/help_bubble_view.cc
index 938667f..ca221c1 100644
--- a/components/user_education/views/help_bubble_view.cc
+++ b/components/user_education/views/help_bubble_view.cc
@@ -18,7 +18,6 @@
 #include "components/strings/grit/components_strings.h"
 #include "components/user_education/common/help_bubble_params.h"
 #include "components/user_education/views/help_bubble_delegate.h"
-#include "components/user_education/views/help_bubble_factory_views.h"
 #include "components/variations/variations_associated_data.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/interaction/element_identifier.h"
@@ -290,17 +289,16 @@
 // outline in dark mode on Mac. Use our own shadow instead. The shadow type is
 // the same for all other platforms.
 HelpBubbleView::HelpBubbleView(const HelpBubbleDelegate* delegate,
-                               views::View* anchor_view,
-                               HelpBubbleParams params,
-                               absl::optional<gfx::Rect> anchor_rect)
-    : BubbleDialogDelegateView(anchor_view,
+                               const internal::HelpBubbleAnchorParams& anchor,
+                               HelpBubbleParams params)
+    : BubbleDialogDelegateView(anchor.view,
                                TranslateArrow(params.arrow),
                                views::BubbleBorder::STANDARD_SHADOW),
       delegate_(delegate),
-      force_anchor_rect_(anchor_rect) {
+      force_anchor_rect_(anchor.rect) {
   // The anchor for promo bubbles should not highlight.
   set_highlight_button_when_shown(false);
-  DCHECK(anchor_view)
+  DCHECK(anchor.view)
       << "A bubble that closes on blur must be initially focused.";
   UseCompactMargins();
 
@@ -615,13 +613,13 @@
   frame_view->SetCornerRadius(
       views::LayoutProvider::Get()->GetCornerRadiusMetric(
           views::Emphasis::kHigh));
-  frame_view->SetDisplayVisibleArrow(!force_anchor_rect_.has_value() &&
+  frame_view->SetDisplayVisibleArrow(anchor.show_arrow &&
                                      params.arrow != HelpBubbleArrow::kNone);
   SizeToContents();
 
   widget->ShowInactive();
   auto* const anchor_bubble =
-      anchor_view->GetWidget()->widget_delegate()->AsBubbleDialogDelegate();
+      anchor.view->GetWidget()->widget_delegate()->AsBubbleDialogDelegate();
   if (anchor_bubble)
     anchor_pin_ = anchor_bubble->PreventCloseOnDeactivate();
   MaybeStartAutoCloseTimer();
diff --git a/components/user_education/views/help_bubble_view.h b/components/user_education/views/help_bubble_view.h
index 104b27f..b5ba447d 100644
--- a/components/user_education/views/help_bubble_view.h
+++ b/components/user_education/views/help_bubble_view.h
@@ -35,6 +35,25 @@
 
 class HelpBubbleDelegate;
 
+namespace internal {
+
+// Describes how a help bubble should be anchored to a Views element, beyond
+// what is specified by the HelpBubbleParams. Should only be instantiated by
+// classes derived from HelpBubbleFactory (or in tests).
+struct HelpBubbleAnchorParams {
+  // This is the View to be anchored to (mandatory).
+  views::View* view = nullptr;
+
+  // This is an optional override of the anchor rect in screen coordinates.
+  // If unspecified, the bubble is anchored as normal to `view`.
+  absl::optional<gfx::Rect> rect;
+
+  // Whether or not a visible arrow should be shown.
+  bool show_arrow = true;
+};
+
+}  // namespace internal
+
 // The HelpBubbleView is a special BubbleDialogDelegateView for
 // in-product help which educates users about certain Chrome features in
 // a deferred context.
@@ -46,9 +65,8 @@
   DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kFirstNonDefaultButtonIdForTesting);
 
   HelpBubbleView(const HelpBubbleDelegate* delegate,
-                 views::View* anchor_view,
-                 HelpBubbleParams params,
-                 absl::optional<gfx::Rect> anchor_rect = absl::nullopt);
+                 const internal::HelpBubbleAnchorParams& anchor,
+                 HelpBubbleParams params);
   HelpBubbleView(const HelpBubbleView&) = delete;
   HelpBubbleView& operator=(const HelpBubbleView&) = delete;
   ~HelpBubbleView() override;
diff --git a/components/user_education/views/help_bubble_view_unittest.cc b/components/user_education/views/help_bubble_view_unittest.cc
index 5509e12e..26191916 100644
--- a/components/user_education/views/help_bubble_view_unittest.cc
+++ b/components/user_education/views/help_bubble_view_unittest.cc
@@ -57,7 +57,9 @@
 
  protected:
   HelpBubbleView* CreateHelpBubbleView(HelpBubbleParams params) {
-    return new HelpBubbleView(&test_delegate_, view_, std::move(params));
+    return new HelpBubbleView(&test_delegate_,
+                              internal::HelpBubbleAnchorParams{view_},
+                              std::move(params));
   }
 
   HelpBubbleView* CreateHelpBubbleView(base::RepeatingClosure button_callback) {
@@ -135,7 +137,9 @@
   button3.is_default = false;
   params.buttons.push_back(std::move(button3));
 
-  auto* bubble = new HelpBubbleView(&test_delegate_, view_, std::move(params));
+  auto* bubble = new HelpBubbleView(&test_delegate_,
+                                    internal::HelpBubbleAnchorParams{view_},
+                                    std::move(params));
   EXPECT_EQ(kButton1Text, bubble->GetNonDefaultButtonForTesting(0)->GetText());
   EXPECT_EQ(kButton2Text, bubble->GetDefaultButtonForTesting()->GetText());
   EXPECT_EQ(kButton3Text, bubble->GetNonDefaultButtonForTesting(1)->GetText());
diff --git a/components/user_education/webui/BUILD.gn b/components/user_education/webui/BUILD.gn
index 44c10b7..7f3af41 100644
--- a/components/user_education/webui/BUILD.gn
+++ b/components/user_education/webui/BUILD.gn
@@ -4,6 +4,8 @@
 
 source_set("webui") {
   sources = [
+    "floating_webui_help_bubble_factory.cc",
+    "floating_webui_help_bubble_factory.h",
     "help_bubble_handler.cc",
     "help_bubble_handler.h",
     "help_bubble_webui.cc",
@@ -15,11 +17,15 @@
   deps = [
     "//base",
     "//components/user_education/common",
+    "//components/user_education/views",
     "//components/vector_icons",
+    "//content/public/browser",
     "//skia",
     "//third_party/abseil-cpp:absl",
     "//ui/accessibility",
     "//ui/base",
+    "//ui/views",
+    "//ui/views/controls/webview",
     "//ui/webui/resources/cr_components/help_bubble:mojo_bindings",
   ]
 }
@@ -39,6 +45,7 @@
     "//components/user_education/test",
     "//components/variations",
     "//components/vector_icons",
+    "//content/public/browser",
     "//skia",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/components/user_education/webui/DEPS b/components/user_education/webui/DEPS
index 78c51f8..2029963 100644
--- a/components/user_education/webui/DEPS
+++ b/components/user_education/webui/DEPS
@@ -1,4 +1,6 @@
 include_rules = [
+  "+content/public/browser",
   "+mojo/public/cpp/bindings",
+  "+ui/views",
   "+ui/webui/resources/cr_components/help_bubble",
 ]
\ No newline at end of file
diff --git a/components/user_education/webui/floating_webui_help_bubble_factory.cc b/components/user_education/webui/floating_webui_help_bubble_factory.cc
new file mode 100644
index 0000000..71ed038
--- /dev/null
+++ b/components/user_education/webui/floating_webui_help_bubble_factory.cc
@@ -0,0 +1,83 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/user_education/webui/floating_webui_help_bubble_factory.h"
+
+#include "components/user_education/views/help_bubble_factory_views.h"
+#include "components/user_education/views/help_bubble_view.h"
+#include "components/user_education/webui/help_bubble_handler.h"
+#include "components/user_education/webui/tracked_element_webui.h"
+#include "content/public/browser/web_contents.h"
+#include "ui/base/interaction/element_tracker.h"
+#include "ui/base/interaction/framework_specific_implementation.h"
+#include "ui/views/controls/webview/webview.h"
+#include "ui/views/view_utils.h"
+#include "ui/views/widget/widget.h"
+
+namespace user_education {
+
+namespace {
+
+// Searches `from_view` recursively (depth-first) for a WebView with `contents`.
+views::WebView* FindWebViewWithContentsRecursive(
+    views::View* from_view,
+    const content::WebContents* contents) {
+  auto* const web_view = views::AsViewClass<views::WebView>(from_view);
+  if (web_view && web_view->web_contents() == contents) {
+    return web_view;
+  }
+
+  for (auto* const child_view : from_view->children()) {
+    auto* const result = FindWebViewWithContentsRecursive(child_view, contents);
+    if (result) {
+      return result;
+    }
+  }
+
+  return nullptr;
+}
+
+// Attempts to extract the host WebView from `element`; returns null if
+// `element` is not a TrackedElementWebUI or the host view cannot be determined.
+views::WebView* GetWebViewForElement(const ui::TrackedElement* element) {
+  if (!element->IsA<TrackedElementWebUI>()) {
+    return nullptr;
+  }
+  const auto* const element_webui = element->AsA<TrackedElementWebUI>();
+  auto* const contents = element_webui->handler()->GetWebContents();
+  if (!contents) {
+    return nullptr;
+  }
+  auto* const widget = views::Widget::GetWidgetForNativeWindow(
+      contents->GetTopLevelNativeWindow());
+  if (!widget) {
+    return nullptr;
+  }
+  return FindWebViewWithContentsRecursive(widget->GetContentsView(), contents);
+}
+
+}  // namespace
+
+FloatingWebUIHelpBubbleFactory::FloatingWebUIHelpBubbleFactory(
+    const HelpBubbleDelegate* delegate)
+    : HelpBubbleFactoryViews(delegate) {}
+FloatingWebUIHelpBubbleFactory::~FloatingWebUIHelpBubbleFactory() = default;
+
+DEFINE_FRAMEWORK_SPECIFIC_METADATA(FloatingWebUIHelpBubbleFactory)
+
+std::unique_ptr<HelpBubble> FloatingWebUIHelpBubbleFactory::CreateBubble(
+    ui::TrackedElement* element,
+    HelpBubbleParams params) {
+  internal::HelpBubbleAnchorParams anchor;
+  anchor.view = GetWebViewForElement(element);
+  anchor.rect = element->GetScreenBounds();
+  return CreateBubbleImpl(element, anchor, std::move(params));
+}
+
+bool FloatingWebUIHelpBubbleFactory::CanBuildBubbleForTrackedElement(
+    const ui::TrackedElement* element) const {
+  return GetWebViewForElement(element) != nullptr;
+}
+
+}  // namespace user_education
diff --git a/components/user_education/webui/floating_webui_help_bubble_factory.h b/components/user_education/webui/floating_webui_help_bubble_factory.h
new file mode 100644
index 0000000..1175f77
--- /dev/null
+++ b/components/user_education/webui/floating_webui_help_bubble_factory.h
@@ -0,0 +1,36 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_USER_EDUCATION_WEBUI_FLOATING_WEBUI_HELP_BUBBLE_FACTORY_H_
+#define COMPONENTS_USER_EDUCATION_WEBUI_FLOATING_WEBUI_HELP_BUBBLE_FACTORY_H_
+
+#include "components/user_education/common/help_bubble.h"
+#include "components/user_education/views/help_bubble_delegate.h"
+#include "components/user_education/views/help_bubble_factory_views.h"
+#include "components/user_education/webui/help_bubble_webui.h"
+
+namespace user_education {
+
+// Help bubble factory that anchors a floating Views help bubble to a WebUI.
+//
+// This factory is designed for help bubbles attached to non-tab WebUI; prefer
+// `HelpBubbleFactoryWebUI` for help bubbles in WebUI that are displayed in tabs
+// (that factory shows the help bubble in the WebUI itself).
+class FloatingWebUIHelpBubbleFactory : public HelpBubbleFactoryViews {
+ public:
+  explicit FloatingWebUIHelpBubbleFactory(const HelpBubbleDelegate* delegate);
+  ~FloatingWebUIHelpBubbleFactory() override;
+
+  DECLARE_FRAMEWORK_SPECIFIC_METADATA()
+
+  // HelpBubbleFactory:
+  std::unique_ptr<HelpBubble> CreateBubble(ui::TrackedElement* element,
+                                           HelpBubbleParams params) override;
+  bool CanBuildBubbleForTrackedElement(
+      const ui::TrackedElement* element) const override;
+};
+
+}  // namespace user_education
+
+#endif  // COMPONENTS_USER_EDUCATION_WEBUI_FLOATING_WEBUI_HELP_BUBBLE_FACTORY_H_
diff --git a/components/user_education/webui/help_bubble_handler.cc b/components/user_education/webui/help_bubble_handler.cc
index aa9a32d..885befff 100644
--- a/components/user_education/webui/help_bubble_handler.cc
+++ b/components/user_education/webui/help_bubble_handler.cc
@@ -19,6 +19,8 @@
 #include "components/user_education/common/help_bubble_params.h"
 #include "components/user_education/webui/help_bubble_webui.h"
 #include "components/user_education/webui/tracked_element_webui.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_controller.h"
 #include "ui/base/interaction/element_identifier.h"
 #include "ui/base/interaction/element_tracker.h"
 #include "ui/webui/resources/cr_components/help_bubble/help_bubble.mojom-shared.h"
@@ -134,6 +136,10 @@
   }
 }
 
+content::WebContents* HelpBubbleHandlerBase::GetWebContents() {
+  return GetController()->web_ui()->GetWebContents();
+}
+
 help_bubble::mojom::HelpBubbleClient* HelpBubbleHandlerBase::GetClient() {
   return client_provider_->GetClient();
 }
@@ -214,7 +220,8 @@
 
 void HelpBubbleHandlerBase::HelpBubbleAnchorVisibilityChanged(
     const std::string& identifier_name,
-    bool visible) {
+    bool visible,
+    const gfx::RectF& rect) {
   ui::ElementIdentifier id;
   ElementData* const data = GetDataByName(identifier_name, &id);
   if (!data)
@@ -222,7 +229,7 @@
 
   // Note: any of the following calls could destroy *this* via a callback.
   if (!data->element->visible() && visible) {
-    data->element->SetVisible(true);
+    data->element->SetVisible(true, rect);
   } else if (data->element->visible() && !visible) {
     // Is a help bubble currently showing?
     if (data->params) {
@@ -421,16 +428,23 @@
     mojo::PendingReceiver<help_bubble::mojom::HelpBubbleHandler>
         pending_handler,
     mojo::PendingRemote<help_bubble::mojom::HelpBubbleClient> pending_client,
-    content::WebContents* web_contents,
+    content::WebUIController* controller,
     const std::vector<ui::ElementIdentifier>& identifiers)
     : HelpBubbleHandlerBase(
           std::make_unique<ClientProvider>(std::move(pending_client)),
           identifiers,
-          ui::ElementContext(web_contents)),
-      receiver_(this, std::move(pending_handler)) {}
+          ui::ElementContext(controller)),
+      receiver_(this, std::move(pending_handler)),
+      controller_(controller) {
+  DCHECK(controller);
+}
 
 HelpBubbleHandler::~HelpBubbleHandler() = default;
 
+content::WebUIController* HelpBubbleHandler::GetController() {
+  return controller_;
+}
+
 void HelpBubbleHandler::ReportBadMessage(base::StringPiece error) {
   receiver_.ReportBadMessage(std::move(error));
 }
diff --git a/components/user_education/webui/help_bubble_handler.h b/components/user_education/webui/help_bubble_handler.h
index 868b7f0..52ae389 100644
--- a/components/user_education/webui/help_bubble_handler.h
+++ b/components/user_education/webui/help_bubble_handler.h
@@ -15,10 +15,12 @@
 #include "base/strings/string_piece.h"
 #include "components/user_education/common/help_bubble_params.h"
 #include "components/user_education/webui/tracked_element_webui.h"
+#include "content/public/browser/web_ui_controller.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "ui/base/interaction/element_identifier.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_f.h"
 #include "ui/webui/resources/cr_components/help_bubble/help_bubble.mojom.h"
 
 namespace content {
@@ -39,9 +41,20 @@
   ~HelpBubbleHandlerBase() override;
   void operator=(const HelpBubbleHandlerBase&) = delete;
 
-  // TODO(dfried): determine if there's a safe way to have these change context.
+  // Returns the context. Currently this is tied to the WebUIController and not
+  // the browser that holds it, as (at least for tab contents) the owning
+  // browser can change during the handler's lifespan.
   ui::ElementContext context() const { return context_; }
 
+  // Returns the associated `WebUIController`. This should not change over the
+  // lifetime of the handler.
+  virtual content::WebUIController* GetController() = 0;
+
+  // Returns the WebContents associated with the controller. This is a
+  // convenience method. A contents should be associated with the controller but
+  // it is probably good to check for null.
+  content::WebContents* GetWebContents();
+
  protected:
   // Provides reliable access to a HelpBubbleClient. Derived classes should
   // create a ClientProvider and pass it to the HelpBubbleHandlerBase
@@ -84,7 +97,8 @@
 
   // mojom::HelpBubbleHandler:
   void HelpBubbleAnchorVisibilityChanged(const std::string& identifier_name,
-                                         bool visible) final;
+                                         bool visible,
+                                         const gfx::RectF& rect) final;
   void HelpBubbleAnchorActivated(const std::string& identifier_name) final;
   void HelpBubbleAnchorCustomEvent(const std::string& identifier_name,
                                    const std::string& event_name) final;
@@ -110,12 +124,12 @@
 //
 // Full usage recommendations can be found in README.md.
 //
-// SECURITY NOTE: a `HelpBubbleHandler` is typically owned by a
-// `WebUIController` that implements `HelpBubbleHandlerFactory`, and typically
-// has a lifespan limited to a subset of the corresponding WebUI page's
-// lifespan. Reloading the page can cause it to be discarded and recreated (and
-// a common attack vector is triggering a recreate). If a class has a raw_ptr to
-// a HelpBubbleHandler[Base], then a test MUST be added to ensure that the class
+// SECURITY NOTE: a `HelpBubbleHandler` is owned by a `WebUIController` that
+// implements `HelpBubbleHandlerFactory`, and typically has a lifespan limited
+// to a subset of the corresponding WebUI page's lifespan. Reloading the page
+// can cause it to be discarded and recreated (and a common attack vector is
+// triggering a recreate). If a class has a raw_ptr to a
+// HelpBubbleHandler[Base], then a test MUST be added to ensure that the class
 // releases the reference when the HelpBubbleHandler is destroyed. Tests are
 // already provided for `HelpBubbleWebUI` and `TrackedElementWebUI` in
 // help_bubble_handler_unittest.cc.
@@ -134,10 +148,13 @@
       mojo::PendingReceiver<help_bubble::mojom::HelpBubbleHandler>
           pending_handler,
       mojo::PendingRemote<help_bubble::mojom::HelpBubbleClient> pending_client,
-      content::WebContents* web_contents,
+      content::WebUIController* controller,
       const std::vector<ui::ElementIdentifier>& identifiers);
   ~HelpBubbleHandler() override;
 
+  // HelpBubbleHandlerBase:
+  content::WebUIController* GetController() override;
+
  private:
   class ClientProvider : public HelpBubbleHandlerBase::ClientProvider {
    public:
@@ -155,6 +172,7 @@
   void ReportBadMessage(base::StringPiece error) override;
 
   mojo::Receiver<help_bubble::mojom::HelpBubbleHandler> receiver_;
+  const base::raw_ptr<content::WebUIController> controller_;
 };
 
 }  // namespace user_education
diff --git a/components/user_education/webui/help_bubble_handler_unittest.cc b/components/user_education/webui/help_bubble_handler_unittest.cc
index f484224..453a8c9d 100644
--- a/components/user_education/webui/help_bubble_handler_unittest.cc
+++ b/components/user_education/webui/help_bubble_handler_unittest.cc
@@ -8,12 +8,14 @@
 #include <vector>
 
 #include "base/memory/raw_ptr.h"
+#include "base/notreached.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/user_education/common/help_bubble_factory_registry.h"
 #include "components/user_education/common/help_bubble_params.h"
 #include "components/user_education/webui/help_bubble_webui.h"
 #include "components/user_education/webui/tracked_element_webui.h"
 #include "components/vector_icons/vector_icons.h"
+#include "content/public/browser/web_ui_controller.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/interaction/element_identifier.h"
@@ -29,6 +31,7 @@
 
 DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kHelpBubbleHandlerTestElementIdentifier);
 DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kHelpBubbleHandlerTestElementIdentifier2);
+constexpr gfx::RectF kElementBounds{50, 51, 51, 53};
 
 // Mock version of the help bubble client so we don't need a remote (while being
 // able to know when the remote methods would have been called).
@@ -70,6 +73,11 @@
     return static_cast<ClientProvider*>(client_provider())->client_;
   }
 
+  content::WebUIController* GetController() override {
+    NOTREACHED() << "Should not call this in tests.";
+    return nullptr;
+  }
+
  private:
   // Provides a mock client.
   class ClientProvider : public HelpBubbleHandlerBase::ClientProvider {
@@ -150,7 +158,7 @@
 
 TEST_F(HelpBubbleHandlerTest, ElementCreatedOnEvent) {
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), true, kElementBounds);
   EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->GetElementInAnyContext(
       kHelpBubbleHandlerTestElementIdentifier));
   EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->GetElementInAnyContext(
@@ -166,9 +174,9 @@
 
 TEST_F(HelpBubbleHandlerTest, ElementHiddenOnEvent) {
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), true, kElementBounds);
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), false);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), false, gfx::RectF());
   EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->GetElementInAnyContext(
       kHelpBubbleHandlerTestElementIdentifier));
   EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->GetElementInAnyContext(
@@ -178,7 +186,7 @@
 TEST_F(HelpBubbleHandlerTest, ElementActivatedOnEvent) {
   UNCALLED_MOCK_CALLBACK(ui::ElementTracker::Callback, activated);
   const std::string name = kHelpBubbleHandlerTestElementIdentifier.GetName();
-  handler()->HelpBubbleAnchorVisibilityChanged(name, true);
+  handler()->HelpBubbleAnchorVisibilityChanged(name, true, kElementBounds);
   auto* const tracker = ui::ElementTracker::GetElementTracker();
   auto* const element =
       tracker->GetElementInAnyContext(kHelpBubbleHandlerTestElementIdentifier);
@@ -195,7 +203,8 @@
   const std::string element_name =
       kHelpBubbleHandlerTestElementIdentifier.GetName();
   UNCALLED_MOCK_CALLBACK(ui::ElementTracker::Callback, custom_event);
-  handler()->HelpBubbleAnchorVisibilityChanged(element_name, true);
+  handler()->HelpBubbleAnchorVisibilityChanged(element_name, true,
+                                               kElementBounds);
   auto* const tracker = ui::ElementTracker::GetElementTracker();
   auto* const element =
       tracker->GetElementInAnyContext(kHelpBubbleHandlerTestElementIdentifier);
@@ -210,9 +219,9 @@
 TEST_F(HelpBubbleHandlerTest, MultipleIdentifiers) {
   // Show two elements.
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), true, kElementBounds);
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier2.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier2.GetName(), true, kElementBounds);
   EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->GetElementInAnyContext(
       kHelpBubbleHandlerTestElementIdentifier));
   EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->GetElementInAnyContext(
@@ -220,7 +229,7 @@
 
   // Hide one element.
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), false);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), false, gfx::RectF());
   EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->GetElementInAnyContext(
       kHelpBubbleHandlerTestElementIdentifier));
   EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->GetElementInAnyContext(
@@ -228,7 +237,7 @@
 
   // Hide the other element.
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier2.GetName(), false);
+      kHelpBubbleHandlerTestElementIdentifier2.GetName(), false, gfx::RectF());
   EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->GetElementInAnyContext(
       kHelpBubbleHandlerTestElementIdentifier));
   EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->GetElementInAnyContext(
@@ -236,7 +245,7 @@
 
   // Re-show an element.
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), true, kElementBounds);
   EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->GetElementInAnyContext(
       kHelpBubbleHandlerTestElementIdentifier));
   EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->GetElementInAnyContext(
@@ -245,7 +254,7 @@
 
 TEST_F(HelpBubbleHandlerTest, ShowHelpBubble) {
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), true, kElementBounds);
   auto* const element =
       ui::ElementTracker::GetElementTracker()->GetUniqueElement(
           kHelpBubbleHandlerTestElementIdentifier, test_handler_->context());
@@ -289,7 +298,7 @@
 
 TEST_F(HelpBubbleHandlerTest, ShowHelpBubbleWithButtonsAndProgress) {
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), true, kElementBounds);
   auto* const element =
       ui::ElementTracker::GetElementTracker()->GetUniqueElement(
           kHelpBubbleHandlerTestElementIdentifier, test_handler_->context());
@@ -348,7 +357,7 @@
 
 TEST_F(HelpBubbleHandlerTest, FocusHelpBubble) {
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), true, kElementBounds);
   auto* const element =
       ui::ElementTracker::GetElementTracker()->GetUniqueElement(
           kHelpBubbleHandlerTestElementIdentifier, test_handler_->context());
@@ -376,9 +385,9 @@
 
 TEST_F(HelpBubbleHandlerTest, HelpBubbleClosedWhenVisibilityChanges) {
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), true, kElementBounds);
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier2.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier2.GetName(), true, kElementBounds);
   auto* const element =
       ui::ElementTracker::GetElementTracker()->GetUniqueElement(
           kHelpBubbleHandlerTestElementIdentifier, test_handler_->context());
@@ -393,11 +402,11 @@
 
   // This should have no effect since it's the wrong element.
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier2.GetName(), false);
+      kHelpBubbleHandlerTestElementIdentifier2.GetName(), false, gfx::RectF());
   EXPECT_TRUE(help_bubble->is_open());
 
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), false);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), false, gfx::RectF());
   EXPECT_FALSE(help_bubble->is_open());
 }
 
@@ -405,7 +414,7 @@
   UNCALLED_MOCK_CALLBACK(HelpBubble::ClosedCallback, closed);
 
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), true, kElementBounds);
   auto* const element =
       ui::ElementTracker::GetElementTracker()->GetUniqueElement(
           kHelpBubbleHandlerTestElementIdentifier, test_handler_->context());
@@ -429,7 +438,7 @@
 
 TEST_F(HelpBubbleHandlerTest, DestroyHandlerCleansUpElement) {
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), true, kElementBounds);
   const ui::ElementContext context = test_handler_->context();
   EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
       kHelpBubbleHandlerTestElementIdentifier, context));
@@ -442,7 +451,7 @@
   UNCALLED_MOCK_CALLBACK(HelpBubble::ClosedCallback, closed);
 
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), true, kElementBounds);
   auto* const element =
       ui::ElementTracker::GetElementTracker()->GetUniqueElement(
           kHelpBubbleHandlerTestElementIdentifier, test_handler_->context());
@@ -467,7 +476,7 @@
   UNCALLED_MOCK_CALLBACK(base::OnceClosure, dismissed);
 
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), true, kElementBounds);
   auto* const element =
       ui::ElementTracker::GetElementTracker()->GetUniqueElement(
           kHelpBubbleHandlerTestElementIdentifier, test_handler_->context());
@@ -494,7 +503,7 @@
   UNCALLED_MOCK_CALLBACK(base::OnceClosure, button2_pressed);
 
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), true, kElementBounds);
   auto* const element =
       ui::ElementTracker::GetElementTracker()->GetUniqueElement(
           kHelpBubbleHandlerTestElementIdentifier, test_handler_->context());
@@ -529,9 +538,9 @@
 
 TEST_F(HelpBubbleHandlerTest, ShowMultipleBubblesAndCloseOneViaVisibility) {
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), true, kElementBounds);
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier2.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier2.GetName(), true, kElementBounds);
   auto* const element =
       ui::ElementTracker::GetElementTracker()->GetUniqueElement(
           kHelpBubbleHandlerTestElementIdentifier, test_handler_->context());
@@ -561,7 +570,7 @@
 
   // Close one bubble without closing the other.
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), false);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), false, gfx::RectF());
   EXPECT_FALSE(help_bubble->is_open());
   EXPECT_TRUE(help_bubble2->is_open());
 
@@ -574,9 +583,9 @@
 
 TEST_F(HelpBubbleHandlerTest, ShowMultipleBubblesAndCloseOneViaCallback) {
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier.GetName(), true, kElementBounds);
   handler()->HelpBubbleAnchorVisibilityChanged(
-      kHelpBubbleHandlerTestElementIdentifier2.GetName(), true);
+      kHelpBubbleHandlerTestElementIdentifier2.GetName(), true, kElementBounds);
   auto* const element =
       ui::ElementTracker::GetElementTracker()->GetUniqueElement(
           kHelpBubbleHandlerTestElementIdentifier, test_handler_->context());
diff --git a/components/user_education/webui/tracked_element_webui.cc b/components/user_education/webui/tracked_element_webui.cc
index 82d7b52..290209e 100644
--- a/components/user_education/webui/tracked_element_webui.cc
+++ b/components/user_education/webui/tracked_element_webui.cc
@@ -5,8 +5,12 @@
 #include "components/user_education/webui/tracked_element_webui.h"
 
 #include "base/check.h"
+#include "components/user_education/webui/help_bubble_handler.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
 #include "ui/base/interaction/element_tracker.h"
 #include "ui/base/interaction/framework_specific_implementation.h"
+#include "ui/gfx/geometry/rect_conversions.h"
 
 namespace user_education {
 
@@ -21,7 +25,29 @@
   SetVisible(false);
 }
 
-void TrackedElementWebUI::SetVisible(bool visible) {
+gfx::Rect TrackedElementWebUI::GetScreenBounds() const {
+  gfx::Rect result;
+  content::WebContents* const contents =
+      handler_->GetController()->web_ui()->GetWebContents();
+  if (contents) {
+    // Use the last known bounds, but if the bounds are empty, make them 1x1 so
+    // there's something to anchor to.
+    result = gfx::ToRoundedRect(last_known_bounds_);
+    if (result.width() < 1) {
+      result.set_width(1);
+    }
+    if (result.height() < 1) {
+      result.set_height(1);
+    }
+    // To get the screen coordinates, have to offset by the coordinates of the
+    // viewport.
+    result.Offset(contents->GetContainerBounds().OffsetFromOrigin());
+  }
+  return result;
+}
+
+void TrackedElementWebUI::SetVisible(bool visible, gfx::RectF bounds) {
+  last_known_bounds_ = bounds;
   if (visible == visible_)
     return;
 
diff --git a/components/user_education/webui/tracked_element_webui.h b/components/user_education/webui/tracked_element_webui.h
index 0e4adac..c95ded7a 100644
--- a/components/user_education/webui/tracked_element_webui.h
+++ b/components/user_education/webui/tracked_element_webui.h
@@ -9,6 +9,7 @@
 #include "ui/base/interaction/element_identifier.h"
 #include "ui/base/interaction/element_tracker.h"
 #include "ui/base/interaction/framework_specific_implementation.h"
+#include "ui/gfx/geometry/rect_f.h"
 
 namespace user_education {
 
@@ -23,18 +24,22 @@
 
   DECLARE_FRAMEWORK_SPECIFIC_METADATA()
 
-  HelpBubbleHandlerBase* handler() { return handler_; }
+  HelpBubbleHandlerBase* handler() const { return handler_; }
+
+  // ui::TrackedElement:
+  gfx::Rect GetScreenBounds() const override;
 
  private:
   friend class HelpBubbleHandlerBase;
 
-  void SetVisible(bool visible);
+  void SetVisible(bool visible, gfx::RectF bounds = gfx::RectF());
   void Activate();
   void CustomEvent(ui::CustomElementEventType event_type);
   bool visible() const { return visible_; }
 
   const base::raw_ptr<HelpBubbleHandlerBase> handler_;
   bool visible_ = false;
+  gfx::RectF last_known_bounds_;
 };
 
 }  // namespace user_education
diff --git a/components/viz/common/resources/shared_image_format.h b/components/viz/common/resources/shared_image_format.h
index 41d31a7..c7e57392 100644
--- a/components/viz/common/resources/shared_image_format.h
+++ b/components/viz/common/resources/shared_image_format.h
@@ -61,13 +61,6 @@
     k16F  // 16 bit float
   };
 
-  // TODO(kylechar): Replace usage of these constant with SinglePlanarFormat
-  // version and delete these.
-  static const SharedImageFormat kRGBA_8888;
-  static const SharedImageFormat kBGRA_8888;
-  static const SharedImageFormat kRGBA_F16;
-  static const SharedImageFormat kBGR_565;
-
   SharedImageFormat() = default;
   static constexpr SharedImageFormat SinglePlane(
       ResourceFormat resource_format) {
@@ -211,15 +204,6 @@
   SharedImageFormatUnion format_;
 };
 
-constexpr SharedImageFormat SharedImageFormat::kRGBA_8888 =
-    SharedImageFormat::SinglePlane(ResourceFormat::RGBA_8888);
-constexpr SharedImageFormat SharedImageFormat::kBGRA_8888 =
-    SharedImageFormat::SinglePlane(ResourceFormat::BGRA_8888);
-constexpr SharedImageFormat SharedImageFormat::kRGBA_F16 =
-    SharedImageFormat::SinglePlane(ResourceFormat::RGBA_F16);
-constexpr SharedImageFormat SharedImageFormat::kBGR_565 =
-    SharedImageFormat::SinglePlane(ResourceFormat::BGR_565);
-
 // Constants for common single-planar formats.
 namespace SinglePlaneFormat {
 inline constexpr SharedImageFormat kRGBA_8888 =
diff --git a/components/viz/service/display/display_resource_provider_skia_unittest.cc b/components/viz/service/display/display_resource_provider_skia_unittest.cc
index 670e818..62dd5f43 100644
--- a/components/viz/service/display/display_resource_provider_skia_unittest.cc
+++ b/components/viz/service/display/display_resource_provider_skia_unittest.cc
@@ -161,7 +161,7 @@
 
   ResourceId parent_id = resource_map[list.front().id];
 
-  auto format = SharedImageFormat::kRGBA_8888;
+  auto format = SinglePlaneFormat::kRGBA_8888;
   auto owned_image_context = std::make_unique<ExternalUseClient::ImageContext>(
       gpu::MailboxHolder(mailbox, sync_token1, GL_TEXTURE_2D), size, format,
       /*ycbcr_info=*/absl::nullopt, /*color_space=*/nullptr);
@@ -242,7 +242,7 @@
 
   ResourceId parent_id = resource_map[list.front().id];
 
-  auto format = SharedImageFormat::kRGBA_8888;
+  auto format = SinglePlaneFormat::kRGBA_8888;
   auto owned_image_context = std::make_unique<ExternalUseClient::ImageContext>(
       gpu::MailboxHolder(mailbox, sync_token1, GL_TEXTURE_2D), size, format,
       /*ycbcr_info=*/absl::nullopt, /*color_space=*/nullptr);
diff --git a/content/browser/accessibility/accessibility_tree_formatter_blink.cc b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
index e9c21d2..aaaacd62 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_blink.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
@@ -113,6 +113,8 @@
       return ui::ToString(static_cast<ax::mojom::HasPopup>(value));
     case ax::mojom::IntAttribute::kInvalidState:
       return ui::ToString(static_cast<ax::mojom::InvalidState>(value));
+    case ax::mojom::IntAttribute::kIsPopup:
+      return ui::ToString(static_cast<ax::mojom::IsPopup>(value));
     case ax::mojom::IntAttribute::kListStyle:
       return ui::ToString(static_cast<ax::mojom::ListStyle>(value));
     case ax::mojom::IntAttribute::kNameFrom:
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index a49946d..5e3aa0b9 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -64,6 +64,7 @@
   property_filters.emplace_back("horizontal", AXPropertyFilter::ALLOW);
   property_filters.emplace_back("multiselectable", AXPropertyFilter::ALLOW);
   property_filters.emplace_back("placeholder=*", AXPropertyFilter::ALLOW);
+  property_filters.emplace_back("ispopup*", AXPropertyFilter::ALLOW);
 
   // Deny most empty values.
   property_filters.emplace_back("*=''", AXPropertyFilter::DENY);
@@ -2796,10 +2797,9 @@
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityParam) {
   RunHtmlTest(FILE_PATH_LITERAL("param.html"));
 }
-// TODO(crbug.com/1367886): Test flaky on multiple platforms.
-IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
-                       DISABLED_AccessibilityPopupApi) {
-  RunHtmlTest(FILE_PATH_LITERAL("popup-api.html"));
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityPopoverApi) {
+  RunHtmlTest(FILE_PATH_LITERAL("popover-api.html"));
 }
 
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityPre) {
diff --git a/content/browser/accessibility/web_contents_accessibility_android.cc b/content/browser/accessibility/web_contents_accessibility_android.cc
index f4f11da..0d446fe 100644
--- a/content/browser/accessibility/web_contents_accessibility_android.cc
+++ b/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -1064,10 +1064,6 @@
   if (node->HasFloatAttribute(ax::mojom::FloatAttribute::kStepValueForRange)) {
     delta =
         node->GetFloatAttribute(ax::mojom::FloatAttribute::kStepValueForRange);
-
-    // If delta from step value is too small, increase to our minimum amount.
-    float minimum_move = (max - min) * kMinimumPercentageMoveForSliders;
-    delta = std::max(delta, minimum_move);
   } else {
     delta = (max - min) / kDefaultNumberOfTicksForSliders;
   }
diff --git a/content/browser/accessibility/web_contents_accessibility_android.h b/content/browser/accessibility/web_contents_accessibility_android.h
index 50b87dad..0ac33da 100644
--- a/content/browser/accessibility/web_contents_accessibility_android.h
+++ b/content/browser/accessibility/web_contents_accessibility_android.h
@@ -33,10 +33,6 @@
 // of 20 implies 20 steps, or a 5% move with each increment/decrement action.
 constexpr int kDefaultNumberOfTicksForSliders = 20;
 
-// The minimum amount a slider can move per increment/decement action as a
-// percentage of the total range, regardless of step value set on the element.
-constexpr float kMinimumPercentageMoveForSliders = 0.01f;
-
 // Max dimensions for the image data of a node.
 constexpr gfx::Size kMaxImageSize = gfx::Size(2000, 2000);
 }  // namespace
diff --git a/content/browser/android/scoped_surface_request_manager_unittest.cc b/content/browser/android/scoped_surface_request_manager_unittest.cc
index 209dcd7..55e2cae 100644
--- a/content/browser/android/scoped_surface_request_manager_unittest.cc
+++ b/content/browser/android/scoped_surface_request_manager_unittest.cc
@@ -25,7 +25,7 @@
     manager_->clear_requests_for_testing();
 
     last_received_request_ = 0;
-    dummy_token_ = base::UnguessableToken::Deserialize(123, 456);
+    dummy_token_ = base::UnguessableToken::CreateForTesting(123, 456);
 
     mock_texture_owner = base::MakeRefCounted<NiceMock<gpu::MockTextureOwner>>(
         0, nullptr, nullptr);
diff --git a/content/browser/attribution_reporting/BUILD.gn b/content/browser/attribution_reporting/BUILD.gn
index d1082c26..c443dfe 100644
--- a/content/browser/attribution_reporting/BUILD.gn
+++ b/content/browser/attribution_reporting/BUILD.gn
@@ -69,7 +69,7 @@
 
     deps = [
       "//base",
-      "//testing/gtest",
+      "//testing/gmock",
     ]
 
     data_deps = [ "//third_party/sqlite:sqlite_dev_shell" ]
diff --git a/content/browser/attribution_reporting/attribution_interop_unittest.cc b/content/browser/attribution_reporting/attribution_interop_unittest.cc
index 941e09d..274e4f4 100644
--- a/content/browser/attribution_reporting/attribution_interop_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_interop_unittest.cc
@@ -112,7 +112,6 @@
           AttributionSimulationOutputOptions{
               .remove_report_ids = true,
               .remove_assembled_report = true,
-              .remove_actual_report_times = true,
           },
   };
 
diff --git a/content/browser/attribution_reporting/attribution_storage_sql_query_plans_unittest.cc b/content/browser/attribution_reporting/attribution_storage_sql_query_plans_unittest.cc
index 0336bf9b0..fb07bc5 100644
--- a/content/browser/attribution_reporting/attribution_storage_sql_query_plans_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_storage_sql_query_plans_unittest.cc
@@ -13,12 +13,15 @@
 #include "content/browser/attribution_reporting/attribution_test_utils.h"
 #include "content/browser/attribution_reporting/sql_queries.h"
 #include "content/browser/attribution_reporting/sql_query_plan_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace content {
 namespace {
 
+using ::testing::AllOf;
+
 class AttributionSqlQueryPlanTest : public testing::Test {
  public:
   AttributionSqlQueryPlanTest() = default;
@@ -53,85 +56,60 @@
 };
 
 TEST_F(AttributionSqlQueryPlanTest, kMinPrioritySql) {
-  SqlQueryPlan plan = GetPlan(attribution_queries::kMinPrioritySql);
-  auto matcher = SqlIndexMatcher("event_level_reports_by_source_id");
-  EXPECT_TRUE(plan.UsesIndex(matcher)) << plan;
+  EXPECT_THAT(GetPlan(attribution_queries::kMinPrioritySql),
+              UsesIndex("event_level_reports_by_source_id"));
 }
 
 TEST_F(AttributionSqlQueryPlanTest, kGetMatchingSourcesSql) {
-  SqlQueryPlan plan = GetPlan(attribution_queries::kGetMatchingSourcesSql);
-  auto matcher = SqlIndexMatcher("sources_by_expiry_time");
-  EXPECT_TRUE(plan.UsesIndex(matcher)) << plan;
+  EXPECT_THAT(GetPlan(attribution_queries::kGetMatchingSourcesSql),
+              UsesIndex("sources_by_expiry_time"));
 }
 
 TEST_F(AttributionSqlQueryPlanTest, kSelectExpiredSourcesSql) {
-  SqlQueryPlan plan = GetPlan(attribution_queries::kSelectExpiredSourcesSql);
-  EXPECT_TRUE(plan.UsesIndex(SqlIndexMatcher("sources_by_expiry_time")
-                                 .set_type(SqlIndexMatcher::Type::kCovering)))
-      << plan;
-  EXPECT_TRUE(
-      plan.UsesIndex(SqlIndexMatcher("event_level_reports_by_source_id")))
-      << plan;
-  EXPECT_TRUE(plan.UsesIndex(SqlIndexMatcher("aggregate_source_id_idx")))
-      << plan;
+  EXPECT_THAT(GetPlan(attribution_queries::kSelectExpiredSourcesSql),
+              AllOf(UsesCoveringIndex("sources_by_expiry_time"),
+                    UsesIndex("event_level_reports_by_source_id"),
+                    UsesIndex("aggregate_source_id_idx")));
 }
 
 TEST_F(AttributionSqlQueryPlanTest, kSelectInactiveSourcesSql) {
-  SqlQueryPlan plan = GetPlan(attribution_queries::kSelectInactiveSourcesSql);
-  EXPECT_TRUE(plan.UsesIndex(
-      SqlIndexMatcher("sources_by_active_destination_site_reporting_origin")
-          .set_type(SqlIndexMatcher::Type::kCovering)
-          .set_columns({"event_level_active", "aggregatable_active"})))
-      << plan;
-  EXPECT_TRUE(
-      plan.UsesIndex(SqlIndexMatcher("event_level_reports_by_source_id")))
-      << plan;
-  EXPECT_TRUE(plan.UsesIndex(SqlIndexMatcher("aggregate_source_id_idx")))
-      << plan;
+  EXPECT_THAT(GetPlan(attribution_queries::kSelectInactiveSourcesSql),
+              AllOf(UsesCoveringIndex(
+                        "sources_by_active_destination_site_reporting_origin",
+                        {"event_level_active", "aggregatable_active"}),
+                    UsesIndex("event_level_reports_by_source_id"),
+                    UsesIndex("aggregate_source_id_idx")));
 }
 
 TEST_F(AttributionSqlQueryPlanTest, kScanCandidateData) {
-  SqlQueryPlan plan = GetPlan(attribution_queries::kScanCandidateData,
-                              SqlFullScanReason::kNotOptimized);
-  EXPECT_TRUE(
-      plan.UsesIndex(SqlIndexMatcher("event_level_reports_by_source_id")))
-      << plan;
+  EXPECT_THAT(GetPlan(attribution_queries::kScanCandidateData,
+                      SqlFullScanReason::kNotOptimized),
+              UsesIndex("event_level_reports_by_source_id"));
 }
 
 TEST_F(AttributionSqlQueryPlanTest, kDeleteVestigialConversionSql) {
-  SqlQueryPlan plan =
-      GetPlan(attribution_queries::kDeleteVestigialConversionSql);
-  EXPECT_TRUE(
-      plan.UsesIndex(SqlIndexMatcher("event_level_reports_by_source_id")))
-      << plan;
+  EXPECT_THAT(GetPlan(attribution_queries::kDeleteVestigialConversionSql),
+              UsesIndex("event_level_reports_by_source_id"));
 }
 
 TEST_F(AttributionSqlQueryPlanTest, kCountSourcesSql) {
-  SqlQueryPlan plan = GetPlan(attribution_queries::kCountSourcesSql);
-  EXPECT_TRUE(
-      plan.UsesIndex(SqlIndexMatcher("active_sources_by_source_origin")))
-      << plan;
+  EXPECT_THAT(GetPlan(attribution_queries::kCountSourcesSql),
+              UsesIndex("active_sources_by_source_origin"));
 }
+
 TEST_F(AttributionSqlQueryPlanTest, kDedupKeySql) {
-  SqlQueryPlan plan = GetPlan(attribution_queries::kDedupKeySql);
-  EXPECT_TRUE(plan.UsesIndex(
-      SqlIndexMatcher().set_type(SqlIndexMatcher::Type::kPrimaryKey)))
-      << plan;
+  EXPECT_THAT(GetPlan(attribution_queries::kDedupKeySql), UsesPrimaryKey());
 }
 
 TEST_F(AttributionSqlQueryPlanTest, kScanCandidateDataAggregatable) {
-  SqlQueryPlan plan =
-      GetPlan(attribution_queries::kScanCandidateDataAggregatable,
-              SqlFullScanReason::kNotOptimized);
-  EXPECT_TRUE(plan.UsesIndex(SqlIndexMatcher("aggregate_source_id_idx")))
-      << plan;
+  EXPECT_THAT(GetPlan(attribution_queries::kScanCandidateDataAggregatable,
+                      SqlFullScanReason::kNotOptimized),
+              UsesIndex("aggregate_source_id_idx"));
 }
 
 TEST_F(AttributionSqlQueryPlanTest, kDeleteAggregationsSql) {
-  SqlQueryPlan plan = GetPlan(attribution_queries::kDeleteAggregationsSql);
-  EXPECT_TRUE(plan.UsesIndex(SqlIndexMatcher("aggregate_source_id_idx")
-                                 .set_type(SqlIndexMatcher::Type::kCovering)))
-      << plan;
+  EXPECT_THAT(GetPlan(attribution_queries::kDeleteAggregationsSql),
+              UsesCoveringIndex("aggregate_source_id_idx"));
 }
 
 }  // namespace
diff --git a/content/browser/attribution_reporting/sql_query_plan_test_util.cc b/content/browser/attribution_reporting/sql_query_plan_test_util.cc
index c255ccf4..36554ee8 100644
--- a/content/browser/attribution_reporting/sql_query_plan_test_util.cc
+++ b/content/browser/attribution_reporting/sql_query_plan_test_util.cc
@@ -4,7 +4,10 @@
 
 #include "content/browser/attribution_reporting/sql_query_plan_test_util.h"
 
+#include <ostream>
+#include <string>
 #include <utility>
+#include <vector>
 
 #include "base/check.h"
 #include "base/command_line.h"
@@ -17,7 +20,9 @@
 #include "base/strings/strcat.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
+#include "base/types/expected.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace content {
 
@@ -29,24 +34,60 @@
   return path.AppendASCII(name);
 }
 
-}  // namespace
+class SqlIndexMatcher {
+ public:
+  using is_gtest_matcher = void;
 
-SqlIndexMatcher::SqlIndexMatcher() = default;
-SqlIndexMatcher::SqlIndexMatcher(std::string name) : name_(std::move(name)) {}
-SqlIndexMatcher::~SqlIndexMatcher() = default;
+  // Specifies the type of index that we should match with. Note this also
+  // covers primary keys which are implemented as indexes in sqlite.
+  enum class Type {
+    kAny,         // USING INDEX, or any of the other options with match
+    kCovering,    // USING COVERING INDEX
+    kPrimaryKey,  // USING PRIMARY KEY
+  };
 
-SqlIndexMatcher::SqlIndexMatcher(const SqlIndexMatcher&) = default;
-SqlIndexMatcher& SqlIndexMatcher::operator=(const SqlIndexMatcher&) = default;
+  // Every sqlite index includes a list of indexed columns. However, some query
+  // plans will only use a subset of the columns in the index. This matcher is
+  // designed to enforce that a given subset of columns are actually used by the
+  // query planner. Note that this list doesn't have to be exhaustive, and
+  // plans that use a superset of columns listed in `columns` will still match.
+  SqlIndexMatcher(std::string name, std::vector<std::string> columns, Type type)
+      : name_(std::move(name)), columns_(std::move(columns)), type_(type) {
+    switch (type_) {
+      case Type::kAny:
+      case Type::kCovering:
+        CHECK_NE(name_, "");
+        break;
+      case Type::kPrimaryKey:
+        CHECK_EQ(name_, "");
+        break;
+    }
+  }
 
-SqlQueryPlan::SqlQueryPlan(std::string query, std::string plan)
-    : query_(std::move(query)), plan_(std::move(plan)) {}
+  bool MatchAndExplain(const SqlQueryPlan&, std::ostream*) const;
 
-SqlQueryPlan::~SqlQueryPlan() = default;
+  void DescribeTo(std::ostream* out) const {
+    return DescribeTo(out, /*negated=*/false);
+  }
 
-bool SqlQueryPlan::UsesIndex(const SqlIndexMatcher& matcher) const {
-  base::StringPiece plan_piece(plan_);
+  void DescribeNegationTo(std::ostream* out) const {
+    return DescribeTo(out, /*negated=*/true);
+  }
 
-  size_t start_pos = matcher.FindIndexStart(plan_piece);
+ private:
+  void DescribeTo(std::ostream*, bool negated) const;
+  size_t FindIndexStart(base::StringPiece plan) const;
+
+  std::string name_;
+  std::vector<std::string> columns_;
+  Type type_;
+};
+
+bool SqlIndexMatcher::MatchAndExplain(const SqlQueryPlan& plan,
+                                      std::ostream*) const {
+  base::StringPiece plan_piece(plan.plan);
+
+  size_t start_pos = FindIndexStart(plan_piece);
   if (start_pos == std::string::npos) {
     return false;
   }
@@ -56,25 +97,19 @@
   base::StringPiece index_text =
       plan_piece.substr(start_pos, end_pos - start_pos);
 
-  return base::ranges::all_of(matcher.columns(),
-                              [index_text](const std::string& col) {
-                                return base::Contains(index_text, col);
-                              });
-}
-
-bool SqlQueryPlan::HasFullTableScan() const {
-  return base::Contains(plan_, "SCAN");
+  return base::ranges::all_of(columns_, [index_text](const std::string& col) {
+    return base::Contains(index_text, col);
+  });
 }
 
 size_t SqlIndexMatcher::FindIndexStart(base::StringPiece plan) const {
-  std::string covering_prefix = base::StrCat({"USING COVERING INDEX ", name()});
-  std::string noncovering_prefix = base::StrCat({"USING INDEX ", name()});
+  std::string covering_prefix = base::StrCat({"USING COVERING INDEX ", name_});
+  std::string noncovering_prefix = base::StrCat({"USING INDEX ", name_});
   std::string primary_prefix = "USING PRIMARY KEY ";
-  switch (type()) {
+  switch (type_) {
     case SqlIndexMatcher::Type::kCovering:
       return plan.find(covering_prefix);
     case SqlIndexMatcher::Type::kPrimaryKey:
-      DCHECK(name().empty());
       return plan.find(primary_prefix);
     case SqlIndexMatcher::Type::kAny:
       for (const base::StringPiece prefix :
@@ -88,8 +123,63 @@
   }
 }
 
+void SqlIndexMatcher::DescribeTo(std::ostream* out, bool negated) const {
+  if (negated) {
+    *out << "does not use ";
+  } else {
+    *out << "uses ";
+  }
+
+  switch (type_) {
+    case Type::kAny:
+      *out << "index " << name_;
+      break;
+    case Type::kCovering:
+      *out << "covering index " << name_;
+      break;
+    case Type::kPrimaryKey:
+      *out << "primary key";
+      break;
+  }
+
+  if (columns_.empty()) {
+    return;
+  }
+
+  *out << " with columns";
+  const char* separator = " ";
+
+  for (const auto& column : columns_) {
+    *out << separator << column;
+    separator = ", ";
+  }
+}
+
+bool HasFullTableScan(const SqlQueryPlan& plan) {
+  return base::Contains(plan.plan, "SCAN");
+}
+
+}  // namespace
+
+testing::Matcher<SqlQueryPlan> UsesIndex(std::string name,
+                                         std::vector<std::string> columns) {
+  return SqlIndexMatcher(std::move(name), std::move(columns),
+                         SqlIndexMatcher::Type::kAny);
+}
+
+testing::Matcher<SqlQueryPlan> UsesCoveringIndex(
+    std::string name,
+    std::vector<std::string> columns) {
+  return SqlIndexMatcher(std::move(name), std::move(columns),
+                         SqlIndexMatcher::Type::kCovering);
+}
+
+testing::Matcher<SqlQueryPlan> UsesPrimaryKey() {
+  return SqlIndexMatcher("", {}, SqlIndexMatcher::Type::kPrimaryKey);
+}
+
 std::ostream& operator<<(std::ostream& out, const SqlQueryPlan& plan) {
-  return out << plan.query_ << "\n" << plan.plan_;
+  return out << plan.query << "\n" << plan.plan;
 }
 
 SqlQueryPlanExplainer::SqlQueryPlanExplainer(base::FilePath db_path)
@@ -98,7 +188,8 @@
 
 SqlQueryPlanExplainer::~SqlQueryPlanExplainer() = default;
 
-absl::optional<SqlQueryPlan> SqlQueryPlanExplainer::GetPlan(
+base::expected<SqlQueryPlan, SqlQueryPlanExplainer::Error>
+SqlQueryPlanExplainer::GetPlan(
     std::string query,
     absl::optional<SqlFullScanReason> full_scan_reason) {
   base::CommandLine command_line(shell_path_);
@@ -108,26 +199,26 @@
   command_line.AppendArg(explain_query);
 
   std::string output;
-  if (!base::GetAppOutputAndError(command_line, &output)) {
-    return absl::nullopt;
+  if (!base::GetAppOutputAndError(command_line, &output) ||
+      !base::StartsWith(output, "QUERY PLAN")) {
+    return base::unexpected(Error::kInvalidOutput);
   }
 
-  if (!base::StartsWith(output, "QUERY PLAN")) {
-    return absl::nullopt;
+  SqlQueryPlan plan{
+      .query = std::move(query),
+      .plan = std::move(output),
+  };
+
+  bool plan_has_full_scan = HasFullTableScan(plan);
+
+  if (plan_has_full_scan && !full_scan_reason.has_value()) {
+    return base::unexpected(Error::kMissingFullScanAnnotation);
   }
 
-  SqlQueryPlan plan(std::move(query), std::move(output));
-
-  if (full_scan_reason.has_value()) {
-    EXPECT_TRUE(plan.HasFullTableScan())
-        << "Plan has out of date SqlFullScanReason. No full scan was found:\n"
-        << plan;
-  } else {
-    EXPECT_FALSE(plan.HasFullTableScan())
-        << "Plan has a full table scan, which must be "
-           "annotated with a SqlFullScanReason:\n"
-        << plan;
+  if (!plan_has_full_scan && full_scan_reason.has_value()) {
+    return base::unexpected(Error::kExtraneousFullScanAnnotation);
   }
+
   return plan;
 }
 
diff --git a/content/browser/attribution_reporting/sql_query_plan_test_util.h b/content/browser/attribution_reporting/sql_query_plan_test_util.h
index c68c908..cb91783 100644
--- a/content/browser/attribution_reporting/sql_query_plan_test_util.h
+++ b/content/browser/attribution_reporting/sql_query_plan_test_util.h
@@ -5,91 +5,39 @@
 #ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_SQL_QUERY_PLAN_TEST_UTIL_H_
 #define CONTENT_BROWSER_ATTRIBUTION_REPORTING_SQL_QUERY_PLAN_TEST_UTIL_H_
 
-#include <ostream>
+#include <iosfwd>
 #include <string>
 #include <vector>
 
 #include "base/files/file_path.h"
-#include "base/strings/string_piece_forward.h"
-
+#include "base/types/expected.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace content {
 
 // TODO(crbug.com/1407007): Move these utilities to //sql once they are trialed
 // in the attribution_reporting directory.
-//
-// Class which specifies how to match an index in a query plan.
-class SqlIndexMatcher {
- public:
-  // Only matches an index with the given name. Note, for primary key indices,
-  // this is unused, so the constructor without the name field should be used.
-  explicit SqlIndexMatcher(std::string name);
-  SqlIndexMatcher();
-  ~SqlIndexMatcher();
 
-  SqlIndexMatcher(const SqlIndexMatcher&);
-  SqlIndexMatcher& operator=(const SqlIndexMatcher& o);
-
-  // Every sqlite index includes a list of indexed columns. However, some query
-  // plans will only use a subset of the columns in the index. This matcher is
-  // designed to enforce that a given subset of columns are actually used by the
-  // query planner. Note that this list doesn't have to be exhaustive, and
-  // plans that use a superset of columns than ones listed in `columns` will
-  // still match.
-  SqlIndexMatcher& set_columns(std::vector<std::string> columns) {
-    columns_ = std::move(columns);
-    return *this;
-  }
-
-  // Specifies the type of index that we should match with. Note this also
-  // covers primary keys which are implemented as indexes in sqlite.
-  enum class Type {
-    kAny,         // USING INDEX, or any of the other options with match
-    kCovering,    // USING COVERING INDEX
-    kPrimaryKey,  // USING PRIMARY KEY
-  };
-  SqlIndexMatcher& set_type(Type type) {
-    type_ = type;
-    return *this;
-  }
-
-  const std::string& name() const { return name_; }
-  const std::vector<std::string>& columns() const { return columns_; }
-  Type type() const { return type_; }
-
-  size_t FindIndexStart(base::StringPiece plan) const;
-
- private:
-  std::string name_;
-  std::vector<std::string> columns_;
-  Type type_ = Type::kAny;
-};
-
-// This class wraps a returned sqlite query plan, as returned from EXPLAIN QUERY
-// PLAN, and allows making various checks on its properties.
-class SqlQueryPlan {
- public:
-  SqlQueryPlan(std::string query, std::string plan);
-  ~SqlQueryPlan();
-
-  // Returns true if the query plan uses the index specified by `index`.
-  [[nodiscard]] bool UsesIndex(const SqlIndexMatcher& matcher) const;
-
-  // Returns true if the query plan does any full table scan, i.e. it includes a
-  // SCAN directive.
-  [[nodiscard]] bool HasFullTableScan() const;
-
- private:
-  friend std::ostream& operator<<(std::ostream& out, const SqlQueryPlan& plan);
-
-  const std::string query_;
-  const std::string plan_;
+// This type wraps a returned sqlite query plan, as returned from EXPLAIN QUERY
+// PLAN.
+struct SqlQueryPlan {
+  std::string query;
+  std::string plan;
 };
 
 // Only for diagnostic messages, not for test expectations, as the underlying
 // query plan format is fragile and should not be relied upon.
-std::ostream& operator<<(std::ostream& out, const SqlQueryPlan& plan);
+std::ostream& operator<<(std::ostream&, const SqlQueryPlan&);
+
+testing::Matcher<SqlQueryPlan> UsesIndex(std::string name,
+                                         std::vector<std::string> columns = {});
+
+testing::Matcher<SqlQueryPlan> UsesCoveringIndex(
+    std::string name,
+    std::vector<std::string> columns = {});
+
+testing::Matcher<SqlQueryPlan> UsesPrimaryKey();
 
 // Enum explaining why a full scan on a query is needed. For use when annotating
 // tests which use queries that perform a full table scan.
@@ -105,6 +53,12 @@
 // queries, in the context of the passed in `db_path`.
 class SqlQueryPlanExplainer {
  public:
+  enum class Error {
+    kInvalidOutput,
+    kMissingFullScanAnnotation,
+    kExtraneousFullScanAnnotation,
+  };
+
   explicit SqlQueryPlanExplainer(base::FilePath db_path);
 
   ~SqlQueryPlanExplainer();
@@ -113,7 +67,7 @@
   // test expectations based on the SqlFullScanReason, which enforces by default
   // that query plans should not perform full table scans and must be annotated
   // when they do.
-  absl::optional<SqlQueryPlan> GetPlan(
+  base::expected<SqlQueryPlan, Error> GetPlan(
       std::string query,
       absl::optional<SqlFullScanReason> full_scan_reason = absl::nullopt);
 
diff --git a/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc b/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc
index ac3bbfb..268c4ab1 100644
--- a/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc
+++ b/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc
@@ -211,10 +211,10 @@
   // If Picture-in-Picture there shouldn't be an active session.
   EXPECT_FALSE(controller->active_session_for_testing());
 
-  viz::SurfaceId surface_id =
-      viz::SurfaceId(viz::FrameSinkId(1, 1),
-                     viz::LocalSurfaceId(
-                         11, base::UnguessableToken::Deserialize(0x111111, 0)));
+  viz::SurfaceId surface_id = viz::SurfaceId(
+      viz::FrameSinkId(1, 1),
+      viz::LocalSurfaceId(
+          11, base::UnguessableToken::CreateForTesting(0x111111, 0)));
 
   EXPECT_CALL(delegate(), EnterPictureInPicture(contents()))
       .WillRepeatedly(testing::Return(PictureInPictureResult::kSuccess));
@@ -257,10 +257,10 @@
 
   mojo::PendingRemote<blink::mojom::PictureInPictureSessionObserver>
       observer_remote;
-  viz::SurfaceId surface_id =
-      viz::SurfaceId(viz::FrameSinkId(1, 1),
-                     viz::LocalSurfaceId(
-                         11, base::UnguessableToken::Deserialize(0x111111, 0)));
+  viz::SurfaceId surface_id = viz::SurfaceId(
+      viz::FrameSinkId(1, 1),
+      viz::LocalSurfaceId(
+          11, base::UnguessableToken::CreateForTesting(0x111111, 0)));
 
   EXPECT_CALL(delegate(), EnterPictureInPicture(contents()))
       .WillRepeatedly(testing::Return(PictureInPictureResult::kNotSupported));
diff --git a/content/browser/renderer_host/media/video_capture_unittest.cc b/content/browser/renderer_host/media/video_capture_unittest.cc
index 413154de..10f82fc 100644
--- a/content/browser/renderer_host/media/video_capture_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_unittest.cc
@@ -68,7 +68,7 @@
 // video_capture_host. This is an arbitrary value.
 const base::UnguessableToken& DeviceId() {
   static const base::UnguessableToken device_id(
-      base::UnguessableToken::Deserialize(555, 555));
+      base::UnguessableToken::CreateForTesting(555, 555));
   return device_id;
 }
 
diff --git a/content/browser/renderer_host/navigation_request_unittest.cc b/content/browser/renderer_host/navigation_request_unittest.cc
index a6c3f46..63ea2f2 100644
--- a/content/browser/renderer_host/navigation_request_unittest.cc
+++ b/content/browser/renderer_host/navigation_request_unittest.cc
@@ -662,7 +662,7 @@
   child_document =
       static_cast<TestRenderFrameHost*>(navigation->GetFinalRenderFrameHost());
   EXPECT_TRUE(child_document->IsCredentialless());
-  EXPECT_EQ(blink::StorageKey::CreateWithNonce(
+  EXPECT_EQ(blink::StorageKey::CreateWithNonceForTesting(
                 url::Origin::Create(kUrl),
                 child_document->GetMainFrame()->credentialless_iframes_nonce()),
             child_document->storage_key());
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 0d02045..c205889 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -158,7 +158,7 @@
 
 const viz::LocalSurfaceId kArbitraryLocalSurfaceId(
     1,
-    base::UnguessableToken::Deserialize(2, 3));
+    base::UnguessableToken::CreateForTesting(2, 3));
 
 std::string GetMessageNames(
     const MockWidgetInputHandler::MessageVector& events) {
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
index 2cd94c4..12ddb35 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
@@ -52,7 +52,7 @@
 
 const viz::LocalSurfaceId kArbitraryLocalSurfaceId(
     1,
-    base::UnguessableToken::Deserialize(2, 3));
+    base::UnguessableToken::CreateForTesting(2, 3));
 
 blink::mojom::ScrollResultDataPtr MakeDefaultScrollResultData() {
   return blink::mojom::ScrollResultData::New(
diff --git a/content/browser/site_per_process_oopsif_browsertest.cc b/content/browser/site_per_process_oopsif_browsertest.cc
index 9f3dedf..11abe48 100644
--- a/content/browser/site_per_process_oopsif_browsertest.cc
+++ b/content/browser/site_per_process_oopsif_browsertest.cc
@@ -355,6 +355,18 @@
             parent_site_instance->GetSiteInfo().site_url());
 }
 
+namespace {
+
+GURL GetFrameBaseUrl(RenderFrameHostImpl* rfhi) {
+  return GURL(EvalJs(rfhi, "document.baseURI").ExtractString());
+}
+
+GURL GetFrameBaseUrl(Shell* shell) {
+  return GURL(EvalJs(shell, "document.baseURI").ExtractString());
+}
+
+}  // namespace
+
 IN_PROC_BROWSER_TEST_P(SitePerProcessPerOriginIsolatedSandboxedIframeTest,
                        SrcdocSandboxedFrameInsideAboutBlank) {
   // Open main page on a.foo.com. It will be put in a site instance with site
@@ -379,7 +391,7 @@
   {
     std::string js_str =
         "const frame = document.createElement('iframe'); "
-        "frame.sandbox = ''; "
+        "frame.sandbox = 'allow-scripts'; "
         "frame.srcdoc = 'foo'; "
         "document.body.appendChild(frame);";
     EXPECT_TRUE(ExecJs(child, js_str));
@@ -395,7 +407,7 @@
   // TODO(https://crbug.com/1356658): The srcdoc iframe should really report
   // a base url that matches `main_url`.
   EXPECT_EQ(GURL("about:blank"),
-            grand_child->current_frame_host()->GetBaseUrl());
+            GetFrameBaseUrl(grand_child->current_frame_host()));
 }
 
 // Similar to SrcdocSandboxedFrameWithNonSiteParent, but this time the srcdoc
@@ -1419,16 +1431,11 @@
   ASSERT_EQ(1U, root->child_count());
   FrameTreeNode* child = root->child_at(0);
   // Make sure the parent's base url propagates properly to the child.
-  GURL parent_base_url = root->current_frame_host()->GetBaseUrl();
-  GURL child_base_url = child->current_frame_host()->GetBaseUrl();
+  GURL parent_base_url = GetFrameBaseUrl(root->current_frame_host());
+  GURL child_base_url = GetFrameBaseUrl(child->current_frame_host());
+  // Verify child inherited base url from parent as expected.
   EXPECT_EQ(parent_base_url, child_base_url);
 
-  // Verify child got base url from parent as expected.
-  EXPECT_EQ(parent_base_url, child->current_frame_host()->GetBaseUrl());
-  EXPECT_EQ(parent_base_url,
-            GURL(EvalJs(child->current_frame_host(), "document.baseURI")
-                     .ExtractString()));
-
   // Switch the base url of the root.
   GURL new_root_base_url("http://b.com/");
   {
@@ -1438,8 +1445,7 @@
         "document.head.appendChild(base_element);",
         new_root_base_url.spec().c_str());
     EXPECT_TRUE(ExecJs(shell(), js_str));
-    EXPECT_EQ(new_root_base_url,
-              GURL(EvalJs(shell(), "document.baseURI").ExtractString()));
+    EXPECT_EQ(new_root_base_url, GetFrameBaseUrl(shell()));
   }
 
   // Create sandboxed srcdoc grandchild frame.
@@ -1458,14 +1464,8 @@
   // Make sure the child's snapshotted base url propagates properly to the
   // grandchild. And make sure child's snapshotted base url hasn't changed with
   // the creation of the child.
-  EXPECT_EQ(parent_base_url, child->current_frame_host()->GetBaseUrl());
-  EXPECT_EQ(parent_base_url, grandchild->current_frame_host()->GetBaseUrl());
-  EXPECT_EQ(parent_base_url,
-            GURL(EvalJs(child->current_frame_host(), "document.baseURI")
-                     .ExtractString()));
-  EXPECT_EQ(parent_base_url,
-            GURL(EvalJs(grandchild->current_frame_host(), "document.baseURI")
-                     .ExtractString()));
+  EXPECT_EQ(parent_base_url, GetFrameBaseUrl(child->current_frame_host()));
+  EXPECT_EQ(parent_base_url, GetFrameBaseUrl(grandchild->current_frame_host()));
 }
 
 // Test to verify that nested sandboxed iframes aren't put in the same
@@ -1742,13 +1742,10 @@
   EXPECT_EQ(GURL(url::kAboutSrcdocURL), child->current_url());
   EXPECT_EQ("srcdoc test content", child->srcdoc_value());
   if (SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled()) {
-    EXPECT_EQ(main_url, child->parent()->GetBaseUrl());
     EXPECT_EQ(main_url, child->current_frame_host()
                             ->snapshotted_base_url_from_parent_for_testing());
   }
-  EXPECT_EQ(main_url,
-            GURL(EvalJs(child->current_frame_host(), "document.baseURI")
-                     .ExtractString()));
+  EXPECT_EQ(main_url, GetFrameBaseUrl(child->current_frame_host()));
 
   // Reset the srcdoc attribute, and verify the FrameTreeNode is updated
   // accordingly.
@@ -1773,11 +1770,7 @@
   EXPECT_EQ("", child->srcdoc_value());
   // The base url is set on the parent, and not cleared with the child's srcdoc
   // information.
-  if (SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled())
-    EXPECT_EQ(main_url, child->parent()->GetBaseUrl());
-  EXPECT_EQ(main_url,
-            GURL(EvalJs(child->current_frame_host(), "document.baseURI")
-                     .ExtractString()));
+  EXPECT_EQ(main_url, GetFrameBaseUrl(child->current_frame_host()));
 
   // Repeat the srcdoc attribute tests from above, but this time using
   // src='about:srcdoc' to make the frame srcdoc.
@@ -1796,13 +1789,10 @@
   EXPECT_EQ(GURL(url::kAboutSrcdocURL), child2->current_url());
   EXPECT_EQ("", child2->srcdoc_value());
   if (SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled()) {
-    EXPECT_EQ(main_url, child2->parent()->GetBaseUrl());
     EXPECT_EQ(main_url, child2->current_frame_host()
                             ->snapshotted_base_url_from_parent_for_testing());
   }
-  EXPECT_EQ(main_url,
-            GURL(EvalJs(child->current_frame_host(), "document.baseURI")
-                     .ExtractString()));
+  EXPECT_EQ(main_url, GetFrameBaseUrl(child->current_frame_host()));
 
   // Reset the src attribute, and verify the FrameTreeNode is updated
   // accordingly.
@@ -1853,8 +1843,7 @@
       root_ftn->current_frame_host()->base_url_from_renderer_for_testing());
   EXPECT_EQ(GURL(), root_ftn->current_frame_host()
                         ->snapshotted_base_url_from_parent_for_testing());
-  if (SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled())
-    EXPECT_EQ(main_url, root_ftn->current_frame_host()->GetBaseUrl());
+  EXPECT_EQ(main_url, GetFrameBaseUrl(root_ftn->current_frame_host()));
 
   // The page modifies its base element to set a non-standard value the browser
   // knows nothing about, so the renderer sends it to the browser.
@@ -1877,8 +1866,8 @@
     EXPECT_EQ(
         foo_url,
         root_ftn->current_frame_host()->base_url_from_renderer_for_testing());
-    EXPECT_EQ(foo_url, root_ftn->current_frame_host()->GetBaseUrl());
   }
+  EXPECT_EQ(foo_url, GetFrameBaseUrl(root_ftn->current_frame_host()));
   EXPECT_EQ(GURL(), root_ftn->current_frame_host()
                         ->snapshotted_base_url_from_parent_for_testing());
 
@@ -1897,8 +1886,7 @@
       root_ftn->current_frame_host()->base_url_from_renderer_for_testing());
   EXPECT_EQ(GURL(), root_ftn->current_frame_host()
                         ->snapshotted_base_url_from_parent_for_testing());
-  if (SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled())
-    EXPECT_EQ(main_url, root_ftn->current_frame_host()->GetBaseUrl());
+  EXPECT_EQ(main_url, GetFrameBaseUrl(root_ftn->current_frame_host()));
 }
 
 // A test to make sure that a sandboxed srcdoc iframe correctly updates its
@@ -1925,11 +1913,8 @@
                             ->GetPrimaryFrameTree()
                             .root();
   auto* child = root->child_at(0);
-  EXPECT_EQ(main_url, GURL(EvalJs(child, "document.baseURI").ExtractString()));
-  if (SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled()) {
-    EXPECT_EQ(main_url, root->current_frame_host()->GetBaseUrl());
-    EXPECT_EQ(main_url, child->current_frame_host()->GetBaseUrl());
-  }
+  EXPECT_EQ(main_url, GetFrameBaseUrl(child->current_frame_host()));
+  EXPECT_EQ(main_url, GetFrameBaseUrl(root->current_frame_host()));
 
   // Srcdoc frame changes its base url.
   GURL b_url("http://b.com/");
@@ -1940,11 +1925,11 @@
         "document.head.appendChild(base_element);",
         b_url.spec().c_str());
     EXPECT_TRUE(ExecJs(child, js_str));
-    EXPECT_EQ(b_url, GURL(EvalJs(child, "document.baseURI").ExtractString()));
+    EXPECT_EQ(b_url, GetFrameBaseUrl(child->current_frame_host()));
   }
+  EXPECT_EQ(main_url, GetFrameBaseUrl(root->current_frame_host()));
+  EXPECT_EQ(b_url, GetFrameBaseUrl(child->current_frame_host()));
   if (SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled()) {
-    EXPECT_EQ(main_url, root->current_frame_host()->GetBaseUrl());
-    EXPECT_EQ(b_url, child->current_frame_host()->GetBaseUrl());
     EXPECT_EQ(
         b_url,
         child->current_frame_host()->base_url_from_renderer_for_testing());
@@ -1961,14 +1946,13 @@
         "document.head.appendChild(base_element);",
         c_url.spec().c_str());
     EXPECT_TRUE(ExecJs(root, js_str));
-    EXPECT_EQ(c_url, GURL(EvalJs(root, "document.baseURI").ExtractString()));
+    EXPECT_EQ(c_url, GetFrameBaseUrl(root->current_frame_host()));
   }
-  EXPECT_EQ(b_url, GURL(EvalJs(child, "document.baseURI").ExtractString()));
+  EXPECT_EQ(b_url, GetFrameBaseUrl(child->current_frame_host()));
+  EXPECT_EQ(c_url, GetFrameBaseUrl(root->current_frame_host()));
   if (SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled()) {
-    EXPECT_EQ(c_url, root->current_frame_host()->GetBaseUrl());
     EXPECT_EQ(c_url,
               root->current_frame_host()->base_url_from_renderer_for_testing());
-    EXPECT_EQ(b_url, child->current_frame_host()->GetBaseUrl());
     // The snapshotted base url from the root doesn't change.
     EXPECT_EQ(main_url, child->current_frame_host()
                             ->snapshotted_base_url_from_parent_for_testing());
@@ -1981,19 +1965,17 @@
   {
     EXPECT_TRUE(ExecJs(child, "document.querySelector('base').remove();"));
     if (SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled()) {
-      EXPECT_EQ(main_url,
-                GURL(EvalJs(child, "document.baseURI").ExtractString()));
+      EXPECT_EQ(main_url, GetFrameBaseUrl(child->current_frame_host()));
     } else {
       // TODO(wjmaclean): we know this expectation is wrong, and needs to be
       // fixed. https://crbug.com/1356658
-      EXPECT_EQ(c_url, GURL(EvalJs(child, "document.baseURI").ExtractString()));
+      EXPECT_EQ(c_url, GetFrameBaseUrl(child->current_frame_host()));
     }
   }
+  EXPECT_EQ(c_url, GetFrameBaseUrl(root->current_frame_host()));
   if (SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled()) {
-    EXPECT_EQ(c_url, root->current_frame_host()->GetBaseUrl());
     EXPECT_EQ(c_url,
               root->current_frame_host()->base_url_from_renderer_for_testing());
-    EXPECT_EQ(main_url, child->current_frame_host()->GetBaseUrl());
     // The snapshotted base url from the root still doesn't change.
     EXPECT_EQ(main_url, child->current_frame_host()
                             ->snapshotted_base_url_from_parent_for_testing());
@@ -2023,7 +2005,7 @@
         "document.head.appendChild(base_element);",
         b_url.spec().c_str());
     EXPECT_TRUE(ExecJs(root, js_str));
-    EXPECT_EQ(b_url, GURL(EvalJs(root, "document.baseURI").ExtractString()));
+    EXPECT_EQ(b_url, GetFrameBaseUrl(root->current_frame_host()));
   }
 
   // Create srcdoc iframe inheriting a base url of b.com.
@@ -2037,31 +2019,23 @@
     ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
   }
   auto* child = root->child_at(0);
-  EXPECT_EQ(b_url, GURL(EvalJs(child, "document.baseURI").ExtractString()));
-  if (SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled()) {
-    EXPECT_EQ(b_url, root->current_frame_host()->GetBaseUrl());
-    EXPECT_EQ(b_url, child->current_frame_host()->GetBaseUrl());
-  }
+  EXPECT_EQ(b_url, GetFrameBaseUrl(child->current_frame_host()));
+  EXPECT_EQ(b_url, GetFrameBaseUrl(root->current_frame_host()));
 
   // Remove base element from root.
   {
     EXPECT_TRUE(ExecJs(root, "document.querySelector('base').remove();"));
-    EXPECT_EQ(main_url, GURL(EvalJs(root, "document.baseURI").ExtractString()));
+    EXPECT_EQ(main_url, GetFrameBaseUrl(root->current_frame_host()));
   }
-  EXPECT_EQ(b_url, GURL(EvalJs(child, "document.baseURI").ExtractString()));
-  if (SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled()) {
-    EXPECT_EQ(main_url, root->current_frame_host()->GetBaseUrl());
-    EXPECT_EQ(b_url, child->current_frame_host()->GetBaseUrl());
-  }
+  EXPECT_EQ(b_url, GetFrameBaseUrl(child->current_frame_host()));
+  EXPECT_EQ(main_url, GetFrameBaseUrl(root->current_frame_host()));
 
   // Reload child.
   {
     EXPECT_TRUE(ExecJs(child, "location.reload();"));
     ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
   }
-  EXPECT_EQ(main_url, GURL(EvalJs(child, "document.baseURI").ExtractString()));
-  if (SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled())
-    EXPECT_EQ(main_url, child->current_frame_host()->GetBaseUrl());
+  EXPECT_EQ(main_url, GetFrameBaseUrl(child->current_frame_host()));
 }
 
 IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
@@ -2081,7 +2055,7 @@
       root_ftn->current_frame_host()->base_url_from_renderer_for_testing());
   EXPECT_EQ(GURL(), root_ftn->current_frame_host()
                         ->snapshotted_base_url_from_parent_for_testing());
-  EXPECT_EQ(main_url, root_ftn->current_frame_host()->GetBaseUrl());
+  EXPECT_EQ(main_url, GetFrameBaseUrl(root_ftn->current_frame_host()));
 
   // The page modifies its base element to set a non-standard value the browser
   // knows nothing about, so the renderer sends it to the browser.
@@ -2105,7 +2079,7 @@
       root_ftn->current_frame_host()->base_url_from_renderer_for_testing());
   EXPECT_EQ(GURL(), root_ftn->current_frame_host()
                         ->snapshotted_base_url_from_parent_for_testing());
-  EXPECT_EQ(foo_url, root_ftn->current_frame_host()->GetBaseUrl());
+  EXPECT_EQ(foo_url, GetFrameBaseUrl(root_ftn->current_frame_host()));
 
   // When the frame navigates to a new document, we don't expect the old base
   // url to persist.
@@ -2116,7 +2090,7 @@
       root_ftn->current_frame_host()->base_url_from_renderer_for_testing());
   EXPECT_EQ(GURL(), root_ftn->current_frame_host()
                         ->snapshotted_base_url_from_parent_for_testing());
-  EXPECT_EQ(main_url2, root_ftn->current_frame_host()->GetBaseUrl());
+  EXPECT_EQ(main_url2, GetFrameBaseUrl(root_ftn->current_frame_host()));
 }
 
 // This test verifies that using enterprise policy to disable
@@ -2136,7 +2110,7 @@
   StartEmbeddedServer();
   GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
-  EXPECT_NE("about:blank", EvalJs(shell(), "document.baseURI").ExtractString());
+  EXPECT_NE(GURL("about:blank"), GetFrameBaseUrl(shell()));
 
   FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                             ->GetPrimaryFrameTree()
@@ -2144,7 +2118,7 @@
   ShellAddedObserver new_shell_observer;
   EXPECT_TRUE(ExecJs(root, "popup = window.open('about:blank');"));
   Shell* popup = new_shell_observer.GetShell();
-  EXPECT_EQ("about:blank", EvalJs(popup, "document.baseURI").ExtractString());
+  EXPECT_EQ(GURL("about:blank"), GetFrameBaseUrl(popup));
 }
 
 // A test to verify the initial stages of the initiator base url plumbing work.
diff --git a/content/browser/worker_host/shared_worker_host_unittest.cc b/content/browser/worker_host/shared_worker_host_unittest.cc
index 5ddd5c47..0ac6da0 100644
--- a/content/browser/worker_host/shared_worker_host_unittest.cc
+++ b/content/browser/worker_host/shared_worker_host_unittest.cc
@@ -382,8 +382,8 @@
   SharedWorkerInstance instance(
       kWorkerUrl, blink::mojom::ScriptType::kClassic,
       network::mojom::CredentialsMode::kSameOrigin, "name",
-      blink::StorageKey::CreateWithNonce(url::Origin::Create(kWorkerUrl),
-                                         nonce),
+      blink::StorageKey::CreateWithNonceForTesting(
+          url::Origin::Create(kWorkerUrl), nonce),
       blink::mojom::SharedWorkerCreationContextType::kSecure);
   auto host = std::make_unique<SharedWorkerHost>(
       &service_, instance, site_instance_,
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
index 92072847..18269cb4 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
@@ -1192,24 +1192,23 @@
     }
 
     /**
-     * Ensure we are honoring min/max/step values for <input type="range"> nodes.
+     * Test <input type="range"> nodes and events for incrementing/decrementing value with actions.
      */
     @Test
     @SmallTest
-    public void testNodeInfo_inputTypeRange_withStepValue() throws Throwable {
+    public void testNodeInfo_inputTypeRangeSmall() throws Throwable {
         // Create a basic input range, and find the associated |AccessibilityNodeInfo| object.
-        setupTestWithHTML("<input type='range' min='0' max='144' step='12'>");
+        setupTestWithHTML("<input type='range' min='0' max='10' value='0'>");
 
         // Find the input range and assert we have the correct node.
         int inputNodeVirtualViewId = waitForNodeMatching(sRangeInfoMatcher, "");
         mNodeInfo = createAccessibilityNodeInfo(inputNodeVirtualViewId);
         Assert.assertNotNull(NODE_TIMEOUT_ERROR, mNodeInfo);
         Assert.assertEquals(NODE_TIMEOUT_ERROR, 0, mNodeInfo.getRangeInfo().getMin(), 0.001);
-        Assert.assertEquals(NODE_TIMEOUT_ERROR, 144, mNodeInfo.getRangeInfo().getMax(), 0.001);
+        Assert.assertEquals(NODE_TIMEOUT_ERROR, 10, mNodeInfo.getRangeInfo().getMax(), 0.001);
 
         // Perform a series of slider increments and check results.
-        int[] expectedVals = new int[] {84, 96, 108, 120, 132, 144};
-        for (int expectedVal : expectedVals) {
+        for (int i = 1; i <= 10; i++) {
             // Increment our slider using action, and poll until we receive the scroll event.
             performActionOnUiThread(inputNodeVirtualViewId, ACTION_SCROLL_FORWARD, new Bundle());
             CriteriaHelper.pollUiThread(
@@ -1219,16 +1218,15 @@
             mNodeInfo = createAccessibilityNodeInfo(inputNodeVirtualViewId);
 
             // Confirm slider values.
-            Assert.assertEquals(INPUT_RANGE_VALUE_MISMATCH, expectedVal,
-                    mNodeInfo.getRangeInfo().getCurrent(), 0.001);
+            Assert.assertEquals(
+                    INPUT_RANGE_VALUE_MISMATCH, i, mNodeInfo.getRangeInfo().getCurrent(), 0.001);
 
             // Reset polling value for next test
             mTestData.setReceivedEvent(false);
         }
 
         // Perform a series of slider decrements and check results.
-        expectedVals = new int[] {132, 120, 108, 96, 84, 72, 60, 48, 36, 24, 12, 0};
-        for (int expectedVal : expectedVals) {
+        for (int i = 1; i <= 10; i++) {
             // Decrement our slider using action, and poll until we receive the scroll event.
             performActionOnUiThread(inputNodeVirtualViewId, ACTION_SCROLL_BACKWARD, new Bundle());
             CriteriaHelper.pollUiThread(
@@ -1238,7 +1236,7 @@
             mNodeInfo = createAccessibilityNodeInfo(inputNodeVirtualViewId);
 
             // Confirm slider values.
-            Assert.assertEquals(INPUT_RANGE_VALUE_MISMATCH, expectedVal,
+            Assert.assertEquals(INPUT_RANGE_VALUE_MISMATCH, 10 - i,
                     mNodeInfo.getRangeInfo().getCurrent(), 0.001);
 
             // Reset polling value for next test
@@ -1273,7 +1271,7 @@
             mNodeInfo = createAccessibilityNodeInfo(inputNodeVirtualViewId);
 
             // Confirm slider values.
-            Assert.assertEquals(INPUT_RANGE_VALUE_MISMATCH, 500 + (10 * i),
+            Assert.assertEquals(INPUT_RANGE_VALUE_MISMATCH, 500 + (50 * i),
                     mNodeInfo.getRangeInfo().getCurrent(), 0.001);
 
             // Reset polling value for next test
@@ -1291,7 +1289,7 @@
             mNodeInfo = createAccessibilityNodeInfo(inputNodeVirtualViewId);
 
             // Confirm slider values.
-            Assert.assertEquals(INPUT_RANGE_VALUE_MISMATCH, 600 - (10 * i),
+            Assert.assertEquals(INPUT_RANGE_VALUE_MISMATCH, 1000 - (50 * i),
                     mNodeInfo.getRangeInfo().getCurrent(), 0.001);
 
             // Reset polling value for next test
diff --git a/content/public/test/attribution_simulator.h b/content/public/test/attribution_simulator.h
index 93abceb..5e75ce0 100644
--- a/content/public/test/attribution_simulator.h
+++ b/content/public/test/attribution_simulator.h
@@ -30,14 +30,6 @@
   // These fields normally encode a random GUID or the absolute time and
   // therefore are sources of nondeterminism in the output.
   bool remove_assembled_report = false;
-
-  // If true, removes the `report_time` field from reports before output.
-  //
-  // This field contains the actual time the report was sent, rather than the
-  // `intended_report_time` determined by the specification. As such, it is
-  // subject to implementation details such as delays that should not be relied
-  // upon in golden test output.
-  bool remove_actual_report_times = false;
 };
 
 struct AttributionSimulationOptions {
diff --git a/content/test/attribution_simulator_impl.cc b/content/test/attribution_simulator_impl.cc
index c976437..92cb5eb 100644
--- a/content/test/attribution_simulator_impl.cc
+++ b/content/test/attribution_simulator_impl.cc
@@ -137,10 +137,6 @@
               FormatTime(is_debug_report ? report.attribution_info().time
                                          : report.report_time()));
 
-    if (!options.remove_actual_report_times) {
-      value.Set("report_time", FormatTime(base::Time::Now()));
-    }
-
     base::Value::Dict test_info;
     if (absl::holds_alternative<AttributionReport::EventLevelData>(
             report.data())) {
diff --git a/content/test/attribution_simulator_impl_unittest.cc b/content/test/attribution_simulator_impl_unittest.cc
index 1ffa92d..82798a7 100644
--- a/content/test/attribution_simulator_impl_unittest.cc
+++ b/content/test/attribution_simulator_impl_unittest.cc
@@ -100,7 +100,6 @@
           AttributionSimulationOutputOptions{
               .remove_report_ids = true,
               .remove_assembled_report = true,
-              .remove_actual_report_times = true,
           },
   };
 
diff --git a/content/test/data/accessibility/event/range-value-maximum-changed-expected-uia-win.txt b/content/test/data/accessibility/event/range-value-maximum-changed-expected-uia-win.txt
index 4a94fe82..ba7051cf 100644
--- a/content/test/data/accessibility/event/range-value-maximum-changed-expected-uia-win.txt
+++ b/content/test/data/accessibility/event/range-value-maximum-changed-expected-uia-win.txt
@@ -2,10 +2,12 @@
 RangeValueMaximum changed on role=slider
 === Start Continuation ===
 AriaProperties changed on role=slider
+RangeValueLargeChange changed on role=slider
 RangeValueMaximum changed on role=slider
+RangeValueSmallChange changed on role=slider
 === Start Continuation ===
 AriaProperties changed on role=slider
 RangeValueMaximum changed on role=slider
 === Start Continuation ===
 AriaProperties changed on role=slider
-RangeValueMaximum changed on role=slider
+RangeValueMaximum changed on role=slider
\ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-range-expected-android-external.txt b/content/test/data/accessibility/html/input-range-expected-android-external.txt
index 4e1d6ee..7f1e4fe4 100644
--- a/content/test/data/accessibility/html/input-range-expected-android-external.txt
+++ b/content/test/data/accessibility/html/input-range-expected-android-external.txt
@@ -4,4 +4,5 @@
 ++++SeekBar text:"3" clickable focusable RangeInfo:[current=3.0, min=1.0, max=10.0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"]
 ++++SeekBar text:"Medium" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"]
 ++++SeekBar text:"Friday" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"]
-++++SeekBar text:"0.2" clickable focusable RangeInfo:[current=0.2, min=-1.0, max=1.0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"]
\ No newline at end of file
+++++SeekBar text:"0.2" clickable focusable RangeInfo:[current=0.2, min=-1.0, max=1.0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"]
+++++SeekBar text:"50" clickable focusable RangeInfo:[current=50.0, min=0.0, max=100.0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"]
diff --git a/content/test/data/accessibility/html/input-range-expected-android.txt b/content/test/data/accessibility/html/input-range-expected-android.txt
index db8a1c3..d1c15d2 100644
--- a/content/test/data/accessibility/html/input-range-expected-android.txt
+++ b/content/test/data/accessibility/html/input-range-expected-android.txt
@@ -4,4 +4,5 @@
 ++++android.widget.SeekBar role_description='slider' clickable focusable range name='3' item_index=22 item_count=100 range_min=1 range_max=10 range_current_value=3
 ++++android.widget.SeekBar role_description='slider' clickable focusable range name='Medium' range_min=1 range_max=10 range_current_value=5
 ++++android.widget.SeekBar role_description='slider' clickable focusable range name='Friday' range_max=5 range_current_value=6
-++++android.widget.SeekBar role_description='slider' clickable focusable range name='0.2' item_index=60 item_count=100 range_min=-1 range_max=1
\ No newline at end of file
+++++android.widget.SeekBar role_description='slider' clickable focusable range name='0.2' item_index=60 item_count=100 range_min=-1 range_max=1
+++++android.widget.SeekBar role_description='slider' clickable focusable range name='50' item_index=50 item_count=100 range_max=100 range_current_value=50
diff --git a/content/test/data/accessibility/html/input-range-expected-auralinux.txt b/content/test/data/accessibility/html/input-range-expected-auralinux.txt
index ad252dd..68c788fb 100644
--- a/content/test/data/accessibility/html/input-range-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/input-range-expected-auralinux.txt
@@ -5,3 +5,4 @@
 ++++[slider] horizontal valuetext:Medium current=5.000000 minimum=1.000000 maximum=10.000000
 ++++[slider] horizontal valuetext:Friday current=6.000000 minimum=0.000000 maximum=5.000000
 ++++[slider] horizontal valuetext:0.2 current=0.200000 minimum=-1.000000 maximum=1.000000
+++++[slider] horizontal valuetext:50 current=50.000000 minimum=0.000000 maximum=100.000000
\ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-range-expected-blink.txt b/content/test/data/accessibility/html/input-range-expected-blink.txt
index 6abe365..8255d0c 100644
--- a/content/test/data/accessibility/html/input-range-expected-blink.txt
+++ b/content/test/data/accessibility/html/input-range-expected-blink.txt
@@ -1,8 +1,9 @@
 rootWebArea
 ++genericContainer ignored
 ++++genericContainer
-++++++slider horizontal inputType='range' valueForRange=5.00 minValueForRange=1.00 maxValueForRange=10.00
-++++++slider horizontal inputType='range' valueForRange=3.00 minValueForRange=1.00 maxValueForRange=10.00
-++++++slider horizontal inputType='range' value='Medium' valueForRange=5.00 minValueForRange=1.00 maxValueForRange=10.00
-++++++slider horizontal inputType='range' value='Friday' valueForRange=6.00 minValueForRange=0.00 maxValueForRange=5.00
-++++++slider horizontal inputType='range' valueForRange=0.20 minValueForRange=-1.00 maxValueForRange=1.00
+++++++slider horizontal inputType='range' valueForRange=5.00 minValueForRange=1.00 maxValueForRange=10.00 stepValueForRange=1.00
+++++++slider horizontal inputType='range' valueForRange=3.00 minValueForRange=1.00 maxValueForRange=10.00 stepValueForRange=1.00
+++++++slider horizontal inputType='range' value='Medium' valueForRange=5.00 minValueForRange=1.00 maxValueForRange=10.00 stepValueForRange=1.00
+++++++slider horizontal inputType='range' value='Friday' valueForRange=6.00 minValueForRange=0.00 maxValueForRange=5.00 stepValueForRange=1.00
+++++++slider horizontal inputType='range' valueForRange=0.20 minValueForRange=-1.00 maxValueForRange=1.00 stepValueForRange=0.10
+++++++slider horizontal inputType='range' valueForRange=50.00 minValueForRange=0.00 maxValueForRange=100.00
\ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-range-expected-mac.txt b/content/test/data/accessibility/html/input-range-expected-mac.txt
index 2cf7e98..ff0169b 100644
--- a/content/test/data/accessibility/html/input-range-expected-mac.txt
+++ b/content/test/data/accessibility/html/input-range-expected-mac.txt
@@ -5,3 +5,4 @@
 ++++AXSlider AXValue=5
 ++++AXSlider AXValue=6
 ++++AXSlider AXValue=0
+++++AXSlider AXValue=50
\ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-range-expected-uia-win.txt b/content/test/data/accessibility/html/input-range-expected-uia-win.txt
index c183eac..e4af677b 100644
--- a/content/test/data/accessibility/html/input-range-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-range-expected-uia-win.txt
@@ -5,3 +5,4 @@
 ++++Slider RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=10.00 RangeValue.Minimum=1.00 RangeValue.Value=5.00 Value.Value='Medium'
 ++++Slider RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=5.00 RangeValue.Minimum=0.00 RangeValue.Value=6.00 Value.Value='Friday'
 ++++Slider RangeValue.IsReadOnly=false RangeValue.LargeChange=1.00 RangeValue.SmallChange=0.10 RangeValue.Maximum=1.00 RangeValue.Minimum=-1.00 RangeValue.Value=0.20 Value.Value='0.2'
+++++Slider RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=100.00 RangeValue.Minimum=0.00 RangeValue.Value=50.00 Value.Value='50'
\ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-range-expected-win.txt b/content/test/data/accessibility/html/input-range-expected-win.txt
index ee22a5c..516e018 100644
--- a/content/test/data/accessibility/html/input-range-expected-win.txt
+++ b/content/test/data/accessibility/html/input-range-expected-win.txt
@@ -1,7 +1,8 @@
 ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0>'
-++IA2_ROLE_SECTION ia2_hypertext='<obj0><obj1><obj2><obj3><obj4>'
+++IA2_ROLE_SECTION ia2_hypertext='<obj0><obj1><obj2><obj3><obj4><obj5>'
 ++++ROLE_SYSTEM_SLIDER value='5' FOCUSABLE IA2_STATE_HORIZONTAL valuetext:5 currentValue=5 minimumValue=1 maximumValue=10
 ++++ROLE_SYSTEM_SLIDER value='3' FOCUSABLE IA2_STATE_HORIZONTAL valuetext:3 currentValue=3 minimumValue=1 maximumValue=10
 ++++ROLE_SYSTEM_SLIDER value='Medium' FOCUSABLE IA2_STATE_HORIZONTAL valuetext:Medium currentValue=5 minimumValue=1 maximumValue=10
 ++++ROLE_SYSTEM_SLIDER value='Friday' FOCUSABLE IA2_STATE_HORIZONTAL valuetext:Friday currentValue=6 minimumValue=0 maximumValue=5
 ++++ROLE_SYSTEM_SLIDER value='0.2' FOCUSABLE IA2_STATE_HORIZONTAL valuetext:0.2 currentValue=0.20000000298023224 minimumValue=-1 maximumValue=1
+++++ROLE_SYSTEM_SLIDER value='50' FOCUSABLE IA2_STATE_HORIZONTAL valuetext:50 currentValue=50 minimumValue=0 maximumValue=100
\ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-range.html b/content/test/data/accessibility/html/input-range.html
index 2e1908f..3867688 100644
--- a/content/test/data/accessibility/html/input-range.html
+++ b/content/test/data/accessibility/html/input-range.html
@@ -4,6 +4,7 @@
 @BLINK-ALLOW:maximumValue*
 @BLINK-ALLOW:minimumValue*
 @BLINK-ALLOW:value*
+@BLINK-ALLOW:step*
 @WIN-DENY:description*
 @WIN-DENY:name*
 @WIN-ALLOW:currentValue*
@@ -26,5 +27,6 @@
     <input type="range" min=1 max=10 value=5 aria-valuetext="Medium">
     <input type="range" min=0 max=5 value=2 aria-valuenow="6" aria-valuetext="Friday">
     <input type="range" min=-1 max=1 value="0.2" step="0.1">
+    <input type='range' min='0' max='100' step='1'>
   </body>
 </html>
diff --git a/content/test/data/accessibility/html/popover-api-expected-auralinux.txt b/content/test/data/accessibility/html/popover-api-expected-auralinux.txt
new file mode 100644
index 0000000..d0b29eb
--- /dev/null
+++ b/content/test/data/accessibility/html/popover-api-expected-auralinux.txt
@@ -0,0 +1,32 @@
+[document web]
+++[push button] name='Button pointing to hidden popover'
+++[entry] selectable-text
+++[static] name='Text input pointing to hidden popover '
+++[push button] name='Hide button pointing to hidden manual'
+++[entry] selectable-text
+++[static] name='Email input pointing to hidden manual '
+++[push button] name='Button pointing to non-popover'
+++[entry] selectable-text
+++[static] name='Text input pointing to non-popover'
+++[section]
+++++[static] name='No popover attribute'
+++[push button] name='Button pointing to invalid popover value'
+++[entry] selectable-text
+++[static] name='Text input pointing to invalid popover value'
+++[paragraph]
+++++[static] name='Showing/visible popovers below'
+++[push button] name='Button pointing to showing popover'
+++[entry] selectable-text
+++[static] name='Tel input pointing to showing popover '
+++[push button] name='Show button pointing to nested popover'
+++[entry] selectable-text
+++[static] name='Url input pointing to nested popover '
+++[section]
+++++[static] name='Popover (showing)'
+++++[section]
+++++++[static] name='Nested popover (showing)'
+++[push button] name='Hide button pointing to showing manual'
+++[entry] selectable-text
+++[static] name='Url input pointing to showing manual'
+++[section]
+++++[static] name='Manual (showing)'
diff --git a/content/test/data/accessibility/html/popover-api-expected-blink.txt b/content/test/data/accessibility/html/popover-api-expected-blink.txt
index 227358b..8b62186 100644
--- a/content/test/data/accessibility/html/popover-api-expected-blink.txt
+++ b/content/test/data/accessibility/html/popover-api-expected-blink.txt
@@ -2,13 +2,13 @@
 ++genericContainer ignored
 ++++genericContainer ignored
 ++++++genericContainer ignored invisible
-++++++++staticText ignored name='Div popover'
+++++++++staticText ignored invisible name='Div popover'
 ++++++listBox ignored invisible
 ++++++++genericContainer ignored invisible
-++++++++++staticText ignored name='Listbox role on ul'
+++++++++++staticText ignored invisible name='Listbox role on ul'
 ++++++listBox ignored invisible
 ++++++++genericContainer ignored invisible
-++++++++++staticText ignored name='Listbox role on ul'
+++++++++++staticText ignored invisible name='Listbox role on ul'
 ++++++details ignored invisible
 ++++++button collapsed name='Button pointing to hidden popover'
 ++++++++staticText name='Button pointing to hidden popover'
@@ -18,16 +18,7 @@
 ++++++staticText name='Text input pointing to hidden popover '
 ++++++++inlineTextBox name='Text input pointing to hidden popover '
 ++++++genericContainer ignored invisible
-++++++++staticText ignored name='Popover'
-++++++button description='Hint' name='Show button pointing to hidden hint' descriptionFrom=popoverElement
-++++++++staticText name='Show button pointing to hidden hint'
-++++++++++inlineTextBox name='Show button pointing to hidden hint'
-++++++searchBox
-++++++++genericContainer
-++++++staticText name='Search input pointing to hidden hint '
-++++++++inlineTextBox name='Search input pointing to hidden hint '
-++++++genericContainer ignored invisible
-++++++++staticText ignored name='Hint'
+++++++++staticText ignored invisible name='Popover'
 ++++++button name='Hide button pointing to hidden manual'
 ++++++++staticText name='Hide button pointing to hidden manual'
 ++++++++++inlineTextBox name='Hide button pointing to hidden manual'
@@ -36,37 +27,7 @@
 ++++++staticText name='Email input pointing to hidden manual '
 ++++++++inlineTextBox name='Email input pointing to hidden manual '
 ++++++genericContainer ignored invisible
-++++++++staticText ignored name='Manual'
-++++++button name='Button pointing to showing popover'
-++++++++staticText name='Button pointing to showing popover'
-++++++++++inlineTextBox name='Button pointing to showing popover'
-++++++textField
-++++++++genericContainer
-++++++staticText name='Tel input pointing to showing popover '
-++++++++inlineTextBox name='Tel input pointing to showing popover '
-++++++button description='Hint (nested)' name='Show button pointing to showing hint' descriptionFrom=popoverElement
-++++++++staticText name='Show button pointing to showing hint'
-++++++++++inlineTextBox name='Show button pointing to showing hint'
-++++++textField
-++++++++genericContainer
-++++++staticText name='Url input pointing to showing hint '
-++++++++inlineTextBox name='Url input pointing to showing hint '
-++++++genericContainer
-++++++++staticText name='Popover'
-++++++++++inlineTextBox name='Popover'
-++++++++genericContainer
-++++++++++staticText name='Hint (nested)'
-++++++++++++inlineTextBox name='Hint (nested)'
-++++++button name='Hide button pointing to showing manual'
-++++++++staticText name='Hide button pointing to showing manual'
-++++++++++inlineTextBox name='Hide button pointing to showing manual'
-++++++textField
-++++++++genericContainer
-++++++staticText name='Text input pointing to showing manual '
-++++++++inlineTextBox name='Text input pointing to showing manual '
-++++++genericContainer
-++++++++staticText name='Manual'
-++++++++++inlineTextBox name='Manual'
+++++++++staticText ignored invisible name='Manual'
 ++++++button name='Button pointing to non-popover'
 ++++++++staticText name='Button pointing to non-popover'
 ++++++++++inlineTextBox name='Button pointing to non-popover'
@@ -85,4 +46,37 @@
 ++++++staticText name='Text input pointing to invalid popover value'
 ++++++++inlineTextBox name='Text input pointing to invalid popover value'
 ++++++genericContainer ignored invisible
-++++++++staticText ignored name='Invalid popover attribute value'
+++++++++staticText ignored invisible name='Invalid popover attribute value'
+++++++paragraph
+++++++++staticText name='Showing/visible popovers below'
+++++++++++inlineTextBox name='Showing/visible popovers below'
+++++++button name='Button pointing to showing popover'
+++++++++staticText name='Button pointing to showing popover'
+++++++++++inlineTextBox name='Button pointing to showing popover'
+++++++textField
+++++++++genericContainer
+++++++staticText name='Tel input pointing to showing popover '
+++++++++inlineTextBox name='Tel input pointing to showing popover '
+++++++button name='Show button pointing to nested popover'
+++++++++staticText name='Show button pointing to nested popover'
+++++++++++inlineTextBox name='Show button pointing to nested popover'
+++++++textField
+++++++++genericContainer
+++++++staticText name='Url input pointing to nested popover '
+++++++++inlineTextBox name='Url input pointing to nested popover '
+++++++genericContainer ispopup=auto
+++++++++staticText name='Popover (showing)'
+++++++++++inlineTextBox name='Popover (showing)'
+++++++++genericContainer ispopup=auto
+++++++++++staticText name='Nested popover (showing)'
+++++++++++++inlineTextBox name='Nested popover (showing)'
+++++++button name='Hide button pointing to showing manual'
+++++++++staticText name='Hide button pointing to showing manual'
+++++++++++inlineTextBox name='Hide button pointing to showing manual'
+++++++textField
+++++++++genericContainer
+++++++staticText name='Url input pointing to showing manual'
+++++++++inlineTextBox name='Url input pointing to showing manual'
+++++++genericContainer ispopup=manual
+++++++++staticText name='Manual (showing)'
+++++++++++inlineTextBox name='Manual (showing)'
diff --git a/content/test/data/accessibility/html/popover-api-expected-mac.txt b/content/test/data/accessibility/html/popover-api-expected-mac.txt
new file mode 100644
index 0000000..b75028b
--- /dev/null
+++ b/content/test/data/accessibility/html/popover-api-expected-mac.txt
@@ -0,0 +1,32 @@
+AXWebArea
+++AXButton AXTitle='Button pointing to hidden popover'
+++AXTextField
+++AXStaticText AXValue='Text input pointing to hidden popover '
+++AXButton AXTitle='Hide button pointing to hidden manual'
+++AXTextField
+++AXStaticText AXValue='Email input pointing to hidden manual '
+++AXButton AXTitle='Button pointing to non-popover'
+++AXTextField
+++AXStaticText AXValue='Text input pointing to non-popover'
+++AXGroup
+++++AXStaticText AXValue='No popover attribute'
+++AXButton AXTitle='Button pointing to invalid popover value'
+++AXTextField
+++AXStaticText AXValue='Text input pointing to invalid popover value'
+++AXGroup
+++++AXStaticText AXValue='Showing/visible popovers below'
+++AXButton AXTitle='Button pointing to showing popover'
+++AXTextField
+++AXStaticText AXValue='Tel input pointing to showing popover '
+++AXButton AXTitle='Show button pointing to nested popover'
+++AXTextField
+++AXStaticText AXValue='Url input pointing to nested popover '
+++AXGroup
+++++AXStaticText AXValue='Popover (showing)'
+++++AXGroup
+++++++AXStaticText AXValue='Nested popover (showing)'
+++AXButton AXTitle='Hide button pointing to showing manual'
+++AXTextField
+++AXStaticText AXValue='Url input pointing to showing manual'
+++AXGroup
+++++AXStaticText AXValue='Manual (showing)'
diff --git a/content/test/data/accessibility/html/popover-api-expected-win.txt b/content/test/data/accessibility/html/popover-api-expected-win.txt
new file mode 100644
index 0000000..388b8b3
--- /dev/null
+++ b/content/test/data/accessibility/html/popover-api-expected-win.txt
@@ -0,0 +1,32 @@
+ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
+++ROLE_SYSTEM_PUSHBUTTON name='Button pointing to hidden popover' COLLAPSED FOCUSABLE
+++ROLE_SYSTEM_TEXT FOCUSABLE
+++ROLE_SYSTEM_STATICTEXT name='Text input pointing to hidden popover '
+++ROLE_SYSTEM_PUSHBUTTON name='Hide button pointing to hidden manual' FOCUSABLE
+++ROLE_SYSTEM_TEXT FOCUSABLE
+++ROLE_SYSTEM_STATICTEXT name='Email input pointing to hidden manual '
+++ROLE_SYSTEM_PUSHBUTTON name='Button pointing to non-popover' FOCUSABLE
+++ROLE_SYSTEM_TEXT FOCUSABLE
+++ROLE_SYSTEM_STATICTEXT name='Text input pointing to non-popover'
+++IA2_ROLE_SECTION
+++++ROLE_SYSTEM_STATICTEXT name='No popover attribute'
+++ROLE_SYSTEM_PUSHBUTTON name='Button pointing to invalid popover value' FOCUSABLE
+++ROLE_SYSTEM_TEXT FOCUSABLE
+++ROLE_SYSTEM_STATICTEXT name='Text input pointing to invalid popover value'
+++IA2_ROLE_PARAGRAPH
+++++ROLE_SYSTEM_STATICTEXT name='Showing/visible popovers below'
+++ROLE_SYSTEM_PUSHBUTTON name='Button pointing to showing popover' EXPANDED FOCUSABLE
+++ROLE_SYSTEM_TEXT FOCUSABLE
+++ROLE_SYSTEM_STATICTEXT name='Tel input pointing to showing popover '
+++ROLE_SYSTEM_PUSHBUTTON name='Show button pointing to nested popover' EXPANDED FOCUSABLE
+++ROLE_SYSTEM_TEXT FOCUSABLE
+++ROLE_SYSTEM_STATICTEXT name='Url input pointing to nested popover '
+++IA2_ROLE_SECTION ispopup:auto
+++++ROLE_SYSTEM_STATICTEXT name='Popover (showing)'
+++++IA2_ROLE_SECTION ispopup:auto
+++++++ROLE_SYSTEM_STATICTEXT name='Nested popover (showing)'
+++ROLE_SYSTEM_PUSHBUTTON name='Hide button pointing to showing manual' FOCUSABLE
+++ROLE_SYSTEM_TEXT FOCUSABLE
+++ROLE_SYSTEM_STATICTEXT name='Url input pointing to showing manual'
+++IA2_ROLE_SECTION ispopup:manual
+++++ROLE_SYSTEM_STATICTEXT name='Manual (showing)'
diff --git a/content/test/data/accessibility/html/popover-api.html b/content/test/data/accessibility/html/popover-api.html
index e0d8cd7..bc6d98c 100644
--- a/content/test/data/accessibility/html/popover-api.html
+++ b/content/test/data/accessibility/html/popover-api.html
@@ -6,32 +6,31 @@
 <button popovertoggletarget=popover1>Button pointing to hidden popover</button>
 <input type=text popovertoggletarget=popover1>Text input pointing to hidden popover</button>
 <div popover id=popover1>Popover</div>
-<button popovershowtarget=hint1>Show button pointing to hidden hint</button>
-<input type=search popovershowtarget=hint1>Search input pointing to hidden hint</button>
-<div popover=hint id=hint1>Hint</div>
 <button popoverhidetarget=manual1>Hide button pointing to hidden manual</button>
 <input type=email popoverhidetarget=manual1>Email input pointing to hidden manual</button>
 <div popover=manual id=manual1>Manual</div>
 
-<button popovertoggletarget=popover2>Button pointing to showing popover</button>
-<input type=tel popovertoggletarget=popover2>Tel input pointing to showing popover</button>
-<button popovershowtarget=hint2>Show button pointing to showing hint</button>
-<input type=url popovershowtarget=hint2>Url input pointing to showing hint</button>
-<div popover id=popover2>Popover
-  <div popover=hint id=hint2>Hint (nested)</div>
-</div>
-<button popoverhidetarget=manual2>Hide button pointing to showing manual</button>
-<input type=text popoverhidetarget=manual2>Text input pointing to showing manual</button>
-<div popover=manual id=manual2>Manual</div>
-<script>
-  popover2.showPopover();
-  hint2.showPopover();
-  manual2.showPopover();
-</script>
-
 <button popovertoggletarget=noattr>Button pointing to non-popover</button>
 <input type=text popovertoggletarget=noattr>Text input pointing to non-popover</button>
 <div id=noattr>No popover attribute</div>
 <button popovertoggletarget=badattr>Button pointing to invalid popover value</button>
 <input type=text popovertoggletarget=badattr>Text input pointing to invalid popover value</button>
 <div id=badattr popover=invalid_value>Invalid popover attribute value</div>
+
+<p> Showing/visible popovers below </p>
+
+<button popovertoggletarget=popover2>Button pointing to showing popover</button>
+<input type=tel popovertoggletarget=popover2>Tel input pointing to showing popover</button>
+<button popovershowtarget=popover3>Show button pointing to nested popover</button>
+<input type=url popovershowtarget=popover3>Url input pointing to nested popover</button>
+<div popover id=popover2>Popover (showing)
+  <div popover id=popover3>Nested popover (showing)</div>
+</div>
+<button popoverhidetarget=manual2>Hide button pointing to showing manual</button>
+<input type=url popoverhidetarget=manual2>Url input pointing to showing manual</button>
+<div popover=manual id=manual2>Manual (showing)</div>
+<script>
+  popover2.showPopover();
+  popover3.showPopover();
+  manual2.showPopover();
+</script>
diff --git a/content/test/data/accessibility/html/selectmenu-open-expected-blink.txt b/content/test/data/accessibility/html/selectmenu-open-expected-blink.txt
index c28f4fc..c3611dc 100644
--- a/content/test/data/accessibility/html/selectmenu-open-expected-blink.txt
+++ b/content/test/data/accessibility/html/selectmenu-open-expected-blink.txt
@@ -7,7 +7,7 @@
 ++++++++++++staticText name='Custom selectmenu button'
 ++++++++++++++inlineTextBox name='Custom selectmenu button'
 ++++++++genericContainer ignored
-++++++++++listBox setSize=3
+++++++++++listBox setSize=3 ispopup=auto
 ++++++++++++listBoxOption focusable name='Option 1' setSize=3 posInSet=1 selected=true
 ++++++++++++listBoxOption focusable name='Option 2' setSize=3 posInSet=2 selected=false
-++++++++++++listBoxOption focusable name='Option 3' setSize=3 posInSet=3 selected=false
\ No newline at end of file
+++++++++++++listBoxOption focusable name='Option 3' setSize=3 posInSet=3 selected=false
diff --git a/content/test/data/accessibility/html/selectmenu-open-expected-win.txt b/content/test/data/accessibility/html/selectmenu-open-expected-win.txt
index a2658bf..1a0570c 100644
--- a/content/test/data/accessibility/html/selectmenu-open-expected-win.txt
+++ b/content/test/data/accessibility/html/selectmenu-open-expected-win.txt
@@ -3,7 +3,7 @@
 ++++IA2_ROLE_SECTION ia2_hypertext='<obj0><obj1>'
 ++++++ROLE_SYSTEM_COMBOBOX value='Option 1' EXPANDED HASPOPUP haspopup:listbox ia2_hypertext='Custom selectmenu button'
 ++++++++ROLE_SYSTEM_STATICTEXT name='Custom selectmenu button' ia2_hypertext='Custom selectmenu button'
-++++++ROLE_SYSTEM_LIST ia2_hypertext='<obj0><obj1><obj2>'
+++++++ROLE_SYSTEM_LIST ispopup:auto ia2_hypertext='<obj0><obj1><obj2>'
 ++++++++ROLE_SYSTEM_LISTITEM name='Option 1' SELECTED FOCUSABLE SELECTABLE ia2_hypertext='Option 1'
 ++++++++ROLE_SYSTEM_LISTITEM name='Option 2' FOCUSABLE SELECTABLE ia2_hypertext='Option 2'
-++++++++ROLE_SYSTEM_LISTITEM name='Option 3' FOCUSABLE SELECTABLE ia2_hypertext='Option 3'
\ No newline at end of file
+++++++++ROLE_SYSTEM_LISTITEM name='Option 3' FOCUSABLE SELECTABLE ia2_hypertext='Option 3'
diff --git a/gin/BUILD.gn b/gin/BUILD.gn
index d222717..fa260d8c 100644
--- a/gin/BUILD.gn
+++ b/gin/BUILD.gn
@@ -137,12 +137,7 @@
         }
         renaming_sources = [ "$root_build_dir/snapshot_blob.bin" ]
         renaming_destinations = [ "snapshot_blob_$_arch_suffix.bin" ]
-
-        # TODO(crbug.com/1402705): Use this more direct target instead in order
-        #     to avoid building all of v8 just to create the snapshot.
-        deps = [ "//v8" ]
-
-        # deps = [ "//v8:run_mksnapshot_default" ]
+        deps = [ "//v8:run_mksnapshot_default" ]
       }
     }
   }
@@ -162,12 +157,8 @@
                            "root_out_dir")
         renaming_sources = [ "$_secondary_abi_out_dir/snapshot_blob.bin" ]
         renaming_destinations = [ "snapshot_blob_32.bin" ]
-
-        # TODO(crbug.com/1402705): Use this more direct target instead in order
-        #     to avoid building all of v8 just to create the snapshot.
-        deps = [ "//v8($android_secondary_abi_toolchain)" ]
-
-        # deps = [ "//v8:run_mksnapshot_default($android_secondary_abi_toolchain)" ]
+        deps =
+            [ "//v8:run_mksnapshot_default($android_secondary_abi_toolchain)" ]
       }
     }
   }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_textures.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_textures.cc
index 5e46814..13e7514 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_textures.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_textures.cc
@@ -38,7 +38,7 @@
 TEST_F(GLES2DecoderPassthroughTest, CreateAndTexStorage2DSharedImageCHROMIUM) {
   MemoryTypeTracker memory_tracker(nullptr);
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   auto backing = AllocateTextureAndCreateSharedImage(
       mailbox, format, gfx::Size(10, 10), gfx::ColorSpace(),
       kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, 0);
@@ -102,7 +102,7 @@
   MemoryTypeTracker memory_tracker(nullptr);
   // Create a texture with kNewClientId.
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
       GetSharedImageManager()->Register(
           AllocateTextureAndCreateSharedImage(
@@ -138,7 +138,7 @@
       shared_images;
   for (int i = 0; i < 40; i++) {
     Mailbox mailbox = Mailbox::GenerateForSharedImage();
-    auto format = viz::SharedImageFormat::kRGBA_8888;
+    auto format = viz::SinglePlaneFormat::kRGBA_8888;
     std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
         GetSharedImageManager()->Register(
             AllocateTextureAndCreateSharedImage(
@@ -206,7 +206,7 @@
   // Create a shared image.
   MemoryTypeTracker memory_tracker(nullptr);
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   auto shared_image_backing = AllocateTextureAndCreateSharedImage(
       mailbox, format, gfx::Size(10, 10), gfx::ColorSpace(),
       kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, 0);
@@ -248,7 +248,7 @@
   // Create an uncleared shared image.
   MemoryTypeTracker memory_tracker(nullptr);
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
       GetSharedImageManager()->Register(
           AllocateTextureAndCreateSharedImage(
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
index 4ce4039..e7f3c10 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
@@ -3064,7 +3064,7 @@
 TEST_P(GLES2DecoderTest, CreateAndTexStorage2DSharedImageCHROMIUM) {
   MemoryTypeTracker memory_tracker(memory_tracker_.get());
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
       GetSharedImageManager()->Register(
           std::make_unique<TestImageBacking>(
@@ -3127,7 +3127,7 @@
   // Try to create a mailbox with kNewClientId.
   MemoryTypeTracker memory_tracker(memory_tracker_.get());
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
       GetSharedImageManager()->Register(
           std::make_unique<TestImageBacking>(
@@ -3152,7 +3152,7 @@
 TEST_P(GLES2DecoderTest, BeginEndSharedImageAccessCRHOMIUM) {
   MemoryTypeTracker memory_tracker(memory_tracker_.get());
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
       GetSharedImageManager()->Register(
           std::make_unique<TestImageBacking>(
@@ -3214,7 +3214,7 @@
   // Create a shared image.
   MemoryTypeTracker memory_tracker(memory_tracker_.get());
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   auto shared_image_backing = std::make_unique<TestImageBacking>(
       mailbox, format, gfx::Size(10, 10), gfx::ColorSpace(),
       kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, 0, 0, kNewServiceId);
diff --git a/gpu/command_buffer/service/gles2_external_framebuffer.cc b/gpu/command_buffer/service/gles2_external_framebuffer.cc
index 8aa459a1..888426be 100644
--- a/gpu/command_buffer/service/gles2_external_framebuffer.cc
+++ b/gpu/command_buffer/service/gles2_external_framebuffer.cc
@@ -393,7 +393,7 @@
       clear_flags |= GL_COLOR_BUFFER_BIT;
   } else {
     const bool has_alpha = shared_image_representation_->format() ==
-                           viz::SharedImageFormat::kRGBA_8888;
+                           viz::SinglePlaneFormat::kRGBA_8888;
     if (UpdateAttachment(GL_COLOR_ATTACHMENT0, size, samples,
                          has_alpha ? GL_RGBA8 : GL_RGB8)) {
       clear_flags |= GL_COLOR_BUFFER_BIT;
diff --git a/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory_unittest.cc
index bbe21ce..5ff813d 100644
--- a/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory_unittest.cc
@@ -163,7 +163,7 @@
 
   // Create a backing using mailbox.
   auto mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   gfx::Size size(1, 1);
   auto color_space = gfx::ColorSpace::CreateSRGB();
   GrSurfaceOrigin surface_origin = kTopLeft_GrSurfaceOrigin;
@@ -223,7 +223,7 @@
     return;
 
   auto mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   gfx::Size size(4, 4);
 
   std::vector<uint8_t> initial_data(size.width() * size.height() * 4);
@@ -281,7 +281,7 @@
     return;
 
   auto mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   gfx::Size size(0, 0);
   auto color_space = gfx::ColorSpace::CreateSRGB();
   GrSurfaceOrigin surface_origin = kTopLeft_GrSurfaceOrigin;
@@ -305,7 +305,7 @@
     return;
 
   auto mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   gfx::Size size(256, 256);
   auto color_space = gfx::ColorSpace::CreateSRGB();
   GrSurfaceOrigin surface_origin = kTopLeft_GrSurfaceOrigin;
@@ -495,7 +495,7 @@
     SharedImageRepresentationFactory* shared_image_representation_factory)
     : size_(256, 256) {
   mailbox_ = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   auto color_space = gfx::ColorSpace::CreateSRGB();
   GrSurfaceOrigin surface_origin = kTopLeft_GrSurfaceOrigin;
   SkAlphaType alpha_type = kPremul_SkAlphaType;
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory_unittest.cc
index 073cf15..3668682 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory_unittest.cc
@@ -564,7 +564,7 @@
 
   // Create a backing using mailbox.
   auto mailbox = Mailbox::GenerateForSharedImage();
-  const auto format = viz::SharedImageFormat::kRGBA_8888;
+  const auto format = viz::SinglePlaneFormat::kRGBA_8888;
   const gfx::Size size(1, 1);
   const auto color_space = gfx::ColorSpace::CreateSRGB();
   const uint32_t usage =
@@ -650,7 +650,7 @@
 
   // Create a backing using mailbox.
   const auto mailbox = Mailbox::GenerateForSharedImage();
-  const auto format = viz::SharedImageFormat::kRGBA_8888;
+  const auto format = viz::SinglePlaneFormat::kRGBA_8888;
   const gfx::Size size(1, 1);
   const auto color_space = gfx::ColorSpace::CreateSRGB();
   const gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle;
@@ -845,7 +845,7 @@
 
   // Create a backing using mailbox.
   const auto mailbox = Mailbox::GenerateForSharedImage();
-  const auto format = viz::SharedImageFormat::kRGBA_8888;
+  const auto format = viz::SinglePlaneFormat::kRGBA_8888;
   const gfx::Size size(1, 1);
   const auto color_space = gfx::ColorSpace::CreateSRGB();
   const gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle;
@@ -933,7 +933,7 @@
 
   // Create a backing using mailbox.
   auto mailbox = Mailbox::GenerateForSharedImage();
-  const auto format = viz::SharedImageFormat::kRGBA_8888;
+  const auto format = viz::SinglePlaneFormat::kRGBA_8888;
   const gfx::Size size(1, 1);
   const auto color_space = gfx::ColorSpace::CreateSRGB();
   const uint32_t usage = SHARED_IMAGE_USAGE_GLES2 |
@@ -1060,7 +1060,7 @@
 
   // Create a backing using mailbox.
   auto mailbox = Mailbox::GenerateForSharedImage();
-  const auto format = viz::SharedImageFormat::kRGBA_8888;
+  const auto format = viz::SinglePlaneFormat::kRGBA_8888;
   const gfx::Size size(1, 1);
   const auto color_space = gfx::ColorSpace::CreateSRGB();
   const uint32_t usage = SHARED_IMAGE_USAGE_GLES2 |
@@ -1158,7 +1158,7 @@
 
   // Create a mailbox.
   auto mailbox = Mailbox::GenerateForSharedImage();
-  const auto format = viz::SharedImageFormat::kRGBA_8888;
+  const auto format = viz::SinglePlaneFormat::kRGBA_8888;
   const gfx::Size size(1, 1);
   const auto color_space = gfx::ColorSpace::CreateSRGB();
   const uint32_t usage =
@@ -1335,7 +1335,7 @@
 
   // Create a backing using mailbox.
   auto mailbox = Mailbox::GenerateForSharedImage();
-  const auto format = viz::SharedImageFormat::kRGBA_8888;
+  const auto format = viz::SinglePlaneFormat::kRGBA_8888;
   const gfx::Size size(1, 1);
   const auto color_space = gfx::ColorSpace::CreateSRGB();
   const uint32_t usage = SHARED_IMAGE_USAGE_GLES2 |
@@ -1466,7 +1466,7 @@
 
   // Create a backing using mailbox.
   auto mailbox = Mailbox::GenerateForSharedImage();
-  const auto format = viz::SharedImageFormat::kRGBA_8888;
+  const auto format = viz::SinglePlaneFormat::kRGBA_8888;
   const gfx::Size size(1, 1);
   const auto color_space = gfx::ColorSpace::CreateSRGB();
   const uint32_t usage = SHARED_IMAGE_USAGE_GLES2 |
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 b1d54c8a..5f84bb6 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
@@ -102,7 +102,7 @@
     Mailbox mailbox = Mailbox::GenerateForSharedImage();
     std::unique_ptr<SharedImageBacking> backing =
         shared_image_factory_->CreateSharedImage(
-            mailbox, viz::SharedImageFormat::kRGBA_8888, nullptr,
+            mailbox, viz::SinglePlaneFormat::kRGBA_8888, nullptr,
             gfx::Size(100, 100), gfx::ColorSpace::CreateSRGB(),
             kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, usage, false);
     ASSERT_NE(nullptr, backing);
@@ -155,7 +155,7 @@
     Mailbox mailbox = Mailbox::GenerateForSharedImage();
     std::unique_ptr<SharedImageBacking> backing =
         shared_image_factory_->CreateSharedImage(
-            mailbox, viz::SharedImageFormat::kRGBA_8888, nullptr,
+            mailbox, viz::SinglePlaneFormat::kRGBA_8888, nullptr,
             gfx::Size(100, 100), gfx::ColorSpace::CreateSRGB(),
             kTopLeft_GrSurfaceOrigin,
             has_alpha ? kPremul_SkAlphaType : kOpaque_SkAlphaType,
@@ -189,38 +189,36 @@
 
 TEST_F(DCompImageBackingFactoryTest, UsageFlags) {
   EXPECT_TRUE(shared_image_factory_->IsSupported(
-      kDCompSurfaceUsage, viz::SharedImageFormat::kRGBA_8888,
+      kDCompSurfaceUsage, viz::SinglePlaneFormat::kRGBA_8888,
       gfx::Size(100, 100), false, gfx::GpuMemoryBufferType::EMPTY_BUFFER,
       kGrContextTypeDontCare, {}));
 
   EXPECT_TRUE(shared_image_factory_->IsSupported(
-      kDXGISwapChainUsage, viz::SharedImageFormat::kRGBA_8888,
+      kDXGISwapChainUsage, viz::SinglePlaneFormat::kRGBA_8888,
       gfx::Size(100, 100), false, gfx::GpuMemoryBufferType::EMPTY_BUFFER,
       kGrContextTypeDontCare, {}));
 
   // DComp surfaces don't support readback.
   EXPECT_FALSE(shared_image_factory_->IsSupported(
       kDCompSurfaceUsage | SHARED_IMAGE_USAGE_DISPLAY_READ,
-      viz::SharedImageFormat::kRGBA_8888, gfx::Size(100, 100), false,
+      viz::SinglePlaneFormat::kRGBA_8888, gfx::Size(100, 100), false,
       gfx::GpuMemoryBufferType::EMPTY_BUFFER, kGrContextTypeDontCare, {}));
 
   // We require callers to explicitly state DXGI swap chains are readable.
   EXPECT_FALSE(shared_image_factory_->IsSupported(
       SHARED_IMAGE_USAGE_DISPLAY_WRITE | SHARED_IMAGE_USAGE_SCANOUT,
-      viz::SharedImageFormat::kRGBA_8888, gfx::Size(100, 100), false,
+      viz::SinglePlaneFormat::kRGBA_8888, gfx::Size(100, 100), false,
       gfx::GpuMemoryBufferType::EMPTY_BUFFER, kGrContextTypeDontCare, {}));
 }
 
 TEST_F(DCompImageBackingFactoryTest, HDR10Support) {
   EXPECT_TRUE(shared_image_factory_->IsSupported(
-      kDXGISwapChainUsage,
-      viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_1010102),
+      kDXGISwapChainUsage, viz::SinglePlaneFormat::kRGBA_1010102,
       gfx::Size(100, 100), false, gfx::GpuMemoryBufferType::EMPTY_BUFFER,
       kGrContextTypeDontCare, {}));
 
   EXPECT_FALSE(shared_image_factory_->IsSupported(
-      kDCompSurfaceUsage,
-      viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_1010102),
+      kDCompSurfaceUsage, viz::SinglePlaneFormat::kRGBA_1010102,
       gfx::Size(100, 100), false, gfx::GpuMemoryBufferType::EMPTY_BUFFER,
       kGrContextTypeDontCare, {}));
 }
@@ -229,11 +227,9 @@
   uint32_t valid_usages[2] = {kDCompSurfaceUsage, kDXGISwapChainUsage};
 
   viz::SharedImageFormat valid_formats[5] = {
-      viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_8888),
-      viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::BGRA_8888),
-      viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBX_8888),
-      viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::BGRX_8888),
-      viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_F16),
+      viz::SinglePlaneFormat::kRGBA_8888, viz::SinglePlaneFormat::kBGRA_8888,
+      viz::SinglePlaneFormat::kRGBX_8888, viz::SinglePlaneFormat::kBGRX_8888,
+      viz::SinglePlaneFormat::kRGBA_F16,
   };
 
   for (auto valid_usage : valid_usages) {
@@ -254,7 +250,7 @@
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
   std::unique_ptr<SharedImageBacking> backing =
       shared_image_factory_->CreateSharedImage(
-          mailbox, viz::SharedImageFormat::kRGBA_8888, nullptr,
+          mailbox, viz::SinglePlaneFormat::kRGBA_8888, nullptr,
           gfx::Size(100, 100), gfx::ColorSpace::CreateSRGB(),
           kTopLeft_GrSurfaceOrigin, kOpaque_SkAlphaType, kDXGISwapChainUsage,
           false);
@@ -311,7 +307,7 @@
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
   std::unique_ptr<SharedImageBacking> backing =
       shared_image_factory_->CreateSharedImage(
-          mailbox, viz::SharedImageFormat::kRGBA_8888, nullptr,
+          mailbox, viz::SinglePlaneFormat::kRGBA_8888, nullptr,
           gfx::Size(100, 100), gfx::ColorSpace::CreateSRGB(),
           kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, kDCompSurfaceUsage,
           false);
@@ -350,7 +346,7 @@
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
   std::unique_ptr<SharedImageBacking> backing =
       shared_image_factory_->CreateSharedImage(
-          mailbox, viz::SharedImageFormat::kRGBA_8888, nullptr,
+          mailbox, viz::SinglePlaneFormat::kRGBA_8888, nullptr,
           gfx::Size(100, 100), gfx::ColorSpace::CreateSRGB(),
           kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, kDCompSurfaceUsage,
           false);
@@ -443,7 +439,7 @@
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
   std::unique_ptr<SharedImageBacking> backing =
       shared_image_factory_->CreateSharedImage(
-          mailbox, viz::SharedImageFormat::kRGBA_8888, nullptr,
+          mailbox, viz::SinglePlaneFormat::kRGBA_8888, nullptr,
           gfx::Size(100, 100), gfx::ColorSpace::CreateSRGB(),
           kTopLeft_GrSurfaceOrigin, kOpaque_SkAlphaType, kDXGISwapChainUsage,
           false);
@@ -658,8 +654,7 @@
 TEST_F(DCompImageBackingFactoryVisualTreeTest, DCompSurfaceCanDisplayLinear) {
   SkColor test_color = SkColorSetRGB(0x20, 0x40, 0x80);
   SkColor expected_color = SkColorSetRGB(0x35, 0x65, 0xc3);
-  RunTest(kDCompSurfaceUsage,
-          viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_F16),
+  RunTest(kDCompSurfaceUsage, viz::SinglePlaneFormat::kRGBA_F16,
           gfx::ColorSpace::CreateSCRGBLinear80Nits(), false, test_color,
           expected_color);
 }
@@ -683,8 +678,7 @@
        DCompSurfaceCanDisplayLinearWithAlpha) {
   SkColor test_color = SkColorSetARGB(0x80, 0x20, 0x40, 0x80);
   SkColor expected_color = SkColorSetRGB(0x10, 0x20, 0x40);
-  RunTest(kDCompSurfaceUsage,
-          viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_F16),
+  RunTest(kDCompSurfaceUsage, viz::SinglePlaneFormat::kRGBA_F16,
           gfx::ColorSpace::CreateSCRGBLinear80Nits(), true, test_color,
           expected_color);
 }
@@ -708,8 +702,7 @@
 TEST_F(DCompImageBackingFactoryVisualTreeTest, DXGISwapChainCanDisplayLinear) {
   SkColor test_color = SkColorSetRGB(0x20, 0x40, 0x80);
   SkColor expected_color = SkColorSetRGB(0x35, 0x65, 0xc3);
-  RunTest(kDXGISwapChainUsage,
-          viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_F16),
+  RunTest(kDXGISwapChainUsage, viz::SinglePlaneFormat::kRGBA_F16,
           gfx::ColorSpace::CreateSCRGBLinear80Nits(), false, test_color,
           expected_color);
 }
@@ -717,10 +710,8 @@
 TEST_F(DCompImageBackingFactoryVisualTreeTest, DXGISwapChainCanDisplayHDR10) {
   SkColor test_color = SkColorSetRGB(0x20, 0x40, 0x80);
   SkColor expected_color = SkColorSetRGB(0x35, 0x65, 0xc3);
-  RunTest(
-      kDXGISwapChainUsage,
-      viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_1010102),
-      gfx::ColorSpace::CreateHDR10(), false, test_color, expected_color);
+  RunTest(kDXGISwapChainUsage, viz::SinglePlaneFormat::kRGBA_1010102,
+          gfx::ColorSpace::CreateHDR10(), false, test_color, expected_color);
 }
 
 TEST_F(DCompImageBackingFactoryVisualTreeTest,
@@ -742,8 +733,7 @@
        DXGISwapChainCanDisplayLinearWithAlpha) {
   SkColor test_color = SkColorSetARGB(0x80, 0x20, 0x40, 0x80);
   SkColor expected_color = SkColorSetRGB(0x10, 0x20, 0x40);
-  RunTest(kDXGISwapChainUsage,
-          viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_F16),
+  RunTest(kDXGISwapChainUsage, viz::SinglePlaneFormat::kRGBA_F16,
           gfx::ColorSpace::CreateSCRGBLinear80Nits(), true, test_color,
           expected_color);
 }
@@ -752,10 +742,8 @@
        DXGISwapChainCanDisplayHDR10WithAlpha) {
   SkColor test_color = SkColorSetARGB(0x80, 0x20, 0x40, 0x80);
   SkColor expected_color = SkColorSetRGB(0x10, 0x20, 0x40);
-  RunTest(
-      kDXGISwapChainUsage,
-      viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_1010102),
-      gfx::ColorSpace::CreateHDR10(), true, test_color, expected_color);
+  RunTest(kDXGISwapChainUsage, viz::SinglePlaneFormat::kRGBA_1010102,
+          gfx::ColorSpace::CreateHDR10(), true, test_color, expected_color);
 }
 
 TEST_F(DCompImageBackingFactoryVisualTreeTest,
@@ -763,7 +751,7 @@
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
   std::unique_ptr<SharedImageBacking> backing =
       shared_image_factory_->CreateSharedImage(
-          mailbox, viz::SharedImageFormat::kRGBA_8888, nullptr,
+          mailbox, viz::SinglePlaneFormat::kRGBA_8888, nullptr,
           gfx::Size(100, 100), gfx::ColorSpace::CreateSRGB(),
           kTopLeft_GrSurfaceOrigin, kOpaque_SkAlphaType, kDXGISwapChainUsage,
           false);
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc
index 08ed4265..13d40eeb 100644
--- a/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc
@@ -103,13 +103,18 @@
        (usage & SHARED_IMAGE_USAGE_RASTER))) {
     return false;
   }
-  constexpr uint32_t kInvalidUsage =
-      SHARED_IMAGE_USAGE_WEBGPU | SHARED_IMAGE_USAGE_VIDEO_DECODE |
-      SHARED_IMAGE_USAGE_SCANOUT | SHARED_IMAGE_USAGE_CPU_UPLOAD;
+  constexpr uint32_t kInvalidUsage = SHARED_IMAGE_USAGE_VIDEO_DECODE |
+                                     SHARED_IMAGE_USAGE_SCANOUT |
+                                     SHARED_IMAGE_USAGE_CPU_UPLOAD;
   if (usage & kInvalidUsage) {
     return false;
   }
 
+  if ((usage & SHARED_IMAGE_USAGE_WEBGPU) &&
+      (use_webgpu_adapter_ != WebGPUAdapterName::kCompat)) {
+    return false;
+  }
+
   if (gl::GetGLImplementation() == gl::kGLImplementationEGLANGLE &&
       gl::GetANGLEImplementation() == gl::ANGLEImplementation::kMetal) {
     constexpr uint32_t kMetalInvalidUsages =
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc
index 85369d64..5ca146c 100644
--- a/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc
@@ -381,7 +381,7 @@
 
   // Create a backing using mailbox.
   const auto mailbox = Mailbox::GenerateForSharedImage();
-  const auto format = viz::SharedImageFormat::kRGBA_8888;
+  const auto format = viz::SinglePlaneFormat::kRGBA_8888;
   const gfx::Size size(1, 1);
   const auto color_space = gfx::ColorSpace::CreateSRGB();
   const gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle;
@@ -581,7 +581,7 @@
 
 // High bit depth rendering is not supported on Android.
 const auto kSharedImageFormats =
-    ::testing::Values(viz::SharedImageFormat::kRGBA_8888);
+    ::testing::Values(viz::SinglePlaneFormat::kRGBA_8888);
 
 std::string TestParamToString(
     const testing::TestParamInfo<std::tuple<bool, viz::SharedImageFormat>>&
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory_unittest.cc
index e7ca039..4295741 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory_unittest.cc
@@ -155,7 +155,7 @@
   }
   // Create a backing using mailbox.
   auto mailbox = Mailbox::GenerateForSharedImage();
-  const auto format = viz::SharedImageFormat::kRGBA_8888;
+  const auto format = viz::SinglePlaneFormat::kRGBA_8888;
   const gfx::Size size(4, 4);
   const auto color_space = gfx::ColorSpace::CreateSRGB();
   const uint32_t usage =
@@ -279,7 +279,7 @@
   }
   // Create a backing using mailbox.
   auto mailbox = Mailbox::GenerateForSharedImage();
-  const auto format = viz::SharedImageFormat::kRGBA_8888;
+  const auto format = viz::SinglePlaneFormat::kRGBA_8888;
   const gfx::Size size(4, 4);
   const auto color_space = gfx::ColorSpace::CreateSRGB();
   const uint32_t usage =
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory_unittest.cc
index 71dd5a2..0a82e5f 100644
--- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory_unittest.cc
@@ -49,7 +49,7 @@
 
 bool IsGLSupported(viz::SharedImageFormat format) {
   return format.is_single_plane() && !format.IsLegacyMultiplanar() &&
-         format != viz::SharedImageFormat::kBGR_565;
+         format != viz::SinglePlaneFormat::kBGR_565;
 }
 
 void CreateSharedContext(const GpuDriverBugWorkarounds& workarounds,
@@ -214,7 +214,7 @@
 // Ensures that GLTextureImageBacking registers it's estimated size
 // with memory tracker.
 TEST_F(GLTextureImageBackingFactoryTest, EstimatedSize) {
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   auto mailbox = Mailbox::GenerateForSharedImage();
   gfx::Size size(256, 256);
   auto color_space = gfx::ColorSpace::CreateSRGB();
@@ -641,31 +641,31 @@
   return param_info.param.ToString();
 }
 
-const auto kInitialDataFormats = ::testing::Values(
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::ETC1),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_8888),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::BGRA_8888),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_4444),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RED_8),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RG_88),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::BGRA_1010102),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_1010102));
+const auto kInitialDataFormats =
+    ::testing::Values(viz::SinglePlaneFormat::kETC1,
+                      viz::SinglePlaneFormat::kRGBA_8888,
+                      viz::SinglePlaneFormat::kBGRA_8888,
+                      viz::SinglePlaneFormat::kRGBA_4444,
+                      viz::SinglePlaneFormat::kRED_8,
+                      viz::SinglePlaneFormat::kRG_88,
+                      viz::SinglePlaneFormat::kBGRA_1010102,
+                      viz::SinglePlaneFormat::kRGBA_1010102);
 
 INSTANTIATE_TEST_SUITE_P(,
                          GLTextureImageBackingFactoryInitialDataTest,
                          kInitialDataFormats,
                          TestParamToString);
 
-const auto kSharedImageFormats = ::testing::Values(
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_8888),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::BGRA_8888),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_4444),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RED_8),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RG_88),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::BGRA_1010102),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_1010102),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBX_8888),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::BGRX_8888));
+const auto kSharedImageFormats =
+    ::testing::Values(viz::SinglePlaneFormat::kRGBA_8888,
+                      viz::SinglePlaneFormat::kBGRA_8888,
+                      viz::SinglePlaneFormat::kRGBA_4444,
+                      viz::SinglePlaneFormat::kRED_8,
+                      viz::SinglePlaneFormat::kRG_88,
+                      viz::SinglePlaneFormat::kBGRA_1010102,
+                      viz::SinglePlaneFormat::kRGBA_1010102,
+                      viz::SinglePlaneFormat::kRGBX_8888,
+                      viz::SinglePlaneFormat::kBGRX_8888);
 
 INSTANTIATE_TEST_SUITE_P(,
                          GLTextureImageBackingFactoryWithFormatTest,
@@ -677,13 +677,13 @@
                          kSharedImageFormats,
                          TestParamToString);
 
-const auto kReadbackFormats = ::testing::Values(
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_8888),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::BGRA_8888),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RED_8),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RG_88),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBX_8888),
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::BGRX_8888));
+const auto kReadbackFormats =
+    ::testing::Values(viz::SinglePlaneFormat::kRGBA_8888,
+                      viz::SinglePlaneFormat::kBGRA_8888,
+                      viz::SinglePlaneFormat::kRED_8,
+                      viz::SinglePlaneFormat::kRG_88,
+                      viz::SinglePlaneFormat::kRGBX_8888,
+                      viz::SinglePlaneFormat::kBGRX_8888);
 
 INSTANTIATE_TEST_SUITE_P(,
                          GLTextureImageBackingFactoryWithReadbackTest,
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing.h b/gpu/command_buffer/service/shared_image/iosurface_image_backing.h
index e2ba97e..b878a90 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing.h
@@ -168,6 +168,33 @@
   gfx::ScopedIOSurface io_surface_;
 };
 
+// Representation of a IOSurfaceImageBacking as a Dawn Texture.
+class DawnIOSurfaceRepresentation : public DawnImageRepresentation {
+ public:
+  DawnIOSurfaceRepresentation(SharedImageManager* manager,
+                              SharedImageBacking* backing,
+                              MemoryTypeTracker* tracker,
+                              WGPUDevice device,
+                              base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
+                              WGPUTextureFormat wgpu_format,
+                              std::vector<WGPUTextureFormat> view_formats);
+  ~DawnIOSurfaceRepresentation() override;
+
+  WGPUTexture BeginAccess(WGPUTextureUsage usage) final;
+  void EndAccess() final;
+
+ private:
+  base::ScopedCFTypeRef<IOSurfaceRef> io_surface_;
+  WGPUDevice device_;
+  WGPUTexture texture_ = nullptr;
+  WGPUTextureFormat wgpu_format_;
+  std::vector<WGPUTextureFormat> view_formats_;
+
+  // TODO(cwallez@chromium.org): Load procs only once when the factory is
+  // created and pass a pointer to them around?
+  DawnProcTable dawn_procs_;
+};
+
 // This class is only put into unique_ptrs and is never copied or assigned.
 class SharedEventAndSignalValue {
  public:
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm b/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm
index 2e43d36..0cbc3c5 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm
@@ -4,6 +4,7 @@
 
 #include "gpu/command_buffer/service/shared_image/iosurface_image_backing.h"
 
+#include "base/mac/scoped_cftyperef.h"
 #include "base/mac/scoped_nsobject.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "components/viz/common/gpu/metal_context_provider.h"
@@ -30,6 +31,12 @@
 
 #import <Metal/Metal.h>
 
+// Usage of BUILDFLAG(USE_DAWN) needs to be after the include for
+// ui/gl/buildflags.h
+#if BUILDFLAG(USE_DAWN)
+#include <dawn/native/MetalBackend.h>
+#endif  // BUILDFLAG(USE_DAWN)
+
 namespace gpu {
 
 namespace {
@@ -371,6 +378,149 @@
   return IOSurfaceIsInUse(io_surface_);
 }
 
+///////////////////////////////////////////////////////////////////////////////
+// DawnIOSurfaceRepresentation
+
+DawnIOSurfaceRepresentation::DawnIOSurfaceRepresentation(
+    SharedImageManager* manager,
+    SharedImageBacking* backing,
+    MemoryTypeTracker* tracker,
+    WGPUDevice device,
+    base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
+    WGPUTextureFormat wgpu_format,
+    std::vector<WGPUTextureFormat> view_formats)
+    : DawnImageRepresentation(manager, backing, tracker),
+      io_surface_(std::move(io_surface)),
+      device_(device),
+      wgpu_format_(wgpu_format),
+      view_formats_(std::move(view_formats)),
+      dawn_procs_(dawn::native::GetProcs()) {
+  DCHECK(device_);
+  DCHECK(io_surface_);
+
+  // Keep a reference to the device so that it stays valid (it might become
+  // lost in which case operations will be noops).
+  dawn_procs_.deviceReference(device_);
+}
+
+DawnIOSurfaceRepresentation::~DawnIOSurfaceRepresentation() {
+  EndAccess();
+  dawn_procs_.deviceRelease(device_);
+}
+
+WGPUTexture DawnIOSurfaceRepresentation::BeginAccess(WGPUTextureUsage usage) {
+  WGPUTextureDescriptor texture_descriptor = {};
+  texture_descriptor.format = wgpu_format_;
+  texture_descriptor.usage = usage;
+  texture_descriptor.dimension = WGPUTextureDimension_2D;
+  texture_descriptor.size = {static_cast<uint32_t>(size().width()),
+                             static_cast<uint32_t>(size().height()), 1};
+  texture_descriptor.mipLevelCount = 1;
+  texture_descriptor.sampleCount = 1;
+  texture_descriptor.viewFormatCount =
+      static_cast<uint32_t>(view_formats_.size());
+  texture_descriptor.viewFormats = view_formats_.data();
+
+  // We need to have internal usages of CopySrc for copies. If texture is not
+  // for video frame import, which has bi-planar format, we also need
+  // RenderAttachment usage for clears, and TextureBinding for
+  // copyTextureForBrowser.
+  WGPUDawnTextureInternalUsageDescriptor internalDesc = {};
+  internalDesc.chain.sType = WGPUSType_DawnTextureInternalUsageDescriptor;
+  internalDesc.internalUsage =
+      WGPUTextureUsage_CopySrc | WGPUTextureUsage_TextureBinding;
+  if (wgpu_format_ != WGPUTextureFormat_R8BG8Biplanar420Unorm) {
+    internalDesc.internalUsage |= WGPUTextureUsage_RenderAttachment;
+  }
+
+  texture_descriptor.nextInChain =
+      reinterpret_cast<WGPUChainedStruct*>(&internalDesc);
+
+  dawn::native::metal::ExternalImageDescriptorIOSurface descriptor;
+  descriptor.cTextureDescriptor = &texture_descriptor;
+  descriptor.isInitialized = IsCleared();
+  descriptor.ioSurface = io_surface_.get();
+  descriptor.plane = 0;
+
+  // Synchronize with all of the MTLSharedEvents that have been
+  // stored in the backing as a consequence of earlier BeginAccess/
+  // EndAccess calls against other representations.
+  if (gl::GetANGLEImplementation() == gl::ANGLEImplementation::kMetal) {
+    if (@available(macOS 10.14, *)) {
+      SharedImageBacking* backing = this->backing();
+      // Not possible to reach this with any other type of backing.
+      DCHECK_EQ(backing->GetType(), SharedImageBackingType::kIOSurface);
+      IOSurfaceImageBacking* iosurface_backing =
+          static_cast<IOSurfaceImageBacking*>(backing);
+      std::vector<std::unique_ptr<SharedEventAndSignalValue>> signals =
+          iosurface_backing->TakeSharedEvents();
+      for (const auto& signal : signals) {
+        dawn::native::metal::ExternalImageMTLSharedEventDescriptor
+            external_desc;
+        external_desc.sharedEvent =
+            static_cast<id<MTLSharedEvent>>(signal->shared_event());
+        external_desc.signaledValue = signal->signaled_value();
+        descriptor.waitEvents.push_back(external_desc);
+      }
+    }
+  }
+
+  texture_ = dawn::native::metal::WrapIOSurface(device_, &descriptor);
+  return texture_;
+}
+
+void DawnIOSurfaceRepresentation::EndAccess() {
+  if (!texture_) {
+    return;
+  }
+
+  dawn::native::metal::ExternalImageIOSurfaceEndAccessDescriptor descriptor;
+  dawn::native::metal::IOSurfaceEndAccess(texture_, &descriptor);
+
+  if (descriptor.isInitialized) {
+    SetCleared();
+  }
+
+  if (gl::GetANGLEImplementation() == gl::ANGLEImplementation::kMetal) {
+    if (@available(macOS 10.14, *)) {
+      SharedImageBacking* backing = this->backing();
+      // Not possible to reach this with any other type of backing.
+      DCHECK_EQ(backing->GetType(), SharedImageBackingType::kIOSurface);
+      IOSurfaceImageBacking* iosurface_backing =
+          static_cast<IOSurfaceImageBacking*>(backing);
+      // Dawn's Metal backend has enqueued a MTLSharedEvent which
+      // consumers of the IOSurface must wait upon before attempting to
+      // use that IOSurface on another MTLDevice. Store this event in
+      // the underlying SharedImageBacking.
+      iosurface_backing->AddSharedEventAndSignalValue(descriptor.sharedEvent,
+                                                      descriptor.signaledValue);
+    }
+  }
+
+  // All further operations on the textures are errors (they would be racy
+  // with other backings).
+  dawn_procs_.textureDestroy(texture_);
+
+  // TODO(b/252731382): the following WaitForCommandsToBeScheduled call should
+  // no longer be necessary, but for some reason it is. Removing it
+  // reintroduces intermittent renders of black frames to the WebGPU canvas.
+  // This points to another synchronization bug not resolved by the use of
+  // MTLSharedEvent between Dawn and ANGLE's Metal backend.
+  //
+  // macOS has a global GPU command queue so synchronization between APIs and
+  // devices is automatic. However on Metal, wgpuQueueSubmit "commits" the
+  // Metal command buffers but they aren't "scheduled" in the global queue
+  // immediately. (that work seems offloaded to a different thread?)
+  // Wait for all the previous submitted commands to be scheduled to have
+  // scheduling races between commands using the IOSurface on different APIs.
+  // This is a blocking call but should be almost instant.
+  TRACE_EVENT0("gpu", "DawnIOSurfaceRepresentation::EndAccess");
+  dawn::native::metal::WaitForCommandsToBeScheduled(device_);
+
+  dawn_procs_.textureRelease(texture_);
+  texture_ = nullptr;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // SharedEventAndSignalValue
 
@@ -622,11 +772,30 @@
     WGPUDevice device,
     WGPUBackendType backend_type,
     std::vector<WGPUTextureFormat> view_formats) {
-  auto result = IOSurfaceImageBackingFactory::ProduceDawn(
-      manager, this, tracker, device, view_formats, io_surface_);
-  if (result)
-    return result;
+#if BUILDFLAG(USE_DAWN)
+  // See comments in IOSurfaceImageBackingFactory::CreateSharedImage
+  // regarding RGBA versus BGRA.
+  viz::SharedImageFormat actual_format = format();
+  if (actual_format == viz::SinglePlaneFormat::kRGBA_8888) {
+    actual_format = viz::SinglePlaneFormat::kBGRA_8888;
+  }
 
+  // TODO(crbug.com/1293514): Remove this if condition after using single
+  // multiplanar mailbox and actual_format could report multiplanar format
+  // correctly.
+  if (IOSurfaceGetPixelFormat(io_surface_) == '420v') {
+    actual_format = viz::SharedImageFormat::SinglePlane(viz::YUV_420_BIPLANAR);
+  }
+
+  absl::optional<WGPUTextureFormat> wgpu_format = ToWGPUFormat(actual_format);
+  if (wgpu_format.value() == WGPUTextureFormat_Undefined) {
+    return nullptr;
+  }
+
+  return std::make_unique<DawnIOSurfaceRepresentation>(
+      manager, this, tracker, device, io_surface_, wgpu_format.value(),
+      std::move(view_formats));
+#else   // BUILDFLAG(USE_DAWN)
   if (!factory()) {
     DLOG(ERROR) << "No SharedImageFactory to create a dawn representation.";
     return nullptr;
@@ -636,6 +805,7 @@
       factory(), manager, tracker, device, backend_type,
       std::move(view_formats), this,
       /*use_passthrough=*/true);
+#endif  // BUILDFLAG(USE_DAWN)
 }
 
 std::unique_ptr<SkiaImageRepresentation> IOSurfaceImageBacking::ProduceSkia(
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h
index 5db9d6b..71be743c 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h
@@ -39,14 +39,6 @@
 class GPU_GLES2_EXPORT IOSurfaceImageBackingFactory
     : public SharedImageBackingFactory {
  public:
-  static std::unique_ptr<DawnImageRepresentation> ProduceDawn(
-      SharedImageManager* manager,
-      SharedImageBacking* backing,
-      MemoryTypeTracker* tracker,
-      WGPUDevice device,
-      std::vector<WGPUTextureFormat> view_formats,
-      gfx::ScopedIOSurface io_surface);
-
   IOSurfaceImageBackingFactory(const GpuPreferences& gpu_preferences,
                                const GpuDriverBugWorkarounds& workarounds,
                                const gles2::FeatureInfo* feature_info,
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm
index fee5d4d..efb7898 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm
@@ -4,7 +4,6 @@
 
 #include "gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h"
 
-#include "base/mac/scoped_cftyperef.h"
 #include "base/memory/scoped_refptr.h"
 #include "build/build_config.h"
 #include "components/viz/common/resources/resource_format_utils.h"
@@ -31,12 +30,6 @@
 
 #import <Metal/Metal.h>
 
-// Usage of BUILDFLAG(USE_DAWN) needs to be after the include for
-// ui/gl/buildflags.h
-#if BUILDFLAG(USE_DAWN)
-#include <dawn/native/MetalBackend.h>
-#endif  // BUILDFLAG(USE_DAWN)
-
 namespace gpu {
 
 namespace {
@@ -103,196 +96,6 @@
 
 }  // anonymous namespace
 
-// Representation of a SharedImageBackingIOSurface as a Dawn Texture.
-#if BUILDFLAG(USE_DAWN)
-class DawnIOSurfaceRepresentation : public DawnImageRepresentation {
- public:
-  DawnIOSurfaceRepresentation(SharedImageManager* manager,
-                              SharedImageBacking* backing,
-                              MemoryTypeTracker* tracker,
-                              WGPUDevice device,
-                              base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
-                              WGPUTextureFormat wgpu_format,
-                              std::vector<WGPUTextureFormat> view_formats)
-      : DawnImageRepresentation(manager, backing, tracker),
-        io_surface_(std::move(io_surface)),
-        device_(device),
-        wgpu_format_(wgpu_format),
-        view_formats_(std::move(view_formats)),
-        dawn_procs_(dawn::native::GetProcs()) {
-    DCHECK(device_);
-    DCHECK(io_surface_);
-
-    // Keep a reference to the device so that it stays valid (it might become
-    // lost in which case operations will be noops).
-    dawn_procs_.deviceReference(device_);
-  }
-
-  ~DawnIOSurfaceRepresentation() override {
-    EndAccess();
-    dawn_procs_.deviceRelease(device_);
-  }
-
-  WGPUTexture BeginAccess(WGPUTextureUsage usage) final {
-    WGPUTextureDescriptor texture_descriptor = {};
-    texture_descriptor.format = wgpu_format_;
-    texture_descriptor.usage = usage;
-    texture_descriptor.dimension = WGPUTextureDimension_2D;
-    texture_descriptor.size = {static_cast<uint32_t>(size().width()),
-                               static_cast<uint32_t>(size().height()), 1};
-    texture_descriptor.mipLevelCount = 1;
-    texture_descriptor.sampleCount = 1;
-    texture_descriptor.viewFormatCount =
-        static_cast<uint32_t>(view_formats_.size());
-    texture_descriptor.viewFormats = view_formats_.data();
-
-    // We need to have internal usages of CopySrc for copies. If texture is not
-    // for video frame import, which has bi-planar format, we also need
-    // RenderAttachment usage for clears, and TextureBinding for
-    // copyTextureForBrowser.
-    WGPUDawnTextureInternalUsageDescriptor internalDesc = {};
-    internalDesc.chain.sType = WGPUSType_DawnTextureInternalUsageDescriptor;
-    internalDesc.internalUsage =
-        WGPUTextureUsage_CopySrc | WGPUTextureUsage_TextureBinding;
-    if (wgpu_format_ != WGPUTextureFormat_R8BG8Biplanar420Unorm) {
-      internalDesc.internalUsage |= WGPUTextureUsage_RenderAttachment;
-    }
-
-    texture_descriptor.nextInChain =
-        reinterpret_cast<WGPUChainedStruct*>(&internalDesc);
-
-    dawn::native::metal::ExternalImageDescriptorIOSurface descriptor;
-    descriptor.cTextureDescriptor = &texture_descriptor;
-    descriptor.isInitialized = IsCleared();
-    descriptor.ioSurface = io_surface_.get();
-    descriptor.plane = 0;
-
-    // Synchronize with all of the MTLSharedEvents that have been
-    // stored in the backing as a consequence of earlier BeginAccess/
-    // EndAccess calls against other representations.
-    if (gl::GetANGLEImplementation() == gl::ANGLEImplementation::kMetal) {
-      if (@available(macOS 10.14, *)) {
-        SharedImageBacking* backing = this->backing();
-        // Not possible to reach this with any other type of backing.
-        DCHECK_EQ(backing->GetType(), SharedImageBackingType::kIOSurface);
-        IOSurfaceImageBacking* iosurface_backing =
-            static_cast<IOSurfaceImageBacking*>(backing);
-        std::vector<std::unique_ptr<SharedEventAndSignalValue>> signals =
-            iosurface_backing->TakeSharedEvents();
-        for (const auto& signal : signals) {
-          dawn::native::metal::ExternalImageMTLSharedEventDescriptor
-              external_desc;
-          external_desc.sharedEvent =
-              static_cast<id<MTLSharedEvent>>(signal->shared_event());
-          external_desc.signaledValue = signal->signaled_value();
-          descriptor.waitEvents.push_back(external_desc);
-        }
-      }
-    }
-
-    texture_ = dawn::native::metal::WrapIOSurface(device_, &descriptor);
-    return texture_;
-  }
-
-  void EndAccess() final {
-    if (!texture_) {
-      return;
-    }
-
-    dawn::native::metal::ExternalImageIOSurfaceEndAccessDescriptor descriptor;
-    dawn::native::metal::IOSurfaceEndAccess(texture_, &descriptor);
-
-    if (descriptor.isInitialized) {
-      SetCleared();
-    }
-
-    if (gl::GetANGLEImplementation() == gl::ANGLEImplementation::kMetal) {
-      if (@available(macOS 10.14, *)) {
-        SharedImageBacking* backing = this->backing();
-        // Not possible to reach this with any other type of backing.
-        DCHECK_EQ(backing->GetType(), SharedImageBackingType::kIOSurface);
-        IOSurfaceImageBacking* iosurface_backing =
-            static_cast<IOSurfaceImageBacking*>(backing);
-        // Dawn's Metal backend has enqueued a MTLSharedEvent which
-        // consumers of the IOSurface must wait upon before attempting to
-        // use that IOSurface on another MTLDevice. Store this event in
-        // the underlying SharedImageBacking.
-        iosurface_backing->AddSharedEventAndSignalValue(
-            descriptor.sharedEvent, descriptor.signaledValue);
-      }
-    }
-
-    // All further operations on the textures are errors (they would be racy
-    // with other backings).
-    dawn_procs_.textureDestroy(texture_);
-
-    // TODO(b/252731382): the following WaitForCommandsToBeScheduled call should
-    // no longer be necessary, but for some reason it is. Removing it
-    // reintroduces intermittent renders of black frames to the WebGPU canvas.
-    // This points to another synchronization bug not resolved by the use of
-    // MTLSharedEvent between Dawn and ANGLE's Metal backend.
-    //
-    // macOS has a global GPU command queue so synchronization between APIs and
-    // devices is automatic. However on Metal, wgpuQueueSubmit "commits" the
-    // Metal command buffers but they aren't "scheduled" in the global queue
-    // immediately. (that work seems offloaded to a different thread?)
-    // Wait for all the previous submitted commands to be scheduled to have
-    // scheduling races between commands using the IOSurface on different APIs.
-    // This is a blocking call but should be almost instant.
-    TRACE_EVENT0("gpu", "DawnIOSurfaceRepresentation::EndAccess");
-    dawn::native::metal::WaitForCommandsToBeScheduled(device_);
-
-    dawn_procs_.textureRelease(texture_);
-    texture_ = nullptr;
-  }
-
- private:
-  base::ScopedCFTypeRef<IOSurfaceRef> io_surface_;
-  WGPUDevice device_;
-  WGPUTexture texture_ = nullptr;
-  WGPUTextureFormat wgpu_format_;
-  std::vector<WGPUTextureFormat> view_formats_;
-
-  // TODO(cwallez@chromium.org): Load procs only once when the factory is
-  // created and pass a pointer to them around?
-  DawnProcTable dawn_procs_;
-};
-#endif  // BUILDFLAG(USE_DAWN)
-
-// static
-std::unique_ptr<DawnImageRepresentation>
-IOSurfaceImageBackingFactory::ProduceDawn(
-    SharedImageManager* manager,
-    SharedImageBacking* backing,
-    MemoryTypeTracker* tracker,
-    WGPUDevice device,
-    std::vector<WGPUTextureFormat> view_formats,
-    gfx::ScopedIOSurface io_surface) {
-#if BUILDFLAG(USE_DAWN)
-  // See comments in IOSurfaceImageBackingFactory::CreateSharedImage
-  // regarding RGBA versus BGRA.
-  viz::SharedImageFormat actual_format = backing->format();
-  if (actual_format == viz::SharedImageFormat::kRGBA_8888)
-    actual_format = viz::SharedImageFormat::kBGRA_8888;
-
-  // TODO(crbug.com/1293514): Remove this if condition after using single
-  // multiplanar mailbox and actual_format could report multiplanar format
-  // correctly.
-  if (IOSurfaceGetPixelFormat(io_surface) == '420v')
-    actual_format = viz::SharedImageFormat::SinglePlane(viz::YUV_420_BIPLANAR);
-
-  absl::optional<WGPUTextureFormat> wgpu_format = ToWGPUFormat(actual_format);
-  if (wgpu_format.value() == WGPUTextureFormat_Undefined)
-    return nullptr;
-
-  return std::make_unique<DawnIOSurfaceRepresentation>(
-      manager, backing, tracker, device, io_surface, wgpu_format.value(),
-      std::move(view_formats));
-#else   // BUILDFLAG(USE_DAWN)
-  return nullptr;
-#endif  // BUILDFLAG(USE_DAWN)
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // IOSurfaceImageBackingFactory
 
diff --git a/gpu/command_buffer/service/shared_image/shared_image_factory_unittest.cc b/gpu/command_buffer/service/shared_image/shared_image_factory_unittest.cc
index 7b129afa..581704471 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/shared_image_factory_unittest.cc
@@ -58,8 +58,7 @@
 
 TEST_F(SharedImageFactoryTest, Basic) {
   auto mailbox = Mailbox::GenerateForSharedImage();
-  auto format =
-      viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_8888);
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   gfx::Size size(256, 256);
   auto color_space = gfx::ColorSpace::CreateSRGB();
   gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle;
@@ -72,8 +71,7 @@
 
 TEST_F(SharedImageFactoryTest, DuplicateMailbox) {
   auto mailbox = Mailbox::GenerateForSharedImage();
-  auto format =
-      viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_8888);
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   gfx::Size size(256, 256);
   auto color_space = gfx::ColorSpace::CreateSRGB();
   gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle;
diff --git a/gpu/command_buffer/service/shared_image/shared_image_manager_unittest.cc b/gpu/command_buffer/service/shared_image/shared_image_manager_unittest.cc
index 624f086..89e6141 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_manager_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/shared_image_manager_unittest.cc
@@ -23,7 +23,7 @@
 
 std::unique_ptr<TestImageBacking> CreateImageBacking(size_t size_in_bytes) {
   auto mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   gfx::Size size(256, 256);
   auto color_space = gfx::ColorSpace::CreateSRGB();
   auto surface_origin = kTopLeft_GrSurfaceOrigin;
@@ -41,7 +41,7 @@
   auto tracker = std::make_unique<MemoryTypeTracker>(nullptr);
 
   auto mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   gfx::Size size(256, 256);
   auto color_space = gfx::ColorSpace::CreateSRGB();
   auto surface_origin = kTopLeft_GrSurfaceOrigin;
@@ -113,7 +113,7 @@
   auto tracker = std::make_unique<MemoryTypeTracker>(nullptr);
 
   auto mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   gfx::Size size(256, 256);
   auto color_space = gfx::ColorSpace::CreateSRGB();
   auto surface_origin = kTopLeft_GrSurfaceOrigin;
@@ -145,7 +145,7 @@
   auto tracker2 = std::make_unique<MemoryTypeTracker>(nullptr);
 
   auto mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   gfx::Size size(256, 256);
   auto color_space = gfx::ColorSpace::CreateSRGB();
   auto surface_origin = kTopLeft_GrSurfaceOrigin;
@@ -215,7 +215,7 @@
       &memory_tracker2, memory_tracker2.task_runner());
 
   auto mailbox = Mailbox::GenerateForSharedImage();
-  auto format = viz::SharedImageFormat::kRGBA_8888;
+  auto format = viz::SinglePlaneFormat::kRGBA_8888;
   gfx::Size size(256, 256);
   auto color_space = gfx::ColorSpace::CreateSRGB();
   auto surface_origin = kTopLeft_GrSurfaceOrigin;
diff --git a/gpu/command_buffer/service/shared_image/shared_image_representation_unittest.cc b/gpu/command_buffer/service/shared_image/shared_image_representation_unittest.cc
index 0c152f6..c44b3f3 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_representation_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/shared_image_representation_unittest.cc
@@ -22,7 +22,7 @@
   void SetUp() override {
     tracker_ = std::make_unique<MemoryTypeTracker>(nullptr);
     mailbox_ = Mailbox::GenerateForSharedImage();
-    auto format = viz::SharedImageFormat::kRGBA_8888;
+    auto format = viz::SinglePlaneFormat::kRGBA_8888;
     gfx::Size size(256, 256);
     auto color_space = gfx::ColorSpace::CreateSRGB();
     auto surface_origin = kTopLeft_GrSurfaceOrigin;
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc
index 15ccec78..2348e26 100644
--- a/gpu/command_buffer/service/webgpu_decoder_impl.cc
+++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -505,12 +505,12 @@
       viz::SharedImageFormat format = representation->format();
       // Include list of formats this is tested to work with.
       // See gpu/command_buffer/tests/webgpu_mailbox_unittest.cc
-      if (format != viz::SharedImageFormat::kBGRA_8888 &&
+      if (format != viz::SinglePlaneFormat::kBGRA_8888 &&
 // TODO(crbug.com/1241369): Handle additional formats.
 #if !BUILDFLAG(IS_MAC)
-          format != viz::SharedImageFormat::kRGBA_8888 &&
+          format != viz::SinglePlaneFormat::kRGBA_8888 &&
 #endif
-          format != viz::SharedImageFormat::kRGBA_F16) {
+          format != viz::SinglePlaneFormat::kRGBA_F16) {
         return nullptr;
       }
 
diff --git a/gpu/ipc/service/gpu_memory_ablation_experiment.cc b/gpu/ipc/service/gpu_memory_ablation_experiment.cc
index 6366f0b..9f84a032 100644
--- a/gpu/ipc/service/gpu_memory_ablation_experiment.cc
+++ b/gpu/ipc/service/gpu_memory_ablation_experiment.cc
@@ -38,8 +38,7 @@
 const char kGPUMemoryAblationFeatureSizeParam[] = "Size";
 
 // Image allocation parameters.
-constexpr viz::SharedImageFormat kFormat =
-    viz::SharedImageFormat::SinglePlane(viz::ResourceFormat::RGBA_8888);
+constexpr viz::SharedImageFormat kFormat = viz::SinglePlaneFormat::kRGBA_8888;
 constexpr uint32_t kUsage = SHARED_IMAGE_USAGE_DISPLAY_READ;
 
 bool GpuMemoryAblationExperiment::ExperimentSupported() {
diff --git a/headless/lib/switches.cc b/headless/lib/switches.cc
index 64b26af9..f07d45a 100644
--- a/headless/lib/switches.cc
+++ b/headless/lib/switches.cc
@@ -7,19 +7,11 @@
 namespace headless {
 namespace switches {
 
-// Whether cookies stored as part of user profile are encrypted.
-const char kDisableCookieEncryption[] = "disable-cookie-encryption";
+// Allowlist for Negotiate Auth servers.
+const char kAuthServerAllowlist[] = "auth-server-allowlist";
 
-// Whether or not begin frames should be issued over DevToolsProtocol
-// (experimental).
-const char kEnableBeginFrameControl[] = "enable-begin-frame-control";
-
-// Enable crash reporter for headless.
-const char kEnableCrashReporter[] = "enable-crash-reporter";
-
-// Disable crash reporter for headless. It is enabled by default in official
-// builds.
-const char kDisableCrashReporter[] = "disable-crash-reporter";
+// If true, then all pop-ups and calls to window.open will fail.
+const char kBlockNewWebContents[] = "block-new-web-contents";
 
 // The directory breakpad should store minidumps in.
 const char kCrashDumpsDir[] = "crash-dumps-dir";
@@ -29,10 +21,43 @@
 // (experimental).
 const char kDeterministicMode[] = "deterministic-mode";
 
+// Disable crash reporter for headless. It is enabled by default in official
+// builds.
+const char kDisableCrashReporter[] = "disable-crash-reporter";
+
+// Whether cookies stored as part of user profile are encrypted.
+const char kDisableCookieEncryption[] = "disable-cookie-encryption";
+
+// Do not emit tags when printing PDFs.
+const char kDisablePDFTagging[] = "disable-pdf-tagging";
+
 // Use a specific disk cache location, rather than one derived from the
 // UserDatadir.
 const char kDiskCacheDir[] = "disk-cache-dir";
 
+// Whether or not begin frames should be issued over DevToolsProtocol
+// (experimental).
+const char kEnableBeginFrameControl[] = "enable-begin-frame-control";
+
+// Enable crash reporter for headless.
+const char kEnableCrashReporter[] = "enable-crash-reporter";
+
+// Allows overriding the list of restricted ports by passing a comma-separated
+// list of port numbers.
+const char kExplicitlyAllowedPorts[] = "explicitly-allowed-ports";
+
+// Sets font render hinting when running headless, affects Skia rendering and
+// whether glyph subpixel positioning is enabled.
+// Possible values: none|slight|medium|full|max. Default: full.
+const char kFontRenderHinting[] = "font-render-hinting";
+
+// Forces Incognito mode even if user data directory is specified using the
+// --user-data-dir switch.
+const char kIncognito[] = "incognito";
+
+// Do not use system proxy configuration service.
+const char kNoSystemProxyConfigService[] = "no-system-proxy-config-service";
+
 // Specifies which encryption storage backend to use. Possible values are
 // kwallet, kwallet5, gnome, gnome-keyring, gnome-libsecret, basic. Any other
 // value will lead to Chrome detecting the best backend automatically.
@@ -43,9 +68,6 @@
 // or KWallets.
 const char kPasswordStore[] = "password-store";
 
-// Do not emit tags when printing PDFs.
-const char kDisablePDFTagging[] = "disable-pdf-tagging";
-
 // Specifies a list of hosts for whom we bypass proxy settings and use direct
 // connections. Ignored unless --proxy-server is also specified. This is a
 // comma-separated list of bypass rules. See:
@@ -56,9 +78,6 @@
 // affects HTTP and HTTPS requests.
 const char kProxyServer[] = "proxy-server";
 
-// Do not use system proxy configuration service.
-const char kNoSystemProxyConfigService[] = "no-system-proxy-config-service";
-
 // Use the given address instead of the default loopback for accepting remote
 // debugging connections. Should be used together with --remote-debugging-port.
 // Note that the remote debugging protocol does not perform any authentication,
@@ -73,27 +92,11 @@
 // forced with --incognito switch.
 const char kUserDataDir[] = "user-data-dir";
 
-// Forces Incognito mode even if user data directory is specified using the
-// --user-data-dir switch.
-const char kIncognito[] = "incognito";
-
 // Sets the initial window size. Provided as string in the format "800,600".
 const char kWindowSize[] = "window-size";
 
-// Allowlist for Negotiate Auth servers.
-const char kAuthServerAllowlist[] = "auth-server-allowlist";
-
-// Sets font render hinting when running headless, affects Skia rendering and
-// whether glyph subpixel positioning is enabled.
-// Possible values: none|slight|medium|full|max. Default: full.
-const char kFontRenderHinting[] = "font-render-hinting";
-
-// If true, then all pop-ups and calls to window.open will fail.
-const char kBlockNewWebContents[] = "block-new-web-contents";
-
-// Allows overriding the list of restricted ports by passing a comma-separated
-// list of port numbers.
-const char kExplicitlyAllowedPorts[] = "explicitly-allowed-ports";
+// No! Please don't just add your switches at the end of the list.
+// Please maintain the switch list sorted.
 
 }  // namespace switches
 }  // namespace headless
diff --git a/headless/public/switches.h b/headless/public/switches.h
index a23b1c1..b2a1abb 100644
--- a/headless/public/switches.h
+++ b/headless/public/switches.h
@@ -10,27 +10,30 @@
 namespace headless {
 namespace switches {
 
+// All switches in alphabetical order. The switches should be documented
+// alongside the definition of their values in the .cc file.
+
+HEADLESS_EXPORT extern const char kAuthServerAllowlist[];
+HEADLESS_EXPORT extern const char kBlockNewWebContents[];
 HEADLESS_EXPORT extern const char kCrashDumpsDir[];
 HEADLESS_EXPORT extern const char kDeterministicMode[];
 HEADLESS_EXPORT extern const char kDisableCookieEncryption[];
 HEADLESS_EXPORT extern const char kDisableCrashReporter[];
+HEADLESS_EXPORT extern const char kDisablePDFTagging[];
 HEADLESS_EXPORT extern const char kDiskCacheDir[];
 HEADLESS_EXPORT extern const char kEnableBeginFrameControl[];
 HEADLESS_EXPORT extern const char kEnableCrashReporter[];
+HEADLESS_EXPORT extern const char kExplicitlyAllowedPorts[];
+HEADLESS_EXPORT extern const char kFontRenderHinting[];
+HEADLESS_EXPORT extern const char kIncognito[];
+HEADLESS_EXPORT extern const char kNoSystemProxyConfigService[];
 HEADLESS_EXPORT extern const char kPasswordStore[];
-HEADLESS_EXPORT extern const char kDisablePDFTagging[];
 HEADLESS_EXPORT extern const char kProxyBypassList[];
 HEADLESS_EXPORT extern const char kProxyServer[];
-HEADLESS_EXPORT extern const char kNoSystemProxyConfigService[];
 HEADLESS_EXPORT extern const char kRemoteDebuggingAddress[];
 HEADLESS_EXPORT extern const char kUserAgent[];
 HEADLESS_EXPORT extern const char kUserDataDir[];
-HEADLESS_EXPORT extern const char kIncognito[];
 HEADLESS_EXPORT extern const char kWindowSize[];
-HEADLESS_EXPORT extern const char kAuthServerAllowlist[];
-HEADLESS_EXPORT extern const char kFontRenderHinting[];
-HEADLESS_EXPORT extern const char kBlockNewWebContents[];
-HEADLESS_EXPORT extern const char kExplicitlyAllowedPorts[];
 
 }  // namespace switches
 }  // namespace headless
diff --git a/ios/chrome/browser/ui/authentication/enterprise/enterprise_prompt/enterprise_prompt_view_controller.mm b/ios/chrome/browser/ui/authentication/enterprise/enterprise_prompt/enterprise_prompt_view_controller.mm
index efc6b9cd..f604a82 100644
--- a/ios/chrome/browser/ui/authentication/enterprise/enterprise_prompt/enterprise_prompt_view_controller.mm
+++ b/ios/chrome/browser/ui/authentication/enterprise/enterprise_prompt/enterprise_prompt_view_controller.mm
@@ -59,7 +59,7 @@
   if (@available(iOS 15, *)) {
     self.titleTextStyle = UIFontTextStyleTitle2;
     // Icon already contains some spacing for the shadow.
-    self.customSpacingBeforeImageIfNoToolbar = 24;
+    self.customSpacingBeforeImageIfNoNavigationBar = 24;
     self.customSpacingAfterImage = 1;
     self.topAlignedLayout = YES;
   }
diff --git a/ios/chrome/browser/ui/follow/first_follow_view_controller.mm b/ios/chrome/browser/ui/follow/first_follow_view_controller.mm
index c95ee03..1d6bcd6 100644
--- a/ios/chrome/browser/ui/follow/first_follow_view_controller.mm
+++ b/ios/chrome/browser/ui/follow/first_follow_view_controller.mm
@@ -21,7 +21,7 @@
 
 namespace {
 
-constexpr CGFloat customSpacingBeforeImageIfNoToolbar = 24;
+constexpr CGFloat customSpacingBeforeImageIfNoNavigationBar = 24;
 constexpr CGFloat customSpacingAfterImage = 24;
 
 }  // namespace
@@ -47,8 +47,8 @@
   self.imageHasFixedSize = YES;
   self.imageEnclosedWithShadowAndBadge = YES;
   self.showDismissBarButton = NO;
-  self.customSpacingBeforeImageIfNoToolbar =
-      customSpacingBeforeImageIfNoToolbar;
+  self.customSpacingBeforeImageIfNoNavigationBar =
+      customSpacingBeforeImageIfNoNavigationBar;
   self.customSpacingAfterImage = customSpacingAfterImage;
   self.titleTextStyle = UIFontTextStyleTitle2;
   self.topAlignedLayout = YES;
diff --git a/ios/chrome/browser/ui/ntp/feed_promos/feed_sign_in_promo_view_controller.mm b/ios/chrome/browser/ui/ntp/feed_promos/feed_sign_in_promo_view_controller.mm
index d8dc661..d5e86f9 100644
--- a/ios/chrome/browser/ui/ntp/feed_promos/feed_sign_in_promo_view_controller.mm
+++ b/ios/chrome/browser/ui/ntp/feed_promos/feed_sign_in_promo_view_controller.mm
@@ -16,7 +16,7 @@
 
 constexpr CGFloat customImageWidth = 60;
 constexpr CGFloat customImageHeight = 60;
-constexpr CGFloat customSpacingBeforeImageIfNoToolbar = 36;
+constexpr CGFloat customSpacingBeforeImageIfNoNavigationBar = 36;
 constexpr CGFloat customSpacingAfterImage = 24;
 
 }  // namespace
@@ -25,8 +25,8 @@
 
 - (void)viewDidLoad {
   self.imageHasFixedSize = YES;
-  self.customSpacingBeforeImageIfNoToolbar =
-      customSpacingBeforeImageIfNoToolbar;
+  self.customSpacingBeforeImageIfNoNavigationBar =
+      customSpacingBeforeImageIfNoNavigationBar;
   self.customSpacingAfterImage = customSpacingAfterImage;
   self.showDismissBarButton = NO;
   self.topAlignedLayout = YES;
diff --git a/ios/chrome/browser/ui/passwords/BUILD.gn b/ios/chrome/browser/ui/passwords/BUILD.gn
index d1e9a9a..d3a3b4c 100644
--- a/ios/chrome/browser/ui/passwords/BUILD.gn
+++ b/ios/chrome/browser/ui/passwords/BUILD.gn
@@ -40,6 +40,7 @@
     "//ios/chrome/browser/ui/autofill/form_input_accessory",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
+    "//ios/chrome/browser/ui/settings/password:title_view",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/browser/web_state_list",
     "//ios/chrome/common/ui/colors",
diff --git a/ios/chrome/browser/ui/passwords/password_breach_view_controller.mm b/ios/chrome/browser/ui/passwords/password_breach_view_controller.mm
index b5df6482..75ef2ac 100644
--- a/ios/chrome/browser/ui/passwords/password_breach_view_controller.mm
+++ b/ios/chrome/browser/ui/passwords/password_breach_view_controller.mm
@@ -5,6 +5,8 @@
 #import "ios/chrome/browser/ui/passwords/password_breach_view_controller.h"
 
 #import "ios/chrome/browser/ui/passwords/password_constants.h"
+#import "ios/chrome/browser/ui/settings/password/branded_navigation_item_title_view.h"
+#import "ios/chrome/browser/ui/settings/password/create_password_manager_title_view.h"
 #import "ios/chrome/common/ui/confirmation_alert/confirmation_alert_action_handler.h"
 #import "ios/chrome/grit/ios_strings.h"
 #import "ui/base/l10n/l10n_util.h"
@@ -19,6 +21,7 @@
 
 - (void)loadView {
   self.helpButtonAvailable = YES;
+  self.titleView = [self setUpTitleView];
   self.helpButtonAccessibilityLabel =
       l10n_util::GetNSString(IDS_IOS_HELP_ACCESSIBILITY_LABEL);
 
@@ -48,4 +51,12 @@
   self.secondaryActionString = secondaryActionString;
 }
 
+#pragma mark - Private methods
+
+// Configures the title view of this ViewController.
+- (UIView*)setUpTitleView {
+  NSString* title = l10n_util::GetNSString(IDS_IOS_PASSWORD_MANAGER);
+  return password_manager::CreatePasswordManagerTitleView(title);
+}
+
 @end
diff --git a/ios/chrome/browser/ui/passwords/password_suggestion_view_controller.mm b/ios/chrome/browser/ui/passwords/password_suggestion_view_controller.mm
index 11bd32d..1fe29cf 100644
--- a/ios/chrome/browser/ui/passwords/password_suggestion_view_controller.mm
+++ b/ios/chrome/browser/ui/passwords/password_suggestion_view_controller.mm
@@ -28,7 +28,7 @@
 @end
 
 namespace {
-constexpr CGFloat customSpacingBeforeImageIfNoToolbar = 24;
+constexpr CGFloat customSpacingBeforeImageIfNoNavigationBar = 24;
 constexpr CGFloat customSpacingAfterImage = 1;
 }  // namespace
 
@@ -50,8 +50,8 @@
       ios::provider::BrandedImage::kPasswordSuggestionKey);
   self.imageHasFixedSize = YES;
   self.showDismissBarButton = NO;
-  self.customSpacingBeforeImageIfNoToolbar =
-      customSpacingBeforeImageIfNoToolbar;
+  self.customSpacingBeforeImageIfNoNavigationBar =
+      customSpacingBeforeImageIfNoNavigationBar;
   self.customSpacingAfterImage = customSpacingAfterImage;
   self.titleTextStyle = UIFontTextStyleTitle2;
   self.topAlignedLayout = YES;
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.h
index 9a70d2d..409f644 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.h
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.h
@@ -7,7 +7,20 @@
 
 #import <Foundation/Foundation.h>
 
+#import "ios/chrome/browser/ui/list_model/list_model.h"
+
 // The accessibility identifier of the password details table view.
 extern NSString* const kPasswordDetailsViewControllerId;
 
+// UI items for password details
+typedef NS_ENUM(NSInteger, PasswordDetailsItemType) {
+  PasswordDetailsItemTypeWebsite = kItemTypeEnumZero,
+  PasswordDetailsItemTypeUsername,
+  PasswordDetailsItemTypePassword,
+  PasswordDetailsItemTypeFederation,
+  PasswordDetailsItemTypeChangePasswordButton,
+  PasswordDetailsItemTypeChangePasswordRecommendation,
+  PasswordDetailsItemTypeDeleteButton,
+};
+
 #endif  // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_TABLE_VIEW_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm
index 0a35edf..3bee782 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm
@@ -57,16 +57,6 @@
   SectionIdentifierCompromisedInfo,
 };
 
-typedef NS_ENUM(NSInteger, ItemType) {
-  ItemTypeWebsite = kItemTypeEnumZero,
-  ItemTypeUsername,
-  ItemTypePassword,
-  ItemTypeFederation,
-  ItemTypeChangePasswordButton,
-  ItemTypeChangePasswordRecommendation,
-  ItemTypeDeleteButton,
-};
-
 typedef NS_ENUM(NSInteger, ReauthenticationReason) {
   ReauthenticationReasonShow = 0,
   ReauthenticationReasonCopy,
@@ -230,8 +220,8 @@
 
 - (TableViewStackedDetailsItem*)websiteItemForPasswordDetails:
     (PasswordDetails*)passwordDetails {
-  TableViewStackedDetailsItem* item =
-      [[TableViewStackedDetailsItem alloc] initWithType:ItemTypeWebsite];
+  TableViewStackedDetailsItem* item = [[TableViewStackedDetailsItem alloc]
+      initWithType:PasswordDetailsItemTypeWebsite];
   item.titleText = l10n_util::GetNSString(
       IsPasswordGroupingEnabled() ? IDS_IOS_SHOW_PASSWORD_VIEW_SITES
                                   : IDS_IOS_SHOW_PASSWORD_VIEW_SITE);
@@ -242,8 +232,8 @@
 
 - (TableViewTextEditItem*)usernameItemForPasswordDetails:
     (PasswordDetails*)passwordDetails {
-  TableViewTextEditItem* item =
-      [[TableViewTextEditItem alloc] initWithType:ItemTypeUsername];
+  TableViewTextEditItem* item = [[TableViewTextEditItem alloc]
+      initWithType:PasswordDetailsItemTypeUsername];
   item.textFieldBackgroundColor = [UIColor clearColor];
   item.textFieldName =
       l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_USERNAME);
@@ -265,8 +255,8 @@
 
 - (TableViewTextEditItem*)passwordItemForPasswordDetails:
     (PasswordDetails*)passwordDetails {
-  TableViewTextEditItem* item =
-      [[TableViewTextEditItem alloc] initWithType:ItemTypePassword];
+  TableViewTextEditItem* item = [[TableViewTextEditItem alloc]
+      initWithType:PasswordDetailsItemTypePassword];
   item.textFieldBackgroundColor = [UIColor clearColor];
   item.textFieldName =
       l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD);
@@ -307,8 +297,8 @@
 
 - (TableViewTextEditItem*)federationItemForPasswordDetails:
     (PasswordDetails*)passwordDetails {
-  TableViewTextEditItem* item =
-      [[TableViewTextEditItem alloc] initWithType:ItemTypeFederation];
+  TableViewTextEditItem* item = [[TableViewTextEditItem alloc]
+      initWithType:PasswordDetailsItemTypeFederation];
   item.textFieldBackgroundColor = [UIColor clearColor];
   item.textFieldName =
       l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_FEDERATION);
@@ -319,8 +309,8 @@
 }
 
 - (TableViewTextItem*)changePasswordItem {
-  TableViewTextItem* item =
-      [[TableViewTextItem alloc] initWithType:ItemTypeChangePasswordButton];
+  TableViewTextItem* item = [[TableViewTextItem alloc]
+      initWithType:PasswordDetailsItemTypeChangePasswordButton];
   item.text = l10n_util::GetNSString(IDS_IOS_CHANGE_COMPROMISED_PASSWORD);
   item.textColor = self.tableView.editing
                        ? [UIColor colorNamed:kTextSecondaryColor]
@@ -331,7 +321,7 @@
 
 - (SettingsImageDetailTextItem*)changePasswordRecommendationItem {
   SettingsImageDetailTextItem* item = [[SettingsImageDetailTextItem alloc]
-      initWithType:ItemTypeChangePasswordRecommendation];
+      initWithType:PasswordDetailsItemTypeChangePasswordRecommendation];
   item.detailText = l10n_util::GetNSString(
       IDS_IOS_CHANGE_COMPROMISED_PASSWORD_DESCRIPTION_BRANDED);
   item.image = [self compromisedIcon];
@@ -343,8 +333,8 @@
 
 - (TableViewTextButtonItem*)deleteButtonItemForPasswordDetails:
     (PasswordDetails*)passwordDetails {
-  TableViewTextButtonItem* item =
-      [[TableViewTextButtonItem alloc] initWithType:ItemTypeDeleteButton];
+  TableViewTextButtonItem* item = [[TableViewTextButtonItem alloc]
+      initWithType:PasswordDetailsItemTypeDeleteButton];
   item.buttonText = l10n_util::GetNSString(IDS_IOS_SETTINGS_TOOLBAR_DELETE);
   item.boldButtonText = NO;
   item.disableButtonIntrinsicWidth = YES;
@@ -363,15 +353,15 @@
   TableViewModel* model = self.tableViewModel;
   NSInteger itemType = [model itemTypeForIndexPath:indexPath];
   switch (itemType) {
-    case ItemTypeWebsite:
-    case ItemTypeFederation:
+    case PasswordDetailsItemTypeWebsite:
+    case PasswordDetailsItemTypeFederation:
       [self ensureContextMenuShownForItemType:itemType
                                     tableView:tableView
                                   atIndexPath:indexPath];
       break;
-    case ItemTypeChangePasswordRecommendation:
+    case PasswordDetailsItemTypeChangePasswordRecommendation:
       break;
-    case ItemTypeUsername: {
+    case PasswordDetailsItemTypeUsername: {
       if (self.tableView.editing) {
         UITableViewCell* cell =
             [self.tableView cellForRowAtIndexPath:indexPath];
@@ -385,7 +375,7 @@
       }
       break;
     }
-    case ItemTypePassword: {
+    case PasswordDetailsItemTypePassword: {
       if (self.tableView.editing) {
         UITableViewCell* cell =
             [self.tableView cellForRowAtIndexPath:indexPath];
@@ -399,19 +389,20 @@
       }
       break;
     }
-    case ItemTypeChangePasswordButton:
+    case PasswordDetailsItemTypeChangePasswordButton:
       if (!self.tableView.editing) {
+        int passwordIndex = IsPasswordGroupingEnabled() ? indexPath.section : 0;
         DCHECK(self.applicationCommandsHandler);
-        DCHECK(self.passwords[indexPath.section].changePasswordURL.is_valid());
+        DCHECK(self.passwords[passwordIndex].changePasswordURL.is_valid());
         OpenNewTabCommand* command = [OpenNewTabCommand
-            commandWithURLFromChrome:self.passwords[indexPath.section]
+            commandWithURLFromChrome:self.passwords[passwordIndex]
                                          .changePasswordURL];
         UmaHistogramEnumeration("PasswordManager.BulkCheck.UserAction",
                                 PasswordCheckInteraction::kChangePassword);
         [self.applicationCommandsHandler closeSettingsUIAndOpenURL:command];
       }
       break;
-    case ItemTypeDeleteButton:
+    case PasswordDetailsItemTypeDeleteButton:
       break;
   }
 }
@@ -471,7 +462,7 @@
   cell.selectionStyle = UITableViewCellSelectionStyleDefault;
 
   switch (itemType) {
-    case ItemTypeUsername: {
+    case PasswordDetailsItemTypeUsername: {
       TableViewTextEditCell* textFieldCell =
           base::mac::ObjCCastStrict<TableViewTextEditCell>(cell);
       textFieldCell.textField.delegate = self;
@@ -482,7 +473,7 @@
       self.usernameErrorAnchorView = textFieldCell.iconView;
       break;
     }
-    case ItemTypePassword: {
+    case PasswordDetailsItemTypePassword: {
       TableViewTextEditCell* textFieldCell =
           base::mac::ObjCCastStrict<TableViewTextEditCell>(cell);
       textFieldCell.textField.delegate = self;
@@ -493,15 +484,15 @@
       [textFieldCell.identifyingIconButton setTag:indexPath.section];
       break;
     }
-    case ItemTypeWebsite:
-    case ItemTypeFederation:
-    case ItemTypeChangePasswordButton:
+    case PasswordDetailsItemTypeWebsite:
+    case PasswordDetailsItemTypeFederation:
+    case PasswordDetailsItemTypeChangePasswordButton:
       break;
-    case ItemTypeChangePasswordRecommendation: {
+    case PasswordDetailsItemTypeChangePasswordRecommendation: {
       cell.selectionStyle = UITableViewCellSelectionStyleNone;
       break;
     }
-    case ItemTypeDeleteButton: {
+    case PasswordDetailsItemTypeDeleteButton: {
       TableViewTextButtonCell* tableViewTextButtonCell =
           base::mac::ObjCCastStrict<TableViewTextButtonCell>(cell);
       [tableViewTextButtonCell.button addTarget:self
@@ -518,10 +509,10 @@
     canEditRowAtIndexPath:(NSIndexPath*)indexPath {
   NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath];
   switch (itemType) {
-    case ItemTypeWebsite:
-    case ItemTypeFederation:
-    case ItemTypeUsername:
-    case ItemTypePassword:
+    case PasswordDetailsItemTypeWebsite:
+    case PasswordDetailsItemTypeFederation:
+    case PasswordDetailsItemTypeUsername:
+    case PasswordDetailsItemTypePassword:
       return YES;
   }
   return NO;
@@ -742,15 +733,15 @@
 
 - (BOOL)isItemAtIndexPathTextEditCell:(NSIndexPath*)cellPath {
   NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:cellPath];
-  switch (static_cast<ItemType>(itemType)) {
-    case ItemTypeUsername:
-    case ItemTypePassword:
+  switch (static_cast<PasswordDetailsItemType>(itemType)) {
+    case PasswordDetailsItemTypeUsername:
+    case PasswordDetailsItemTypePassword:
       return YES;
-    case ItemTypeWebsite:
-    case ItemTypeFederation:
-    case ItemTypeChangePasswordButton:
-    case ItemTypeChangePasswordRecommendation:
-    case ItemTypeDeleteButton:
+    case PasswordDetailsItemTypeWebsite:
+    case PasswordDetailsItemTypeFederation:
+    case PasswordDetailsItemTypeChangePasswordButton:
+    case PasswordDetailsItemTypeChangePasswordRecommendation:
+    case PasswordDetailsItemTypeDeleteButton:
       return NO;
   }
 }
@@ -1028,7 +1019,7 @@
   NSString* message = nil;
 
   switch (menuItem.itemType) {
-    case ItemTypeWebsite: {
+    case PasswordDetailsItemTypeWebsite: {
       PasswordDetails* detailsToCopy;
       if (IsPasswordGroupingEnabled()) {
         detailsToCopy =
@@ -1052,7 +1043,7 @@
       generalPasteboard.string = websitesForPasteboard;
       break;
     }
-    case ItemTypeUsername:
+    case PasswordDetailsItemTypeUsername:
       generalPasteboard.string =
           self.passwords[IsPasswordGroupingEnabled()
                              ? self.tableView.indexPathForSelectedRow.section
@@ -1061,7 +1052,7 @@
       message =
           l10n_util::GetNSString(IDS_IOS_SETTINGS_USERNAME_WAS_COPIED_MESSAGE);
       break;
-    case ItemTypeFederation:
+    case PasswordDetailsItemTypeFederation:
       generalPasteboard.string =
           self.passwords[IsPasswordGroupingEnabled()
                              ? self.tableView.indexPathForSelectedRow.section
@@ -1069,7 +1060,7 @@
               .federation;
       [self logCopyPasswordDetailsFailure:NO];
       return;
-    case ItemTypePassword:
+    case PasswordDetailsItemTypePassword:
       [self attemptToShowPasswordFor:ReauthenticationReasonCopy];
       [self logCopyPasswordDetailsFailure:NO];
       return;
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_unittest.mm
index 7b48e90..23fae0d 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_unittest.mm
@@ -15,12 +15,15 @@
 #import "components/password_manager/core/browser/ui/credential_ui_entry.h"
 #import "components/password_manager/core/common/password_manager_features.h"
 #import "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#import "ios/chrome/browser/ui/commands/application_commands.h"
+#import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
 #import "ios/chrome/browser/ui/commands/snackbar_commands.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_item.h"
 #import "ios/chrome/browser/ui/settings/password/password_details/cells/table_view_stacked_details_item.h"
 #import "ios/chrome/browser/ui/settings/password/password_details/password_details.h"
 #import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h"
 #import "ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.h"
 #import "ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_delegate.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h"
 #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.h"
@@ -32,6 +35,8 @@
 #import "ios/web/public/test/web_task_environment.h"
 #import "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+#import "third_party/ocmock/gtest_support.h"
 #import "ui/base/l10n/l10n_util_mac.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -94,8 +99,8 @@
 
 @end
 
-// Test class that conforms to PasswordDetailsViewControllerDelegate in order to
-// test the delegate methods are called correctly.
+// Test class that conforms to PasswordDetailsViewControllerDelegate in order
+// to test the delegate methods are called correctly.
 @interface FakePasswordDetailsDelegate
     : NSObject <PasswordDetailsTableViewControllerDelegate>
 
@@ -347,6 +352,18 @@
   NSString* syncing_user_email_ = nil;
 };
 
+class PasswordGroupingTest : public ::testing::WithParamInterface<bool>,
+                             public PasswordDetailsTableViewControllerTest {
+ protected:
+  PasswordGroupingTest() {
+    feature_list_.InitWithFeatureState(
+        password_manager::features::kPasswordsGrouping, GetParam());
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
 // Tests that password is displayed properly.
 TEST_F(PasswordDetailsTableViewControllerTest, TestPassword) {
   SetPassword();
@@ -388,6 +405,34 @@
   CheckTextCellTextWithId(IDS_IOS_CHANGE_COMPROMISED_PASSWORD, 2, 1);
 }
 
+// Tests the “Change Password on Website” button
+TEST_P(PasswordGroupingTest, TestChangePasswordOnWebsite) {
+  SetPassword(kExampleCom, kUsername, kPassword, true);
+  PasswordDetailsTableViewController* passwordDetails =
+      base::mac::ObjCCastStrict<PasswordDetailsTableViewController>(
+          controller());
+
+  id applicationCommandsMock = OCMProtocolMock(@protocol(ApplicationCommands));
+  passwordDetails.applicationCommandsHandler = applicationCommandsMock;
+
+  TableViewModel* model = passwordDetails.tableViewModel;
+  NSIndexPath* indexPath =
+      [model indexPathForItemType:PasswordDetailsItemTypeChangePasswordButton];
+
+  OCMExpect([applicationCommandsMock
+      closeSettingsUIAndOpenURL:[OCMArg checkWithBlock:^BOOL(id value) {
+        // This block verifies that the closeSettingsUIAndOpenURL function is
+        // called with a URL argument which matches the initial URL passed to
+        // the password form above. Information may have been appended to the
+        // URL argument, so we only make sure it includes the initial URL.
+        return (((OpenNewTabCommand*)value).URL.spec().find(kExampleCom) !=
+                std::string::npos);
+      }]]);
+  [passwordDetails tableView:passwordDetails.tableView
+      didSelectRowAtIndexPath:indexPath];
+  EXPECT_OCMOCK_VERIFY(applicationCommandsMock);
+}
+
 // Tests that password is shown/hidden.
 TEST_F(PasswordDetailsTableViewControllerTest, TestShowHidePassword) {
   SetPassword();
@@ -755,3 +800,7 @@
   EXPECT_EQ(1, NumberOfItemsInSection(0));
   EXPECT_EQ(2, NumberOfItemsInSection(1));
 }
+
+INSTANTIATE_TEST_SUITE_P(PasswordDetailsTableViewControllerTest,
+                         PasswordGroupingTest,
+                         ::testing::Bool());
diff --git a/ios/chrome/browser/web/chrome_web_client_unittest.mm b/ios/chrome/browser/web/chrome_web_client_unittest.mm
index a1f8ecd..59de61c 100644
--- a/ios/chrome/browser/web/chrome_web_client_unittest.mm
+++ b/ios/chrome/browser/web/chrome_web_client_unittest.mm
@@ -358,8 +358,9 @@
   web_state.SetNavigationManager(std::move(navigation_manager));
 
   LookalikeUrlContainer::FromWebState(&web_state)
-      ->SetLookalikeUrlInfo(GURL("https://www.safe.test"), GURL(kTestUrl),
-                            LookalikeUrlMatchType::kSkeletonMatchTop5k);
+      ->SetLookalikeUrlInfo(
+          GURL("https://www.safe.test"), GURL(kTestUrl),
+          lookalikes::LookalikeUrlMatchType::kSkeletonMatchTop5k);
 
   NSError* error = [NSError errorWithDomain:kLookalikeUrlErrorDomain
                                        code:kLookalikeUrlErrorCode
@@ -399,8 +400,9 @@
   web_state.SetNavigationManager(std::move(navigation_manager));
 
   LookalikeUrlContainer::FromWebState(&web_state)
-      ->SetLookalikeUrlInfo(GURL(""), GURL(kTestUrl),
-                            LookalikeUrlMatchType::kSkeletonMatchTop5k);
+      ->SetLookalikeUrlInfo(
+          GURL(""), GURL(kTestUrl),
+          lookalikes::LookalikeUrlMatchType::kSkeletonMatchTop5k);
 
   NSError* error = [NSError errorWithDomain:kLookalikeUrlErrorDomain
                                        code:kLookalikeUrlErrorCode
diff --git a/ios/chrome/browser/web/lookalike_url_app_interface.mm b/ios/chrome/browser/web/lookalike_url_app_interface.mm
index 7f2371be..26e8315 100644
--- a/ios/chrome/browser/web/lookalike_url_app_interface.mm
+++ b/ios/chrome/browser/web/lookalike_url_app_interface.mm
@@ -61,14 +61,14 @@
       }
       lookalike_container->SetLookalikeUrlInfo(
           response_url.ReplaceComponents(safeReplacements), response_url,
-          LookalikeUrlMatchType::kSkeletonMatchTop5k);
+          lookalikes::LookalikeUrlMatchType::kSkeletonMatchTop5k);
       std::move(callback).Run(CreateLookalikeErrorDecision());
       return;
     }
     if (response_url.path() == kLookalikePageEmptyUrlPathForTesting) {
       lookalike_container->SetLookalikeUrlInfo(
           GURL::EmptyGURL(), response_url,
-          LookalikeUrlMatchType::kSkeletonMatchTop5k);
+          lookalikes::LookalikeUrlMatchType::kSkeletonMatchTop5k);
       std::move(callback).Run(CreateLookalikeErrorDecision());
       return;
     }
diff --git a/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h b/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h
index 0962eff..7302e14 100644
--- a/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h
+++ b/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h
@@ -25,6 +25,9 @@
 // Setting those properties will make those buttons be added to the view
 // controller.
 @interface ConfirmationAlertViewController : UIViewController
+// The navigation bar title view. Nil if not needed. If needed, must be set
+// before the view is loaded.
+@property(nonatomic, assign) UIView* titleView;
 
 // The headline below the image. Must be set before the view is loaded.
 @property(nonatomic, copy) NSString* titleString;
@@ -52,8 +55,8 @@
 @property(nonatomic, strong) UIImage* image;
 
 // Sets the custom spacing between the top and the image, if there is no
-// toolbar. Must be set before the view is loaded.
-@property(nonatomic, assign) CGFloat customSpacingBeforeImageIfNoToolbar;
+// navigation bar. Must be set before the view is loaded.
+@property(nonatomic, assign) CGFloat customSpacingBeforeImageIfNoNavigationBar;
 
 // Sets the custom spacing between the image and the title / subtitle. Must be
 // set before the view is loaded.
@@ -81,8 +84,8 @@
 // The help button item in the top left of the view. Nil if not available.
 @property(nonatomic, readonly) UIBarButtonItem* helpButton;
 
-// Controls if the toolbar dismiss button is available in the view. Default is
-// YES. Must be set before the view is loaded.
+// Controls if the navigation bar dismiss button is available in the view.
+// Default is YES. Must be set before the view is loaded.
 @property(nonatomic) BOOL showDismissBarButton;
 
 // Allows to modify the system item for the dismiss bar button (defaults to
diff --git a/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.mm b/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.mm
index f106f0b..894a96f 100644
--- a/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.mm
+++ b/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.mm
@@ -69,14 +69,14 @@
 
 }  // namespace
 
-@interface ConfirmationAlertViewController () <UIToolbarDelegate>
+@interface ConfirmationAlertViewController ()
 
 // References to the UI properties that need to be updated when the trait
 // collection changes.
 @property(nonatomic, strong) UIButton* primaryActionButton;
 @property(nonatomic, strong) UIButton* secondaryActionButton;
 @property(nonatomic, strong) UIButton* tertiaryActionButton;
-@property(nonatomic, strong) UIToolbar* topToolbar;
+@property(nonatomic, strong) UINavigationBar* navigationBar;
 @property(nonatomic, strong) UIImageView* imageView;
 @property(nonatomic, strong) UIView* imageContainerView;
 @property(nonatomic, strong) NSLayoutConstraint* imageViewAspectRatioConstraint;
@@ -101,9 +101,9 @@
 
   self.view.backgroundColor = [UIColor colorNamed:kPrimaryBackgroundColor];
 
-  if (self.hasTopToolbar) {
-    self.topToolbar = [self createTopToolbar];
-    [self.view addSubview:self.topToolbar];
+  if (self.hasNavigationBar) {
+    self.navigationBar = [self createNavigationBar];
+    [self.view addSubview:self.navigationBar];
   }
 
   if (self.imageEnclosedWithShadowAndBadge) {
@@ -139,10 +139,10 @@
   self.view.preservesSuperviewLayoutMargins = YES;
   UILayoutGuide* margins = self.view.layoutMarginsGuide;
 
-  if (self.hasTopToolbar) {
-    // Toolbar constraints to the top.
+  if (self.hasNavigationBar) {
+    // Constraints the navigation bar to the top.
     AddSameConstraintsToSides(
-        self.topToolbar, self.view.safeAreaLayoutGuide,
+        self.navigationBar, self.view.safeAreaLayoutGuide,
         LayoutSides::kTrailing | LayoutSides::kTop | LayoutSides::kLeading);
   }
 
@@ -257,11 +257,11 @@
 
   NSLayoutYAxisAnchor* scrollViewTopAnchor;
   CGFloat scrollViewTopConstant = 0;
-  if (self.hasTopToolbar) {
-    scrollViewTopAnchor = self.topToolbar.bottomAnchor;
+  if (self.hasNavigationBar) {
+    scrollViewTopAnchor = self.navigationBar.bottomAnchor;
   } else {
     scrollViewTopAnchor = self.view.safeAreaLayoutGuide.topAnchor;
-    scrollViewTopConstant = self.customSpacingBeforeImageIfNoToolbar;
+    scrollViewTopConstant = self.customSpacingBeforeImageIfNoNavigationBar;
   }
   if (self.topAlignedLayout) {
     [scrollView.topAnchor constraintEqualToAnchor:scrollViewTopAnchor
@@ -277,8 +277,8 @@
     NSLayoutConstraint* centerYConstraint = [scrollView.centerYAnchor
         constraintEqualToAnchor:margins.centerYAnchor];
     // This needs to be lower than the height constraint, so it's deprioritized.
-    // If this breaks, the scroll view is still constrained to the top toolbar
-    // and the bottom safe area or button.
+    // If this breaks, the scroll view is still constrained to the navigation
+    // bar and the bottom safe area or button.
     centerYConstraint.priority = heightConstraint.priority - 1;
     centerYConstraint.active = YES;
   }
@@ -349,8 +349,8 @@
   [self.imageContainerView setHidden:isVerticalCompact];
   self.imageViewAspectRatioConstraint.active = !isVerticalCompact;
 
-  // Allow toolbar to update its height based on new layout.
-  [self.topToolbar invalidateIntrinsicContentSize];
+  // Allow the navigation bar to update its height based on new layout.
+  [self.navigationBar invalidateIntrinsicContentSize];
 
   [super updateViewConstraints];
 }
@@ -365,12 +365,6 @@
   // than the default.
 }
 
-#pragma mark - UIToolbarDelegate
-
-- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar {
-  return UIBarPositionTopAttached;
-}
-
 #pragma mark - Private
 
 // Handle taps on the dismiss button.
@@ -412,23 +406,21 @@
   }
 }
 
-// Helper to create the top toolbar.
-- (UIToolbar*)createTopToolbar {
-  UIToolbar* topToolbar = [[UIToolbar alloc] init];
-  topToolbar.translucent = NO;
-  [topToolbar setShadowImage:[[UIImage alloc] init]
-          forToolbarPosition:UIBarPositionAny];
-  [topToolbar setBarTintColor:[UIColor colorNamed:kBackgroundColor]];
-  topToolbar.delegate = self;
+// Helper to create the navigation bar.
+- (UINavigationBar*)createNavigationBar {
+  UINavigationBar* navigationBar = [[UINavigationBar alloc] init];
+  navigationBar.translucent = NO;
+  [navigationBar setShadowImage:[[UIImage alloc] init]];
+  [navigationBar setBarTintColor:[UIColor colorNamed:kBackgroundColor]];
 
-  NSMutableArray* toolbarItems = [[NSMutableArray alloc] init];
+  UINavigationItem* navigationItem = [[UINavigationItem alloc] init];
   if (self.helpButtonAvailable) {
     UIBarButtonItem* helpButton =
         [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"help_icon"]
                                          style:UIBarButtonItemStylePlain
                                         target:self
                                         action:@selector(didTapHelpButton)];
-    [toolbarItems addObject:helpButton];
+    navigationItem.leftBarButtonItem = helpButton;
 
     if (self.helpButtonAccessibilityLabel) {
       helpButton.isAccessibilityElement = YES;
@@ -442,24 +434,22 @@
     _helpButton = helpButton;
   }
 
-  UIBarButtonItem* spacer = [[UIBarButtonItem alloc]
-      initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
-                           target:nil
-                           action:nil];
-  [toolbarItems addObject:spacer];
+  if (self.titleView) {
+    navigationItem.titleView = self.titleView;
+  }
 
   if (self.showDismissBarButton) {
     UIBarButtonItem* dismissButton = [[UIBarButtonItem alloc]
         initWithBarButtonSystemItem:self.dismissBarButtonSystemItem
                              target:self
                              action:@selector(didTapDismissBarButton)];
-    [toolbarItems addObject:dismissButton];
+    navigationItem.rightBarButtonItem = dismissButton;
   }
 
-  topToolbar.translatesAutoresizingMaskIntoConstraints = NO;
-  [topToolbar setItems:toolbarItems];
+  navigationBar.translatesAutoresizingMaskIntoConstraints = NO;
+  [navigationBar setItems:@[ navigationItem ]];
 
-  return topToolbar;
+  return navigationBar;
 }
 
 - (void)setImage:(UIImage*)image {
@@ -602,8 +592,9 @@
   return subtitle;
 }
 
-- (BOOL)hasTopToolbar {
-  return self.helpButtonAvailable || self.showDismissBarButton;
+- (BOOL)hasNavigationBar {
+  return self.helpButtonAvailable || self.showDismissBarButton ||
+         self.titleView;
 }
 
 // Helper to create the scroll view.
diff --git a/ios/components/security_interstitials/lookalikes/BUILD.gn b/ios/components/security_interstitials/lookalikes/BUILD.gn
index 2c77434..e2e22bc 100644
--- a/ios/components/security_interstitials/lookalikes/BUILD.gn
+++ b/ios/components/security_interstitials/lookalikes/BUILD.gn
@@ -21,7 +21,6 @@
   deps = [
     "//base",
     "//components/lookalikes/core",
-    "//components/lookalikes/core:features",
     "//components/lookalikes/core:safety_tips",
     "//components/security_interstitials/core",
     "//components/ukm/ios",
@@ -45,7 +44,6 @@
     ":lookalikes",
     "//base/test:test_support",
     "//components/lookalikes/core",
-    "//components/lookalikes/core:features",
     "//components/lookalikes/core:safety_tips",
     "//components/security_interstitials/core",
     "//components/ukm:test_support",
diff --git a/ios/components/security_interstitials/lookalikes/lookalike_url_blocking_page.h b/ios/components/security_interstitials/lookalikes/lookalike_url_blocking_page.h
index 0c327908e..fe965df 100644
--- a/ios/components/security_interstitials/lookalikes/lookalike_url_blocking_page.h
+++ b/ios/components/security_interstitials/lookalikes/lookalike_url_blocking_page.h
@@ -28,7 +28,7 @@
       const GURL& safe_url,
       const GURL& request_url,
       ukm::SourceId source_id,
-      LookalikeUrlMatchType match_type,
+      lookalikes::LookalikeUrlMatchType match_type,
       std::unique_ptr<LookalikeUrlControllerClient> client);
 
  protected:
@@ -51,7 +51,7 @@
   // the default action on the interstitial is to go back or close the tab.
   const GURL safe_url_;
   ukm::SourceId source_id_;
-  LookalikeUrlMatchType match_type_;
+  lookalikes::LookalikeUrlMatchType match_type_;
 };
 
 #endif  // IOS_COMPONENTS_SECURITY_INTERSTITIALS_LOOKALIKES_LOOKALIKE_URL_BLOCKING_PAGE_H_
diff --git a/ios/components/security_interstitials/lookalikes/lookalike_url_blocking_page.mm b/ios/components/security_interstitials/lookalikes/lookalike_url_blocking_page.mm
index a9bbaad..47a303a 100644
--- a/ios/components/security_interstitials/lookalikes/lookalike_url_blocking_page.mm
+++ b/ios/components/security_interstitials/lookalikes/lookalike_url_blocking_page.mm
@@ -24,7 +24,7 @@
     const GURL& safe_url,
     const GURL& request_url,
     ukm::SourceId source_id,
-    LookalikeUrlMatchType match_type,
+    lookalikes::LookalikeUrlMatchType match_type,
     std::unique_ptr<LookalikeUrlControllerClient> client)
     : security_interstitials::IOSSecurityInterstitialPage(web_state,
                                                           request_url,
@@ -47,7 +47,8 @@
 LookalikeUrlBlockingPage::~LookalikeUrlBlockingPage() {
   // Update metrics when the interstitial is closed or user navigates away.
   ReportUkmForLookalikeUrlBlockingPageIfNeeded(
-      source_id_, match_type_, LookalikeUrlBlockingPageUserAction::kCloseOrBack,
+      source_id_, match_type_,
+      lookalikes::LookalikeUrlBlockingPageUserAction::kCloseOrBack,
       /*triggered_by_initial_url=*/false);
 }
 
@@ -64,8 +65,8 @@
     load_time_data.Set("cant_go_back", true);
   }
 
-  PopulateLookalikeUrlBlockingPageStrings(load_time_data, safe_url_,
-                                          request_url());
+  lookalikes::PopulateLookalikeUrlBlockingPageStrings(load_time_data, safe_url_,
+                                                      request_url());
 }
 
 bool LookalikeUrlBlockingPage::ShouldDisplayURL() const {
@@ -82,7 +83,7 @@
         security_interstitials::MetricsHelper::DONT_PROCEED);
     ReportUkmForLookalikeUrlBlockingPageIfNeeded(
         source_id_, match_type_,
-        LookalikeUrlBlockingPageUserAction::kAcceptSuggestion,
+        lookalikes::LookalikeUrlBlockingPageUserAction::kAcceptSuggestion,
         /*triggered_by_initial_url=*/false);
     controller_->GoBack();
   } else if (command == security_interstitials::CMD_PROCEED) {
@@ -90,7 +91,7 @@
         security_interstitials::MetricsHelper::PROCEED);
     ReportUkmForLookalikeUrlBlockingPageIfNeeded(
         source_id_, match_type_,
-        LookalikeUrlBlockingPageUserAction::kClickThrough,
+        lookalikes::LookalikeUrlBlockingPageUserAction::kClickThrough,
         /*triggered_by_initial_url=*/false);
     controller_->Proceed();
   }
diff --git a/ios/components/security_interstitials/lookalikes/lookalike_url_blocking_page_unittest.mm b/ios/components/security_interstitials/lookalikes/lookalike_url_blocking_page_unittest.mm
index e1a7262..4464924 100644
--- a/ios/components/security_interstitials/lookalikes/lookalike_url_blocking_page_unittest.mm
+++ b/ios/components/security_interstitials/lookalikes/lookalike_url_blocking_page_unittest.mm
@@ -39,8 +39,8 @@
 const char kInterstitialInteractionMetric[] =
     "interstitial.lookalike.interaction";
 const ukm::SourceId kTestSourceId = 1;
-const LookalikeUrlMatchType kTestMatchType =
-    LookalikeUrlMatchType::kSkeletonMatchTop500;
+const lookalikes::LookalikeUrlMatchType kTestMatchType =
+    lookalikes::LookalikeUrlMatchType::kSkeletonMatchTop500;
 
 using UkmEntry = ukm::builders::LookalikeUrl_NavigationSuggestion;
 
@@ -133,7 +133,8 @@
   histogram_tester_.ExpectBucketCount(kInterstitialInteractionMetric,
                                       MetricsHelper::TOTAL_VISITS, 1);
   CheckUkm("MatchType", kTestMatchType);
-  CheckUkm("UserAction", LookalikeUrlBlockingPageUserAction::kClickThrough);
+  CheckUkm("UserAction",
+           lookalikes::LookalikeUrlBlockingPageUserAction::kClickThrough);
 }
 
 // Tests that the blocking page handles the don't proceed command by navigating
@@ -161,7 +162,8 @@
   histogram_tester_.ExpectBucketCount(kInterstitialInteractionMetric,
                                       MetricsHelper::TOTAL_VISITS, 1);
   CheckUkm("MatchType", kTestMatchType);
-  CheckUkm("UserAction", LookalikeUrlBlockingPageUserAction::kAcceptSuggestion);
+  CheckUkm("UserAction",
+           lookalikes::LookalikeUrlBlockingPageUserAction::kAcceptSuggestion);
 }
 
 // Tests that the blocking page handles the don't proceed command by going back
@@ -196,7 +198,8 @@
   histogram_tester_.ExpectBucketCount(kInterstitialInteractionMetric,
                                       MetricsHelper::TOTAL_VISITS, 1);
   CheckUkm("MatchType", kTestMatchType);
-  CheckUkm("UserAction", LookalikeUrlBlockingPageUserAction::kAcceptSuggestion);
+  CheckUkm("UserAction",
+           lookalikes::LookalikeUrlBlockingPageUserAction::kAcceptSuggestion);
 }
 
 // Tests that the blocking page handles the don't proceed command by closing the
@@ -228,5 +231,6 @@
   histogram_tester_.ExpectBucketCount(kInterstitialInteractionMetric,
                                       MetricsHelper::TOTAL_VISITS, 1);
   CheckUkm("MatchType", kTestMatchType);
-  CheckUkm("UserAction", LookalikeUrlBlockingPageUserAction::kAcceptSuggestion);
+  CheckUkm("UserAction",
+           lookalikes::LookalikeUrlBlockingPageUserAction::kAcceptSuggestion);
 }
diff --git a/ios/components/security_interstitials/lookalikes/lookalike_url_container.h b/ios/components/security_interstitials/lookalikes/lookalike_url_container.h
index dfd1d81..90a751c 100644
--- a/ios/components/security_interstitials/lookalikes/lookalike_url_container.h
+++ b/ios/components/security_interstitials/lookalikes/lookalike_url_container.h
@@ -47,11 +47,11 @@
   struct LookalikeUrlInfo {
     const GURL safe_url;
     const GURL request_url;
-    LookalikeUrlMatchType match_type;
+    lookalikes::LookalikeUrlMatchType match_type;
 
     LookalikeUrlInfo(const GURL& safe_url,
                      const GURL& request_url,
-                     LookalikeUrlMatchType match_type);
+                     lookalikes::LookalikeUrlMatchType match_type);
     LookalikeUrlInfo(const LookalikeUrlInfo& other);
     ~LookalikeUrlInfo();
   };
@@ -66,7 +66,7 @@
   // Stores URL info associated with a lookalike blocking page.
   void SetLookalikeUrlInfo(const GURL& safe_url,
                            const GURL& request_url,
-                           LookalikeUrlMatchType match_type);
+                           lookalikes::LookalikeUrlMatchType match_type);
 
   // Returns currently stored parameters associated with a lookalike blocking
   // page, transferring ownership to the caller.
diff --git a/ios/components/security_interstitials/lookalikes/lookalike_url_container.mm b/ios/components/security_interstitials/lookalikes/lookalike_url_container.mm
index 138e2fc..b8f1434 100644
--- a/ios/components/security_interstitials/lookalikes/lookalike_url_container.mm
+++ b/ios/components/security_interstitials/lookalikes/lookalike_url_container.mm
@@ -34,7 +34,7 @@
 LookalikeUrlContainer::LookalikeUrlInfo::LookalikeUrlInfo(
     const GURL& safe_url,
     const GURL& request_url,
-    LookalikeUrlMatchType match_type)
+    lookalikes::LookalikeUrlMatchType match_type)
     : safe_url(safe_url), request_url(request_url), match_type(match_type) {}
 
 LookalikeUrlContainer::LookalikeUrlInfo::~LookalikeUrlInfo() {}
@@ -54,7 +54,7 @@
 void LookalikeUrlContainer::SetLookalikeUrlInfo(
     const GURL& safe_url,
     const GURL& request_url,
-    LookalikeUrlMatchType match_type) {
+    lookalikes::LookalikeUrlMatchType match_type) {
   lookalike_info_ =
       std::make_unique<LookalikeUrlInfo>(safe_url, request_url, match_type);
 }
diff --git a/ios/components/security_interstitials/lookalikes/lookalike_url_tab_helper.mm b/ios/components/security_interstitials/lookalikes/lookalike_url_tab_helper.mm
index bf54f962..15f05586 100644
--- a/ios/components/security_interstitials/lookalikes/lookalike_url_tab_helper.mm
+++ b/ios/components/security_interstitials/lookalikes/lookalike_url_tab_helper.mm
@@ -4,8 +4,6 @@
 
 #import "ios/components/security_interstitials/lookalikes/lookalike_url_tab_helper.h"
 
-#import "base/feature_list.h"
-#import "components/lookalikes/core/features.h"
 #import "components/lookalikes/core/lookalike_url_ui_util.h"
 #import "components/lookalikes/core/lookalike_url_util.h"
 #import "components/lookalikes/core/safety_tips_config.h"
@@ -87,7 +85,8 @@
   // was probably reloaded. Stop the reload and navigate back to the
   // original lookalike URL so that the full checks are exercised again.
 
-  const DomainInfo navigated_domain = GetDomainInfo(response_url);
+  const lookalikes::DomainInfo navigated_domain =
+      lookalikes::GetDomainInfo(response_url);
   // Empty domain_and_registry happens on private domains.
   if (navigated_domain.domain_and_registry.empty() ||
       IsTopDomain(navigated_domain)) {
@@ -99,11 +98,12 @@
   // fetch and set `engaged_sites` here so that an interstitial won't be
   // shown on engaged sites, and so that the interstitial will be shown on
   // lookalikes of engaged sites.
-  std::vector<DomainInfo> engaged_sites;
+  std::vector<lookalikes::DomainInfo> engaged_sites;
   std::string matched_domain;
-  LookalikeUrlMatchType match_type;
+  lookalikes::LookalikeUrlMatchType match_type =
+      lookalikes::LookalikeUrlMatchType::kNone;
   // Target allowlist is not currently used in ios.
-  const LookalikeTargetAllowlistChecker in_target_allowlist =
+  const lookalikes::LookalikeTargetAllowlistChecker in_target_allowlist =
       base::BindRepeating(^(const std::string& hostname) {
         return false;
       });
@@ -115,7 +115,7 @@
         !lookalikes::IsUrlAllowlistedBySafetyTipsComponent(
             proto, response_url.GetWithEmptyPath(),
             response_url.GetWithEmptyPath())) {
-      match_type = LookalikeUrlMatchType::kFailedSpoofChecks;
+      match_type = lookalikes::LookalikeUrlMatchType::kFailedSpoofChecks;
       RecordUMAFromMatchType(match_type);
       LookalikeUrlContainer* lookalike_container =
           LookalikeUrlContainer::FromWebState(web_state());
@@ -132,7 +132,8 @@
 
   RecordUMAFromMatchType(match_type);
 
-  const std::string suggested_domain = GetETLDPlusOne(matched_domain);
+  const std::string suggested_domain =
+      lookalikes::GetETLDPlusOne(matched_domain);
   DCHECK(!suggested_domain.empty());
   GURL::Replacements replace_host;
   replace_host.SetHostStr(suggested_domain);
@@ -152,11 +153,11 @@
   // rollout checks by passing null proto and unknown channel.
   if (GetActionForMatchType(nullptr, version_info::Channel::UNKNOWN,
                             navigated_domain.domain_and_registry, match_type) ==
-      LookalikeActionType::kRecordMetrics) {
+      lookalikes::LookalikeActionType::kRecordMetrics) {
     // Interstitial normally records UKM, but still record when it's not shown.
     RecordUkmForLookalikeUrlBlockingPage(
         ukm::GetSourceIdForWebStateDocument(web_state()), match_type,
-        LookalikeUrlBlockingPageUserAction::kInterstitialNotShown,
+        lookalikes::LookalikeUrlBlockingPageUserAction::kInterstitialNotShown,
         /*triggered_by_initial_url=*/false);
 
     std::move(callback).Run(CreateAllowDecision());
diff --git a/ios/components/security_interstitials/lookalikes/lookalike_url_tab_helper_unittest.mm b/ios/components/security_interstitials/lookalikes/lookalike_url_tab_helper_unittest.mm
index 0d3760a..584f2806 100644
--- a/ios/components/security_interstitials/lookalikes/lookalike_url_tab_helper_unittest.mm
+++ b/ios/components/security_interstitials/lookalikes/lookalike_url_tab_helper_unittest.mm
@@ -5,8 +5,6 @@
 #import "ios/components/security_interstitials/lookalikes/lookalike_url_tab_helper.h"
 
 #import "base/test/metrics/histogram_tester.h"
-#import "base/test/scoped_feature_list.h"
-#import "components/lookalikes/core/features.h"
 #import "components/lookalikes/core/safety_tip_test_utils.h"
 #import "ios/components/security_interstitials/lookalikes/lookalike_url_container.h"
 #import "ios/components/security_interstitials/lookalikes/lookalike_url_tab_allow_list.h"
@@ -75,9 +73,9 @@
   EXPECT_FALSE(ShouldAllowResponseUrl(lookalike_url, /*main_frame=*/true)
                    .ShouldAllowNavigation());
   histogram_tester_.ExpectUniqueSample(
-      lookalikes::kHistogramName,
+      lookalikes::kInterstitialHistogramName,
       static_cast<base::HistogramBase::Sample>(
-          NavigationSuggestionEvent::kMatchSkeletonTop500),
+          lookalikes::NavigationSuggestionEvent::kMatchSkeletonTop500),
       1);
 
   // Non-main frame navigations should be allowed.
@@ -94,7 +92,7 @@
   EXPECT_TRUE(ShouldAllowResponseUrl(lookalike_url, /*main_frame=*/true)
                   .ShouldAllowNavigation());
 
-  histogram_tester_.ExpectTotalCount(lookalikes::kHistogramName, 1);
+  histogram_tester_.ExpectTotalCount(lookalikes::kInterstitialHistogramName, 1);
 }
 
 // Tests that ShouldAllowResponse properly allows lookalike navigations
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
index 81486fe..07ef394 100644
--- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-3cba705b71c7d9224b5c019024175f924dfb906d
\ No newline at end of file
+21c64dda0793db20ef6c6b96d49279a3100ef055
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
index d7fae04..372fe41 100644
--- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-dc7e6f0244797d65d64ca518a652e23c671b2643
\ No newline at end of file
+9557c715e337d235b8613cfa81e0e04d0f080203
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
index 736f936..b1b7d1f 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-93cee01b874b2492de8c9a3be641e10cb9cf75a4
\ No newline at end of file
+7161db71bb8d9bd04ad51dbfd5b0bf65c958d224
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
index ac144ed3..28ab63b46 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-39712e7cdbfd7d54a8668c8b49b832f4c15feb35
\ No newline at end of file
+536115cdaa3e3142df06dfa0852144afa0603c65
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
index db98e5a..959fe55 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-019dd7b3b365a624346fda67e885bb6da4277628
\ No newline at end of file
+02df12abd9791f3014607620f20232561536e264
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
index 3e13580f..e246b97e 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-19b09568d3b639d27ebd8aa8aef19441e1189372
\ No newline at end of file
+50f4f2864b8b352bdb1d535a512e6664ce5dd8bd
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
index 4d45834..24f1454 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-35d2b0ef23e213ac0d314a4f02ea91c1f5701175
\ No newline at end of file
+1cec94c5dc5356f356338c60f8978f6a0e279ee7
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
index acb5cf1..ff91a63 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-e3e00ff319eb2c4d355f85784fe015fcf2e92a3f
\ No newline at end of file
+d97698c1de504928deb20c8f884545adb38b6c15
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
index 362164e..2f2bb2e4 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-74a9221e51cddb3431e8f8b859ba44c872ca1ec7
\ No newline at end of file
+320fd2b4d03fabac1f87ffe1410e97ce5bd97e90
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
index d1d1173..e93f334b 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-c85bce06a8287aa91d9df96f4281b8c966c976e9
\ No newline at end of file
+d7e4c313df1f6d10559a3b7c1d6952188b517655
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
index 0fd3088..af410bf 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-e4944044a1ba9852899674bdcab78b7eba51af32
\ No newline at end of file
+d18b6158ac6fa60125f81cd5056defe029f72c56
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
index 5ff1ba94..efdf516 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-9c61270b47afc934f6ef195f5d72e89fdc2374e6
\ No newline at end of file
+f8fa4de0ffc701c6c8347147238e2f8881e8ee10
\ No newline at end of file
diff --git a/ios/web_view/internal/cwv_lookalike_url_handler_unittest.mm b/ios/web_view/internal/cwv_lookalike_url_handler_unittest.mm
index 9a5c0e82..d609b29 100644
--- a/ios/web_view/internal/cwv_lookalike_url_handler_unittest.mm
+++ b/ios/web_view/internal/cwv_lookalike_url_handler_unittest.mm
@@ -43,7 +43,7 @@
       base::OnceCallback<void(NSString*)> callback) {
     auto url_info = std::make_unique<LookalikeUrlContainer::LookalikeUrlInfo>(
         safe_url, request_url,
-        LookalikeUrlMatchType::kSkeletonMatchSiteEngagement);
+        lookalikes::LookalikeUrlMatchType::kSkeletonMatchSiteEngagement);
     return
         [[CWVLookalikeURLHandler alloc] initWithWebState:&web_state_
                                         lookalikeURLInfo:std::move(url_info)
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 9e77808..37b0aa3 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -954,14 +954,10 @@
              base::FEATURE_ENABLED_BY_DEFAULT);
 
 #if defined(ARCH_CPU_ARM_FAMILY)
-// Some architectures have separate image processor hardware that
-// can be used by Chromium's ImageProcessor to color convert/crop/etc.
-// video buffers.  Sometimes it is more efficient/performant/correct
-// to use a libYUV or GL based implementation instead of the hardware to
-// do this processing.
-BASE_FEATURE(kPreferLibYuvImageProcessor,
-             "PreferLibYUVImageProcessor",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+// Experimental support for GL based image processing. On some architectures,
+// the hardware accelerated video decoder outputs frames in a format not
+// understood by the display controller. We usually use LibYUV to convert these
+// frames. This flag enables an experimental GL-based conversion method.
 BASE_FEATURE(kPreferGLImageProcessor,
              "PreferGLImageProcessor",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index b24cd08..64e3f2c 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -299,7 +299,6 @@
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kUseChromeOSDirectVideoDecoder);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kLimitConcurrentDecoderInstances);
 #if defined(ARCH_CPU_ARM_FAMILY)
-MEDIA_EXPORT BASE_DECLARE_FEATURE(kPreferLibYuvImageProcessor);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kPreferGLImageProcessor);
 #endif  // defined(ARCH_CPU_ARM_FAMILY)
 #if BUILDFLAG(IS_CHROMEOS)
diff --git a/media/gpu/android/media_codec_video_decoder_unittest.cc b/media/gpu/android/media_codec_video_decoder_unittest.cc
index c90ebae..d3b2b06c 100644
--- a/media/gpu/android/media_codec_video_decoder_unittest.cc
+++ b/media/gpu/android/media_codec_video_decoder_unittest.cc
@@ -221,7 +221,7 @@
     Initialize(config);
     mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get());
     OverlayInfo info;
-    info.routing_token = base::UnguessableToken::Deserialize(1, 2);
+    info.routing_token = base::UnguessableToken::CreateForTesting(1, 2);
     provide_overlay_info_cb_.Run(info);
     auto overlay_ptr = std::make_unique<MockAndroidOverlay>();
     auto* overlay = overlay_ptr.get();
@@ -451,10 +451,10 @@
 
   EXPECT_CALL(*surface_chooser_, MockReplaceOverlayFactory(_)).Times(2);
   OverlayInfo info;
-  info.routing_token = base::UnguessableToken::Deserialize(1, 2);
+  info.routing_token = base::UnguessableToken::CreateForTesting(1, 2);
   provide_overlay_info_cb_.Run(info);
   ASSERT_TRUE(surface_chooser_->factory_);
-  info.routing_token = base::UnguessableToken::Deserialize(3, 4);
+  info.routing_token = base::UnguessableToken::CreateForTesting(3, 4);
   provide_overlay_info_cb_.Run(info);
   ASSERT_TRUE(surface_chooser_->factory_);
 }
@@ -466,7 +466,7 @@
 
   EXPECT_CALL(*surface_chooser_, MockUpdateState()).Times(0);
   OverlayInfo info;
-  info.routing_token = base::UnguessableToken::Deserialize(1, 2);
+  info.routing_token = base::UnguessableToken::CreateForTesting(1, 2);
   provide_overlay_info_cb_.Run(info);
 }
 
@@ -476,7 +476,7 @@
   // The second overlay info update should be ignored.
   EXPECT_CALL(*surface_chooser_, MockReplaceOverlayFactory(_)).Times(1);
   OverlayInfo info;
-  info.routing_token = base::UnguessableToken::Deserialize(1, 2);
+  info.routing_token = base::UnguessableToken::CreateForTesting(1, 2);
   provide_overlay_info_cb_.Run(info);
   provide_overlay_info_cb_.Run(info);
 }
diff --git a/media/gpu/video_decode_accelerator_perf_tests.cc b/media/gpu/video_decode_accelerator_perf_tests.cc
index 15c6732..b8b537c 100644
--- a/media/gpu/video_decode_accelerator_perf_tests.cc
+++ b/media/gpu/video_decode_accelerator_perf_tests.cc
@@ -474,10 +474,6 @@
   std::vector<base::test::FeatureRef> disabled_features;
   std::vector<base::test::FeatureRef> enabled_features;
 
-#if defined(ARCH_CPU_ARM_FAMILY)
-  enabled_features.push_back(media::kPreferLibYuvImageProcessor);
-#endif  // defined(ARCH_CPU_ARM_FAMILY)
-
   media::test::DecoderImplementation implementation =
       media::test::DecoderImplementation::kVD;
   base::CommandLine::SwitchMap switches = cmd_line->GetSwitches();
diff --git a/media/gpu/video_decode_accelerator_tests.cc b/media/gpu/video_decode_accelerator_tests.cc
index ed143f9..56730436 100644
--- a/media/gpu/video_decode_accelerator_tests.cc
+++ b/media/gpu/video_decode_accelerator_tests.cc
@@ -546,10 +546,6 @@
   std::vector<base::test::FeatureRef> disabled_features;
   std::vector<base::test::FeatureRef> enabled_features;
 
-#if defined(ARCH_CPU_ARM_FAMILY)
-  enabled_features.push_back(media::kPreferLibYuvImageProcessor);
-#endif  // defined(ARCH_CPU_ARM_FAMILY)
-
   media::test::DecoderImplementation implementation =
       media::test::DecoderImplementation::kVD;
   base::CommandLine::SwitchMap switches = cmd_line->GetSwitches();
diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc
index ac2637af..45a50f0f 100644
--- a/media/renderers/video_resource_updater.cc
+++ b/media/renderers/video_resource_updater.cc
@@ -1004,6 +1004,7 @@
       }
       transfer_resource.ycbcr_info = video_frame->ycbcr_info();
 
+#if BUILDFLAG(ENABLE_VULKAN)
       // Ensure that `ycbcr_info` is provided when necessary.
       // TODO(crbug.com/1399429): Avoid duplicating this logic.
       if (IsYuvFormat(transfer_resource.format.resource_format()) &&
@@ -1021,6 +1022,7 @@
             VK_CHROMA_LOCATION_COSITED_EVEN,
             /*format_features=*/0);
       }
+#endif
 
 #if BUILDFLAG(IS_ANDROID)
       transfer_resource.is_backed_by_surface_texture =
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index ad2cce8..d3916dc6 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -193942,6 +193942,87 @@
     { "name": "wrighttownshippa.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
     { "name": "wvbvm.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
     { "name": "wvrtboard.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "applingcounty.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "bethlehemwv.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "bristolctwatersewer.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "chinohills.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "cliomi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "comanchetexas.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "cortemadera.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "dunkirkin.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "eaglefireid.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "eastlandcountytexas.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "enterpriseoregon.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "etowahwaterga.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "fallriverma.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "findnhmoney.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "flatwoodsky.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "fredoniawi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "freeporttx.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "georgetowntexas.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "glendalewv.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "granttwpstclairmi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "greenfieldwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "hayestwpotsegomi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "hewlettharbor.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "hicksvilleohio.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "hilbertwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "hookercountyne.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "howardcounty-mo.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "ingersolltwpmi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "iowaworksforveterans.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "jamestowncando-nc.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "kalkaskavillagemi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "kanecountyhospitalut.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "klackingtownshipmi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "lakepoint.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "manitowocwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "metcalfecountyky.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "micourt.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "mitchellcountync.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "monroecountymo.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "mtjoytwppa.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "mulberryfirear.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "muskegontwpmi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "nebraskaresearch2.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "newalbanyohio.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "northbranfordpdct.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "northmiamibeachfl.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "orfordvillewi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "pascoflcorrections.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "pccdal.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "peoriail.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "pikeky.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "plymouthboroughpa.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "portcanaveral.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "rochestertwpil.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "salinevilleoh.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "sanjuancountywa.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "sdarcc.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "sgcountymt.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "southkingstownri.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "springfieldchartertownship.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "springlakemi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "starcitywv.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "sublettecountywy.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "sussexwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "tauntonpdma.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "tecumsehmi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "theresapolicewi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "townoconomowoc-wi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "townofbayfieldwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "townofcarthagetn.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "townofdane.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "townoflenrootwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "townofmentorwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "townofnewhavendunnwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "townofrichfordwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "vaoig.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "villageofsheldonwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "westhamptonma.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "westmarlboroughpa.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "willardohio.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
+    { "name": "yorkcountyne.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
     // END OF ETLD-OWNER REQUESTED ENTRIES
 
     // To avoid trailing comma changes from showing up in diffs, we place a
diff --git a/sandbox/policy/win/sandbox_win.cc b/sandbox/policy/win/sandbox_win.cc
index 6b37717..c13f677 100644
--- a/sandbox/policy/win/sandbox_win.cc
+++ b/sandbox/policy/win/sandbox_win.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include <map>
 #include <sstream>
 #include <string>
 #include <utility>
@@ -30,6 +31,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
+#include "base/strings/string_util_win.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/system/sys_info.h"
@@ -197,69 +199,52 @@
 }
 #endif  // !defined(NACL_WIN64)
 
-// Compares the loaded |module| file name matches |module_name|.
-bool IsExpandedModuleName(HMODULE module, const wchar_t* module_name) {
-  wchar_t path[MAX_PATH];
-  DWORD sz = ::GetModuleFileNameW(module, path, std::size(path));
-  if ((sz == std::size(path)) || (sz == 0)) {
-    // XP does not set the last error properly, so we bail out anyway.
-    return false;
+// Return a mapping between the long and short names for all loaded modules in
+// the current process. The mapping excludes modules which don't have a typical
+// short name, e.g. EXAMPL~1.DLL.
+std::map<std::wstring, std::wstring> GetShortNameModules() {
+  std::vector<HMODULE> modules;
+  if (!base::win::GetLoadedModulesSnapshot(::GetCurrentProcess(), &modules)) {
+    return {};
   }
-  if (!::GetLongPathName(path, path, std::size(path)))
-    return false;
-  base::FilePath fname(path);
-  return (fname.BaseName().value() == module_name);
+  std::map<std::wstring, std::wstring> names;
+  for (HMODULE module : modules) {
+    wchar_t path[MAX_PATH];
+    DWORD sz = ::GetModuleFileNameW(module, path, std::size(path));
+    if ((sz == std::size(path)) || (sz == 0)) {
+      continue;
+    }
+    base::FilePath module_path(path);
+    base::FilePath name = module_path.BaseName();
+    if (name.RemoveExtension().value().size() > 8 ||
+        name.Extension().size() > 4 ||
+        name.value().find(L"~") == std::wstring::npos) {
+      continue;
+    }
+    base::FilePath fname = base::MakeLongFilePath(module_path);
+    names.insert_or_assign(base::ToLowerASCII(fname.BaseName().value()),
+                           name.value());
+  }
+  return names;
 }
 
-std::vector<std::wstring> GetShortNameVariants(const std::wstring& name) {
-  std::vector<std::wstring> alt_names;
-  size_t period = name.rfind(L'.');
-  DCHECK_NE(std::string::npos, period);
-  DCHECK_LE(3U, (name.size() - period));
-  if (period <= 8)
-    return alt_names;
-
-  // The module could have been loaded with a 8.3 short name. We check
-  // the three most common cases: 'thelongname.dll' becomes
-  // 'thelon~1.dll', 'thelon~2.dll' and 'thelon~3.dll'.
-  alt_names.reserve(3);
-  for (wchar_t ix = '1'; ix <= '3'; ++ix) {
-    const wchar_t suffix[] = {'~', ix, 0};
-    alt_names.push_back(
-        base::StrCat({name.substr(0, 6), suffix, name.substr(period)}));
-  }
-  return alt_names;
-}
-
-// Adds a single dll by |module_name| into the |policy| blocklist.
-// If |check_in_browser| is true we only add an unload policy only if the dll
-// is also loaded in this process.
+// Add a block list DLL to a configuration |config| based on the name of the DLL
+// passed as |module_name|. The DLL must be loaded in the current process. A
+// mapping from long names to short names should also be passed in |modules| to
+// attempt to map a long name to the actual loaded name, this can be initialized
+// with a call to GetShortNameModules.
 void BlocklistAddOneDll(const wchar_t* module_name,
-                        bool check_in_browser,
+                        const std::map<std::wstring, std::wstring>& modules,
                         TargetConfig* config) {
   DCHECK(!config->IsConfigured());
-  if (check_in_browser) {
-    HMODULE module = ::GetModuleHandleW(module_name);
-    if (module) {
-      config->AddDllToUnload(module_name);
-      DVLOG(1) << "dll to unload found: " << module_name;
-    } else {
-      for (const auto& alt_name : GetShortNameVariants(module_name)) {
-        module = ::GetModuleHandleW(alt_name.c_str());
-        // We found it, but because it only has 6 significant letters, we
-        // want to make sure it is the right one.
-        if (module && IsExpandedModuleName(module, module_name)) {
-          // Found a match. We add both forms to the policy.
-          config->AddDllToUnload(alt_name.c_str());
-          config->AddDllToUnload(module_name);
-          return;
-        }
-      }
-    }
-  } else {
+  if (::GetModuleHandleW(module_name) != nullptr) {
     config->AddDllToUnload(module_name);
-    for (const auto& alt_name : GetShortNameVariants(module_name)) {
-      config->AddDllToUnload(alt_name.c_str());
+    DVLOG(1) << "dll to unload found: " << module_name;
+  } else {
+    auto short_name = modules.find(base::ToLowerASCII(module_name));
+    if (short_name != modules.end()) {
+      config->AddDllToUnload(short_name->second.c_str());
+      config->AddDllToUnload(module_name);
     }
   }
 }
@@ -334,11 +319,12 @@
   }
 #endif
 
+  std::map<std::wstring, std::wstring> modules = GetShortNameModules();
   // Adds policy rules for unloading the known dlls that cause Chrome to crash.
   // Eviction of injected DLLs is done by the sandbox so that the injected
   // module does not get a chance to execute any code.
   for (int ix = 0; ix != std::size(kTroublesomeDlls); ++ix)
-    BlocklistAddOneDll(kTroublesomeDlls[ix], true, config);
+    BlocklistAddOneDll(kTroublesomeDlls[ix], modules, config);
 
   return SBOX_ALL_OK;
 }
@@ -1131,9 +1117,9 @@
 }
 
 void BlocklistAddOneDllForTesting(const wchar_t* module_name,
-                                  bool check_in_browser,
                                   TargetConfig* config) {
-  BlocklistAddOneDll(module_name, check_in_browser, config);
+  std::map<std::wstring, std::wstring> modules = GetShortNameModules();
+  BlocklistAddOneDll(module_name, modules, config);
 }
 
 // static
diff --git a/sandbox/policy/win/sandbox_win.h b/sandbox/policy/win/sandbox_win.h
index 41329ac..d8842ebd 100644
--- a/sandbox/policy/win/sandbox_win.h
+++ b/sandbox/policy/win/sandbox_win.h
@@ -121,9 +121,10 @@
       sandbox::mojom::Sandbox sandbox_type);
 };
 
+// Add a block list DLL to a configuration |config| based on the name of the DLL
+// passed as |module_name|. The DLL must be loaded in the current process.
 SANDBOX_POLICY_EXPORT
 void BlocklistAddOneDllForTesting(const wchar_t* module_name,
-                                  bool check_in_browser,
                                   TargetConfig* config);
 
 }  // namespace policy
diff --git a/sandbox/policy/win/sandbox_win_unittest.cc b/sandbox/policy/win/sandbox_win_unittest.cc
index 6104d24..3863f3f4 100644
--- a/sandbox/policy/win/sandbox_win_unittest.cc
+++ b/sandbox/policy/win/sandbox_win_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/notreached.h"
 #include "base/path_service.h"
@@ -179,6 +180,16 @@
   EXPECT_EQ(sid_set, compare_set);
 }
 
+base::FilePath GetShortPathName(const base::FilePath& path) {
+  WCHAR short_path[MAX_PATH];
+  DWORD size = ::GetShortPathName(path.value().c_str(), short_path,
+                                  std::size(short_path));
+  if (size == 0 || size >= MAX_PATH) {
+    return {};
+  }
+  return base::FilePath(short_path);
+}
+
 struct AppContainerProfileTest {
   sandbox::mojom::Sandbox sandbox_type;
   std::wstring package_sid;
@@ -378,13 +389,12 @@
   test.Check(profile.get(), {L"cap1", L"cap2"});
 }
 
-// Disabled due to crbug.com/1210614
-TEST_F(SandboxWinTest, DISABLED_BlocklistAddOneDllCheckInBrowser) {
+TEST_F(SandboxWinTest, BlocklistAddOneDllCheckInBrowser) {
   {  // Block loaded module.
     TestTargetPolicy policy;
     TestTargetConfig* config =
         static_cast<TestTargetConfig*>(policy.GetConfig());
-    BlocklistAddOneDllForTesting(L"kernel32.dll", true, config);
+    BlocklistAddOneDllForTesting(L"kernel32.dll", config);
     EXPECT_EQ(config->blocklisted_dlls(),
               std::vector<std::wstring>({L"kernel32.dll"}));
   }
@@ -393,57 +403,35 @@
     TestTargetPolicy policy;
     TestTargetConfig* config =
         static_cast<TestTargetConfig*>(policy.GetConfig());
-    BlocklistAddOneDllForTesting(L"notloaded.dll", true, config);
+    BlocklistAddOneDllForTesting(L"notloaded.dll", config);
     EXPECT_TRUE(config->blocklisted_dlls().empty());
   }
 
-  {  // Block module loaded by short name.
-#if defined(ARCH_CPU_X86)
-    const std::wstring short_dll_name = L"pe_ima~1.dll";
-    const std::wstring full_dll_name = L"pe_image_test_32.dll";
-#elif defined(ARCH_CPU_X86_64)
-    const std::wstring short_dll_name = L"pe_ima~2.dll";
-    const std::wstring full_dll_name = L"pe_image_test_64.dll";
-#elif defined(ARCH_CPU_ARM64)
-    const std::wstring short_dll_name = L"pe_ima~3.dll";
-    const std::wstring full_dll_name = L"pe_image_test_arm64.dll";
-#endif
+  {
+    base::FilePath executable_path;
+    ASSERT_TRUE(base::PathService::Get(base::FILE_EXE, &executable_path));
+    constexpr wchar_t kFullDllName[] = L"longfilename.dll";
+    base::FilePath dll_path = temp_dir_.GetPath().Append(kFullDllName);
 
-    base::FilePath test_data_dir;
-    base::PathService::Get(base::DIR_TEST_DATA, &test_data_dir);
-    auto dll_path =
-        test_data_dir.AppendASCII("pe_image").Append(short_dll_name);
+    ASSERT_TRUE(base::CopyFile(executable_path, dll_path));
+    base::FilePath short_path = GetShortPathName(dll_path);
+    base::FilePath short_name = short_path.BaseName();
+    if (short_path.empty() ||
+        base::EqualsCaseInsensitiveASCII(short_name.value(), kFullDllName)) {
+      LOG(WARNING) << short_path.value()
+                   << " doesn't have a short path. Ignoring remaining tests.";
+      return;
+    }
 
-    base::ScopedNativeLibrary library(dll_path);
-    EXPECT_TRUE(library.is_valid());
+    base::ScopedNativeLibrary library(short_path);
+    ASSERT_TRUE(library.is_valid());
 
     TestTargetPolicy policy;
     TestTargetConfig* config =
         static_cast<TestTargetConfig*>(policy.GetConfig());
-    BlocklistAddOneDllForTesting(full_dll_name.c_str(), true, config);
+    BlocklistAddOneDllForTesting(kFullDllName, config);
     EXPECT_EQ(config->blocklisted_dlls(),
-              std::vector<std::wstring>({short_dll_name, full_dll_name}));
-  }
-}
-
-TEST_F(SandboxWinTest, BlocklistAddOneDllDontCheckInBrowser) {
-  {  // Block module with short name.
-    TestTargetPolicy policy;
-    TestTargetConfig* config =
-        static_cast<TestTargetConfig*>(policy.GetConfig());
-    BlocklistAddOneDllForTesting(L"short.dll", false, config);
-    EXPECT_EQ(config->blocklisted_dlls(),
-              std::vector<std::wstring>({L"short.dll"}));
-  }
-
-  {  // Block module with long name.
-    TestTargetPolicy policy;
-    TestTargetConfig* config =
-        static_cast<TestTargetConfig*>(policy.GetConfig());
-    BlocklistAddOneDllForTesting(L"thelongname.dll", false, config);
-    EXPECT_EQ(config->blocklisted_dlls(),
-              std::vector<std::wstring>({L"thelongname.dll", L"thelon~1.dll",
-                                         L"thelon~2.dll", L"thelon~3.dll"}));
+              std::vector<std::wstring>({short_name.value(), kFullDllName}));
   }
 }
 
diff --git a/services/viz/public/cpp/compositing/mojom_traits_unittest.cc b/services/viz/public/cpp/compositing/mojom_traits_unittest.cc
index e7fb57b..5f97609 100644
--- a/services/viz/public/cpp/compositing/mojom_traits_unittest.cc
+++ b/services/viz/public/cpp/compositing/mojom_traits_unittest.cc
@@ -227,7 +227,7 @@
 
 TEST_F(StructTraitsTest, LocalSurfaceId) {
   LocalSurfaceId input(
-      42, base::UnguessableToken::Deserialize(0x12345678, 0x9abcdef0));
+      42, base::UnguessableToken::CreateForTesting(0x12345678, 0x9abcdef0));
 
   LocalSurfaceId output;
   mojo::test::SerializeAndDeserialize<mojom::LocalSurfaceId>(input, output);
@@ -243,7 +243,7 @@
       CopyOutputRequest::ResultDestination::kSystemMemory;
   const gfx::Rect area(5, 7, 44, 55);
   const auto source =
-      base::UnguessableToken::Deserialize(0xdeadbeef, 0xdeadf00d);
+      base::UnguessableToken::CreateForTesting(0xdeadbeef, 0xdeadf00d);
   // Requesting 2:3 scale in X dimension, 5:4 in Y dimension.
   const gfx::Vector2d scale_from(2, 5);
   const gfx::Vector2d scale_to(3, 4);
@@ -655,7 +655,7 @@
   const SurfaceId surface_id(
       FrameSinkId(1234, 4321),
       LocalSurfaceId(5678,
-                     base::UnguessableToken::Deserialize(143254, 144132)));
+                     base::UnguessableToken::CreateForTesting(143254, 144132)));
   constexpr float device_scale_factor = 1.234f;
   constexpr gfx::Size size(987, 123);
 
diff --git a/storage/browser/file_system/obfuscated_file_util.cc b/storage/browser/file_system/obfuscated_file_util.cc
index 139120a..84fea73 100644
--- a/storage/browser/file_system/obfuscated_file_util.cc
+++ b/storage/browser/file_system/obfuscated_file_util.cc
@@ -372,7 +372,6 @@
   if (db->GetFileWithPath(url.path(), &file_id)) {
     FileInfo file_info;
     if (!db->GetFileInfo(file_id, &file_info)) {
-      NOTREACHED();
       return base::File::FILE_ERROR_FAILED;
     }
     if (file_info.is_directory())
@@ -419,7 +418,6 @@
     if (exclusive)
       return base::File::FILE_ERROR_EXISTS;
     if (!db->GetFileInfo(file_id, &file_info)) {
-      NOTREACHED();
       return base::File::FILE_ERROR_FAILED;
     }
     if (!file_info.is_directory())
@@ -497,7 +495,6 @@
     return base::File::FILE_ERROR_NOT_FOUND;
   FileInfo file_info;
   if (!db->GetFileInfo(file_id, &file_info) || file_info.is_directory()) {
-    NOTREACHED();
     // Directories have no local file path.
     return base::File::FILE_ERROR_NOT_FOUND;
   }
@@ -523,7 +520,6 @@
 
   FileInfo file_info;
   if (!db->GetFileInfo(file_id, &file_info)) {
-    NOTREACHED();
     return base::File::FILE_ERROR_FAILED;
   }
   if (file_info.is_directory()) {
@@ -842,7 +838,6 @@
   }
   FileInfo file_info;
   if (!db->GetFileInfo(file_id, &file_info)) {
-    NOTREACHED();
     return base::File::FILE_ERROR_FAILED;
   }
   if (!file_info.is_directory())
@@ -900,7 +895,6 @@
     return true;  // Ditto.
   FileInfo file_info;
   if (!db->GetFileInfo(file_id, &file_info)) {
-    DCHECK(!file_id);
     // It's the root directory and the database hasn't been initialized yet.
     return true;
   }
@@ -1214,7 +1208,6 @@
   DCHECK(platform_file_path);
 
   if (!db->GetFileInfo(file_id, local_info)) {
-    NOTREACHED();
     return base::File::FILE_ERROR_FAILED;
   }
 
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index 912c37c..890874a 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -288,6 +288,7 @@
     "//testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter",
     "//testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
     "//testing/buildbot/filters/linux.linux-rel-cft.interactive_ui_tests.filter",
+    "//testing/buildbot/filters/mac.mac11-arm64-rel.interactive_ui_tests.filter",
     "//testing/buildbot/filters/mac.mac-rel-cft.interactive_ui_tests.filter",
     "//testing/buildbot/filters/ozone-linux.interactive_ui_tests_wayland.filter",
     "//testing/buildbot/filters/pixel_tests.filter",
diff --git a/testing/buildbot/filters/fuchsia.browser_tests.filter b/testing/buildbot/filters/fuchsia.browser_tests.filter
index ceb9e62..92ccd2b1 100644
--- a/testing/buildbot/filters/fuchsia.browser_tests.filter
+++ b/testing/buildbot/filters/fuchsia.browser_tests.filter
@@ -4,8 +4,10 @@
 # Expected: blinkRequestResource XMLHttpRequest
 -ActivityLogApiTest.TriggerEvent
 
-# TODO(crbug.com/1326647): Comparison of a couple of very long strings in spanish has an unexpected
-# diff
+# TODO(crbug.com/1326647): Comparison of a couple of very long strings has an unexpected
+# diff. These tests pass when run locally, but fail on bots.
+-AllForms/FormStructureBrowserTest.DataDrivenHeuristics/87
+-AllForms/FormStructureBrowserTest.DataDrivenHeuristics/103
 -AllForms/FormStructureBrowserTest.DataDrivenHeuristics/153
 
 # TODO(crbug.com/1326648):
@@ -27,7 +29,6 @@
 -LoadingPredictorBrowserTestWithProxy.PrepareForPageLoadWithPrediction
 -LoadingPredictorBrowserTestWithProxy.PrepareForPageLoadWithoutPrediction
 -MyIpAddressProxyScriptBrowserTest.Verify
--SCTReportingServiceWithPersistenceBrowserTest.PersistedReportClearedOnClearBrowsingHistory
 
 # TODO(crbug.com/1326652):
 # ../../chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_test_utils.cc:518: Failure
@@ -439,18 +440,6 @@
 -ContentScriptApiTest.ContentScriptExtensionProcess
 -CookieControlsBubbleViewTest.InvokeUi_NotWorkingClicked
 -CookieControlsBubbleViewTest.NotWorkingClicked
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_aria_allowed_attr
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_aria_required_attr
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_audio_caption
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_button_name
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_definition_list
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_document_title
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_marquee
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_meta_viewport_large
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_scope_attr_valid
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_table_fake_caption
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_td_has_header
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_video_description
 -CrSettingsBasicPageTest.BasicPage
 -DesktopCaptureApiTest.ChooseDesktopMedia
 -DesktopCaptureApiTest.Delegation
@@ -531,6 +520,7 @@
 -PrintPreviewDialogControllerBrowserTest.PdfPluginDisabled
 -PrintPreviewDialogControllerBrowserTest.PrintPreviewPdfAccessibility
 -ProxySettingsApiTest.ProxyEventsParseError
+-SCTReportingServiceBrowserTest.PersistedReportClearedOnClearBrowsingHistory
 -ServiceWorkerTest.MimeHandlerView
 -SitePerProcessHitTestBrowserTest.TouchpadPinchOverOOPIF
 -SitePerProcessPrintBrowserTest.*
diff --git a/testing/buildbot/filters/mac.mac11-arm64-rel.browser_tests.filter b/testing/buildbot/filters/mac.mac11-arm64-rel.browser_tests.filter
index 1181e4a..6f8a6fc 100644
--- a/testing/buildbot/filters/mac.mac11-arm64-rel.browser_tests.filter
+++ b/testing/buildbot/filters/mac.mac11-arm64-rel.browser_tests.filter
@@ -15,51 +15,6 @@
 -BackForwardCachePageLoadMetricsObserverBrowserTest.ResponsivenessMetricsNormalizationWithSendingAllLatencies
 -BackForwardCachePageLoadMetricsObserverBrowserTest.ResumesLoggingAfterRestoringFromCacheAfterBackgrounding
 -BackgroundFetchBrowserTest.OfflineItemCollection_VerifyIconReceived
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_marquee
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_meta_viewport_large
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_list
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_heading_order
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_link_name
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_input_image_alt
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_server_side_image_map
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_th_has_data_cells
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_aria_valid_attr
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_td_headers_attr
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_aria_allowed_attr
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_object_alt
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_meta_viewport
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_aria_required_parent
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_document_title
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_frame_title
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_hidden_content
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_valid_lang
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_video_caption
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_radiogroup
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_p_as_heading
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_video_description
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_audio_caption
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_html_has_lang
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_meta_refresh
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_duplicate_id
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_aria_required_children
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_aria_hidden_body
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_listitem
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_blink
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_dlitem
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_empty_heading
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_scope_attr_valid
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_label
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_definition_list
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_html_lang_valid
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_checkboxgroup
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_table_duplicate_name
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_tabindex
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_image_alt
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_bypass
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_layout_table
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_accesskeys
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_aria_required_attr
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_label_title_only
 -ComponentCloudPolicyTest.InstallNewExtension
 -CookieControlsBubbleViewTest.InvokeUi_CookiesBlocked
 -DeclarativeNetRequestApiFencedFrameTest/DeclarativeNetRequestApiFencedFrameTest.Load/0
@@ -83,7 +38,6 @@
 -InlineLoginHelperBrowserTest.UntrustedSigninDialogCancel
 -InspectUIFencedFrameTest.FencedFrameInFrontEnd
 -InspectUITest.LaunchUIDevtools
--LocationIconViewTest.HideOnSecondClick
 -ManagementUITest.ManagementStateChange
 -MediaEngagementBrowserTest.SessionMultipleTabsClosingParent
 -MediaInternalsUIBrowserTest.Integration
diff --git a/testing/buildbot/filters/mac.mac11-arm64-rel.interactive_ui_tests.filter b/testing/buildbot/filters/mac.mac11-arm64-rel.interactive_ui_tests.filter
new file mode 100644
index 0000000..8e87579
--- /dev/null
+++ b/testing/buildbot/filters/mac.mac11-arm64-rel.interactive_ui_tests.filter
@@ -0,0 +1,3 @@
+# Test filter for interactive_ui_tests on mac11-arm64-rel
+
+-LocationIconViewTest.HideOnSecondClick
diff --git a/testing/buildbot/filters/mac.mac12-arm64-rel.browser_tests.filter b/testing/buildbot/filters/mac.mac12-arm64-rel.browser_tests.filter
index 49b75bc..26ab498f 100644
--- a/testing/buildbot/filters/mac.mac12-arm64-rel.browser_tests.filter
+++ b/testing/buildbot/filters/mac.mac12-arm64-rel.browser_tests.filter
@@ -49,35 +49,6 @@
 -BrowserShutdownBrowserTest.TwoBrowsersClosingShutdownHistograms
 -ChromeURLDataManagerWebUITrustedTypesTest.NoTrustedTypesViolation/chrome___net_internals
 -ConditionalFocusBrowserTest.FocusBeforeCapture
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_marquee
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_meta_viewport_large
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_list
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_heading_order
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_link_name
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_input_image_alt
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_server_side_image_map
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_th_has_data_cells
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_aria_valid_attr
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_td_headers_attr
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_aria_allowed_attr
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_object_alt
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_meta_viewport
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_aria_required_parent
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_document_title
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_frame_title
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_hidden_content
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_valid_lang
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_video_caption
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_radiogroup
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_p_as_heading
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_video_description
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_audio_caption
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_html_has_lang
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_meta_refresh
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_duplicate_id
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_aria_required_children
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_aria_hidden_body
--CrExtensionsA11yTestWithMultipleExensions.WithExtensions_listitem
 -CrExtensionsManagerUnitTest.UpdateItemData
 -CrExtensionsManagerUnitTestWithActivityLogFlag.UpdateFromActivityLog
 -CrExtensionsSidebarTest.LayoutAndClickHandlers
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 39a6ec4..f0c0c92 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -434,6 +434,11 @@
           '--debug',
         ],
       },
+      'linux-blink-rel': {
+        'swarming': {
+          'hard_timeout': 2400,
+        },
+      },
       'linux-blink-web-tests-force-accessibility-rel': {
         'args': [
           '--flag-specific=force-renderer-accessibility',
@@ -739,6 +744,11 @@
           '--debug',
         ],
       },
+      'linux-blink-rel': {
+        'swarming': {
+          'hard_timeout': 2400,
+        },
+      },
       'linux-blink-web-tests-force-accessibility-rel': {
         'args': [
           '--flag-specific=force-renderer-accessibility',
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index d4ccf30..76ca8cdb 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -1498,78 +1498,6 @@
       'services_unittests': {},
     },
 
-    'chromium_web_tests_and_wpt_webdriver_isolated_scripts': {
-      'blink_web_tests': {
-        # layout test failures are retried 3 times when '--test-list' is not
-        # passed, but 0 times when '--test-list' is passed. We want to always
-        # retry 3 times, so we explicitly specify it.
-        'args': [
-          '--num-retries=3',
-        ],
-        'isolate_name': 'blink_web_tests',
-        'merge': {
-          'args': [
-            '--verbose',
-          ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
-        'mixins': [
-          'blink_tests_write_run_histories',
-           # TODO(crbug.com/1327314): Enable for blink web tests.
-          'disable_check_flakiness_web_tests',
-          'skia_gold_test',
-        ],
-        'resultdb': {
-          'enable': True,
-        },
-        'results_handler': 'layout tests',
-        'swarming': {
-          'shards': 5,
-        },
-      },
-      'blink_wpt_tests': {
-        # layout test failures are retried 3 times when '--test-list' is not
-        # passed, but 0 times when '--test-list' is passed. We want to always
-        # retry 3 times, so we explicitly specify it.
-        'args': [
-          '--num-retries=3',
-          '--step-name=blink-wpt-tests',
-        ],
-        'isolate_name': 'blink_wpt_tests',
-        'merge': {
-          'args': [
-            '--verbose',
-          ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
-        'mixins': [
-          'blink_tests_write_run_histories',
-          # TODO(crbug.com/1327314): Enable for blink web tests.
-          'disable_check_flakiness_web_tests',
-          'skia_gold_test',
-        ],
-        'resultdb': {
-          'enable': True,
-        },
-        'results_handler': 'layout tests',
-        'swarming': {
-          'shards': 7,
-        },
-      },
-      'webdriver_tests_suite': {
-        'isolate_name': 'webdriver_wpt_tests',
-         'merge': {
-          'args': [
-            '--verbose',
-          ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
-        'swarming': {
-          'shards': 4,
-        },
-      },
-    },
-
     'chromium_web_tests_high_dpi_isolated_scripts': {
       'high_dpi_blink_web_tests': {
         # high_dpi_blink_web_tests provides coverage for
@@ -5817,6 +5745,13 @@
       'vr_platform_specific_chromium_gtests',
     ],
 
+    'chromium_linux_blink_rel_isolated_scripts': [
+      'chromium_webkit_isolated_scripts',
+      'linux_specific_chromium_isolated_scripts',
+      'vulkan_swiftshader_isolated_scripts',
+      'chromium_web_tests_high_dpi_isolated_scripts',
+    ],
+
     'chromium_linux_cast_audio_gtests': [
       'cast_audio_specific_chromium_gtests',
       'chromium_gtests',
diff --git a/testing/buildbot/tryserver.blink.json b/testing/buildbot/tryserver.blink.json
index 92dd17f3..c50edb6 100644
--- a/testing/buildbot/tryserver.blink.json
+++ b/testing/buildbot/tryserver.blink.json
@@ -34,6 +34,7 @@
               "os": "Ubuntu-18.04"
             }
           ],
+          "hard_timeout": 2400,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
           "shards": 5
         },
@@ -42,7 +43,6 @@
       {
         "args": [
           "--num-retries=3",
-          "--step-name=blink-wpt-tests",
           "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json",
           "--git-revision=${got_revision}"
         ],
@@ -71,12 +71,199 @@
               "os": "Ubuntu-18.04"
             }
           ],
+          "hard_timeout": 2400,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
           "shards": 7
         },
         "test_id_prefix": "ninja://:blink_wpt_tests/"
       },
       {
+        "args": [
+          "--flag-specific=highdpi",
+          "--skipped=always",
+          "--num-retries=3",
+          "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json",
+          "--git-revision=${got_revision}"
+        ],
+        "check_flakiness_for_new_tests": false,
+        "isolate_name": "blink_web_tests",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "high_dpi_blink_web_tests",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://:blink_web_tests/"
+      },
+      {
+        "args": [
+          "--flag-specific=highdpi",
+          "--skipped=always",
+          "--num-retries=3",
+          "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json",
+          "--git-revision=${got_revision}"
+        ],
+        "check_flakiness_for_new_tests": false,
+        "isolate_name": "blink_wpt_tests",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "high_dpi_blink_wpt_tests",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 3
+        },
+        "test_id_prefix": "ninja://:blink_wpt_tests/"
+      },
+      {
+        "args": [
+          "--flag-specific=disable-site-isolation-trials",
+          "--num-retries=3",
+          "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json",
+          "--git-revision=${got_revision}"
+        ],
+        "check_flakiness_for_new_tests": false,
+        "isolate_name": "blink_web_tests",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "not_site_per_process_blink_web_tests",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 8
+        },
+        "test_id_prefix": "ninja://:blink_web_tests/"
+      },
+      {
+        "args": [
+          "--flag-specific=disable-site-isolation-trials",
+          "--num-retries=3",
+          "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json",
+          "--git-revision=${got_revision}"
+        ],
+        "check_flakiness_for_new_tests": false,
+        "isolate_name": "blink_wpt_tests",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "not_site_per_process_blink_wpt_tests",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 10
+        },
+        "test_id_prefix": "ninja://:blink_wpt_tests/"
+      },
+      {
+        "args": [
+          "--num-retries=3",
+          "--skipped=always",
+          "--flag-specific=skia-vulkan-swiftshader",
+          "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json",
+          "--git-revision=${got_revision}"
+        ],
+        "check_flakiness_for_new_tests": false,
+        "isolate_name": "blink_web_tests",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "vulkan_swiftshader_blink_web_tests",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://:blink_web_tests/"
+      },
+      {
         "isolate_name": "webdriver_wpt_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/tryserver.v8.json b/testing/buildbot/tryserver.v8.json
index ca73b391..c6eceb0 100644
--- a/testing/buildbot/tryserver.v8.json
+++ b/testing/buildbot/tryserver.v8.json
@@ -42,7 +42,6 @@
       {
         "args": [
           "--num-retries=3",
-          "--step-name=blink-wpt-tests",
           "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json",
           "--git-revision=${got_revision}"
         ],
@@ -77,6 +76,192 @@
         "test_id_prefix": "ninja://:blink_wpt_tests/"
       },
       {
+        "args": [
+          "--flag-specific=highdpi",
+          "--skipped=always",
+          "--num-retries=3",
+          "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json",
+          "--git-revision=${got_revision}"
+        ],
+        "check_flakiness_for_new_tests": false,
+        "isolate_name": "blink_web_tests",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "high_dpi_blink_web_tests",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://:blink_web_tests/"
+      },
+      {
+        "args": [
+          "--flag-specific=highdpi",
+          "--skipped=always",
+          "--num-retries=3",
+          "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json",
+          "--git-revision=${got_revision}"
+        ],
+        "check_flakiness_for_new_tests": false,
+        "isolate_name": "blink_wpt_tests",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "high_dpi_blink_wpt_tests",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 3
+        },
+        "test_id_prefix": "ninja://:blink_wpt_tests/"
+      },
+      {
+        "args": [
+          "--flag-specific=disable-site-isolation-trials",
+          "--num-retries=3",
+          "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json",
+          "--git-revision=${got_revision}"
+        ],
+        "check_flakiness_for_new_tests": false,
+        "isolate_name": "blink_web_tests",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "not_site_per_process_blink_web_tests",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 8
+        },
+        "test_id_prefix": "ninja://:blink_web_tests/"
+      },
+      {
+        "args": [
+          "--flag-specific=disable-site-isolation-trials",
+          "--num-retries=3",
+          "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json",
+          "--git-revision=${got_revision}"
+        ],
+        "check_flakiness_for_new_tests": false,
+        "isolate_name": "blink_wpt_tests",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "not_site_per_process_blink_wpt_tests",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 10
+        },
+        "test_id_prefix": "ninja://:blink_wpt_tests/"
+      },
+      {
+        "args": [
+          "--num-retries=3",
+          "--skipped=always",
+          "--flag-specific=skia-vulkan-swiftshader",
+          "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json",
+          "--git-revision=${got_revision}"
+        ],
+        "check_flakiness_for_new_tests": false,
+        "isolate_name": "blink_web_tests",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "vulkan_swiftshader_blink_web_tests",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://:blink_web_tests/"
+      },
+      {
         "isolate_name": "webdriver_wpt_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 67658c1..dfe9d35 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -6628,7 +6628,7 @@
           'linux-bionic',
         ],
         'test_suites': {
-          'isolated_scripts': 'chromium_web_tests_and_wpt_webdriver_isolated_scripts',
+          'isolated_scripts': 'chromium_linux_blink_rel_isolated_scripts',
         },
       },
       'mac10.13-blink-rel': {
@@ -6879,7 +6879,7 @@
           'linux-bionic',
         ],
         'test_suites': {
-          'isolated_scripts': 'chromium_web_tests_and_wpt_webdriver_isolated_scripts',
+          'isolated_scripts': 'chromium_linux_blink_rel_isolated_scripts',
         },
       },
     },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index d5be7cca..51b41e70 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -473,6 +473,21 @@
             ]
         }
     ],
+    "AppKMDecouplingCoverage": [
+        {
+            "platforms": [
+                "chromeos"
+            ],
+            "experiments": [
+                {
+                    "name": "AppKMDecoupling",
+                    "enable_features": [
+                        "AppMetricsOnlyRelyOnAppSync"
+                    ]
+                }
+            ]
+        }
+    ],
     "AppListLaunchRecorder": [
         {
             "platforms": [
@@ -7834,6 +7849,26 @@
             ]
         }
     ],
+    "OptimizationGuideInstallWideModelStore": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "chromeos_lacros",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "OptimizationGuideInstallWideModelStore"
+                    ]
+                }
+            ]
+        }
+    ],
     "OptimizeNetworkBuffers": [
         {
             "platforms": [
diff --git a/third_party/android_build_tools/aapt2/README.chromium b/third_party/android_build_tools/aapt2/README.chromium
index c845cc6..99295a1 100644
--- a/third_party/android_build_tools/aapt2/README.chromium
+++ b/third_party/android_build_tools/aapt2/README.chromium
@@ -12,21 +12,14 @@
 distributed here as a CIPD package instead.
 
 What version is this:
-  * aapt2 is now autorolled ~once a week.
-  * To lookup the latest version being used currently:
-    * Look up the cipd instance id from //DEPS, or run
-      `gclient getdep -r src/third_party/android_build_tools/aapt2:chromium/third_party/android_build_tools/aapt2`.
-    * Find the version tag at this url
-      https://chrome-infra-packages.appspot.com/p/chromium/third_party/android_build_tools/aapt2/+/<instance id>
-    * Or, run `cipd describe chromium/third_party/android_build_tools/aapt2 -version <instance id>` and look at the version tag.
-    * The version string appears after the @ symbol in the tag.
+  * Run print_version.sh to find out the version.
   * New instances are uploaded by the packager bot:
     https://ci.chromium.org/p/chromium/builders/ci/3pp-linux-amd64-packager
-  * The bot autoruns every 6 hours. Ping a trooper or a clank build core dev to
+  * The bot autoruns every 6 hours. Ping a trooper or a clank-build-core@ dev to
     trigger it if you need it sooner:
     https://luci-scheduler.appspot.com/jobs/chromium/3pp-linux-amd64-packager
-  * The autoroller runs automatically when a new cipd instance is uploaded, see
-    its status here: https://autoroll.skia.org/r/aapt2-chromium
+  * New versions are rolled automatically by:
+    https://autoroll.skia.org/r/aapt2-chromium
 
 Local Modifications:
 None
diff --git a/third_party/android_build_tools/aapt2/print_version.sh b/third_party/android_build_tools/aapt2/print_version.sh
new file mode 100755
index 0000000..f003044d
--- /dev/null
+++ b/third_party/android_build_tools/aapt2/print_version.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# 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.
+
+set -e
+DIR_SRC_ROOT=$(pwd)/
+DIR_SRC_ROOT=${DIR_SRC_ROOT%/src/*}/src
+SUBDIR=$(cd $(dirname $0); pwd)
+SUBDIR="${SUBDIR#$DIR_SRC_ROOT/}"
+CIPD_PACKAGE=chromium/$SUBDIR
+
+exec $DIR_SRC_ROOT/build/android/print_cipd_version.py \
+    --subdir "$SUBDIR" \
+    --cipd-package "$CIPD_PACKAGE" \
+    "$@"
diff --git a/third_party/android_build_tools/apkanalyzer/print_version.sh b/third_party/android_build_tools/apkanalyzer/print_version.sh
new file mode 100755
index 0000000..f003044d
--- /dev/null
+++ b/third_party/android_build_tools/apkanalyzer/print_version.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# 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.
+
+set -e
+DIR_SRC_ROOT=$(pwd)/
+DIR_SRC_ROOT=${DIR_SRC_ROOT%/src/*}/src
+SUBDIR=$(cd $(dirname $0); pwd)
+SUBDIR="${SUBDIR#$DIR_SRC_ROOT/}"
+CIPD_PACKAGE=chromium/$SUBDIR
+
+exec $DIR_SRC_ROOT/build/android/print_cipd_version.py \
+    --subdir "$SUBDIR" \
+    --cipd-package "$CIPD_PACKAGE" \
+    "$@"
diff --git a/third_party/android_build_tools/bundletool/README.chromium b/third_party/android_build_tools/bundletool/README.chromium
index 9d8bb7f1..96fac53 100644
--- a/third_party/android_build_tools/bundletool/README.chromium
+++ b/third_party/android_build_tools/bundletool/README.chromium
@@ -13,18 +13,11 @@
 None
 
 What version is this:
-  * bundletool is now autorolled.
-  * To lookup the latest version being used currently:
-    * Look up the cipd instance id from //DEPS, or run
-      `gclient getdep -r src/third_party/android_build_tools/bundletool:chromium/third_party/android_build_tools/bundletool`.
-    * Find the version tag at this url
-      https://chrome-infra-packages.appspot.com/p/chromium/third_party/android_build_tools/bundletool/+/<instance id>
-    * Or, run `cipd describe chromium/third_party/android_build_tools/bundletool -version <instance id>` and look at the version tag.
-    * The version string appears after the @ symbol in the tag.
+  * Run print_version.sh to find out the version.
   * New instances are uploaded by the packager bot:
     https://ci.chromium.org/p/chromium/builders/ci/3pp-linux-amd64-packager
-  * The bot autoruns every 6 hours. Ping a trooper or a clank build core dev to
+  * The bot autoruns every 6 hours. Ping a trooper or a clank-build-core@ dev to
     trigger it if you need it sooner:
     https://luci-scheduler.appspot.com/jobs/chromium/3pp-linux-amd64-packager
-  * The autoroller runs automatically when a new cipd instance is uploaded, see
-    its status here: https://autoroll.skia.org/r/bundletool-chromium
+  * New versions are rolled automatically by:
+    https://autoroll.skia.org/r/bundletool-chromium
diff --git a/third_party/android_build_tools/bundletool/print_version.sh b/third_party/android_build_tools/bundletool/print_version.sh
new file mode 100755
index 0000000..f003044d
--- /dev/null
+++ b/third_party/android_build_tools/bundletool/print_version.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# 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.
+
+set -e
+DIR_SRC_ROOT=$(pwd)/
+DIR_SRC_ROOT=${DIR_SRC_ROOT%/src/*}/src
+SUBDIR=$(cd $(dirname $0); pwd)
+SUBDIR="${SUBDIR#$DIR_SRC_ROOT/}"
+CIPD_PACKAGE=chromium/$SUBDIR
+
+exec $DIR_SRC_ROOT/build/android/print_cipd_version.py \
+    --subdir "$SUBDIR" \
+    --cipd-package "$CIPD_PACKAGE" \
+    "$@"
diff --git a/third_party/android_build_tools/lint/README.chromium b/third_party/android_build_tools/lint/README.chromium
index 49c32c9..f9d393e 100644
--- a/third_party/android_build_tools/lint/README.chromium
+++ b/third_party/android_build_tools/lint/README.chromium
@@ -17,9 +17,11 @@
    third_party/android_build_tools/lint/custom_lint.jar
 
 What version is this:
+  * Run print_version.sh to find out the version.
   * New instances are uploaded by the packager bot:
     https://ci.chromium.org/p/chromium/builders/ci/3pp-linux-amd64-packager
   * The bot autoruns every 6 hours. Ping a trooper or a clank-build-core@ dev to
     trigger it if you need it sooner:
     https://luci-scheduler.appspot.com/jobs/chromium/3pp-linux-amd64-packager
-  * Switching to a newer verison requires manually updating //DEPS.
+  * New versions are rolled automatically by:
+    https://autoroll.skia.org/r/lint-chromium
diff --git a/third_party/android_build_tools/lint/print_version.sh b/third_party/android_build_tools/lint/print_version.sh
new file mode 100755
index 0000000..f003044d
--- /dev/null
+++ b/third_party/android_build_tools/lint/print_version.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# 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.
+
+set -e
+DIR_SRC_ROOT=$(pwd)/
+DIR_SRC_ROOT=${DIR_SRC_ROOT%/src/*}/src
+SUBDIR=$(cd $(dirname $0); pwd)
+SUBDIR="${SUBDIR#$DIR_SRC_ROOT/}"
+CIPD_PACKAGE=chromium/$SUBDIR
+
+exec $DIR_SRC_ROOT/build/android/print_cipd_version.py \
+    --subdir "$SUBDIR" \
+    --cipd-package "$CIPD_PACKAGE" \
+    "$@"
diff --git a/third_party/android_build_tools/manifest_merger/README.chromium b/third_party/android_build_tools/manifest_merger/README.chromium
index 140058b..db7f817b 100644
--- a/third_party/android_build_tools/manifest_merger/README.chromium
+++ b/third_party/android_build_tools/manifest_merger/README.chromium
@@ -13,8 +13,11 @@
 None
 
 What version is this:
+  * Run print_version.sh to find out the version.
   * New instances are uploaded by the packager bot:
     https://ci.chromium.org/p/chromium/builders/ci/3pp-linux-amd64-packager
   * The bot autoruns every 6 hours. Ping a trooper or a clank-build-core@ dev to
     trigger it if you need it sooner:
     https://luci-scheduler.appspot.com/jobs/chromium/3pp-linux-amd64-packager
+  * New versions are rolled automatically by:
+    https://autoroll.skia.org/r/manifest-merger-chromium
diff --git a/third_party/android_build_tools/manifest_merger/print_version.sh b/third_party/android_build_tools/manifest_merger/print_version.sh
new file mode 100755
index 0000000..f003044d
--- /dev/null
+++ b/third_party/android_build_tools/manifest_merger/print_version.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# 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.
+
+set -e
+DIR_SRC_ROOT=$(pwd)/
+DIR_SRC_ROOT=${DIR_SRC_ROOT%/src/*}/src
+SUBDIR=$(cd $(dirname $0); pwd)
+SUBDIR="${SUBDIR#$DIR_SRC_ROOT/}"
+CIPD_PACKAGE=chromium/$SUBDIR
+
+exec $DIR_SRC_ROOT/build/android/print_cipd_version.py \
+    --subdir "$SUBDIR" \
+    --cipd-package "$CIPD_PACKAGE" \
+    "$@"
diff --git a/third_party/blink/common/storage_key/storage_key.cc b/third_party/blink/common/storage_key/storage_key.cc
index e539300..2fb946e5 100644
--- a/third_party/blink/common/storage_key/storage_key.cc
+++ b/third_party/blink/common/storage_key/storage_key.cc
@@ -191,7 +191,10 @@
       if (key_origin.opaque() || !nonce || nonce->is_empty())
         return absl::nullopt;
 
-      return StorageKey::CreateWithNonce(key_origin, *nonce);
+      // This constructor makes a copy of the nonce, so getting the raw pointer
+      // is safe.
+      return StorageKey(key_origin, net::SchemefulSite(key_origin), nonce.get(),
+                        blink::mojom::AncestorChainBit::kSameSite);
     }
     default: {
       // Malformed input case. We saw a separator that we don't understand
@@ -210,11 +213,7 @@
 // static
 StorageKey StorageKey::CreateForTesting(const url::Origin& origin,
                                         const url::Origin& top_level_origin) {
-  auto top_level_site = net::SchemefulSite(top_level_origin);
-  return StorageKey(origin, std::move(top_level_site), nullptr,
-                    top_level_site == net::SchemefulSite(origin)
-                        ? blink::mojom::AncestorChainBit::kSameSite
-                        : blink::mojom::AncestorChainBit::kCrossSite);
+  return CreateForTesting(origin, net::SchemefulSite(top_level_origin));
 }
 
 // static
@@ -234,8 +233,9 @@
 }
 
 // static
-StorageKey StorageKey::CreateWithNonce(const url::Origin& origin,
-                                       const base::UnguessableToken& nonce) {
+StorageKey StorageKey::CreateWithNonceForTesting(
+    const url::Origin& origin,
+    const base::UnguessableToken& nonce) {
   DCHECK(!nonce.is_empty());
   // The AncestorChainBit is not applicable to StorageKeys with a non-empty
   // nonce, so they are initialized to be kSameSite.
diff --git a/third_party/blink/common/storage_key/storage_key_mojom_traits_unittest.cc b/third_party/blink/common/storage_key/storage_key_mojom_traits_unittest.cc
index 89c7005..486da98 100644
--- a/third_party/blink/common/storage_key/storage_key_mojom_traits_unittest.cc
+++ b/third_party/blink/common/storage_key/storage_key_mojom_traits_unittest.cc
@@ -49,11 +49,11 @@
             url::Origin::Create(GURL("http://sub2.example.com")),
             url::Origin::Create(GURL("https://example.com"))),
         StorageKey(url::Origin()),
-        StorageKey::CreateWithNonce(
+        StorageKey::CreateWithNonceForTesting(
             url::Origin::Create(GURL("https://.example.com")),
             base::UnguessableToken::Create()),
-        StorageKey::CreateWithNonce(url::Origin(),
-                                    base::UnguessableToken::Create()),
+        StorageKey::CreateWithNonceForTesting(url::Origin(),
+                                              base::UnguessableToken::Create()),
         StorageKey::CreateWithOptionalNonce(
             url::Origin::Create(GURL("http://sub2.example.com")),
             net::SchemefulSite(
diff --git a/third_party/blink/common/storage_key/storage_key_unittest.cc b/third_party/blink/common/storage_key/storage_key_unittest.cc
index d27f783..be35d11 100644
--- a/third_party/blink/common/storage_key/storage_key_unittest.cc
+++ b/third_party/blink/common/storage_key/storage_key_unittest.cc
@@ -76,23 +76,23 @@
       {StorageKey(origin3), StorageKey(origin3), true},
       {StorageKey(origin4), StorageKey(origin4), true},
       // StorageKeys made from the same origin and nonce are equivalent.
-      {StorageKey::CreateWithNonce(origin1, nonce1),
-       StorageKey::CreateWithNonce(origin1, nonce1), true},
-      {StorageKey::CreateWithNonce(origin1, nonce2),
-       StorageKey::CreateWithNonce(origin1, nonce2), true},
-      {StorageKey::CreateWithNonce(origin2, nonce1),
-       StorageKey::CreateWithNonce(origin2, nonce1), true},
+      {StorageKey::CreateWithNonceForTesting(origin1, nonce1),
+       StorageKey::CreateWithNonceForTesting(origin1, nonce1), true},
+      {StorageKey::CreateWithNonceForTesting(origin1, nonce2),
+       StorageKey::CreateWithNonceForTesting(origin1, nonce2), true},
+      {StorageKey::CreateWithNonceForTesting(origin2, nonce1),
+       StorageKey::CreateWithNonceForTesting(origin2, nonce1), true},
       // StorageKeys made from different origins are not equivalent.
       {StorageKey(origin1), StorageKey(origin2), false},
       {StorageKey(origin3), StorageKey(origin4), false},
-      {StorageKey::CreateWithNonce(origin1, nonce1),
-       StorageKey::CreateWithNonce(origin2, nonce1), false},
+      {StorageKey::CreateWithNonceForTesting(origin1, nonce1),
+       StorageKey::CreateWithNonceForTesting(origin2, nonce1), false},
       // StorageKeys made from different nonces are not equivalent.
-      {StorageKey::CreateWithNonce(origin1, nonce1),
-       StorageKey::CreateWithNonce(origin1, nonce2), false},
+      {StorageKey::CreateWithNonceForTesting(origin1, nonce1),
+       StorageKey::CreateWithNonceForTesting(origin1, nonce2), false},
       // StorageKeys made from different origins and nonce are not equivalent.
-      {StorageKey::CreateWithNonce(origin1, nonce1),
-       StorageKey::CreateWithNonce(origin2, nonce2), false},
+      {StorageKey::CreateWithNonceForTesting(origin1, nonce1),
+       StorageKey::CreateWithNonceForTesting(origin2, nonce2), false},
       // When storage partitioning is disabled, the top-level site isn't taken
       // into account for equivalence.
       {StorageKey::CreateForTesting(origin1, origin2), StorageKey(origin1),
@@ -252,16 +252,16 @@
     const char* expected_serialization;
   } kTestCases[] = {
       {{"https://example.com/",
-        base::UnguessableToken::Deserialize(12345ULL, 67890ULL)},
+        base::UnguessableToken::CreateForTesting(12345ULL, 67890ULL)},
        "https://example.com/^112345^267890"},
       {{"https://test.example",
-        base::UnguessableToken::Deserialize(22222ULL, 99999ULL)},
+        base::UnguessableToken::CreateForTesting(22222ULL, 99999ULL)},
        "https://test.example/^122222^299999"},
       {{"https://sub.test.example/",
-        base::UnguessableToken::Deserialize(9876ULL, 54321ULL)},
+        base::UnguessableToken::CreateForTesting(9876ULL, 54321ULL)},
        "https://sub.test.example/^19876^254321"},
       {{"https://other.example/",
-        base::UnguessableToken::Deserialize(3735928559ULL, 110521ULL)},
+        base::UnguessableToken::CreateForTesting(3735928559ULL, 110521ULL)},
        "https://other.example/^13735928559^2110521"},
   };
 
@@ -270,7 +270,7 @@
     const url::Origin origin =
         url::Origin::Create(GURL(test.origin_and_nonce.first));
     const base::UnguessableToken& nonce = test.origin_and_nonce.second;
-    StorageKey key = StorageKey::CreateWithNonce(origin, nonce);
+    StorageKey key = StorageKey::CreateWithNonceForTesting(origin, nonce);
     EXPECT_EQ(test.expected_serialization, key.Serialize());
   }
 }
@@ -444,13 +444,13 @@
     const base::UnguessableToken nonce;
   } kTestCases[] = {
       {"https://example.com/",
-       base::UnguessableToken::Deserialize(12345ULL, 67890ULL)},
+       base::UnguessableToken::CreateForTesting(12345ULL, 67890ULL)},
       {"https://test.example",
-       base::UnguessableToken::Deserialize(22222ULL, 99999ULL)},
+       base::UnguessableToken::CreateForTesting(22222ULL, 99999ULL)},
       {"https://sub.test.example/",
-       base::UnguessableToken::Deserialize(9876ULL, 54321ULL)},
+       base::UnguessableToken::CreateForTesting(9876ULL, 54321ULL)},
       {"https://other.example/",
-       base::UnguessableToken::Deserialize(3735928559ULL, 110521ULL)},
+       base::UnguessableToken::CreateForTesting(3735928559ULL, 110521ULL)},
       {"https://other2.example/", base::UnguessableToken::Create()},
   };
 
@@ -459,7 +459,7 @@
     url::Origin origin = url::Origin::Create(GURL(test.origin));
     const base::UnguessableToken& nonce = test.nonce;
 
-    StorageKey key = StorageKey::CreateWithNonce(origin, nonce);
+    StorageKey key = StorageKey::CreateWithNonceForTesting(origin, nonce);
     std::string key_string = key.Serialize();
     std::string key_string_for_local_storage = key.SerializeForLocalStorage();
     absl::optional<StorageKey> key_deserialized =
@@ -587,7 +587,7 @@
                     {kOrigin, kOrigin, true, true}};
   for (const auto& test_case : test_cases) {
     if (test_case.has_nonce) {
-      StorageKey key = StorageKey::CreateWithNonce(
+      StorageKey key = StorageKey::CreateWithNonceForTesting(
           test_case.origin, base::UnguessableToken::Create());
       EXPECT_EQ(test_case.expected, key.IsThirdPartyContext());
       EXPECT_NE(key.IsThirdPartyContext(), key.IsFirstPartyContext());
@@ -642,8 +642,8 @@
   for (const auto& test_case : test_cases) {
     net::SchemefulSite got_site;
     if (test_case.has_nonce) {
-      got_site = StorageKey::CreateWithNonce(test_case.origin,
-                                             base::UnguessableToken::Create())
+      got_site = StorageKey::CreateWithNonceForTesting(
+                     test_case.origin, base::UnguessableToken::Create())
                      .ToNetSiteForCookies()
                      .site();
     } else {
@@ -720,7 +720,7 @@
              url::Origin::Create(GURL("https://www.foo.com")),
              url::Origin::Create(GURL("https://www.bar.com"))),
          absl::nullopt},
-        {StorageKey::CreateWithNonce(
+        {StorageKey::CreateWithNonceForTesting(
              url::Origin::Create(GURL("https://www.example.com")), nonce),
          absl::nullopt},
     };
@@ -741,7 +741,7 @@
     TestCase test_cases[] = {
         {StorageKey(url::Origin::Create(GURL("https://www.example.com"))),
          absl::nullopt},
-        {StorageKey::CreateWithNonce(
+        {StorageKey::CreateWithNonceForTesting(
              url::Origin::Create(GURL("https://www.example.com")), nonce),
          net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"),
                                                     nonce)},
@@ -768,7 +768,7 @@
              url::Origin::Create(GURL("https://www.bar.com"))),
          net::CookiePartitionKey::FromURLForTesting(
              GURL("https://subdomain.bar.com"))},
-        {StorageKey::CreateWithNonce(
+        {StorageKey::CreateWithNonceForTesting(
              url::Origin::Create(GURL("https://www.example.com")), nonce),
          net::CookiePartitionKey::FromURLForTesting(
              GURL("https://www.example.com"), nonce)},
diff --git a/third_party/blink/public/common/storage_key/storage_key.h b/third_party/blink/public/common/storage_key/storage_key.h
index 6693703..c1e647c 100644
--- a/third_party/blink/public/common/storage_key/storage_key.h
+++ b/third_party/blink/public/common/storage_key/storage_key.h
@@ -70,8 +70,9 @@
   // unique anyway. Implementation wise however, the top-level site is set to
   // the `origin`'s site. The AncestorChainBit is not applicable to StorageKeys
   // with a non-empty nonce so they are initialized to kSameSite.
-  static StorageKey CreateWithNonce(const url::Origin& origin,
-                                    const base::UnguessableToken& nonce);
+  static StorageKey CreateWithNonceForTesting(
+      const url::Origin& origin,
+      const base::UnguessableToken& nonce);
 
   // Callers may specify an optional nonce by passing nullptr.
   static StorageKey CreateWithOptionalNonce(
diff --git a/third_party/blink/public/common/storage_key/storage_key_proto_converter.cc b/third_party/blink/public/common/storage_key/storage_key_proto_converter.cc
index 8cab4ee..8c8ae173 100644
--- a/third_party/blink/public/common/storage_key/storage_key_proto_converter.cc
+++ b/third_party/blink/public/common/storage_key/storage_key_proto_converter.cc
@@ -70,8 +70,10 @@
     return blink::StorageKey(origin);
 
   if (storage_key_type == StorageKeyType::kUnguessableToken) {
-    return blink::StorageKey::CreateWithNonce(origin,
-                                              base::UnguessableToken::Create());
+    auto nonce = base::UnguessableToken::Create();
+    return blink::StorageKey::CreateWithOptionalNonce(
+        origin, net::SchemefulSite(origin), &nonce,
+        blink::mojom::AncestorChainBit::kSameSite);
   }
 
   if (storage_key_type == StorageKey::OneOfCase::kTopLevelSite) {
diff --git a/third_party/blink/renderer/core/aom/accessible_node.cc b/third_party/blink/renderer/core/aom/accessible_node.cc
index 7220068b..d0b72aa 100644
--- a/third_party/blink/renderer/core/aom/accessible_node.cc
+++ b/third_party/blink/renderer/core/aom/accessible_node.cc
@@ -36,7 +36,7 @@
       return html_names::kAriaCurrentAttr;
     case AOMStringProperty::kDescription:
       return html_names::kAriaDescriptionAttr;
-    case AOMStringProperty::kHasPopUp:
+    case AOMStringProperty::kHasPopup:
       return html_names::kAriaHaspopupAttr;
     case AOMStringProperty::kInvalid:
       return html_names::kAriaInvalidAttr;
@@ -663,12 +663,12 @@
   NotifyAttributeChanged(html_names::kAriaFlowtoAttr);
 }
 
-AtomicString AccessibleNode::hasPopUp() const {
-  return GetProperty(AOMStringProperty::kHasPopUp);
+AtomicString AccessibleNode::hasPopup() const {
+  return GetProperty(AOMStringProperty::kHasPopup);
 }
 
-void AccessibleNode::setHasPopUp(const AtomicString& has_popup) {
-  SetStringProperty(AOMStringProperty::kHasPopUp, has_popup);
+void AccessibleNode::setHasPopup(const AtomicString& has_popup) {
+  SetStringProperty(AOMStringProperty::kHasPopup, has_popup);
   NotifyAttributeChanged(html_names::kAriaHaspopupAttr);
 }
 
@@ -1052,7 +1052,7 @@
     case AOMStringProperty::kAutocomplete:
     case AOMStringProperty::kChecked:
     case AOMStringProperty::kCurrent:
-    case AOMStringProperty::kHasPopUp:
+    case AOMStringProperty::kHasPopup:
     case AOMStringProperty::kInvalid:
     case AOMStringProperty::kLive:
     case AOMStringProperty::kOrientation:
diff --git a/third_party/blink/renderer/core/aom/accessible_node.h b/third_party/blink/renderer/core/aom/accessible_node.h
index 16c24d61..676ee61 100644
--- a/third_party/blink/renderer/core/aom/accessible_node.h
+++ b/third_party/blink/renderer/core/aom/accessible_node.h
@@ -30,7 +30,7 @@
   kChecked,
   kCurrent,
   kDescription,
-  kHasPopUp,
+  kHasPopup,
   kInvalid,
   kKeyShortcuts,
   kLabel,
@@ -257,8 +257,8 @@
   AccessibleNodeList* flowTo() const;
   void setFlowTo(AccessibleNodeList*);
 
-  AtomicString hasPopUp() const;
-  void setHasPopUp(const AtomicString&);
+  AtomicString hasPopup() const;
+  void setHasPopup(const AtomicString&);
 
   absl::optional<bool> hidden() const;
   void setHidden(absl::optional<bool>);
diff --git a/third_party/blink/renderer/core/aom/accessible_node.idl b/third_party/blink/renderer/core/aom/accessible_node.idl
index f6d7e2f..6f8885d 100644
--- a/third_party/blink/renderer/core/aom/accessible_node.idl
+++ b/third_party/blink/renderer/core/aom/accessible_node.idl
@@ -26,7 +26,7 @@
     attribute AccessibleNode? errorMessage;
     attribute boolean? expanded;
     attribute AccessibleNodeList? flowTo;
-    attribute DOMString? hasPopUp;
+    attribute DOMString? hasPopup;
     attribute boolean? hidden;
     attribute DOMString? invalid;
     attribute DOMString? keyShortcuts;
diff --git a/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc b/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc
index fbea7ea..a514bc9 100644
--- a/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc
+++ b/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc
@@ -903,8 +903,9 @@
   media::MockCdmContext mock_cdm_context_;
 
   viz::FrameSinkId frame_sink_id_ = viz::FrameSinkId(1, 1);
-  viz::LocalSurfaceId local_surface_id_ =
-      viz::LocalSurfaceId(11, base::UnguessableToken::Deserialize(0x111111, 0));
+  viz::LocalSurfaceId local_surface_id_ = viz::LocalSurfaceId(
+      11,
+      base::UnguessableToken::CreateForTesting(0x111111, 0));
   viz::SurfaceId surface_id_ =
       viz::SurfaceId(frame_sink_id_, local_surface_id_);
 
diff --git a/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc b/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc
index c74c5c4..47d094c 100644
--- a/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc
+++ b/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc
@@ -43,7 +43,7 @@
   return viz::SurfaceId(
       frame_sink_id,
       viz::LocalSurfaceId(parent_sequence_number, child_sequence_number,
-                          base::UnguessableToken::Deserialize(0, 1u)));
+                          base::UnguessableToken::CreateForTesting(0, 1u)));
 }
 
 }  // namespace
diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc
index 64d6838..9cd3d360 100644
--- a/third_party/blink/renderer/core/frame/web_frame_test.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_test.cc
@@ -8052,7 +8052,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad("data:text/html,<iframe></iframe>");
 
-  StorageKey storage_key = StorageKey::CreateWithNonce(
+  StorageKey storage_key = StorageKey::CreateWithNonceForTesting(
       url::Origin(), base::UnguessableToken::Create());
 
   auto* child_frame =
diff --git a/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc b/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc
index daaccd33..57459c5 100644
--- a/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc
+++ b/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc
@@ -95,8 +95,8 @@
     // Use a fake but valid viz::SurfaceId.
     surface_id_ = viz::SurfaceId(
         viz::FrameSinkId(1, 1),
-        viz::LocalSurfaceId(11,
-                            base::UnguessableToken::Deserialize(0x111111, 0)));
+        viz::LocalSurfaceId(
+            11, base::UnguessableToken::CreateForTesting(0x111111, 0)));
   }
   absl::optional<viz::SurfaceId> GetSurfaceId() override { return surface_id_; }
 
diff --git a/third_party/blink/renderer/core/html/parser/html_construction_site.cc b/third_party/blink/renderer/core/html/parser/html_construction_site.cc
index 9c8b086..12e458ee 100644
--- a/third_party/blink/renderer/core/html/parser/html_construction_site.cc
+++ b/third_party/blink/renderer/core/html/parser/html_construction_site.cc
@@ -132,8 +132,72 @@
   return std::min(current_position + *length_limit, string_length);
 }
 
-static inline bool IsAllWhitespace(const StringView& string_view) {
-  return string_view.IsAllSpecialCharacters<IsHTMLSpace<UChar>>();
+static inline WhitespaceMode RecomputeWhiteSpaceMode(
+    const StringView& string_view) {
+  DCHECK(!string_view.empty());
+  if (string_view[0] != '\n') {
+    return string_view.IsAllSpecialCharacters<IsHTMLSpace<UChar>>()
+               ? WhitespaceMode::kAllWhitespace
+               : WhitespaceMode::kNotAllWhitespace;
+  }
+
+  auto check_whitespace = [](auto* buffer, size_t length) {
+    WhitespaceMode result = WhitespaceMode::kNewlineThenWhitespace;
+    for (size_t i = 1; i < length; ++i) {
+      if (LIKELY(buffer[i] == ' ')) {
+        continue;
+      } else if (IsHTMLSpecialWhitespace(buffer[i])) {
+        result = WhitespaceMode::kAllWhitespace;
+      } else {
+        return WhitespaceMode::kNotAllWhitespace;
+      }
+    }
+    return result;
+  };
+
+  if (string_view.Is8Bit()) {
+    return check_whitespace(string_view.Characters8(), string_view.length());
+  } else {
+    return check_whitespace(string_view.Characters16(), string_view.length());
+  }
+}
+
+enum class RecomputeMode {
+  kDontRecompute,
+  kRecomputeIfNeeded,
+};
+
+// Strings composed entirely of whitespace are likely to be repeated. Turn them
+// into AtomicString so we share a single string for each.
+static String CheckWhitespaceAndConvertToString(const StringView& string,
+                                                WhitespaceMode whitespace_mode,
+                                                RecomputeMode recompute_mode) {
+  switch (whitespace_mode) {
+    case WhitespaceMode::kNewlineThenWhitespace:
+      DCHECK(WTF::NewlineThenWhitespaceStringsTable::IsCommon(string));
+      if (string.length() <
+          WTF::NewlineThenWhitespaceStringsTable::kTableSize) {
+        return WTF::NewlineThenWhitespaceStringsTable::GetStringForLength(
+            string.length());
+      }
+      [[fallthrough]];
+    case WhitespaceMode::kAllWhitespace:
+      return string.ToAtomicString().GetString();
+    case WhitespaceMode::kNotAllWhitespace:
+      // Other strings are pretty random and unlikely to repeat.
+      return string.ToString();
+    case WhitespaceMode::kWhitespaceUnknown:
+      DCHECK_EQ(RecomputeMode::kRecomputeIfNeeded, recompute_mode);
+      return CheckWhitespaceAndConvertToString(string,
+                                               RecomputeWhiteSpaceMode(string),
+                                               RecomputeMode::kDontRecompute);
+  }
+}
+
+static String TryCanonicalizeString(const StringView& string,
+                                    WhitespaceMode mode) {
+  return CheckWhitespaceAndConvertToString(string, mode,
+                                           RecomputeMode::kRecomputeIfNeeded);
 }
 
 static inline void Insert(HTMLConstructionSiteTask& task) {
@@ -303,17 +367,10 @@
     }
     StringView substring_view =
         string.SubstringView(current_position, break_index - current_position);
-    String substring;
-    if (canonicalize_whitespace_strings_ &&
-        (pending_text_.whitespace_mode == kAllWhitespace ||
-         (pending_text_.whitespace_mode == kWhitespaceUnknown &&
-          IsAllWhitespace(substring_view)))) {
-      // Strings composed entirely of whitespace are likely to be repeated. Turn
-      // them into AtomicString so we share a single string for each.
-      substring = substring_view.ToAtomicString().GetString();
-    } else {
-      substring = substring_view.ToString();
-    }
+    String substring = canonicalize_whitespace_strings_
+                           ? TryCanonicalizeString(
+                                 substring_view, pending_text_.whitespace_mode)
+                           : substring_view.ToString();
 
     DCHECK_GT(break_index, current_position);
     DCHECK_EQ(break_index - current_position, substring.length());
@@ -405,7 +462,7 @@
       redirect_attach_to_foster_parent_(false),
       in_quirks_mode_(document.InQuirksMode()),
       canonicalize_whitespace_strings_(
-          RuntimeEnabledFeatures::CanonicalizeWhiteSpaceStringsEnabled()) {
+          RuntimeEnabledFeatures::CanonicalizeWhitespaceStringsEnabled()) {
   DCHECK(document_->IsHTMLDocument() || document_->IsXHTMLDocument());
 }
 
diff --git a/third_party/blink/renderer/core/html/parser/html_construction_site.h b/third_party/blink/renderer/core/html/parser/html_construction_site.h
index f6e1c23..c8f75f4 100644
--- a/third_party/blink/renderer/core/html/parser/html_construction_site.h
+++ b/third_party/blink/renderer/core/html/parser/html_construction_site.h
@@ -82,10 +82,12 @@
 
 // Note: These are intentionally ordered so that when we concatonate strings and
 // whitespaces the resulting whitespace is ws = min(ws1, ws2).
-enum WhitespaceMode {
+enum class WhitespaceMode {
   kWhitespaceUnknown,
   kNotAllWhitespace,
   kAllWhitespace,
+  // Even stronger guarantee: string of type '\n[space]*'.
+  kNewlineThenWhitespace,
 };
 
 class AtomicHTMLToken;
@@ -150,7 +152,8 @@
   void InsertHTMLBodyElement(AtomicHTMLToken*);
   void InsertHTMLFormElement(AtomicHTMLToken*, bool is_demoted = false);
   void InsertScriptElement(AtomicHTMLToken*);
-  void InsertTextNode(const StringView&, WhitespaceMode = kWhitespaceUnknown);
+  void InsertTextNode(const StringView&,
+                      WhitespaceMode = WhitespaceMode::kWhitespaceUnknown);
   void InsertForeignElement(AtomicHTMLToken*,
                             const AtomicString& namespace_uri);
 
@@ -289,7 +292,7 @@
     DISALLOW_NEW();
 
    public:
-    PendingText() : whitespace_mode(kWhitespaceUnknown) {}
+    PendingText() : whitespace_mode(WhitespaceMode::kWhitespaceUnknown) {}
 
     void Append(ContainerNode* new_parent,
                 Node* new_next_child,
@@ -304,22 +307,23 @@
     }
 
     void Discard() {
-      if (IsEmpty())
+      if (IsEmpty()) {
         return;
+      }
 
       parent.Clear();
       next_child.Clear();
       string_builder.Clear();
-      whitespace_mode = kWhitespaceUnknown;
+      whitespace_mode = WhitespaceMode::kWhitespaceUnknown;
     }
 
-    bool IsEmpty() {
+    bool IsEmpty() const {
       // When the stringbuilder is empty, the parent and whitespace should also
       // be "empty".
       DCHECK_EQ(string_builder.empty(), !parent);
       DCHECK(!string_builder.empty() || !next_child);
       DCHECK(!string_builder.empty() ||
-             (whitespace_mode == kWhitespaceUnknown));
+             (whitespace_mode == WhitespaceMode::kWhitespaceUnknown));
       return string_builder.empty();
     }
 
@@ -349,7 +353,7 @@
   bool reported_duplicate_attribute_ = false;
 
   // Whether strings should be canonicalized (deduplicated).
-  bool canonicalize_whitespace_strings_ = false;
+  bool canonicalize_whitespace_strings_ = true;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/parser/html_parser_idioms.h b/third_party/blink/renderer/core/html/parser/html_parser_idioms.h
index 1c1b0b4c..aba85b58 100644
--- a/third_party/blink/renderer/core/html/parser/html_parser_idioms.h
+++ b/third_party/blink/renderer/core/html/parser/html_parser_idioms.h
@@ -99,6 +99,12 @@
 }
 
 template <typename CharType>
+ALWAYS_INLINE bool IsHTMLSpecialWhitespace(CharType character) {
+  return character <= '\r' && (character == '\r' || character == '\n' ||
+                               character == '\t' || character == '\f');
+}
+
+template <typename CharType>
 inline bool IsComma(CharType character) {
   return character == ',';
 }
diff --git a/third_party/blink/renderer/core/html/parser/html_tree_builder.cc b/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
index 0a7ef834..2ccf1569 100644
--- a/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
+++ b/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
@@ -153,8 +153,42 @@
 
   void SkipLeadingWhitespace() { SkipLeading<IsHTMLSpace<UChar>>(); }
 
-  StringView TakeLeadingWhitespace() {
-    return TakeLeading<IsHTMLSpace<UChar>>();
+  struct TakeLeadingWhitespaceResult {
+    StringView string;
+    WhitespaceMode whitespace_mode;
+  };
+
+  TakeLeadingWhitespaceResult TakeLeadingWhitespace() {
+    DCHECK(!IsEmpty());
+    const unsigned start = current_;
+    WhitespaceMode whitespace_mode = WhitespaceMode::kNewlineThenWhitespace;
+
+    // First, check the first character to identify whether the string looks
+    // common (i.e. "\n<space>*").
+    const UChar first = (*characters_)[current_];
+    if (!IsHTMLSpace(first)) {
+      return {StringView(characters_.get(), start, 0),
+              WhitespaceMode::kNotAllWhitespace};
+    }
+    if (first != '\n') {
+      whitespace_mode = WhitespaceMode::kAllWhitespace;
+    }
+
+    // Then, check the rest.
+    ++current_;
+    for (; current_ != end_; ++current_) {
+      const UChar ch = (*characters_)[current_];
+      if (LIKELY(ch == ' ')) {
+        continue;
+      } else if (IsHTMLSpecialWhitespace(ch)) {
+        whitespace_mode = WhitespaceMode::kAllWhitespace;
+      } else {
+        break;
+      }
+    }
+
+    return {StringView(characters_.get(), start, current_ - start),
+            whitespace_mode};
   }
 
   void SkipLeadingNonWhitespace() { SkipLeading<IsNotHTMLSpace<UChar>>(); }
@@ -175,34 +209,54 @@
     current_ = end_;
   }
 
-  String TakeRemainingWhitespace() {
+  struct TakeRemainingWhitespaceResult {
+    String string;
+    WhitespaceMode whitespace_mode;
+  };
+
+  TakeRemainingWhitespaceResult TakeRemainingWhitespace() {
     DCHECK(!IsEmpty());
     const unsigned start = current_;
     current_ = end_;  // One way or another, we're taking everything!
 
+    WhitespaceMode whitespace_mode = WhitespaceMode::kNewlineThenWhitespace;
     unsigned length = 0;
     for (unsigned i = start; i < end_; ++i) {
-      if (IsHTMLSpace<UChar>((*characters_)[i]))
+      const UChar ch = (*characters_)[i];
+      if (ch == '\n' && length == 0) {
         ++length;
+        continue;
+      }
+
+      if (ch == ' ') {
+        ++length;
+      } else if (IsHTMLSpecialWhitespace<UChar>(ch)) {
+        whitespace_mode = WhitespaceMode::kAllWhitespace;
+        ++length;
+      }
     }
     // Returning the null string when there aren't any whitespace
     // characters is slightly cleaner semantically because we don't want
     // to insert a text node (as opposed to inserting an empty text node).
-    if (!length)
-      return String();
-    if (length == start - end_)  // It's all whitespace.
-      return String(characters_->Substring(start, start - end_));
+    if (!length) {
+      return {String(), WhitespaceMode::kNotAllWhitespace};
+    }
+    if (length == start - end_) {  // It's all whitespace.
+      return {String(characters_->Substring(start, start - end_)),
+              whitespace_mode};
+    }
 
     // All HTML spaces are ASCII.
     StringBuffer<LChar> result(length);
     unsigned j = 0;
     for (unsigned i = start; i < end_; ++i) {
       UChar c = (*characters_)[i];
-      if (IsHTMLSpace(c))
+      if (c == ' ' || IsHTMLSpecialWhitespace(c)) {
         result[j++] = static_cast<LChar>(c);
+      }
     }
     DCHECK_EQ(j, length);
-    return String::Adopt(result);
+    return {String::Adopt(result), whitespace_mode};
   }
 
  private:
@@ -215,14 +269,6 @@
     }
   }
 
-  template <bool characterPredicate(UChar)>
-  StringView TakeLeading() {
-    DCHECK(!IsEmpty());
-    const unsigned start = current_;
-    SkipLeading<characterPredicate>();
-    return StringView(characters_.get(), start, current_ - start);
-  }
-
   scoped_refptr<StringImpl> characters_;
   unsigned current_;
   unsigned end_;
@@ -2479,18 +2525,22 @@
       [[fallthrough]];
     }
     case kInHeadMode: {
-      StringView leading_whitespace = buffer.TakeLeadingWhitespace();
-      if (!leading_whitespace.empty())
-        tree_.InsertTextNode(leading_whitespace, kAllWhitespace);
+      auto leading_whitespace = buffer.TakeLeadingWhitespace();
+      if (!leading_whitespace.string.empty()) {
+        tree_.InsertTextNode(leading_whitespace.string,
+                             leading_whitespace.whitespace_mode);
+      }
       if (buffer.IsEmpty())
         return;
       DefaultForInHead();
       [[fallthrough]];
     }
     case kAfterHeadMode: {
-      StringView leading_whitespace = buffer.TakeLeadingWhitespace();
-      if (!leading_whitespace.empty())
-        tree_.InsertTextNode(leading_whitespace, kAllWhitespace);
+      auto leading_whitespace = buffer.TakeLeadingWhitespace();
+      if (!leading_whitespace.string.empty()) {
+        tree_.InsertTextNode(leading_whitespace.string,
+                             leading_whitespace.whitespace_mode);
+      }
       if (buffer.IsEmpty())
         return;
       DefaultForAfterHead();
@@ -2528,9 +2578,11 @@
       break;
     }
     case kInColumnGroupMode: {
-      StringView leading_whitespace = buffer.TakeLeadingWhitespace();
-      if (!leading_whitespace.empty())
-        tree_.InsertTextNode(leading_whitespace, kAllWhitespace);
+      auto leading_whitespace = buffer.TakeLeadingWhitespace();
+      if (!leading_whitespace.string.empty()) {
+        tree_.InsertTextNode(leading_whitespace.string,
+                             leading_whitespace.whitespace_mode);
+      }
       if (buffer.IsEmpty())
         return;
       if (!ProcessColgroupEndTagForInColumnGroup()) {
@@ -2545,11 +2597,12 @@
     case kAfterBodyMode:
     case kAfterAfterBodyMode: {
       // FIXME: parse error
-      StringView leading_whitespace = buffer.TakeLeadingWhitespace();
-      if (!leading_whitespace.empty()) {
+      auto leading_whitespace = buffer.TakeLeadingWhitespace();
+      if (!leading_whitespace.string.empty()) {
         InsertionMode mode = GetInsertionMode();
         SetInsertionMode(kInBodyMode);
-        tree_.InsertTextNode(leading_whitespace, kAllWhitespace);
+        tree_.InsertTextNode(leading_whitespace.string,
+                             leading_whitespace.whitespace_mode);
         SetInsertionMode(mode);
       }
       if (buffer.IsEmpty())
@@ -2562,19 +2615,24 @@
       break;
     }
     case kInHeadNoscriptMode: {
-      StringView leading_whitespace = buffer.TakeLeadingWhitespace();
-      if (!leading_whitespace.empty())
-        tree_.InsertTextNode(leading_whitespace, kAllWhitespace);
-      if (buffer.IsEmpty())
+      auto leading_whitespace = buffer.TakeLeadingWhitespace();
+      if (!leading_whitespace.string.empty()) {
+        tree_.InsertTextNode(leading_whitespace.string,
+                             leading_whitespace.whitespace_mode);
+      }
+      if (buffer.IsEmpty()) {
         return;
+      }
       DefaultForInHeadNoscript();
       goto ReprocessBuffer;
     }
     case kInFramesetMode:
     case kAfterFramesetMode: {
-      String leading_whitespace = buffer.TakeRemainingWhitespace();
-      if (!leading_whitespace.empty())
-        tree_.InsertTextNode(leading_whitespace, kAllWhitespace);
+      auto leading_whitespace = buffer.TakeRemainingWhitespace();
+      if (!leading_whitespace.string.empty()) {
+        tree_.InsertTextNode(leading_whitespace.string,
+                             leading_whitespace.whitespace_mode);
+      }
       // FIXME: We should generate a parse error if we skipped over any
       // non-whitespace characters.
       break;
@@ -2585,10 +2643,11 @@
       break;
     }
     case kAfterAfterFramesetMode: {
-      String leading_whitespace = buffer.TakeRemainingWhitespace();
-      if (!leading_whitespace.empty()) {
+      auto leading_whitespace = buffer.TakeRemainingWhitespace();
+      if (!leading_whitespace.string.empty()) {
         tree_.ReconstructTheActiveFormattingElements();
-        tree_.InsertTextNode(leading_whitespace, kAllWhitespace);
+        tree_.InsertTextNode(leading_whitespace.string,
+                             leading_whitespace.whitespace_mode);
       }
       // FIXME: We should generate a parse error if we skipped over any
       // non-whitespace characters.
@@ -2732,7 +2791,7 @@
     // FIXME: parse error
     HTMLConstructionSite::RedirectToFosterParentGuard redirecter(tree_);
     tree_.ReconstructTheActiveFormattingElements();
-    tree_.InsertTextNode(characters, kNotAllWhitespace);
+    tree_.InsertTextNode(characters, WhitespaceMode::kNotAllWhitespace);
     frameset_ok_ = false;
     SetInsertionMode(original_insertion_mode_);
     return;
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index 770321f..098f2d3 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -612,7 +612,8 @@
     // The background of the root element or the body element could propagate up
     // to the canvas. Just dirty the entire canvas when our style changes
     // substantially.
-    if ((diff.NeedsPaintInvalidation() || diff.NeedsLayout()) && GetNode() &&
+    if ((diff.NeedsNormalPaintInvalidation() || diff.NeedsLayout()) &&
+        GetNode() &&
         (IsDocumentElement() || IsA<HTMLBodyElement>(*GetNode()))) {
       View()->SetShouldDoFullPaintInvalidation();
     }
@@ -827,7 +828,7 @@
   if (IsCustomItem())
     GetCustomLayoutChild()->styleMap()->UpdateStyle(GetDocument(), StyleRef());
 
-  if (diff.NeedsPaintInvalidation()) {
+  if (diff.NeedsNormalPaintInvalidation()) {
     if (const AnchorScrollValue* old_anchor_scroll =
             old_style ? old_style->AnchorScroll() : nullptr;
         !base::ValuesEquivalent(StyleRef().AnchorScroll().Get(),
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 3c69c00..9f77146 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
@@ -229,8 +229,10 @@
                                                const ComputedStyle* old_style) {
   NOT_DESTROYED();
   LayoutReplaced::StyleDidChange(diff, old_style);
-  if (old_style && (diff.NeedsPaintInvalidation() || diff.NeedsLayout()))
+  if (old_style &&
+      (diff.NeedsNormalPaintInvalidation() || diff.NeedsLayout())) {
     SetNeedsPaintInvalidation();
+  }
   RecordPercentLengthStats();
 }
 
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index 594029a..62a0068 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -235,12 +235,12 @@
   // whether the background color changed.
   if (RuntimeEnabledFeatures::CompositeBGColorAnimationEnabled() &&
       (had_background_color_animation != has_background_color_animation))
-    diff.SetNeedsPaintInvalidation();
+    diff.SetNeedsNormalPaintInvalidation();
 
   bool skip_background_color_paint_invalidation =
       !diff.BackgroundColorChanged() || HasNativeBackgroundPainter(node);
   if (!skip_background_color_paint_invalidation)
-    diff.SetNeedsPaintInvalidation();
+    diff.SetNeedsNormalPaintInvalidation();
 
   bool had_clip_path_animation =
       old_style ? old_style->HasCurrentClipPathAnimation() : false;
@@ -250,12 +250,12 @@
   // whether the background color changed.
   if (RuntimeEnabledFeatures::CompositeClipPathAnimationEnabled() &&
       (had_clip_path_animation != has_clip_path_animation))
-    diff.SetNeedsPaintInvalidation();
+    diff.SetNeedsNormalPaintInvalidation();
 
   bool skip_clip_path_paint_invalidation =
       !diff.ClipPathChanged() || HasClipPathPaintWorklet(node);
   if (!skip_clip_path_paint_invalidation)
-    diff.SetNeedsPaintInvalidation();
+    diff.SetNeedsNormalPaintInvalidation();
 
   return diff;
 }
@@ -1124,7 +1124,7 @@
   return nullptr;
 }
 
-PaintLayer* LayoutObject::PaintingLayer() const {
+PaintLayer* LayoutObject::PaintingLayer(int max_depth) const {
   NOT_DESTROYED();
   auto FindContainer = [](const LayoutObject& object) -> const LayoutObject* {
     // Column spanners paint through their multicolumn containers which can
@@ -1141,9 +1141,12 @@
       return object.GetFrame()->OwnerLayoutObject();
     return object.Parent();
   };
-
+  int depth = 0;
   for (const LayoutObject* current = this; current;
        current = FindContainer(*current)) {
+    if (max_depth != -1 && ++depth > max_depth) {
+      break;
+    }
     if (current->HasLayer() &&
         To<LayoutBoxModelObject>(current)->Layer()->IsSelfPaintingLayer())
       return To<LayoutBoxModelObject>(current)->Layer();
@@ -2448,7 +2451,9 @@
 
   // Optimization: for decoration/color property changes, invalidation is only
   // needed if we have style or text affected by these properties.
-  if (diff.TextDecorationOrColorChanged() && !diff.NeedsPaintInvalidation()) {
+  if (diff.TextDecorationOrColorChanged() &&
+      !diff.NeedsNormalPaintInvalidation() &&
+      !diff.NeedsSimplePaintInvalidation()) {
     if (StyleRef().HasOutlineWithCurrentColor() ||
         StyleRef().HasBackgroundRelatedColorReferencingCurrentColor() ||
         // Skip any text nodes that do not contain text boxes. Whitespace cannot
@@ -2458,15 +2463,16 @@
         (IsText() && !IsBR() && To<LayoutText>(this)->HasInlineFragments()) ||
         (IsSVG() && StyleRef().IsFillColorCurrentColor()) ||
         (IsSVG() && StyleRef().IsStrokeColorCurrentColor()) ||
-        IsListMarkerForNormalContent() || IsMathML())
-      diff.SetNeedsPaintInvalidation();
+        IsListMarkerForNormalContent() || IsMathML()) {
+      diff.SetNeedsSimplePaintInvalidation();
+    }
   }
 
   // TODO(1088373): Pixel_WebGLHighToLowPower fails without this. This isn't the
   // right way to ensure GPU switching. Investigate and do it in the right way.
-  if (!diff.NeedsPaintInvalidation() && IsLayoutView() && Style() &&
+  if (!diff.NeedsNormalPaintInvalidation() && IsLayoutView() && Style() &&
       !Style()->GetFont().IsFallbackValid()) {
-    diff.SetNeedsPaintInvalidation();
+    diff.SetNeedsNormalPaintInvalidation();
   }
 
   // The answer to layerTypeRequired() for plugins, iframes, and canvas can
@@ -2613,7 +2619,7 @@
           diff.Merge(pseudo_old_style->VisualInvalidationDiff(
               GetDocument(), *pseudo_new_style));
         } else {
-          diff.SetNeedsPaintInvalidation();
+          diff.SetNeedsNormalPaintInvalidation();
         }
       }
     };
@@ -2665,6 +2671,18 @@
   // invalidate paints.
   StyleDifference updated_diff = AdjustStyleDifference(diff);
 
+  if (updated_diff.NeedsSimplePaintInvalidation()) {
+    DCHECK(!diff.NeedsNormalPaintInvalidation());
+    constexpr int kMaxDepth = 5;
+    if (auto* painting_layer = PaintingLayer(kMaxDepth)) {
+      painting_layer->SetNeedsRepaint();
+      InvalidateDisplayItemClients(PaintInvalidationReason::kStyle);
+      GetFrameView()->ScheduleVisualUpdateForPaintInvalidationIfNeeded();
+    } else {
+      updated_diff.SetNeedsNormalPaintInvalidation();
+    }
+  }
+
   if (!diff.NeedsFullLayout()) {
     if (updated_diff.NeedsFullLayout()) {
       SetNeedsLayoutAndIntrinsicWidthsRecalc(
@@ -2706,7 +2724,8 @@
 #endif
   }
 
-  if (diff.NeedsPaintInvalidation() || updated_diff.NeedsPaintInvalidation()) {
+  if (diff.NeedsNormalPaintInvalidation() ||
+      updated_diff.NeedsNormalPaintInvalidation()) {
     if (IsSVGRoot()) {
       // LayoutSVGRoot::LocalVisualRect() depends on some styles.
       SetShouldDoFullPaintInvalidation();
@@ -2718,7 +2737,7 @@
     }
   }
 
-  if (diff.NeedsPaintInvalidation() && old_style &&
+  if (diff.NeedsNormalPaintInvalidation() && old_style &&
       !old_style->ClipPathDataEquivalent(*style_)) {
     SetNeedsPaintPropertyUpdate();
     PaintingLayer()->SetNeedsCompositingInputsUpdate();
@@ -3098,7 +3117,7 @@
     }
   }
 
-  if (diff.NeedsPaintInvalidation() && old_style) {
+  if (diff.NeedsNormalPaintInvalidation() && old_style) {
     if (ResolveColor(*old_style, GetCSSPropertyBackgroundColor()) !=
             ResolveColor(GetCSSPropertyBackgroundColor()) ||
         old_style->BackgroundLayers() != StyleRef().BackgroundLayers())
@@ -3170,12 +3189,12 @@
     }
   }
   if (!has_diff) {
-    diff.SetNeedsPaintInvalidation();
+    diff.SetNeedsNormalPaintInvalidation();
     diff.SetNeedsFullLayout();
   }
 
-  if (BehavesLikeBlockContainer() &&
-      (diff.NeedsPaintInvalidation() || diff.TextDecorationOrColorChanged())) {
+  if (BehavesLikeBlockContainer() && (diff.NeedsNormalPaintInvalidation() ||
+                                      diff.TextDecorationOrColorChanged())) {
     if (auto* first_line_container =
             To<LayoutBlock>(this)->NearestInnerBlockWithFirstLine())
       first_line_container->SetShouldDoFullPaintInvalidationForFirstLine();
@@ -4623,8 +4642,9 @@
 
 void LayoutObject::SetShouldCheckForPaintInvalidationWithoutLayoutChange() {
   NOT_DESTROYED();
-  if (ShouldCheckForPaintInvalidation())
+  if (ShouldCheckForPaintInvalidation()) {
     return;
+  }
   GetFrameView()->ScheduleVisualUpdateForPaintInvalidationIfNeeded();
 
   bitfields_.SetShouldCheckForPaintInvalidation(true);
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index cb33b934..02faebf 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -449,7 +449,7 @@
 
   // Returns the layer that will paint this object. During paint invalidation,
   // we should use the faster PaintInvalidatorContext::painting_layer instead.
-  PaintLayer* PaintingLayer() const;
+  PaintLayer* PaintingLayer(int max_depth = -1) const;
 
   bool IsFixedPositionObjectInPagedMedia() const;
 
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_sizing_tree.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_sizing_tree.cc
index 29f9647..763e21f 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_sizing_tree.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_sizing_tree.cc
@@ -39,4 +39,21 @@
           range_indices.begin, range_indices.end, track_direction));
 }
 
+NGGridSizingTree NGGridSizingTree::CopySubtree(wtf_size_t subtree_root) const {
+  DCHECK_LT(subtree_root, sizing_data_.size());
+
+  const wtf_size_t subtree_size = sizing_data_[subtree_root]->subtree_size;
+  DCHECK_LE(subtree_root + subtree_size, sizing_data_.size());
+
+  NGGridSizingTree subtree_copy(subtree_size);
+  for (wtf_size_t i = 0; i < subtree_size; ++i) {
+    auto& copy_data = subtree_copy.CreateSizingData();
+    const auto& original_data = *sizing_data_[subtree_root + i];
+
+    copy_data.subtree_size = original_data.subtree_size;
+    copy_data.layout_data = original_data.layout_data;
+  }
+  return subtree_copy;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_sizing_tree.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_sizing_tree.h
index 2c83b751..47e86afe 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_sizing_tree.h
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_sizing_tree.h
@@ -43,7 +43,14 @@
  public:
   using GridSizingDataVector = Vector<std::unique_ptr<NGGridSizingData>, 16>;
 
-  wtf_size_t Size() const { return sizing_data_.size(); }
+  NGGridSizingTree(NGGridSizingTree&&) = default;
+  NGGridSizingTree(const NGGridSizingTree&) = delete;
+  NGGridSizingTree& operator=(NGGridSizingTree&&) = default;
+  NGGridSizingTree& operator=(const NGGridSizingTree&) = delete;
+
+  explicit NGGridSizingTree(wtf_size_t tree_size = 1) {
+    sizing_data_.ReserveInitialCapacity(tree_size);
+  }
 
   NGGridSizingData& CreateSizingData() {
     return *sizing_data_.emplace_back(std::make_unique<NGGridSizingData>());
@@ -54,6 +61,9 @@
     return *sizing_data_[index];
   }
 
+  NGGridSizingTree CopySubtree(wtf_size_t subtree_root) const;
+  wtf_size_t Size() const { return sizing_data_.size(); }
+
  private:
   GridSizingDataVector sizing_data_;
 };
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc
index 8db3a4c..1326b6a 100644
--- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc
@@ -26,7 +26,7 @@
   NOT_DESTROYED();
   if (diff.HasDifference()) {
     if (LayoutNGTable* table = Table()) {
-      if (old_style && diff.NeedsPaintInvalidation()) {
+      if (old_style && diff.NeedsNormalPaintInvalidation()) {
         // Regenerate table borders if needed
         if (!old_style->BorderVisuallyEqual(StyleRef()))
           table->GridBordersChanged();
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc
index 6dbee76..f7b6dcb 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc
@@ -287,7 +287,7 @@
   // If this LayoutObject is the child of a resource container and
   // it requires repainting because of changes to CSS properties
   // such as 'visibility', upgrade to invalidate layout.
-  bool needs_layout = diff.NeedsPaintInvalidation() &&
+  bool needs_layout = diff.NeedsNormalPaintInvalidation() &&
                       IsLayoutObjectOfResourceContainer(object);
   MarkForLayoutAndParentResourceInvalidation(object, needs_layout);
 }
diff --git a/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc b/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc
index d6bd29b..11fd9fb2 100644
--- a/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc
+++ b/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc
@@ -124,4 +124,28 @@
   EXPECT_FALSE(IsValidDisplayItemClient(target));
 }
 
+TEST_F(ObjectPaintInvalidatorTest,
+       DirectPaintInvalidationSkipsPaintInvalidationChecking) {
+  SetBodyInnerHTML(R"HTML(
+    <div id='target' style="color: rgb(80, 230, 175);">Text</div>
+  )HTML");
+
+  auto* div = GetDocument().getElementById("target");
+  auto* text = div->firstChild();
+  const auto* object = text->GetLayoutObject();
+  ValidateDisplayItemClient(object);
+  EXPECT_TRUE(IsValidDisplayItemClient(object));
+  EXPECT_FALSE(object->ShouldCheckForPaintInvalidation());
+
+  div->setAttribute(html_names::kStyleAttr, "color: rgb(80, 100, 175)");
+  GetDocument().View()->UpdateLifecycleToLayoutClean(
+      DocumentUpdateReason::kTest);
+  EXPECT_FALSE(IsValidDisplayItemClient(object));
+  EXPECT_FALSE(object->ShouldCheckForPaintInvalidation());
+
+  UpdateAllLifecyclePhasesForTest();
+  EXPECT_TRUE(IsValidDisplayItemClient(object));
+  EXPECT_FALSE(object->ShouldCheckForPaintInvalidation());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/view_painter_test.cc b/third_party/blink/renderer/core/paint/view_painter_test.cc
index 978647849..d8ccc77 100644
--- a/third_party/blink/renderer/core/paint/view_painter_test.cc
+++ b/third_party/blink/renderer/core/paint/view_painter_test.cc
@@ -5,15 +5,21 @@
 #include "third_party/blink/renderer/core/paint/view_painter.h"
 
 #include <gtest/gtest.h>
+#include "cc/test/paint_op_matchers.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
 #include "third_party/blink/renderer/platform/testing/paint_property_test_helpers.h"
 #include "ui/gfx/geometry/skia_conversions.h"
 
-using testing::ElementsAre;
-
 namespace blink {
+namespace {
+
+using ::cc::PaintOpIs;
+using ::testing::_;
+using ::testing::AllOf;
+using ::testing::ElementsAre;
+using ::testing::ResultOf;
 
 class ViewPainterFixedBackgroundTest : public PaintControllerPaintTest {
  protected:
@@ -60,18 +66,20 @@
 
   PaintRecord record =
       To<DrawingDisplayItem>(background_display_item)->GetPaintRecord();
-  ASSERT_EQ(record.size(), 2u);
-  const cc::DrawRectOp* op = record.GetOpAtForTesting<cc::DrawRectOp>(1);
-  ASSERT_TRUE(op);
 
-  // This is the dest_rect_ calculated by BackgroundImageGeometry. For a fixed
-  // background in scrolling contents layer, its location is the scroll offset.
-  auto rect = gfx::SkRectToRectF(op->rect);
-  if (prefer_compositing_to_lcd_text) {
-    EXPECT_EQ(gfx::RectF(0, 0, 800, 600), rect);
-  } else {
-    EXPECT_EQ(gfx::RectF(scroll_offset.x(), scroll_offset.y(), 800, 600), rect);
-  }
+  SkRect expected_rect =
+      prefer_compositing_to_lcd_text
+          ? SkRect::MakeXYWH(0, 0, 800, 600)
+          : SkRect::MakeXYWH(scroll_offset.x(), scroll_offset.y(), 800, 600);
+  EXPECT_THAT(
+      record,
+      ElementsAre(
+          _, AllOf(PaintOpIs<cc::DrawRectOp>(),
+                   ResultOf(
+                       [](const cc::PaintOp& op) {
+                         return static_cast<const cc::DrawRectOp&>(op).rect;
+                       },
+                       expected_rect))));
 }
 
 TEST_P(ViewPainterFixedBackgroundTest,
@@ -287,4 +295,5 @@
           gfx::Rect(0, 0, 800, 3000))));
 }
 
+}  // namespace
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc
index 2e054587..d171d4ff 100644
--- a/third_party/blink/renderer/core/style/computed_style.cc
+++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -730,13 +730,13 @@
   if (DiffNeedsReshapeAndFullLayoutAndPaintInvalidation(*this, other)) {
     diff.SetNeedsReshape();
     diff.SetNeedsFullLayout();
-    diff.SetNeedsPaintInvalidation();
+    diff.SetNeedsNormalPaintInvalidation();
   }
 
-  if ((!diff.NeedsFullLayout() || !diff.NeedsPaintInvalidation()) &&
+  if ((!diff.NeedsFullLayout() || !diff.NeedsNormalPaintInvalidation()) &&
       DiffNeedsFullLayoutAndPaintInvalidation(other)) {
     diff.SetNeedsFullLayout();
-    diff.SetNeedsPaintInvalidation();
+    diff.SetNeedsNormalPaintInvalidation();
   }
 
   if (!diff.NeedsFullLayout() && DiffNeedsFullLayout(document, other)) {
@@ -946,13 +946,13 @@
     const Document& document) const {
   if (ComputedStyleBase::DiffNeedsPaintInvalidation(*this, other) ||
       !BorderVisuallyEqual(other) || !RadiiEqual(other)) {
-    diff.SetNeedsPaintInvalidation();
+    diff.SetNeedsNormalPaintInvalidation();
   }
 
   AdjustDiffForClipPath(other, diff);
   AdjustDiffForBackgroundVisuallyEqual(other, diff);
 
-  if (diff.NeedsPaintInvalidation()) {
+  if (diff.NeedsNormalPaintInvalidation()) {
     return;
   }
 
@@ -960,7 +960,7 @@
     for (const auto& image : *PaintImagesInternal()) {
       DCHECK(image);
       if (DiffNeedsPaintInvalidationForPaintImage(*image, other, document)) {
-        diff.SetNeedsPaintInvalidation();
+        diff.SetNeedsNormalPaintInvalidation();
         return;
       }
     }
@@ -994,7 +994,7 @@
   }
 
   if (!BackgroundInternal().VisuallyEqual(other.BackgroundInternal())) {
-    diff.SetNeedsPaintInvalidation();
+    diff.SetNeedsNormalPaintInvalidation();
     return;
   }
   // If the background image depends on currentColor
@@ -1005,7 +1005,7 @@
       (GetCurrentColor() != other.GetCurrentColor() ||
        GetInternalVisitedCurrentColor() !=
            other.GetInternalVisitedCurrentColor())) {
-    diff.SetNeedsPaintInvalidation();
+    diff.SetNeedsNormalPaintInvalidation();
   }
 }
 
@@ -1124,7 +1124,7 @@
     diff.SetNeedsRecomputeVisualOverflow();
   }
 
-  if (!diff.NeedsPaintInvalidation() &&
+  if (!diff.NeedsNormalPaintInvalidation() &&
       ComputedStyleBase::UpdatePropertySpecificDifferencesTextDecorationOrColor(
           *this, other)) {
     diff.SetTextDecorationOrColorChanged();
diff --git a/third_party/blink/renderer/core/style/style_difference.cc b/third_party/blink/renderer/core/style/style_difference.cc
index fc14805..42e34b02 100644
--- a/third_party/blink/renderer/core/style/style_difference.cc
+++ b/third_party/blink/renderer/core/style/style_difference.cc
@@ -29,7 +29,23 @@
   }
 
   out << ", reshape=" << diff.needs_reshape_;
-  out << ", paintInvalidation=" << diff.needs_paint_invalidation_;
+
+  out << ", paintInvalidationType=";
+  switch (diff.paint_invalidation_type_) {
+    case static_cast<unsigned>(StyleDifference::PaintInvalidationType::kNone):
+      out << "None";
+      break;
+    case static_cast<unsigned>(StyleDifference::PaintInvalidationType::kSimple):
+      out << "Simple";
+      break;
+    case static_cast<unsigned>(StyleDifference::PaintInvalidationType::kNormal):
+      out << "Normal";
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+
   out << ", recomputeVisualOverflow=" << diff.recompute_visual_overflow_;
 
   out << ", propertySpecificDifferences=";
diff --git a/third_party/blink/renderer/core/style/style_difference.h b/third_party/blink/renderer/core/style/style_difference.h
index 4558afe..e35fe3c 100644
--- a/third_party/blink/renderer/core/style/style_difference.h
+++ b/third_party/blink/renderer/core/style/style_difference.h
@@ -39,7 +39,8 @@
   };
 
   StyleDifference()
-      : needs_paint_invalidation_(false),
+      : paint_invalidation_type_(
+            static_cast<unsigned>(PaintInvalidationType::kNone)),
         layout_type_(kNoLayout),
         needs_reshape_(false),
         recompute_visual_overflow_(false),
@@ -49,7 +50,8 @@
         compositable_paint_effect_changed_(false) {}
 
   void Merge(StyleDifference other) {
-    needs_paint_invalidation_ |= other.needs_paint_invalidation_;
+    paint_invalidation_type_ =
+        std::max(paint_invalidation_type_, other.paint_invalidation_type_);
     layout_type_ = std::max(layout_type_, other.layout_type_);
     needs_reshape_ |= other.needs_reshape_;
     recompute_visual_overflow_ |= other.recompute_visual_overflow_;
@@ -62,21 +64,42 @@
   }
 
   bool HasDifference() const {
-    return needs_paint_invalidation_ || layout_type_ || needs_reshape_ ||
-           property_specific_differences_ || recompute_visual_overflow_ ||
+    return (paint_invalidation_type_ !=
+            static_cast<unsigned>(PaintInvalidationType::kNone)) ||
+           layout_type_ || needs_reshape_ || property_specific_differences_ ||
+           recompute_visual_overflow_ ||
            scroll_anchor_disabling_property_changed_ ||
            compositing_reasons_changed_ || compositable_paint_effect_changed_;
   }
 
   bool HasAtMostPropertySpecificDifferences(
       unsigned property_differences) const {
-    return !needs_paint_invalidation_ && !layout_type_ &&
-           !compositing_reasons_changed_ &&
+    return (paint_invalidation_type_ ==
+            static_cast<unsigned>(PaintInvalidationType::kNone)) &&
+           !layout_type_ && !compositing_reasons_changed_ &&
            !(property_specific_differences_ & ~property_differences);
   }
 
-  bool NeedsPaintInvalidation() const { return needs_paint_invalidation_; }
-  void SetNeedsPaintInvalidation() { needs_paint_invalidation_ = true; }
+  // For simple paint invalidation, we can directly invalidate the
+  // DisplayItemClients during style update, without paint invalidation during
+  // PrePaintTreeWalk.
+  bool NeedsSimplePaintInvalidation() const {
+    return paint_invalidation_type_ ==
+           static_cast<unsigned>(PaintInvalidationType::kSimple);
+  }
+  bool NeedsNormalPaintInvalidation() const {
+    return paint_invalidation_type_ ==
+           static_cast<unsigned>(PaintInvalidationType::kNormal);
+  }
+  void SetNeedsSimplePaintInvalidation() {
+    DCHECK(!NeedsNormalPaintInvalidation());
+    paint_invalidation_type_ =
+        static_cast<unsigned>(PaintInvalidationType::kSimple);
+  }
+  void SetNeedsNormalPaintInvalidation() {
+    paint_invalidation_type_ =
+        static_cast<unsigned>(PaintInvalidationType::kNormal);
+  }
 
   bool NeedsLayout() const { return layout_type_ != kNoLayout; }
   void ClearNeedsLayout() { layout_type_ = kNoLayout; }
@@ -198,7 +221,8 @@
   friend CORE_EXPORT std::ostream& operator<<(std::ostream&,
                                               const StyleDifference&);
 
-  unsigned needs_paint_invalidation_ : 1;
+  enum class PaintInvalidationType { kNone, kSimple, kNormal };
+  unsigned paint_invalidation_type_ : 2;
 
   enum LayoutType { kNoLayout = 0, kPositionedMovement, kFullLayout };
   unsigned layout_type_ : 2;
@@ -217,7 +241,7 @@
   // data back again with a large read can cause store-to-load forward
   // stalls). Feel free to take bits from here if you need them
   // for something else.
-  unsigned padding_ [[maybe_unused]] : 13;
+  unsigned padding_ [[maybe_unused]] : 12;
 };
 static_assert(sizeof(StyleDifference) == 4, "Remove some padding bits!");
 
diff --git a/third_party/blink/renderer/core/style/style_difference_test.cc b/third_party/blink/renderer/core/style/style_difference_test.cc
index 3183f22..2f54a312 100644
--- a/third_party/blink/renderer/core/style/style_difference_test.cc
+++ b/third_party/blink/renderer/core/style/style_difference_test.cc
@@ -15,7 +15,7 @@
   string_stream << diff;
   EXPECT_EQ(
       "StyleDifference{layoutType=NoLayout, "
-      "reshape=0, paintInvalidation=0, recomputeVisualOverflow=0, "
+      "reshape=0, paintInvalidationType=None, recomputeVisualOverflow=0, "
       "propertySpecificDifferences=, "
       "scrollAnchorDisablingPropertyChanged=0}",
       string_stream.str());
@@ -24,7 +24,7 @@
 TEST(StyleDifferenceTest, StreamOutputAllFieldsMutated) {
   std::stringstream string_stream;
   StyleDifference diff;
-  diff.SetNeedsPaintInvalidation();
+  diff.SetNeedsNormalPaintInvalidation();
   diff.SetNeedsPositionedMovementLayout();
   diff.SetNeedsReshape();
   diff.SetNeedsRecomputeVisualOverflow();
@@ -34,7 +34,7 @@
   string_stream << diff;
   EXPECT_EQ(
       "StyleDifference{layoutType=PositionedMovement, "
-      "reshape=1, paintInvalidation=1, recomputeVisualOverflow=1, "
+      "reshape=1, paintInvalidationType=Normal, recomputeVisualOverflow=1, "
       "propertySpecificDifferences="
       "TransformPropertyChanged|OtherTransformPropertyChanged, "
       "scrollAnchorDisablingPropertyChanged=1}",
@@ -55,7 +55,7 @@
   string_stream << diff;
   EXPECT_EQ(
       "StyleDifference{layoutType=NoLayout, "
-      "reshape=0, paintInvalidation=0, recomputeVisualOverflow=0, "
+      "reshape=0, paintInvalidationType=None, recomputeVisualOverflow=0, "
       "propertySpecificDifferences=TransformPropertyChanged|"
       "OtherTransformPropertyChanged|OpacityChanged|"
       "ZIndexChanged|FilterChanged|CSSClipChanged|"
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
index eb842caf..869e83c 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -2870,17 +2870,30 @@
 
 bool AXNodeObject::StepValueForRange(float* out_value) const {
   if (IsNativeSlider() || IsNativeSpinButton()) {
-    // AT may want to know whether a step value was explicitly provided or not,
-    // so return false if there was not one set.
-    if (!To<HTMLInputElement>(*GetNode())
-             .FastGetAttribute(html_names::kStepAttr)) {
+    auto step_range =
+        To<HTMLInputElement>(*GetNode()).CreateStepRange(kRejectAny);
+    auto step = step_range.Step().ToString().ToFloat();
+
+    // Provide a step if ATs incrementing slider should move by step, otherwise
+    // AT will move by 5%.
+    // If there are too few allowed stops (< 20), incrementing/decrementing
+    // the slider by 5% could get stuck, and therefore the step is exposed.
+    // The step is also exposed if moving by 5% would cause intermittent
+    // behavior where sometimes the slider would alternate by 1 or 2 steps.
+    // Therefore the final decision is to use the step if there are
+    // less than stops in the slider, otherwise, move by 5%.
+    float max = step_range.Maximum().ToString().ToFloat();
+    float min = step_range.Minimum().ToString().ToFloat();
+    int num_stops = (max - min) / step;
+    constexpr int kNumStopsForFivePercentRule = 40;
+    if (num_stops >= kNumStopsForFivePercentRule) {
+      // No explicit step, and the step is very small -- don't expose a step
+      // so that Talkback will move by 5% increments.
       *out_value = 0.0f;
       return false;
     }
 
-    auto step =
-        To<HTMLInputElement>(*GetNode()).CreateStepRange(kRejectAny).Step();
-    *out_value = step.ToString().ToFloat();
+    *out_value = step;
     return std::isfinite(*out_value);
   }
 
@@ -3152,7 +3165,7 @@
 
 ax::mojom::blink::HasPopup AXNodeObject::HasPopup() const {
   const AtomicString& has_popup =
-      GetAOMPropertyOrARIAAttribute(AOMStringProperty::kHasPopUp);
+      GetAOMPropertyOrARIAAttribute(AOMStringProperty::kHasPopup);
   if (!has_popup.IsNull()) {
     if (EqualIgnoringASCIICase(has_popup, "false"))
       return ax::mojom::blink::HasPopup::kFalse;
@@ -3191,6 +3204,24 @@
   return AXObject::HasPopup();
 }
 
+ax::mojom::blink::IsPopup AXNodeObject::IsPopup() const {
+  if (IsDetached() || !GetElement()) {
+    return ax::mojom::blink::IsPopup::kNone;
+  }
+  const auto* html_element = DynamicTo<HTMLElement>(GetElement());
+  if (!html_element) {
+    return ax::mojom::blink::IsPopup::kNone;
+  }
+  switch (html_element->PopoverType()) {
+    case PopoverValueType::kNone:
+      return ax::mojom::blink::IsPopup::kNone;
+    case PopoverValueType::kAuto:
+      return ax::mojom::blink::IsPopup::kAuto;
+    case PopoverValueType::kManual:
+      return ax::mojom::blink::IsPopup::kManual;
+  }
+}
+
 bool AXNodeObject::IsEditableRoot() const {
   const Node* node = GetNode();
   if (IsDetached() || !node)
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.h b/third_party/blink/renderer/modules/accessibility/ax_node_object.h
index 5d49b69..c74736e8 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.h
@@ -191,6 +191,7 @@
       Vector<ax::mojom::blink::Dropeffect>& dropeffects) const override;
 
   ax::mojom::blink::HasPopup HasPopup() const override;
+  ax::mojom::blink::IsPopup IsPopup() const override;
   bool IsEditableRoot() const override;
   bool HasContentEditableAttributeSet() const override;
 
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index c48b9ae..20a68f2 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -2094,6 +2094,10 @@
     node_data->SetHasPopup(ax::mojom::blink::HasPopup::kListbox);
   }
 
+  if (IsPopup() != ax::mojom::blink::IsPopup::kNone) {
+    node_data->SetIsPopup(IsPopup());
+  }
+
   if (IsAutofillAvailable())
     node_data->AddState(ax::mojom::blink::State::kAutofillAvailable);
 
@@ -4632,6 +4636,10 @@
   return ax::mojom::blink::HasPopup::kFalse;
 }
 
+ax::mojom::blink::IsPopup AXObject::IsPopup() const {
+  return ax::mojom::blink::IsPopup::kNone;
+}
+
 bool AXObject::IsEditable() const {
   const Node* node = GetNode();
   if (IsDetached() || !node)
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h
index f82601e..2a468b6 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -782,6 +782,9 @@
   // autocomplete suggestion.
   virtual ax::mojom::blink::HasPopup HasPopup() const;
 
+  // Determines whether this object is a popup, and what type.
+  virtual ax::mojom::blink::IsPopup IsPopup() const;
+
   // Heuristic to get the listbox for an <input role="combobox">.
   AXObject* GetControlsListboxForTextfieldCombobox();
 
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
index 5d598141..3f7e135 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
+++ b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
@@ -1371,8 +1371,13 @@
     }
 
     if (!web_identity_requester_) {
-      web_identity_requester_ = MakeGarbageCollected<WebIdentityRequester>(
-          WrapPersistent(context), std::move(scoped_abort_state));
+      web_identity_requester_ =
+          MakeGarbageCollected<WebIdentityRequester>(WrapPersistent(context));
+    }
+
+    if (scoped_abort_state) {
+      web_identity_requester_->InsertScopedAbortState(
+          std::move(scoped_abort_state));
     }
 
     web_identity_requester_->AppendGetCall(WrapPersistent(resolver),
diff --git a/third_party/blink/renderer/modules/credentialmanagement/web_identity_requester.cc b/third_party/blink/renderer/modules/credentialmanagement/web_identity_requester.cc
index 8304f91..8b91fa1e 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/web_identity_requester.cc
+++ b/third_party/blink/renderer/modules/credentialmanagement/web_identity_requester.cc
@@ -11,11 +11,8 @@
 
 namespace blink {
 
-WebIdentityRequester::WebIdentityRequester(
-    ExecutionContext* context,
-    std::unique_ptr<ScopedAbortState> scoped_abort_state)
-    : execution_context_(context),
-      scoped_abort_state_(std::move(scoped_abort_state)) {}
+WebIdentityRequester::WebIdentityRequester(ExecutionContext* context)
+    : execution_context_(context) {}
 
 void WebIdentityRequester::OnRequestToken(
     mojom::blink::RequestTokenStatus status,
@@ -138,6 +135,11 @@
   has_posted_task_ = true;
 }
 
+void WebIdentityRequester::InsertScopedAbortState(
+    std::unique_ptr<ScopedAbortState> scoped_abort_state) {
+  scoped_abort_states_.insert(std::move(scoped_abort_state));
+}
+
 void WebIdentityRequester::Trace(Visitor* visitor) const {
   visitor->Trace(execution_context_);
   visitor->Trace(window_onload_event_listener_);
diff --git a/third_party/blink/renderer/modules/credentialmanagement/web_identity_requester.h b/third_party/blink/renderer/modules/credentialmanagement/web_identity_requester.h
index 7212015..381dbb5 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/web_identity_requester.h
+++ b/third_party/blink/renderer/modules/credentialmanagement/web_identity_requester.h
@@ -22,9 +22,7 @@
 class WebIdentityRequester final
     : public GarbageCollected<WebIdentityRequester> {
  public:
-  explicit WebIdentityRequester(
-      ExecutionContext* context,
-      std::unique_ptr<ScopedAbortState> scoped_abort_state);
+  explicit WebIdentityRequester(ExecutionContext* context);
 
   void OnRequestToken(mojom::blink::RequestTokenStatus status,
                       const absl::optional<KURL>& selected_idp_config_url,
@@ -37,6 +35,8 @@
       const HeapVector<Member<IdentityProviderConfig>>& providers,
       bool prefer_auto_sign_in,
       mojom::blink::RpContext rp_context);
+  void InsertScopedAbortState(
+      std::unique_ptr<ScopedAbortState> scoped_abort_state);
   void Trace(Visitor* visitor) const;
 
  private:
@@ -47,7 +47,7 @@
   // array of IDPs in FederatedAuthRequestImpl::RequestToken.
   Vector<mojom::blink::IdentityProviderGetParametersPtr> idp_get_params_;
   Member<ExecutionContext> execution_context_;
-  std::unique_ptr<ScopedAbortState> scoped_abort_state_;
+  HashSet<std::unique_ptr<ScopedAbortState>> scoped_abort_states_;
   Member<WebIdentityWindowOnloadEventListener> window_onload_event_listener_;
   HeapHashMap<KURL, Member<ScriptPromiseResolver>> provider_to_resolver_;
   bool is_requesting_token_{false};
diff --git a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc
index b3f6bbd..1796e92a 100644
--- a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc
+++ b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc
@@ -124,7 +124,7 @@
   // Use a fake but valid viz::SurfaceId.
   return {viz::FrameSinkId(1, 1),
           viz::LocalSurfaceId(
-              11, base::UnguessableToken::Deserialize(0x111111, 0))};
+              11, base::UnguessableToken::CreateForTesting(0x111111, 0))};
 }
 
 // The MockPictureInPictureSession implements a PictureInPicture session in the
diff --git a/third_party/blink/renderer/modules/media/audio/audio_output_ipc_factory_test.cc b/third_party/blink/renderer/modules/media/audio/audio_output_ipc_factory_test.cc
index 9c3dbf8..e295688 100644
--- a/third_party/blink/renderer/modules/media/audio/audio_output_ipc_factory_test.cc
+++ b/third_party/blink/renderer/modules/media/audio/audio_output_ipc_factory_test.cc
@@ -33,7 +33,7 @@
 
 blink::LocalFrameToken TokenFromInt(int i) {
   static base::UnguessableToken base_token = base::UnguessableToken::Create();
-  return blink::LocalFrameToken(base::UnguessableToken::Deserialize(
+  return blink::LocalFrameToken(base::UnguessableToken::CreateForTesting(
       base_token.GetHighForSerialization() + i,
       base_token.GetLowForSerialization() + i));
 }
diff --git a/third_party/blink/renderer/modules/media/audio/mojo_audio_input_ipc_test.cc b/third_party/blink/renderer/modules/media/audio/mojo_audio_input_ipc_test.cc
index 7be2cb6..c2470f8 100644
--- a/third_party/blink/renderer/modules/media/audio/mojo_audio_input_ipc_test.cc
+++ b/third_party/blink/renderer/modules/media/audio/mojo_audio_input_ipc_test.cc
@@ -49,12 +49,12 @@
 
 media::AudioSourceParameters SourceParams() {
   return media::AudioSourceParameters(
-      base::UnguessableToken::Deserialize(1234, 5678));
+      base::UnguessableToken::CreateForTesting(1234, 5678));
 }
 
 media::AudioSourceParameters SourceParamsWithProcessing() {
   media::AudioSourceParameters params(
-      base::UnguessableToken::Deserialize(1234, 5678));
+      base::UnguessableToken::CreateForTesting(1234, 5678));
   params.processing = media::AudioProcessingSettings();
   return params;
 }
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_test.cc b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_test.cc
index db9dd170..c3e1479 100644
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_test.cc
@@ -76,8 +76,9 @@
   MOCK_METHOD0(UnregisterFrameSinkHierarchy, void());
 
   viz::FrameSinkId frame_sink_id_ = viz::FrameSinkId(1, 1);
-  viz::LocalSurfaceId local_surface_id_ =
-      viz::LocalSurfaceId(11, base::UnguessableToken::Deserialize(0x111111, 0));
+  viz::LocalSurfaceId local_surface_id_ = viz::LocalSurfaceId(
+      11,
+      base::UnguessableToken::CreateForTesting(0x111111, 0));
   viz::SurfaceId surface_id_ =
       viz::SurfaceId(frame_sink_id_, local_surface_id_);
 };
diff --git a/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc b/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
index 1790527..b522e93f 100644
--- a/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
+++ b/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
@@ -218,8 +218,7 @@
   return new_parkable;
 }
 
-void ParkableStringManager::RemoveOnMainThread(
-    MayBeDangling<ParkableStringImpl> string) {
+void ParkableStringManager::RemoveOnMainThread(ParkableStringImpl* string) {
   DCHECK(IsMainThread());
   DCHECK(string->may_be_parked());
   DCHECK(string->digest());
@@ -262,7 +261,7 @@
   task_runner_->PostTask(
       FROM_HERE,
       base::BindOnce(&ParkableStringManager::RemoveOnMainThread,
-                     base::Unretained(this), base::UnsafeDangling(string)));
+                     base::Unretained(this), base::Unretained(string)));
 }
 
 void ParkableStringManager::CompleteUnparkOnMainThread(
diff --git a/third_party/blink/renderer/platform/bindings/parkable_string_manager.h b/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
index efe0ef9..ce9c3b8 100644
--- a/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
+++ b/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
@@ -107,7 +107,7 @@
       scoped_refptr<StringImpl>&&,
       std::unique_ptr<ParkableStringImpl::SecureDigest> digest);
 
-  void RemoveOnMainThread(MayBeDangling<ParkableStringImpl> string);
+  void RemoveOnMainThread(ParkableStringImpl* string);
   // If on a background thread, posts a `RemoveOnMainThread` task to the Main
   // thread. Calls `RemoveOnMainThread` otherwise.
   void Remove(ParkableStringImpl* string);
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
index 0d4895a0..745407c2 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
@@ -11,6 +11,8 @@
 #include "cc/paint/paint_filter.h"
 #include "cc/paint/paint_flags.h"
 #include "cc/paint/paint_op_buffer_iterator.h"
+#include "cc/paint/render_surface_filters.h"
+#include "cc/test/paint_op_matchers.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h"
@@ -27,134 +29,18 @@
 #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
 #include "ui/gfx/geometry/skia_conversions.h"
 
-void PrintTo(const Vector<cc::PaintOpType>& ops, std::ostream* os) {
-  *os << "[";
-  bool first = true;
-  for (auto op : ops) {
-    if (first)
-      first = false;
-    else
-      *os << ", ";
-    *os << op;
-  }
-  *os << "]";
-}
-
-void PrintTo(const cc::PaintRecord& record, std::ostream* os) {
-  Vector<cc::PaintOpType> ops;
-  for (const cc::PaintOp& op : record)
-    ops.push_back(op.GetType());
-  PrintTo(ops, os);
-}
-
-void PrintTo(const SkRect& rect, std::ostream* os) {
-  *os << (cc::PaintOp::IsUnsetRect(rect) ? "(unset)"
-                                         : gfx::SkRectToRectF(rect).ToString());
-}
-
 namespace blink {
 namespace {
 
+using ::cc::PaintOpEq;
+using ::cc::PaintOpIs;
+using ::testing::ElementsAre;
+
 class PaintChunksToCcLayerTest : public testing::Test,
                                  public PaintTestConfigurations {};
 
 INSTANTIATE_PAINT_TEST_SUITE_P(PaintChunksToCcLayerTest);
 
-// Matches PaintOpTypes in a PaintRecord.
-class PaintRecordMatcher
-    : public testing::MatcherInterface<const cc::PaintRecord&> {
- public:
-  static testing::Matcher<const cc::PaintRecord&> Make(
-      std::initializer_list<cc::PaintOpType> args) {
-    return testing::MakeMatcher(new PaintRecordMatcher(args));
-  }
-  PaintRecordMatcher(std::initializer_list<cc::PaintOpType> args)
-      : expected_ops_(args) {}
-
-  bool MatchAndExplain(const cc::PaintRecord& record,
-                       testing::MatchResultListener* listener) const override {
-    size_t index = 0;
-    for (const cc::PaintOp& op : record) {
-      cc::PaintOpType op_type = op.GetType();
-      if (index < expected_ops_.size() && expected_ops_[index] == op_type) {
-        ++index;
-        continue;
-      }
-
-      if (listener->IsInterested()) {
-        *listener << "unexpected op " << op_type << " at index " << index
-                  << ",";
-        if (index < expected_ops_.size())
-          *listener << " expecting " << expected_ops_[index] << ".";
-        else
-          *listener << " expecting end of list.";
-      }
-      return false;
-    }
-    if (index == expected_ops_.size())
-      return true;
-    if (listener->IsInterested()) {
-      *listener << "unexpected end of list, expecting " << expected_ops_[index]
-                << " at index " << index << ".";
-    }
-    return false;
-  }
-
-  void DescribeTo(::std::ostream* os) const override {
-    PrintTo(expected_ops_, os);
-  }
-
- private:
-  Vector<cc::PaintOpType> expected_ops_;
-};
-
-#define EXPECT_EFFECT_BOUNDS(x, y, width, height, op_buffer, index)         \
-  do {                                                                      \
-    SkRect bounds;                                                          \
-    if (const auto* save_layer_alpha =                                      \
-            (op_buffer).GetOpAtForTesting<cc::SaveLayerAlphaOp>(index)) {   \
-      bounds = save_layer_alpha->bounds;                                    \
-    } else if (const auto* save_layer =                                     \
-                   (op_buffer).GetOpAtForTesting<cc::SaveLayerOp>(index)) { \
-      bounds = save_layer->bounds;                                          \
-    } else {                                                                \
-      FAIL() << "No SaveLayer[Alpha]Op at " << index;                       \
-    }                                                                       \
-    EXPECT_EQ(SkRect::MakeXYWH(x, y, width, height), bounds);               \
-  } while (false)
-
-#define EXPECT_TRANSFORM_MATRIX(transform, op_buffer, index)                 \
-  do {                                                                       \
-    const auto* concat = (op_buffer).GetOpAtForTesting<cc::ConcatOp>(index); \
-    ASSERT_NE(nullptr, concat);                                              \
-    EXPECT_EQ(gfx::TransformToSkM44(transform), concat->matrix);             \
-  } while (false)
-
-#define EXPECT_TRANSLATE(x, y, op_buffer, index)               \
-  do {                                                         \
-    const auto* translate =                                    \
-        (op_buffer).GetOpAtForTesting<cc::TranslateOp>(index); \
-    ASSERT_NE(nullptr, translate);                             \
-    EXPECT_EQ(x, translate->dx);                               \
-    EXPECT_EQ(y, translate->dy);                               \
-  } while (false)
-
-#define EXPECT_CLIP(r, op_buffer, index)                      \
-  do {                                                        \
-    const auto* clip_op =                                     \
-        (op_buffer).GetOpAtForTesting<cc::ClipRectOp>(index); \
-    ASSERT_NE(nullptr, clip_op);                              \
-    EXPECT_EQ(gfx::RectFToSkRect(r), clip_op->rect);          \
-  } while (false)
-
-#define EXPECT_ROUNDED_CLIP(r, op_buffer, index)               \
-  do {                                                         \
-    const auto* clip_op =                                      \
-        (op_buffer).GetOpAtForTesting<cc::ClipRRectOp>(index); \
-    ASSERT_NE(nullptr, clip_op);                               \
-    EXPECT_EQ(SkRRect(r), clip_op->rrect);                     \
-  } while (false)
-
 const DisplayItemClient& DefaultClient() {
   DEFINE_STATIC_LOCAL(
       Persistent<FakeDisplayItemClient>, fake_client,
@@ -237,11 +123,11 @@
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   EXPECT_THAT(
       output,
-      PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e1>
-                                cc::PaintOpType::DrawRecord,      // <p0/>
-                                cc::PaintOpType::DrawRecord,      // <p1/>
-                                cc::PaintOpType::Restore}));      // </e1>
-  EXPECT_EFFECT_BOUNDS(0, 0, 90, 90, output, 0);
+      ElementsAre(PaintOpEq(cc::SaveLayerAlphaOp(SkRect::MakeXYWH(0, 0, 90, 90),
+                                                 127 / 255.f)),  // <e1>
+                  PaintOpIs<cc::DrawRecordOp>(),                 // <p0/>
+                  PaintOpIs<cc::DrawRecordOp>(),                 // <p1/>
+                  PaintOpIs<cc::RestoreOp>()));                  // </e1>
 }
 
 TEST_P(PaintChunksToCcLayerTest, EffectGroupingNested) {
@@ -257,17 +143,18 @@
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   EXPECT_THAT(
       output,
-      PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e1>
-                                cc::PaintOpType::SaveLayerAlpha,  // <e2>
-                                cc::PaintOpType::DrawRecord,      // <p0/>
-                                cc::PaintOpType::Restore,         // </e2>
-                                cc::PaintOpType::SaveLayerAlpha,  // <e3>
-                                cc::PaintOpType::DrawRecord,      // <p1/>
-                                cc::PaintOpType::Restore,         // </e3>
-                                cc::PaintOpType::Restore}));      // </e1>
-  EXPECT_EFFECT_BOUNDS(0, 0, 444, 666, output, 0);
-  EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, output, 1);
-  EXPECT_EFFECT_BOUNDS(111, 222, 333, 444, output, 4);
+      ElementsAre(
+          PaintOpEq(cc::SaveLayerAlphaOp(SkRect::MakeXYWH(0, 0, 444, 666),
+                                         127 / 255.f)),  // <e1>
+          PaintOpEq(cc::SaveLayerAlphaOp(SkRect::MakeXYWH(0, 0, 100, 100),
+                                         127 / 255.f)),  // <e2>
+          PaintOpIs<cc::DrawRecordOp>(),                 // <p0/>
+          PaintOpIs<cc::RestoreOp>(),                    // </e2>
+          PaintOpEq(cc::SaveLayerAlphaOp(SkRect::MakeXYWH(111, 222, 333, 444),
+                                         127 / 255.f)),  // <e3>
+          PaintOpIs<cc::DrawRecordOp>(),                 // <p1/>
+          PaintOpIs<cc::RestoreOp>(),                    // </e3>
+          PaintOpIs<cc::RestoreOp>()));                  // </e1>
 }
 
 TEST_P(PaintChunksToCcLayerTest, EffectFilterGroupingNestedWithTransforms) {
@@ -285,27 +172,32 @@
 
   PaintRecord output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
+
+  cc::PaintFlags expected_flags;
+  expected_flags.setImageFilter(cc::RenderSurfaceFilters::BuildImageFilter(
+      filter.AsCcFilterOperations(), gfx::SizeF()));
   EXPECT_THAT(
       output,
-      PaintRecordMatcher::Make(
-          {cc::PaintOpType::Save, cc::PaintOpType::Concat,     // <t1*t2>
-           cc::PaintOpType::SaveLayerAlpha,                    // <e1>
-           cc::PaintOpType::DrawRecord,                        // <p1/>
-           cc::PaintOpType::SaveLayer,                         // <e2>
-           cc::PaintOpType::Save, cc::PaintOpType::Translate,  // <t2^-1>
-           cc::PaintOpType::DrawRecord,                        // <p2/>
-           cc::PaintOpType::Restore,                           // </t2^-1>
-           cc::PaintOpType::Restore,                           // </e2>
-           cc::PaintOpType::Restore,                           // </e1>
-           cc::PaintOpType::Restore}));                        // </t1*t2>
-  EXPECT_TRANSFORM_MATRIX(t1->Matrix() * t2->Matrix(), output, 1);
-  // chunk1.bounds + e2(t2^-1(chunk2.bounds))
-  EXPECT_EFFECT_BOUNDS(0, 0, 155, 155, output, 2);
-  // t2^-1(chunk2.bounds)
-  EXPECT_EFFECT_BOUNDS(70, 70, 70, 70, output, 4);
-  // t2^1
-  EXPECT_TRANSLATE(-t2->Get2dTranslation().x(), -t2->Get2dTranslation().y(),
-                   output, 6);
+      ElementsAre(
+          PaintOpIs<cc::SaveOp>(),
+          PaintOpEq(cc::ConcatOp(
+              gfx::TransformToSkM44(t1->Matrix() * t2->Matrix()))),  // <t1*t2>
+          // chunk1.bounds + e2(t2^-1(chunk2.bounds))
+          PaintOpEq(cc::SaveLayerAlphaOp(SkRect::MakeXYWH(0, 0, 155, 155),
+                                         127 / 255.f)),  // <e1>
+          PaintOpIs<cc::DrawRecordOp>(),                 // <p1/>
+          // t2^-1(chunk2.bounds)
+          PaintOpEq(cc::SaveLayerOp(SkRect::MakeXYWH(70, 70, 70, 70),
+                                    expected_flags)),  // <e2>
+          PaintOpIs<cc::SaveOp>(),
+          // t2^1
+          PaintOpEq(cc::TranslateOp(-t2->Get2dTranslation().x(),
+                                    -t2->Get2dTranslation().y())),  // <t2^-1>
+          PaintOpIs<cc::DrawRecordOp>(),                            // <p2/>
+          PaintOpIs<cc::RestoreOp>(),                               // </t2^-1>
+          PaintOpIs<cc::RestoreOp>(),                               // </e2>
+          PaintOpIs<cc::RestoreOp>(),                               // </e1>
+          PaintOpIs<cc::RestoreOp>()));                             // </t1*t2>
 }
 
 TEST_P(PaintChunksToCcLayerTest, InterleavedClipEffect) {
@@ -329,33 +221,34 @@
 
   PaintRecord output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
-  EXPECT_THAT(output, PaintRecordMatcher::Make(
-                          {cc::PaintOpType::Save,
-                           cc::PaintOpType::ClipRect,    // <c1+c2>
-                           cc::PaintOpType::DrawRecord,  // <p0/>
-                           cc::PaintOpType::Save,
-                           cc::PaintOpType::ClipRect,        // <c3>
-                           cc::PaintOpType::DrawRecord,      // <p1/>
-                           cc::PaintOpType::Restore,         // </c3>
-                           cc::PaintOpType::SaveLayerAlpha,  // <e1>
-                           cc::PaintOpType::Save,
-                           cc::PaintOpType::ClipRect,        // <c3+c4>
-                           cc::PaintOpType::SaveLayerAlpha,  // <e2>
-                           cc::PaintOpType::DrawRecord,      // <p2/>
-                           cc::PaintOpType::Restore,         // </e2>
-                           cc::PaintOpType::Restore,         // </c3+c4>
-                           cc::PaintOpType::Save,
-                           cc::PaintOpType::ClipRect,    // <c3>
-                           cc::PaintOpType::DrawRecord,  // <p3/>
-                           cc::PaintOpType::Restore,     // </c3>
-                           cc::PaintOpType::Restore,     // </e1>
-                           cc::PaintOpType::Save,
-                           cc::PaintOpType::ClipRect,    // <c3+c4>
-                           cc::PaintOpType::DrawRecord,  // <p4/>
-                           cc::PaintOpType::Restore,     // </c3+c4>
-                           cc::PaintOpType::Restore}));  // </c1+c2>
-  EXPECT_EFFECT_BOUNDS(0, 0, 90, 90, output, 7);
-  EXPECT_EFFECT_BOUNDS(0, 0, 50, 50, output, 10);
+  EXPECT_THAT(
+      output,
+      ElementsAre(PaintOpIs<cc::SaveOp>(),
+                  PaintOpIs<cc::ClipRectOp>(),    // <c1+c2>
+                  PaintOpIs<cc::DrawRecordOp>(),  // <p0/>
+                  PaintOpIs<cc::SaveOp>(),
+                  PaintOpIs<cc::ClipRectOp>(),    // <c3>
+                  PaintOpIs<cc::DrawRecordOp>(),  // <p1/>
+                  PaintOpIs<cc::RestoreOp>(),     // </c3>
+                  PaintOpEq(cc::SaveLayerAlphaOp(SkRect::MakeXYWH(0, 0, 90, 90),
+                                                 127 / 255.f)),  // <e1>
+                  PaintOpIs<cc::SaveOp>(),
+                  PaintOpIs<cc::ClipRectOp>(),  // <c3+c4>
+                  PaintOpEq(cc::SaveLayerAlphaOp(SkRect::MakeXYWH(0, 0, 50, 50),
+                                                 127 / 255.f)),  // <e2>
+                  PaintOpIs<cc::DrawRecordOp>(),                 // <p2/>
+                  PaintOpIs<cc::RestoreOp>(),                    // </e2>
+                  PaintOpIs<cc::RestoreOp>(),                    // </c3+c4>
+                  PaintOpIs<cc::SaveOp>(),
+                  PaintOpIs<cc::ClipRectOp>(),    // <c3>
+                  PaintOpIs<cc::DrawRecordOp>(),  // <p3/>
+                  PaintOpIs<cc::RestoreOp>(),     // </c3>
+                  PaintOpIs<cc::RestoreOp>(),     // </e1>
+                  PaintOpIs<cc::SaveOp>(),
+                  PaintOpIs<cc::ClipRectOp>(),    // <c3+c4>
+                  PaintOpIs<cc::DrawRecordOp>(),  // <p4/>
+                  PaintOpIs<cc::RestoreOp>(),     // </c3+c4>
+                  PaintOpIs<cc::RestoreOp>()));   // </c1+c2>
 }
 
 TEST_P(PaintChunksToCcLayerTest, ClipSpaceInversion) {
@@ -371,14 +264,14 @@
 
   PaintRecord output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
-  EXPECT_THAT(output,
-              PaintRecordMatcher::Make(
-                  {cc::PaintOpType::Save, cc::PaintOpType::Concat,  // <t1
-                   cc::PaintOpType::ClipRect,                       //  c1>
-                   cc::PaintOpType::Save, cc::PaintOpType::Concat,  // <t1^-1>
-                   cc::PaintOpType::DrawRecord,                     // <p0/>
-                   cc::PaintOpType::Restore,                        // </t1^-1>
-                   cc::PaintOpType::Restore}));                     // </c1 t1>
+  EXPECT_THAT(output, ElementsAre(PaintOpIs<cc::SaveOp>(),
+                                  PaintOpIs<cc::ConcatOp>(),    // <t1
+                                  PaintOpIs<cc::ClipRectOp>(),  //  c1>
+                                  PaintOpIs<cc::SaveOp>(),
+                                  PaintOpIs<cc::ConcatOp>(),      // <t1^-1>
+                                  PaintOpIs<cc::DrawRecordOp>(),  // <p0/>
+                                  PaintOpIs<cc::RestoreOp>(),     // </t1^-1>
+                                  PaintOpIs<cc::RestoreOp>()));   // </c1 t1>
 }
 
 TEST_P(PaintChunksToCcLayerTest, OpacityEffectSpaceInversion) {
@@ -397,19 +290,21 @@
 
   PaintRecord output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
-  EXPECT_THAT(output,
-              PaintRecordMatcher::Make(
-                  {cc::PaintOpType::Save, cc::PaintOpType::Concat,  // <t1>
-                   cc::PaintOpType::SaveLayerAlpha,                 // <e1>
-                   cc::PaintOpType::Save, cc::PaintOpType::Concat,  // <t1^-1>
-                   cc::PaintOpType::DrawRecord,                     // <p0/>
-                   cc::PaintOpType::Restore,                        // </t1^-1>
-                   cc::PaintOpType::DrawRecord,                     // <p1/>
-                   cc::PaintOpType::Restore,                        // </e1>
-                   cc::PaintOpType::Restore}));                     // </t1>
-  EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, output, 2);
-  EXPECT_TRANSFORM_MATRIX(t1->Matrix(), output, 1);
-  EXPECT_TRANSFORM_MATRIX(t1->Matrix().GetCheckedInverse(), output, 4);
+  EXPECT_THAT(
+      output,
+      ElementsAre(
+          PaintOpIs<cc::SaveOp>(),
+          PaintOpEq(cc::ConcatOp(gfx::TransformToSkM44(t1->Matrix()))),  // <t1>
+          PaintOpEq(cc::SaveLayerAlphaOp(SkRect::MakeXYWH(0, 0, 100, 100),
+                                         127 / 255.f)),  // <e1>
+          PaintOpIs<cc::SaveOp>(),
+          PaintOpEq(cc::ConcatOp(gfx::TransformToSkM44(
+              t1->Matrix().GetCheckedInverse()))),  // <t1^-1>
+          PaintOpIs<cc::DrawRecordOp>(),            // <p0/>
+          PaintOpIs<cc::RestoreOp>(),               // </t1^-1>
+          PaintOpIs<cc::DrawRecordOp>(),            // <p1/>
+          PaintOpIs<cc::RestoreOp>(),               // </e1>
+          PaintOpIs<cc::RestoreOp>()));             // </t1>
 }
 
 TEST_P(PaintChunksToCcLayerTest, FilterEffectSpaceInversion) {
@@ -429,18 +324,24 @@
 
   auto output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
-  EXPECT_THAT(output,
-              PaintRecordMatcher::Make(
-                  {cc::PaintOpType::Save, cc::PaintOpType::Concat,  // <t1>
-                   cc::PaintOpType::SaveLayer,                      // <e1>
-                   cc::PaintOpType::Save, cc::PaintOpType::Concat,  // <t1^-1>
-                   cc::PaintOpType::DrawRecord,                     // <p0/>
-                   cc::PaintOpType::Restore,                        // </t1^-1>
-                   cc::PaintOpType::Restore,                        // </e1>
-                   cc::PaintOpType::Restore}));                     // </t1>
-  EXPECT_TRANSFORM_MATRIX(t1->Matrix(), output, 1);
-  EXPECT_EFFECT_BOUNDS(0, 0, 50, 50, output, 2);
-  EXPECT_TRANSFORM_MATRIX(t1->Matrix().GetCheckedInverse(), output, 4);
+
+  cc::PaintFlags expected_flags;
+  expected_flags.setImageFilter(cc::RenderSurfaceFilters::BuildImageFilter(
+      filter.AsCcFilterOperations(), gfx::SizeF()));
+  EXPECT_THAT(
+      output,
+      ElementsAre(
+          PaintOpIs<cc::SaveOp>(),
+          PaintOpEq(cc::ConcatOp(gfx::TransformToSkM44(t1->Matrix()))),  // <t1>
+          PaintOpEq(cc::SaveLayerOp(SkRect::MakeXYWH(0, 0, 50, 50),
+                                    expected_flags)),  // <e1>
+          PaintOpIs<cc::SaveOp>(),
+          PaintOpEq(cc::ConcatOp(gfx::TransformToSkM44(
+              t1->Matrix().GetCheckedInverse()))),  // <t1^-1>
+          PaintOpIs<cc::DrawRecordOp>(),            // <p0/>
+          PaintOpIs<cc::RestoreOp>(),               // </t1^-1>
+          PaintOpIs<cc::RestoreOp>(),               // </e1>
+          PaintOpIs<cc::RestoreOp>()));             // </t1>
 }
 
 TEST_P(PaintChunksToCcLayerTest, NonRootLayerSimple) {
@@ -454,7 +355,7 @@
 
   PaintRecord output = PaintChunksToCcLayer::Convert(
       chunks.Build(), PropertyTreeState(*t1, *c1, *e1));
-  EXPECT_THAT(output, PaintRecordMatcher::Make({cc::PaintOpType::DrawRecord}));
+  EXPECT_THAT(output, ElementsAre(PaintOpIs<cc::DrawRecordOp>()));
 }
 
 TEST_P(PaintChunksToCcLayerTest, NonRootLayerTransformEscape) {
@@ -468,11 +369,10 @@
 
   PaintRecord output = PaintChunksToCcLayer::Convert(
       chunks.Build(), PropertyTreeState(*t1, *c1, *e1));
-  EXPECT_THAT(output,
-              PaintRecordMatcher::Make(
-                  {cc::PaintOpType::Save, cc::PaintOpType::Concat,  // <t1^-1>
-                   cc::PaintOpType::DrawRecord,                     // <p0/>
-                   cc::PaintOpType::Restore}));                     // </t1^-1>
+  EXPECT_THAT(output, ElementsAre(PaintOpIs<cc::SaveOp>(),
+                                  PaintOpIs<cc::ConcatOp>(),      // <t1^-1>
+                                  PaintOpIs<cc::DrawRecordOp>(),  // <p0/>
+                                  PaintOpIs<cc::RestoreOp>()));   // </t1^-1>
 }
 
 TEST_P(PaintChunksToCcLayerTest, EffectWithNoOutputClip) {
@@ -486,15 +386,14 @@
 
   PaintRecord output = PaintChunksToCcLayer::Convert(
       chunks.Build(), PropertyTreeState(t0(), *c1, e0()));
-  EXPECT_THAT(
-      output,
-      PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e1>
-                                cc::PaintOpType::Save,
-                                cc::PaintOpType::ClipRect,    // <c2>
-                                cc::PaintOpType::DrawRecord,  // <p0/>
-                                cc::PaintOpType::Restore,     // </c2>
-                                cc::PaintOpType::Restore}));  // </e1>
-  EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, output, 0);
+  EXPECT_THAT(output, ElementsAre(PaintOpEq(cc::SaveLayerAlphaOp(
+                                      SkRect::MakeXYWH(0, 0, 100, 100),
+                                      127 / 255.f)),  // <e1>
+                                  PaintOpIs<cc::SaveOp>(),
+                                  PaintOpIs<cc::ClipRectOp>(),    // <c2>
+                                  PaintOpIs<cc::DrawRecordOp>(),  // <p0/>
+                                  PaintOpIs<cc::RestoreOp>(),     // </c2>
+                                  PaintOpIs<cc::RestoreOp>()));   // </e1>
 }
 
 TEST_P(PaintChunksToCcLayerTest,
@@ -510,16 +409,17 @@
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   EXPECT_THAT(
       output,
-      PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e1>
-                                cc::PaintOpType::SaveLayerAlpha,  // <e2>
-                                cc::PaintOpType::Save,
-                                cc::PaintOpType::ClipRect,    // <c1>
-                                cc::PaintOpType::DrawRecord,  // <p0/>
-                                cc::PaintOpType::Restore,     // </c1>
-                                cc::PaintOpType::Restore,     // </e2>
-                                cc::PaintOpType::Restore}));  // </e1>
-  EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, output, 0);
-  EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, output, 1);
+      ElementsAre(
+          PaintOpEq(cc::SaveLayerAlphaOp(SkRect::MakeXYWH(0, 0, 100, 100),
+                                         127 / 255.f)),  // <e1>
+          PaintOpEq(cc::SaveLayerAlphaOp(SkRect::MakeXYWH(0, 0, 100, 100),
+                                         127 / 255.f)),  // <e2>
+          PaintOpIs<cc::SaveOp>(),
+          PaintOpIs<cc::ClipRectOp>(),    // <c1>
+          PaintOpIs<cc::DrawRecordOp>(),  // <p0/>
+          PaintOpIs<cc::RestoreOp>(),     // </c1>
+          PaintOpIs<cc::RestoreOp>(),     // </e2>
+          PaintOpIs<cc::RestoreOp>()));   // </e1>
 }
 
 TEST_P(PaintChunksToCcLayerTest,
@@ -533,15 +433,14 @@
 
   PaintRecord output = PaintChunksToCcLayer::Convert(
       chunks.Build(), PropertyTreeState(t0(), c0(), *e1));
-  EXPECT_THAT(
-      output,
-      PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e2>
-                                cc::PaintOpType::Save,
-                                cc::PaintOpType::ClipRect,    // <c1>
-                                cc::PaintOpType::DrawRecord,  // <p0/>
-                                cc::PaintOpType::Restore,     // </c1>
-                                cc::PaintOpType::Restore}));  // </e2>
-  EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, output, 0);
+  EXPECT_THAT(output, ElementsAre(PaintOpEq(cc::SaveLayerAlphaOp(
+                                      SkRect::MakeXYWH(0, 0, 100, 100),
+                                      127 / 255.f)),  // <e2>
+                                  PaintOpIs<cc::SaveOp>(),
+                                  PaintOpIs<cc::ClipRectOp>(),    // <c1>
+                                  PaintOpIs<cc::DrawRecordOp>(),  // <p0/>
+                                  PaintOpIs<cc::RestoreOp>(),     // </c1>
+                                  PaintOpIs<cc::RestoreOp>()));   // </e2>
 }
 
 TEST_P(PaintChunksToCcLayerTest,
@@ -555,12 +454,11 @@
 
   PaintRecord output = PaintChunksToCcLayer::Convert(
       chunks.Build(), PropertyTreeState(t0(), *c1, *e1));
-  EXPECT_THAT(
-      output,
-      PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e2>
-                                cc::PaintOpType::DrawRecord,      // <p0/>
-                                cc::PaintOpType::Restore}));      // </e2>
-  EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, output, 0);
+  EXPECT_THAT(output, ElementsAre(PaintOpEq(cc::SaveLayerAlphaOp(
+                                      SkRect::MakeXYWH(0, 0, 100, 100),
+                                      127 / 255.f)),              // <e2>
+                                  PaintOpIs<cc::DrawRecordOp>(),  // <p0/>
+                                  PaintOpIs<cc::RestoreOp>()));   // </e2>
 }
 
 TEST_P(PaintChunksToCcLayerTest, VisualRect) {
@@ -577,14 +475,13 @@
   EXPECT_EQ(gfx::Rect(-50, -100, 100, 100), cc_list->VisualRectForTesting(4));
 
   EXPECT_THAT(cc_list->FinalizeAndReleaseAsRecord(),
-              PaintRecordMatcher::Make(
-                  {cc::PaintOpType::Save,        //
-                   cc::PaintOpType::Translate,   // <layer_offset>
-                   cc::PaintOpType::Save,        //
-                   cc::PaintOpType::Translate,   // <layer_transform>
-                   cc::PaintOpType::DrawRecord,  // <p0/>
-                   cc::PaintOpType::Restore,     // </layer_transform>
-                   cc::PaintOpType::Restore}));  // </layer_offset>
+              ElementsAre(PaintOpIs<cc::SaveOp>(),        //
+                          PaintOpIs<cc::TranslateOp>(),   // <layer_offset>
+                          PaintOpIs<cc::SaveOp>(),        //
+                          PaintOpIs<cc::TranslateOp>(),   // <layer_transform>
+                          PaintOpIs<cc::DrawRecordOp>(),  // <p0/>
+                          PaintOpIs<cc::RestoreOp>(),     // </layer_transform>
+                          PaintOpIs<cc::RestoreOp>()));   // </layer_offset>
 }
 
 TEST_P(PaintChunksToCcLayerTest, NoncompositedClipPath) {
@@ -595,13 +492,12 @@
   auto output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
-  EXPECT_THAT(
-      output,
-      PaintRecordMatcher::Make({cc::PaintOpType::Save,        //
-                                cc::PaintOpType::ClipRect,    //
-                                cc::PaintOpType::ClipPath,    // <clip_path>
-                                cc::PaintOpType::DrawRecord,  // <p0/>
-                                cc::PaintOpType::Restore}));  // </clip_path>
+  EXPECT_THAT(output,
+              ElementsAre(PaintOpIs<cc::SaveOp>(),        //
+                          PaintOpIs<cc::ClipRectOp>(),    //
+                          PaintOpIs<cc::ClipPathOp>(),    // <clip_path>
+                          PaintOpIs<cc::DrawRecordOp>(),  // <p0/>
+                          PaintOpIs<cc::RestoreOp>()));   // </clip_path>
 }
 
 TEST_P(PaintChunksToCcLayerTest, EmptyClipsAreElided) {
@@ -622,12 +518,11 @@
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   // Note that c1 and c1c2 are elided.
-  EXPECT_THAT(output, PaintRecordMatcher::Make({
-                          cc::PaintOpType::Save,        //
-                          cc::PaintOpType::ClipRect,    // <c2>
-                          cc::PaintOpType::DrawRecord,  // D1
-                          cc::PaintOpType::Restore,     // </c2>
-                      }));
+  EXPECT_THAT(output, ElementsAre(PaintOpIs<cc::SaveOp>(),        //
+                                  PaintOpIs<cc::ClipRectOp>(),    // <c2>
+                                  PaintOpIs<cc::DrawRecordOp>(),  // D1
+                                  PaintOpIs<cc::RestoreOp>()      // </c2>
+                                  ));
 }
 
 TEST_P(PaintChunksToCcLayerTest, NonEmptyClipsAreStored) {
@@ -648,15 +543,15 @@
   PaintRecord output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
-  EXPECT_THAT(output,
-              PaintRecordMatcher::Make({
-                  cc::PaintOpType::Save, cc::PaintOpType::ClipRect,  // <c1+c2>
-                  cc::PaintOpType::DrawRecord,                       // D1
-                  cc::PaintOpType::Restore,                          // </c1+c2>
-                  cc::PaintOpType::Save, cc::PaintOpType::ClipRect,  // <c2>
-                  cc::PaintOpType::DrawRecord,                       // D2
-                  cc::PaintOpType::Restore,                          // </c2>
-              }));
+  EXPECT_THAT(output, ElementsAre(PaintOpIs<cc::SaveOp>(),
+                                  PaintOpIs<cc::ClipRectOp>(),    // <c1+c2>
+                                  PaintOpIs<cc::DrawRecordOp>(),  // D1
+                                  PaintOpIs<cc::RestoreOp>(),     // </c1+c2>
+                                  PaintOpIs<cc::SaveOp>(),
+                                  PaintOpIs<cc::ClipRectOp>(),    // <c2>
+                                  PaintOpIs<cc::DrawRecordOp>(),  // D2
+                                  PaintOpIs<cc::RestoreOp>()      // </c2>
+                                  ));
 }
 
 TEST_P(PaintChunksToCcLayerTest, EmptyEffectsAreStored) {
@@ -669,11 +564,11 @@
   PaintRecord output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
-  EXPECT_THAT(output, PaintRecordMatcher::Make({
-                          cc::PaintOpType::SaveLayerAlpha,  // <e1>
-                          cc::PaintOpType::Restore,         // </e1>
-                      }));
-  EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, output, 0);
+  EXPECT_THAT(output, ElementsAre(PaintOpEq(cc::SaveLayerAlphaOp(
+                                      SkRect::MakeXYWH(0, 0, 100, 100),
+                                      127 / 255.f)),          // <e1>
+                                  PaintOpIs<cc::RestoreOp>()  // </e1>
+                                  ));
 }
 
 TEST_P(PaintChunksToCcLayerTest, CombineClips) {
@@ -695,19 +590,20 @@
 
   EXPECT_THAT(
       output,
-      PaintRecordMatcher::Make(
-          {cc::PaintOpType::Save, cc::PaintOpType::ClipRect,      // <c1+c2>
-           cc::PaintOpType::Save, cc::PaintOpType::Concat,        // <t1
-           cc::PaintOpType::ClipRect, cc::PaintOpType::ClipPath,  //  c3+c4+c5>
-           cc::PaintOpType::Save, cc::PaintOpType::ClipRect,      // <c6>
-           cc::PaintOpType::DrawRecord,                           // <p0/>
-           cc::PaintOpType::Restore,                              // </c6>
-           cc::PaintOpType::Restore,                        // </c3+c4+c5 t1>
-           cc::PaintOpType::Save, cc::PaintOpType::Concat,  // <t1
-           cc::PaintOpType::ClipRect,                       // c3>
-           cc::PaintOpType::DrawRecord,                     // <p1/>
-           cc::PaintOpType::Restore,                        // </c3 t1>
-           cc::PaintOpType::Restore}));                     // </c1+c2>
+      ElementsAre(PaintOpIs<cc::SaveOp>(),
+                  PaintOpIs<cc::ClipRectOp>(),  // <c1+c2>
+                  PaintOpIs<cc::SaveOp>(), PaintOpIs<cc::ConcatOp>(),  // <t1
+                  PaintOpIs<cc::ClipRectOp>(),
+                  PaintOpIs<cc::ClipPathOp>(),  //  c3+c4+c5>
+                  PaintOpIs<cc::SaveOp>(), PaintOpIs<cc::ClipRectOp>(),  // <c6>
+                  PaintOpIs<cc::DrawRecordOp>(),  // <p0/>
+                  PaintOpIs<cc::RestoreOp>(),     // </c6>
+                  PaintOpIs<cc::RestoreOp>(),     // </c3+c4+c5 t1>
+                  PaintOpIs<cc::SaveOp>(), PaintOpIs<cc::ConcatOp>(),  // <t1
+                  PaintOpIs<cc::ClipRectOp>(),                         // c3>
+                  PaintOpIs<cc::DrawRecordOp>(),                       // <p1/>
+                  PaintOpIs<cc::RestoreOp>(),    // </c3 t1>
+                  PaintOpIs<cc::RestoreOp>()));  // </c1+c2>
 }
 
 TEST_P(PaintChunksToCcLayerTest, CombineClipsAcrossTransform) {
@@ -731,36 +627,41 @@
   // and c3/c4 across |non_invertible|.
   EXPECT_THAT(
       output,
-      PaintRecordMatcher::Make(
-          {cc::PaintOpType::Save, cc::PaintOpType::ClipRect,  // <c1+c2>
-           cc::PaintOpType::Save, cc::PaintOpType::Concat,    // <non_identity
-           cc::PaintOpType::ClipRect,                         //  c3>
-           cc::PaintOpType::Save, cc::PaintOpType::Concat,    // <non_invertible
-           cc::PaintOpType::ClipRect,                         //  c4>
-           cc::PaintOpType::DrawRecord,                       // <p0/>
-           cc::PaintOpType::Restore,     // </c4 non_invertible>
-           cc::PaintOpType::Restore,     // </c3 non_identity>
-           cc::PaintOpType::Restore}));  // </c1+c2>
-
-  EXPECT_CLIP(gfx::RectF(50, 50, 50, 50), output, 1);
-  EXPECT_TRANSFORM_MATRIX(non_identity->Matrix(), output, 3);
-  EXPECT_CLIP(gfx::RectF(1, 2, 3, 4), output, 4);
-  EXPECT_TRANSFORM_MATRIX(non_invertible->Matrix(), output, 6);
-  EXPECT_CLIP(gfx::RectF(5, 6, 7, 8), output, 7);
+      ElementsAre(PaintOpIs<cc::SaveOp>(),
+                  PaintOpEq(cc::ClipRectOp(SkRect::MakeXYWH(50, 50, 50, 50),
+                                           SkClipOp::kIntersect,
+                                           /*antialias=*/true)),  // <c1+c2>
+                  PaintOpIs<cc::SaveOp>(),
+                  PaintOpEq(cc::ConcatOp(gfx::TransformToSkM44(
+                      non_identity->Matrix()))),  // <non_identity
+                  PaintOpEq(cc::ClipRectOp(SkRect::MakeXYWH(1, 2, 3, 4),
+                                           SkClipOp::kIntersect,
+                                           /*antialias=*/true)),  //  c3>
+                  PaintOpIs<cc::SaveOp>(),
+                  PaintOpEq(cc::ConcatOp(gfx::TransformToSkM44(
+                      non_invertible->Matrix()))),  // <non_invertible
+                  PaintOpEq(cc::ClipRectOp(SkRect::MakeXYWH(5, 6, 7, 8),
+                                           SkClipOp::kIntersect,
+                                           /*antialias=*/true)),  //  c4>
+                  PaintOpIs<cc::DrawRecordOp>(),                  // <p0/>
+                  PaintOpIs<cc::RestoreOp>(),  // </c4 non_invertible>
+                  PaintOpIs<cc::RestoreOp>(),  // </c3 non_identity>
+                  PaintOpIs<cc::RestoreOp>()   // </c1+c2>
+                  ));
 }
 
 TEST_P(PaintChunksToCcLayerTest, CombineClipsWithRoundedRects) {
-  FloatRoundedRect clip_rect(0, 0, 100, 100);
-  FloatRoundedRect big_rounded_clip_rect(gfx::RectF(0, 0, 200, 200), 5);
-  FloatRoundedRect small_rounded_clip_rect(gfx::RectF(0, 0, 100, 100), 5);
+  FloatRoundedRect rect(0, 0, 100, 100);
+  FloatRoundedRect big_rounded_rect(gfx::RectF(0, 0, 200, 200), 5);
+  FloatRoundedRect small_rounded_rect(gfx::RectF(0, 0, 100, 100), 5);
 
-  auto c1 = CreateClip(c0(), t0(), clip_rect);
-  auto c2 = CreateClip(*c1, t0(), small_rounded_clip_rect);
-  auto c3 = CreateClip(*c2, t0(), clip_rect);
-  auto c4 = CreateClip(*c3, t0(), big_rounded_clip_rect);
-  auto c5 = CreateClip(*c4, t0(), clip_rect);
-  auto c6 = CreateClip(*c5, t0(), big_rounded_clip_rect);
-  auto c7 = CreateClip(*c6, t0(), small_rounded_clip_rect);
+  auto c1 = CreateClip(c0(), t0(), rect);
+  auto c2 = CreateClip(*c1, t0(), small_rounded_rect);
+  auto c3 = CreateClip(*c2, t0(), rect);
+  auto c4 = CreateClip(*c3, t0(), big_rounded_rect);
+  auto c5 = CreateClip(*c4, t0(), rect);
+  auto c6 = CreateClip(*c5, t0(), big_rounded_rect);
+  auto c7 = CreateClip(*c6, t0(), small_rounded_rect);
 
   TestChunks chunks;
   chunks.AddChunk(t0(), *c7, e0());
@@ -770,24 +671,32 @@
 
   EXPECT_THAT(
       output,
-      PaintRecordMatcher::Make(
-          {cc::PaintOpType::Save, cc::PaintOpType::ClipRRect,  // <c1+c2+c3>
-           cc::PaintOpType::Save, cc::PaintOpType::ClipRRect,  // <c4>
-           cc::PaintOpType::Save, cc::PaintOpType::ClipRect,   // <c5>
-           cc::PaintOpType::Save, cc::PaintOpType::ClipRRect,  // <c6>
-           cc::PaintOpType::Save, cc::PaintOpType::ClipRRect,  // <c7>
-           cc::PaintOpType::DrawRecord,                        // <p0/>
-           cc::PaintOpType::Restore,                           // </c7>
-           cc::PaintOpType::Restore,                           // </c6>
-           cc::PaintOpType::Restore,                           // </c5>
-           cc::PaintOpType::Restore,                           // </c4>
-           cc::PaintOpType::Restore}));                        // </c1+c2+c3>
-
-  EXPECT_ROUNDED_CLIP(small_rounded_clip_rect, output, 1);
-  EXPECT_ROUNDED_CLIP(big_rounded_clip_rect, output, 3);
-  EXPECT_CLIP(clip_rect.Rect(), output, 5);
-  EXPECT_ROUNDED_CLIP(big_rounded_clip_rect, output, 7);
-  EXPECT_ROUNDED_CLIP(small_rounded_clip_rect, output, 9);
+      ElementsAre(PaintOpIs<cc::SaveOp>(),
+                  PaintOpEq(cc::ClipRRectOp(SkRRect(small_rounded_rect),
+                                            SkClipOp::kIntersect,
+                                            /*antialias=*/true)),  // <c1+c2+c3>
+                  PaintOpIs<cc::SaveOp>(),
+                  PaintOpEq(cc::ClipRRectOp(SkRRect(big_rounded_rect),
+                                            SkClipOp::kIntersect,
+                                            /*antialias=*/true)),  // <c4>
+                  PaintOpIs<cc::SaveOp>(),
+                  PaintOpEq(cc::ClipRectOp(gfx::RectFToSkRect(rect.Rect()),
+                                           SkClipOp::kIntersect,
+                                           /*antialias=*/true)),  // <c5>
+                  PaintOpIs<cc::SaveOp>(),
+                  PaintOpEq(cc::ClipRRectOp(SkRRect(big_rounded_rect),
+                                            SkClipOp::kIntersect,
+                                            /*antialias=*/true)),  // <c6>
+                  PaintOpIs<cc::SaveOp>(),
+                  PaintOpEq(cc::ClipRRectOp(SkRRect(small_rounded_rect),
+                                            SkClipOp::kIntersect,
+                                            /*antialias=*/true)),  // <c7>
+                  PaintOpIs<cc::DrawRecordOp>(),                   // <p0/>
+                  PaintOpIs<cc::RestoreOp>(),                      // </c7>
+                  PaintOpIs<cc::RestoreOp>(),                      // </c6>
+                  PaintOpIs<cc::RestoreOp>(),                      // </c5>
+                  PaintOpIs<cc::RestoreOp>(),                      // </c4>
+                  PaintOpIs<cc::RestoreOp>()));  // </c1+c2+c3>
 }
 
 TEST_P(PaintChunksToCcLayerTest, ChunksSamePropertyTreeState) {
@@ -807,21 +716,21 @@
   PaintRecord output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
-  EXPECT_THAT(output,
-              PaintRecordMatcher::Make(
-                  {cc::PaintOpType::DrawRecord,                       // <p0/>
-                   cc::PaintOpType::Save, cc::PaintOpType::Concat,    // <t1>
-                   cc::PaintOpType::DrawRecord,                       // <p1/>
-                   cc::PaintOpType::DrawRecord,                       // <p2/>
-                   cc::PaintOpType::Save, cc::PaintOpType::ClipRect,  // <c1>
-                   cc::PaintOpType::DrawRecord,                       // <p3/>
-                   cc::PaintOpType::DrawRecord,                       // <p4/>
-                   cc::PaintOpType::Save, cc::PaintOpType::Concat,    // <t2>
-                   cc::PaintOpType::DrawRecord,                       // <p5/>
-                   cc::PaintOpType::DrawRecord,                       // <p6/>
-                   cc::PaintOpType::Restore,                          // </t2>
-                   cc::PaintOpType::Restore,                          // </c1>
-                   cc::PaintOpType::Restore}));                       // </t1>
+  EXPECT_THAT(
+      output,
+      ElementsAre(PaintOpIs<cc::DrawRecordOp>(),                       // <p0/>
+                  PaintOpIs<cc::SaveOp>(), PaintOpIs<cc::ConcatOp>(),  // <t1>
+                  PaintOpIs<cc::DrawRecordOp>(),                       // <p1/>
+                  PaintOpIs<cc::DrawRecordOp>(),                       // <p2/>
+                  PaintOpIs<cc::SaveOp>(), PaintOpIs<cc::ClipRectOp>(),  // <c1>
+                  PaintOpIs<cc::DrawRecordOp>(),                       // <p3/>
+                  PaintOpIs<cc::DrawRecordOp>(),                       // <p4/>
+                  PaintOpIs<cc::SaveOp>(), PaintOpIs<cc::ConcatOp>(),  // <t2>
+                  PaintOpIs<cc::DrawRecordOp>(),                       // <p5/>
+                  PaintOpIs<cc::DrawRecordOp>(),                       // <p6/>
+                  PaintOpIs<cc::RestoreOp>(),                          // </t2>
+                  PaintOpIs<cc::RestoreOp>(),                          // </c1>
+                  PaintOpIs<cc::RestoreOp>()));                        // </t1>
 }
 
 TEST_P(PaintChunksToCcLayerTest, NoOpForIdentityTransforms) {
@@ -844,16 +753,16 @@
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output,
-              PaintRecordMatcher::Make(
-                  {cc::PaintOpType::DrawRecord,                       // <p0/>
-                   cc::PaintOpType::DrawRecord,                       // <p1/>
-                   cc::PaintOpType::DrawRecord,                       // <p2/>
-                   cc::PaintOpType::DrawRecord,                       // <p3/>
-                   cc::PaintOpType::DrawRecord,                       // <p4/>
-                   cc::PaintOpType::DrawRecord,                       // <p5/>
-                   cc::PaintOpType::Save, cc::PaintOpType::ClipRect,  // <c1+c2>
-                   cc::PaintOpType::DrawRecord,                       // <p6/>
-                   cc::PaintOpType::Restore}));  // </c1+c2>
+              ElementsAre(PaintOpIs<cc::DrawRecordOp>(),  // <p0/>
+                          PaintOpIs<cc::DrawRecordOp>(),  // <p1/>
+                          PaintOpIs<cc::DrawRecordOp>(),  // <p2/>
+                          PaintOpIs<cc::DrawRecordOp>(),  // <p3/>
+                          PaintOpIs<cc::DrawRecordOp>(),  // <p4/>
+                          PaintOpIs<cc::DrawRecordOp>(),  // <p5/>
+                          PaintOpIs<cc::SaveOp>(),
+                          PaintOpIs<cc::ClipRectOp>(),    // <c1+c2>
+                          PaintOpIs<cc::DrawRecordOp>(),  // <p6/>
+                          PaintOpIs<cc::RestoreOp>()));   // </c1+c2>
 }
 
 TEST_P(PaintChunksToCcLayerTest, EffectsWithSameTransform) {
@@ -869,17 +778,17 @@
   auto output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
-  EXPECT_THAT(output,
-              PaintRecordMatcher::Make(
-                  {cc::PaintOpType::DrawRecord,                     // <p0/>
-                   cc::PaintOpType::Save, cc::PaintOpType::Concat,  // <t1>
-                   cc::PaintOpType::SaveLayerAlpha,                 // <e1>
-                   cc::PaintOpType::DrawRecord,                     // <p1/>
-                   cc::PaintOpType::Restore,                        // </e1>
-                   cc::PaintOpType::SaveLayerAlpha,                 // <e2>
-                   cc::PaintOpType::DrawRecord,                     // <p2>
-                   cc::PaintOpType::Restore,                        // </e2>
-                   cc::PaintOpType::Restore}));                     // </t1>
+  EXPECT_THAT(
+      output,
+      ElementsAre(PaintOpIs<cc::DrawRecordOp>(),                       // <p0/>
+                  PaintOpIs<cc::SaveOp>(), PaintOpIs<cc::ConcatOp>(),  // <t1>
+                  PaintOpIs<cc::SaveLayerAlphaOp>(),                   // <e1>
+                  PaintOpIs<cc::DrawRecordOp>(),                       // <p1/>
+                  PaintOpIs<cc::RestoreOp>(),                          // </e1>
+                  PaintOpIs<cc::SaveLayerAlphaOp>(),                   // <e2>
+                  PaintOpIs<cc::DrawRecordOp>(),                       // <p2>
+                  PaintOpIs<cc::RestoreOp>(),                          // </e2>
+                  PaintOpIs<cc::RestoreOp>()));                        // </t1>
 }
 
 TEST_P(PaintChunksToCcLayerTest, NestedEffectsWithSameTransform) {
@@ -895,17 +804,17 @@
   auto output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
-  EXPECT_THAT(output,
-              PaintRecordMatcher::Make(
-                  {cc::PaintOpType::DrawRecord,                     // <p0/>
-                   cc::PaintOpType::Save, cc::PaintOpType::Concat,  // <t1>
-                   cc::PaintOpType::SaveLayerAlpha,                 // <e1>
-                   cc::PaintOpType::DrawRecord,                     // <p1/>
-                   cc::PaintOpType::SaveLayerAlpha,                 // <e2>
-                   cc::PaintOpType::DrawRecord,                     // <p2>
-                   cc::PaintOpType::Restore,                        // </e2>
-                   cc::PaintOpType::Restore,                        // </e1>
-                   cc::PaintOpType::Restore}));                     // </t1>
+  EXPECT_THAT(
+      output,
+      ElementsAre(PaintOpIs<cc::DrawRecordOp>(),                       // <p0/>
+                  PaintOpIs<cc::SaveOp>(), PaintOpIs<cc::ConcatOp>(),  // <t1>
+                  PaintOpIs<cc::SaveLayerAlphaOp>(),                   // <e1>
+                  PaintOpIs<cc::DrawRecordOp>(),                       // <p1/>
+                  PaintOpIs<cc::SaveLayerAlphaOp>(),                   // <e2>
+                  PaintOpIs<cc::DrawRecordOp>(),                       // <p2>
+                  PaintOpIs<cc::RestoreOp>(),                          // </e2>
+                  PaintOpIs<cc::RestoreOp>(),                          // </e1>
+                  PaintOpIs<cc::RestoreOp>()));                        // </t1>
 }
 
 TEST_P(PaintChunksToCcLayerTest, NoopTransformIsNotEmitted) {
@@ -927,21 +836,21 @@
   auto output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
-  EXPECT_THAT(output,
-              PaintRecordMatcher::Make({
-                  cc::PaintOpType::DrawRecord,  // draw with t0
-                  cc::PaintOpType::Save, cc::PaintOpType::Concat,  // t1
-                  cc::PaintOpType::DrawRecord,  // draw with t1
-                  cc::PaintOpType::DrawRecord,  // draw with noop_t2
-                  cc::PaintOpType::DrawRecord,  // draw with noop_t3
-                  cc::PaintOpType::DrawRecord,  // draw with noop_t2
-                  cc::PaintOpType::Restore,     // end t1
-                  cc::PaintOpType::Save, cc::PaintOpType::Concat,  // t4
-                  cc::PaintOpType::DrawRecord,  // draw with t4
-                  cc::PaintOpType::DrawRecord,  // draw with noop_t5
-                  cc::PaintOpType::DrawRecord,  // draw with t4
-                  cc::PaintOpType::Restore      // end t4
-              }));
+  EXPECT_THAT(
+      output,
+      ElementsAre(PaintOpIs<cc::DrawRecordOp>(),  // draw with t0
+                  PaintOpIs<cc::SaveOp>(), PaintOpIs<cc::ConcatOp>(),  // t1
+                  PaintOpIs<cc::DrawRecordOp>(),  // draw with t1
+                  PaintOpIs<cc::DrawRecordOp>(),  // draw with noop_t2
+                  PaintOpIs<cc::DrawRecordOp>(),  // draw with noop_t3
+                  PaintOpIs<cc::DrawRecordOp>(),  // draw with noop_t2
+                  PaintOpIs<cc::RestoreOp>(),     // end t1
+                  PaintOpIs<cc::SaveOp>(), PaintOpIs<cc::ConcatOp>(),  // t4
+                  PaintOpIs<cc::DrawRecordOp>(),  // draw with t4
+                  PaintOpIs<cc::DrawRecordOp>(),  // draw with noop_t5
+                  PaintOpIs<cc::DrawRecordOp>(),  // draw with t4
+                  PaintOpIs<cc::RestoreOp>()      // end t4
+                  ));
 }
 
 TEST_P(PaintChunksToCcLayerTest, OnlyNoopTransformIsNotEmitted) {
@@ -956,9 +865,9 @@
   auto output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
-  EXPECT_THAT(output, PaintRecordMatcher::Make({cc::PaintOpType::DrawRecord,
-                                                cc::PaintOpType::DrawRecord,
-                                                cc::PaintOpType::DrawRecord}));
+  EXPECT_THAT(output, ElementsAre(PaintOpIs<cc::DrawRecordOp>(),
+                                  PaintOpIs<cc::DrawRecordOp>(),
+                                  PaintOpIs<cc::DrawRecordOp>()));
 }
 
 TEST_P(PaintChunksToCcLayerTest, NoopTransformFirstThenBackToParent) {
@@ -973,14 +882,14 @@
   auto output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
-  EXPECT_THAT(output, PaintRecordMatcher::Make({
-                          cc::PaintOpType::DrawRecord,  // t0
-                          cc::PaintOpType::Save,
-                          cc::PaintOpType::Concat,      // t1 + noop_t2
-                          cc::PaintOpType::DrawRecord,  // draw with above
-                          cc::PaintOpType::DrawRecord,  // draw with just t1
-                          cc::PaintOpType::Restore      // end t1
-                      }));
+  EXPECT_THAT(output,
+              ElementsAre(PaintOpIs<cc::DrawRecordOp>(),  // t0
+                          PaintOpIs<cc::SaveOp>(),
+                          PaintOpIs<cc::ConcatOp>(),      // t1 + noop_t2
+                          PaintOpIs<cc::DrawRecordOp>(),  // draw with above
+                          PaintOpIs<cc::DrawRecordOp>(),  // draw with just t1
+                          PaintOpIs<cc::RestoreOp>()      // end t1
+                          ));
 }
 
 TEST_P(PaintChunksToCcLayerTest, ClipUndoesNoopTransform) {
@@ -997,16 +906,17 @@
   auto output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
-  EXPECT_THAT(output, PaintRecordMatcher::Make({
-                          cc::PaintOpType::DrawRecord,  // t0
-                          cc::PaintOpType::Save,
-                          cc::PaintOpType::Concat,  // t1 + noop_t2
-                          cc::PaintOpType::DrawRecord, cc::PaintOpType::Save,
-                          cc::PaintOpType::ClipRect,  // c1 (with t1 space)
-                          cc::PaintOpType::DrawRecord,
-                          cc::PaintOpType::Restore,  // end c1
-                          cc::PaintOpType::Restore   // end t1
-                      }));
+  EXPECT_THAT(
+      output,
+      ElementsAre(PaintOpIs<cc::DrawRecordOp>(),  // t0
+                  PaintOpIs<cc::SaveOp>(),
+                  PaintOpIs<cc::ConcatOp>(),  // t1 + noop_t2
+                  PaintOpIs<cc::DrawRecordOp>(), PaintOpIs<cc::SaveOp>(),
+                  PaintOpIs<cc::ClipRectOp>(),  // c1 (with t1 space)
+                  PaintOpIs<cc::DrawRecordOp>(),
+                  PaintOpIs<cc::RestoreOp>(),  // end c1
+                  PaintOpIs<cc::RestoreOp>()   // end t1
+                  ));
 }
 
 TEST_P(PaintChunksToCcLayerTest, EffectUndoesNoopTransform) {
@@ -1023,16 +933,15 @@
   auto output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
-  EXPECT_THAT(output, PaintRecordMatcher::Make({
-                          cc::PaintOpType::DrawRecord,  // t0
-                          cc::PaintOpType::Save,
-                          cc::PaintOpType::Concat,  // t1 + noop_t2
-                          cc::PaintOpType::DrawRecord,
-                          cc::PaintOpType::SaveLayerAlpha,  // e1
-                          cc::PaintOpType::DrawRecord,
-                          cc::PaintOpType::Restore,  // end e1
-                          cc::PaintOpType::Restore   // end t1
-                      }));
+  EXPECT_THAT(output, ElementsAre(PaintOpIs<cc::DrawRecordOp>(),  // t0
+                                  PaintOpIs<cc::SaveOp>(),
+                                  PaintOpIs<cc::ConcatOp>(),  // t1 + noop_t2
+                                  PaintOpIs<cc::DrawRecordOp>(),
+                                  PaintOpIs<cc::SaveLayerAlphaOp>(),  // e1
+                                  PaintOpIs<cc::DrawRecordOp>(),
+                                  PaintOpIs<cc::RestoreOp>(),  // end e1
+                                  PaintOpIs<cc::RestoreOp>()   // end t1
+                                  ));
 }
 
 TEST_P(PaintChunksToCcLayerTest, NoopClipDoesNotEmitItems) {
@@ -1054,20 +963,20 @@
   auto output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
-  EXPECT_THAT(output,
-              PaintRecordMatcher::Make({
-                  cc::PaintOpType::DrawRecord,                       // c0
-                  cc::PaintOpType::Save, cc::PaintOpType::ClipRect,  // c1
-                  cc::PaintOpType::DrawRecord,  // draw with c1
-                  cc::PaintOpType::DrawRecord,  // draw with noop_c2
-                  cc::PaintOpType::DrawRecord,  // draw_with noop_c3
-                  cc::PaintOpType::Save, cc::PaintOpType::ClipRect,  // c4
-                  cc::PaintOpType::DrawRecord,  // draw with c4
-                  cc::PaintOpType::Restore,     // end c4
-                  cc::PaintOpType::DrawRecord,  // draw with noop_c2
-                  cc::PaintOpType::DrawRecord,  // draw with c1
-                  cc::PaintOpType::Restore      // end noop_c2 (or c1)
-              }));
+  EXPECT_THAT(
+      output,
+      ElementsAre(PaintOpIs<cc::DrawRecordOp>(),                         // c0
+                  PaintOpIs<cc::SaveOp>(), PaintOpIs<cc::ClipRectOp>(),  // c1
+                  PaintOpIs<cc::DrawRecordOp>(),  // draw with c1
+                  PaintOpIs<cc::DrawRecordOp>(),  // draw with noop_c2
+                  PaintOpIs<cc::DrawRecordOp>(),  // draw_with noop_c3
+                  PaintOpIs<cc::SaveOp>(), PaintOpIs<cc::ClipRectOp>(),  // c4
+                  PaintOpIs<cc::DrawRecordOp>(),  // draw with c4
+                  PaintOpIs<cc::RestoreOp>(),     // end c4
+                  PaintOpIs<cc::DrawRecordOp>(),  // draw with noop_c2
+                  PaintOpIs<cc::DrawRecordOp>(),  // draw with c1
+                  PaintOpIs<cc::RestoreOp>()      // end noop_c2 (or c1)
+                  ));
 }
 
 TEST_P(PaintChunksToCcLayerTest, EffectUndoesNoopClip) {
@@ -1084,14 +993,14 @@
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output,
-              PaintRecordMatcher::Make({
-                  cc::PaintOpType::Save, cc::PaintOpType::ClipRect,  // noop_c2
-                  cc::PaintOpType::DrawRecord,      // draw with noop_c2
-                  cc::PaintOpType::SaveLayerAlpha,  // e1
-                  cc::PaintOpType::DrawRecord,      // draw with e1
-                  cc::PaintOpType::Restore,         // end e1
-                  cc::PaintOpType::Restore          // end noop_c2
-              }));
+              ElementsAre(PaintOpIs<cc::SaveOp>(),
+                          PaintOpIs<cc::ClipRectOp>(),    // noop_c2
+                          PaintOpIs<cc::DrawRecordOp>(),  // draw with noop_c2
+                          PaintOpIs<cc::SaveLayerAlphaOp>(),  // e1
+                          PaintOpIs<cc::DrawRecordOp>(),      // draw with e1
+                          PaintOpIs<cc::RestoreOp>(),         // end e1
+                          PaintOpIs<cc::RestoreOp>()          // end noop_c2
+                          ));
 }
 
 TEST_P(PaintChunksToCcLayerTest, NoopEffectDoesNotEmitItems) {
@@ -1113,19 +1022,18 @@
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output,
-              PaintRecordMatcher::Make({
-                  cc::PaintOpType::DrawRecord,      // e0
-                  cc::PaintOpType::SaveLayerAlpha,  // e1
-                  cc::PaintOpType::DrawRecord,      // draw with e1
-                  cc::PaintOpType::DrawRecord,      // draw with noop_e2
-                  cc::PaintOpType::DrawRecord,      // draw_with noop_e3
-                  cc::PaintOpType::SaveLayerAlpha,  // e4
-                  cc::PaintOpType::DrawRecord,      // draw with e4
-                  cc::PaintOpType::Restore,         // end e4
-                  cc::PaintOpType::DrawRecord,      // draw with noop_e2
-                  cc::PaintOpType::DrawRecord,      // draw with e1
-                  cc::PaintOpType::Restore          // end noop_e2 (or e1)
-              }));
+              ElementsAre(PaintOpIs<cc::DrawRecordOp>(),      // e0
+                          PaintOpIs<cc::SaveLayerAlphaOp>(),  // e1
+                          PaintOpIs<cc::DrawRecordOp>(),      // draw with e1
+                          PaintOpIs<cc::DrawRecordOp>(),  // draw with noop_e2
+                          PaintOpIs<cc::DrawRecordOp>(),  // draw_with noop_e3
+                          PaintOpIs<cc::SaveLayerAlphaOp>(),  // e4
+                          PaintOpIs<cc::DrawRecordOp>(),      // draw with e4
+                          PaintOpIs<cc::RestoreOp>(),         // end e4
+                          PaintOpIs<cc::DrawRecordOp>(),  // draw with noop_e2
+                          PaintOpIs<cc::DrawRecordOp>(),  // draw with e1
+                          PaintOpIs<cc::RestoreOp>()      // end noop_e2 (or e1)
+                          ));
 }
 
 TEST_P(PaintChunksToCcLayerTest, EmptyChunkRect) {
@@ -1137,10 +1045,15 @@
 
   auto output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
-  EXPECT_THAT(output,
-              PaintRecordMatcher::Make({cc::PaintOpType::SaveLayer,   // <e1>
-                                        cc::PaintOpType::Restore}));  // </e1>
-  EXPECT_EFFECT_BOUNDS(0, 0, 0, 0, output, 0);
+
+  cc::PaintFlags expected_flags;
+  expected_flags.setImageFilter(cc::RenderSurfaceFilters::BuildImageFilter(
+      filter.AsCcFilterOperations(), gfx::SizeF()));
+  EXPECT_THAT(
+      output,
+      ElementsAre(PaintOpEq(cc::SaveLayerOp(SkRect::MakeXYWH(0, 0, 0, 0),
+                                            expected_flags)),  // <e1>
+                  PaintOpIs<cc::RestoreOp>()));                // </e1>
 }
 
 static sk_sp<cc::PaintFilter> MakeFilter(gfx::RectF bounds) {
@@ -1170,13 +1083,18 @@
   }
 
   auto output = cc_list->FinalizeAndReleaseAsRecord();
-  EXPECT_THAT(output, PaintRecordMatcher::Make(
-                          {cc::PaintOpType::Save,
-                           cc::PaintOpType::Translate,  // layer offset
-                           cc::PaintOpType::SaveLayer,  // <e1>
-                           cc::PaintOpType::Restore,    // </e1>
-                           cc::PaintOpType::Restore}));
-  EXPECT_EFFECT_BOUNDS(12, 26, 93, 84, output, 2);
+
+  cc::PaintFlags expected_flags;
+  expected_flags.setImageFilter(cc::RenderSurfaceFilters::BuildImageFilter(
+      filter.AsCcFilterOperations(), gfx::SizeF()));
+  EXPECT_THAT(
+      output,
+      ElementsAre(PaintOpIs<cc::SaveOp>(),
+                  PaintOpIs<cc::TranslateOp>(),  // layer offset
+                  PaintOpEq(cc::SaveLayerOp(SkRect::MakeXYWH(12, 26, 93, 84),
+                                            expected_flags)),  // <e1>
+                  PaintOpIs<cc::RestoreOp>(),                  // </e1>
+                  PaintOpIs<cc::RestoreOp>()));
 }
 
 TEST_P(PaintChunksToCcLayerTest, ReferenceFilterOnChunkWithDrawingDisplayItem) {
@@ -1206,17 +1124,22 @@
   }
 
   auto output = cc_list->FinalizeAndReleaseAsRecord();
-  EXPECT_THAT(output,
-              PaintRecordMatcher::Make(
-                  {cc::PaintOpType::Save,
-                   cc::PaintOpType::Translate,   // layer offset
-                   cc::PaintOpType::SaveLayer,   // <e1>
-                   cc::PaintOpType::DrawRecord,  // the DrawingDisplayItem
-                   cc::PaintOpType::Restore,     // </e1>
-                   cc::PaintOpType::Restore}));
-  // The effect bounds are the union of the chunk's drawable_bounds and the
-  // output bounds of the filter with empty input in the filter's space.
-  EXPECT_EFFECT_BOUNDS(7, 15, 93, 85, output, 2);
+
+  cc::PaintFlags expected_flags;
+  expected_flags.setImageFilter(cc::RenderSurfaceFilters::BuildImageFilter(
+      filter.AsCcFilterOperations(), gfx::SizeF()));
+  EXPECT_THAT(
+      output,
+      ElementsAre(PaintOpIs<cc::SaveOp>(),
+                  PaintOpIs<cc::TranslateOp>(),  // layer offset
+                  // The effect bounds are the union of the chunk's
+                  // drawable_bounds and the output bounds of the filter
+                  // with empty input in the filter's space.
+                  PaintOpEq(cc::SaveLayerOp(SkRect::MakeXYWH(7, 15, 93, 85),
+                                            expected_flags)),  // <e1>
+                  PaintOpIs<cc::DrawRecordOp>(),  // the DrawingDisplayItem
+                  PaintOpIs<cc::RestoreOp>(),     // </e1>
+                  PaintOpIs<cc::RestoreOp>()));
 }
 
 TEST_P(PaintChunksToCcLayerTest, FilterClipExpanderUnderClip) {
@@ -1233,14 +1156,14 @@
   auto output =
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   ASSERT_EQ(7u, output.total_op_count());
-  EXPECT_THAT(output,
-              PaintRecordMatcher::Make(
-                  {cc::PaintOpType::SaveLayer,  // <e1>
-                   cc::PaintOpType::Save,
-                   cc::PaintOpType::ClipRect,    // <c1>
-                   cc::PaintOpType::DrawRecord,  // the DrawingDisplayItem
-                   cc::PaintOpType::Restore,     // </c1>
-                   cc::PaintOpType::Restore}));  // </e1>
+  EXPECT_THAT(
+      output,
+      ElementsAre(PaintOpIs<cc::SaveLayerOp>(),  // <e1>
+                  PaintOpIs<cc::SaveOp>(),
+                  PaintOpIs<cc::ClipRectOp>(),    // <c1>
+                  PaintOpIs<cc::DrawRecordOp>(),  // the DrawingDisplayItem
+                  PaintOpIs<cc::RestoreOp>(),     // </c1>
+                  PaintOpIs<cc::RestoreOp>()));   // </e1>
 }
 
 TEST_P(PaintChunksToCcLayerTest,
@@ -1365,9 +1288,9 @@
       PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   // TODO(crbug.com/1334293): For now non-composited backdrop filters are
   // ignored.
-  EXPECT_THAT(output, PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,
-                                                cc::PaintOpType::DrawRecord,
-                                                cc::PaintOpType::Restore}));
+  EXPECT_THAT(output, ElementsAre(PaintOpIs<cc::SaveLayerAlphaOp>(),
+                                  PaintOpIs<cc::DrawRecordOp>(),
+                                  PaintOpIs<cc::RestoreOp>()));
 }
 
 }  // namespace
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle_test.cc b/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle_test.cc
index d7294ac..9dba75e 100644
--- a/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle_test.cc
+++ b/third_party/blink/renderer/platform/graphics/video_frame_sink_bundle_test.cc
@@ -90,7 +90,7 @@
 
 const viz::LocalSurfaceId kTestSurfaceId(
     1,
-    base::UnguessableToken::Deserialize(1, 2));
+    base::UnguessableToken::CreateForTesting(1, 2));
 
 class VideoFrameSinkBundleTest : public testing::Test {
  public:
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc b/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
index 203c491..56e48af8 100644
--- a/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
+++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
@@ -192,8 +192,8 @@
     submitter_->surface_embedder_ = std::move(embedder);
     auto surface_id = viz::SurfaceId(
         viz::FrameSinkId(1, 1),
-        viz::LocalSurfaceId(11,
-                            base::UnguessableToken::Deserialize(0x111111, 0)));
+        viz::LocalSurfaceId(
+            11, base::UnguessableToken::CreateForTesting(0x111111, 0)));
     submitter_->frame_sink_id_ = surface_id.frame_sink_id();
     submitter_->child_local_surface_id_allocator_.UpdateFromParent(
         surface_id.local_surface_id());
diff --git a/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc b/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc
index 5ba61a3..a26d2de 100644
--- a/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc
+++ b/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc
@@ -218,7 +218,7 @@
 
 void MultiBufferDataSource::OnRedirected(
     const scoped_refptr<UrlData>& new_destination) {
-  if (!new_destination) {
+  if (!new_destination || !url_data_) {
     // A failure occurred.
     failed_ = true;
     if (init_cb_) {
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 7dd0cc0..a17731c 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -445,8 +445,9 @@
     },
     {
       // If set, the parser will canonicalize whitespace strings.
-      name: "CanonicalizeWhiteSpaceStrings",
-      base_feature: "CanonicalizeWhiteSpaceStrings",
+      name: "CanonicalizeWhitespaceStrings",
+      status: "stable",
+      base_feature: "CanonicalizeWhitespaceStrings",
     },
     {
       name: "Canvas2dImageChromium",
diff --git a/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits_test.cc b/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits_test.cc
index a8380dc..46b52da 100644
--- a/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits_test.cc
+++ b/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits_test.cc
@@ -98,8 +98,8 @@
       StorageKey::CreateForTesting(url_origin2, net_site1),
       StorageKey::CreateForTesting(url_origin3, net_site2),
       StorageKey::CreateForTesting(url_origin4, net_site2),
-      StorageKey::CreateWithNonce(url_origin1, nonce),
-      StorageKey::CreateWithNonce(url_origin2, nonce),
+      StorageKey::CreateWithNonceForTesting(url_origin1, nonce),
+      StorageKey::CreateWithNonceForTesting(url_origin2, nonce),
       StorageKey::CreateWithOptionalNonce(
           url_origin2, net_site2, nullptr,
           mojom::blink::AncestorChainBit::kCrossSite),
@@ -170,8 +170,8 @@
         StorageKey::CreateForTesting(url_origin2, net_site1),
         StorageKey::CreateForTesting(url_origin3, net_site2),
         StorageKey::CreateForTesting(url_origin4, net_site2),
-        StorageKey::CreateWithNonce(url_origin1, nonce),
-        StorageKey::CreateWithNonce(url_origin2, nonce),
+        StorageKey::CreateWithNonceForTesting(url_origin1, nonce),
+        StorageKey::CreateWithNonceForTesting(url_origin2, nonce),
         StorageKey::CreateWithOptionalNonce(
             url_origin2, net_site2, nullptr,
             mojom::blink::AncestorChainBit::kCrossSite),
diff --git a/third_party/blink/renderer/platform/storage/blink_storage_key_test.cc b/third_party/blink/renderer/platform/storage/blink_storage_key_test.cc
index d1ef270c1..6bd6000 100644
--- a/third_party/blink/renderer/platform/storage/blink_storage_key_test.cc
+++ b/third_party/blink/renderer/platform/storage/blink_storage_key_test.cc
@@ -140,8 +140,8 @@
         StorageKey(url_origin2),
         StorageKey(url_origin3),
         StorageKey(url_origin4),
-        StorageKey::CreateWithNonce(url_origin1, nonce),
-        StorageKey::CreateWithNonce(url_origin2, nonce),
+        StorageKey::CreateWithNonceForTesting(url_origin1, nonce),
+        StorageKey::CreateWithNonceForTesting(url_origin2, nonce),
         StorageKey::CreateWithOptionalNonce(
             url_origin1, net::SchemefulSite(url_origin2), nullptr,
             blink::mojom::AncestorChainBit::kCrossSite)};
diff --git a/third_party/blink/renderer/platform/wtf/text/string_statics.cc b/third_party/blink/renderer/platform/wtf/text/string_statics.cc
index aeb0d1d2..c26ba77 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_statics.cc
+++ b/third_party/blink/renderer/platform/wtf/text/string_statics.cc
@@ -28,6 +28,7 @@
 #include "third_party/blink/renderer/platform/wtf/dynamic_annotations.h"
 #include "third_party/blink/renderer/platform/wtf/static_constructors.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
 #include "third_party/blink/renderer/platform/wtf/wtf.h"
 
@@ -50,6 +51,18 @@
 WTF_EXPORT DEFINE_GLOBAL(String, g_empty_string);
 WTF_EXPORT DEFINE_GLOBAL(String, g_empty_string16_bit);
 
+namespace {
+std::aligned_storage_t<sizeof(String) *
+                           NewlineThenWhitespaceStringsTable::kTableSize,
+                       alignof(String)>
+    g_canonical_whitespace_table_storage;
+}
+
+WTF_EXPORT const String (&NewlineThenWhitespaceStringsTable::g_table_)
+    [NewlineThenWhitespaceStringsTable::kTableSize] = *reinterpret_cast<
+        String (*)[NewlineThenWhitespaceStringsTable::kTableSize]>(
+        &g_canonical_whitespace_table_storage);
+
 NOINLINE unsigned StringImpl::HashSlowCase() const {
   if (Is8Bit())
     SetHash(StringHasher::ComputeHashAndMaskTop8Bits(Characters8(), length_));
@@ -74,6 +87,32 @@
   return base::AdoptRef(StringImpl::CreateStatic(characters, length, hash));
 }
 
+void NewlineThenWhitespaceStringsTable::Init() {
+  LChar whitespace_buffer[kTableSize + 1] = {'\n'};
+  std::fill(std::next(std::begin(whitespace_buffer), 1),
+            std::end(whitespace_buffer), ' ');
+
+  // Keep g_table_[0] uninitialized.
+  for (size_t i = 1; i < kTableSize; ++i) {
+    new (NotNullTag::kNotNull, (void*)(&g_table_[i]))
+        String(AtomicString(whitespace_buffer, i).GetString());
+  }
+}
+
+bool NewlineThenWhitespaceStringsTable::IsCommon(const StringView& view) {
+  if (view.empty()) {
+    return false;
+  }
+  if (!view.Is8Bit()) {
+    return false;
+  }
+  if (view[0] != '\n') {
+    return false;
+  }
+  return std::all_of(view.Characters8() + 1, view.Characters8() + view.length(),
+                     [](LChar ch) { return ch == ' '; });
+}
+
 void StringStatics::Init() {
   DCHECK(IsMainThread());
 
@@ -95,6 +134,8 @@
       AtomicString(AddStaticASCIILiteral("http"));
   new (NotNullTag::kNotNull, (void*)&g_https_atom)
       AtomicString(AddStaticASCIILiteral("https"));
+
+  NewlineThenWhitespaceStringsTable::Init();
 }
 
 }  // namespace WTF
diff --git a/third_party/blink/renderer/platform/wtf/text/wtf_string.h b/third_party/blink/renderer/platform/wtf/text/wtf_string.h
index ad5de1f..dd94285 100644
--- a/third_party/blink/renderer/platform/wtf/text/wtf_string.h
+++ b/third_party/blink/renderer/platform/wtf/text/wtf_string.h
@@ -682,6 +682,25 @@
 WTF_EXPORT extern const String& g_empty_string16_bit;
 WTF_EXPORT extern const String& g_xmlns_with_colon;
 
+// Table representing common HTML strings of type '\n<space>*'.
+class WTF_EXPORT NewlineThenWhitespaceStringsTable {
+ public:
+  static constexpr size_t kTableSize = 128;
+
+  static void Init();
+
+  static inline String GetStringForLength(size_t string_length) {
+    DCHECK_NE(string_length, 0u);
+    DCHECK_LT(string_length, kTableSize);
+    return g_table_[string_length];
+  }
+
+  static bool IsCommon(const StringView& view);
+
+ private:
+  static const String (&g_table_)[kTableSize];
+};
+
 // Pretty printer for gtest and base/logging.*.  It prepends and appends
 // double-quotes, and escapes characters other than ASCII printables.
 WTF_EXPORT std::ostream& operator<<(std::ostream&, const String&);
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py
index 4c1e8f64..164cd89 100644
--- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py
+++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py
@@ -221,25 +221,11 @@
             for builder_names in self._builders:
                 try_builders.update(builder_names.split(','))
         else:
-            try_builders = frozenset(
-                self._tool.builders.filter_builders(
-                    is_try=True, exclude_specifiers={'android'}))
+            try_builders.update(
+                self._tool.builders.builders_for_rebaselining())
 
         if self._use_blink_try_bots_only:
             try_builders = try_builders - self.cq_try_bots
-        elif not self._builders:
-            # User did not specify builders and --use-blink-try-bots-only in
-            # command line. Trigger default set of builders in this case, that
-            # is CQ builders plus blink-rel builders that covers additional platforms.
-            # Running duplicated builders for the same platform wastes resource, and
-            # causes problem to rebaseline as we will randomly choose a builder later.
-            to_remove = set()
-            for try_builder, cq_builder in self.try_bots_with_cq_mirror:
-                if (try_builder in try_builders
-                        and cq_builder in try_builders):
-                    to_remove.add(try_builder)
-            try_builders = try_builders - to_remove
-
         return set([
             builder for builder in try_builders
             if not self._tool.builders.uses_wptrunner(builder)
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py
index 985ad81..14ab020 100644
--- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py
+++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py
@@ -80,6 +80,12 @@
                     },
                 },
             },
+            'MOCK Try Linux (CQ duplicate)': {
+                'port_name': 'test-linux-trusty',
+                'specifiers': ['Trusty', 'Release'],
+                'is_try_builder': True,
+                'is_cq_builder': True,
+            },
         })
 
         self.raw_web_test_results = {
diff --git a/third_party/blink/tools/blinkpy/tool/commands/update_metadata.py b/third_party/blink/tools/blinkpy/tool/commands/update_metadata.py
index 5f1780c..aacf9ff 100644
--- a/third_party/blink/tools/blinkpy/tool/commands/update_metadata.py
+++ b/third_party/blink/tools/blinkpy/tool/commands/update_metadata.py
@@ -471,7 +471,13 @@
             version_match = version_pattern.match(config.version)
             if version_match:
                 version = version_match['version']
+
+            processor = config.architecture
             cpu_match = cpu_pattern.match(config.architecture)
+            if cpu_match['arch'] == 'arm':
+                # Coerce `arm64` to `arm` to match:
+                #   https://firefox-source-docs.mozilla.org/build/buildsystem/mozinfo.html
+                processor = 'arm'
 
             for step in self._tool.builders.step_names_for_builder(builder):
                 flag_specific = self._tool.builders.flag_specific_option(
@@ -482,7 +488,7 @@
                     metadata.RunInfo({
                         'os': port.operating_system(),
                         'version': version,
-                        'processor': cpu_match['arch'],
+                        'processor': processor,
                         'bits': int(cpu_match['bits'] or 32),
                         'debug': config.build_type != 'release',
                         'product': product,
diff --git a/third_party/blink/tools/blinkpy/tool/commands/update_metadata_unittest.py b/third_party/blink/tools/blinkpy/tool/commands/update_metadata_unittest.py
index b4a2656a..533054e4 100644
--- a/third_party/blink/tools/blinkpy/tool/commands/update_metadata_unittest.py
+++ b/third_party/blink/tools/blinkpy/tool/commands/update_metadata_unittest.py
@@ -505,7 +505,7 @@
 
         self.assertEqual(linux['os'], 'linux')
         self.assertEqual(linux['version'], 'trusty')
-        self.assertEqual(linux['processor'], 'x86')
+        self.assertEqual(linux['processor'], 'x86_64')
         self.assertEqual(linux['bits'], 64)
         self.assertFalse(linux['debug'])
         self.assertEqual(linux['flag_specific'], '')
diff --git a/third_party/blink/tools/blinkpy/w3c/test_importer.py b/third_party/blink/tools/blinkpy/w3c/test_importer.py
index d7565929..089e697 100644
--- a/third_party/blink/tools/blinkpy/w3c/test_importer.py
+++ b/third_party/blink/tools/blinkpy/w3c/test_importer.py
@@ -249,13 +249,12 @@
 
     def _trigger_try_jobs(self):
         _log.info('Triggering try jobs for updating expectations.')
-        try_bots = set(self.blink_try_bots())
+        rebaselining_builders = self.host.builders.builders_for_rebaselining()
         wptrunner_builders = {
             builder
-            for builder in try_bots
+            for builder in self.host.builders.all_try_builder_names()
             if self.host.builders.uses_wptrunner(builder)
         }
-        rebaselining_builders = try_bots - wptrunner_builders
         if rebaselining_builders:
             _log.info('For rebaselining:')
             for builder in sorted(rebaselining_builders):
@@ -264,7 +263,8 @@
             _log.info('For updating WPT metadata:')
             for builder in sorted(wptrunner_builders):
                 _log.info('  %s', builder)
-        self.git_cl.trigger_try_jobs(try_bots)
+        self.git_cl.trigger_try_jobs(rebaselining_builders
+                                     | wptrunner_builders)
 
     def run_commit_queue_for_cl(self):
         """Triggers CQ and either commits or aborts; returns True on success."""
@@ -338,10 +338,6 @@
                 raise e
         return False
 
-    def blink_try_bots(self):
-        """Returns the collection of builders used for updating expectations."""
-        return self.host.builders.filter_builders(is_try=True)
-
     def parse_args(self, argv):
         parser = argparse.ArgumentParser()
         parser.description = __doc__
diff --git a/third_party/blink/tools/blinkpy/web_tests/builder_list.py b/third_party/blink/tools/blinkpy/web_tests/builder_list.py
index 1f60d58..d1ec442 100644
--- a/third_party/blink/tools/blinkpy/web_tests/builder_list.py
+++ b/third_party/blink/tools/blinkpy/web_tests/builder_list.py
@@ -32,10 +32,12 @@
 """
 
 import json
+from typing import Set
 
 from blinkpy.common.path_finder import PathFinder
 
-class BuilderList(object):
+
+class BuilderList:
     def __init__(self, builders_dict):
         """Creates and validates a builders list.
 
@@ -102,6 +104,20 @@
     def all_flag_specific_try_builder_names(self, flag_specific):
         return self.filter_builders(is_try=True, flag_specific=flag_specific)
 
+    def builders_for_rebaselining(self) -> Set[str]:
+        try_builders = {
+            builder
+            for builder in self.filter_builders(is_try=True,
+                                                exclude_specifiers={'android'})
+            if not self.uses_wptrunner(builder)
+        }
+        # Remove CQ builders whose port is a duplicate of a *-blink-rel builder
+        # to avoid wasting resources.
+        for blink_builder, cq_builder in self.try_bots_with_cq_mirror():
+            if blink_builder in try_builders and cq_builder in try_builders:
+                try_builders.remove(cq_builder)
+        return try_builders
+
     def try_bots_with_cq_mirror(self):
         """Returns a sorted list of (try_builder_names, cq_mirror_builder_names).
 
diff --git a/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py b/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py
index d967eb1..30e461d1 100644
--- a/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py
@@ -104,7 +104,7 @@
                 'main': "luci",
                 'has_webdriver_tests': True
             },
-            'Flag Specific A': {
+            'Flag Specific C': {
                 'port_name': 'port-c',
                 'specifiers': ['C', 'Release'],
                 'steps': {
@@ -132,7 +132,7 @@
             'CQ Try A',
             'CQ Try B',
             'CQ Try C',
-            'Flag Specific A',
+            'Flag Specific C',
             'Try A',
             'Try B',
             'some-wpt-bot',
@@ -147,7 +147,7 @@
     def test_all_try_builder_names(self):
         builders = self.sample_builder_list()
         self.assertEqual([
-            'CQ Try A', 'CQ Try B', 'CQ Try C', 'Flag Specific A', 'Try A',
+            'CQ Try A', 'CQ Try B', 'CQ Try C', 'Flag Specific C', 'Try A',
             'Try B', 'some-wpt-bot'
         ], builders.all_try_builder_names())
 
@@ -159,16 +159,21 @@
 
     def test_all_flag_specific_builder_names(self):
         builders = self.sample_builder_list()
-        self.assertEqual(['CQ Try C', 'Flag Specific A'],
+        self.assertEqual(['CQ Try C', 'Flag Specific C'],
                          builders.all_flag_specific_try_builder_names(
                              flag_specific="highdpi"))
         self.assertEqual(
-            ['CQ Try C', 'Flag Specific A'],
+            ['CQ Try C', 'Flag Specific C'],
             builders.all_flag_specific_try_builder_names(flag_specific="*"))
 
+    def test_builders_for_rebaselining(self):
+        builders = self.sample_builder_list()
+        self.assertEqual({'Try A', 'Try B', 'CQ Try B', 'Flag Specific C'},
+                         builders.builders_for_rebaselining())
+
     def test_try_bots_with_cq_mirror(self):
         builders = self.sample_builder_list()
-        try_and_cq = [('Flag Specific A', 'CQ Try C'), ('Try A', 'CQ Try A')]
+        try_and_cq = [('Flag Specific C', 'CQ Try C'), ('Try A', 'CQ Try A')]
         self.assertEqual(try_and_cq, builders.try_bots_with_cq_mirror())
 
     def test_all_port_names(self):
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index c5a61df..39e782d 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -51,7 +51,8 @@
   {
     "prefix": "gpu",
     "platforms": ["Linux", "Mac", "Win", "Fuchsia"],
-    "bases": ["fast/canvas"],
+    "bases": [ "fast/canvas",
+               "external/wpt/mediacapture-record/MediaRecorder-canvas-media-source.https.html" ],
     "args": ["--enable-accelerated-2d-canvas"],
     "expires": "Jul 1, 2023"
   },
@@ -1029,7 +1030,8 @@
   {
     "prefix": "oopr-canvas2d",
     "platforms": ["Linux", "Mac", "Win"],
-    "bases": [ "fast/canvas" ],
+    "bases": [ "fast/canvas",
+               "external/wpt/mediacapture-record/MediaRecorder-canvas-media-source.https.html" ],
     "args": [ "--enable-features=CanvasOopRasterization",
               "--enable-accelerated-2d-canvas",
               "--enable-gpu-rasterization" ],
diff --git a/third_party/blink/web_tests/external/wpt/credential-management/fedcm-multi-idp/abort-multiple-gets-through-first-idp.https.html b/third_party/blink/web_tests/external/wpt/credential-management/fedcm-multi-idp/abort-multiple-gets-through-first-idp.https.html
new file mode 100644
index 0000000..eb9f7da
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/credential-management/fedcm-multi-idp/abort-multiple-gets-through-first-idp.https.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Federated Credential Management API multi IDP abort first IDP test.</title>
+<link rel="help" href="https://fedidcg.github.io/FedCM">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script type="module">
+  import {
+    set_fedcm_cookie,
+    set_alt_fedcm_cookie,
+    default_request_options,
+    default_alt_request_options
+  } from '../support/fedcm-helper.sub.js';
+
+  let cookies_promise = Promise.all([set_fedcm_cookie(), set_alt_fedcm_cookie()]);
+
+  promise_test(async t => {
+    let first_controller = new AbortController();
+    let first_test_options = default_request_options();
+    first_test_options.signal = first_controller.signal;
+    const first_cred = navigator.credentials.get(first_test_options);
+
+    let second_controller = new AbortController();
+    let second_test_options = default_alt_request_options();
+    second_test_options.signal = second_controller.signal;
+    const second_cred = navigator.credentials.get(second_test_options);
+
+    await cookies_promise;
+    first_controller.abort();
+    return Promise.all([
+      promise_rejects_dom(t, 'AbortError', first_cred),
+      promise_rejects_dom(t, 'AbortError', second_cred)
+    ]);
+  }, "Test abort signal for a multi IDP request by aborting the first IDP");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/credential-management/fedcm-multi-idp/abort-multiple-gets-through-second-idp.https.html b/third_party/blink/web_tests/external/wpt/credential-management/fedcm-multi-idp/abort-multiple-gets-through-second-idp.https.html
new file mode 100644
index 0000000..7e7ec2c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/credential-management/fedcm-multi-idp/abort-multiple-gets-through-second-idp.https.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Federated Credential Management API multi IDP abort second IDP test.</title>
+<link rel="help" href="https://fedidcg.github.io/FedCM">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script type="module">
+  import {
+    set_fedcm_cookie,
+    set_alt_fedcm_cookie,
+    default_request_options,
+    default_alt_request_options
+  } from '../support/fedcm-helper.sub.js';
+
+  let cookies_promise = Promise.all([set_fedcm_cookie(), set_alt_fedcm_cookie()]);
+
+  promise_test(async t => {
+    let first_controller = new AbortController();
+    let first_test_options = default_request_options();
+    first_test_options.signal = first_controller.signal;
+    const first_cred = navigator.credentials.get(first_test_options);
+
+    let second_controller = new AbortController();
+    let second_test_options = default_alt_request_options();
+    second_test_options.signal = second_controller.signal;
+    const second_cred = navigator.credentials.get(second_test_options);
+
+    await cookies_promise;
+    second_controller.abort();
+    return Promise.all([
+      promise_rejects_dom(t, 'AbortError', first_cred),
+      promise_rejects_dom(t, 'AbortError', second_cred)
+    ]);
+  }, "Test abort signal for a multi IDP request by aborting the second IDP");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/credential-management/fedcm-multi-idp/multiple-gets-after-abort.https.html b/third_party/blink/web_tests/external/wpt/credential-management/fedcm-multi-idp/multiple-gets-after-abort.https.html
new file mode 100644
index 0000000..b7b03e4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/credential-management/fedcm-multi-idp/multiple-gets-after-abort.https.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<title>Federated Credential Management API multi IDP get after abort test.</title>
+<link rel="help" href="https://fedidcg.github.io/FedCM">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script type="module">
+  import {
+    set_fedcm_cookie,
+    set_alt_fedcm_cookie,
+    default_request_options,
+    default_alt_request_options
+  } from '../support/fedcm-helper.sub.js';
+
+  let cookies_promise = Promise.all([set_fedcm_cookie(), set_alt_fedcm_cookie()]);
+
+  promise_test(async t => {
+    let first_controller = new AbortController();
+    let first_test_options = default_request_options();
+    first_test_options.signal = first_controller.signal;
+    const first_cred = navigator.credentials.get(first_test_options);
+
+    let second_controller = new AbortController();
+    let second_test_options = default_alt_request_options();
+    second_test_options.signal = second_controller.signal;
+    const second_cred = navigator.credentials.get(second_test_options);
+
+    await cookies_promise;
+    second_controller.abort();
+    await Promise.all([
+      promise_rejects_dom(t, 'AbortError', first_cred),
+      promise_rejects_dom(t, 'AbortError', second_cred)
+    ]);
+
+    const third_cred = navigator.credentials.get(default_request_options());
+    const fourth_cred = navigator.credentials.get(default_alt_request_options());
+
+    // NetworkError is returned when another IDP is selected.
+    await promise_rejects_dom(t, 'NetworkError', fourth_cred);
+    const cred = await third_cred;
+    assert_equals(cred.token, "token");
+  }, "Multiple gets after aborting a multi IDP request should work");
+</script>
diff --git a/third_party/blink/web_tests/paint/invalidation/outline/inline-outline-repaint-2-expected.txt b/third_party/blink/web_tests/paint/invalidation/outline/inline-outline-repaint-2-expected.txt
index 230f7fe..6243bc7 100644
--- a/third_party/blink/web_tests/paint/invalidation/outline/inline-outline-repaint-2-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/outline/inline-outline-repaint-2-expected.txt
@@ -6,7 +6,7 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [210, 0, 50, 15]
+        [215, 0, 40, 10]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/virtual/gpu/fast/canvas/README.txt b/third_party/blink/web_tests/virtual/gpu/README.md
similarity index 100%
rename from third_party/blink/web_tests/virtual/gpu/fast/canvas/README.txt
rename to third_party/blink/web_tests/virtual/gpu/README.md
diff --git a/third_party/blink/web_tests/virtual/oopr-canvas2d/fast/canvas/README.txt b/third_party/blink/web_tests/virtual/oopr-canvas2d/README.md
similarity index 100%
rename from third_party/blink/web_tests/virtual/oopr-canvas2d/fast/canvas/README.txt
rename to third_party/blink/web_tests/virtual/oopr-canvas2d/README.md
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index eaa7bd2..8bba2fd 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -55,7 +55,7 @@
     getter errorMessage
     getter expanded
     getter flowTo
-    getter hasPopUp
+    getter hasPopup
     getter hidden
     getter invalid
     getter keyShortcuts
@@ -111,7 +111,7 @@
     setter errorMessage
     setter expanded
     setter flowTo
-    setter hasPopUp
+    setter hasPopup
     setter hidden
     setter invalid
     setter keyShortcuts
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium
index 09319fb..9353003 100644
--- a/third_party/nearby/README.chromium
+++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@
 Name: Nearby Connections Library
 Short Name: Nearby
 URL: https://github.com/google/nearby
-Version: f7f0a266fe5baf2abc96564e696e666d24b54920
+Version: d347d0688b698100506e9dcaf227d3b69c78df67
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/r8/print_version.sh b/third_party/r8/print_version.sh
index e936996e..8d219e96 100755
--- a/third_party/r8/print_version.sh
+++ b/third_party/r8/print_version.sh
@@ -1,16 +1,17 @@
 #!/bin/bash
-# Copyright 2022 The Chromium Authors
+# Copyright 2023 The Chromium Authors
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-cipd_hash=$1
-if [[ -z "$cipd_hash" ]]; then
-  cd "$(dirname $0)/../.."
-  export DEPOT_TOOLS_UPDATE=0
-  cipd_hash=$(gclient getdep -r src/third_party/r8:chromium/third_party/r8)
-fi
-echo "CIPD instance: $cipd_hash"
-# Multiple version tags can exist when 3pp bot runs again but R8.jar doesn't change.
-r8_commit=$(cipd describe chromium/third_party/r8 -version "$cipd_hash" | grep --max-count=1 "version:" | grep -P --only-matching '(?<=@).*(?=-)')
-echo "R8 commit: $r8_commit"
-echo "Recent commits: https://r8.googlesource.com/r8/+log/$r8_commit"
+set -e
+DIR_SRC_ROOT=$(pwd)/
+DIR_SRC_ROOT=${DIR_SRC_ROOT%/src/*}/src
+SUBDIR=$(cd $(dirname $0); pwd)
+SUBDIR="${SUBDIR#$DIR_SRC_ROOT/}"
+CIPD_PACKAGE=chromium/$SUBDIR
+
+exec $DIR_SRC_ROOT/build/android/print_cipd_version.py \
+    --subdir "$SUBDIR" \
+    --cipd-package "$CIPD_PACKAGE" \
+    --git-log-url "https://r8.googlesource.com/r8/+log/{}" \
+    "$@"
diff --git a/third_party/turbine/README.chromium b/third_party/turbine/README.chromium
index 20512294..0da595ca 100644
--- a/third_party/turbine/README.chromium
+++ b/third_party/turbine/README.chromium
@@ -14,21 +14,14 @@
 it in GN, so we are using a prebuilt jar encapsulating all of its dependencies.
 
 What version is this:
-  * turbine is now autorolled.
-  * To lookup the latest version being used currently:
-    * Look up the cipd instance id from //DEPS, or run
-      `gclient getdep -r src/third_party/turbine:chromium/third_party/turbine`.
-    * Find the version tag at this url
-      https://chrome-infra-packages.appspot.com/p/chromium/third_party/turbine/+/<instance id>
-    * Or, run `cipd describe chromium/third_party/turbine -version <instance id>` and look at the version tag.
-    * The version string appears after the @ symbol in the tag.
+  * Run print_version.sh to find out the version.
   * New instances are uploaded by the packager bot:
     https://ci.chromium.org/p/chromium/builders/ci/3pp-linux-amd64-packager
-  * The bot autoruns every 6 hours. Ping a trooper or a clank build core dev to
+  * The bot autoruns every 6 hours. Ping a trooper or a clank-build-core@ dev to
     trigger it if you need it sooner:
     https://luci-scheduler.appspot.com/jobs/chromium/3pp-linux-amd64-packager
-  * The autoroller runs automatically when a new cipd instance is uploaded, see
-    its status here: https://autoroll.skia.org/r/turbine-chromium
+  * New versions are rolled automatically by:
+    https://autoroll.skia.org/r/turbine-chromium
 
 Local Modifications:
 No modifications.
diff --git a/third_party/turbine/print_version.sh b/third_party/turbine/print_version.sh
new file mode 100755
index 0000000..1fd6da657
--- /dev/null
+++ b/third_party/turbine/print_version.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# 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.
+
+set -e
+DIR_SRC_ROOT=$(pwd)/
+DIR_SRC_ROOT=${DIR_SRC_ROOT%/src/*}/src
+SUBDIR=$(cd $(dirname $0); pwd)
+SUBDIR="${SUBDIR#$DIR_SRC_ROOT/}"
+CIPD_PACKAGE=chromium/$SUBDIR
+
+exec $DIR_SRC_ROOT/build/android/print_cipd_version.py \
+    --subdir "$SUBDIR" \
+    --cipd-package "$CIPD_PACKAGE" \
+    --git-log-url "https://github.com/google/turbine/commits/{}" \
+    "$@"
diff --git a/tools/attribution_reporting/simulator_main.cc b/tools/attribution_reporting/simulator_main.cc
index b49fd030..169a580 100644
--- a/tools/attribution_reporting/simulator_main.cc
+++ b/tools/attribution_reporting/simulator_main.cc
@@ -36,7 +36,6 @@
     "randomized_response_rate_navigation";
 constexpr char kSwitchRandomizedResponseRateEvent[] =
     "randomized_response_rate_event";
-constexpr char kSwitchRemoveActualReportTimes[] = "remove_actual_report_times";
 constexpr char kSwitchRemoveAssembledReport[] = "remove_assembled_report";
 
 constexpr const char* kAllowedSwitches[] = {
@@ -52,7 +51,6 @@
     kSwitchCopyInputToOutput,
     kSwitchRandomizedResponseRateNavigation,
     kSwitchRandomizedResponseRateEvent,
-    kSwitchRemoveActualReportTimes,
 };
 
 constexpr char kHelpMsg[] = R"(
@@ -65,7 +63,6 @@
   [--input_mode=<input_mode>]
   [--remove_report_ids]
   [--remove_assembled_report]
-  [--remove_actual_report_times]
 
 attribution_reporting_simulator is a command-line tool that simulates the
 Attribution Reporting API for for sources and triggers specified in an input
@@ -140,11 +137,6 @@
                               generated. Use this switch to make the tool's
                               output more deterministic.
 
-  --remove_actual_report_times
-                            - Optional. If present, removes the `report_time`
-                              field from reports, as they are subject to
-                              implementation details.
-
   --version                 - Outputs the tool version and exits.
 
 See //content/test/data/attribution_reporting/simulator/README.md
@@ -317,8 +309,6 @@
                   command_line.HasSwitch(kSwitchRemoveReportIds),
               .remove_assembled_report =
                   command_line.HasSwitch(kSwitchRemoveAssembledReport),
-              .remove_actual_report_times =
-                  command_line.HasSwitch(kSwitchRemoveActualReportTimes),
           },
   });
 
diff --git a/tools/binary_size/libsupersize/integration_test.py b/tools/binary_size/libsupersize/integration_test.py
index bad83b9..5fad410 100755
--- a/tools/binary_size/libsupersize/integration_test.py
+++ b/tools/binary_size/libsupersize/integration_test.py
@@ -67,6 +67,9 @@
     'assets/icudtl.dat': '../../third_party/icu/android/icudtl.dat',
 }
 
+_TEST_DEX_AFTER_PATH = os.path.join(_TEST_DATA_DIR,
+                                    'mock_dex/after/classes.dex')
+
 
 def _CompareWithGolden(name=None):
   def real_decorator(func):
@@ -147,9 +150,7 @@
       apk_file.write(_TEST_APK_LOCALE_PAK_PATH, locale_pak_rel_path)
       pak_rel_path = os.path.relpath(_TEST_APK_PAK_PATH, _TEST_APK_ROOT_DIR)
       apk_file.write(_TEST_APK_PAK_PATH, pak_rel_path)
-      # Exactly 8MB of data (2^23).
-      apk_file.writestr(
-          _TEST_APK_DEX_PATH, IntegrationTest._CreateBlankData(23))
+      apk_file.write(_TEST_DEX_AFTER_PATH, _TEST_APK_DEX_PATH)
 
     with zipfile.ZipFile(_TEST_NOT_ON_DEMAND_SPLIT_APK_PATH, 'w') as z:
       z.write(_TEST_ALWAYS_INSTALLED_MANIFEST_PATH, 'AndroidManifest.xml')
@@ -365,6 +366,21 @@
 
     _RunApp('archive', args, debug_measures=debug_measures)
 
+  def _FixupExpectedSizeInfoForMinimalApks(self, expected_size_info):
+    # DEX string symbols "actual" size_info have object_path assigned to
+    # '$SYSTEM/base-master.apk', which is from the value written to minimal
+    # apks file. Meanwhile, the correpsonding symbols in "expected" are
+    # '$SYSTEM/test.apk' because that's the file passed.
+    # * Changing both to "test.apk" is bad because SuperSize has code to
+    #   handle '-master.apk' filename.
+    # * Changing both to "base-master.apk" is bad because the name "test.apk"
+    #   is engrained in the test.
+    # As a kludge, here we mutate "expected" values for the affected symbols.
+    for sym in expected_size_info.raw_symbols:
+      if (sym.section_name == models.SECTION_DEX
+          and sym.object_path == '$SYSTEM/test.apk'):
+        sym.object_path = '$SYSTEM/base-master.apk'
+
   def _DoArchiveTest(self,
                      *,
                      use_output_directory=True,
@@ -399,6 +415,8 @@
         use_pak=use_pak,
         use_aux_elf=use_aux_elf,
         ignore_linker_map=ignore_linker_map)
+    if use_minimal_apks:
+      self._FixupExpectedSizeInfoForMinimalApks(expected_size_info)
     self.assertEqual(_AllMetadata(expected_size_info), _AllMetadata(size_info))
     # Don't cluster.
     expected_size_info.symbols = expected_size_info.raw_symbols
diff --git a/tools/binary_size/libsupersize/test_util.py b/tools/binary_size/libsupersize/test_util.py
index b58b5c3..3783395 100644
--- a/tools/binary_size/libsupersize/test_util.py
+++ b/tools/binary_size/libsupersize/test_util.py
@@ -19,6 +19,11 @@
 TEST_OUTPUT_DIR = os.path.join(TEST_SOURCE_DIR, 'out', 'Release')
 
 
+# Helper to make presubmit happy with .golden files.
+def _Neutralize(line):
+  return line + ' # nocheck' if '-master.' in line else line
+
+
 class Golden:
   """Utility to use or manage "Golden" test files."""
 
@@ -33,12 +38,12 @@
   def CheckOrUpdate(golden_path, actual_lines):
     if Golden.do_update:
       with open(golden_path, 'w') as file_obj:
-        describe.WriteLines(actual_lines, file_obj.write)
+        describe.WriteLines(map(_Neutralize, actual_lines), file_obj.write)
       logging.info('Wrote %s', golden_path)
     else:
       with open(golden_path) as file_obj:
         expected = list(file_obj)
-        actual = list(l + '\n' for l in actual_lines)
+        actual = list(_Neutralize(l) + '\n' for l in actual_lines)
         assert actual == expected, (
             ('Did not match %s.\n' % golden_path) + ''.join(
                 difflib.unified_diff(expected, actual, 'expected', 'actual')))
diff --git a/tools/binary_size/libsupersize/testdata/ArchiveContainers.golden b/tools/binary_size/libsupersize/testdata/ArchiveContainers.golden
index 4044ea2..05e794c9 100644
--- a/tools/binary_size/libsupersize/testdata/ArchiveContainers.golden
+++ b/tools/binary_size/libsupersize/testdata/ArchiveContainers.golden
@@ -30,7 +30,7 @@
 Container1:
 apk_file_name=test.apk
 apk_signature_block_size=0
-apk_size=147858965
+apk_size=139472373
 zipalign_padding=32
 Symbols:
 <Container1:/test.so (armeabi-v7a)>.text@28d900(size_without_padding=16,padding=0,full_name=_GLOBAL__sub_I_page_allocator.cc,object_path=base/base/page_allocator.o,source_path=base/page_allocator.cc,flags={startup},num_aliases=1,component=Blink>Internal)
@@ -201,210 +201,33 @@
 <Container1:/smalltest.so (x86)>.other@0(size_without_padding=36,padding=0,full_name=** ELF Section: .note.gnu.build-id,object_path=,source_path=$NATIVE/smalltest.so (arm),flags={},num_aliases=1,component=)
 <Container1:/smalltest.so (x86)>.other@0(size_without_padding=2655384,padding=0,full_name=** ELF Section: .rel.dyn,object_path=,source_path=$NATIVE/smalltest.so (arm),flags={},num_aliases=1,component=)
 <Container1:/smalltest.so (x86)>.other@0(size_without_padding=0,padding=1524724,full_name=Overhead: ELF file,object_path=,source_path=$NATIVE/smalltest.so (arm),flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=1792,padding=0,full_name=org,object_path=$APK/org,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=975347,padding=0,full_name=org.chromium,object_path=$APK/org/chromium,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=44714,padding=0,full_name=org.chromium.chrome,object_path=$APK/org/chromium/chrome,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=2522400,padding=0,full_name=org.chromium.chrome.browser,object_path=$APK/org/chromium/chrome/browser,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=111986,padding=0,full_name=org.chromium.chrome.browser.compositor,object_path=$APK/org/chromium/chrome/browser/compositor,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=58449,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts,object_path=$APK/org/chromium/chrome/browser/compositor/layouts,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=23896,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=7566,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=40,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=12,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#$assertionsDisabled: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=11,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mAnimationFactory: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mBorderLeftPadding: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mBorderTopPadding: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mBorderTransparentSide: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mBorderTransparentTop: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mCurrentMode: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mCurrentScrollDirection: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mDiscardDirection: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mDiscardingTab: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mDragLock$7be2905e: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mEvenOutProgress: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mEvenOutRate: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mInSwipe: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mIsDying: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mIsStackForCurrentTabList: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mLastPinch0Offset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mLastPinch1Offset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mLastScrollUpdate: long,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mLayout: org.chromium.chrome.browser.compositor.layouts.phone.StackLayout,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mLongPressSelected: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMaxOverScroll: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMaxOverScrollAngle: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMaxOverScrollSlide: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMaxUnderScroll: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMinScrollMotion: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMinSpacing: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverScrollAngleInterpolator: android.view.animation.Interpolator,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverScrollCounter: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverScrollDerivative: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverScrollOffset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverscrollSlideInterpolator: android.view.animation.Interpolator,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverviewAnimationType$5d025a5c: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mPinch0TabIndex: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mPinch1TabIndex: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mRecomputePosition: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mReferenceOrderIndex: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mScrollOffset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mScrollOffsetForDyingTabs: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mScrollTarget: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mScroller: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mScrollingTab: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mSpacing: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mStackTabs: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mSwipeBoundedScrollOffset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mSwipeCanScroll: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mSwipeIsCancelable: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mSwipeUnboundScrollOffset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mTabAnimations: org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mTabList: org.chromium.chrome.browser.tabmodel.TabList,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mUnderScrollAngleInterpolator: android.view.animation.Interpolator,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mViewAnimationFactory: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackViewAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mViewAnimations: android.animation.Animator,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mViewAnimatorListener: android.animation.AnimatorListenerAdapter,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mWarpSize: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation.DRAG_ANGLE_THRESHOLD: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=40,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=11,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mBorderTopHeight: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mBorderTopOpaqueHeight: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mHeight: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mHeightMinusBrowserControls: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mStack: org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mWidth: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$$Lambda$0,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$$Lambda$0#$instance: Object,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$0,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$0#$instance: Object,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=220,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$1,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzkB/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested2$$Lambda$0,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested2$$Lambda$0#$instance: Object,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=104,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=40,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=11,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#DECELERATION_RATE: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#SPLINE_POSITION: float[],object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#SPLINE_TIME: float[],object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=11,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mCurrVelocity: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mCurrentPosition: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mDeceleration: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mDuration: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mFinal: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mFinished: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mFlingFriction: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mOver: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mPhysicalCoeff: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mSplineDistance: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mSplineDuration: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mStart: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mStartTime: long,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mState: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mVelocity: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex@0(size_without_padding=4616803,padding=0,full_name=** .dex (unattributed - includes string literals),object_path=,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=113,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#<clinit>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=225,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#<init>(android.content.Context,org.chromium.chrome.browser.compositor.layouts.phone.StackLayout),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=61,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#access$000(org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack): org.chromium.chrome.browser.compositor.layouts.phone.StackLayout,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=90,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#approxScreen(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab,float): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=64,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#cleanupTabs(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=261,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#commitDiscard(long,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=112,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeDiscardAlpha(float,float): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=136,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeDiscardScale(float,float,boolean): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=88,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeOverscrollPercent(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=253,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeSpacing(int): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=969,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabClippingVisibilityHelper(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=1512,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabOffsetHelper(android.graphics.RectF): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=318,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabPosition(long,android.graphics.RectF): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=217,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabScrollOffsetHelper(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=1008,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabTiltHelper(long,android.graphics.RectF): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=560,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabVisibilitySortingHelper(android.graphics.RectF): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=322,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#contextChanged(android.content.Context): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=563,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#createStackTabs(boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=1521,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#drag(long,float,float,float,float): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=446,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#evenOutTabs(float,boolean): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=813,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#finishAnimation(long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=223,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#finishAnimationsIfDone(long,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=503,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#fling(long,float,float,float,float): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=68,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getCount(): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=84,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getDefaultDiscardDirection(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=79,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getMaxScroll(boolean): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=113,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getMaxTabHeight(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=196,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getMinScroll(boolean): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=105,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getRange(float): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=94,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getScrollDimensionSize(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=128,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getStackScale(android.graphics.RectF): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=87,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getTabAtPositon(float,float): org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=360,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getTabIndexAtPositon(float,float,float): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=121,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getVisibleCount(): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=96,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#isDisplayable(): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=400,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#notifySizeChanged$483d2f6e(int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=107,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#onUpOrCancel(long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=341,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#onUpdateCompositorAnimations(long,boolean): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=101,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#onUpdateViewAnimation(long,boolean): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=100,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation.allowOverscroll(): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=68,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#requestUpdate(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=79,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#resetInputActionIndices(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=69,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#screenToScroll(float): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=69,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#scrollToScreen(float): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=134,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#setScrollTarget(float,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=121,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#setStackFocusInfo(float,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=244,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#setWarpState(boolean,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=219,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#springBack(long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=919,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#startAnimation$62adfb33(long,int,int,int,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=77,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#startAnimation$6848a047(long,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=95,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#startAnimation$78b04ab8(long,int,int,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=137,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#stopScrollingMovement(long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=142,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#swipeCancelled(long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=266,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#tabClosingEffect(long,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=217,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#updateOverscrollOffset(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=112,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#<init>(org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack,float,float,float,float,float),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=40,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#addTiltScrollAnimation(org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,org.chromium.chrome.browser.compositor.layouts.components.LayoutTab,float,int,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=1055,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createAnimatorSetForType$2fab410e$104f6ddb(int,org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,int,float,float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=36,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createEnterStackAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=139,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createNewTabOpenedAnimatorSet$4078c09e(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[]): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=32,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createReachTopAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=36,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createTabFocusedAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=32,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createViewMoreAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=30,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#getScreenPositionInScrollDirection(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=24,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#getScreenSizeInScrollDirection(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=92,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#getStaticTabPosition(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=67,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#getToolbarOffsetToLineUpWithBorder(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=24,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#isDefaultDiscardDirectionPositive(): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$$Lambda$0#<init>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$0#<init>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$1#<init>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzkB/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested2$$Lambda$0#<init>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=82,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#<init>(org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack,float,float,float,float,float),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=106,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#addTiltScrollAnimation(org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,org.chromium.chrome.browser.compositor.layouts.components.LayoutTab,float,int,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=592,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#createEnterStackAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=59,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#createNewTabOpenedAnimatorSet$4078c09e(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[]): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#createReachTopAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=961,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#createTabFocusedAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=256,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#createViewMoreAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=79,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#getScreenPositionInScrollDirection(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=54,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#getScreenSizeInScrollDirection(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=52,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#isDefaultDiscardDirectionPositive(): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=471,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#<clinit>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=146,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#<init>(android.content.Context),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$000(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=65,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$002(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller,boolean): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$100(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$200(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$300(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): long,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$400(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$500(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=176,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#adjustDuration(int,int,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=218,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#continueWhenFinished(long): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=66,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#finish(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=660,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#fling(int,int,int,int,int,long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=71,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#getDeceleration(int): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=97,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#getSplineDeceleration(int): double,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=115,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#getSplineFlingDistance(int): double,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=220,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#onEdgeReached(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=138,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#springback(int,int,int,long): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=109,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#startScroll(int,int,long,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=167,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#startSpringback$4868d30e(int,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=440,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#update(long): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Container1:>.dex.method@0(size_without_padding=90,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#updateScroll(float): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
+<Container1:>.dex@0(size_without_padding=6,padding=0,full_name="",object_path=$SYSTEM/test.apk,source_path=$APK/AuxClass,flags={},num_aliases=1,component=)
+<Container1:>.dex@0(size_without_padding=7,padding=0,full_name="1",object_path=$SYSTEM/test.apk,source_path=$APK/AuxClass,flags={},num_aliases=1,component=)
+<Container1:>.dex@0(size_without_padding=34,padding=0,full_name="Complex roots not supported.",object_path=$SYSTEM/test.apk,source_path=$APK/TestClass,flags={},num_aliases=1,component=)
+<Container1:>.dex@0(size_without_padding=20,padding=0,full_name="a cannot be 0.",object_path=$SYSTEM/test.apk,source_path=$APK/TestClass,flags={},num_aliases=1,component=)
+<Container1:>.dex@0(size_without_padding=40,padding=0,full_name=AuxClass,object_path=$APK/AuxClass,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex@0(size_without_padding=10,padding=0,full_name=AuxClass#mRepeat: int,object_path=$APK/AuxClass,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex@0(size_without_padding=57,padding=0,full_name=TestClass,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex@0(size_without_padding=12,padding=0,full_name=TestClass#REPEAT: int,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex@0(size_without_padding=0,padding=0,full_name=java.lang.IllegalArgumentException,object_path=$APK/java/lang/IllegalArgumentException,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex@0(size_without_padding=0,padding=0,full_name=java.lang.Math,object_path=$APK/java/lang/Math,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex@0(size_without_padding=0,padding=0,full_name=java.lang.Object,object_path=$APK/java/lang/Object,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex@0(size_without_padding=0,padding=0,full_name=java.lang.StringBuilder,object_path=$APK/java/lang/StringBuilder,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex@0(size_without_padding=1260,padding=0,full_name=** .dex (unattributed - includes string literals),object_path=,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex.method@0(size_without_padding=42,padding=0,full_name=AuxClass#<init>(int),object_path=$APK/AuxClass,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex.method@0(size_without_padding=90,padding=0,full_name=AuxClass#repeatString(java.lang.String): java.lang.String,object_path=$APK/AuxClass,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex.method@0(size_without_padding=62,padding=0,full_name=AuxClass#reverse(int[]): int[],object_path=$APK/AuxClass,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex.method@0(size_without_padding=38,padding=0,full_name=TestClass#<init>(),object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex.method@0(size_without_padding=62,padding=0,full_name=TestClass#gcd(long,long): long,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex.method@0(size_without_padding=58,padding=0,full_name=TestClass#lcm(long,long): long,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex.method@0(size_without_padding=120,padding=0,full_name=TestClass#quadHi(double,double,double): double,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex.method@0(size_without_padding=50,padding=0,full_name=TestClass#repeat(java.lang.String): java.lang.String,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.IllegalArgumentException#<init>(java.lang.String),object_path=$APK/java/lang/IllegalArgumentException,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.Math#sqrt(double): double,object_path=$APK/java/lang/Math,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.Object#<init>(),object_path=$APK/java/lang/Object,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.StringBuilder#<init>(),object_path=$APK/java/lang/StringBuilder,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.StringBuilder#append(java.lang.String): java.lang.StringBuilder,object_path=$APK/java/lang/StringBuilder,source_path=,flags={},num_aliases=1,component=)
+<Container1:>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.StringBuilder#toString(): java.lang.String,object_path=$APK/java/lang/StringBuilder,source_path=,flags={},num_aliases=1,component=)
 <Container1:>.pak.nontranslated@2f03(size_without_padding=502,padding=0,full_name=../../chrome/browser/browser_resources.grd: IDR_PDF_COMPOSITOR_MANIFEST,object_path=,source_path=,flags={uncompressed},num_aliases=1,component=)
 <Container1:>.pak.nontranslated@2f04(size_without_padding=217,padding=0,full_name=../../chrome/browser/browser_resources.grd: IDR_CHROME_RENDERER_SERVICE_MANIFEST,object_path=,source_path=,flags={},num_aliases=1,component=)
 <Container1:>.pak.nontranslated@0(size_without_padding=0,padding=18,full_name=Overhead: assets/resources.pak,object_path=,source_path=,flags={},num_aliases=1,component=)
diff --git a/tools/binary_size/libsupersize/testdata/Archive_Apk.golden b/tools/binary_size/libsupersize/testdata/Archive_Apk.golden
index c0aa437..baf0d26 100644
--- a/tools/binary_size/libsupersize/testdata/Archive_Apk.golden
+++ b/tools/binary_size/libsupersize/testdata/Archive_Apk.golden
@@ -17,7 +17,7 @@
 elf_build_id=WhatAnAmazingBuildId
 apk_file_name=test.apk
 apk_signature_block_size=0
-apk_size=147858965
+apk_size=139472373
 zipalign_padding=32
 Container <test.apk/test.so (armeabi-v7a)>
 Section .text: has 100.0% of 35982248 bytes accounted for from 23 symbols. 0 bytes are unaccounted for.
@@ -169,15 +169,15 @@
 * 0 have source paths. Accounts for 0 bytes (0.0%).
 * 0 have a component assigned. Accounts for 0 bytes (0.0%).
 * 0 symbols have shared ownership.
-Section .dex: has 100.0% of 8364863 bytes accounted for from 100 symbols. 0 bytes are unaccounted for.
+Section .dex: has 100.0% of 1446 bytes accounted for from 13 symbols. 0 bytes are unaccounted for.
 * Padding accounts for 0 bytes (0.0%)
-* 90 have source paths. Accounts for 1806 bytes (0.0%).
+* 4 have source paths. Accounts for 67 bytes (4.6%).
 * 0 have a component assigned. Accounts for 0 bytes (0.0%).
-* 1 placeholders exist (symbols that start with **). Accounts for 4616803 bytes (55.2%).
+* 1 placeholders exist (symbols that start with **). Accounts for 1260 bytes (87.1%).
 * 0 symbols have shared ownership.
-Section .dex.method: has 100.0% of 23745 bytes accounted for from 104 symbols. 0 bytes are unaccounted for.
+Section .dex.method: has 100.0% of 570 bytes accounted for from 14 symbols. 0 bytes are unaccounted for.
 * Padding accounts for 0 bytes (0.0%)
-* 94 have source paths. Accounts for 21294 bytes (89.7%).
+* 0 have source paths. Accounts for 0 bytes (0.0%).
 * 0 have a component assigned. Accounts for 0 bytes (0.0%).
 * 0 symbols have shared ownership.
 Section .pak.translations: has 100.0% of 6821 bytes accounted for from 207 symbols. 0 bytes are unaccounted for.
@@ -286,210 +286,33 @@
 <test.apk/smalltest.so (x86)>.other@0(size_without_padding=36,padding=0,full_name=** ELF Section: .note.gnu.build-id,object_path=,source_path=$NATIVE/smalltest.so (arm),flags={},num_aliases=1,component=)
 <test.apk/smalltest.so (x86)>.other@0(size_without_padding=2655384,padding=0,full_name=** ELF Section: .rel.dyn,object_path=,source_path=$NATIVE/smalltest.so (arm),flags={},num_aliases=1,component=)
 <test.apk/smalltest.so (x86)>.other@0(size_without_padding=0,padding=1524724,full_name=Overhead: ELF file,object_path=,source_path=$NATIVE/smalltest.so (arm),flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=1792,padding=0,full_name=org,object_path=$APK/org,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=975347,padding=0,full_name=org.chromium,object_path=$APK/org/chromium,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=44714,padding=0,full_name=org.chromium.chrome,object_path=$APK/org/chromium/chrome,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=2522400,padding=0,full_name=org.chromium.chrome.browser,object_path=$APK/org/chromium/chrome/browser,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=111986,padding=0,full_name=org.chromium.chrome.browser.compositor,object_path=$APK/org/chromium/chrome/browser/compositor,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=58449,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts,object_path=$APK/org/chromium/chrome/browser/compositor/layouts,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=23896,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=7566,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=40,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=12,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#$assertionsDisabled: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=11,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mAnimationFactory: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mBorderLeftPadding: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mBorderTopPadding: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mBorderTransparentSide: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mBorderTransparentTop: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mCurrentMode: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mCurrentScrollDirection: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mDiscardDirection: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mDiscardingTab: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mDragLock$7be2905e: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mEvenOutProgress: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mEvenOutRate: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mInSwipe: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mIsDying: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mIsStackForCurrentTabList: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mLastPinch0Offset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mLastPinch1Offset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mLastScrollUpdate: long,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mLayout: org.chromium.chrome.browser.compositor.layouts.phone.StackLayout,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mLongPressSelected: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMaxOverScroll: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMaxOverScrollAngle: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMaxOverScrollSlide: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMaxUnderScroll: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMinScrollMotion: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMinSpacing: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverScrollAngleInterpolator: android.view.animation.Interpolator,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverScrollCounter: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverScrollDerivative: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverScrollOffset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverscrollSlideInterpolator: android.view.animation.Interpolator,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverviewAnimationType$5d025a5c: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mPinch0TabIndex: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mPinch1TabIndex: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mRecomputePosition: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mReferenceOrderIndex: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mScrollOffset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mScrollOffsetForDyingTabs: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mScrollTarget: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mScroller: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mScrollingTab: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mSpacing: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mStackTabs: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mSwipeBoundedScrollOffset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mSwipeCanScroll: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mSwipeIsCancelable: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mSwipeUnboundScrollOffset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mTabAnimations: org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mTabList: org.chromium.chrome.browser.tabmodel.TabList,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mUnderScrollAngleInterpolator: android.view.animation.Interpolator,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mViewAnimationFactory: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackViewAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mViewAnimations: android.animation.Animator,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mViewAnimatorListener: android.animation.AnimatorListenerAdapter,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mWarpSize: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation.DRAG_ANGLE_THRESHOLD: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=40,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=11,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mBorderTopHeight: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mBorderTopOpaqueHeight: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mHeight: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mHeightMinusBrowserControls: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mStack: org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mWidth: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$$Lambda$0,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$$Lambda$0#$instance: Object,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$0,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$0#$instance: Object,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=220,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$1,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzkB/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested2$$Lambda$0,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested2$$Lambda$0#$instance: Object,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=104,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=40,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=11,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#DECELERATION_RATE: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#SPLINE_POSITION: float[],object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#SPLINE_TIME: float[],object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=11,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mCurrVelocity: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mCurrentPosition: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mDeceleration: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mDuration: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mFinal: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mFinished: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mFlingFriction: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mOver: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mPhysicalCoeff: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mSplineDistance: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mSplineDuration: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mStart: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mStartTime: long,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mState: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mVelocity: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex@0(size_without_padding=4616803,padding=0,full_name=** .dex (unattributed - includes string literals),object_path=,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=113,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#<clinit>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=225,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#<init>(android.content.Context,org.chromium.chrome.browser.compositor.layouts.phone.StackLayout),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=61,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#access$000(org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack): org.chromium.chrome.browser.compositor.layouts.phone.StackLayout,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=90,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#approxScreen(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab,float): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=64,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#cleanupTabs(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=261,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#commitDiscard(long,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=112,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeDiscardAlpha(float,float): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=136,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeDiscardScale(float,float,boolean): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=88,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeOverscrollPercent(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=253,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeSpacing(int): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=969,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabClippingVisibilityHelper(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=1512,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabOffsetHelper(android.graphics.RectF): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=318,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabPosition(long,android.graphics.RectF): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=217,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabScrollOffsetHelper(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=1008,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabTiltHelper(long,android.graphics.RectF): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=560,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabVisibilitySortingHelper(android.graphics.RectF): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=322,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#contextChanged(android.content.Context): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=563,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#createStackTabs(boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=1521,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#drag(long,float,float,float,float): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=446,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#evenOutTabs(float,boolean): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=813,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#finishAnimation(long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=223,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#finishAnimationsIfDone(long,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=503,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#fling(long,float,float,float,float): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=68,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getCount(): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=84,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getDefaultDiscardDirection(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=79,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getMaxScroll(boolean): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=113,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getMaxTabHeight(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=196,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getMinScroll(boolean): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=105,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getRange(float): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=94,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getScrollDimensionSize(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=128,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getStackScale(android.graphics.RectF): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=87,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getTabAtPositon(float,float): org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=360,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getTabIndexAtPositon(float,float,float): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=121,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getVisibleCount(): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=96,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#isDisplayable(): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=400,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#notifySizeChanged$483d2f6e(int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=107,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#onUpOrCancel(long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=341,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#onUpdateCompositorAnimations(long,boolean): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=101,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#onUpdateViewAnimation(long,boolean): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=100,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation.allowOverscroll(): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=68,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#requestUpdate(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=79,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#resetInputActionIndices(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=69,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#screenToScroll(float): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=69,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#scrollToScreen(float): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=134,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#setScrollTarget(float,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=121,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#setStackFocusInfo(float,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=244,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#setWarpState(boolean,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=219,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#springBack(long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=919,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#startAnimation$62adfb33(long,int,int,int,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=77,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#startAnimation$6848a047(long,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=95,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#startAnimation$78b04ab8(long,int,int,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=137,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#stopScrollingMovement(long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=142,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#swipeCancelled(long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=266,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#tabClosingEffect(long,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=217,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#updateOverscrollOffset(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=112,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#<init>(org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack,float,float,float,float,float),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=40,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#addTiltScrollAnimation(org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,org.chromium.chrome.browser.compositor.layouts.components.LayoutTab,float,int,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=1055,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createAnimatorSetForType$2fab410e$104f6ddb(int,org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,int,float,float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=36,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createEnterStackAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=139,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createNewTabOpenedAnimatorSet$4078c09e(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[]): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=32,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createReachTopAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=36,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createTabFocusedAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=32,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createViewMoreAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=30,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#getScreenPositionInScrollDirection(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=24,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#getScreenSizeInScrollDirection(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=92,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#getStaticTabPosition(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=67,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#getToolbarOffsetToLineUpWithBorder(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=24,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#isDefaultDiscardDirectionPositive(): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$$Lambda$0#<init>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$0#<init>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$1#<init>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzkB/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested2$$Lambda$0#<init>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=82,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#<init>(org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack,float,float,float,float,float),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=106,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#addTiltScrollAnimation(org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,org.chromium.chrome.browser.compositor.layouts.components.LayoutTab,float,int,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=592,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#createEnterStackAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=59,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#createNewTabOpenedAnimatorSet$4078c09e(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[]): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#createReachTopAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=961,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#createTabFocusedAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=256,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#createViewMoreAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=79,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#getScreenPositionInScrollDirection(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=54,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#getScreenSizeInScrollDirection(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=52,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#isDefaultDiscardDirectionPositive(): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=471,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#<clinit>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=146,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#<init>(android.content.Context),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$000(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=65,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$002(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller,boolean): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$100(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$200(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$300(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): long,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$400(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$500(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=176,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#adjustDuration(int,int,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=218,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#continueWhenFinished(long): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=66,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#finish(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=660,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#fling(int,int,int,int,int,long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=71,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#getDeceleration(int): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=97,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#getSplineDeceleration(int): double,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=115,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#getSplineFlingDistance(int): double,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=220,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#onEdgeReached(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=138,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#springback(int,int,int,long): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=109,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#startScroll(int,int,long,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=167,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#startSpringback$4868d30e(int,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=440,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#update(long): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<test.apk>.dex.method@0(size_without_padding=90,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#updateScroll(float): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
+<test.apk>.dex@0(size_without_padding=6,padding=0,full_name="",object_path=$SYSTEM/test.apk,source_path=$APK/AuxClass,flags={},num_aliases=1,component=)
+<test.apk>.dex@0(size_without_padding=7,padding=0,full_name="1",object_path=$SYSTEM/test.apk,source_path=$APK/AuxClass,flags={},num_aliases=1,component=)
+<test.apk>.dex@0(size_without_padding=34,padding=0,full_name="Complex roots not supported.",object_path=$SYSTEM/test.apk,source_path=$APK/TestClass,flags={},num_aliases=1,component=)
+<test.apk>.dex@0(size_without_padding=20,padding=0,full_name="a cannot be 0.",object_path=$SYSTEM/test.apk,source_path=$APK/TestClass,flags={},num_aliases=1,component=)
+<test.apk>.dex@0(size_without_padding=40,padding=0,full_name=AuxClass,object_path=$APK/AuxClass,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex@0(size_without_padding=10,padding=0,full_name=AuxClass#mRepeat: int,object_path=$APK/AuxClass,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex@0(size_without_padding=57,padding=0,full_name=TestClass,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex@0(size_without_padding=12,padding=0,full_name=TestClass#REPEAT: int,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex@0(size_without_padding=0,padding=0,full_name=java.lang.IllegalArgumentException,object_path=$APK/java/lang/IllegalArgumentException,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex@0(size_without_padding=0,padding=0,full_name=java.lang.Math,object_path=$APK/java/lang/Math,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex@0(size_without_padding=0,padding=0,full_name=java.lang.Object,object_path=$APK/java/lang/Object,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex@0(size_without_padding=0,padding=0,full_name=java.lang.StringBuilder,object_path=$APK/java/lang/StringBuilder,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex@0(size_without_padding=1260,padding=0,full_name=** .dex (unattributed - includes string literals),object_path=,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex.method@0(size_without_padding=42,padding=0,full_name=AuxClass#<init>(int),object_path=$APK/AuxClass,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex.method@0(size_without_padding=90,padding=0,full_name=AuxClass#repeatString(java.lang.String): java.lang.String,object_path=$APK/AuxClass,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=AuxClass#reverse(int[]): int[],object_path=$APK/AuxClass,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex.method@0(size_without_padding=38,padding=0,full_name=TestClass#<init>(),object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=TestClass#gcd(long,long): long,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex.method@0(size_without_padding=58,padding=0,full_name=TestClass#lcm(long,long): long,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex.method@0(size_without_padding=120,padding=0,full_name=TestClass#quadHi(double,double,double): double,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex.method@0(size_without_padding=50,padding=0,full_name=TestClass#repeat(java.lang.String): java.lang.String,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.IllegalArgumentException#<init>(java.lang.String),object_path=$APK/java/lang/IllegalArgumentException,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.Math#sqrt(double): double,object_path=$APK/java/lang/Math,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.Object#<init>(),object_path=$APK/java/lang/Object,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.StringBuilder#<init>(),object_path=$APK/java/lang/StringBuilder,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.StringBuilder#append(java.lang.String): java.lang.StringBuilder,object_path=$APK/java/lang/StringBuilder,source_path=,flags={},num_aliases=1,component=)
+<test.apk>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.StringBuilder#toString(): java.lang.String,object_path=$APK/java/lang/StringBuilder,source_path=,flags={},num_aliases=1,component=)
 <test.apk>.pak.nontranslated@2f03(size_without_padding=502,padding=0,full_name=../../chrome/browser/browser_resources.grd: IDR_PDF_COMPOSITOR_MANIFEST,object_path=,source_path=,flags={uncompressed},num_aliases=1,component=)
 <test.apk>.pak.nontranslated@2f04(size_without_padding=217,padding=0,full_name=../../chrome/browser/browser_resources.grd: IDR_CHROME_RENDERER_SERVICE_MANIFEST,object_path=,source_path=,flags={},num_aliases=1,component=)
 <test.apk>.pak.nontranslated@0(size_without_padding=0,padding=18,full_name=Overhead: assets/resources.pak,object_path=,source_path=,flags={},num_aliases=1,component=)
diff --git a/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden b/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden
index 48f934e4..51105d6 100644
--- a/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden
+++ b/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden
@@ -24,7 +24,7 @@
 zipalign_padding=0
 apk_file_name=Bundle.minimal.apks
 apk_signature_block_size=0
-apk_size=147858965
+apk_size=139472373
 apk_split_name=base
 zipalign_padding=32
 apk_file_name=Bundle.minimal.apks
@@ -240,15 +240,15 @@
 * 0 have source paths. Accounts for 0 bytes (0.0%).
 * 0 have a component assigned. Accounts for 0 bytes (0.0%).
 * 0 symbols have shared ownership.
-Section .dex: has 100.0% of 8364863 bytes accounted for from 100 symbols. 0 bytes are unaccounted for.
+Section .dex: has 100.0% of 1446 bytes accounted for from 13 symbols. 0 bytes are unaccounted for.
 * Padding accounts for 0 bytes (0.0%)
-* 90 have source paths. Accounts for 1806 bytes (0.0%).
+* 4 have source paths. Accounts for 67 bytes (4.6%).
 * 0 have a component assigned. Accounts for 0 bytes (0.0%).
-* 1 placeholders exist (symbols that start with **). Accounts for 4616803 bytes (55.2%).
+* 1 placeholders exist (symbols that start with **). Accounts for 1260 bytes (87.1%).
 * 0 symbols have shared ownership.
-Section .dex.method: has 100.0% of 23745 bytes accounted for from 104 symbols. 0 bytes are unaccounted for.
+Section .dex.method: has 100.0% of 570 bytes accounted for from 14 symbols. 0 bytes are unaccounted for.
 * Padding accounts for 0 bytes (0.0%)
-* 94 have source paths. Accounts for 21294 bytes (89.7%).
+* 0 have source paths. Accounts for 0 bytes (0.0%).
 * 0 have a component assigned. Accounts for 0 bytes (0.0%).
 * 0 symbols have shared ownership.
 Section .pak.translations: has 100.0% of 6821 bytes accounted for from 207 symbols. 0 bytes are unaccounted for.
@@ -465,210 +465,33 @@
 <Bundle.minimal.apks/base.apk/smalltest.so (x86)>.other@0(size_without_padding=0,padding=1524724,full_name=Overhead: ELF file,object_path=,source_path=$NATIVE/smalltest.so (arm),flags={},num_aliases=1,component=)
 <Bundle.minimal.apks/base-hi.apk>.other@0(size_without_padding=560,padding=0,full_name=AndroidManifest.xml,object_path=,source_path=$APK/AndroidManifest.xml,flags={},num_aliases=1,component=)
 <Bundle.minimal.apks/base-hi.apk>.other@0(size_without_padding=0,padding=136,full_name=Overhead: APK file,object_path=,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=1792,padding=0,full_name=org,object_path=$APK/org,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=975347,padding=0,full_name=org.chromium,object_path=$APK/org/chromium,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=44714,padding=0,full_name=org.chromium.chrome,object_path=$APK/org/chromium/chrome,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=2522400,padding=0,full_name=org.chromium.chrome.browser,object_path=$APK/org/chromium/chrome/browser,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=111986,padding=0,full_name=org.chromium.chrome.browser.compositor,object_path=$APK/org/chromium/chrome/browser/compositor,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=58449,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts,object_path=$APK/org/chromium/chrome/browser/compositor/layouts,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=23896,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=7566,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=40,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=12,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#$assertionsDisabled: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=11,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mAnimationFactory: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mBorderLeftPadding: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mBorderTopPadding: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mBorderTransparentSide: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mBorderTransparentTop: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mCurrentMode: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mCurrentScrollDirection: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mDiscardDirection: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mDiscardingTab: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mDragLock$7be2905e: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mEvenOutProgress: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mEvenOutRate: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mInSwipe: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mIsDying: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mIsStackForCurrentTabList: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mLastPinch0Offset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mLastPinch1Offset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mLastScrollUpdate: long,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mLayout: org.chromium.chrome.browser.compositor.layouts.phone.StackLayout,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mLongPressSelected: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMaxOverScroll: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMaxOverScrollAngle: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMaxOverScrollSlide: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMaxUnderScroll: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMinScrollMotion: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mMinSpacing: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverScrollAngleInterpolator: android.view.animation.Interpolator,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverScrollCounter: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverScrollDerivative: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverScrollOffset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverscrollSlideInterpolator: android.view.animation.Interpolator,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mOverviewAnimationType$5d025a5c: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mPinch0TabIndex: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mPinch1TabIndex: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mRecomputePosition: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mReferenceOrderIndex: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mScrollOffset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mScrollOffsetForDyingTabs: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mScrollTarget: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mScroller: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mScrollingTab: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mSpacing: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mStackTabs: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mSwipeBoundedScrollOffset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mSwipeCanScroll: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mSwipeIsCancelable: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mSwipeUnboundScrollOffset: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mTabAnimations: org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mTabList: org.chromium.chrome.browser.tabmodel.TabList,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mUnderScrollAngleInterpolator: android.view.animation.Interpolator,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mViewAnimationFactory: org.chromium.chrome.browser.compositor.layouts.phone.stack.StackViewAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mViewAnimations: android.animation.Animator,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mViewAnimatorListener: android.animation.AnimatorListenerAdapter,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#mWarpSize: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation.DRAG_ANGLE_THRESHOLD: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=40,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=11,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mBorderTopHeight: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mBorderTopOpaqueHeight: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mHeight: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mHeightMinusBrowserControls: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mStack: org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mWidth: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$$Lambda$0,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$$Lambda$0#$instance: Object,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$0,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$0#$instance: Object,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=220,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$1,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzkB/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested2$$Lambda$0,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested2$$Lambda$0#$instance: Object,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=104,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=40,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=11,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#DECELERATION_RATE: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#SPLINE_POSITION: float[],object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#SPLINE_TIME: float[],object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=11,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mCurrVelocity: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mCurrentPosition: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mDeceleration: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mDuration: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mFinal: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mFinished: boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mFlingFriction: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mOver: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mPhysicalCoeff: float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mSplineDistance: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mSplineDuration: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mStart: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mStartTime: long,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mState: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#mVelocity: int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=4616803,padding=0,full_name=** .dex (unattributed - includes string literals),object_path=,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=113,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#<clinit>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=225,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#<init>(android.content.Context,org.chromium.chrome.browser.compositor.layouts.phone.StackLayout),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=61,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#access$000(org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack): org.chromium.chrome.browser.compositor.layouts.phone.StackLayout,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=90,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#approxScreen(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab,float): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=64,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#cleanupTabs(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=261,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#commitDiscard(long,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=112,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeDiscardAlpha(float,float): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=136,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeDiscardScale(float,float,boolean): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=88,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeOverscrollPercent(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=253,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeSpacing(int): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=969,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabClippingVisibilityHelper(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=1512,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabOffsetHelper(android.graphics.RectF): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=318,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabPosition(long,android.graphics.RectF): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=217,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabScrollOffsetHelper(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=1008,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabTiltHelper(long,android.graphics.RectF): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=560,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#computeTabVisibilitySortingHelper(android.graphics.RectF): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=322,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#contextChanged(android.content.Context): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=563,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#createStackTabs(boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=1521,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#drag(long,float,float,float,float): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=446,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#evenOutTabs(float,boolean): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=813,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#finishAnimation(long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=223,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#finishAnimationsIfDone(long,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=503,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#fling(long,float,float,float,float): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=68,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getCount(): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=84,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getDefaultDiscardDirection(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=79,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getMaxScroll(boolean): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=113,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getMaxTabHeight(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=196,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getMinScroll(boolean): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=105,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getRange(float): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=94,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getScrollDimensionSize(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=128,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getStackScale(android.graphics.RectF): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=87,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getTabAtPositon(float,float): org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=360,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getTabIndexAtPositon(float,float,float): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=121,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#getVisibleCount(): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=96,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#isDisplayable(): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=400,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#notifySizeChanged$483d2f6e(int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=107,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#onUpOrCancel(long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=341,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#onUpdateCompositorAnimations(long,boolean): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=101,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#onUpdateViewAnimation(long,boolean): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=100,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation.allowOverscroll(): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=68,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#requestUpdate(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=79,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#resetInputActionIndices(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=69,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#screenToScroll(float): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=69,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#scrollToScreen(float): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=134,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#setScrollTarget(float,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=121,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#setStackFocusInfo(float,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=244,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#setWarpState(boolean,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=219,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#springBack(long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=919,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#startAnimation$62adfb33(long,int,int,int,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=77,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#startAnimation$6848a047(long,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=95,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#startAnimation$78b04ab8(long,int,int,boolean): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=137,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#stopScrollingMovement(long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=142,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#swipeCancelled(long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=266,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#tabClosingEffect(long,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=217,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack#updateOverscrollOffset(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=112,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#<init>(org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack,float,float,float,float,float),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=40,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#addTiltScrollAnimation(org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,org.chromium.chrome.browser.compositor.layouts.components.LayoutTab,float,int,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=1055,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createAnimatorSetForType$2fab410e$104f6ddb(int,org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,int,float,float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=36,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createEnterStackAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=139,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createNewTabOpenedAnimatorSet$4078c09e(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[]): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=32,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createReachTopAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=36,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createTabFocusedAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=32,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#createViewMoreAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=30,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#getScreenPositionInScrollDirection(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=24,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#getScreenSizeInScrollDirection(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=92,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#getStaticTabPosition(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=67,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#getToolbarOffsetToLineUpWithBorder(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=24,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#isDefaultDiscardDirectionPositive(): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$$Lambda$0#<init>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$0#<init>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$1#<init>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzkB/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested2$$Lambda$0#<init>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk/dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=82,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#<init>(org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack,float,float,float,float,float),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=106,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#addTiltScrollAnimation(org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,org.chromium.chrome.browser.compositor.layouts.components.LayoutTab,float,int,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=592,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#createEnterStackAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=59,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#createNewTabOpenedAnimatorSet$4078c09e(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[]): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#createReachTopAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=961,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#createTabFocusedAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=256,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#createViewMoreAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int): org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=79,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#getScreenPositionInScrollDirection(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=54,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#getScreenSizeInScrollDirection(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=52,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#isDefaultDiscardDirectionPositive(): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=471,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#<clinit>(),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=146,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#<init>(android.content.Context),object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$000(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=65,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$002(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller,boolean): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$100(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$200(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$300(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): long,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$400(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): int,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#access$500(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=176,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#adjustDuration(int,int,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=218,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#continueWhenFinished(long): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=66,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#finish(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=660,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#fling(int,int,int,int,int,long): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=71,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#getDeceleration(int): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=97,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#getSplineDeceleration(int): double,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=115,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#getSplineFlingDistance(int): double,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=220,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#onEdgeReached(): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=138,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#springback(int,int,int,long): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=109,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#startScroll(int,int,long,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=167,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#startSpringback$4868d30e(int,int): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=440,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#update(long): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
-<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=90,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller#updateScroll(float): void,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller$SplineStackScroller,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=6,padding=0,full_name="",object_path=$SYSTEM/base-master.apk,source_path=$APK/AuxClass,flags={},num_aliases=1,component=) # nocheck
+<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=7,padding=0,full_name="1",object_path=$SYSTEM/base-master.apk,source_path=$APK/AuxClass,flags={},num_aliases=1,component=) # nocheck
+<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=34,padding=0,full_name="Complex roots not supported.",object_path=$SYSTEM/base-master.apk,source_path=$APK/TestClass,flags={},num_aliases=1,component=) # nocheck
+<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=20,padding=0,full_name="a cannot be 0.",object_path=$SYSTEM/base-master.apk,source_path=$APK/TestClass,flags={},num_aliases=1,component=) # nocheck
+<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=40,padding=0,full_name=AuxClass,object_path=$APK/AuxClass,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=10,padding=0,full_name=AuxClass#mRepeat: int,object_path=$APK/AuxClass,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=57,padding=0,full_name=TestClass,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=12,padding=0,full_name=TestClass#REPEAT: int,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=0,padding=0,full_name=java.lang.IllegalArgumentException,object_path=$APK/java/lang/IllegalArgumentException,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=0,padding=0,full_name=java.lang.Math,object_path=$APK/java/lang/Math,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=0,padding=0,full_name=java.lang.Object,object_path=$APK/java/lang/Object,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=0,padding=0,full_name=java.lang.StringBuilder,object_path=$APK/java/lang/StringBuilder,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex@0(size_without_padding=1260,padding=0,full_name=** .dex (unattributed - includes string literals),object_path=,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=42,padding=0,full_name=AuxClass#<init>(int),object_path=$APK/AuxClass,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=90,padding=0,full_name=AuxClass#repeatString(java.lang.String): java.lang.String,object_path=$APK/AuxClass,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=AuxClass#reverse(int[]): int[],object_path=$APK/AuxClass,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=38,padding=0,full_name=TestClass#<init>(),object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=62,padding=0,full_name=TestClass#gcd(long,long): long,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=58,padding=0,full_name=TestClass#lcm(long,long): long,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=120,padding=0,full_name=TestClass#quadHi(double,double,double): double,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=50,padding=0,full_name=TestClass#repeat(java.lang.String): java.lang.String,object_path=$APK/TestClass,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.IllegalArgumentException#<init>(java.lang.String),object_path=$APK/java/lang/IllegalArgumentException,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.Math#sqrt(double): double,object_path=$APK/java/lang/Math,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.Object#<init>(),object_path=$APK/java/lang/Object,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.StringBuilder#<init>(),object_path=$APK/java/lang/StringBuilder,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.StringBuilder#append(java.lang.String): java.lang.StringBuilder,object_path=$APK/java/lang/StringBuilder,source_path=,flags={},num_aliases=1,component=)
+<Bundle.minimal.apks/base.apk>.dex.method@0(size_without_padding=8,padding=0,full_name=java.lang.StringBuilder#toString(): java.lang.String,object_path=$APK/java/lang/StringBuilder,source_path=,flags={},num_aliases=1,component=)
 <Bundle.minimal.apks/base.apk>.pak.nontranslated@2f03(size_without_padding=502,padding=0,full_name=../../chrome/browser/browser_resources.grd: IDR_PDF_COMPOSITOR_MANIFEST,object_path=,source_path=,flags={uncompressed},num_aliases=1,component=)
 <Bundle.minimal.apks/base.apk>.pak.nontranslated@2f04(size_without_padding=217,padding=0,full_name=../../chrome/browser/browser_resources.grd: IDR_CHROME_RENDERER_SERVICE_MANIFEST,object_path=,source_path=,flags={},num_aliases=1,component=)
 <Bundle.minimal.apks/base.apk>.pak.nontranslated@0(size_without_padding=0,padding=18,full_name=Overhead: assets/resources.pak,object_path=,source_path=,flags={},num_aliases=1,component=)
diff --git a/tools/binary_size/libsupersize/testdata/mock_dex/after/AuxClass.java b/tools/binary_size/libsupersize/testdata/mock_dex/after/AuxClass.java
new file mode 100644
index 0000000..4645bde0
--- /dev/null
+++ b/tools/binary_size/libsupersize/testdata/mock_dex/after/AuxClass.java
@@ -0,0 +1,31 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * Auxiliary test class for SuperSize.
+ */
+public class AuxClass {
+    private int mRepeat;
+
+    AuxClass(int repeat) {
+        mRepeat = repeat;
+    }
+
+    static int[] reverse(int[] ar) {
+        int n = ar.length;
+        int[] ret = new int[n];
+        for (int i = 0; i < n; ++i) {
+            ret[i] = ar[n - 1 - i];
+        }
+        return ret;
+    }
+
+    String repeatString(String s) {
+        String ret = "";
+        for (int i = 0; i < mRepeat; ++i) {
+            ret = ret + 1;
+        }
+        return ret;
+    }
+}
diff --git a/tools/binary_size/libsupersize/testdata/mock_dex/after/TestClass.java b/tools/binary_size/libsupersize/testdata/mock_dex/after/TestClass.java
new file mode 100644
index 0000000..b462e1f
--- /dev/null
+++ b/tools/binary_size/libsupersize/testdata/mock_dex/after/TestClass.java
@@ -0,0 +1,41 @@
+// 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.
+
+/**
+ * Test class for SuperSize.
+ */
+public class TestClass {
+    static final int REPEAT = 3;
+
+    long gcd(long a, long b) {
+        while (b != 0) {
+            long c = a % b;
+            a = b;
+            b = c;
+        }
+        return a;
+    }
+
+    long lcm(long a, long b) {
+        long g = gcd(a, b);
+        return g == 0 ? 0 : a / g * b;
+    }
+
+    double quadHi(double a, double b, double c) throws IllegalArgumentException {
+        if (a == 0) {
+            throw new IllegalArgumentException("a cannot be 0.");
+        }
+        double bb = b * b;
+        double ac4 = a * c * 4;
+        if (bb < ac4) {
+            throw new IllegalArgumentException("Complex roots not supported.");
+        }
+        return (Math.sqrt(bb - ac4) - b) / (a * 2);
+    }
+
+    String repeat(String a) {
+        AuxClass aux = new AuxClass(REPEAT);
+        return aux.repeatString(a);
+    }
+}
diff --git a/tools/binary_size/libsupersize/testdata/mock_dex/after/classes.dex b/tools/binary_size/libsupersize/testdata/mock_dex/after/classes.dex
new file mode 100644
index 0000000..f8e7b3e
--- /dev/null
+++ b/tools/binary_size/libsupersize/testdata/mock_dex/after/classes.dex
Binary files differ
diff --git a/tools/binary_size/libsupersize/testdata/mock_dex/before/TestClass.java b/tools/binary_size/libsupersize/testdata/mock_dex/before/TestClass.java
new file mode 100644
index 0000000..a4e8275
--- /dev/null
+++ b/tools/binary_size/libsupersize/testdata/mock_dex/before/TestClass.java
@@ -0,0 +1,47 @@
+// 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.
+
+/**
+ * Test class for SuperSize.
+ */
+public class TestClass {
+    static final int REPEAT = 3;
+
+    static int[] reverse(int[] ar) {
+        int n = ar.length;
+        int[] ret = new int[n];
+        for (int i = 0; i < n; ++i) {
+            ret[i] = ar[n - 1 - i];
+        }
+        return ret;
+    }
+
+    long gcd(long a, long b) {
+        while (b != 0) {
+            long c = a % b;
+            a = b;
+            b = c;
+        }
+        return a;
+    }
+
+    double quadHi(double a, double b, double c) throws IllegalArgumentException {
+        if (a == 0) {
+            throw new IllegalArgumentException("a cannot be 0.");
+        }
+        double desc = b * b - 4 * a * c;
+        if (desc < 0) {
+            throw new IllegalArgumentException("Complex roots not supported.");
+        }
+        return (-b + Math.sqrt(desc)) / (2 * a);
+    }
+
+    String repeat(String a) {
+        String ret = "";
+        for (int i = 0; i < REPEAT; ++i) {
+            ret = ret + 1;
+        }
+        return ret;
+    }
+}
diff --git a/tools/binary_size/libsupersize/testdata/mock_dex/before/classes.dex b/tools/binary_size/libsupersize/testdata/mock_dex/before/classes.dex
new file mode 100644
index 0000000..050b70d
--- /dev/null
+++ b/tools/binary_size/libsupersize/testdata/mock_dex/before/classes.dex
Binary files differ
diff --git a/tools/binary_size/libsupersize/testdata/mock_dex/buildall.sh b/tools/binary_size/libsupersize/testdata/mock_dex/buildall.sh
new file mode 100755
index 0000000..27b7a01
--- /dev/null
+++ b/tools/binary_size/libsupersize/testdata/mock_dex/buildall.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# 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.
+
+set -e
+
+MOCK_DEX_DIR=$(realpath $(dirname "$0"))
+MOCK_SDK_TOOLS_BIN_DIR=$(realpath $MOCK_DEX_DIR/../mock_sdk/tools/bin)
+SRC_DIR=$(realpath $MOCK_DEX_DIR/../../../../..)
+JAVAC=$SRC_DIR/third_party/jdk/current/bin/javac
+APKANALYZER=$SRC_DIR/third_party/android_build_tools/apkanalyzer/apkanalyzer
+D8=$SRC_DIR/third_party/android_sdk/public/build-tools/33.0.0/d8
+
+pushd $MOCK_DEX_DIR/before > /dev/null
+echo Making $MOCK_DEX_DIR/before/classes.dex
+$JAVAC TestClass.java
+$D8 TestClass.class
+rm TestClass.class
+popd > /dev/null
+
+pushd $MOCK_DEX_DIR/after > /dev/null
+echo Making $MOCK_DEX_DIR/after/classes.dex
+$JAVAC TestClass.java
+$D8 TestClass.class AuxClass.class
+rm TestClass.class AuxClass.class
+echo Making $MOCK_SDK_TOOLS_BIN_DIR/apkanalyzer.output
+zip temp.apk classes.dex > /dev/null
+$APKANALYZER dex packages temp.apk > $MOCK_SDK_TOOLS_BIN_DIR/apkanalyzer.output
+rm temp.apk
+popd > /dev/null
+
+echo ''
+echo You might need to run the following to update .golden files:
+echo ''
+echo cd $SRC_DIR/tools/binary_size/libsupersize
+echo ./integration_test.py --update
diff --git a/tools/binary_size/libsupersize/testdata/mock_sdk/tools/bin/apkanalyzer.output b/tools/binary_size/libsupersize/testdata/mock_sdk/tools/bin/apkanalyzer.output
index 6ced87f0..8affa65 100644
--- a/tools/binary_size/libsupersize/testdata/mock_sdk/tools/bin/apkanalyzer.output
+++ b/tools/binary_size/libsupersize/testdata/mock_sdk/tools/bin/apkanalyzer.output
@@ -1,204 +1,25 @@
-P d 42356	53800	5949070	<TOTAL>
-P d 28637	31775	3771805	org
-P d 28637	31703	3770013	org.chromium
-P d 20581	23192	2794666	org.chromium.chrome
-P d 20580	23191	2749952	org.chromium.chrome.browser
-P d 1660	1861	227552	org.chromium.chrome.browser.compositor
-P d 755	818	115566	org.chromium.chrome.browser.compositor.layouts
-P d 281	308	57117	org.chromium.chrome.browser.compositor.layouts.phone
-P d 140	146	33221	org.chromium.chrome.browser.compositor.layouts.phone.stack
-C d 55	55	16417	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack
-M d 1	1	113	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack <clinit>()
-M d 1	1	225	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack <init>(android.content.Context,org.chromium.chrome.browser.compositor.layouts.phone.StackLayout)
-M d 1	1	61	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack org.chromium.chrome.browser.compositor.layouts.phone.StackLayout access$000(org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack)
-M d 1	1	100	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack boolean org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation.allowOverscroll()
-M d 1	1	112	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float computeDiscardAlpha(float,float)
-M d 1	1	136	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float computeDiscardScale(float,float,boolean)
-M d 1	1	88	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float computeOverscrollPercent()
-M d 1	1	969	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void computeTabClippingVisibilityHelper()
-M d 1	1	1512	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void computeTabOffsetHelper(android.graphics.RectF)
-M d 1	1	217	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void computeTabScrollOffsetHelper()
-M d 1	1	1008	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void computeTabTiltHelper(long,android.graphics.RectF)
-M d 1	1	560	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void computeTabVisibilitySortingHelper(android.graphics.RectF)
-M d 1	1	446	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack boolean evenOutTabs(float,boolean)
-M d 1	1	223	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void finishAnimationsIfDone(long,boolean)
-M d 1	1	128	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float getStackScale(android.graphics.RectF)
-M d 1	1	87	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab getTabAtPositon(float,float)
-M d 1	1	79	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void resetInputActionIndices()
-M d 1	1	219	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void springBack(long)
-M d 1	1	217	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void updateOverscrollOffset()
-M d 1	1	90	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float approxScreen(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab,float)
-M d 1	1	64	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void cleanupTabs()
-M d 1	1	261	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void commitDiscard(long,boolean)
-M d 1	1	253	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack int computeSpacing(int)
-M d 1	1	318	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void computeTabPosition(long,android.graphics.RectF)
-M d 1	1	322	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void contextChanged(android.content.Context)
-M d 1	1	563	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void createStackTabs(boolean)
-M d 1	1	1521	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void drag(long,float,float,float,float)
-M d 1	1	813	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void finishAnimation(long)
-M d 1	1	503	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void fling(long,float,float,float,float)
-M d 1	1	68	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack int getCount()
-M d 1	1	84	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float getDefaultDiscardDirection()
-M d 1	1	79	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float getMaxScroll(boolean)
-M d 1	1	113	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float getMaxTabHeight()
-M d 1	1	196	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float getMinScroll(boolean)
-M d 1	1	105	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float getRange(float)
-M d 1	1	94	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float getScrollDimensionSize()
-M d 1	1	360	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack int getTabIndexAtPositon(float,float,float)
-M d 1	1	121	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack int getVisibleCount()
-M d 1	1	96	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack boolean isDisplayable()
-M d 1	1	400	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void notifySizeChanged$483d2f6e(int)
-M d 1	1	107	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void onUpOrCancel(long)
-M d 1	1	341	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack boolean onUpdateCompositorAnimations(long,boolean)
-M d 1	1	101	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack boolean onUpdateViewAnimation(long,boolean)
-M d 1	1	68	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void requestUpdate()
-M d 1	1	69	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float screenToScroll(float)
-M d 1	1	69	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float scrollToScreen(float)
-M d 1	1	134	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void setScrollTarget(float,boolean)
-M d 1	1	121	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void setStackFocusInfo(float,int)
-M d 1	1	244	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void setWarpState(boolean,boolean)
-M d 1	1	919	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void startAnimation$62adfb33(long,int,int,int,boolean)
-M d 1	1	77	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void startAnimation$6848a047(long,int)
-M d 1	1	95	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void startAnimation$78b04ab8(long,int,int,boolean)
-M d 1	1	137	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void stopScrollingMovement(long)
-M d 1	1	142	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void swipeCancelled(long)
-M d 1	1	266	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack void tabClosingEffect(long,int)
-F d 0	0	12	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack boolean $assertionsDisabled
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation.DRAG_ANGLE_THRESHOLD
-F d 0	0	11	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation mAnimationFactory
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mBorderLeftPadding
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mBorderTopPadding
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mBorderTransparentSide
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mBorderTransparentTop
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack int mCurrentMode
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mCurrentScrollDirection
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mDiscardDirection
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab mDiscardingTab
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack int mDragLock$7be2905e
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mEvenOutProgress
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mEvenOutRate
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack boolean mInSwipe
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack boolean mIsDying
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack boolean mIsStackForCurrentTabList
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mLastPinch0Offset
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mLastPinch1Offset
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack long mLastScrollUpdate
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack org.chromium.chrome.browser.compositor.layouts.phone.StackLayout mLayout
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack int mLongPressSelected
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mMaxOverScroll
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mMaxOverScrollAngle
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mMaxOverScrollSlide
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mMaxUnderScroll
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mMinScrollMotion
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mMinSpacing
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack android.view.animation.Interpolator mOverScrollAngleInterpolator
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack int mOverScrollCounter
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack int mOverScrollDerivative
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mOverScrollOffset
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack android.view.animation.Interpolator mOverscrollSlideInterpolator
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack int mOverviewAnimationType$5d025a5c
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack int mPinch0TabIndex
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack int mPinch1TabIndex
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack boolean mRecomputePosition
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack int mReferenceOrderIndex
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mScrollOffset
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mScrollOffsetForDyingTabs
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mScrollTarget
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller mScroller
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab mScrollingTab
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack int mSpacing
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[] mStackTabs
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mSwipeBoundedScrollOffset
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack boolean mSwipeCanScroll
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack boolean mSwipeIsCancelable
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mSwipeUnboundScrollOffset
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack org.chromium.chrome.browser.compositor.layouts.ChromeAnimation mTabAnimations
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack org.chromium.chrome.browser.tabmodel.TabList mTabList
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack android.view.animation.Interpolator mUnderScrollAngleInterpolator
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack org.chromium.chrome.browser.compositor.layouts.phone.stack.StackViewAnimation mViewAnimationFactory
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack android.animation.Animator mViewAnimations
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack android.animation.AnimatorListenerAdapter mViewAnimatorListener
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack float mWarpSize
-C d 22	22	3843	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller
-M d 1	1	471	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller <clinit>()
-M d 1	1	146	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller <init>(android.content.Context)
-M d 1	1	62	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller boolean access$000(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller)
-M d 1	1	65	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller boolean access$002(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller,boolean)
-M d 1	1	62	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller int access$100(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller)
-M d 1	1	62	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller int access$200(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller)
-M d 1	1	62	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller long access$300(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller)
-M d 1	1	62	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller int access$400(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller)
-M d 1	1	62	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller float access$500(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller)
-M d 1	1	176	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller void adjustDuration(int,int,int)
-M d 1	1	71	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller float getDeceleration(int)
-M d 1	1	97	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller double getSplineDeceleration(int)
-M d 1	1	115	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller double getSplineFlingDistance(int)
-M d 1	1	220	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller void onEdgeReached()
-M d 1	1	167	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller void startSpringback$4868d30e(int,int)
-M d 1	1	218	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller boolean continueWhenFinished(long)
-M d 1	1	66	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller void finish()
-M d 1	1	660	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller void fling(int,int,int,int,int,long)
-M d 1	1	138	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller boolean springback(int,int,int,long)
-M d 1	1	109	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller void startScroll(int,int,long,int)
-M d 1	1	440	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller boolean update(long)
-M d 1	1	90	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller void updateScroll(float)
-F d 0	0	11	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller float DECELERATION_RATE
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller float[] SPLINE_POSITION
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller float[] SPLINE_TIME
-F d 0	0	11	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller float mCurrVelocity
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller int mCurrentPosition
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller float mDeceleration
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller int mDuration
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller int mFinal
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller boolean mFinished
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller float mFlingFriction
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller int mOver
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller float mPhysicalCoeff
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller int mSplineDistance
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller int mSplineDuration
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller int mStart
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller long mStartTime
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller int mState
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller$SplineStackScroller int mVelocity
-C d 13	13	1820	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation
-M d 1	1	112	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation <init>(org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack,float,float,float,float,float)
-M d 1	1	40	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation void addTiltScrollAnimation(org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,org.chromium.chrome.browser.compositor.layouts.components.LayoutTab,float,int,int)
-M d 1	1	1055	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation org.chromium.chrome.browser.compositor.layouts.ChromeAnimation createAnimatorSetForType$2fab410e$104f6ddb(int,org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,int,float,float)
-M d 1	1	36	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation org.chromium.chrome.browser.compositor.layouts.ChromeAnimation createEnterStackAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float)
-M d 1	1	139	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation org.chromium.chrome.browser.compositor.layouts.ChromeAnimation createNewTabOpenedAnimatorSet$4078c09e(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[])
-M d 1	1	32	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation org.chromium.chrome.browser.compositor.layouts.ChromeAnimation createReachTopAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],float)
-M d 1	1	36	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation org.chromium.chrome.browser.compositor.layouts.ChromeAnimation createTabFocusedAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float)
-M d 1	1	32	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation org.chromium.chrome.browser.compositor.layouts.ChromeAnimation createViewMoreAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int)
-M d 1	1	30	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation float getScreenPositionInScrollDirection(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab)
-M d 1	1	24	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation float getScreenSizeInScrollDirection()
-M d 1	1	92	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation float getStaticTabPosition()
-M d 1	1	67	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation float getToolbarOffsetToLineUpWithBorder()
-M d 1	1	24	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation boolean isDefaultDiscardDirectionPositive()
-F d 0	0	11	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation float mBorderTopHeight
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation float mBorderTopOpaqueHeight
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation float mHeight
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation float mHeightMinusBrowserControls
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack mStack
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation float mWidth
-C d 10	12	2555	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape
-M d 1	1	82	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape <init>(org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack,float,float,float,float,float)
-M d 1	1	106	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape void addTiltScrollAnimation(org.chromium.chrome.browser.compositor.layouts.ChromeAnimation,org.chromium.chrome.browser.compositor.layouts.components.LayoutTab,float,int,int)
-M d 1	1	592	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape org.chromium.chrome.browser.compositor.layouts.ChromeAnimation createEnterStackAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float)
-M d 1	1	59	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape org.chromium.chrome.browser.compositor.layouts.ChromeAnimation createNewTabOpenedAnimatorSet$4078c09e(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[])
-M d 1	1	210	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape org.chromium.chrome.browser.compositor.layouts.ChromeAnimation createReachTopAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],float)
-M d 1	1	961	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape org.chromium.chrome.browser.compositor.layouts.ChromeAnimation createTabFocusedAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int,int,float)
-M d 1	1	256	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape org.chromium.chrome.browser.compositor.layouts.ChromeAnimation createViewMoreAnimatorSet(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab[],int)
-M d 1	1	79	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape float getScreenPositionInScrollDirection(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab)
-M d 1	1	54	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape float getScreenSizeInScrollDirection()
-M d 1	1	52	org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape boolean isDefaultDiscardDirectionPositive()
-C d 10	12	255	org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk.dex
-M d 1	1	35	org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk.dex <init>()
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk.dex Object $instance
-C d 10	12	255	org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzkB.dex
-M d 1	1	35	org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzkB.dex <init>()
-C d 10	12	255	org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk.dex
-M d 1	1	35	org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk.dex <init>()
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk.dex Object $instance
-C d 10	12	255	org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk.dex
-M d 1	1	35	org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk.dex <init>()
-F d 0	0	10	org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk.dex Object $instance
+P d 8	14	689	<TOTAL>
+P r 0	6	48	java
+P r 0	6	48	java.lang
+C r 0	3	24	java.lang.StringBuilder
+M r 0	1	8	java.lang.StringBuilder <init>()
+M r 0	1	8	java.lang.StringBuilder java.lang.StringBuilder append(java.lang.String)
+M r 0	1	8	java.lang.StringBuilder java.lang.String toString()
+C r 0	1	8	java.lang.Object
+M r 0	1	8	java.lang.Object <init>()
+C r 0	1	8	java.lang.IllegalArgumentException
+M r 0	1	8	java.lang.IllegalArgumentException <init>(java.lang.String)
+C r 0	1	8	java.lang.Math
+M r 0	1	8	java.lang.Math double sqrt(double)
+C d 5	5	397	TestClass
+M d 1	1	38	TestClass <init>()
+M d 1	1	62	TestClass long gcd(long,long)
+M d 1	1	58	TestClass long lcm(long,long)
+M d 1	1	120	TestClass double quadHi(double,double,double)
+M d 1	1	50	TestClass java.lang.String repeat(java.lang.String)
+F d 0	0	12	TestClass int REPEAT
+C d 3	3	244	AuxClass
+M d 1	1	42	AuxClass <init>(int)
+M d 1	1	62	AuxClass int[] reverse(int[])
+M d 1	1	90	AuxClass java.lang.String repeatString(java.lang.String)
+F d 0	0	10	AuxClass int mRepeat
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 057d02b..86559e03 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -10278,13 +10278,13 @@
   <int value="1" label="(01) VR_DELEGATE"/>
   <int value="2" label="(02) AR_DELEGATE"/>
   <int value="3" label="(03) SCENE_OVERLAY"/>
-  <int value="4" label="(04) START_SURFACE_MEDIATOR (tab switcher)"/>
+  <int value="4" label="(04) START_SURFACE (with tab switcher if enabled)"/>
   <int value="5" label="(05) SELECTION_POPUP"/>
   <int value="6" label="(06) MANUAL_FILLING"/>
   <int value="7" label="(07) FULLSCREEN"/>
   <int value="8" label="(08) BOTTOM_SHEET"/>
   <int value="9" label="(10) TAB_MODAL_HANDLER"/>
-  <int value="10" label="(11) TAB_SWITCHER_TO_BROWSING"/>
+  <int value="10" label="(11) TAB_SWITCHER (if Start surface is disabled)"/>
   <int value="11" label="(12) CLOSE_WATCHER"/>
   <int value="12" label="(14) TAB_HISTORY (and bottom controls)"/>
   <int value="13" label="(15) TAB_RETURN_TO_CHROME_START_SURFACE"/>
@@ -17217,6 +17217,8 @@
   <int value="1" label="Render View Context Menu"/>
   <int value="2" label="Textfield Context Menu"/>
   <int value="3" label="Virtual Keyboard"/>
+  <int value="4" label="Unknown"/>
+  <int value="5" label="Toast"/>
 </enum>
 
 <enum name="ClipboardPastedImageUrls">
@@ -72212,7 +72214,8 @@
     how to display captive portal signin UI.
   </summary>
   <int value="1" label="Dialog using the signin Profile"/>
-  <int value="2" label="Singleton tab using the active user Profile"/>
+  <int value="2"
+      label="DEPRECATED: Singleton tab using the active user Profile"/>
   <int value="3" label="Browser tab using the active user Profile"/>
   <int value="4" label="Browser tab using an OTR Profile"/>
   <int value="5" label="Dialog using an incognito Profile (deprecated)"/>
@@ -73543,6 +73546,7 @@
   <int value="3" label="Dark Light Mode"/>
   <int value="4" label="Autozoom"/>
   <int value="5" label="Adaptive Charging"/>
+  <int value="6" label="Phone Hub"/>
 </enum>
 
 <enum name="NukeProfileResult">
@@ -99301,6 +99305,7 @@
   <int value="37" label="Eche Tray Copy Paste Not Implemented"/>
   <int value="38" label="Eche Tray Tablet Mode Not Supported"/>
   <int value="39" label="Notification Center Tray No Notifications"/>
+  <int value="40" label="Copy to Clipboard Action"/>
 </enum>
 
 <enum name="TokenBinding.KeyMatch">
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml
index 172c3b4..86efb3c8 100644
--- a/tools/metrics/histograms/metadata/chromeos/histograms.xml
+++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -1119,6 +1119,7 @@
   <token key="Survey">
     <variant name="General"/>
     <variant name="Performance"/>
+    <variant name="PrivacyHubBaseline"/>
     <variant name="Stability"/>
   </token>
 </histogram>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml
index 342b2d8..c225362e 100644
--- a/tools/metrics/histograms/metadata/tab/histograms.xml
+++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -1301,6 +1301,22 @@
   </summary>
 </histogram>
 
+<histogram name="TabRestore.{RestoreType}.TimeBetweenClosedAndRestored"
+    units="ms" expires_after="2023-07-10">
+  <owner>sreejakshetty@chromium.org</owner>
+  <owner>chrome-brapp-loading@google.com</owner>
+  <summary>
+    Recorded when the user restores a {RestoreType}. The value is the time
+    duration between the previous closing of the {RestoreType} and the
+    {RestoreType} being restored.
+  </summary>
+  <token key="RestoreType">
+    <variant name="Group" summary="tab group"/>
+    <variant name="Tab" summary="tab"/>
+    <variant name="Window" summary="window"/>
+  </token>
+</histogram>
+
 <histogram name="Tabs.CountAtResume" units="tabs" expires_after="2022-11-02">
   <owner>marq@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
diff --git a/tools/v8_context_snapshot/v8_context_snapshot.gni b/tools/v8_context_snapshot/v8_context_snapshot.gni
index f6cb20f..23bee57 100644
--- a/tools/v8_context_snapshot/v8_context_snapshot.gni
+++ b/tools/v8_context_snapshot/v8_context_snapshot.gni
@@ -7,6 +7,7 @@
 # third_party/WebKit/Source/bindings/core/v8/V8ContextSnapshot.{cpp|h}.
 # to speedup creating a V8 context and setting up around it.
 
+import("//build/config/chrome_build.gni")
 import("//build/config/chromecast_build.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/v8_target_cpu.gni")
@@ -16,8 +17,8 @@
   # TODO(crbug.com/764576): Enable the feature on more environments.
   # Disable in mac and win cross builds since building Blink twice is slow.
   use_v8_context_snapshot =
-      !is_chromeos && !is_android && !is_castos && !is_fuchsia &&
-      !(host_os == "mac" && current_cpu == "x86") &&
+      !is_chromeos && (!is_android || is_high_end_android) && !is_castos &&
+      !is_fuchsia && !(host_os == "mac" && current_cpu == "x86") &&
       # Android may build for both 64 bit and 32bit. When this happens, the
       # v8_target_cpu will not equal the target_cpu (for example,
       # v8_target_cpu == "arm" but target_os == "arm64").
diff --git a/ui/accessibility/ax_enum_util.cc b/ui/accessibility/ax_enum_util.cc
index dfccf72..e0e2619 100644
--- a/ui/accessibility/ax_enum_util.cc
+++ b/ui/accessibility/ax_enum_util.cc
@@ -948,6 +948,8 @@
       return "color";
     case ax::mojom::IntAttribute::kHasPopup:
       return "haspopup";
+    case ax::mojom::IntAttribute::kIsPopup:
+      return "ispopup";
     case ax::mojom::IntAttribute::kInvalidState:
       return "invalidState";
     case ax::mojom::IntAttribute::kCheckedState:
@@ -1481,6 +1483,17 @@
   return "";
 }
 
+const char* ToString(ax::mojom::IsPopup is_popup) {
+  switch (is_popup) {
+    case ax::mojom::IsPopup::kNone:
+      return "";
+    case ax::mojom::IsPopup::kAuto:
+      return "auto";
+    case ax::mojom::IsPopup::kManual:
+      return "manual";
+  }
+}
+
 const char* ToString(ax::mojom::InvalidState invalid_state) {
   switch (invalid_state) {
     case ax::mojom::InvalidState::kNone:
diff --git a/ui/accessibility/ax_enum_util.h b/ui/accessibility/ax_enum_util.h
index 3e7f172f..60125fec 100644
--- a/ui/accessibility/ax_enum_util.h
+++ b/ui/accessibility/ax_enum_util.h
@@ -105,6 +105,9 @@
 // ax::mojom::HasPopup
 AX_BASE_EXPORT const char* ToString(ax::mojom::HasPopup has_popup);
 
+// ax::mojom::IsPopup
+AX_BASE_EXPORT const char* ToString(ax::mojom::IsPopup is_popup);
+
 // ax::mojom::InvalidState
 AX_BASE_EXPORT const char* ToString(ax::mojom::InvalidState invalid_state);
 
diff --git a/ui/accessibility/ax_enums.mojom b/ui/accessibility/ax_enums.mojom
index b7523b4b..c79434e 100644
--- a/ui/accessibility/ax_enums.mojom
+++ b/ui/accessibility/ax_enums.mojom
@@ -610,7 +610,8 @@
   kVirtualContent = 30,
 };
 
-// Next value: 61
+// Next version: 2
+// Next value: 62
 [Extensible, Stable, Uuid="c350e50f-5177-405d-b155-79868449ba7b"]
 enum IntAttribute {
   [Default]kNone = 0,
@@ -697,6 +698,8 @@
   kBackgroundColor = 43,
   kColor = 44,
 
+  // Indicates the availability and type of interactive popup element that can
+  // be triggered by the element on which the attribute is set.
   kHasPopup = 45,
 
   // Image annotation status, of type ImageAnnotationStatus.
@@ -747,6 +750,9 @@
   // unrelated to the accessibility node ID, or the ID attribute for an
   // HTML element - it's an ID used to uniquely identify nodes in Blink.
   kDOMNodeId = 60,
+
+  // Indicates whether the element is a popover ("popup") and if so, what type.
+  [MinVersion=1] kIsPopup = 61,
 };
 
 // Next version: 2
@@ -1164,6 +1170,12 @@
   kNone = kFalse
 };
 
+enum IsPopup {
+  kNone = 0,
+  kManual,
+  kAuto,
+};
+
 enum InvalidState {
   kNone,
   kFalse,
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc
index 2086f1a..594b582 100644
--- a/ui/accessibility/ax_node_data.cc
+++ b/ui/accessibility/ax_node_data.cc
@@ -150,6 +150,7 @@
     case ax::mojom::IntAttribute::kColorValue:
     case ax::mojom::IntAttribute::kAriaCurrentState:
     case ax::mojom::IntAttribute::kHasPopup:
+    case ax::mojom::IntAttribute::kIsPopup:
     case ax::mojom::IntAttribute::kBackgroundColor:
     case ax::mojom::IntAttribute::kColor:
     case ax::mojom::IntAttribute::kInvalidState:
@@ -897,6 +898,21 @@
   }
 }
 
+ax::mojom::IsPopup AXNodeData::GetIsPopup() const {
+  return static_cast<ax::mojom::IsPopup>(
+      GetIntAttribute(ax::mojom::IntAttribute::kIsPopup));
+}
+
+void AXNodeData::SetIsPopup(ax::mojom::IsPopup is_popup) {
+  if (HasIntAttribute(ax::mojom::IntAttribute::kIsPopup)) {
+    RemoveIntAttribute(ax::mojom::IntAttribute::kIsPopup);
+  }
+  if (is_popup != ax::mojom::IsPopup::kNone) {
+    AddIntAttribute(ax::mojom::IntAttribute::kIsPopup,
+                    static_cast<int32_t>(is_popup));
+  }
+}
+
 ax::mojom::InvalidState AXNodeData::GetInvalidState() const {
   return static_cast<ax::mojom::InvalidState>(
       GetIntAttribute(ax::mojom::IntAttribute::kInvalidState));
@@ -1554,6 +1570,18 @@
             break;
         }
         break;
+      case ax::mojom::IntAttribute::kIsPopup:
+        switch (static_cast<ax::mojom::IsPopup>(int_attribute.second)) {
+          case ax::mojom::IsPopup::kNone:
+            break;
+          case ax::mojom::IsPopup::kAuto:
+            result += " ispopup=auto";
+            break;
+          case ax::mojom::IsPopup::kManual:
+            result += " ispopup=manual";
+            break;
+        }
+        break;
       case ax::mojom::IntAttribute::kInvalidState:
         switch (static_cast<ax::mojom::InvalidState>(int_attribute.second)) {
           case ax::mojom::InvalidState::kFalse:
diff --git a/ui/accessibility/ax_node_data.h b/ui/accessibility/ax_node_data.h
index 0662dbd..d206343 100644
--- a/ui/accessibility/ax_node_data.h
+++ b/ui/accessibility/ax_node_data.h
@@ -236,6 +236,8 @@
   void SetDefaultActionVerb(ax::mojom::DefaultActionVerb default_action_verb);
   ax::mojom::HasPopup GetHasPopup() const;
   void SetHasPopup(ax::mojom::HasPopup has_popup);
+  ax::mojom::IsPopup GetIsPopup() const;
+  void SetIsPopup(ax::mojom::IsPopup is_popup);
   ax::mojom::InvalidState GetInvalidState() const;
   void SetInvalidState(ax::mojom::InvalidState invalid_state);
   ax::mojom::NameFrom GetNameFrom() const;
diff --git a/ui/accessibility/platform/ax_platform_node_base.cc b/ui/accessibility/platform/ax_platform_node_base.cc
index c2cff80..221a44a 100644
--- a/ui/accessibility/platform/ax_platform_node_base.cc
+++ b/ui/accessibility/platform/ax_platform_node_base.cc
@@ -1194,7 +1194,7 @@
                        "AXPlatformNodeDelegate.";
   // Expose some HTML and ARIA attributes in the IAccessible2 attributes string
   // "display", "tag", and "xml-roles" have somewhat unusual names for
-  // historical reasons. Aside from that virtually every ARIA attribute
+  // historical reasons. Aside from that, virtually every ARIA attribute
   // is exposed in a really straightforward way, i.e. "aria-foo" is exposed
   // as "foo".
   AddAttributeToList(ax::mojom::StringAttribute::kDisplay, "display",
@@ -1344,6 +1344,21 @@
     AddAttributeToList("haspopup", "menu", attributes);
   }
 
+  // Expose the aria-ispopup attribute.
+  int32_t is_popup;
+  if (GetIntAttribute(ax::mojom::IntAttribute::kIsPopup, &is_popup)) {
+    switch (static_cast<ax::mojom::IsPopup>(is_popup)) {
+      case ax::mojom::IsPopup::kNone:
+        break;
+      case ax::mojom::IsPopup::kManual:
+        AddAttributeToList("ispopup", "manual", attributes);
+        break;
+      case ax::mojom::IsPopup::kAuto:
+        AddAttributeToList("ispopup", "auto", attributes);
+        break;
+    }
+  }
+
   // Expose the aria-current attribute.
   int32_t aria_current_state;
   if (GetIntAttribute(ax::mojom::IntAttribute::kAriaCurrentState,
diff --git a/ui/android/java/src/org/chromium/ui/base/EventForwarder.java b/ui/android/java/src/org/chromium/ui/base/EventForwarder.java
index cb0349b..efc28e6 100644
--- a/ui/android/java/src/org/chromium/ui/base/EventForwarder.java
+++ b/ui/android/java/src/org/chromium/ui/base/EventForwarder.java
@@ -15,6 +15,7 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import org.chromium.base.Log;
 import org.chromium.base.TraceEvent;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
@@ -22,11 +23,14 @@
 import org.chromium.base.compat.ApiHelperForM;
 import org.chromium.base.compat.ApiHelperForQ;
 
+import java.lang.reflect.UndeclaredThrowableException;
+
 /**
  * Class used to forward view, input events down to native.
  */
 @JNINamespace("ui")
 public class EventForwarder {
+    private static final String TAG = "EventForwarder";
     private final boolean mIsDragDropEnabled;
 
     private long mNativeEventForwarder;
@@ -382,15 +386,24 @@
             return mimeTypes != null && mimeTypes.length > 0 && mIsDragDropEnabled;
         }
 
-        StringBuilder content = new StringBuilder("");
+        String content = "";
         if (event.getAction() == DragEvent.ACTION_DROP) {
-            // TODO(hush): obtain dragdrop permissions, when dragging files into Chrome/WebView is
-            // supported. Not necessary to do so for now, because only text dragging is supported.
-            ClipData clipData = event.getClipData();
-            final int itemCount = clipData.getItemCount();
-            for (int i = 0; i < itemCount; i++) {
-                ClipData.Item item = clipData.getItemAt(i);
-                content.append(item.coerceToStyledText(containerView.getContext()));
+            try {
+                StringBuilder contentBuilder = new StringBuilder("");
+                ClipData clipData = event.getClipData();
+                final int itemCount = clipData.getItemCount();
+                for (int i = 0; i < itemCount; i++) {
+                    ClipData.Item item = clipData.getItemAt(i);
+                    contentBuilder.append(item.coerceToStyledText(containerView.getContext()));
+                }
+                content = contentBuilder.toString();
+            } catch (UndeclaredThrowableException e) {
+                // When dropped item is not successful for whatever reason, catch before we crash.
+                // While ClipData.Item does capture most common failures, there could be exceptions
+                // that's wrapped by Chrome classes (e.g. ServiceTracingProxyProvider) which changed
+                // the exception signiture. See crbug.com/1406777.
+                Log.e(TAG, "Parsing clip data content failed.", e.getMessage());
+                content = "";
             }
         }
 
@@ -407,7 +420,7 @@
 
         EventForwarderJni.get().onDragEvent(mNativeEventForwarder, EventForwarder.this,
                 event.getAction(), x / scale, y / scale, screenX / scale, screenY / scale,
-                mimeTypes, content.toString());
+                mimeTypes, content);
         return true;
     }
 
diff --git a/ui/lottie/animation_unittest.cc b/ui/lottie/animation_unittest.cc
index ddd865c..b9f311e 100644
--- a/ui/lottie/animation_unittest.cc
+++ b/ui/lottie/animation_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/test/simple_test_tick_clock.h"
 #include "cc/paint/display_item_list.h"
 #include "cc/paint/paint_op_buffer.h"
+#include "cc/paint/paint_op_buffer_iterator.h"
 #include "cc/paint/paint_record.h"
 #include "cc/paint/record_paint_canvas.h"
 #include "cc/paint/skottie_frame_data.h"
@@ -23,6 +24,7 @@
 #include "cc/paint/skottie_wrapper.h"
 #include "cc/test/lottie_test_data.h"
 #include "cc/test/paint_image_matchers.h"
+#include "cc/test/paint_op_matchers.h"
 #include "cc/test/skia_common.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -37,6 +39,8 @@
 namespace lottie {
 namespace {
 
+using ::cc::PaintOpIs;
+using ::testing::AllOf;
 using ::testing::ElementsAre;
 using ::testing::Eq;
 using ::testing::FieldsAre;
@@ -45,6 +49,7 @@
 using ::testing::IsEmpty;
 using ::testing::NotNull;
 using ::testing::Pair;
+using ::testing::ResultOf;
 using ::testing::SizeIs;
 
 // A skottie animation with solid green color for the first 2.5 seconds and then
@@ -1334,21 +1339,28 @@
   animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
 
   cc::PaintRecord paint_record = record_canvas_.ReleaseAsRecord();
-  ASSERT_THAT(paint_record.size(), Eq(1u));
-  const cc::DrawSkottieOp* op =
-      paint_record.GetOpAtForTesting<cc::DrawSkottieOp>(0);
-  ASSERT_THAT(op, NotNull());
-  EXPECT_THAT(op->images, ElementsAre(cc::SkottieImageIs("image_0", frame_0)));
+  EXPECT_THAT(paint_record,
+              ElementsAre(AllOf(
+                  PaintOpIs<cc::DrawSkottieOp>(),
+                  ResultOf(
+                      [](const cc::PaintOp& op) {
+                        return static_cast<const cc::DrawSkottieOp&>(op).images;
+                      },
+                      ElementsAre(cc::SkottieImageIs("image_0", frame_0))))));
 
   AdvanceClock(animation_->GetAnimationDuration() * .75);
 
   animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
 
   paint_record = record_canvas_.ReleaseAsRecord();
-  ASSERT_THAT(paint_record.size(), Eq(1u));
-  op = paint_record.GetOpAtForTesting<cc::DrawSkottieOp>(0);
-  ASSERT_THAT(op, NotNull());
-  EXPECT_THAT(op->images, ElementsAre(cc::SkottieImageIs("image_1", frame_1)));
+  EXPECT_THAT(paint_record,
+              ElementsAre(AllOf(
+                  PaintOpIs<cc::DrawSkottieOp>(),
+                  ResultOf(
+                      [](const cc::PaintOp& op) {
+                        return static_cast<const cc::DrawSkottieOp&>(op).images;
+                      },
+                      ElementsAre(cc::SkottieImageIs("image_1", frame_1))))));
 }
 
 TEST_F(AnimationWithImageAssetsTest, GracefullyHandlesNullImages) {
@@ -1359,12 +1371,15 @@
   animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
 
   cc::PaintRecord paint_record = record_canvas_.ReleaseAsRecord();
-  ASSERT_THAT(paint_record.size(), Eq(1u));
-  const cc::DrawSkottieOp* op =
-      paint_record.GetOpAtForTesting<cc::DrawSkottieOp>(0);
-  ASSERT_THAT(op, NotNull());
-  EXPECT_THAT(op->images, ElementsAre(cc::SkottieImageIs(
-                              "image_0", cc::SkottieFrameData())));
+  EXPECT_THAT(paint_record,
+              ElementsAre(AllOf(
+                  PaintOpIs<cc::DrawSkottieOp>(),
+                  ResultOf(
+                      [](const cc::PaintOp& op) {
+                        return static_cast<const cc::DrawSkottieOp&>(op).images;
+                      },
+                      ElementsAre(cc::SkottieImageIs(
+                          "image_0", cc::SkottieFrameData()))))));
 }
 
 TEST_F(AnimationWithImageAssetsTest, LoadsCorrectFrameTimestamp) {
diff --git a/ui/views/animation/ink_drop_mask_unittest.cc b/ui/views/animation/ink_drop_mask_unittest.cc
index b55a533..7809937e 100644
--- a/ui/views/animation/ink_drop_mask_unittest.cc
+++ b/ui/views/animation/ink_drop_mask_unittest.cc
@@ -6,10 +6,12 @@
 
 #include <algorithm>
 #include <memory>
+#include <vector>
 
 #include "cc/paint/display_item_list.h"
-#include "cc/paint/paint_op_buffer.h"
+#include "cc/paint/paint_op_buffer_iterator.h"
 #include "cc/paint/paint_record.h"
+#include "cc/test/paint_op_matchers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkPath.h"
 #include "third_party/skia/include/core/SkPoint.h"
@@ -17,15 +19,40 @@
 
 namespace views {
 
+using ::cc::PaintOpIs;
+using ::testing::AllOf;
+using ::testing::ElementsAre;
+using ::testing::ExplainMatchResult;
+using ::testing::ResultOf;
+using ::testing::UnorderedElementsAreArray;
+
+MATCHER_P(PointsAre, expected, "") {
+  int expected_size = expected.size();
+  if (arg.countPoints() != expected_size) {
+    *result_listener << "Expected path to have " << expected_size
+                     << " points, but had " << arg.countPoints() << ".";
+    return false;
+  }
+
+  std::vector<SkPoint> actual(expected_size);
+  if (arg.getPoints(&actual.front(), expected_size) != expected_size) {
+    *result_listener << "Failed extracting " << expected.size()
+                     << " points from path.";
+    return false;
+  }
+
+  return ExplainMatchResult(UnorderedElementsAreArray(expected), actual,
+                            result_listener);
+}
+
 TEST(InkDropMaskTest, PathInkDropMaskPaintsTriangle) {
   gfx::Size layer_size(10, 10);
   SkPath path;
-  SkPoint p1 = SkPoint::Make(3, 3);
-  SkPoint p2 = SkPoint::Make(5, 6);
-  SkPoint p3 = SkPoint::Make(8, 1);
-  path.moveTo(p1.x(), p1.y());
-  path.lineTo(p2.x(), p2.y());
-  path.lineTo(p3.x(), p3.y());
+  std::vector<SkPoint> points = {SkPoint::Make(3, 3), SkPoint::Make(5, 6),
+                                 SkPoint::Make(8, 1)};
+  path.moveTo(points[0].x(), points[0].y());
+  path.lineTo(points[1].x(), points[1].y());
+  path.lineTo(points[2].x(), points[2].y());
   path.close();
   PathInkDropMask mask(layer_size, path);
 
@@ -35,20 +62,21 @@
   EXPECT_EQ(1u, list->num_paint_ops()) << list->ToString();
 
   cc::PaintRecord record = list->FinalizeAndReleaseAsRecord();
-  const auto* draw_record_op = record.GetOpAtForTesting<cc::DrawRecordOp>(0);
-  ASSERT_NE(nullptr, draw_record_op);
-  const auto* draw_op =
-      draw_record_op->record.GetOpAtForTesting<cc::DrawPathOp>(0);
-  ASSERT_NE(nullptr, draw_op);
-  ASSERT_EQ(3, draw_op->path.countPoints());
-
-  SkPoint points[3];
-  ASSERT_EQ(3, draw_op->path.getPoints(points, 3));
-  std::sort(points, points + 3,
-            [](const SkPoint& a, const SkPoint& b) { return a.x() < b.x(); });
-  EXPECT_EQ(p1, points[0]);
-  EXPECT_EQ(p2, points[1]);
-  EXPECT_EQ(p3, points[2]);
+  EXPECT_THAT(
+      record,
+      ElementsAre(AllOf(
+          PaintOpIs<cc::DrawRecordOp>(),
+          ResultOf(
+              [](const cc::PaintOp& op) {
+                return static_cast<const cc::DrawRecordOp&>(op).record;
+              },
+              ElementsAre(AllOf(
+                  PaintOpIs<cc::DrawPathOp>(),
+                  ResultOf(
+                      [](const cc::PaintOp& op) {
+                        return static_cast<const cc::DrawPathOp&>(op).path;
+                      },
+                      PointsAre(points))))))));
 }
 
 }  // namespace views
diff --git a/ui/views/controls/menu/menu_controller_cocoa_delegate_impl.mm b/ui/views/controls/menu/menu_controller_cocoa_delegate_impl.mm
index 012e4ed..9f7fc0d8 100644
--- a/ui/views/controls/menu/menu_controller_cocoa_delegate_impl.mm
+++ b/ui/views/controls/menu/menu_controller_cocoa_delegate_impl.mm
@@ -155,23 +155,14 @@
 
 @end
 
-@interface IdentifierContainer : NSObject
-- (std::vector<ui::ElementIdentifier>&)ids;
-@end
-
-@implementation IdentifierContainer {
-  std::vector<ui::ElementIdentifier> _ids;
-}
-- (std::vector<ui::ElementIdentifier>&)ids {
-  return _ids;
+@interface MenuControllerCocoaDelegateImpl () {
+  NSMutableArray* _menuObservers;
+  gfx::Rect _anchorRect;
 }
 @end
 
 @implementation MenuControllerCocoaDelegateImpl
 
-NSMutableArray* _menuObservers;
-gfx::Rect _anchorRect;
-
 - (instancetype)init {
   if (self = [super init]) {
     _menuObservers = [[NSMutableArray alloc] init];
@@ -226,8 +217,11 @@
 
 - (void)controllerWillAddMenu:(NSMenu*)menu fromModel:(ui::MenuModel*)model {
   absl::optional<size_t> alerted_index;
-  IdentifierContainer* const element_ids =
-      [[[IdentifierContainer alloc] init] autorelease];
+
+  // This list will be copied into callback blocks later if it's non-empty, but
+  // since it's fairly small that's not a big deal.
+  std::vector<ui::ElementIdentifier> element_ids;
+
   for (size_t i = 0; i < model->GetItemCount(); ++i) {
     if (model->IsAlertedAt(i)) {
       DCHECK(!alerted_index.has_value());
@@ -235,11 +229,11 @@
     }
     const ui::ElementIdentifier identifier = model->GetElementIdentifierAt(i);
     if (identifier) {
-      [element_ids ids].push_back(identifier);
+      element_ids.push_back(identifier);
     }
   }
 
-  if (alerted_index.has_value() || ![element_ids ids].empty()) {
+  if (alerted_index.has_value() || !element_ids.empty()) {
     auto shown_callback = ^(NSNotification* note) {
       NSMenu* const menu_obj = note.object;
       if (alerted_index.has_value()) {
@@ -299,7 +293,7 @@
               }
             }
 
-            for (ui::ElementIdentifier element_id : [element_ids ids]) {
+            for (ui::ElementIdentifier element_id : element_ids) {
               ui::ElementTrackerMac::GetInstance()->NotifyMenuItemShown(
                   menu_obj, element_id, screen_rect);
             }
@@ -314,7 +308,7 @@
                               usingBlock:shown_callback]];
   }
 
-  if (![element_ids ids].empty()) {
+  if (!element_ids.empty()) {
     auto hidden_callback = ^(NSNotification* note) {
       NSMenu* const menu_obj = note.object;
       // We expect to see the following order of events:
@@ -328,7 +322,7 @@
       dispatch_after(
           dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_MSEC),
           dispatch_get_main_queue(), ^{
-            for (ui::ElementIdentifier element_id : [element_ids ids]) {
+            for (ui::ElementIdentifier element_id : element_ids) {
               ui::ElementTrackerMac::GetInstance()->NotifyMenuItemHidden(
                   menu_obj, element_id);
             }
diff --git a/ui/views/interaction/interaction_test_util_mouse.cc b/ui/views/interaction/interaction_test_util_mouse.cc
index 9b7582a..b5211b6 100644
--- a/ui/views/interaction/interaction_test_util_mouse.cc
+++ b/ui/views/interaction/interaction_test_util_mouse.cc
@@ -8,10 +8,16 @@
 #include <utility>
 
 #include "base/auto_reset.h"
+#include "base/check.h"
 #include "base/containers/contains.h"
+#include "base/functional/callback_forward.h"
+#include "base/functional/callback_helpers.h"
+#include "base/location.h"
 #include "base/logging.h"
+#include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
 #include "base/task/single_thread_task_runner.h"
+#include "base/threading/thread.h"
 #include "build/build_config.h"
 #include "ui/base/test/ui_controls.h"
 #include "ui/gfx/native_widget_types.h"
@@ -175,6 +181,59 @@
 #endif
 }
 
+bool InteractionTestUtilMouse::SendButtonPress(
+    const MouseButtonGesture& gesture,
+    gfx::NativeWindow window_hint,
+    base::OnceClosure sync_operation_complete) {
+  if (sync_operation_complete) {
+    return ui_controls::SendMouseEventsNotifyWhenDone(
+        gesture.first, gesture.second, std::move(sync_operation_complete),
+        ui_controls::kNoAccelerator, window_hint);
+  }
+
+  base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          [](base::WeakPtr<InteractionTestUtilMouse> util,
+             MouseButtonGesture gesture, gfx::NativeWindow window_hint) {
+            if (!util) {
+              return;
+            }
+            CHECK(ui_controls::SendMouseEvents(gesture.first, gesture.second,
+                                               ui_controls::kNoAccelerator,
+                                               window_hint));
+          },
+          weak_ptr_factory_.GetWeakPtr(), gesture, window_hint));
+
+  return true;
+}
+
+bool InteractionTestUtilMouse::SendMove(
+    const MouseMoveGesture& gesture,
+    gfx::NativeWindow window_hint,
+    base::OnceClosure sync_operation_complete) {
+  if (sync_operation_complete) {
+    return ui_controls::SendMouseMoveNotifyWhenDone(
+        gesture.x(), gesture.y(), std::move(sync_operation_complete),
+        window_hint);
+  }
+
+  base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          [](base::WeakPtr<InteractionTestUtilMouse> util,
+             MouseMoveGesture gesture, gfx::NativeWindow window_hint) {
+            if (!util) {
+              return;
+            }
+            CHECK(ui_controls::SendMouseMove(gesture.x(), gesture.y(),
+                                             window_hint));
+          },
+          weak_ptr_factory_.GetWeakPtr(), gesture, window_hint));
+
+  return true;
+}
+
 bool InteractionTestUtilMouse::PerformGesturesImpl(
     MouseGestures gestures,
     gfx::NativeWindow window_hint) {
@@ -186,31 +245,59 @@
     if (canceled_)
       break;
 
+    bool force_async = false;
+#if BUILDFLAG(IS_MAC)
+    force_async = base::Contains(buttons_down_, ui_controls::RIGHT);
+#endif
+
     base::RunLoop run_loop{base::RunLoop::Type::kNestableTasksAllowed};
     if (MouseButtonGesture* const button =
             absl::get_if<MouseButtonGesture>(&gesture)) {
       switch (button->second) {
         case ui_controls::UP:
           CHECK(buttons_down_.erase(button->first));
-          if (!ui_controls::SendMouseEventsNotifyWhenDone(
-                  button->first, button->second, run_loop.QuitClosure(),
-                  ui_controls::kNoAccelerator, window_hint)) {
+          if (!SendButtonPress(*button, window_hint,
+                               force_async ? base::NullCallback()
+                                           : run_loop.QuitClosure())) {
             LOG(ERROR) << "Mouse button " << button->first << " up failed.";
             return false;
           }
-          run_loop.Run();
+          if (!force_async) {
+            run_loop.Run();
+          }
           MaybeCancelDrag(true);
           break;
         case ui_controls::DOWN:
           CHECK(buttons_down_.insert(button->first).second);
+#if BUILDFLAG(IS_MAC)
+          if (!force_async && button->first == ui_controls::RIGHT) {
+            force_async = true;
+            LOG(WARNING)
+                << "InteractionTestUtilMouse::PerformGestures(): "
+                   "Important note:\n"
+                << "Because right-clicking on Mac typically results in a "
+                   "context menu, and because context menus on Mac are native "
+                   "and take over the main message loop, mouse events from "
+                   "here until release of the right mouse button will be sent "
+                   "asynchronously to avoid a hang.\n"
+                << "Furthermore, your test will likely still hang unless you "
+                   "explicitly find and close the context menu. There is (as "
+                   "of the time this warning was written) no general way to do "
+                   "this because it requires access to the menu runner, which "
+                   "is not always publicly exposed.";
+          }
+#endif
           MaybeCancelDrag(false);
-          if (!ui_controls::SendMouseEventsNotifyWhenDone(
-                  button->first, button->second, run_loop.QuitClosure(),
-                  ui_controls::kNoAccelerator, window_hint)) {
+          if (!SendButtonPress(*button, window_hint,
+                               force_async ? base::NullCallback()
+                                           : run_loop.QuitClosure())) {
             LOG(ERROR) << "Mouse button " << button->first << " down failed.";
             return false;
           }
-          run_loop.Run();
+
+          if (!force_async) {
+            run_loop.Run();
+          }
           break;
       }
     } else {
@@ -221,12 +308,16 @@
         dragging_ = true;
       }
 #endif
-      if (!ui_controls::SendMouseMoveNotifyWhenDone(
-              move.x(), move.y(), run_loop.QuitClosure(), window_hint)) {
+      if (!SendMove(
+              move, window_hint,
+              force_async ? base::NullCallback() : run_loop.QuitClosure())) {
         LOG(ERROR) << "Mouse move to " << move.ToString() << " failed.";
         return false;
       }
-      run_loop.Run();
+
+      if (!force_async) {
+        run_loop.Run();
+      }
     }
   }
 
@@ -234,6 +325,7 @@
 }
 
 void InteractionTestUtilMouse::CancelAllGestures() {
+  weak_ptr_factory_.InvalidateWeakPtrs();
   canceled_ = true;
 
   // Now that no additional actions will happen, release all mouse buttons.
diff --git a/ui/views/interaction/interaction_test_util_mouse.h b/ui/views/interaction/interaction_test_util_mouse.h
index 5978bc40..6fba9b9 100644
--- a/ui/views/interaction/interaction_test_util_mouse.h
+++ b/ui/views/interaction/interaction_test_util_mouse.h
@@ -78,6 +78,13 @@
 
   void MaybeCancelDrag(bool in_future);
 
+  bool SendButtonPress(const MouseButtonGesture& gesture,
+                       gfx::NativeWindow window_hint,
+                       base::OnceClosure sync_operation_complete);
+  bool SendMove(const MouseMoveGesture& gesture,
+                gfx::NativeWindow window_hint,
+                base::OnceClosure sync_operation_complete);
+
   // The set of mouse buttons currently depressed. Used to clean up on abort.
   std::set<ui_controls::MouseButton> buttons_down_;
 
@@ -99,6 +106,8 @@
   class NativeWindowRef;
   const std::unique_ptr<NativeWindowRef> native_window_;
 #endif
+
+  base::WeakPtrFactory<InteractionTestUtilMouse> weak_ptr_factory_{this};
 };
 
 template <typename... Args>
diff --git a/ui/webui/resources/cr_components/help_bubble/BUILD.gn b/ui/webui/resources/cr_components/help_bubble/BUILD.gn
index 229a679..21716ba2 100644
--- a/ui/webui/resources/cr_components/help_bubble/BUILD.gn
+++ b/ui/webui/resources/cr_components/help_bubble/BUILD.gn
@@ -14,7 +14,10 @@
 mojom("mojo_bindings") {
   sources = [ "help_bubble.mojom" ]
 
-  public_deps = [ "//mojo/public/mojom/base" ]
+  public_deps = [
+    "//mojo/public/mojom/base",
+    "//ui/gfx/geometry/mojom",
+  ]
 
   webui_module_path = "chrome://resources/cr_components/help_bubble/"
 }
diff --git a/ui/webui/resources/cr_components/help_bubble/help_bubble.mojom b/ui/webui/resources/cr_components/help_bubble/help_bubble.mojom
index 37fc326..bcde6f7 100644
--- a/ui/webui/resources/cr_components/help_bubble/help_bubble.mojom
+++ b/ui/webui/resources/cr_components/help_bubble/help_bubble.mojom
@@ -5,6 +5,7 @@
 module help_bubble.mojom;
 
 import "mojo/public/mojom/base/time.mojom";
+import "ui/gfx/geometry/mojom/geometry.mojom";
 
 // Contains IPC calls that allow the HelpBubbleFactory system to connect to
 // the HelpBubbleMixin and HelpBubbleElement component.
@@ -105,7 +106,9 @@
 interface HelpBubbleHandler {
   // Indicates that the visibility of the element that the help bubble could be
   // anchored to has changed.
-  HelpBubbleAnchorVisibilityChanged(string native_identifier, bool visible);
+  HelpBubbleAnchorVisibilityChanged(string native_identifier,
+                                    bool visible,
+                                    gfx.mojom.RectF rect);
 
   // Notifies that a specific element tagged as a help bubble anchor has been
   // activated, which will in turn be propagated through the ui::ElementTracker
diff --git a/ui/webui/resources/cr_components/help_bubble/help_bubble_mixin.ts b/ui/webui/resources/cr_components/help_bubble/help_bubble_mixin.ts
index 8da6ec23..88207aaa 100644
--- a/ui/webui/resources/cr_components/help_bubble/help_bubble_mixin.ts
+++ b/ui/webui/resources/cr_components/help_bubble/help_bubble_mixin.ts
@@ -20,6 +20,7 @@
 
 import {assert} from 'chrome://resources/js/assert_ts.js';
 import {EventTracker} from 'chrome://resources/js/event_tracker.js';
+import {RectF} from 'chrome://resources/mojo/ui/gfx/geometry/mojom/geometry.mojom-webui.js';
 import {dedupingMixin, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {HELP_BUBBLE_DISMISSED_EVENT, HELP_BUBBLE_TIMED_OUT_EVENT, HelpBubbleDismissedEvent, HelpBubbleElement} from './help_bubble.js';
@@ -327,8 +328,16 @@
             this.helpBubbleHandler_.helpBubbleClosed(
                 nativeId, HelpBubbleClosedReason.kPageChanged);
           }
+          const rect = new RectF();
+          if (isVisible) {
+            const bounds = target.getBoundingClientRect();
+            rect.x = bounds.x;
+            rect.y = bounds.y;
+            rect.width = bounds.width;
+            rect.height = bounds.height;
+          }
           this.helpBubbleHandler_.helpBubbleAnchorVisibilityChanged(
-              nativeId, isVisible);
+              nativeId, isVisible, rect);
         }
 
         /**
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java
index 3574f2c1..08302a6 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java
@@ -13,7 +13,6 @@
 import org.chromium.base.supplier.Supplier;
 import org.chromium.components.embedder_support.util.UrlUtilities;
 import org.chromium.components.external_intents.ExternalNavigationDelegate;
-import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.url.GURL;
@@ -60,12 +59,6 @@
     }
 
     @Override
-    public void loadUrlIfPossible(LoadUrlParams loadUrlParams) {
-        if (!hasValidTab()) return;
-        mTab.loadUrl(loadUrlParams);
-    }
-
-    @Override
     public boolean isApplicationInForeground() {
         return mTab.getBrowser().getBrowserFragment().isVisible();
     }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/InterceptNavigationDelegateClientImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/InterceptNavigationDelegateClientImpl.java
index f52ae76..fd3c7b5 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/InterceptNavigationDelegateClientImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/InterceptNavigationDelegateClientImpl.java
@@ -15,6 +15,7 @@
 import org.chromium.components.external_intents.InterceptNavigationDelegateClient;
 import org.chromium.components.external_intents.InterceptNavigationDelegateImpl;
 import org.chromium.components.external_intents.RedirectHandler;
+import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsObserver;
@@ -167,7 +168,7 @@
                     navigation.setIsUserDecidingIntentLaunch();
                 }
                 break;
-            case OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB:
+            case OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB:
             case OverrideUrlLoadingResultType.NO_OVERRIDE:
             default:
                 break;
@@ -177,4 +178,10 @@
     static void closeTab(TabImpl tab) {
         tab.getBrowser().destroyTab(tab);
     }
+
+    @Override
+    public void loadUrlIfPossible(LoadUrlParams loadUrlParams) {
+        if (mDestroyed) return;
+        mTab.loadUrl(loadUrlParams);
+    }
 }