diff --git a/DEPS b/DEPS
index f435c3a8..ee2a6ba 100644
--- a/DEPS
+++ b/DEPS
@@ -297,11 +297,11 @@
   # 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': '4230d45a2f1d20f42be581ae73cae098519c2f90',
+  'skia_revision': '3b5bc87f117e6818bb9cafc8f31599fa3a12d529',
   # 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': 'f811d9ab7df0016978bb3059440d4b60537ccc9e',
+  'v8_revision': 'ee693918cc40b49095d46157a24d38950b2c4769',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
@@ -324,7 +324,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
-  'fuchsia_version': 'version:9.20220719.3.1',
+  'fuchsia_version': 'version:9.20220720.1.1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -376,7 +376,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': 'cdaa82eb133e0a640736978c4605eae581da56bc',
+  'devtools_frontend_revision': '2abdc356ba855cd026b9b81a221028d35a957a60',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -412,7 +412,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'aea3154e461b73ae7912679162a10abd515ab56c',
+  'dawn_revision': 'dbf3f4c8c25d7083171167ef2df9f76118abba87',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -773,7 +773,7 @@
     Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + 'c58ae99b9ff9e2aa4c524633519570bf33536248',
 
   'src/docs/website': {
-    'url': Var('chromium_git') + '/website.git' + '@' + '1bc046658540a1c45a9fb142dc4a36d5762ffc1b',
+    'url': Var('chromium_git') + '/website.git' + '@' + '3965ba67f8d283378e6c0b64d634b91fb830a378',
   },
 
   'src/ios/third_party/earl_grey2/src': {
@@ -1584,7 +1584,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'ac8e40ad9eda05b00c491201b9cffbeaad8f566e',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'c2235982559f7008e5384d5145e1febe571573cd',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1751,10 +1751,10 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '44e4c8770158c505b03ee7feafa4859d083b0912',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'ea005701c620004cd8cee217284d49d47acae36c',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'bee49351f3258c1773561b87557c477df28560d1',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '049dde6c8ef0eaaa00896787783f6725c9a2fe78',
+    Var('webrtc_git') + '/src.git' + '@' + 'ed7526c3f188abdb90db9fbee7f46dd8a1408146',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1827,7 +1827,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@278777ee0df2a9427bc17cd5f871abd882fab83e',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@7861871d1795b5673070f9b34ba640d4faee2bc7',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/WATCHLISTS b/WATCHLISTS
index ee510c48..fee9fac 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -903,7 +903,6 @@
     'cursor': {
       'filepath': 'ash/display/cursor'\
                   '|ash/wm/.*cursor'\
-                  '|ui/aura/cursor/'\
                   '|ui/base/cursor/'\
                   '|ui/base/x/x11_cursor'\
                   '|ui/base/win/win_cursor'\
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index a09a04d..28b6940 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -2176,7 +2176,6 @@
     "//services/media_session/public/mojom",
     "//skia",
     "//ui/aura",
-    "//ui/aura/cursor",
     "//ui/base/cursor",
     "//ui/base/cursor/mojom:cursor_type",
     "//ui/base/dragdrop:types",
diff --git a/ash/app_menu/notification_menu_controller.cc b/ash/app_menu/notification_menu_controller.cc
index e53406b..ad567bad 100644
--- a/ash/app_menu/notification_menu_controller.cc
+++ b/ash/app_menu/notification_menu_controller.cc
@@ -78,9 +78,8 @@
   // |root_menu_|, and remove the entry from the model.
   root_menu_->RemoveMenuItem(notification_menu_view_->parent());
   app_menu_model_adapter_->model()->RemoveItemAt(
-      app_menu_model_adapter_->model()
-          ->GetIndexOfCommandId(NOTIFICATION_CONTAINER)
-          .value());
+      app_menu_model_adapter_->model()->GetIndexOfCommandId(
+          NOTIFICATION_CONTAINER));
   notification_menu_view_ = nullptr;
 
   // Notify the root MenuItemView so it knows to resize and re-calculate the
diff --git a/ash/capture_mode/capture_mode_session.cc b/ash/capture_mode/capture_mode_session.cc
index 5c1a878..ca0827c 100644
--- a/ash/capture_mode/capture_mode_session.cc
+++ b/ash/capture_mode/capture_mode_session.cc
@@ -46,7 +46,6 @@
 #include "cc/paint/paint_flags.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/capture_client.h"
-#include "ui/aura/cursor/cursor_util.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
@@ -77,6 +76,7 @@
 #include "ui/views/controls/label.h"
 #include "ui/views/widget/widget.h"
 #include "ui/wm/core/coordinate_conversion.h"
+#include "ui/wm/core/cursor_util.h"
 
 namespace ash {
 
@@ -258,7 +258,7 @@
           capture_image ? IDR_CAPTURE_IMAGE_CURSOR : IDR_CAPTURE_VIDEO_CURSOR);
   SkBitmap bitmap = *icon->bitmap();
   gfx::Point hotspot(bitmap.width() / 2, bitmap.height() / 2);
-  aura::ScaleAndRotateCursorBitmapAndHotpoint(
+  wm::ScaleAndRotateCursorBitmapAndHotpoint(
       device_scale_factor, display.panel_rotation(), &bitmap, &hotspot);
   auto* cursor_factory = ui::CursorFactory::GetInstance();
   cursor.SetPlatformCursor(
diff --git a/ash/capture_mode/video_recording_watcher.cc b/ash/capture_mode/video_recording_watcher.cc
index 4b7ec3e..f556532 100644
--- a/ash/capture_mode/video_recording_watcher.cc
+++ b/ash/capture_mode/video_recording_watcher.cc
@@ -25,7 +25,6 @@
 #include "base/notreached.h"
 #include "base/time/time.h"
 #include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/aura/cursor/cursor_lookup.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/compositor/layer.h"
@@ -39,6 +38,7 @@
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/scoped_canvas.h"
 #include "ui/wm/core/coordinate_conversion.h"
+#include "ui/wm/core/cursor_lookup.h"
 #include "ui/wm/public/activation_client.h"
 
 namespace ash {
@@ -775,9 +775,9 @@
   DCHECK_NE(cursor.type(), ui::mojom::CursorType::kNull);
 
   const float cursor_image_scale_factor = cursor.image_scale_factor();
-  const SkBitmap cursor_image = aura::GetCursorBitmap(cursor);
+  const SkBitmap cursor_image = wm::GetCursorBitmap(cursor);
   const gfx::RectF cursor_overlay_bounds = GetCursorOverlayBounds(
-      window_being_recorded_, location, aura::GetCursorHotspot(cursor),
+      window_being_recorded_, location, wm::GetCursorHotspot(cursor),
       cursor_image_scale_factor, cursor_image);
 
   if (cursor != last_cursor_) {
diff --git a/ash/clipboard/clipboard_history_menu_model_adapter.cc b/ash/clipboard/clipboard_history_menu_model_adapter.cc
index 46b99149..259c658 100644
--- a/ash/clipboard/clipboard_history_menu_model_adapter.cc
+++ b/ash/clipboard/clipboard_history_menu_model_adapter.cc
@@ -364,7 +364,7 @@
 
   // The menu item view and its corresponding command should be removed at the
   // same time. Otherwise, it may run into check errors.
-  model_->RemoveItemAt(model_->GetIndexOfCommandId(command_id).value());
+  model_->RemoveItemAt(model_->GetIndexOfCommandId(command_id));
   root_view_->RemoveMenuItem(root_view_->GetMenuItemByID(command_id));
   root_view_->ChildrenChanged();
 
diff --git a/ash/components/drivefs/fake_drivefs.cc b/ash/components/drivefs/fake_drivefs.cc
index 6ec2496..2b3e6fa 100644
--- a/ash/components/drivefs/fake_drivefs.cc
+++ b/ash/components/drivefs/fake_drivefs.cc
@@ -534,15 +534,8 @@
 
 void FakeDriveFs::GetPooledQuotaUsage(
     drivefs::mojom::DriveFs::GetPooledQuotaUsageCallback callback) {
-  auto usage = mojom::PooledQuotaUsage::New();
-
-  usage->user_type = mojom::UserType::kUnmanaged;
-  usage->used_user_bytes = 1 * 1024 * 1024;
-  usage->total_user_bytes = 2 * 1024 * 1024;
-  usage->organization_limit_exceeded = false;
-  usage->organization_name = "Test Organization";
-
-  std::move(callback).Run(drive::FileError::FILE_ERROR_OK, std::move(usage));
+  std::move(callback).Run(drive::FileError::FILE_ERROR_SERVICE_UNAVAILABLE,
+                          mojom::PooledQuotaUsage::New());
 }
 
 void FakeDriveFs::ToggleMirroring(
diff --git a/ash/display/cursor_window_controller.cc b/ash/display/cursor_window_controller.cc
index cf795a8..17b6de4 100644
--- a/ash/display/cursor_window_controller.cc
+++ b/ash/display/cursor_window_controller.cc
@@ -22,7 +22,6 @@
 #include "base/command_line.h"
 #include "base/metrics/histogram_macros.h"
 #include "components/prefs/pref_service.h"
-#include "ui/aura/cursor/cursors_aura.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
@@ -40,6 +39,7 @@
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_skia_operations.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/core/cursors_aura.h"
 
 namespace ash {
 namespace {
@@ -364,8 +364,8 @@
     hot_point_in_physical_pixels = cursor_.custom_hotspot();
   } else {
     int resource_id;
-    if (!aura::GetCursorDataFor(cursor_size_, cursor_.type(), cursor_scale,
-                                &resource_id, &hot_point_in_physical_pixels)) {
+    if (!wm::GetCursorDataFor(cursor_size_, cursor_.type(), cursor_scale,
+                              &resource_id, &hot_point_in_physical_pixels)) {
       return;
     }
     image =
diff --git a/ash/public/cpp/session/session_controller.h b/ash/public/cpp/session/session_controller.h
index fd5555d..5759979b 100644
--- a/ash/public/cpp/session/session_controller.h
+++ b/ash/public/cpp/session/session_controller.h
@@ -69,7 +69,10 @@
   // Runs the pre-unlock animation. Invoked by the screen locker before
   // dismissing. When the mojo call returns, screen locker takes that as a
   // signal of finished unlock animation and dismisses itself.
-  using RunUnlockAnimationCallback = base::OnceClosure;
+  // The boolean parameter will be `true` if the unlock animation was aborted,
+  // resulting in the lock screen being reshown. It will be false otherwise and
+  // the unlock will proceed as normal.
+  using RunUnlockAnimationCallback = base::OnceCallback<void(bool)>;
   virtual void RunUnlockAnimation(RunUnlockAnimationCallback callback) = 0;
 
   // Notifies that chrome is terminating.
diff --git a/ash/public/cpp/views_text_services_context_menu_impl.cc b/ash/public/cpp/views_text_services_context_menu_impl.cc
index 3bcf0612..70677db 100644
--- a/ash/public/cpp/views_text_services_context_menu_impl.cc
+++ b/ash/public/cpp/views_text_services_context_menu_impl.cc
@@ -83,15 +83,15 @@
 
 void ViewsTextServicesContextMenuImpl::AddClipboardHistoryMenuOption(
     ui::SimpleMenuModel* menu) {
-  const absl::optional<size_t> index_of_paste =
+  const int index_of_paste =
       menu->GetIndexOfCommandId(ui::TouchEditable::kPaste);
 
   // Only add the clipboard history menu option when having the menu option
   // for paste.
-  if (!index_of_paste.has_value())
+  if (index_of_paste == -1)
     return;
 
-  const size_t target_index = index_of_paste.value() + 1;
+  const int target_index = index_of_paste + 1;
   menu->InsertItemAt(target_index, IDS_APP_SHOW_CLIPBOARD_HISTORY,
                      l10n_util::GetStringUTF16(IDS_APP_SHOW_CLIPBOARD_HISTORY));
   if (ClipboardHistoryController::Get()->ShouldShowNewFeatureBadge()) {
diff --git a/ash/session/session_controller_impl_unittest.cc b/ash/session/session_controller_impl_unittest.cc
index 5a3c048..a71d739 100644
--- a/ash/session/session_controller_impl_unittest.cc
+++ b/ash/session/session_controller_impl_unittest.cc
@@ -21,6 +21,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/run_loop.h"
+#include "base/test/bind.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/user_manager/user_type.h"
@@ -447,7 +448,8 @@
 
     // Mark a running unlock animation.
     base::RunLoop run_loop;
-    controller()->RunUnlockAnimation(run_loop.QuitClosure());
+    controller()->RunUnlockAnimation(base::BindLambdaForTesting(
+        [&run_loop](bool aborted) { run_loop.Quit(); }));
     run_loop.Run();
     EXPECT_EQ(test_case.expect_blocked_after_unlock_animation,
               controller()->IsUserSessionBlocked())
diff --git a/ash/shelf/shelf_application_menu_model.cc b/ash/shelf/shelf_application_menu_model.cc
index 9aab2aa..3e8de8d 100644
--- a/ash/shelf/shelf_application_menu_model.cc
+++ b/ash/shelf/shelf_application_menu_model.cc
@@ -38,7 +38,8 @@
                     ui::ImageModel::FromImageSkia(item.icon));
   }
   AddSeparator(ui::SPACING_SEPARATOR);
-  DCHECK_EQ(GetItemCount(), items.size() + 2) << "Update metrics |- 2|";
+  DCHECK_EQ(GetItemCount(), static_cast<int>(items.size() + 2))
+      << "Update metrics |- 2|";
 }
 
 ShelfApplicationMenuModel::~ShelfApplicationMenuModel() = default;
@@ -62,8 +63,7 @@
                               event_flags, display::kInvalidDisplayId);
   }
   // Subtract two to avoid counting the title and separator.
-  RecordMenuItemSelectedMetrics(command_id,
-                                std::max(GetItemCount(), size_t{2}) - 2);
+  RecordMenuItemSelectedMetrics(command_id, std::max(GetItemCount() - 2, 0));
 }
 
 void ShelfApplicationMenuModel::RecordMenuItemSelectedMetrics(
diff --git a/ash/shelf/shelf_application_menu_model_unittest.cc b/ash/shelf/shelf_application_menu_model_unittest.cc
index 051ccf7..ed3ff70 100644
--- a/ash/shelf/shelf_application_menu_model_unittest.cc
+++ b/ash/shelf/shelf_application_menu_model_unittest.cc
@@ -53,7 +53,7 @@
   std::u16string title = u"title";
   ShelfApplicationMenuModel menu(title, {}, nullptr);
   // Expect the title and a separator.
-  ASSERT_EQ(2u, menu.GetItemCount());
+  ASSERT_EQ(2, menu.GetItemCount());
   EXPECT_EQ(ui::MenuModel::TYPE_TITLE, menu.GetTypeAt(0));
   EXPECT_EQ(title, menu.GetLabelAt(0));
   EXPECT_FALSE(menu.IsEnabledAt(0));
@@ -75,7 +75,7 @@
   ShelfApplicationMenuModelTestAPI menu_test_api(&menu);
 
   // Expect the title and the enabled items.
-  ASSERT_EQ(5u, menu.GetItemCount());
+  ASSERT_EQ(static_cast<int>(5), menu.GetItemCount());
 
   // The label title should not be enabled.
   EXPECT_EQ(ui::MenuModel::TYPE_TITLE, menu.GetTypeAt(0));
diff --git a/ash/shelf/shelf_context_menu_model_unittest.cc b/ash/shelf/shelf_context_menu_model_unittest.cc
index f39b197d..0209e3435 100644
--- a/ash/shelf/shelf_context_menu_model_unittest.cc
+++ b/ash/shelf/shelf_context_menu_model_unittest.cc
@@ -123,7 +123,7 @@
 TEST_P(ShelfContextMenuModelTest, Basic) {
   ShelfContextMenuModel menu(nullptr, GetPrimaryDisplay().id());
 
-  ASSERT_EQ(3u, menu.GetItemCount());
+  ASSERT_EQ(3, menu.GetItemCount());
   EXPECT_EQ(CommandId::MENU_AUTO_HIDE, menu.GetCommandIdAt(0));
   EXPECT_EQ(CommandId::MENU_ALIGNMENT_MENU, menu.GetCommandIdAt(1));
   if (IsPersonalizationHubParamEnabled()) {
@@ -131,7 +131,7 @@
   } else {
     EXPECT_EQ(CommandId::MENU_CHANGE_WALLPAPER, menu.GetCommandIdAt(2));
   }
-  for (size_t i = 0; i < menu.GetItemCount(); ++i) {
+  for (int i = 0; i < menu.GetItemCount(); ++i) {
     EXPECT_TRUE(menu.IsEnabledAt(i));
     EXPECT_TRUE(menu.IsVisibleAt(i));
   }
@@ -140,7 +140,7 @@
   EXPECT_EQ(ui::MenuModel::TYPE_SUBMENU, menu.GetTypeAt(1));
   ui::MenuModel* submenu = menu.GetSubmenuModelAt(1);
   ASSERT_TRUE(submenu);
-  ASSERT_EQ(3u, submenu->GetItemCount());
+  ASSERT_EQ(3, submenu->GetItemCount());
   EXPECT_EQ(CommandId::MENU_ALIGNMENT_LEFT, submenu->GetCommandIdAt(0));
   EXPECT_EQ(CommandId::MENU_ALIGNMENT_BOTTOM, submenu->GetCommandIdAt(1));
   EXPECT_EQ(CommandId::MENU_ALIGNMENT_RIGHT, submenu->GetCommandIdAt(2));
@@ -205,7 +205,7 @@
 
   // Because the delegate is valid, the context menu will not have the desktop
   // menu options (autohide, shelf position, and wallpaper picker).
-  ASSERT_EQ(0u, menu.GetItemCount());
+  ASSERT_EQ(0, menu.GetItemCount());
 
   // Add some custom items.
   menu.AddItem(203, u"item");
@@ -215,7 +215,7 @@
   menu.AddSubMenu(55, u"submenu", &submenu);
 
   // Ensure the menu contents match the items above.
-  ASSERT_EQ(4u, menu.GetItemCount());
+  ASSERT_EQ(4, menu.GetItemCount());
   EXPECT_EQ(ui::MenuModel::TYPE_COMMAND, menu.GetTypeAt(0));
   EXPECT_EQ(ui::MenuModel::TYPE_CHECK, menu.GetTypeAt(1));
   EXPECT_EQ(ui::MenuModel::TYPE_RADIO, menu.GetTypeAt(2));
@@ -239,10 +239,8 @@
 
   ShelfContextMenuModel primary_menu(nullptr, primary_id);
   ShelfContextMenuModel secondary_menu(nullptr, secondary_id);
-  EXPECT_FALSE(
-      primary_menu.GetIndexOfCommandId(CommandId::MENU_AUTO_HIDE).has_value());
-  EXPECT_TRUE(secondary_menu.GetIndexOfCommandId(CommandId::MENU_AUTO_HIDE)
-                  .has_value());
+  EXPECT_EQ(-1, primary_menu.GetIndexOfCommandId(CommandId::MENU_AUTO_HIDE));
+  EXPECT_NE(-1, secondary_menu.GetIndexOfCommandId(CommandId::MENU_AUTO_HIDE));
 }
 
 // Tests that the autohide and alignment menu options are not included in tablet
@@ -256,7 +254,7 @@
   // options because other options are disabled.
   tablet_mode_controller->SetEnabledForTest(true);
   ShelfContextMenuModel menu1(nullptr, primary_id);
-  EXPECT_EQ(2u, menu1.GetItemCount());
+  EXPECT_EQ(2, menu1.GetItemCount());
   EXPECT_EQ(ShelfContextMenuModel::MENU_AUTO_HIDE, menu1.GetCommandIdAt(0));
   if (IsPersonalizationHubParamEnabled()) {
     EXPECT_EQ(ShelfContextMenuModel::MENU_PERSONALIZATION_HUB,
@@ -270,7 +268,7 @@
   // MENU_AUTO_HIDE, MENU_ALIGNMENT_MENU, and MENU_CHANGE_WALLPAPER.
   tablet_mode_controller->SetEnabledForTest(false);
   ShelfContextMenuModel menu2(nullptr, primary_id);
-  EXPECT_EQ(3u, menu2.GetItemCount());
+  EXPECT_EQ(3, menu2.GetItemCount());
 
   // Test the auto hide option.
   EXPECT_EQ(ShelfContextMenuModel::MENU_AUTO_HIDE, menu2.GetCommandIdAt(0));
@@ -323,7 +321,7 @@
   // tools/metrics/enums.xml and that you haven't modified the order of the
   // existing enums.
   ShelfContextMenuModel menu(nullptr, GetPrimaryDisplay().id());
-  EXPECT_EQ(3u, menu.GetItemCount());
+  EXPECT_EQ(3, menu.GetItemCount());
 }
 
 TEST_P(ShelfContextMenuModelTest, NotificationContainerEnabled) {
diff --git a/ash/webui/camera_app_ui/resources/js/custom_toast.ts b/ash/webui/camera_app_ui/resources/js/custom_effect.ts
similarity index 71%
rename from ash/webui/camera_app_ui/resources/js/custom_toast.ts
rename to ash/webui/camera_app_ui/resources/js/custom_effect.ts
index 1204ab7..6a50bdc 100644
--- a/ash/webui/camera_app_ui/resources/js/custom_toast.ts
+++ b/ash/webui/camera_app_ui/resources/js/custom_effect.ts
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import * as animation from './animation.js';
-import {assert, assertExists, assertNotReached} from './assert.js';
+import {assertExists, assertInstanceof, assertNotReached} from './assert.js';
 import * as dom from './dom.js';
 import {I18nString} from './i18n_string.js';
 import * as loadTimeData from './models/load_time_data.js';
@@ -255,21 +255,36 @@
   }
 }
 
-let showing: {
-  ripple: RippleEffect|null,
-  toast: Toast,
-  timeout: number,
-}|null = null;
+interface EffectPayload {
+  ripple: RippleEffect|null;
+  toast: Toast;
+  timeout: number;
+}
+
+interface EffectHandle {
+  hide: () => void;
+  focusToast: () => void;
+}
+
+let globalEffectPayload: EffectPayload|null = null;
 
 /**
- * Hides the new feature toast.
+ * Hides the specified effect or the effect being showing.
  */
-export function hide(): void {
-  if (showing === null) {
-    return;
+export function hide(effectPayload?: EffectPayload): void {
+  if (effectPayload !== undefined) {
+    stopEffect(effectPayload);
+    if (effectPayload === globalEffectPayload) {
+      globalEffectPayload = null;
+    }
+  } else if (globalEffectPayload !== null) {
+    stopEffect(globalEffectPayload);
+    globalEffectPayload = null;
   }
-  const {ripple, toast, timeout} = showing;
-  showing = null;
+}
+
+function stopEffect(effectPayload: EffectPayload) {
+  const {ripple, toast, timeout} = effectPayload;
   if (ripple !== null) {
     ripple.stop();
   }
@@ -278,16 +293,18 @@
 }
 
 /**
- * Timeout for showing new feature toast.
+ * Timeout for effects.
  */
-const SHOWING_TIMEOUT_MS = 10000;
+const EFFECT_TIMEOUT_MS = 10000;
 
 /**
- * Shows the new feature toast message around the `anchor` element. The message
- * to show is defined in HTML attribute and the relative position is defined in
- * CSS.
+ * Shows the new feature toast message and ripple around the `anchor` element.
+ * The message to show is defined in HTML attribute and the relative position is
+ * defined in CSS.
+ *
+ * @return Functions to hide the effect or focus the toast.
  */
-export function showNewFeatureToast(anchor: HTMLElement): void {
+export function showNewFeature(anchor: HTMLElement): EffectHandle {
   return show(new NewFeatureToast(anchor), new RippleEffect(anchor));
 }
 
@@ -295,37 +312,81 @@
  * Shows the indicator toast message and an indicator dot around the `anchor`
  * element. The message to show is given by `indicatorType` and the relative
  * position of the toast and dot are defined in CSS.
+ *
+ * @return Functions to hide the effect or focus the toast.
  */
-export function showIndicatorToast(
-    anchor: HTMLElement, indicatorType: IndicatorType): void {
-  assert(indicatorType !== undefined);
+export function showIndicator(
+    anchor: HTMLElement, indicatorType: IndicatorType): EffectHandle {
   return show(new IndicatorToast(anchor, indicatorType));
 }
 
 /**
- * Shows the toast on the given element.
+ * Shows the effects.
+ *
+ * @return Functions to hide the effect or focus the toast.
  */
-function show(toast: Toast, ripple: RippleEffect|null = null): void {
+function show(toast: Toast, ripple: RippleEffect|null = null): EffectHandle {
   hide();
 
-  const timeout = setTimeout(hide, SHOWING_TIMEOUT_MS);
-  showing = {ripple, toast, timeout};
+  const timeout = setTimeout(hide, EFFECT_TIMEOUT_MS);
+  globalEffectPayload = {ripple, toast, timeout};
   toast.show();
+  const originalEffectPayload = globalEffectPayload;
+  return {
+    hide: () => hide(originalEffectPayload),
+    focusToast: () => toast.focus(),
+  };
 }
 
 /**
- * @return If toast is showing.
+ * @return If effect is showing.
  */
 export function isShowing(): boolean {
-  return showing !== null;
+  return globalEffectPayload !== null;
 }
 
 /**
  * Focuses to toast.
  */
 export function focus(): void {
-  if (showing === null) {
+  if (globalEffectPayload === null) {
     return;
   }
-  showing.toast.focus();
+  globalEffectPayload.toast.focus();
+}
+
+/**
+ * Shows feature visual effect for PTZ options entry.
+ */
+export function showPtzToast(): void {
+  const ptzPanelEntry = dom.get('#open-ptz-panel', HTMLButtonElement);
+  const {hide, focusToast} = showNewFeature(ptzPanelEntry);
+  focusToast();
+  ptzPanelEntry.addEventListener('click', hide, {once: true});
+}
+
+/**
+ * Shows feature visual effect for document mode entry.
+ */
+export function showDocToast(): void {
+  const scanModeButton = dom.get('input[data-mode="scan"]', HTMLInputElement);
+  const scanModeItem =
+      assertInstanceof(scanModeButton.parentElement, HTMLDivElement);
+  // aria-owns don't work on HTMLInputElement, show toast on parent div
+  // instead.
+  const {hide} = showNewFeature(scanModeItem);
+  scanModeButton.addEventListener('click', hide, {once: true});
+}
+
+/**
+ * Shows loading indicator toast for document mode when it's supported but not
+ * yet ready.
+ */
+export function showDocIndicator(): void {
+  const scanModeButton = dom.get('input[data-mode="scan"]', HTMLInputElement);
+  const scanModeItem =
+      assertInstanceof(scanModeButton.parentElement, HTMLDivElement);
+  const {hide} =
+      showIndicator(scanModeItem, IndicatorType.DOWNLOAD_DOCUMENT_SCANNER);
+  scanModeButton.addEventListener('click', hide, {once: true});
 }
diff --git a/ash/webui/camera_app_ui/resources/js/js.gni b/ash/webui/camera_app_ui/resources/js/js.gni
index 445e413d..765cbb90 100644
--- a/ash/webui/camera_app_ui/resources/js/js.gni
+++ b/ash/webui/camera_app_ui/resources/js/js.gni
@@ -8,7 +8,7 @@
   "assert.ts",
   "async_job_queue.ts",
   "barcode_chip.ts",
-  "custom_toast.ts",
+  "custom_effect.ts",
   "css.ts",
   "deployed_version.ts",
   "device/camera3_device_info.ts",
diff --git a/ash/webui/camera_app_ui/resources/js/main.ts b/ash/webui/camera_app_ui/resources/js/main.ts
index a878c8cd..e11cb6cd 100644
--- a/ash/webui/camera_app_ui/resources/js/main.ts
+++ b/ash/webui/camera_app_ui/resources/js/main.ts
@@ -6,6 +6,7 @@
   getDefaultWindowSize,
 } from './app_window.js';
 import {assert, assertInstanceof} from './assert.js';
+import * as customEffect from './custom_effect.js';
 import {DEPLOYED_VERSION} from './deployed_version.js';
 import {CameraManager} from './device/index.js';
 import {ModeConstraints} from './device/type.js';
@@ -186,6 +187,71 @@
   }
 
   /**
+   * Sets up visual effects, toasts, and dialogs for the new features.
+   */
+  async setupFeatureEffectsAndDialogs(): Promise<void> {
+    const registerDocDialog = () => {
+      this.cameraManager.registerCameraUI({
+        onUpdateConfig: () => {
+          if (localStorage.getBool(LocalStorageKey.DOC_MODE_DIALOG_SHOWN) ||
+              !state.get(Mode.SCAN) ||
+              // TODO(b/238403258): Remove this line after
+              // camera.CCAUIDocumentScanning.manual_crop is able to close the
+              // dialog.
+              appWindow !== null) {
+            return;
+          }
+          localStorage.set(LocalStorageKey.DOC_MODE_DIALOG_SHOWN, true);
+          const message = loadTimeData.getI18nMessage(
+              I18nString.DOCUMENT_MODE_DIALOG_INTRO_TITLE);
+          nav.open(ViewName.DOCUMENT_MODE_DIALOG, {message});
+        },
+      });
+    };
+    const registerPtzToast = () => {
+      this.cameraManager.registerCameraUI({
+        onUpdateConfig: () => {
+          if (state.get(state.State.ENABLE_PTZ) &&
+              !localStorage.getBool(LocalStorageKey.PTZ_TOAST_SHOWN)) {
+            localStorage.set(LocalStorageKey.PTZ_TOAST_SHOWN, true);
+            customEffect.showPtzToast();
+          }
+        },
+      });
+    };
+
+    const {supported, ready} =
+        await ChromeHelper.getInstance().getDocumentScannerReadyState();
+    // TODO(chuhsuan): Separate loading indicators and feature toasts in
+    // order to provide more control like showing them at the same time.
+    if (supported) {
+      if (!ready) {
+        customEffect.showDocIndicator();
+      }
+      const loaded =
+          await ChromeHelper.getInstance().waitUntilDocumentModeReady();
+      if (loaded) {
+        if (!localStorage.getBool(LocalStorageKey.DOC_MODE_DIALOG_SHOWN)) {
+          registerDocDialog();
+        }
+        if (!localStorage.getBool(LocalStorageKey.DOC_MODE_TOAST_SHOWN)) {
+          localStorage.set(LocalStorageKey.DOC_MODE_TOAST_SHOWN, true);
+          customEffect.showDocToast();
+          return;
+        }
+      }
+    }
+    if (!localStorage.getBool(LocalStorageKey.PTZ_TOAST_SHOWN)) {
+      if (state.get(state.State.ENABLE_PTZ)) {
+        localStorage.set(LocalStorageKey.PTZ_TOAST_SHOWN, true);
+        customEffect.showPtzToast();
+      } else {
+        registerPtzToast();
+      }
+    }
+  }
+
+  /**
    * Sets up visual effect for all applicable elements.
    */
   private setupEffect() {
@@ -318,6 +384,7 @@
 
     metrics.sendLaunchEvent({launchType});
     await Promise.all([showWindow, startCamera, preloadImages]);
+    await this.setupFeatureEffectsAndDialogs();
   }
 
   /**
diff --git a/ash/webui/camera_app_ui/resources/js/state.ts b/ash/webui/camera_app_ui/resources/js/state.ts
index be32a07..e96440d 100644
--- a/ash/webui/camera_app_ui/resources/js/state.ts
+++ b/ash/webui/camera_app_ui/resources/js/state.ts
@@ -31,7 +31,6 @@
   HAS_TILT_SUPPORT = 'has-tilt-support',
   HAS_ZOOM_SUPPORT = 'has-zoom-support',
   INTENT = 'intent',
-  IS_NEW_FEATURE_TOAST_SHOWN = 'is-new-feature-toast-shown',
   KEYBOARD_NAVIGATION = 'keyboard-navigation',
   MAX_WND = 'max-wnd',
   MIC = 'mic',
diff --git a/ash/webui/camera_app_ui/resources/js/views/camera.ts b/ash/webui/camera_app_ui/resources/js/views/camera.ts
index 54525c6..0ac98e5 100644
--- a/ash/webui/camera_app_ui/resources/js/views/camera.ts
+++ b/ash/webui/camera_app_ui/resources/js/views/camera.ts
@@ -7,7 +7,7 @@
   assert,
   assertInstanceof,
 } from '../assert.js';
-import * as customToast from '../custom_toast.js';
+import * as customToast from '../custom_effect.js';
 import {
   CameraConfig,
   CameraManager,
@@ -25,8 +25,6 @@
 import {I18nString} from '../i18n_string.js';
 import * as metrics from '../metrics.js';
 import {Filenamer} from '../models/file_namer.js';
-import * as loadTimeData from '../models/load_time_data.js';
-import * as localStorage from '../models/local_storage.js';
 import {ResultSaver} from '../models/result_saver.js';
 import {VideoSaver} from '../models/video_saver.js';
 import {ChromeHelper} from '../mojo/chrome_helper.js';
@@ -43,7 +41,6 @@
   ErrorType,
   Facing,
   ImageBlob,
-  LocalStorageKey,
   MimeType,
   Mode,
   PerfEvent,
@@ -321,58 +318,10 @@
   }
 
   private async initScanMode() {
-    const {supported, ready} =
-        await ChromeHelper.getInstance().getDocumentScannerReadyState();
-    if (!supported) {
+    const isLoaded = await this.scanOptions.waitUntilDocumentModeReady();
+    if (!isLoaded) {
       return;
     }
-
-    const scanModeBtn = dom.get('input[data-mode="scan"]', HTMLInputElement);
-    const scanModeItem =
-        assertInstanceof(scanModeBtn.parentElement, HTMLDivElement);
-    if (!ready) {
-      customToast.showIndicatorToast(
-          scanModeItem, customToast.IndicatorType.DOWNLOAD_DOCUMENT_SCANNER);
-      scanModeBtn.addEventListener('click', () => {
-        customToast.hide();
-      });
-      const isLoaded = await this.scanOptions.waitUntilDocumentModeReady();
-      if (!isLoaded) {
-        return;
-      }
-    } else {
-      this.scanOptions.onDocumentModeReady();
-    }
-
-    // Check show toast.
-    if (!state.get(state.State.IS_NEW_FEATURE_TOAST_SHOWN) &&
-        !localStorage.getBool(LocalStorageKey.DOC_MODE_TOAST_SHOWN)) {
-      state.set(state.State.IS_NEW_FEATURE_TOAST_SHOWN, true);
-      localStorage.set(LocalStorageKey.DOC_MODE_TOAST_SHOWN, true);
-      // aria-owns don't work on HTMLInputElement, show toast on parent div
-      // instead.
-      customToast.showNewFeatureToast(scanModeItem);
-      scanModeBtn.addEventListener('click', () => {
-        customToast.hide();
-      });
-    }
-
-    if (!localStorage.getBool(LocalStorageKey.DOC_MODE_DIALOG_SHOWN)) {
-      this.cameraManager.registerCameraUI({
-        onUpdateConfig: () => {
-          if (localStorage.getBool(LocalStorageKey.DOC_MODE_DIALOG_SHOWN) ||
-              !state.get(Mode.SCAN) ||
-              !this.scanOptions.isDocumentModeEnabled()) {
-            return;
-          }
-          localStorage.set(LocalStorageKey.DOC_MODE_DIALOG_SHOWN, true);
-          const message = loadTimeData.getI18nMessage(
-              I18nString.DOCUMENT_MODE_DIALOG_INTRO_TITLE);
-          nav.open(ViewName.DOCUMENT_MODE_DIALOG, {message});
-        },
-      });
-    }
-
     // When entering document mode, refocus to shutter button for letting user
     // to take document photo with space key as shortcut. See b/196907822.
     const checkRefocus = () => {
diff --git a/ash/webui/camera_app_ui/resources/js/views/camera/options.ts b/ash/webui/camera_app_ui/resources/js/views/camera/options.ts
index ea50460..41da0cd 100644
--- a/ash/webui/camera_app_ui/resources/js/views/camera/options.ts
+++ b/ash/webui/camera_app_ui/resources/js/views/camera/options.ts
@@ -4,7 +4,6 @@
 
 import * as animate from '../../animation.js';
 import {assert} from '../../assert.js';
-import * as customToast from '../../custom_toast.js';
 import {
   CameraConfig,
   CameraInfo,
@@ -234,36 +233,6 @@
                  vidPid: this.cameraManager.getVidPid(),
                  resetPTZ: () => this.cameraManager.resetPTZ(),
                }));
-      highlight(false);
-    });
-
-    // Highlight effect for PTZ button.
-    let toastShown = false;
-    const highlight = (enabled: boolean) => {
-      if (!enabled) {
-        if (toastShown) {
-          customToast.hide();
-          toastShown = false;
-        }
-        return;
-      }
-      toastShown = true;
-      customToast.showNewFeatureToast(this.openPTZPanel);
-      customToast.focus();
-    };
-
-    this.cameraManager.registerCameraUI({
-      onUpdateConfig: () => {
-        if (!state.get(state.State.ENABLE_PTZ) ||
-            state.get(state.State.IS_NEW_FEATURE_TOAST_SHOWN) ||
-            localStorage.getBool(LocalStorageKey.PTZ_TOAST_SHOWN)) {
-          highlight(false);
-          return;
-        }
-        localStorage.set(LocalStorageKey.PTZ_TOAST_SHOWN, true);
-        state.set(state.State.IS_NEW_FEATURE_TOAST_SHOWN, true);
-        highlight(true);
-      },
     });
   }
 
diff --git a/ash/wm/lock_state_controller.cc b/ash/wm/lock_state_controller.cc
index 42fe3f1..d23b6308 100644
--- a/ash/wm/lock_state_controller.cc
+++ b/ash/wm/lock_state_controller.cc
@@ -168,6 +168,8 @@
 }
 
 void LockStateController::LockWithoutAnimation() {
+  if (animating_unlock_)
+    CancelUnlockAnimation();
   if (animating_lock_)
     return;
   animating_lock_ = true;
@@ -212,6 +214,15 @@
   animation_sequence->EndSequence();
 }
 
+void LockStateController::CancelUnlockAnimation() {
+  VLOG(1) << "CancelUnlockAnimation";
+  animator_->AbortAllAnimations(
+      SessionStateAnimator::SHELF |
+      SessionStateAnimator::LOCK_SCREEN_CONTAINERS |
+      SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS);
+  animating_unlock_ = false;
+}
+
 bool LockStateController::CanCancelShutdownAnimation() {
   return pre_shutdown_timer_.IsRunning();
 }
@@ -251,7 +262,8 @@
   StartRealShutdownTimer(true);
 }
 
-void LockStateController::OnLockScreenHide(base::OnceClosure callback) {
+void LockStateController::OnLockScreenHide(
+    SessionStateAnimator::AnimationCallback callback) {
   StartUnlockAnimationBeforeUIDestroyed(std::move(callback));
 }
 
@@ -428,20 +440,25 @@
 }
 
 void LockStateController::StartUnlockAnimationBeforeUIDestroyed(
-    base::OnceClosure callback) {
+    SessionStateAnimator::AnimationCallback callback) {
   VLOG(1) << "StartUnlockAnimationBeforeUIDestroyed";
+  animating_unlock_ = true;
+  auto* animation_sequence =
+      animator_->BeginAnimationSequence(std::move(callback));
+
   // Hide the lock screen shelf. This is a no-op if views-based shelf is
   // disabled, since shelf is in NonLockScreenContainersContainer.
-  animator_->StartAnimation(SessionStateAnimator::SHELF,
-                            SessionStateAnimator::ANIMATION_FADE_OUT,
-                            SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS);
-  animator_->StartAnimationWithCallback(
+  animation_sequence->StartAnimation(
+      SessionStateAnimator::SHELF, SessionStateAnimator::ANIMATION_FADE_OUT,
+      SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS);
+  animation_sequence->StartAnimation(
       SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
       SessionStateAnimator::ANIMATION_LIFT,
-      SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, std::move(callback));
+      SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS);
   animator_->StartAnimation(SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
                             SessionStateAnimator::ANIMATION_COPY_LAYER,
                             SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
+  animation_sequence->EndSequence();
 }
 
 void LockStateController::StartUnlockAnimationAfterUIDestroyed() {
@@ -512,6 +529,7 @@
 void LockStateController::UnlockAnimationAfterUIDestroyedFinished(
     bool aborted) {
   DVLOG(1) << "UnlockAnimationAfterUIDestroyedFinished: aborted=" << aborted;
+  animating_unlock_ = false;
   Shell::Get()->wallpaper_controller()->UpdateWallpaperBlurForLockState(false);
   RestoreUnlockedProperties();
 }
diff --git a/ash/wm/lock_state_controller.h b/ash/wm/lock_state_controller.h
index f54d55b..0772421 100644
--- a/ash/wm/lock_state_controller.h
+++ b/ash/wm/lock_state_controller.h
@@ -85,6 +85,9 @@
   // Cancels locking and reverts lock animation.
   void CancelLockAnimation();
 
+  // Cancels unlock animation.
+  void CancelUnlockAnimation();
+
   // Returns true if we are within cancellable shutdown timeframe.
   bool CanCancelShutdownAnimation();
 
@@ -98,7 +101,7 @@
   // Called when ScreenLocker is ready to close, but not yet destroyed.
   // Can be used to display "hiding" animations on unlock.
   // |callback| will be called when all animations are done.
-  void OnLockScreenHide(base::OnceClosure callback);
+  void OnLockScreenHide(SessionStateAnimator::AnimationCallback callback);
 
   // Sets up the callback that should be called once lock animation is finished.
   // Callback is guaranteed to be called once and then discarded.
@@ -144,7 +147,8 @@
                         bool request_lock_on_completion);
   void StartPostLockAnimation();
   // This method calls |callback| when animation completes.
-  void StartUnlockAnimationBeforeUIDestroyed(base::OnceClosure callback);
+  void StartUnlockAnimationBeforeUIDestroyed(
+      SessionStateAnimator::AnimationCallback callback);
   void StartUnlockAnimationAfterUIDestroyed();
 
   // These methods are called when corresponding animation completes.
@@ -188,6 +192,9 @@
   // Indicates that controller displays lock animation.
   bool animating_lock_ = false;
 
+  // Indicates that controller displays unlock animation.
+  bool animating_unlock_ = false;
+
   // Indicates whether post lock animation should be immediate.
   bool post_lock_immediate_animation_ = false;
 
diff --git a/ash/wm/lock_state_controller_unittest.cc b/ash/wm/lock_state_controller_unittest.cc
index 13e35a0..3afdd99 100644
--- a/ash/wm/lock_state_controller_unittest.cc
+++ b/ash/wm/lock_state_controller_unittest.cc
@@ -54,7 +54,7 @@
   return Shell::Get()->cursor_manager()->IsCursorVisible();
 }
 
-void CheckCalledCallback(bool* flag) {
+void CheckCalledCallback(bool* flag, bool aborted) {
   if (flag)
     (*flag) = true;
 }
@@ -309,8 +309,8 @@
   }
 
   void SuccessfulAuthentication(bool* call_flag) {
-    base::OnceClosure closure = base::BindOnce(&CheckCalledCallback, call_flag);
-    lock_state_controller_->OnLockScreenHide(std::move(closure));
+    auto callback = base::BindOnce(&CheckCalledCallback, call_flag);
+    lock_state_controller_->OnLockScreenHide(std::move(callback));
   }
 
   bool IsDefaultValueLoginShutdownTimestamp() {
@@ -472,7 +472,7 @@
     if (GetParam()) {
       test_animator_->Advance(test_animator_->GetDuration(speed));
     } else {
-      test_animator_->AbortAnimations(
+      test_animator_->AbortAllAnimations(
           SessionStateAnimator::kAllNonRootContainersMask);
     }
   }
diff --git a/ash/wm/native_cursor_manager_ash.cc b/ash/wm/native_cursor_manager_ash.cc
index 9829a9a..c334bc41 100644
--- a/ash/wm/native_cursor_manager_ash.cc
+++ b/ash/wm/native_cursor_manager_ash.cc
@@ -8,13 +8,13 @@
 #include "ash/display/window_tree_host_manager.h"
 #include "ash/shell.h"
 #include "base/check.h"
-#include "ui/aura/cursor/cursor_loader.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
 #include "ui/base/layout.h"
+#include "ui/wm/core/cursor_loader.h"
 #include "ui/wm/core/native_cursor_manager_delegate.h"
 
 namespace ash {
diff --git a/ash/wm/native_cursor_manager_ash.h b/ash/wm/native_cursor_manager_ash.h
index 5a599d6b..e70d8b18b 100644
--- a/ash/wm/native_cursor_manager_ash.h
+++ b/ash/wm/native_cursor_manager_ash.h
@@ -6,8 +6,8 @@
 #define ASH_WM_NATIVE_CURSOR_MANAGER_ASH_H_
 
 #include "ash/ash_export.h"
-#include "ui/aura/cursor/cursor_loader.h"
 #include "ui/display/display.h"
+#include "ui/wm/core/cursor_loader.h"
 #include "ui/wm/core/native_cursor_manager.h"
 
 namespace ash {
@@ -55,7 +55,7 @@
 
   bool native_cursor_enabled_;
 
-  aura::CursorLoader cursor_loader_{/*use_platform_cursors=*/false};
+  wm::CursorLoader cursor_loader_{/*use_platform_cursors=*/false};
 };
 
 }  // namespace ash
diff --git a/ash/wm/session_state_animator.h b/ash/wm/session_state_animator.h
index 6c0cbce..064d3f66 100644
--- a/ash/wm/session_state_animator.h
+++ b/ash/wm/session_state_animator.h
@@ -194,7 +194,9 @@
   virtual AnimationSequence* BeginAnimationSequence(
       AnimationCallback callback) = 0;
 
-  // Retruns true if the wallpaper is hidden.
+  virtual void AbortAllAnimations(int container_mask) = 0;
+
+  // Returns true if the wallpaper is hidden.
   virtual bool IsWallpaperHidden() const = 0;
 
   // Shows the wallpaper immediately.
diff --git a/ash/wm/session_state_animator_impl.cc b/ash/wm/session_state_animator_impl.cc
index 236dca9d..02f16d3 100644
--- a/ash/wm/session_state_animator_impl.cc
+++ b/ash/wm/session_state_animator_impl.cc
@@ -459,6 +459,16 @@
   return new AnimationSequence(this, std::move(callback));
 }
 
+void SessionStateAnimatorImpl::AbortAllAnimations(int container_mask) {
+  aura::Window::Windows containers;
+  GetContainers(container_mask, &containers);
+
+  for (aura::Window::Windows::const_iterator it = containers.begin();
+       it != containers.end(); ++it) {
+    (*it)->layer()->GetAnimator()->AbortAllAnimations();
+  }
+}
+
 bool SessionStateAnimatorImpl::IsWallpaperHidden() const {
   return !GetWallpaper()->IsVisible();
 }
diff --git a/ash/wm/session_state_animator_impl.h b/ash/wm/session_state_animator_impl.h
index fb5eb3c..1c21c99 100644
--- a/ash/wm/session_state_animator_impl.h
+++ b/ash/wm/session_state_animator_impl.h
@@ -63,6 +63,7 @@
                                   base::OnceClosure callback) override;
   AnimationSequence* BeginAnimationSequence(
       AnimationCallback callback) override;
+  void AbortAllAnimations(int container_mask) override;
   bool IsWallpaperHidden() const override;
   void ShowWallpaper() override;
   void HideWallpaper() override;
diff --git a/ash/wm/test_session_state_animator.cc b/ash/wm/test_session_state_animator.cc
index 722d9c9..9c6a552 100644
--- a/ash/wm/test_session_state_animator.cc
+++ b/ash/wm/test_session_state_animator.cc
@@ -248,7 +248,7 @@
   is_wallpaper_hidden_ = true;
 }
 
-void TestSessionStateAnimator::AbortAnimations(int container_mask) {
+void TestSessionStateAnimator::AbortAllAnimations(int container_mask) {
   for (size_t i = 0; i < std::size(kAllContainers); ++i) {
     if (container_mask & kAllContainers[i])
       AbortAnimation(kAllContainers[i]);
diff --git a/ash/wm/test_session_state_animator.h b/ash/wm/test_session_state_animator.h
index 406ced0..605ab96 100644
--- a/ash/wm/test_session_state_animator.h
+++ b/ash/wm/test_session_state_animator.h
@@ -75,12 +75,11 @@
                                   base::OnceClosure callback) override;
   AnimationSequence* BeginAnimationSequence(
       AnimationCallback callback) override;
+  void AbortAllAnimations(int container_mask) override;
   bool IsWallpaperHidden() const override;
   void ShowWallpaper() override;
   void HideWallpaper() override;
 
-  void AbortAnimations(int container_mask);
-
  private:
   class AnimationSequence;
   friend class AnimationSequence;
diff --git a/base/allocator/allocator.gni b/base/allocator/allocator.gni
index c3c62f8..2f879ed7 100644
--- a/base/allocator/allocator.gni
+++ b/base/allocator/allocator.gni
@@ -81,7 +81,8 @@
          "The allocator shim doesn't work for the component build on Windows.")
 }
 
-_is_brp_supported = (is_win || is_android) && use_allocator == "partition"
+_is_brp_supported = (is_win || is_android || is_linux || is_mac ||
+                     is_chromeos) && use_allocator == "partition"
 
 declare_args() {
   # Set use_backup_ref_ptr true to use BackupRefPtr (BRP) as the implementation
diff --git a/base/allocator/partition_allocator/partition_alloc.cc b/base/allocator/partition_allocator/partition_alloc.cc
index 671ae93..69a3c75 100644
--- a/base/allocator/partition_allocator/partition_alloc.cc
+++ b/base/allocator/partition_allocator/partition_alloc.cc
@@ -70,6 +70,29 @@
       internal::MaxSystemPagesPerRegularSlotSpan() <= 16,
       "System pages per slot span must be no greater than 16.");
 
+#if BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
+  STATIC_ASSERT_OR_PA_CHECK(
+      internal::GetPartitionRefCountIndexMultiplierShift() <
+          std::numeric_limits<size_t>::max() / 2,
+      "Calculation in GetPartitionRefCountIndexMultiplierShift() must not "
+      "underflow.");
+  // Check that the GetPartitionRefCountIndexMultiplierShift() calculation is
+  // correct.
+  STATIC_ASSERT_OR_PA_CHECK(
+      (1 << internal::GetPartitionRefCountIndexMultiplierShift()) ==
+          (internal::SystemPageSize() /
+           (sizeof(internal::PartitionRefCount) *
+            (internal::kSuperPageSize / internal::SystemPageSize()))),
+      "Bitshift must match the intended multiplication.");
+  STATIC_ASSERT_OR_PA_CHECK(
+      ((sizeof(internal::PartitionRefCount) *
+        (internal::kSuperPageSize / internal::SystemPageSize()))
+       << internal::GetPartitionRefCountIndexMultiplierShift()) <=
+          internal::SystemPageSize(),
+      "PartitionRefCount Bitmap size must be smaller than or equal to "
+      "<= SystemPageSize().");
+#endif  // BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
+
   PA_DCHECK(on_out_of_memory);
   internal::g_oom_handling_function = on_out_of_memory;
 }
diff --git a/base/allocator/partition_allocator/partition_ref_count.h b/base/allocator/partition_allocator/partition_ref_count.h
index 9126d9dcd..b950bf5 100644
--- a/base/allocator/partition_allocator/partition_ref_count.h
+++ b/base/allocator/partition_allocator/partition_ref_count.h
@@ -319,15 +319,46 @@
 constexpr size_t kPartitionRefCountOffsetAdjustment = 0;
 constexpr size_t kPartitionPastAllocationAdjustment = 0;
 
-constexpr size_t kPartitionRefCountIndexMultiplier =
-    SystemPageSize() /
-    (sizeof(PartitionRefCount) * (kSuperPageSize / SystemPageSize()));
+#if BUILDFLAG(ENABLE_DANGLING_RAW_PTR_CHECKS)
 
-static_assert((sizeof(PartitionRefCount) * (kSuperPageSize / SystemPageSize()) *
-                   kPartitionRefCountIndexMultiplier <=
-               SystemPageSize()),
-              "PartitionRefCount Bitmap size must be smaller than or equal to "
-              "<= SystemPageSize().");
+#if defined(PA_REF_COUNT_CHECK_COOKIE) || \
+    defined(PA_REF_COUNT_STORE_REQUESTED_SIZE)
+static constexpr size_t kPartitionRefCountSizeShift = 4;
+#else   //  defined(PA_REF_COUNT_CHECK_COOKIE) ||
+        //  defined(PA_REF_COUNT_STORE_REQUESTED_SIZE)
+static constexpr size_t kPartitionRefCountSizeShift = 3;
+#endif  //  defined(PA_REF_COUNT_CHECK_COOKIE) ||
+        //  defined(PA_REF_COUNT_STORE_REQUESTED_SIZE)
+
+#else  // BUILDFLAG(ENABLE_DANGLING_RAW_PTR_CHECKS)
+
+#if defined(PA_REF_COUNT_CHECK_COOKIE) && \
+    defined(PA_REF_COUNT_STORE_REQUESTED_SIZE)
+static constexpr size_t kPartitionRefCountSizeShift = 4;
+#elif defined(PA_REF_COUNT_CHECK_COOKIE) || \
+    defined(PA_REF_COUNT_STORE_REQUESTED_SIZE)
+static constexpr size_t kPartitionRefCountSizeShift = 3;
+#else
+static constexpr size_t kPartitionRefCountSizeShift = 2;
+#endif
+
+#endif  // defined(PA_REF_COUNT_CHECK_COOKIE)
+static_assert((1 << kPartitionRefCountSizeShift) == sizeof(PartitionRefCount));
+
+// We need one PartitionRefCount for each system page in a super page. They take
+// `x = sizeof(PartitionRefCount) * (kSuperPageSize / SystemPageSize())` space.
+// They need to fit into a system page of metadata as sparsely as possible to
+// minimize cache line sharing, hence we calculate a multiplier as
+// `SystemPageSize() / x`.
+//
+// The multiplier is expressed as a bitshift to optimize the code generation.
+// SystemPageSize() isn't always a constrexpr, in which case the compiler
+// wouldn't know it's a power of two. The equivalence of these calculations is
+// checked in PartitionAllocGlobalInit().
+static PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR PA_ALWAYS_INLINE size_t
+GetPartitionRefCountIndexMultiplierShift() {
+  return SystemPageShift() * 2 - kSuperPageShift - kPartitionRefCountSizeShift;
+}
 
 PA_ALWAYS_INLINE PartitionRefCount* PartitionRefCountPointer(
     uintptr_t slot_start) {
@@ -351,8 +382,8 @@
     // No need to tag, as the metadata region isn't protected by MTE.
     PartitionRefCount* bitmap_base = reinterpret_cast<PartitionRefCount*>(
         (slot_start & kSuperPageBaseMask) + SystemPageSize() * 2);
-    size_t index = ((slot_start & kSuperPageOffsetMask) >> SystemPageShift()) *
-                   kPartitionRefCountIndexMultiplier;
+    size_t index = ((slot_start & kSuperPageOffsetMask) >> SystemPageShift())
+                   << GetPartitionRefCountIndexMultiplierShift();
 #if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
     PA_CHECK(sizeof(PartitionRefCount) * index <= SystemPageSize());
 #endif
diff --git a/base/feature_list.cc b/base/feature_list.cc
index fa17e9f..b9c8d05 100644
--- a/base/feature_list.cc
+++ b/base/feature_list.cc
@@ -8,7 +8,7 @@
 // time. Try not to raise this limit unless necessary. See
 // https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md
 #ifndef NACL_TC_REV
-#pragma clang max_tokens_here 556000
+#pragma clang max_tokens_here 600000
 #endif
 
 #include <string>
diff --git a/base/observer_list_unittest.cc b/base/observer_list_unittest.cc
index 21f931e..b320f667 100644
--- a/base/observer_list_unittest.cc
+++ b/base/observer_list_unittest.cc
@@ -10,7 +10,7 @@
 // impact on build time. Try not to raise this limit unless necessary. See
 // https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md
 #ifndef NACL_TC_REV
-#pragma clang max_tokens_here 510000
+#pragma clang max_tokens_here 550000
 #endif
 
 #include <memory>
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
index cee73d8..ed3a1d3 100644
--- a/base/threading/thread_restrictions.h
+++ b/base/threading/thread_restrictions.h
@@ -132,6 +132,7 @@
 namespace blink {
 class CategorizedWorkerPool;
 class DiskDataAllocator;
+class IdentifiabilityActiveSampler;
 class RTCVideoDecoderAdapter;
 class RTCVideoEncoder;
 class SourceStream;
@@ -562,6 +563,7 @@
   friend class ::ChromeNSSCryptoModuleDelegate;
   friend class base::internal::GetAppOutputScopedAllowBaseSyncPrimitives;
   friend class base::SimpleThread;
+  friend class blink::IdentifiabilityActiveSampler;
   friend class blink::SourceStream;
   friend class blink::WorkerThread;
   friend class blink::scheduler::WorkerThread;
diff --git a/base/values.cc b/base/values.cc
index 73f70c6..950291bc 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -8,7 +8,7 @@
 // build time. Try not to raise this limit unless absolutely necessary. See
 // https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md
 #ifndef NACL_TC_REV
-#pragma clang max_tokens_here 540000
+#pragma clang max_tokens_here 580000
 #endif
 
 #include <algorithm>
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index 0633538..606cd98 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-9.20220719.3.1
+9.20220720.1.1
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn
index f2255718..ce80267 100644
--- a/chrome/android/features/autofill_assistant/BUILD.gn
+++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -90,6 +90,7 @@
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFormActionTest.java",
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantGenericUiTest.java",
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantHeaderUiTest.java",
+    "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxEndToEndTest.java",
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java",
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInputActionIntegrationTest.java",
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInterruptIntegrationTest.java",
diff --git a/chrome/android/features/autofill_assistant/guided_browsing/javatests/src/org/chromium/chrome/browser/autofill_assistant/guided_browsing/AssistantQrCodeTest.java b/chrome/android/features/autofill_assistant/guided_browsing/javatests/src/org/chromium/chrome/browser/autofill_assistant/guided_browsing/AssistantQrCodeTest.java
index d47a142..ec04c456 100644
--- a/chrome/android/features/autofill_assistant/guided_browsing/javatests/src/org/chromium/chrome/browser/autofill_assistant/guided_browsing/AssistantQrCodeTest.java
+++ b/chrome/android/features/autofill_assistant/guided_browsing/javatests/src/org/chromium/chrome/browser/autofill_assistant/guided_browsing/AssistantQrCodeTest.java
@@ -7,15 +7,24 @@
 import static androidx.test.espresso.Espresso.onView;
 import static androidx.test.espresso.action.ViewActions.click;
 import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.intent.Intents.intended;
+import static androidx.test.espresso.intent.Intents.intending;
+import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction;
+import static androidx.test.espresso.intent.matcher.IntentMatchers.isInternal;
 import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
 import static androidx.test.espresso.matcher.ViewMatchers.withId;
 import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
+import static org.hamcrest.Matchers.not;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 
+import android.app.Activity;
+import android.app.Instrumentation.ActivityResult;
+import android.content.Intent;
 import android.support.test.InstrumentationRegistry;
 
+import androidx.test.espresso.intent.Intents;
 import androidx.test.filters.MediumTest;
 
 import org.junit.Before;
@@ -28,7 +37,7 @@
 
 import org.chromium.base.Log;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Manual;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
 import org.chromium.chrome.browser.customtabs.CustomTabsIntentTestUtils;
@@ -38,6 +47,7 @@
 import org.chromium.components.autofill_assistant.guided_browsing.qr_code.AssistantQrCodeController;
 import org.chromium.components.autofill_assistant.guided_browsing.qr_code.AssistantQrCodeDelegate;
 import org.chromium.components.autofill_assistant.guided_browsing.qr_code.camera_scan.AssistantQrCodeCameraScanModel;
+import org.chromium.components.autofill_assistant.guided_browsing.qr_code.image_picker.AssistantQrCodeImagePickerModel;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 /**
@@ -63,6 +73,50 @@
     @Mock
     public AssistantQrCodeDelegate mAssistantQrCodeDelegateMock;
 
+    /**
+     * Dummy Implementation of AssistantQrCodeDelegate that prints user interaction logs to
+     * STDOUT for manual testing.
+     */
+    class MockAssistantQrCodeDelegate implements AssistantQrCodeDelegate {
+        public static final String TAG = "MockAssistantQrCodeDelegate";
+
+        private Runnable mOnUserInteractionComplete;
+
+        /**
+         * Constructor for MockAssistantQrCodeDelegate.
+         *
+         * @param onUserInteractionComplete Run when any of the delegate function is called.
+         *         Used to notify the completion of user interaction.
+         */
+        public MockAssistantQrCodeDelegate(Runnable onUserInteractionComplete) {
+            mOnUserInteractionComplete = onUserInteractionComplete;
+        }
+
+        @Override
+        public void onScanResult(String value) {
+            Log.i(TAG, "Scan Result: " + value);
+            mOnUserInteractionComplete.run();
+        }
+
+        @Override
+        public void onScanCancelled() {
+            Log.i(TAG, "onScanCancelled");
+            mOnUserInteractionComplete.run();
+        }
+
+        @Override
+        public void onScanFailure() {
+            Log.i(TAG, "onScanFailure");
+            mOnUserInteractionComplete.run();
+        }
+
+        @Override
+        public void onCameraError() {
+            Log.i(TAG, "onCameraError");
+            mOnUserInteractionComplete.run();
+        }
+    }
+
     @Before
     public void setUp() {
         mCustomTabActivityTestRule.startCustomTabActivityWithIntent(
@@ -77,13 +131,13 @@
     @Test
     @MediumTest
     public void testCameraScanToolbar() {
-        // Trigger QR Code Scanning
+        // Trigger QR Code Scanning via Camera Preview
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             AssistantQrCodeCameraScanModel cameraScanModel = new AssistantQrCodeCameraScanModel();
             cameraScanModel.setDelegate(mAssistantQrCodeDelegateMock);
             cameraScanModel.setToolbarTitle("Scan QR Code");
 
-            AssistantQrCodeController.promptQrCodeScan(
+            AssistantQrCodeController.promptQrCodeCameraScan(
                     getActivity(), getActivity().getWindowAndroid(), cameraScanModel);
         });
 
@@ -95,48 +149,38 @@
         verify(mAssistantQrCodeDelegateMock).onScanCancelled();
     }
 
+    @Test
+    @MediumTest
+    public void testImagePickerCreatesActionPickIntent() {
+        // Initializes Intents and begins recording intents. Must be called prior to triggering
+        // any actions that send out intents which need to be verified or stubbed.
+        Intents.init();
+
+        // Stub all external intents. By default Espresso does not stub any Intent. Note that in
+        // this case, all external calls will be blocked.
+        intending(not(isInternal())).respondWith(new ActivityResult(Activity.RESULT_OK, null));
+
+        // Trigger QR Code Scanning via Image Picker
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            AssistantQrCodeImagePickerModel imagePickerModel =
+                    new AssistantQrCodeImagePickerModel();
+            imagePickerModel.setDelegate(mAssistantQrCodeDelegateMock);
+
+            AssistantQrCodeController.promptQrCodeImagePicker(
+                    getActivity(), getActivity().getWindowAndroid(), imagePickerModel);
+        });
+
+        // Verify that an ACTION_PICK intent is started.
+        intended(hasAction(Intent.ACTION_PICK));
+
+        // Clears Intents state.
+        Intents.release();
+    }
+
     /** Manual Test to prompt QR Code Camera Scan and wait for any user interaction. */
     @Test
-    @Manual
-    public void testpromptQrCodeScan() throws Exception {
-        /**
-         * Dummy Implementation of AssistantQrCodeDelegate that prints user interaction logs to
-         * STDOUT for manual testing.
-         */
-        class MockAssistantQrCodeDelegate implements AssistantQrCodeDelegate {
-            public static final String TAG = "MockAssistantQrCodeDelegate";
-
-            private Runnable mOnUserInteractionComplete;
-
-            /**
-             * Constructor for MockAssistantQrCodeDelegate.
-             *
-             * @param onUserInteractionComplete Run when any of the delegate function is called.
-             *         Used to notify the completion of user interaction.
-             */
-            public MockAssistantQrCodeDelegate(Runnable onUserInteractionComplete) {
-                mOnUserInteractionComplete = onUserInteractionComplete;
-            }
-
-            @Override
-            public void onScanResult(String value) {
-                Log.i(TAG, "Scan Result: " + value);
-                mOnUserInteractionComplete.run();
-            }
-
-            @Override
-            public void onScanCancelled() {
-                Log.i(TAG, "onScanCancelled");
-                mOnUserInteractionComplete.run();
-            }
-
-            @Override
-            public void onCameraError() {
-                Log.i(TAG, "onCameraError");
-                mOnUserInteractionComplete.run();
-            }
-        }
-
+    @DisabledTest(message = "Only for local testing. Not supposed in production")
+    public void testpromptQrCodeCameraScan() throws Exception {
         MockAssistantQrCodeDelegate delegate = new MockAssistantQrCodeDelegate(mRunnableMock);
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             AssistantQrCodeCameraScanModel cameraScanModel = new AssistantQrCodeCameraScanModel();
@@ -151,10 +195,35 @@
             cameraScanModel.setOpenSettingsButtonText("Open Settings");
             cameraScanModel.setOverlayTitle("Focus the QR Code inside the box");
 
-            AssistantQrCodeController.promptQrCodeScan(
+            AssistantQrCodeController.promptQrCodeCameraScan(
                     getActivity(), getActivity().getWindowAndroid(), cameraScanModel);
         });
 
         verify(mRunnableMock, timeout(/* millis= */ 60000)).run();
     }
+
+    /** Manual Test to prompt QR Code Image Picker and wait for any user interaction. */
+    @Test
+    @DisabledTest(message = "Only for local testing. Not supposed in production")
+    public void testpromptQrCodeImagePicker() throws Exception {
+        MockAssistantQrCodeDelegate delegate = new MockAssistantQrCodeDelegate(mRunnableMock);
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            AssistantQrCodeImagePickerModel imagePickerModel =
+                    new AssistantQrCodeImagePickerModel();
+            imagePickerModel.setDelegate(delegate);
+
+            // Set UI strings in model.
+            imagePickerModel.setToolbarTitle("Scan QR Code");
+            imagePickerModel.setPermissionText("Please provide permissions to access images");
+            imagePickerModel.setPermissionButtonText("Continue");
+            imagePickerModel.setOpenSettingsText(
+                    "Please enable media permissions in device settings");
+            imagePickerModel.setOpenSettingsButtonText("Open Settings");
+
+            AssistantQrCodeController.promptQrCodeImagePicker(
+                    getActivity(), getActivity().getWindowAndroid(), imagePickerModel);
+        });
+
+        verify(mRunnableMock, timeout(/* millis= */ 60000)).run();
+    }
 }
\ No newline at end of file
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantGenericUiTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantGenericUiTest.java
index e0e0aa7..466b10d4 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantGenericUiTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantGenericUiTest.java
@@ -11,6 +11,7 @@
 import static androidx.test.espresso.action.ViewActions.clearText;
 import static androidx.test.espresso.action.ViewActions.click;
 import static androidx.test.espresso.action.ViewActions.typeText;
+import static androidx.test.espresso.action.ViewActions.typeTextIntoFocusedView;
 import static androidx.test.espresso.assertion.PositionAssertions.isLeftAlignedWith;
 import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
 import static androidx.test.espresso.assertion.ViewAssertions.matches;
@@ -1693,7 +1694,8 @@
                                                         .setHint("Type here")
                                                         .setType(TextInputViewProto.InputTypeHint
                                                                          .NONE)
-                                                        .setModelIdentifier("text_value")))
+                                                        .setModelIdentifier("text_value")
+                                                        .setFocusAndShowKeyboard(true)))
                         .setInteractions(
                                 InteractionsProto.newBuilder().addAllInteractions(interactions))
                         .setModel(ModelProto.newBuilder().addAllValues(modelValues))
@@ -1717,7 +1719,10 @@
         startAutofillAssistant(mTestRule.getActivity(), testService);
 
         waitUntilViewMatchesCondition(withContentDescription("Type here"), isCompletelyDisplayed());
-        onView(withContentDescription("Type here")).perform(typeText("test 1"));
+        // Verify that the text input view is focused.
+        // Ideally, we should also check for keyboard being open but Espresso does not show keyboard
+        // on focus or click.
+        onView(withContentDescription("Type here")).perform(typeTextIntoFocusedView("test 1"));
         waitUntilViewMatchesCondition(withText("test 1"), isDisplayed());
         onView(withContentDescription("Type here")).perform(clearText());
         onView(withContentDescription("Type here")).perform(typeText("test 2"));
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxEndToEndTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxEndToEndTest.java
new file mode 100644
index 0000000..e7d0c144
--- /dev/null
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxEndToEndTest.java
@@ -0,0 +1,163 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.autofill_assistant;
+
+import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.startAutofillAssistant;
+import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.waitUntilViewMatchesCondition;
+
+import android.view.View;
+
+import androidx.test.filters.MediumTest;
+
+import org.hamcrest.Matcher;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.chrome.browser.autofill_assistant.proto.ActionProto;
+import org.chromium.chrome.browser.autofill_assistant.proto.BitmapDrawableProto;
+import org.chromium.chrome.browser.autofill_assistant.proto.ClientDimensionProto;
+import org.chromium.chrome.browser.autofill_assistant.proto.ConfigBasedUrlProto;
+import org.chromium.chrome.browser.autofill_assistant.proto.DrawableProto;
+import org.chromium.chrome.browser.autofill_assistant.proto.InfoBoxProto;
+import org.chromium.chrome.browser.autofill_assistant.proto.ShowInfoBoxProto;
+import org.chromium.chrome.browser.autofill_assistant.proto.SupportedScriptProto;
+import org.chromium.chrome.browser.autofill_assistant.proto.SupportedScriptProto.PresentationProto;
+import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
+import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.components.autofill_assistant.R;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+/** Tests autofill assistant's show info box feature. */
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@RunWith(ChromeJUnit4ClassRunner.class)
+public class AutofillAssistantInfoBoxEndToEndTest {
+    private static final String TEST_PAGE = "form_target_website.html";
+    private static final String IMAGE_URL =
+            "https://www.gstatic.com/images/branding/product/2x/googleg_48dp.png";
+    private static final ClientDimensionProto DIMENSION =
+            ClientDimensionProto.newBuilder().setDp(150).build();
+    private static final ConfigBasedUrlProto MDPI_CONFIG =
+            ConfigBasedUrlProto.newBuilder().putUrl("mdpi", IMAGE_URL).build();
+
+    private static final ConfigBasedUrlProto DARK_MDPI_CONFIG =
+            ConfigBasedUrlProto.newBuilder().putUrl("night-mdpi", IMAGE_URL).build();
+
+    private static DrawableProto drawable(ConfigBasedUrlProto config) {
+        BitmapDrawableProto.Builder bitmapBuilder = BitmapDrawableProto.newBuilder();
+        bitmapBuilder.setConfigBasedUrl(config);
+        bitmapBuilder.setHeight(DIMENSION);
+        bitmapBuilder.setWidth(DIMENSION);
+        return DrawableProto.newBuilder().setBitmap(bitmapBuilder.build()).build();
+    }
+
+    private static ShowInfoBoxProto showInfoBox(DrawableProto drawable) {
+        return ShowInfoBoxProto.newBuilder()
+                .setInfoBox(InfoBoxProto.newBuilder().setDrawable(drawable))
+                .build();
+    }
+
+    private static ShowInfoBoxProto showInfoBox(String explanation) {
+        return ShowInfoBoxProto.newBuilder()
+                .setInfoBox(InfoBoxProto.newBuilder().setExplanation(explanation))
+                .build();
+    }
+
+    private static ShowInfoBoxProto showInfoBox(String explanation, DrawableProto drawable) {
+        return ShowInfoBoxProto.newBuilder()
+                .setInfoBox(
+                        InfoBoxProto.newBuilder().setExplanation(explanation).setDrawable(drawable))
+                .build();
+    }
+
+    private static ActionProto actionProto(ShowInfoBoxProto showInfoBox) {
+        return ActionProto.newBuilder().setShowInfoBox(showInfoBox).build();
+    }
+
+    private static AutofillAssistantTestScript testScript(ArrayList<ActionProto> list) {
+        return new AutofillAssistantTestScript(
+                SupportedScriptProto.newBuilder()
+                        .setPath(TEST_PAGE)
+                        .setPresentation(PresentationProto.newBuilder().setAutostart(true))
+                        .build(),
+                list);
+    }
+
+    private final CustomTabActivityTestRule mTestRule = new CustomTabActivityTestRule();
+
+    @Rule
+    public final TestRule mRulesChain = RuleChain.outerRule(mTestRule).around(
+            new AutofillAssistantCustomTabTestRule(mTestRule, TEST_PAGE));
+
+    private void runAutofillAssistant(AutofillAssistantTestScript script) {
+        AutofillAssistantTestService testService =
+                new AutofillAssistantTestService(Collections.singletonList(script));
+        startAutofillAssistant(mTestRule.getActivity(), testService);
+    }
+
+    private Matcher<View> getImageView() {
+        return withId(R.id.info_box_image);
+    }
+
+    private Matcher<View> getTextView() {
+        return withId(R.id.info_box_explanation);
+    }
+
+    @Test
+    @MediumTest
+    public void showInfoBoxShown_onlyText() throws Exception {
+        ArrayList<ActionProto> list = new ArrayList<>();
+        list.add(actionProto(showInfoBox("explanation")));
+
+        runAutofillAssistant(testScript(list));
+
+        waitUntilViewMatchesCondition(withText("explanation"), isCompletelyDisplayed());
+    }
+
+    @Test
+    @MediumTest
+    public void showInfoBoxShown_textAndImage() throws Exception {
+        ArrayList<ActionProto> list = new ArrayList<>();
+        list.add(actionProto(showInfoBox("explanation", drawable(MDPI_CONFIG))));
+
+        runAutofillAssistant(testScript(list));
+
+        waitUntilViewMatchesCondition(withText("explanation"), isCompletelyDisplayed());
+        waitUntilViewMatchesCondition(getImageView(), isDisplayed());
+    }
+
+    @Test
+    @MediumTest
+    public void showInfoBoxShown_image() throws Exception {
+        ArrayList<ActionProto> list = new ArrayList<>();
+        list.add(actionProto(showInfoBox(drawable(MDPI_CONFIG))));
+
+        runAutofillAssistant(testScript(list));
+
+        waitUntilViewMatchesCondition(getImageView(), isDisplayed());
+    }
+
+    @Test
+    @MediumTest
+    public void showInfoBoxShown_fallbacks() throws Exception {
+        ArrayList<ActionProto> list = new ArrayList<>();
+        list.add(actionProto(showInfoBox(drawable(DARK_MDPI_CONFIG))));
+
+        runAutofillAssistant(testScript(list));
+
+        waitUntilViewMatchesCondition(getImageView(), isDisplayed());
+    }
+}
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java
index 74e8fb2c..9ee6062 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java
@@ -20,6 +20,7 @@
 import android.graphics.BitmapFactory;
 import android.graphics.Typeface;
 import android.support.test.InstrumentationRegistry;
+import android.widget.ImageView;
 import android.widget.TextView;
 
 import androidx.test.filters.MediumTest;
@@ -35,6 +36,7 @@
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.components.autofill_assistant.R;
+import org.chromium.components.autofill_assistant.generic_ui.AssistantDrawable;
 import org.chromium.components.autofill_assistant.infobox.AssistantInfoBox;
 import org.chromium.components.autofill_assistant.infobox.AssistantInfoBoxCoordinator;
 import org.chromium.components.autofill_assistant.infobox.AssistantInfoBoxModel;
@@ -44,6 +46,7 @@
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RunWith(ChromeJUnit4ClassRunner.class)
 public class AutofillAssistantInfoBoxUiTest {
+    private static final AssistantDrawable sAssistantDrawable = AssistantDrawable.createFromIcon(1);
     @Rule
     public CustomTabActivityTestRule mTestRule = new CustomTabActivityTestRule();
 
@@ -51,6 +54,10 @@
         return coordinator.getView().findViewById(R.id.info_box_explanation);
     }
 
+    private ImageView getImageView(AssistantInfoBoxCoordinator coordinator) {
+        return coordinator.getView().findViewById(R.id.info_box_image);
+    }
+
     private AssistantInfoBoxModel createModel() {
         return TestThreadUtils.runOnUiThreadBlockingNoException(AssistantInfoBoxModel::new);
     }
@@ -94,20 +101,35 @@
     /** Tests for an infobox with a message, but without an image. */
     @Test
     @MediumTest
+    public void testMessageNoImageLegacy() throws Exception {
+        testMessageNoImage(/*useLegacyImplementation=*/false);
+    }
+
+    /** Tests for an infobox with a message, but without an image. */
+    @Test
+    @MediumTest
     public void testMessageNoImage() throws Exception {
+        testMessageNoImage(/*useLegacyImplementation=*/true);
+    }
+
+    private void testMessageNoImage(boolean useLegacyImplementation) throws Exception {
         AssistantInfoBoxModel model = createModel();
         AssistantInfoBoxCoordinator coordinator = createCoordinator(model);
-        AssistantInfoBox infoBox = new AssistantInfoBox("", "Message");
+        AssistantInfoBox infoBox = new AssistantInfoBox(
+                null, "Message", /* useIntrinsicDimensions= */ useLegacyImplementation);
 
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantInfoBoxModel.INFO_BOX, infoBox));
         onView(is(coordinator.getView())).check(matches(isDisplayed()));
-        // Image should not be set.
+        // Image should not be set.org.chromium.components.autofill_assistant.generic_ui
         assertThat(getExplanationView(coordinator).getCompoundDrawables()[1], nullValue());
+        onView(is(getImageView(coordinator))).check(matches(not(isDisplayed())));
+
         onView(is(getExplanationView(coordinator))).check(matches(withText("Message")));
 
         // Test that info message supports typeface span.
-        AssistantInfoBox boldInfoBox = new AssistantInfoBox("", "<b>Message</b>");
+        AssistantInfoBox boldInfoBox = new AssistantInfoBox(
+                null, "<b>Message</b>", /* useIntrinsicDimensions= */ useLegacyImplementation);
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantInfoBoxModel.INFO_BOX, boldInfoBox));
         onView(is(getExplanationView(coordinator))).check(matches(withText("Message")));
@@ -118,10 +140,11 @@
     /** Tests for an infobox with message and image. */
     @Test
     @MediumTest
-    public void testImage() throws Exception {
+    public void testImageLegacy() throws Exception {
         AssistantInfoBoxModel model = createModel();
         AssistantInfoBoxCoordinator coordinator = createCoordinator(model);
-        AssistantInfoBox infoBox = new AssistantInfoBox("x", "Message");
+        AssistantInfoBox infoBox = new AssistantInfoBox(
+                sAssistantDrawable, "Message", /* useIntrinsicDimensions= */ true);
 
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantInfoBoxModel.INFO_BOX, infoBox));
@@ -131,19 +154,42 @@
         onView(is(getExplanationView(coordinator))).check(matches(withText("Message")));
     }
 
+    /** Tests for an infobox with message and image. */
+    @Test
+    @MediumTest
+    public void testImage() throws Exception {
+        AssistantInfoBoxModel model = createModel();
+        AssistantInfoBoxCoordinator coordinator = createCoordinator(model);
+        AssistantInfoBox infoBox = new AssistantInfoBox(
+                sAssistantDrawable, "Message", /* useIntrinsicDimensions= */ false);
+
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> model.set(AssistantInfoBoxModel.INFO_BOX, infoBox));
+        onView(is(getExplanationView(coordinator))).check(matches(isDisplayed()));
+        onView(is(getImageView(coordinator))).check(matches(isDisplayed()));
+        // Image should be set.
+        assertThat(getImageView(coordinator).getDrawable(), not(nullValue()));
+        onView(is(getExplanationView(coordinator))).check(matches(withText("Message")));
+    }
+
     @Test
     @MediumTest
     public void hideIfEmpty() throws Exception {
         AssistantInfoBoxModel model = createModel();
         AssistantInfoBoxCoordinator coordinator = createCoordinator(model);
 
-        TestThreadUtils.runOnUiThreadBlocking(()
-                                                      -> model.set(AssistantInfoBoxModel.INFO_BOX,
-                                                              new AssistantInfoBox("", "Message")));
+        TestThreadUtils.runOnUiThreadBlocking(
+                ()
+                        -> model.set(AssistantInfoBoxModel.INFO_BOX,
+                                new AssistantInfoBox(
+                                        null, "Message", /* useIntrinsicDimensions= */ false)));
         onView(is(coordinator.getView())).check(matches(isDisplayed()));
 
         TestThreadUtils.runOnUiThreadBlocking(
-                () -> model.set(AssistantInfoBoxModel.INFO_BOX, new AssistantInfoBox("", "")));
+                ()
+                        -> model.set(AssistantInfoBoxModel.INFO_BOX,
+                                new AssistantInfoBox(
+                                        null, "", /* useIntrinsicDimensions= */ false)));
         onView(is(coordinator.getView())).check(matches(not(isDisplayed())));
     }
 
@@ -152,7 +198,8 @@
     public void hideIfNull() throws Exception {
         AssistantInfoBoxModel model = createModel();
         AssistantInfoBoxCoordinator coordinator = createCoordinator(model);
-        AssistantInfoBox infoBox = new AssistantInfoBox("Message", "");
+        AssistantInfoBox infoBox =
+                new AssistantInfoBox(null, "Message", /* useIntrinsicDimensions= */ false);
 
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantInfoBoxModel.INFO_BOX, infoBox));
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
index 2437a877..29c83a52 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
@@ -64,9 +64,7 @@
 import java.util.Arrays;
 import java.util.List;
 
-/**
- * Instrumentation tests for autofill assistant UI.
- */
+/** Instrumentation tests for autofill assistant UI. */
 @RunWith(ChromeJUnit4ClassRunner.class)
 public class AutofillAssistantUiTest {
     private String mTestPage;
@@ -195,8 +193,9 @@
                                         descriptionLine3,
                                         /* priceAttribution = */ "",
                                         /* userApprovalRequired= */ false,
-                                        /* highlightTitle= */ false, /* highlightLine1= */
-                                        false, /* highlightLine2 = */ false,
+                                        /* highlightTitle= */ false,
+                                        /* highlightLine1= */ false,
+                                        /* highlightLine2 = */ false,
                                         /* highlightLine3 = */ false,
                                         AutofillAssistantDetailsUiTest.NO_PLACEHOLDERS))));
         onView(withId(R.id.details_title))
@@ -227,8 +226,8 @@
                 ()
                         -> assistantCoordinator.getModel().getInfoBoxModel().set(
                                 AssistantInfoBoxModel.INFO_BOX,
-                                new AssistantInfoBox(
-                                        /* imagePath = */ "", infoBoxExplanation)));
+                                new AssistantInfoBox(null, infoBoxExplanation,
+                                        /*useIntrinsicDimensions=*/false)));
         TextView infoBoxExplanationView =
                 bottomSheetContent.findViewById(R.id.info_box_explanation);
         onView(is(infoBoxExplanationView)).check(matches(withText(infoBoxExplanation)));
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn
index fc224420..2cb14fe 100644
--- a/chrome/android/features/tab_ui/BUILD.gn
+++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -94,6 +94,7 @@
     "java/src/org/chromium/chrome/browser/tasks/tab_management/ClosableTabGridView.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/CouponCardView.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageService.java",
+    "java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoViewModel.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageCardViewModel.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageService.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/LargeMessageCardView.java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageService.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageService.java
index 0f396dd..f2b89224 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageService.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageService.java
@@ -11,6 +11,7 @@
 import android.os.Build;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.supplier.Supplier;
@@ -27,6 +28,12 @@
  * TODO(crbug.com/1227656): Add review logic and integrate this class.
  */
 public class IncognitoReauthPromoMessageService extends MessageService {
+    /**
+     * TODO(crbug.com/1227656): Remove this when we support all the Android versions.
+     */
+    @VisibleForTesting
+    public static Boolean sIsPromoEnabledForTesting;
+
     private final int mMaxPromoMessageCount = 10;
     /**
      *  TODO(crbug.com/1148020): Currently every time entering the tab switcher,
@@ -35,10 +42,7 @@
      *  {@link TabSwitcherMediator#prepareOverview}.
      */
     private final int mPrepareMessageEnteringTabSwitcher;
-    /**
-     * This is NOT intended to be accessed by the outside world. This is made public for test
-     * purposes only.
-     */
+
     @VisibleForTesting
     public final int mMaximumPromoShowCountLimit;
 
@@ -82,27 +86,56 @@
         mSnackBarManager = snackbarManager;
         mPrepareMessageEnteringTabSwitcher = isTabToGtsAnimationEnabledSupplier.get() ? 2 : 1;
         mMaximumPromoShowCountLimit = mMaxPromoMessageCount * mPrepareMessageEnteringTabSwitcher;
-        preparePromoMessage();
     }
 
     @VisibleForTesting
-    int getPromoShowCount() {
-        return mSharedPreferencesManager.readInt(INCOGNITO_REAUTH_PROMO_SHOW_COUNT, 0);
+    void dismiss() {
+        sendInvalidNotification();
+        disableIncognitoReauthPromoMessage();
     }
 
-    @VisibleForTesting
-    void increasePromoShowCount() {
+    void increasePromoShowCountAndMayDisableIfCountExceeds() {
+        if (getPromoShowCount() > mMaximumPromoShowCountLimit) {
+            dismiss();
+            return;
+        }
+
         mSharedPreferencesManager.writeInt(
                 INCOGNITO_REAUTH_PROMO_SHOW_COUNT, getPromoShowCount() + 1);
     }
 
-    private void disableIncognitoReauthPromoMessage() {
-        mSharedPreferencesManager.writeBoolean(INCOGNITO_REAUTH_PROMO_CARD_ENABLED, false);
+    int getPromoShowCount() {
+        return mSharedPreferencesManager.readInt(INCOGNITO_REAUTH_PROMO_SHOW_COUNT, 0);
     }
 
-    private void dismiss() {
-        sendInvalidNotification();
-        disableIncognitoReauthPromoMessage();
+    /**
+     * Prepares a re-auth promo message notifying a new message is available.
+     *
+     * @return A boolean indicating if the promo message was successfully prepared or not.
+     */
+    @VisibleForTesting
+    boolean preparePromoMessage() {
+        if (!isIncognitoReauthPromoMessageEnabled(mProfile)) return false;
+
+        // We also need to ensure an "equality" check because, we only increase the count of the
+        // promo when we actually show it in the tab switcher. At the |mMaximumPromoShowCountLimit|
+        // time (the last time) we show the promo, we haven't yet dismissed the dialog.
+        // Now, if the user recreates the Chrome Activity instance, the count will be read as
+        // |mMaximumPromoShowCountLimit| at this point, so we should dismiss the promo.
+        if (getPromoShowCount() >= mMaximumPromoShowCountLimit) {
+            dismiss();
+            return false;
+        }
+
+        sendAvailabilityNotification(
+                new IncognitoReauthMessageData(this::review, (int messageType) -> dismiss()));
+        return true;
+    }
+
+    @Override
+    public void addObserver(MessageObserver observer) {
+        super.addObserver(observer);
+        preparePromoMessage();
     }
 
     /**
@@ -119,6 +152,9 @@
      * @return True, if the incognito re-auth promo message is enabled, false otherwise.
      */
     public boolean isIncognitoReauthPromoMessageEnabled(Profile profile) {
+        // To support lower android versions where we support running the render tests.
+        if (sIsPromoEnabledForTesting != null) return sIsPromoEnabledForTesting;
+
         // The Chrome level Incognito lock setting is already enabled, so no use to show a promo for
         // that.
         if (IncognitoReauthManager.isIncognitoReauthEnabled(profile)) return false;
@@ -136,22 +172,12 @@
         return mSharedPreferencesManager.readBoolean(INCOGNITO_REAUTH_PROMO_CARD_ENABLED, true);
     }
 
-    /**
-     * Prepares a re-auth promo message notifying a new message is available.
-     *
-     * @return A boolean indicating if the promo message was successfully prepared or not.
-     */
     @VisibleForTesting
-    boolean preparePromoMessage() {
-        if (!isIncognitoReauthPromoMessageEnabled(mProfile)) return false;
-        increasePromoShowCount();
-        if (getPromoShowCount() > mMaximumPromoShowCountLimit) {
-            disableIncognitoReauthPromoMessage();
-            return false;
-        }
+    public static void setIsPromoEnabledForTesting(@Nullable Boolean enabled) {
+        sIsPromoEnabledForTesting = enabled;
+    }
 
-        sendAvailabilityNotification(
-                new IncognitoReauthMessageData(this::review, (int messageType) -> dismiss()));
-        return true;
+    private void disableIncognitoReauthPromoMessage() {
+        mSharedPreferencesManager.writeBoolean(INCOGNITO_REAUTH_PROMO_CARD_ENABLED, false);
     }
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoViewModel.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoViewModel.java
new file mode 100644
index 0000000..b936ad9
--- /dev/null
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoViewModel.java
@@ -0,0 +1,40 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.tasks.tab_management;
+
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.CardProperties.CARD_TYPE;
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.CardProperties.ModelType.MESSAGE;
+
+import android.content.Context;
+
+import org.chromium.ui.modelutil.PropertyModel;
+
+/**
+ * A class to create the property model for the Incognito re-auth promo card.
+ */
+public class IncognitoReauthPromoViewModel {
+    /**
+     * Create a {@link PropertyModel} for incognito re-auth promo card.
+     *
+     * TODO(crbug.com/1227656): Build the property model to actually design the re-auth promo card.
+     *
+     * @param context The {@link Context} to use.
+     * @param uiDismissActionProvider The {@link MessageCardView.DismissActionProvider} to set.
+     * @param data The {@link IncognitoReauthPromoMessageService.IncognitoReauthMessageData} to use.
+     * @return A {@link PropertyModel} for the given {@code data}.
+     */
+    public static PropertyModel create(Context context,
+            MessageCardView.DismissActionProvider uiDismissActionProvider,
+            IncognitoReauthPromoMessageService.IncognitoReauthMessageData data) {
+        return new PropertyModel.Builder(MessageCardViewProperties.ALL_KEYS)
+                .with(MessageCardViewProperties.MESSAGE_TYPE,
+                        MessageService.MessageType.INCOGNITO_REAUTH_PROMO_MESSAGE)
+                .with(MessageCardViewProperties
+                                .MESSAGE_CARD_VISIBILITY_CONTROL_IN_REGULAR_AND_INCOGNITO_MODE,
+                        MessageCardViewProperties.MessageCardScope.INCOGNITO)
+                .with(CARD_TYPE, MESSAGE)
+                .build();
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageCardViewModel.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageCardViewModel.java
index 30cb599..79c418a 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageCardViewModel.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageCardViewModel.java
@@ -52,7 +52,9 @@
                 .with(MessageCardViewProperties.SHOULD_KEEP_AFTER_REVIEW, true)
                 .with(MessageCardViewProperties.IS_ICON_VISIBLE, false)
                 .with(MessageCardViewProperties.IS_INCOGNITO, false)
-                .with(MessageCardViewProperties.SHOULD_SHOW_IN_INCOGNITO, true)
+                .with(MessageCardViewProperties
+                                .MESSAGE_CARD_VISIBILITY_CONTROL_IN_REGULAR_AND_INCOGNITO_MODE,
+                        MessageCardViewProperties.MessageCardScope.BOTH)
                 .with(CARD_TYPE, MESSAGE)
                 .with(CARD_ALPHA, 1f)
                 .build();
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java
index e58923db..2d0cc8e2b 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.tasks.tab_management;
 
+import static org.chromium.chrome.browser.tasks.tab_management.MessageService.MessageType.INCOGNITO_REAUTH_PROMO_MESSAGE;
 import static org.chromium.chrome.browser.tasks.tab_management.MessageService.MessageType.IPH;
 import static org.chromium.chrome.browser.tasks.tab_management.MessageService.MessageType.PRICE_MESSAGE;
 import static org.chromium.chrome.browser.tasks.tab_management.MessageService.MessageType.TAB_SUGGESTION;
@@ -115,6 +116,11 @@
                 assert data instanceof PriceMessageService.PriceMessageData;
                 return PriceMessageCardViewModel.create(mContext, this::invalidateShownMessage,
                         (PriceMessageService.PriceMessageData) data);
+            case INCOGNITO_REAUTH_PROMO_MESSAGE:
+                assert data
+                        instanceof IncognitoReauthPromoMessageService.IncognitoReauthMessageData;
+                return IncognitoReauthPromoViewModel.create(mContext, this::invalidateShownMessage,
+                        (IncognitoReauthPromoMessageService.IncognitoReauthMessageData) data);
             default:
                 return new PropertyModel.Builder(MessageCardViewProperties.ALL_KEYS)
                         .with(MessageCardViewProperties.IS_INCOGNITO, false)
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewProperties.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewProperties.java
index d14ed27..23010a1 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewProperties.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewProperties.java
@@ -9,14 +9,34 @@
 
 import android.view.View.OnClickListener;
 
+import androidx.annotation.IntDef;
+
 import org.chromium.chrome.browser.tab.state.ShoppingPersistedTabData;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * List of properties used by TabGridSecondaryItem.
  */
 class MessageCardViewProperties {
+    /**
+     * An enum interface to specify where the message card can be shown.
+     */
+    @IntDef({MessageCardScope.REGULAR, MessageCardScope.INCOGNITO, MessageCardScope.BOTH})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface MessageCardScope {
+        // Message card would only be shown inside regular mode.
+        int REGULAR = 0;
+        // Message card would only be shown inside incognito mode.
+        int INCOGNITO = 1;
+        // Message card would be shown in both regular and incognito mode.
+        int BOTH = 2;
+    }
+
+    /** This corresponds to the {@link MessageService.MessageType}. */
     public static final PropertyModel.ReadableIntPropertyKey MESSAGE_TYPE =
             new PropertyModel.ReadableIntPropertyKey();
     // Identifier is the subtype of message. For example, the message with type PRICE_MESSAGE may
@@ -66,8 +86,11 @@
             new PropertyModel.WritableBooleanPropertyKey();
     public static final PropertyModel.WritableObjectPropertyKey<String> TITLE_TEXT =
             new PropertyModel.WritableObjectPropertyKey<>();
-    public static final PropertyModel.WritableBooleanPropertyKey SHOULD_SHOW_IN_INCOGNITO =
-            new PropertyModel.WritableBooleanPropertyKey();
+    /** By default, if nothing is specified, regular is assumed. */
+    public static final PropertyModel
+            .ReadableIntPropertyKey MESSAGE_CARD_VISIBILITY_CONTROL_IN_REGULAR_AND_INCOGNITO_MODE =
+            new PropertyModel.ReadableIntPropertyKey();
+
     // TODO(crbug.com/1148020): Change to a more general property CUSTOM_INFO_OBJECT
     public static final PropertyModel
             .WritableObjectPropertyKey<ShoppingPersistedTabData.PriceDrop> PRICE_DROP =
@@ -79,6 +102,6 @@
             SECONDARY_ACTION_BUTTON_CLICK_HANDLER, MESSAGE_SERVICE_ACTION_PROVIDER,
             MESSAGE_SERVICE_DISMISS_ACTION_PROVIDER, DISMISS_BUTTON_CONTENT_DESCRIPTION,
             SHOULD_KEEP_AFTER_REVIEW, IS_CLOSE_BUTTON_VISIBLE, IS_ICON_VISIBLE, ICON_WIDTH,
-            ICON_HEIGHT, CARD_TYPE, CARD_ALPHA, IS_INCOGNITO, TITLE_TEXT, SHOULD_SHOW_IN_INCOGNITO,
-            PRICE_DROP};
+            ICON_HEIGHT, CARD_TYPE, CARD_ALPHA, IS_INCOGNITO, TITLE_TEXT,
+            MESSAGE_CARD_VISIBILITY_CONTROL_IN_REGULAR_AND_INCOGNITO_MODE, PRICE_DROP};
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageService.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageService.java
index 490f42df..103afb1 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageService.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageService.java
@@ -21,14 +21,15 @@
  */
 public class MessageService {
     @IntDef({MessageType.TAB_SUGGESTION, MessageType.IPH, MessageType.PRICE_MESSAGE,
-            MessageType.ALL})
+            MessageType.INCOGNITO_REAUTH_PROMO_MESSAGE, MessageType.ALL})
     @Retention(RetentionPolicy.SOURCE)
     public @interface MessageType {
         int FOR_TESTING = 0;
         int TAB_SUGGESTION = 1;
         int IPH = 2;
         int PRICE_MESSAGE = 3;
-        int ALL = 4;
+        int INCOGNITO_REAUTH_PROMO_MESSAGE = 4;
+        int ALL = 5;
     }
 
     /**
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/PriceMessageCardViewModel.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/PriceMessageCardViewModel.java
index bbeb8d9..ea76d20 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/PriceMessageCardViewModel.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/PriceMessageCardViewModel.java
@@ -56,7 +56,9 @@
                 .with(MessageCardViewProperties.SHOULD_KEEP_AFTER_REVIEW, false)
                 .with(MessageCardViewProperties.IS_ICON_VISIBLE, isIconVisible)
                 .with(MessageCardViewProperties.IS_INCOGNITO, false)
-                .with(MessageCardViewProperties.SHOULD_SHOW_IN_INCOGNITO, false)
+                .with(MessageCardViewProperties
+                                .MESSAGE_CARD_VISIBILITY_CONTROL_IN_REGULAR_AND_INCOGNITO_MODE,
+                        MessageCardViewProperties.MessageCardScope.REGULAR)
                 .with(MessageCardViewProperties.TITLE_TEXT, titleText)
                 .with(MessageCardViewProperties.PRICE_DROP, data.getPriceDrop())
                 .with(MessageCardViewProperties.ICON_PROVIDER,
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
index 5955f92..e606c013 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -1826,7 +1826,8 @@
      *         org.chromium.ui.modelutil.MVCListAdapter.ListItem} does not need additional
      *         identifier.
      */
-    void removeSpecialItemFromModel(@UiType int uiType, int itemIdentifier) {
+    void removeSpecialItemFromModel(
+            @UiType int uiType, @MessageService.MessageType int itemIdentifier) {
         int index = TabModel.INVALID_TAB_INDEX;
         if (uiType == UiType.MESSAGE || uiType == UiType.LARGE_MESSAGE) {
             if (itemIdentifier == MessageService.MessageType.ALL) {
@@ -1845,7 +1846,8 @@
         mModel.removeAt(index);
     }
 
-    private boolean validateItemAt(int index, @UiType int uiType, int itemIdentifier) {
+    private boolean validateItemAt(
+            int index, @UiType int uiType, @MessageService.MessageType int itemIdentifier) {
         if (uiType == UiType.MESSAGE || uiType == UiType.LARGE_MESSAGE) {
             return mModel.get(index).type == uiType
                     && mModel.get(index).model.get(MESSAGE_TYPE) == itemIdentifier;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListModel.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListModel.java
index 3651552..a839d4c 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListModel.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListModel.java
@@ -50,6 +50,7 @@
             int OTHERS = 3;
         }
 
+        /** This corresponds to {@link CardProperties.ModelType}*/
         public static final PropertyModel.ReadableIntPropertyKey CARD_TYPE =
                 new PropertyModel.ReadableIntPropertyKey();
 
@@ -156,7 +157,7 @@
      * @param messageType The message type to match.
      * @return The index within the model.
      */
-    public int lastIndexForMessageItemFromType(int messageType) {
+    public int lastIndexForMessageItemFromType(@MessageService.MessageType int messageType) {
         for (int i = size() - 1; i >= 0; i--) {
             PropertyModel model = get(i).model;
             if (model.get(CARD_TYPE) == MESSAGE && model.get(MESSAGE_TYPE) == messageType) {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardViewModel.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardViewModel.java
index f63411ec..7f8337a 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardViewModel.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardViewModel.java
@@ -55,7 +55,9 @@
                         dismissButtonContextDescription)
                 .with(MessageCardViewProperties.IS_ICON_VISIBLE, true)
                 .with(MessageCardViewProperties.IS_INCOGNITO, false)
-                .with(MessageCardViewProperties.SHOULD_SHOW_IN_INCOGNITO, false)
+                .with(MessageCardViewProperties
+                                .MESSAGE_CARD_VISIBILITY_CONTROL_IN_REGULAR_AND_INCOGNITO_MODE,
+                        MessageCardViewProperties.MessageCardScope.REGULAR)
                 .with(CARD_TYPE, MESSAGE)
                 .with(CARD_ALPHA, 1f)
                 .build();
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 13f4e8c..a3107369 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
@@ -26,6 +26,7 @@
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthManager;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.DestroyObserver;
 import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher;
@@ -34,6 +35,7 @@
 import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerFactory;
 import org.chromium.chrome.browser.price_tracking.PriceTrackingFeatures;
 import org.chromium.chrome.browser.price_tracking.PriceTrackingUtilities;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.share.ShareDelegate;
 import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 import org.chromium.chrome.browser.tabmodel.TabList;
@@ -134,6 +136,7 @@
     private final ViewGroup mCoordinatorView;
     private final ViewGroup mRootView;
     private TabContentManager mTabContentManager;
+    private IncognitoReauthPromoMessageService mIncognitoReauthPromoMessageService;
 
     private final MenuOrKeyboardActionController
             .MenuOrKeyboardActionHandler mTabSwitcherMenuActionHandler =
@@ -290,7 +293,10 @@
 
             mMessageCardProviderCoordinator = new MessageCardProviderCoordinator(
                     activity, tabModelSelector::isIncognitoSelected, (identifier) -> {
-                        if (identifier == MessageService.MessageType.PRICE_MESSAGE) {
+                        if (identifier == MessageService.MessageType.PRICE_MESSAGE
+                                || identifier
+                                        == MessageService.MessageType
+                                                   .INCOGNITO_REAUTH_PROMO_MESSAGE) {
                             mTabListCoordinator.removeSpecialListItem(
                                     TabProperties.UiType.LARGE_MESSAGE, identifier);
                         } else {
@@ -320,24 +326,25 @@
                             MessageCardViewBinder::bind);
                 }
 
-                if (PriceTrackingFeatures.isPriceTrackingEnabled()) {
+                if (shouldRegisterLargeMessageItemType()) {
                     mTabListCoordinator.registerItemType(TabProperties.UiType.LARGE_MESSAGE,
                             new LayoutViewBuilder(R.layout.large_message_card_item),
                             LargeMessageCardViewBinder::bind);
+                }
 
-                    if (PriceTrackingFeatures.getPriceTrackingEnabled()) {
-                        mPriceAnnotationsPrefObserver = key -> {
-                            if (PriceTrackingUtilities.TRACK_PRICES_ON_TABS.equals(key)
-                                    && !mTabModelSelector.isIncognitoSelected()
-                                    && mTabModelSelector.isTabStateInitialized()) {
-                                resetWithTabList(mTabModelSelector.getTabModelFilterProvider()
-                                                         .getCurrentTabModelFilter(),
-                                        false, isShowingTabsInMRUOrder(mMode));
-                            }
-                        };
-                        SharedPreferencesManager.getInstance().addObserver(
-                                mPriceAnnotationsPrefObserver);
-                    }
+                if (PriceTrackingFeatures.isPriceTrackingEnabled()
+                        && PriceTrackingFeatures.getPriceTrackingEnabled()) {
+                    mPriceAnnotationsPrefObserver = key -> {
+                        if (PriceTrackingUtilities.TRACK_PRICES_ON_TABS.equals(key)
+                                && !mTabModelSelector.isIncognitoSelected()
+                                && mTabModelSelector.isTabStateInitialized()) {
+                            resetWithTabList(mTabModelSelector.getTabModelFilterProvider()
+                                                     .getCurrentTabModelFilter(),
+                                    false, isShowingTabsInMRUOrder(mMode));
+                        }
+                    };
+                    SharedPreferencesManager.getInstance().addObserver(
+                            mPriceAnnotationsPrefObserver);
                 }
             }
 
@@ -427,6 +434,17 @@
                             new IphMessageService(mTabGridIphDialogCoordinator);
                     mMessageCardProviderCoordinator.subscribeMessageService(iphMessageService);
                 }
+
+                if (IncognitoReauthManager.isIncognitoReauthFeatureAvailable()
+                        && mIncognitoReauthPromoMessageService == null) {
+                    mIncognitoReauthPromoMessageService = new IncognitoReauthPromoMessageService(
+                            MessageService.MessageType.INCOGNITO_REAUTH_PROMO_MESSAGE,
+                            Profile.getLastUsedRegularProfile(), mActivity,
+                            SharedPreferencesManager.getInstance(), mSnackbarManager,
+                            TabUiFeatureUtilities::isTabToGtsAnimationEnabled);
+                    mMessageCardProviderCoordinator.subscribeMessageService(
+                            mIncognitoReauthPromoMessageService);
+                }
             }
 
             mMultiThumbnailCardProvider.initWithNative();
@@ -631,6 +649,8 @@
     public void removeAllAppendedMessage() {
         mTabListCoordinator.removeSpecialListItem(
                 TabProperties.UiType.MESSAGE, MessageService.MessageType.ALL);
+        mTabListCoordinator.removeSpecialListItem(TabProperties.UiType.LARGE_MESSAGE,
+                MessageService.MessageType.INCOGNITO_REAUTH_PROMO_MESSAGE);
         sAppendedMessagesForTesting = false;
     }
 
@@ -640,13 +660,18 @@
         List<MessageCardProviderMediator.Message> messages =
                 mMessageCardProviderCoordinator.getMessageItems();
         for (int i = 0; i < messages.size(); i++) {
+            if (!shouldAppendMessage(messages.get(i).model)) continue;
             // The restore of PRICE_MESSAGE is handled in the restorePriceWelcomeMessage() below.
-            if (messages.get(i).type == MessageService.MessageType.PRICE_MESSAGE
-                    || shouldSkipMessageDueToIncognito(messages.get(i).model)) {
+            if (messages.get(i).type == MessageService.MessageType.PRICE_MESSAGE) {
                 continue;
+            } else if (messages.get(i).type
+                    == MessageService.MessageType.INCOGNITO_REAUTH_PROMO_MESSAGE) {
+                mTabListCoordinator.addSpecialListItemToEnd(
+                        TabProperties.UiType.LARGE_MESSAGE, messages.get(i).model);
+            } else {
+                mTabListCoordinator.addSpecialListItemToEnd(
+                        TabProperties.UiType.MESSAGE, messages.get(i).model);
             }
-            mTabListCoordinator.addSpecialListItemToEnd(
-                    TabProperties.UiType.MESSAGE, messages.get(i).model);
         }
         sAppendedMessagesForTesting = messages.size() > 0;
     }
@@ -689,10 +714,13 @@
         List<MessageCardProviderMediator.Message> messages =
                 mMessageCardProviderCoordinator.getMessageItems();
         for (int i = 0; i < messages.size(); i++) {
-            if (shouldSkipMessageDueToIncognito(messages.get(i).model)) continue;
+            if (!shouldAppendMessage(messages.get(i).model)) continue;
             if (messages.get(i).type == MessageService.MessageType.PRICE_MESSAGE) {
                 mTabListCoordinator.addSpecialListItem(
                         index, TabProperties.UiType.LARGE_MESSAGE, messages.get(i).model);
+            } else if (messages.get(i).type
+                    == MessageService.MessageType.INCOGNITO_REAUTH_PROMO_MESSAGE) {
+                mayAddIncognitoReauthPromoCard(messages.get(i).model);
             } else {
                 mTabListCoordinator.addSpecialListItem(
                         index, TabProperties.UiType.MESSAGE, messages.get(i).model);
@@ -707,7 +735,7 @@
 
         MessageCardProviderMediator.Message nextMessage =
                 mMessageCardProviderCoordinator.getNextMessageItemForType(messageType);
-        if (nextMessage == null || shouldSkipMessageDueToIncognito(nextMessage.model)) return;
+        if (nextMessage == null || !shouldAppendMessage(nextMessage.model)) return;
         if (messageType == MessageService.MessageType.PRICE_MESSAGE) {
             mTabListCoordinator.addSpecialListItem(
                     mTabListCoordinator.getPriceWelcomeMessageInsertionIndex(),
@@ -718,9 +746,28 @@
         }
     }
 
-    private boolean shouldSkipMessageDueToIncognito(PropertyModel messageModel) {
+    private void mayAddIncognitoReauthPromoCard(PropertyModel model) {
+        if (mIncognitoReauthPromoMessageService.isIncognitoReauthPromoMessageEnabled(
+                    Profile.getLastUsedRegularProfile())) {
+            mTabListCoordinator.addSpecialListItemToEnd(TabProperties.UiType.LARGE_MESSAGE, model);
+            mIncognitoReauthPromoMessageService.increasePromoShowCountAndMayDisableIfCountExceeds();
+        }
+    }
+
+    private boolean shouldAppendMessage(PropertyModel messageModel) {
+        Integer messageCardVisibilityControlValue = messageModel.get(
+                MessageCardViewProperties
+                        .MESSAGE_CARD_VISIBILITY_CONTROL_IN_REGULAR_AND_INCOGNITO_MODE);
+
+        @MessageCardViewProperties.MessageCardScope
+        int scope = (messageCardVisibilityControlValue != null)
+                ? messageCardVisibilityControlValue
+                : MessageCardViewProperties.MessageCardScope.REGULAR;
+
+        if (scope == MessageCardViewProperties.MessageCardScope.BOTH) return true;
         return mTabModelSelector.isIncognitoSelected()
-                && !messageModel.get(MessageCardViewProperties.SHOULD_SHOW_IN_INCOGNITO);
+                ? scope == MessageCardViewProperties.MessageCardScope.INCOGNITO
+                : scope == MessageCardViewProperties.MessageCardScope.REGULAR;
     }
 
     private View getTabGridDialogAnimationSourceView(int tabId) {
@@ -741,6 +788,11 @@
                         && !TabSwitcherCoordinator.isShowingTabsInMRUOrder(mMode));
     }
 
+    private boolean shouldRegisterLargeMessageItemType() {
+        return PriceTrackingFeatures.isPriceTrackingEnabled()
+                || IncognitoReauthManager.isIncognitoReauthFeatureAvailable();
+    }
+
     @Override
     public void softCleanup() {
         mTabListCoordinator.softCleanup();
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIncognitoReauthPromoTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIncognitoReauthPromoTest.java
new file mode 100644
index 0000000..2eddb16
--- /dev/null
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIncognitoReauthPromoTest.java
@@ -0,0 +1,122 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.tasks.tab_management;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import static org.chromium.base.test.util.Batch.PER_CLASS;
+import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE;
+import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.createTabs;
+import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.enterTabSwitcher;
+import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.switchTabModel;
+
+import androidx.test.filters.MediumTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.util.Batch;
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.CriteriaHelper;
+import org.chromium.base.test.util.Restriction;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
+import org.chromium.chrome.browser.compositor.layouts.Layout;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthManager;
+import org.chromium.chrome.features.start_surface.TabSwitcherAndStartSurfaceLayout;
+import org.chromium.chrome.tab_ui.R;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
+import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.ui.test.util.UiRestriction;
+
+/**
+ * Instrumentation tests for the incognito re-auth promo component.
+ *
+ * TODO(crbug.com/1227656): Remove the restriction on only phone type and make it available for
+ * tablets. Also, remove the restriction on running this suite only for high end phones when
+ * GTS is available for them.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE)
+@Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
+@Features.EnableFeatures({ChromeFeatureList.INCOGNITO_REAUTHENTICATION_FOR_ANDROID,
+        ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID})
+@Batch(PER_CLASS)
+public class TabGridIncognitoReauthPromoTest {
+    @Rule
+    public final ChromeTabbedActivityTestRule mActivityTestRule =
+            new ChromeTabbedActivityTestRule();
+
+    @Before
+    public void setUp() {
+        IncognitoReauthManager.setIsIncognitoReauthFeatureAvailableForTesting(true);
+        IncognitoReauthPromoMessageService.setIsPromoEnabledForTesting(true);
+        mActivityTestRule.startMainActivityOnBlankPage();
+
+        Layout layout = mActivityTestRule.getActivity().getLayoutManager().getOverviewLayout();
+        assertTrue(layout instanceof TabSwitcherAndStartSurfaceLayout);
+        CriteriaHelper.pollUiThread(
+                mActivityTestRule.getActivity().getTabModelSelector()::isTabStateInitialized);
+    }
+
+    @After
+    public void tearDown() {
+        IncognitoReauthManager.setIsIncognitoReauthFeatureAvailableForTesting(false);
+        IncognitoReauthPromoMessageService.setIsPromoEnabledForTesting(false);
+    }
+
+    @Test
+    @MediumTest
+    public void testIncognitoReauthPromoShown() {
+        final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+
+        createTabs(cta, true, 1);
+        enterTabSwitcher(cta);
+
+        assertTrue(cta.getTabModelSelector().getCurrentModel().isIncognito());
+        CriteriaHelper.pollUiThread(TabSwitcherCoordinator::hasAppendedMessagesForTesting);
+        onView(withId(R.id.large_message_card_item)).check(matches(isDisplayed()));
+    }
+
+    @Test
+    @MediumTest
+    public void testIncognitoPromoNotShownInRegularMode() {
+        final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+
+        createTabs(cta, false, 1);
+        enterTabSwitcher(cta);
+
+        onView(withId(R.id.large_message_card_item)).check(doesNotExist());
+    }
+
+    @Test
+    @MediumTest
+    public void testIncognitoPromoNotShownInRegularMode_WhenTogglingFromIncognito() {
+        final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        createTabs(cta, false, 1);
+        createTabs(cta, true, 1);
+        enterTabSwitcher(cta);
+
+        assertTrue(cta.getTabModelSelector().getCurrentModel().isIncognito());
+        CriteriaHelper.pollUiThread(TabSwitcherCoordinator::hasAppendedMessagesForTesting);
+        onView(withId(R.id.large_message_card_item)).check(matches(isDisplayed()));
+
+        switchTabModel(cta, false);
+        assertFalse(cta.getTabModelSelector().getCurrentModel().isIncognito());
+        onView(withId(R.id.large_message_card_item)).check(doesNotExist());
+    }
+}
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageServiceUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageServiceUnitTest.java
index cb184a2..0726d1b 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageServiceUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageServiceUnitTest.java
@@ -7,6 +7,11 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
@@ -62,6 +67,8 @@
     private UserPrefs.Natives mUserPrefsJniMock;
     @Mock
     private PrefService mPrefServiceMock;
+    @Mock
+    private MessageService.MessageObserver mMessageObserverMock;
 
     private SharedPreferencesManager mSharedPreferenceManager;
     private IncognitoReauthPromoMessageService mIncognitoReauthPromoMessageService;
@@ -74,6 +81,7 @@
         when(mUserPrefsJniMock.get(mProfileMock)).thenReturn(mPrefServiceMock);
         IncognitoReauthManager.setIsIncognitoReauthFeatureAvailableForTesting(false);
         IncognitoReauthSettingUtils.setIsDeviceScreenLockEnabledForTesting(false);
+        IncognitoReauthPromoMessageService.setIsPromoEnabledForTesting(null);
         mSharedPreferenceManager = SharedPreferencesManager.getInstance();
     }
 
@@ -90,6 +98,23 @@
 
     @Test
     @SmallTest
+    public void testDismissMessage_SendsInvalidNotification_AndDisablesPromo() {
+        createIncognitoReauthPromoMessageService();
+        mIncognitoReauthPromoMessageService.addObserver(mMessageObserverMock);
+        assertTrue("Observer was not added.",
+                mIncognitoReauthPromoMessageService.getObserversForTesting().hasObserver(
+                        mMessageObserverMock));
+        doNothing().when(mMessageObserverMock).messageInvalidate(MessageType.FOR_TESTING);
+
+        mIncognitoReauthPromoMessageService.dismiss();
+
+        verify(mMessageObserverMock, times(1)).messageInvalidate(MessageType.FOR_TESTING);
+        assertFalse(
+                mSharedPreferenceManager.readBoolean(INCOGNITO_REAUTH_PROMO_CARD_ENABLED, true));
+    }
+
+    @Test
+    @SmallTest
     public void testPreparePromoMessage_Fails_WhenReauthIsAlreadyEnabled() {
         createIncognitoReauthPromoMessageService();
         when(mPrefServiceMock.getBoolean(Pref.INCOGNITO_REAUTHENTICATION_FOR_ANDROID))
@@ -133,7 +158,7 @@
 
     @Test
     @SmallTest
-    public void testPreparePromoMessage_Succeeds_And_IncreasesCount() {
+    public void testPreparePromoMessage_Succeeds() {
         createIncognitoReauthPromoMessageService();
         when(mPrefServiceMock.getBoolean(Pref.INCOGNITO_REAUTHENTICATION_FOR_ANDROID))
                 .thenReturn(false);
@@ -143,7 +168,26 @@
         IncognitoReauthSettingUtils.setIsDeviceScreenLockEnabledForTesting(/*value=*/true);
         assertTrue("Promo message should have been prepared.",
                 mIncognitoReauthPromoMessageService.preparePromoMessage());
-        assertEquals(1, mSharedPreferenceManager.readInt(INCOGNITO_REAUTH_PROMO_SHOW_COUNT, 0));
+    }
+
+    @Test
+    @SmallTest
+    public void testAddObserver_Succeeds_AndNotifiesObserverOfMessagePrepared() {
+        createIncognitoReauthPromoMessageService();
+        when(mPrefServiceMock.getBoolean(Pref.INCOGNITO_REAUTHENTICATION_FOR_ANDROID))
+                .thenReturn(false);
+
+        IncognitoReauthManager.setIsIncognitoReauthFeatureAvailableForTesting(
+                /*isAvailable=*/true);
+        IncognitoReauthSettingUtils.setIsDeviceScreenLockEnabledForTesting(/*value=*/true);
+        doNothing().when(mMessageObserverMock).messageReady(eq(MessageType.FOR_TESTING), any());
+
+        mIncognitoReauthPromoMessageService.addObserver(mMessageObserverMock);
+
+        assertTrue("Observer was not added.",
+                mIncognitoReauthPromoMessageService.getObserversForTesting().hasObserver(
+                        mMessageObserverMock));
+        verify(mMessageObserverMock, times(1)).messageReady(eq(MessageType.FOR_TESTING), any());
     }
 
     @Test
@@ -152,13 +196,35 @@
         createIncognitoReauthPromoMessageService();
 
         int currentCount = mIncognitoReauthPromoMessageService.getPromoShowCount();
-        mIncognitoReauthPromoMessageService.increasePromoShowCount();
+        mIncognitoReauthPromoMessageService.increasePromoShowCountAndMayDisableIfCountExceeds();
         int newCount = mIncognitoReauthPromoMessageService.getPromoShowCount();
         assertEquals("The count should be increased by only 1.", currentCount + 1, newCount);
     }
 
     @Test
     @SmallTest
+    public void testIncreasePromoCount_DisablesCardIfCountExceeds() {
+        createIncognitoReauthPromoMessageService();
+        mSharedPreferenceManager.writeInt(INCOGNITO_REAUTH_PROMO_SHOW_COUNT,
+                mIncognitoReauthPromoMessageService.mMaximumPromoShowCountLimit + 1);
+        mIncognitoReauthPromoMessageService.increasePromoShowCountAndMayDisableIfCountExceeds();
+        assertFalse(
+                mSharedPreferenceManager.readBoolean(INCOGNITO_REAUTH_PROMO_CARD_ENABLED, true));
+    }
+
+    @Test
+    @SmallTest
+    public void testIncreasePromoCount_DoesNotDisablesCardIfCountBelowThreshold() {
+        createIncognitoReauthPromoMessageService();
+        int currentCount = mIncognitoReauthPromoMessageService.getPromoShowCount();
+        mIncognitoReauthPromoMessageService.increasePromoShowCountAndMayDisableIfCountExceeds();
+        int newCount = mIncognitoReauthPromoMessageService.getPromoShowCount();
+        assertEquals("The count should be increased by 1.", currentCount + 1, newCount);
+        assertTrue(mSharedPreferenceManager.readBoolean(INCOGNITO_REAUTH_PROMO_CARD_ENABLED, true));
+    }
+
+    @Test
+    @SmallTest
     public void testPreparePromoMessage_Fails_AfterMaxShowCountReached_TabToGTSEnabled() {
         mIsTabToGTSAnimationEnabled = true;
         createIncognitoReauthPromoMessageService();
@@ -179,8 +245,8 @@
             assertTrue("Promo message should have been prepared as the current count: " + i
                             + ", is less than the max count: " + maxShowCount,
                     mIncognitoReauthPromoMessageService.preparePromoMessage());
+            mIncognitoReauthPromoMessageService.increasePromoShowCountAndMayDisableIfCountExceeds();
         }
-
         assertFalse(
                 "We shouldn't prepare the message since the max limit was reached in the previous step.",
                 mIncognitoReauthPromoMessageService.preparePromoMessage());
@@ -209,10 +275,30 @@
             assertTrue("Promo message should have been prepared as the current count: " + i
                             + ", is less than the max count: " + maxShowCount,
                     mIncognitoReauthPromoMessageService.preparePromoMessage());
+            mIncognitoReauthPromoMessageService.increasePromoShowCountAndMayDisableIfCountExceeds();
         }
 
         assertFalse(
                 "We shouldn't prepare the message since the max limit was reached in the previous step.",
                 mIncognitoReauthPromoMessageService.preparePromoMessage());
     }
+
+    @Test
+    @SmallTest
+    public void testPreparePromoMessage_DismissesCard_WhenShowCountExceeds() {
+        createIncognitoReauthPromoMessageService();
+        // Exceed the max count.
+        mSharedPreferenceManager.writeInt(INCOGNITO_REAUTH_PROMO_SHOW_COUNT,
+                mIncognitoReauthPromoMessageService.mMaximumPromoShowCountLimit + 1);
+        // Ensure that promo can be shown.
+        IncognitoReauthPromoMessageService.setIsPromoEnabledForTesting(true);
+
+        doNothing().when(mMessageObserverMock).messageInvalidate(MessageType.FOR_TESTING);
+        // This calls the prepare message internally.
+        mIncognitoReauthPromoMessageService.addObserver(mMessageObserverMock);
+
+        verify(mMessageObserverMock, times(1)).messageInvalidate(MessageType.FOR_TESTING);
+        assertFalse(
+                mSharedPreferenceManager.readBoolean(INCOGNITO_REAUTH_PROMO_CARD_ENABLED, true));
+    }
 }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java
index 7524faa..cf93ed2c 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java
@@ -56,6 +56,10 @@
     @Mock
     private IphMessageService.IphMessageData mIphMessageData;
 
+    @Mock
+    private IncognitoReauthPromoMessageService
+            .IncognitoReauthMessageData mIncognitoReauthMessageData;
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -88,6 +92,9 @@
                 when(mIphMessageData.getReviewActionProvider()).thenReturn(() -> {});
                 mMediator.messageReady(type, mIphMessageData);
                 break;
+            case MessageService.MessageType.INCOGNITO_REAUTH_PROMO_MESSAGE:
+                mMediator.messageReady(type, mIncognitoReauthMessageData);
+                break;
             default:
                 mMediator.messageReady(type, new MessageService.MessageData() {});
         }
@@ -342,6 +349,19 @@
     }
 
     @Test
+    public void buildModel_ForIncognitoReauthPromoMessage() {
+        enqueueMessageItem(MessageService.MessageType.INCOGNITO_REAUTH_PROMO_MESSAGE, -1);
+
+        PropertyModel model =
+                mMediator.getReadyMessageItemsForTesting()
+                        .get(MessageService.MessageType.INCOGNITO_REAUTH_PROMO_MESSAGE)
+                        .get(0)
+                        .model;
+        Assert.assertEquals(MessageService.MessageType.INCOGNITO_REAUTH_PROMO_MESSAGE,
+                model.get(MessageCardViewProperties.MESSAGE_TYPE));
+    }
+
+    @Test
     public void getMessageItemsTest_UpdateIncognito() {
         enqueueMessageItem(
                 MessageService.MessageType.TAB_SUGGESTION, TabSuggestion.TabSuggestionAction.CLOSE);
diff --git a/chrome/android/features/tab_ui/tab_management_java_sources.gni b/chrome/android/features/tab_ui/tab_management_java_sources.gni
index afb4906..c0747b83 100644
--- a/chrome/android/features/tab_ui/tab_management_java_sources.gni
+++ b/chrome/android/features/tab_ui/tab_management_java_sources.gni
@@ -28,6 +28,7 @@
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/RecyclerViewMatcherUtils.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridAccessibilityHelperTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java",
+  "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIncognitoReauthPromoTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/TrustedVaultClient.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/TrustedVaultClient.java
index ab6f15af..750dd70 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/TrustedVaultClient.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/TrustedVaultClient.java
@@ -68,6 +68,21 @@
         Promise<Boolean> getIsRecoverabilityDegraded(CoreAccountInfo accountInfo);
 
         /**
+         * Registers a new trusted recovery method that can be used to retrieve keys,
+         * usually for the purpose of resolving a recoverability-degraded case.
+         *
+         * @param accountInfo Account representing the user.
+         * @param publicKey Public key representing the recovery method.
+         * @param methodTypeHint Opaque value provided by the server (e.g. via Javascript).
+         * @return a promise which indicates completion.
+         */
+        // TODO(crbug.com/1341279): Switch to non-default method once all implementations are ready.
+        default Promise<Void> addTrustedRecoveryMethod(
+                CoreAccountInfo accountInfo, byte[] publicKey, int methodTypeHint) {
+            return Promise.rejected();
+        }
+
+        /**
          * Gets a PendingIntent that can be used to display a UI that allows the user to resolve a
          * degraded recoverability state, usually involving reauthentication.
          *
@@ -314,6 +329,26 @@
                 .then(responseCallback::accept, exception -> responseCallback.accept(false));
     }
 
+    /**
+     * Forwards calls to Backend.addTrustedRecoveryMethod() and upon completion invokes native
+     * method addTrustedRecoveryMethodCompleted().
+     */
+    @CalledByNative
+    private static void addTrustedRecoveryMethod(
+            int requestId, CoreAccountInfo accountInfo, byte[] publicKey, int methodTypeHint) {
+        Consumer<Void> responseCallback = unused -> {
+            if (get().mNativeTrustedVaultClientAndroid == 0) {
+                // Native already unregistered, no response needed.
+                return;
+            }
+            TrustedVaultClientJni.get().addTrustedRecoveryMethodCompleted(
+                    get().mNativeTrustedVaultClientAndroid, requestId);
+        };
+
+        get().mBackend.addTrustedRecoveryMethod(accountInfo, publicKey, methodTypeHint)
+                .then(responseCallback::accept, exception -> responseCallback.accept(null));
+    }
+
     @NativeMethods
     interface Natives {
         void fetchKeysCompleted(
@@ -322,6 +357,7 @@
                 long nativeTrustedVaultClientAndroid, int requestId, boolean succeeded);
         void getIsRecoverabilityDegradedCompleted(
                 long nativeTrustedVaultClientAndroid, int requestId, boolean isDegraded);
+        void addTrustedRecoveryMethodCompleted(long nativeTrustedVaultClientAndroid, int requestId);
         void notifyKeysChanged(long nativeTrustedVaultClientAndroid);
         void notifyRecoverabilityChanged(long nativeTrustedVaultClientAndroid);
         void recordKeyRetrievalTrigger(@TrustedVaultUserActionTriggerForUMA int trigger);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java
index 3af4b533..e3ea3d12 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java
@@ -150,6 +150,12 @@
         }
 
         @Override
+        public Promise<Void> addTrustedRecoveryMethod(
+                CoreAccountInfo accountInfo, byte[] publicKey, int methodTypeHint) {
+            return Promise.fulfilled(null);
+        }
+
+        @Override
         public Promise<PendingIntent> createRecoverabilityDegradedIntent(
                 CoreAccountInfo accountInfo) {
             Context context = InstrumentationRegistry.getContext();
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index de55608..870b29d 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -465,14 +465,14 @@
       <message name="IDS_HISTORY_OPEN_TABS_MENU_ITEM" desc="Label displayed in history sidebar button to display synced tabs from other devices.">
         Tabs from other devices
       </message>
-      <message name="IDS_HISTORY_SIGN_IN_BUTTON" desc="Label displayed on a button to let user sign in to Chrome to get synced tab history.">
-        Sign in to Chrome
+      <message name="IDS_HISTORY_TURN_ON_SYNC_BUTTON" desc="Label displayed on a button to let user turn on sync or sign in to Chrome to get synced tab history.">
+        Turn on sync
       </message>
-      <message name="IDS_HISTORY_SIGN_IN_PROMO" desc="Text of the sign-in promo. This will show up if a user is not logged in and has no synced tabs.">
+      <message name="IDS_HISTORY_TURN_ON_SYNC_PROMO" desc="Text of the turn on sync/sign-in promo. This will show up if a user is not logged in and has no synced tabs.">
         Continue from another device
       </message>
-      <message name="IDS_HISTORY_SIGN_IN_PROMO_DESC" desc="Description of the sign-in promo. Further tells users to sign in to Chrome to see synced tabs from other devices.">
-        To get your tabs from your other devices, sign in to Chrome.
+      <message name="IDS_HISTORY_TURN_ON_SYNC_PROMO_DESC" desc="Description of the turn on sync/sign-in promo. Further tells users to turn o sync/sign in to Chrome to see synced tabs from other devices.">
+        To get your tabs from your other devices, turn on sync
       </message>
 
       <!-- Generic terms -->
diff --git a/chrome/app/generated_resources_grd/IDS_HISTORY_TURN_ON_SYNC_BUTTON.png.sha1 b/chrome/app/generated_resources_grd/IDS_HISTORY_TURN_ON_SYNC_BUTTON.png.sha1
new file mode 100644
index 0000000..1f4594b
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_HISTORY_TURN_ON_SYNC_BUTTON.png.sha1
@@ -0,0 +1 @@
+d991808613c6952e5b498bc7711876324f62ab3c
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_HISTORY_TURN_ON_SYNC_PROMO.png.sha1 b/chrome/app/generated_resources_grd/IDS_HISTORY_TURN_ON_SYNC_PROMO.png.sha1
new file mode 100644
index 0000000..1f4594b
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_HISTORY_TURN_ON_SYNC_PROMO.png.sha1
@@ -0,0 +1 @@
+d991808613c6952e5b498bc7711876324f62ab3c
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_HISTORY_TURN_ON_SYNC_PROMO_DESC.png.sha1 b/chrome/app/generated_resources_grd/IDS_HISTORY_TURN_ON_SYNC_PROMO_DESC.png.sha1
new file mode 100644
index 0000000..1f4594b
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_HISTORY_TURN_ON_SYNC_PROMO_DESC.png.sha1
@@ -0,0 +1 @@
+d991808613c6952e5b498bc7711876324f62ab3c
\ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 2c2c808..8150ad50 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -526,9 +526,6 @@
   <message name="IDS_SETTINGS_REMOVE_COMPROMISED_PASSWORD_CONFIRMATION_DESCRIPTION" desc="Compromised password remove dialog conformation description">
     Removing this password will not delete your account on <ph name="DOMAIN">$1<ex>airbnb.com</ex></ph>. Change your password or delete your account on <ph name="DOMAIN_LINK">$2<ex>&lt;a href="https://airbnb.com" target="_blank"&gt;airbnb.com&lt;/a&gt;</ex></ph> to keep it safe from others.
   </message>
-  <message name="IDS_SETTINGS_COMPROMISED_EDIT_PASSWORD_SITE" desc="A label for the field, which displays the site for which the password was saved. The field is part of a dialog, which allows the user to edit the password.">
-    Site
-  </message>
   <message name="IDS_SETTINGS_COMPROMISED_EDIT_PASSWORD_APP" desc="A label for the field, which displays the app for which the password was saved. The field is part of a dialog, which allows the user to edit the password.">
     App
   </message>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_COMPROMISED_EDIT_PASSWORD_SITE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_COMPROMISED_EDIT_PASSWORD_SITE.png.sha1
deleted file mode 100644
index bf77dbb..0000000
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_COMPROMISED_EDIT_PASSWORD_SITE.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a71f11822ca8bd5b27d51b6c5d993b643056f9a1
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 8302d254..9fbe0572 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1433,6 +1433,8 @@
     "profiles/profile_io_data.h",
     "profiles/profile_key.cc",
     "profiles/profile_key.h",
+    "profiles/profile_keyed_service_factory.cc",
+    "profiles/profile_keyed_service_factory.h",
     "profiles/profile_manager.cc",
     "profiles/profile_manager.h",
     "profiles/profile_manager_observer.h",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 1ec8f8c..18845e76 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -8033,6 +8033,12 @@
      FEATURE_VALUE_TYPE(::features::kFocusFollowsCursor)},
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
+    {"password-strength-indicator",
+     flag_descriptions::kPasswordStrengthIndicatorName,
+     flag_descriptions::kPasswordStrengthIndicatorDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(
+         password_manager::features::kPasswordStrengthIndicator)},
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     {"partial-split", flag_descriptions::kPartialSplit,
      flag_descriptions::kPartialSplitDescription, kOsCrOS,
diff --git a/chrome/browser/apps/app_service/intent_util.cc b/chrome/browser/apps/app_service/intent_util.cc
index dfa9b39..a37d320 100644
--- a/chrome/browser/apps/app_service/intent_util.cc
+++ b/chrome/browser/apps/app_service/intent_util.cc
@@ -802,11 +802,11 @@
 }
 
 std::string CreateLaunchIntent(const std::string& package_name,
-                               const apps::mojom::IntentPtr& intent) {
+                               const apps::IntentPtr& intent) {
   // If |intent| has |ui_bypassed|, |url| or |data|, it is too complex to
   // convert to a string, so return the empty string.
-  if (intent->ui_bypassed != apps::mojom::OptionalBool::kUnknown ||
-      intent->url.has_value() || intent->data.has_value()) {
+  if (intent->ui_bypassed.has_value() || intent->url.has_value() ||
+      intent->data.has_value()) {
     return std::string();
   }
 
@@ -818,10 +818,8 @@
                             ConvertAppServiceToArcIntentAction(intent->action));
 
   // Convert categories.
-  if (intent->categories.has_value()) {
-    for (const auto& category : intent->categories.value()) {
-      ret += base::StringPrintf("%s=%s;", arc::kCategory, category.c_str());
-    }
+  for (const auto& category : intent->categories) {
+    ret += base::StringPrintf("%s=%s;", arc::kCategory, category.c_str());
   }
 
   // Set launch flags.
@@ -864,10 +862,8 @@
                               intent->start_type.value().c_str());
   }
 
-  if (intent->extras.has_value()) {
-    for (auto it : intent->extras.value()) {
-      ret += base::StringPrintf("%s=%s;", it.first.c_str(), it.second.c_str());
-    }
+  for (auto it : intent->extras) {
+    ret += base::StringPrintf("%s=%s;", it.first.c_str(), it.second.c_str());
   }
 
   ret += arc::kEndSuffix;
diff --git a/chrome/browser/apps/app_service/intent_util.h b/chrome/browser/apps/app_service/intent_util.h
index fa756ce..867b79c 100644
--- a/chrome/browser/apps/app_service/intent_util.h
+++ b/chrome/browser/apps/app_service/intent_util.h
@@ -160,12 +160,12 @@
 // nullptr if |arc_action| is an action which is not supported by App Service.
 const char* ConvertArcToAppServiceIntentAction(const std::string& arc_action);
 
-// Convert an apps::mojom::Intent struct to a string to call the LaunchIntent
+// Converts an apps::Intent struct to a string to call the LaunchIntent
 // interface from arc::mojom::AppInstance. If |intent| has |ui_bypassed|, |url|
 // or |data|, returns an empty string as these intents cannot be represented in
 // string form.
 std::string CreateLaunchIntent(const std::string& package_name,
-                               const apps::mojom::IntentPtr& intent);
+                               const apps::IntentPtr& intent);
 
 // Convert between App Service and ARC IntentFilters.
 arc::IntentFilter ConvertAppServiceToArcIntentFilter(
diff --git a/chrome/browser/apps/app_service/intent_util_unittest.cc b/chrome/browser/apps/app_service/intent_util_unittest.cc
index 07d00c1..33ced41 100644
--- a/chrome/browser/apps/app_service/intent_util_unittest.cc
+++ b/chrome/browser/apps/app_service/intent_util_unittest.cc
@@ -147,8 +147,12 @@
   ASSERT_TRUE(intent);
   ASSERT_TRUE(arc_intent);
 
-  // TODO(crbug.com/1253250): Modify CreateLaunchIntent to use the non mojom
-  // intent to verity intent_str, done in CreateIntentForActivityMojom.
+  std::string intent_str =
+      "#Intent;action=android.intent.action.MAIN;category=android.intent."
+      "category.LAUNCHER;launchFlags=0x10200000;component=com.android.vending/"
+      ".AssetBrowserActivity;S.org.chromium.arc.start_type=initialStart;end";
+  EXPECT_EQ(intent_str,
+            apps_util::CreateLaunchIntent("com.android.vending", intent));
 
   EXPECT_EQ(arc::kIntentActionMain, arc_intent->action);
 
@@ -182,8 +186,9 @@
       "#Intent;action=android.intent.action.MAIN;category=android.intent."
       "category.LAUNCHER;launchFlags=0x10200000;component=com.android.vending/"
       ".AssetBrowserActivity;S.org.chromium.arc.start_type=initialStart;end";
-  EXPECT_EQ(intent_str,
-            apps_util::CreateLaunchIntent("com.android.vending", intent));
+  EXPECT_EQ(intent_str, apps_util::CreateLaunchIntent(
+                            "com.android.vending",
+                            apps::ConvertMojomIntentToIntent(intent)));
 
   EXPECT_EQ(arc::kIntentActionMain, arc_intent->action);
 
@@ -201,8 +206,7 @@
 }
 
 TEST_F(IntentUtilsTest, CreateShareIntentFromText) {
-  apps::mojom::IntentPtr intent =
-      apps_util::CreateShareIntentFromText("text", "title");
+  apps::IntentPtr intent = apps_util::MakeShareIntent("text", "title");
   std::string intent_str =
       "#Intent;action=android.intent.action.SEND;launchFlags=0x10200000;"
       "component=com.android.vending/;type=text/"
diff --git a/chrome/browser/apps/app_service/publishers/arc_apps.cc b/chrome/browser/apps/app_service/publishers/arc_apps.cc
index e9b8166..8762a6a 100644
--- a/chrome/browser/apps/app_service/publishers/arc_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/arc_apps.cc
@@ -405,29 +405,29 @@
 // Constructs an OpenUrlsRequest to be passed to
 // FileSystemInstance.OpenUrlsWithPermissionAndWindowInfo.
 arc::mojom::OpenUrlsRequestPtr ConstructOpenUrlsRequest(
-    const apps::mojom::IntentPtr& intent,
+    const apps::IntentPtr& intent,
     const arc::mojom::ActivityNamePtr& activity,
     const std::vector<GURL>& content_urls) {
   arc::mojom::OpenUrlsRequestPtr request = arc::mojom::OpenUrlsRequest::New();
   request->action_type = GetArcActionType(intent->action);
   request->activity_name = activity.Clone();
-  DCHECK_EQ(content_urls.size(), intent->files.value().size());
+  DCHECK_EQ(content_urls.size(), intent->files.size());
   for (int i = 0; i < content_urls.size(); i++) {
     auto content_url = content_urls[i];
     arc::mojom::ContentUrlWithMimeTypePtr url_with_type =
         arc::mojom::ContentUrlWithMimeType::New();
     url_with_type->content_url = content_url;
-    DCHECK(intent->files.value()[i]->mime_type.has_value() ||
+    DCHECK(intent->files[i]->mime_type.has_value() ||
            intent->mime_type.has_value());
     // Save the file's original mimetype to the URL if it exists. Otherwise, use
     // the common intent mime type instead.
-    url_with_type->mime_type = intent->files.value()[i]->mime_type.has_value()
-                                   ? intent->files.value()[i]->mime_type.value()
+    url_with_type->mime_type = intent->files[i]->mime_type.has_value()
+                                   ? intent->files[i]->mime_type.value()
                                    : intent->mime_type.value();
     request->urls.push_back(std::move(url_with_type));
   }
   if (intent->share_text.has_value() || intent->share_title.has_value() ||
-      intent->extras.has_value()) {
+      !intent->extras.empty()) {
     request->extras = apps_util::CreateArcIntentExtras(intent);
   }
   return request;
@@ -436,10 +436,10 @@
 void OnContentUrlResolved(const base::FilePath& file_path,
                           const std::string& app_id,
                           int32_t event_flags,
-                          apps::mojom::IntentPtr intent,
+                          apps::IntentPtr intent,
                           arc::mojom::ActivityNamePtr activity,
-                          apps::mojom::WindowInfoPtr window_info,
-                          apps::ArcApps::LaunchAppWithIntentCallback callback,
+                          apps::WindowInfoPtr window_info,
+                          base::OnceCallback<void(bool)> callback,
                           const std::vector<GURL>& content_urls) {
   for (const auto& content_url : content_urls) {
     if (!content_url.is_valid()) {
@@ -474,8 +474,7 @@
   ::full_restore::SaveAppLaunchInfo(
       file_path,
       std::make_unique<app_restore::AppLaunchInfo>(
-          app_id, event_flags, apps::ConvertMojomIntentToIntent(intent),
-          session_id, display_id));
+          app_id, event_flags, std::move(intent), session_id, display_id));
 
   std::move(callback).Run(/*success=*/true);
 }
@@ -580,6 +579,18 @@
          apk_web_app_service->IsWebAppShellPackage(app_info.package_name);
 }
 
+bool IntentHasFilesAndMimeTypes(const apps::IntentPtr& intent) {
+  if (intent->files.empty()) {
+    return false;
+  }
+  bool all_files_have_mime_type = base::ranges::all_of(
+      intent->files,
+      [](apps::IntentFilePtr& file) { return file->mime_type.has_value(); });
+  return all_files_have_mime_type || intent->mime_type.has_value();
+}
+
+// TODO(crbug.com/1253250): Remove. Prefer the non mojom
+// IntentHasFilesAndMimeTypes.
 bool IntentHasFilesAndMimeTypes(const apps::mojom::IntentPtr& intent) {
   if (!intent->files.has_value()) {
     return false;
@@ -767,6 +778,174 @@
                                app_id, event_flags, session_id, display_id));
 }
 
+void ArcApps::LaunchAppWithIntent(const std::string& app_id,
+                                  int32_t event_flags,
+                                  IntentPtr intent,
+                                  LaunchSource launch_source,
+                                  WindowInfoPtr window_info,
+                                  base::OnceCallback<void(bool)> callback) {
+  auto user_interaction_type = GetUserInterationType(launch_source);
+  if (!user_interaction_type.has_value()) {
+    std::move(callback).Run(/*success=*/false);
+    return;
+  }
+
+  if (app_id == arc::kPlayStoreAppId &&
+      apps_util::IsHumanLaunch(launch_source)) {
+    arc::RecordPlayStoreLaunchWithinAWeek(profile_->GetPrefs(),
+                                          /*launched=*/true);
+  }
+
+  arc::ArcMetricsService::RecordArcUserInteraction(
+      profile_, user_interaction_type.value());
+
+  ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_);
+  if (!prefs) {
+    std::move(callback).Run(/*success=*/false);
+    return;
+  }
+  const std::unique_ptr<ArcAppListPrefs::AppInfo> app_info =
+      prefs->GetApp(app_id);
+  if (!app_info) {
+    LOG(ERROR) << "Launch App failed, could not find app with id " << app_id;
+    std::move(callback).Run(/*success=*/false);
+    return;
+  }
+
+  if (app_info->ready) {
+    arc::mojom::ActivityNamePtr activity = arc::mojom::ActivityName::New();
+    activity->package_name = app_info->package_name;
+    if (intent->activity_name.has_value() &&
+        !intent->activity_name.value().empty()) {
+      activity->activity_name = intent->activity_name.value();
+    }
+
+    auto new_window_info = SetSessionId(std::move(window_info));
+    int32_t session_id = new_window_info->window_id;
+    int64_t display_id = new_window_info->display_id;
+
+    // Check if the intent has files, and whether the intent has a mime type or
+    // all the individual files have mime types.
+    if (IntentHasFilesAndMimeTypes(intent)) {
+      std::vector<GURL> file_urls;
+      for (const auto& file : intent->files) {
+        file_urls.push_back(file->url);
+      }
+      arc::ConvertToContentUrlsAndShare(
+          profile_, apps::GetFileSystemURL(profile_, file_urls),
+          base::BindOnce(&OnContentUrlResolved, profile_->GetPath(), app_id,
+                         event_flags, std::move(intent), std::move(activity),
+                         std::move(new_window_info), std::move(callback)));
+      return;
+    }
+
+    auto intent_for_full_restore = intent->Clone();
+
+    std::string intent_str =
+        apps_util::CreateLaunchIntent(app_info->package_name, intent);
+    if (!intent_str.empty()) {
+      // If |intent| can be converted to a string, call the Launch interface.
+      if (!arc::LaunchAppWithIntent(
+              profile_, app_id, intent_str, event_flags,
+              user_interaction_type.value(),
+              MakeArcWindowInfo(std::move(new_window_info)))) {
+        VLOG(2) << "Failed to launch app: " + app_id + ".";
+        std::move(callback).Run(/*success=*/false);
+        return;
+      }
+    } else {
+      // If |intent| can't be converted to a string, call the HandleIntent
+      // interface.
+      auto arc_intent =
+          apps_util::ConvertAppServiceToArcIntent(std::move(intent));
+
+      if (!arc_intent) {
+        LOG(ERROR) << "Launch App failed, launch intent is not valid";
+        std::move(callback).Run(/*success=*/false);
+        return;
+      }
+
+      auto* arc_service_manager = arc::ArcServiceManager::Get();
+      if (!arc_service_manager) {
+        std::move(callback).Run(/*success=*/false);
+        return;
+      }
+
+      arc::mojom::IntentHelperInstance* instance = ARC_GET_INSTANCE_FOR_METHOD(
+          arc_service_manager->arc_bridge_service()->intent_helper(),
+          HandleIntentWithWindowInfo);
+      if (instance) {
+        instance->HandleIntentWithWindowInfo(
+            std::move(arc_intent), std::move(activity),
+            MakeArcWindowInfo(std::move(new_window_info)));
+      } else {
+        instance = ARC_GET_INSTANCE_FOR_METHOD(
+            arc_service_manager->arc_bridge_service()->intent_helper(),
+            HandleIntent);
+        if (!instance) {
+          std::move(callback).Run(/*success=*/false);
+          return;
+        }
+
+        instance->HandleIntent(std::move(arc_intent), std::move(activity));
+      }
+    }
+
+    prefs->SetLastLaunchTime(app_id);
+
+    full_restore::SaveAppLaunchInfo(
+        profile_->GetPath(),
+        std::make_unique<app_restore::AppLaunchInfo>(
+            app_id, event_flags, std::move(intent_for_full_restore), session_id,
+            display_id));
+    std::move(callback).Run(/*success=*/true);
+    return;
+  }
+
+  if (arc::IsArcPlayStoreEnabledForProfile(profile_)) {
+    // Handle the case when default app tries to re-activate OptIn flow.
+    if (arc::IsArcPlayStoreEnabledPreferenceManagedForProfile(profile_) &&
+        !arc::ArcSessionManager::Get()->enable_requested() &&
+        prefs->IsDefault(app_id)) {
+      arc::SetArcPlayStoreEnabledForProfile(profile_, true);
+      // PlayStore item has special handling for shelf controllers. In order
+      // to avoid unwanted initial animation for PlayStore item do not create
+      // deferred launch request when PlayStore item enables Google Play
+      // Store.
+      if (app_id == arc::kPlayStoreAppId) {
+        prefs->SetLastLaunchTime(app_id);
+        std::move(callback).Run(/*success=*/true);
+        return;
+      }
+    }
+  } else {
+    if (prefs->IsDefault(app_id)) {
+      // The setting can fail if the preference is managed.  However, the
+      // caller is responsible to not call this function in such case.  DCHECK
+      // is here to prevent possible mistake.
+      if (!arc::SetArcPlayStoreEnabledForProfile(profile_, true)) {
+        std::move(callback).Run(/*success=*/false);
+        return;
+      }
+      DCHECK(arc::IsArcPlayStoreEnabledForProfile(profile_));
+
+      // PlayStore item has special handling for shelf controllers. In order
+      // to avoid unwanted initial animation for PlayStore item do not create
+      // deferred launch request when PlayStore item enables Google Play
+      // Store.
+      if (app_id == arc::kPlayStoreAppId) {
+        prefs->SetLastLaunchTime(app_id);
+        std::move(callback).Run(/*success=*/false);
+        return;
+      }
+    } else {
+      // Only reachable when ARC always starts.
+      DCHECK(arc::ShouldArcAlwaysStart());
+    }
+  }
+  std::move(callback).Run(/*success=*/true);
+}
+
 void ArcApps::LaunchAppWithParams(AppLaunchParams&& params,
                                   LaunchCallback callback) {
   auto event_flags = apps::GetEventFlags(params.disposition,
@@ -917,15 +1096,17 @@
       arc::ConvertToContentUrlsAndShare(
           profile_, apps::GetFileSystemURL(profile_, file_urls),
           base::BindOnce(&OnContentUrlResolved, profile_->GetPath(), app_id,
-                         event_flags, std::move(intent), std::move(activity),
-                         std::move(new_window_info), std::move(callback)));
+                         event_flags, ConvertMojomIntentToIntent(intent),
+                         std::move(activity),
+                         ConvertMojomWindowInfoToWindowInfo(new_window_info),
+                         std::move(callback)));
       return;
     }
 
     auto intent_for_full_restore = intent.Clone();
 
-    std::string intent_str =
-        apps_util::CreateLaunchIntent(app_info->package_name, intent);
+    std::string intent_str = apps_util::CreateLaunchIntent(
+        app_info->package_name, ConvertMojomIntentToIntent(intent));
     if (!intent_str.empty()) {
       // If |intent| can be converted to a string, call the Launch interface.
       if (!arc::LaunchAppWithIntent(
diff --git a/chrome/browser/apps/app_service/publishers/arc_apps.h b/chrome/browser/apps/app_service/publishers/arc_apps.h
index ca5aeaa9..c51b96a 100644
--- a/chrome/browser/apps/app_service/publishers/arc_apps.h
+++ b/chrome/browser/apps/app_service/publishers/arc_apps.h
@@ -38,6 +38,7 @@
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/instance_registry.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/publisher_base.h"
 #include "components/services/app_service/public/mojom/app_service.mojom.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -109,6 +110,12 @@
               int32_t event_flags,
               LaunchSource launch_source,
               WindowInfoPtr window_info) override;
+  void LaunchAppWithIntent(const std::string& app_id,
+                           int32_t event_flags,
+                           IntentPtr intent,
+                           LaunchSource launch_source,
+                           WindowInfoPtr window_info,
+                           base::OnceCallback<void(bool)> callback);
   void LaunchAppWithParams(AppLaunchParams&& params,
                            LaunchCallback callback) override;
   void LaunchShortcut(const std::string& app_id,
diff --git a/chrome/browser/apps/app_service/publishers/web_apps_crosapi_browsertest.cc b/chrome/browser/apps/app_service/publishers/web_apps_crosapi_browsertest.cc
index 73bbc698..23105ee 100644
--- a/chrome/browser/apps/app_service/publishers/web_apps_crosapi_browsertest.cc
+++ b/chrome/browser/apps/app_service/publishers/web_apps_crosapi_browsertest.cc
@@ -81,7 +81,7 @@
       base::BindLambdaForTesting(
           [&](std::unique_ptr<ui::SimpleMenuModel> model) {
             items.reserve(model->GetItemCount());
-            for (size_t i = 0; i < model->GetItemCount(); ++i) {
+            for (int i = 0; i < model->GetItemCount(); ++i) {
               items.push_back(base::UTF16ToUTF8(model->GetLabelAt(i)));
             }
 
@@ -91,7 +91,7 @@
   return items;
 }
 
-void SelectContextMenuForApp(const std::string& app_id, size_t index) {
+void SelectContextMenuForApp(const std::string& app_id, int index) {
   base::RunLoop run_loop;
   ash::ShelfItemDelegate* delegate =
       ash::ShelfModel::Get()->GetShelfItemDelegate(ash::ShelfID(app_id));
@@ -164,10 +164,10 @@
     return;
   }
 
-  const size_t kNewWindowIndex = 0;
-  const size_t kPinIndex = 1;
-  const size_t kUnpinIndex = 1;
-  const size_t kCloseIndex = 2;
+  const int kNewWindowIndex = 0;
+  const int kPinIndex = 1;
+  const int kUnpinIndex = 1;
+  const int kCloseIndex = 2;
 
   const web_app::AppId app_id =
       InstallWebApp("https://example.org/", apps::WindowMode::kBrowser);
@@ -232,8 +232,8 @@
     return;
   }
 
-  const size_t kPinIndex = 1;
-  const size_t kUninstallIndex = 3;
+  const int kPinIndex = 1;
+  const int kUninstallIndex = 3;
 
   const web_app::AppId app_id =
       InstallWebApp("https://example.org/", apps::WindowMode::kBrowser);
diff --git a/chrome/browser/apps/platform_apps/app_browsertest.cc b/chrome/browser/apps/platform_apps/app_browsertest.cc
index 62e392f..6ad44e4 100644
--- a/chrome/browser/apps/platform_apps/app_browsertest.cc
+++ b/chrome/browser/apps/platform_apps/app_browsertest.cc
@@ -101,7 +101,7 @@
       : RenderViewContextMenu(render_frame_host, params) {}
 
   bool HasCommandWithId(int command_id) {
-    return menu_model_.GetIndexOfCommandId(command_id).has_value();
+    return menu_model_.GetIndexOfCommandId(command_id) != -1;
   }
 
   void Show() override {}
diff --git a/chrome/browser/apps/platform_apps/app_load_service_factory.cc b/chrome/browser/apps/platform_apps/app_load_service_factory.cc
index b95974d..c862bfb 100644
--- a/chrome/browser/apps/platform_apps/app_load_service_factory.cc
+++ b/chrome/browser/apps/platform_apps/app_load_service_factory.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/apps/platform_apps/app_load_service_factory.h"
 
 #include "chrome/browser/apps/platform_apps/app_load_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "content/public/browser/browser_context.h"
 #include "extensions/browser/app_window/app_window_registry.h"
 #include "extensions/browser/extension_host_registry.h"
@@ -28,9 +27,9 @@
 }
 
 AppLoadServiceFactory::AppLoadServiceFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "AppLoadService",
-          BrowserContextDependencyManager::GetInstance()) {
+          ProfileSelections::BuildServicesRedirectedInOTR()) {
   DependsOn(extensions::AppWindowRegistry::Factory::GetInstance());
   DependsOn(extensions::ExtensionPrefsFactory::GetInstance());
   DependsOn(extensions::ExtensionRegistryFactory::GetInstance());
@@ -50,11 +49,4 @@
   return true;
 }
 
-content::BrowserContext* AppLoadServiceFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  // Redirected in incognito.
-  return extensions::ExtensionsBrowserClient::Get()->GetOriginalContext(
-      context);
-}
-
 }  // namespace apps
diff --git a/chrome/browser/apps/platform_apps/app_load_service_factory.h b/chrome/browser/apps/platform_apps/app_load_service_factory.h
index 9faed18c..038fc10 100644
--- a/chrome/browser/apps/platform_apps/app_load_service_factory.h
+++ b/chrome/browser/apps/platform_apps/app_load_service_factory.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_APPS_PLATFORM_APPS_APP_LOAD_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 namespace content {
 class BrowserContext;
@@ -16,7 +16,7 @@
 
 class AppLoadService;
 
-class AppLoadServiceFactory : public BrowserContextKeyedServiceFactory {
+class AppLoadServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static AppLoadService* GetForBrowserContext(content::BrowserContext* context);
 
@@ -32,8 +32,6 @@
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
   bool ServiceIsCreatedWithBrowserContext() const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 }  // namespace apps
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index cce97c9..87e4acd 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -154,12 +154,12 @@
     "app_restore/arc_app_launch_handler.h",
     "app_restore/arc_ghost_window_delegate.cc",
     "app_restore/arc_ghost_window_delegate.h",
+    "app_restore/arc_ghost_window_handler.cc",
+    "app_restore/arc_ghost_window_handler.h",
     "app_restore/arc_ghost_window_shell_surface.cc",
     "app_restore/arc_ghost_window_shell_surface.h",
     "app_restore/arc_ghost_window_view.cc",
     "app_restore/arc_ghost_window_view.h",
-    "app_restore/arc_window_handler.cc",
-    "app_restore/arc_window_handler.h",
     "app_restore/arc_window_utils.cc",
     "app_restore/arc_window_utils.h",
     "app_restore/full_restore_app_launch_handler.cc",
diff --git a/chrome/browser/ash/app_restore/app_restore_arc_task_handler.cc b/chrome/browser/ash/app_restore/app_restore_arc_task_handler.cc
index f5717ea..8c871c7 100644
--- a/chrome/browser/ash/app_restore/app_restore_arc_task_handler.cc
+++ b/chrome/browser/ash/app_restore/app_restore_arc_task_handler.cc
@@ -7,7 +7,7 @@
 #include "ash/constants/ash_features.h"
 #include "chrome/browser/ash/app_restore/app_restore_arc_task_handler_factory.h"
 #include "chrome/browser/ash/app_restore/arc_app_launch_handler.h"
-#include "chrome/browser/ash/app_restore/arc_window_handler.h"
+#include "chrome/browser/ash/app_restore/arc_ghost_window_handler.h"
 #include "chrome/browser/ash/app_restore/arc_window_utils.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chrome/browser/profiles/profile.h"
@@ -42,7 +42,7 @@
 
 #if BUILDFLAG(ENABLE_WAYLAND_SERVER)
   if (full_restore::IsArcGhostWindowEnabled())
-    window_handler_ = std::make_unique<full_restore::ArcWindowHandler>();
+    window_handler_ = std::make_unique<full_restore::ArcGhostWindowHandler>();
 #endif
 
   arc_app_launch_handlers_[kFullRestoreId] =
diff --git a/chrome/browser/ash/app_restore/app_restore_arc_task_handler.h b/chrome/browser/ash/app_restore/app_restore_arc_task_handler.h
index ec6888e9..b8d985f3 100644
--- a/chrome/browser/ash/app_restore/app_restore_arc_task_handler.h
+++ b/chrome/browser/ash/app_restore/app_restore_arc_task_handler.h
@@ -17,7 +17,7 @@
 
 namespace ash {
 namespace full_restore {
-class ArcWindowHandler;
+class ArcGhostWindowHandler;
 class FullRestoreAppLaunchHandlerArcAppBrowserTest;
 }  // namespace full_restore
 
@@ -42,7 +42,7 @@
   ~AppRestoreArcTaskHandler() override;
 
 #if BUILDFLAG(ENABLE_WAYLAND_SERVER)
-  full_restore::ArcWindowHandler* window_handler() {
+  full_restore::ArcGhostWindowHandler* window_handler() {
     return window_handler_.get();
   }
 #endif
@@ -98,7 +98,7 @@
       arc_prefs_observer_{this};
 
 #if BUILDFLAG(ENABLE_WAYLAND_SERVER)
-  std::unique_ptr<full_restore::ArcWindowHandler> window_handler_;
+  std::unique_ptr<full_restore::ArcGhostWindowHandler> window_handler_;
 #endif
 
   // Maps launch ids to ArcAppLaunchHandlers. Positive ids are used for desk
diff --git a/chrome/browser/ash/app_restore/arc_app_launch_handler.cc b/chrome/browser/ash/app_restore/arc_app_launch_handler.cc
index 44a97a1..4f8711c 100644
--- a/chrome/browser/ash/app_restore/arc_app_launch_handler.cc
+++ b/chrome/browser/ash/app_restore/arc_app_launch_handler.cc
@@ -21,7 +21,7 @@
 #include "chrome/browser/apps/app_service/launch_utils.h"
 #include "chrome/browser/apps/app_service/metrics/app_platform_metrics.h"
 #include "chrome/browser/ash/app_restore/app_restore_arc_task_handler.h"
-#include "chrome/browser/ash/app_restore/arc_window_handler.h"
+#include "chrome/browser/ash/app_restore/arc_ghost_window_handler.h"
 #include "chrome/browser/ash/app_restore/arc_window_utils.h"
 #include "chrome/browser/ash/app_restore/full_restore_app_launch_handler.h"
 #include "chrome/browser/ash/arc/arc_util.h"
diff --git a/chrome/browser/ash/app_restore/arc_app_launch_handler.h b/chrome/browser/ash/app_restore/arc_app_launch_handler.h
index de59a3b..98c5bfa6 100644
--- a/chrome/browser/ash/app_restore/arc_app_launch_handler.h
+++ b/chrome/browser/ash/app_restore/arc_app_launch_handler.h
@@ -35,7 +35,7 @@
 
 namespace full_restore {
 class ArcAppLaunchHandlerArcAppBrowserTest;
-class ArcWindowHandler;
+class ArcGhostWindowHandler;
 class FullRestoreAppLaunchHandlerArcAppBrowserTest;
 }  // namespace full_restore
 
@@ -254,7 +254,7 @@
   std::map<int32_t, int32_t> window_id_to_session_id_;
   std::map<int32_t, int32_t> session_id_to_window_id_;
 
-  full_restore::ArcWindowHandler* window_handler_ = nullptr;
+  full_restore::ArcGhostWindowHandler* window_handler_ = nullptr;
 
   // If the system is under memory pressuure or high CPU usage rate, only launch
   // 1 window following the window stack priority. `first_run_` is used to check
diff --git a/chrome/browser/ash/app_restore/arc_ghost_window_delegate.cc b/chrome/browser/ash/app_restore/arc_ghost_window_delegate.cc
index c6cb5d64..e90186e 100644
--- a/chrome/browser/ash/app_restore/arc_ghost_window_delegate.cc
+++ b/chrome/browser/ash/app_restore/arc_ghost_window_delegate.cc
@@ -28,7 +28,7 @@
       shell_surface_(shell_surface) {
   DCHECK(shell_surface);
 
-  observation_.Observe(ArcWindowHandler::Get());
+  observation_.Observe(ArcGhostWindowHandler::Get());
   SetDisplayId(display_id);
 }
 ArcGhostWindowDelegate::~ArcGhostWindowDelegate() = default;
@@ -132,7 +132,7 @@
 
 void ArcGhostWindowDelegate::OnZoomLevelChanged(exo::ZoomChange zoom_change) {}
 
-// ArcWindowHandler::Observer
+// ArcGhostWindowHandler::Observer
 void ArcGhostWindowDelegate::OnAppInstanceConnected() {
   // Update window info to ARC when app instance connected, since the previous
   // window info may not be delivered.
@@ -159,7 +159,7 @@
 }
 
 void ArcGhostWindowDelegate::UpdateWindowInfoToArc() {
-  ArcWindowHandler::Get()->OnWindowInfoUpdated(
+  ArcGhostWindowHandler::Get()->OnWindowInfoUpdated(
       window_id_, pending_close_ ? kNullWindowState : (int)window_state_,
       display_id_, gfx::ScaleToRoundedRect(bounds_, scale_factor_));
 }
diff --git a/chrome/browser/ash/app_restore/arc_ghost_window_delegate.h b/chrome/browser/ash/app_restore/arc_ghost_window_delegate.h
index ce3c9d0..b22d1acc 100644
--- a/chrome/browser/ash/app_restore/arc_ghost_window_delegate.h
+++ b/chrome/browser/ash/app_restore/arc_ghost_window_delegate.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_DELEGATE_H_
 #define CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_DELEGATE_H_
 
-#include "chrome/browser/ash/app_restore/arc_window_handler.h"
+#include "chrome/browser/ash/app_restore/arc_ghost_window_handler.h"
 #include "chromeos/ui/base/window_state_type.h"
 #include "components/exo/client_controlled_shell_surface.h"
 #include "ui/gfx/geometry/rect.h"
@@ -18,7 +18,7 @@
 // changed, notify ARC.
 class ArcGhostWindowDelegate
     : public exo::ClientControlledShellSurface::Delegate,
-      public ArcWindowHandler::Observer {
+      public ArcGhostWindowHandler::Observer {
  public:
   ArcGhostWindowDelegate(exo::ClientControlledShellSurface* shell_surface,
                          int window_id,
@@ -46,7 +46,7 @@
 
   void OnZoomLevelChanged(exo::ZoomChange zoom_change) override;
 
-  // ArcWindowHandler::Observer
+  // ArcGhostWindowHandler::Observer
   void OnAppInstanceConnected() override;
 
   void OnWindowCloseRequested(int window_id) override;
@@ -63,7 +63,8 @@
   chromeos::WindowStateType window_state_;
   exo::ClientControlledShellSurface* shell_surface_;
 
-  base::ScopedObservation<ArcWindowHandler, ArcWindowHandler::Observer>
+  base::ScopedObservation<ArcGhostWindowHandler,
+                          ArcGhostWindowHandler::Observer>
       observation_{this};
 };
 
diff --git a/chrome/browser/ash/app_restore/arc_window_handler.cc b/chrome/browser/ash/app_restore/arc_ghost_window_handler.cc
similarity index 82%
rename from chrome/browser/ash/app_restore/arc_window_handler.cc
rename to chrome/browser/ash/app_restore/arc_ghost_window_handler.cc
index ace54b0..5c517a6 100644
--- a/chrome/browser/ash/app_restore/arc_window_handler.cc
+++ b/chrome/browser/ash/app_restore/arc_ghost_window_handler.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/app_restore/arc_window_handler.h"
+#include "chrome/browser/ash/app_restore/arc_ghost_window_handler.h"
 
 #include "chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.h"
 #include "chrome/browser/ash/app_restore/arc_window_utils.h"
@@ -20,16 +20,16 @@
 
 namespace {
 
-ArcWindowHandler* g_instance = nullptr;
+ArcGhostWindowHandler* g_instance = nullptr;
 
 }  // namespace
 
-void ArcWindowHandler::WindowSessionResolver::PopulateProperties(
+void ArcGhostWindowHandler::WindowSessionResolver::PopulateProperties(
     const Params& params,
     ui::PropertyHandler& out_properties_container) {
   if (params.window_session_id <= 0)
     return;
-  auto* handler = ArcWindowHandler::Get();
+  auto* handler = ArcGhostWindowHandler::Get();
   auto it =
       handler->session_id_to_shell_surface_.find(params.window_session_id);
   if (it != handler->session_id_to_shell_surface_.end()) {
@@ -52,7 +52,7 @@
   }
 }
 
-ArcWindowHandler::ArcWindowHandler() {
+ArcGhostWindowHandler::ArcGhostWindowHandler() {
   DCHECK_EQ(nullptr, g_instance);
   exo::WMHelper::GetInstance()->RegisterAppPropertyResolver(
       std::make_unique<WindowSessionResolver>());
@@ -62,7 +62,7 @@
   g_instance = this;
 }
 
-ArcWindowHandler::~ArcWindowHandler() {
+ArcGhostWindowHandler::~ArcGhostWindowHandler() {
   DCHECK_EQ(this, g_instance);
   if (exo::WMHelper::HasInstance()) {
     auto* lifetime_manager = exo::WMHelper::GetInstance()->GetLifetimeManager();
@@ -73,11 +73,11 @@
 }
 
 // static
-ArcWindowHandler* ArcWindowHandler::Get() {
+ArcGhostWindowHandler* ArcGhostWindowHandler::Get() {
   return g_instance;
 }
 
-void ArcWindowHandler::OnDestroyed() {
+void ArcGhostWindowHandler::OnDestroyed() {
   // Destroy all ARC ghost window when Wayland server shutdown.
   std::vector<int> session_ids;
   for (const auto& session_id : session_id_to_shell_surface_)
@@ -92,7 +92,7 @@
   lifetime_manager->RemoveObserver(this);
 }
 
-bool ArcWindowHandler::LaunchArcGhostWindow(
+bool ArcGhostWindowHandler::LaunchArcGhostWindow(
     const std::string& app_id,
     int32_t session_id,
     app_restore::AppRestoreData* restore_data) {
@@ -118,7 +118,7 @@
 
   auto shell_surface = ArcGhostWindowShellSurface::Create(
       app_id, session_id, adjust_bounds, restore_data,
-      base::BindRepeating(&ArcWindowHandler::CloseWindow,
+      base::BindRepeating(&ArcGhostWindowHandler::CloseWindow,
                           weak_ptr_factory_.GetWeakPtr(), session_id));
   if (!shell_surface)
     return false;
@@ -127,7 +127,7 @@
   return true;
 }
 
-void ArcWindowHandler::CloseWindow(int session_id) {
+void ArcGhostWindowHandler::CloseWindow(int session_id) {
   auto it = session_id_to_shell_surface_.find(session_id);
   if (it == session_id_to_shell_surface_.end())
     return;
@@ -137,17 +137,17 @@
   session_id_to_shell_surface_.erase(it);
 }
 
-void ArcWindowHandler::AddObserver(Observer* observer) {
+void ArcGhostWindowHandler::AddObserver(Observer* observer) {
   observer_list_.AddObserver(observer);
 }
-void ArcWindowHandler::RemoveObserver(Observer* observer) {
+void ArcGhostWindowHandler::RemoveObserver(Observer* observer) {
   observer_list_.RemoveObserver(observer);
 }
-bool ArcWindowHandler::HasObserver(Observer* observer) {
+bool ArcGhostWindowHandler::HasObserver(Observer* observer) {
   return observer_list_.HasObserver(observer);
 }
 
-void ArcWindowHandler::OnAppInstanceConnected() {
+void ArcGhostWindowHandler::OnAppInstanceConnected() {
   is_app_instance_connected_ = true;
 
   // Send all pending window info updates to ARC.
@@ -160,10 +160,10 @@
     observer.OnAppInstanceConnected();
 }
 
-void ArcWindowHandler::OnWindowInfoUpdated(int window_id,
-                                           int state,
-                                           int64_t display_id,
-                                           gfx::Rect bounds) {
+void ArcGhostWindowHandler::OnWindowInfoUpdated(int window_id,
+                                                int state,
+                                                int64_t display_id,
+                                                gfx::Rect bounds) {
   auto window_info = arc::mojom::WindowInfo::New();
   window_info->window_id = window_id;
   window_info->display_id = display_id;
diff --git a/chrome/browser/ash/app_restore/arc_window_handler.h b/chrome/browser/ash/app_restore/arc_ghost_window_handler.h
similarity index 79%
rename from chrome/browser/ash/app_restore/arc_window_handler.h
rename to chrome/browser/ash/app_restore/arc_ghost_window_handler.h
index 14788ce..f02aad7f 100644
--- a/chrome/browser/ash/app_restore/arc_window_handler.h
+++ b/chrome/browser/ash/app_restore/arc_ghost_window_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_APP_RESTORE_ARC_WINDOW_HANDLER_H_
-#define CHROME_BROWSER_ASH_APP_RESTORE_ARC_WINDOW_HANDLER_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_HANDLER_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_HANDLER_H_
 
 #include "ash/components/arc/mojom/app.mojom.h"
 #include "base/memory/weak_ptr.h"
@@ -19,8 +19,8 @@
 namespace ash {
 namespace full_restore {
 
-// The ArcWindowHandler class provides control for ARC ghost window.
-class ArcWindowHandler : public exo::WMHelper::LifetimeManager::Observer {
+// The ArcGhostWindowHandler class provides control for ARC ghost window.
+class ArcGhostWindowHandler : public exo::WMHelper::LifetimeManager::Observer {
   // Map from window_session_id to exo::ClientControlledShellSurface.
   using ShellSurfaceMap =
       std::map<int, std::unique_ptr<exo::ClientControlledShellSurface>>;
@@ -56,16 +56,16 @@
     ~Observer() override = default;
   };
 
-  ArcWindowHandler();
-  ArcWindowHandler(const ArcWindowHandler&) = delete;
-  ArcWindowHandler& operator=(const ArcWindowHandler&) = delete;
-  ~ArcWindowHandler() override;
+  ArcGhostWindowHandler();
+  ArcGhostWindowHandler(const ArcGhostWindowHandler&) = delete;
+  ArcGhostWindowHandler& operator=(const ArcGhostWindowHandler&) = delete;
+  ~ArcGhostWindowHandler() override;
 
-  // ArcWindowHandler is created and destroyed with the
+  // ArcGhostWindowHandler is created and destroyed with the
   // ash::AppRestore::AppRestoreArcTaskHandler.
-  // ArcWindowHandler::Get may be nullptr if accessed outside the expected
+  // ArcGhostWindowHandler::Get may be nullptr if accessed outside the expected
   // lifetime.
-  static ArcWindowHandler* Get();
+  static ArcGhostWindowHandler* Get();
 
   // Returns true if the ghost window is created and launched. Otherwise,
   // returns false.
@@ -106,10 +106,10 @@
 
   base::ObserverList<Observer> observer_list_;
 
-  base::WeakPtrFactory<ArcWindowHandler> weak_ptr_factory_{this};
+  base::WeakPtrFactory<ArcGhostWindowHandler> weak_ptr_factory_{this};
 };
 
 }  // namespace full_restore
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_APP_RESTORE_ARC_WINDOW_HANDLER_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_HANDLER_H_
diff --git a/chrome/browser/ash/app_restore/arc_ghost_window_view.cc b/chrome/browser/ash/app_restore/arc_ghost_window_view.cc
index ebdccac..e5da9043 100644
--- a/chrome/browser/ash/app_restore/arc_ghost_window_view.cc
+++ b/chrome/browser/ash/app_restore/arc_ghost_window_view.cc
@@ -8,7 +8,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
-#include "chrome/browser/ash/app_restore/arc_window_handler.h"
+#include "chrome/browser/ash/app_restore/arc_ghost_window_handler.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_menu_builder_unittest.cc b/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_menu_builder_unittest.cc
index 59df601b..2991fda5 100644
--- a/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_menu_builder_unittest.cc
+++ b/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_menu_builder_unittest.cc
@@ -8,7 +8,7 @@
 #include <utility>
 
 #include "base/run_loop.h"
-#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
 #include "chrome/browser/chromeos/arc/icon_decode_request.h"
@@ -85,8 +85,8 @@
   EXPECT_EQ(first_item_label, menu->GetLabelAt(i++));
   EXPECT_EQ(ui::DOUBLE_SEPARATOR, menu->GetSeparatorTypeAt(i++));
   // There is a separator between each app shortcut.
-  for (size_t shortcut_index = 0; i < menu->GetItemCount(); ++i) {
-    EXPECT_EQ("ShortLabel " + base::NumberToString(shortcut_index++),
+  for (int shortcut_index = 0; i < menu->GetItemCount(); ++i) {
+    EXPECT_EQ(base::StringPrintf("ShortLabel %d", shortcut_index++),
               base::UTF16ToUTF8(menu->GetLabelAt(i++)));
     if (i < menu->GetItemCount())
       EXPECT_EQ(ui::PADDED_SEPARATOR, menu->GetSeparatorTypeAt(i));
diff --git a/chrome/browser/ash/arc/tracing/arc_app_performance_tracing_unittest.cc b/chrome/browser/ash/arc/tracing/arc_app_performance_tracing_unittest.cc
index 78a9af8..8dcfaefa 100644
--- a/chrome/browser/ash/arc/tracing/arc_app_performance_tracing_unittest.cc
+++ b/chrome/browser/ash/arc/tracing/arc_app_performance_tracing_unittest.cc
@@ -11,8 +11,8 @@
 #include "base/metrics/histogram_samples.h"
 #include "base/metrics/statistics_recorder.h"
 #include "base/strings/stringprintf.h"
+#include "chrome/browser/ash/app_restore/arc_ghost_window_handler.h"
 #include "chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.h"
-#include "chrome/browser/ash/app_restore/arc_window_handler.h"
 #include "chrome/browser/ash/arc/tracing/arc_app_performance_tracing_session.h"
 #include "chrome/browser/ash/arc/tracing/arc_app_performance_tracing_test_helper.h"
 #include "chrome/browser/ash/arc/tracing/arc_app_performance_tracing_uma_session.h"
@@ -324,8 +324,9 @@
   display::Display display =
       display::Screen::GetScreen()->GetDisplayNearestWindow(
           ash::Shell::GetPrimaryRootWindow());
-  std::unique_ptr<ash::full_restore::ArcWindowHandler> ghost_window_handler =
-      std::make_unique<ash::full_restore::ArcWindowHandler>();
+  std::unique_ptr<ash::full_restore::ArcGhostWindowHandler>
+      ghost_window_handler =
+          std::make_unique<ash::full_restore::ArcGhostWindowHandler>();
 
   app_restore::AppRestoreData restore_data;
   restore_data.display_id = display.id();
diff --git a/chrome/browser/ash/crosapi/test_controller_ash.cc b/chrome/browser/ash/crosapi/test_controller_ash.cc
index ca038d0..b34e7a1 100644
--- a/chrome/browser/ash/crosapi/test_controller_ash.cc
+++ b/chrome/browser/ash/crosapi/test_controller_ash.cc
@@ -391,7 +391,7 @@
     std::unique_ptr<ui::SimpleMenuModel> model) {
   std::vector<std::string> items;
   items.reserve(model->GetItemCount());
-  for (size_t i = 0; i < model->GetItemCount(); ++i) {
+  for (int i = 0; i < model->GetItemCount(); ++i) {
     items.push_back(base::UTF16ToUTF8(model->GetLabelAt(i)));
   }
   std::move(callback).Run(std::move(items));
@@ -400,7 +400,7 @@
 void TestControllerAsh::OnSelectContextMenuForShelfItem(
     SelectContextMenuForShelfItemCallback callback,
     const std::string& item_id,
-    size_t index,
+    uint32_t index,
     std::unique_ptr<ui::SimpleMenuModel> model) {
   if (index < model->GetItemCount()) {
     model->ActivatedAt(index, /*event_flags=*/0);
diff --git a/chrome/browser/ash/crosapi/test_controller_ash.h b/chrome/browser/ash/crosapi/test_controller_ash.h
index 3b8de6b..eadf3f6 100644
--- a/chrome/browser/ash/crosapi/test_controller_ash.h
+++ b/chrome/browser/ash/crosapi/test_controller_ash.h
@@ -120,7 +120,7 @@
   static void OnSelectContextMenuForShelfItem(
       SelectContextMenuForShelfItemCallback callback,
       const std::string& item_id,
-      size_t index,
+      uint32_t index,
       std::unique_ptr<ui::SimpleMenuModel> model);
 
   // Each call to EnterOverviewMode or ExitOverviewMode spawns a waiter for the
diff --git a/chrome/browser/ash/crostini/ansible/ansible_management_service.cc b/chrome/browser/ash/crostini/ansible/ansible_management_service.cc
index cdd20ba..be425e0 100644
--- a/chrome/browser/ash/crostini/ansible/ansible_management_service.cc
+++ b/chrome/browser/ash/crostini/ansible/ansible_management_service.cc
@@ -225,12 +225,7 @@
       OnConfigurationFinished(container_id, false);
       break;
     case vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::IN_PROGRESS:
-      for (auto& observer : observers_) {
-        observer.OnAnsibleSoftwareConfigurationProgress(
-            container_id,
-            std::vector<std::string>(signal.status_string().begin(),
-                                     signal.status_string().end()));
-      }
+      // TODO(okalitova): Report Ansible playbook application progress.
       break;
     default:
       NOTREACHED();
diff --git a/chrome/browser/ash/crostini/ansible/ansible_management_service.h b/chrome/browser/ash/crostini/ansible/ansible_management_service.h
index aa1cddd..b05400e 100644
--- a/chrome/browser/ash/crostini/ansible/ansible_management_service.h
+++ b/chrome/browser/ash/crostini/ansible/ansible_management_service.h
@@ -43,9 +43,6 @@
     ~Observer() override = default;
     virtual void OnAnsibleSoftwareConfigurationStarted(
         const guest_os::GuestId& container_id) = 0;
-    virtual void OnAnsibleSoftwareConfigurationProgress(
-        const guest_os::GuestId& container_id,
-        const std::vector<std::string>& status_lines) {}
     virtual void OnAnsibleSoftwareConfigurationFinished(
         const guest_os::GuestId& container_id,
         bool success) = 0;
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest.cc b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
index 3c2d3f3..234bb05 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
@@ -1639,8 +1639,10 @@
         TestCase("enableDisableStorageSettingsLink").FilesSwa(),
         TestCase("showAvailableStorageMyFiles"),
         TestCase("showAvailableStorageMyFiles").FilesSwa(),
-        TestCase("showAvailableStorageDrive"),
-        TestCase("showAvailableStorageDrive").FilesSwa(),
+        // Disabled until Drive quota can be properly displayed.
+        // crbug.com/1177203
+        // TestCase("showAvailableStorageDrive"),
+        // TestCase("showAvailableStorageDrive").FilesSwa(),
         TestCase("showAvailableStorageSmbfs"),
         TestCase("showAvailableStorageSmbfs").FilesSwa(),
         TestCase("showAvailableStorageDocProvider")
diff --git a/chrome/browser/ash/file_manager/file_manager_string_util.cc b/chrome/browser/ash/file_manager/file_manager_string_util.cc
index f163193c..545af78 100644
--- a/chrome/browser/ash/file_manager/file_manager_string_util.cc
+++ b/chrome/browser/ash/file_manager/file_manager_string_util.cc
@@ -19,6 +19,8 @@
 #include "chrome/browser/ash/login/demo_mode/demo_session.h"
 #include "chrome/browser/ash/plugin_vm/plugin_vm_features.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h"
+#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/grit/generated_resources.h"
@@ -1051,6 +1053,17 @@
   dict->Set("GUEST_OS",
             base::FeatureList::IsEnabled(chromeos::features::kGuestOsFiles));
 
+  if (base::FeatureList::IsEnabled(features::kDataLeakPreventionPolicy) &&
+      base::FeatureList::IsEnabled(
+          features::kDataLeakPreventionFilesRestriction)) {
+    policy::DlpRulesManager* rules_manager =
+        policy::DlpRulesManagerFactory::GetForPrimaryProfile();
+    dict->Set("DLP_ENABLED",
+              (rules_manager && rules_manager->IsFilesPolicyEnabled()));
+  } else {
+    dict->Set("DLP_ENABLED", false);
+  }
+
   dict->Set("UI_LOCALE", locale);
   dict->Set("WEEK_START_FROM", GetLocaleBasedWeekStart());
 }
diff --git a/chrome/browser/ash/login/lock/screen_locker.cc b/chrome/browser/ash/login/lock/screen_locker.cc
index 9f063b0..f4e89ca 100644
--- a/chrome/browser/ash/login/lock/screen_locker.cc
+++ b/chrome/browser/ash/login/lock/screen_locker.cc
@@ -650,11 +650,28 @@
   }
 
   DCHECK(screen_locker_);
-  SessionControllerClientImpl::Get()->RunUnlockAnimation(base::BindOnce([]() {
-    session_manager::SessionManager::Get()->SetSessionState(
-        session_manager::SessionState::ACTIVE);
-    ScreenLocker::ScheduleDeletion();
-  }));
+  SessionControllerClientImpl::Get()->RunUnlockAnimation(
+      base::BindOnce(&ScreenLocker::OnUnlockAnimationFinished));
+}
+
+void ScreenLocker::ResetToLockedState() {
+  LoginScreen::Get()->GetModel()->SetFingerprintState(
+      user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId(),
+      FingerprintState::AVAILABLE_DEFAULT);
+  screen_locker_->unlock_started_ = false;
+}
+
+// static
+void ScreenLocker::OnUnlockAnimationFinished(bool aborted) {
+  if (aborted) {
+    // Reset state that was impacted by successful auth.
+    screen_locker_->ResetToLockedState();
+    return;
+  }
+
+  session_manager::SessionManager::Get()->SetSessionState(
+      session_manager::SessionState::ACTIVE);
+  ScreenLocker::ScheduleDeletion();
 }
 
 void ScreenLocker::RefreshPinAndFingerprintTimeout() {
diff --git a/chrome/browser/ash/login/lock/screen_locker.h b/chrome/browser/ash/login/lock/screen_locker.h
index cf3bf6b..45a6ac13 100644
--- a/chrome/browser/ash/login/lock/screen_locker.h
+++ b/chrome/browser/ash/login/lock/screen_locker.h
@@ -157,6 +157,17 @@
   // Hide the screen locker.
   static void Hide();
 
+  // If the unlock animation was aborted (for instance, as a result of
+  // pressing the power button during the unlock animatoin), we  reset
+  // the state of UI elements (such as LoginAuthUserView::FingerprintView)
+  // which might have been altered as a result of a successful authentication
+  // attempt.
+  void ResetToLockedState();
+
+  // If the unlock animation was not aborted, changes session state to
+  // active and schedules `ScreenLocker` deletion.
+  static void OnUnlockAnimationFinished(bool aborted);
+
   // we should probably not call it anymore
   void RefreshPinAndFingerprintTimeout();
 
@@ -286,8 +297,8 @@
   bool locked_ = false;
 
   // True if the unlock process has started, or false otherwise.  This changes
-  // from false to true, but will never change from true to false. Instead,
-  // ScreenLocker object gets deleted when unlocked.
+  // from false to true, but will only change from true to false when unlock is
+  // aborted. Otherwise, ScreenLocker object gets deleted when unlocked.
   bool unlock_started_ = false;
 
   // Reference to the single instance of the screen locker object.
diff --git a/chrome/browser/ash/login/screens/multidevice_setup_screen.cc b/chrome/browser/ash/login/screens/multidevice_setup_screen.cc
index 5b1749f..ad380dd 100644
--- a/chrome/browser/ash/login/screens/multidevice_setup_screen.cc
+++ b/chrome/browser/ash/login/screens/multidevice_setup_screen.cc
@@ -8,6 +8,7 @@
 #include "ash/services/multidevice_setup/public/cpp/oobe_completion_tracker.h"
 #include "base/feature_list.h"
 #include "base/logging.h"
+#include "base/memory/weak_ptr.h"
 #include "base/metrics/histogram_macros.h"
 #include "chrome/browser/ash/login/users/chrome_user_manager_util.h"
 #include "chrome/browser/ash/multidevice_setup/multidevice_setup_client_factory.h"
@@ -38,19 +39,16 @@
 }
 
 MultiDeviceSetupScreen::MultiDeviceSetupScreen(
-    MultiDeviceSetupScreenView* view,
+    base::WeakPtr<MultiDeviceSetupScreenView> view,
     const ScreenExitCallback& exit_callback)
     : BaseScreen(MultiDeviceSetupScreenView::kScreenId,
                  OobeScreenPriority::DEFAULT),
-      view_(view),
+      view_(std::move(view)),
       exit_callback_(exit_callback) {
   DCHECK(view_);
-  view_->Bind(this);
 }
 
-MultiDeviceSetupScreen::~MultiDeviceSetupScreen() {
-  view_->Bind(nullptr);
-}
+MultiDeviceSetupScreen::~MultiDeviceSetupScreen() = default;
 
 void MultiDeviceSetupScreen::TryInitSetupClient() {
   if (!setup_client_) {
@@ -87,7 +85,9 @@
 }
 
 void MultiDeviceSetupScreen::ShowImpl() {
-  view_->Show();
+  if (view_) {
+    view_->Show();
+  }
 
   // Record that user was presented with setup flow to prevent spam
   // notifications from suggesting setup in the future.
@@ -98,12 +98,11 @@
   oobe_completion_tracker->MarkOobeShown();
 }
 
-void MultiDeviceSetupScreen::HideImpl() {
-  view_->Hide();
-}
+void MultiDeviceSetupScreen::HideImpl() {}
 
-void MultiDeviceSetupScreen::OnUserActionDeprecated(
-    const std::string& action_id) {
+void MultiDeviceSetupScreen::OnUserAction(const base::Value::List& args) {
+  const std::string& action_id = args[0].GetString();
+
   if (action_id == kAcceptedSetupUserAction) {
     RecordMultiDeviceSetupOOBEUserChoiceHistogram(
         MultiDeviceSetupOOBEUserChoice::kAccepted);
@@ -113,7 +112,7 @@
         MultiDeviceSetupOOBEUserChoice::kDeclined);
     exit_callback_.Run(Result::NEXT);
   } else {
-    BaseScreen::OnUserActionDeprecated(action_id);
+    BaseScreen::OnUserAction(args);
     NOTREACHED();
   }
 }
diff --git a/chrome/browser/ash/login/screens/multidevice_setup_screen.h b/chrome/browser/ash/login/screens/multidevice_setup_screen.h
index d1fad04e2..301727e 100644
--- a/chrome/browser/ash/login/screens/multidevice_setup_screen.h
+++ b/chrome/browser/ash/login/screens/multidevice_setup_screen.h
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/login/screens/base_screen.h"
 // TODO(https://crbug.com/1164001): move to forward declaration.
 #include "chrome/browser/ui/webui/chromeos/login/multidevice_setup_screen_handler.h"
@@ -26,7 +27,7 @@
   static std::string GetResultString(Result result);
 
   using ScreenExitCallback = base::RepeatingCallback<void(Result result)>;
-  MultiDeviceSetupScreen(MultiDeviceSetupScreenView* view,
+  MultiDeviceSetupScreen(base::WeakPtr<MultiDeviceSetupScreenView> view,
                          const ScreenExitCallback& exit_callback);
 
   MultiDeviceSetupScreen(const MultiDeviceSetupScreen&) = delete;
@@ -54,7 +55,7 @@
   bool MaybeSkip(WizardContext* context) override;
   void ShowImpl() override;
   void HideImpl() override;
-  void OnUserActionDeprecated(const std::string& action_id) override;
+  void OnUserAction(const base::Value::List& args) override;
 
  private:
   friend class MultiDeviceSetupScreenTest;
@@ -77,7 +78,7 @@
 
   multidevice_setup::MultiDeviceSetupClient* setup_client_ = nullptr;
 
-  MultiDeviceSetupScreenView* view_;
+  base::WeakPtr<MultiDeviceSetupScreenView> view_;
   ScreenExitCallback exit_callback_;
 };
 
diff --git a/chrome/browser/ash/login/wizard_controller.cc b/chrome/browser/ash/login/wizard_controller.cc
index 64c65a1..ffbca7a 100644
--- a/chrome/browser/ash/login/wizard_controller.cc
+++ b/chrome/browser/ash/login/wizard_controller.cc
@@ -298,11 +298,24 @@
     {chromeos::WelcomeView::kScreenId, "network"},
     {chromeos::TermsOfServiceScreenView::kScreenId, "tos"}};
 
+std::string GetLegacyUmaOobeScreenName(const OobeScreenId& screen_id) {
+  // Make sure to use initial UMA name if the name has changed.
+  std::string uma_name = screen_id.name;
+  for (const auto& entry : kLegacyUmaOobeScreenNames) {
+    if (entry.screen.AsId() == screen_id) {
+      uma_name = entry.uma_name;
+      break;
+    }
+  }
+  uma_name[0] = std::toupper(uma_name[0]);
+  return uma_name;
+}
+
 void RecordUMAHistogramForOOBEStepShownStatus(
     OobeScreenId screen,
     WizardController::ScreenShownStatus status) {
-  std::string screen_name = screen.name;
-  screen_name[0] = std::toupper(screen_name[0]);
+  // Legacy histogram, requires old screen names.
+  std::string screen_name = GetLegacyUmaOobeScreenName(screen);
   std::string histogram_name = "OOBE.StepShownStatus." + screen_name;
   base::UmaHistogramEnumeration(histogram_name, status);
 }
@@ -310,23 +323,14 @@
 void RecordUMAHistogramForOOBEStepCompletionTime(OobeScreenId screen,
                                                  const std::string& exit_reason,
                                                  base::TimeDelta step_time) {
-  // Fetch screen name; make sure to use initial UMA name if the name has
-  // changed.
-  std::string screen_name = screen.name;
-  for (const auto& entry : kLegacyUmaOobeScreenNames) {
-    if (entry.screen.AsId() == screen) {
-      screen_name = entry.uma_name;
-      break;
-    }
-  }
-
-  screen_name[0] = std::toupper(screen_name[0]);
-  std::string histogram_name = "OOBE.StepCompletionTime." + screen_name;
+  // Legacy histogram, requires old screen names.
+  std::string uma_name = GetLegacyUmaOobeScreenName(screen);
+  std::string histogram_name = "OOBE.StepCompletionTime." + uma_name;
 
   base::UmaHistogramMediumTimes(histogram_name, step_time);
 
-  // Use for this Histogram real screen names.
-  screen_name = screen.name;
+  // Use for this histogram real screen names.
+  std::string screen_name = screen.name;
   screen_name[0] = std::toupper(screen_name[0]);
   std::string histogram_name_with_reason =
       "OOBE.StepCompletionTimeByExitReason." + screen_name + "." + exit_reason;
@@ -682,7 +686,7 @@
       base::BindRepeating(&WizardController::OnAssistantOptInFlowScreenExit,
                           weak_factory_.GetWeakPtr())));
   append(std::make_unique<MultiDeviceSetupScreen>(
-      oobe_ui->GetView<MultiDeviceSetupScreenHandler>(),
+      oobe_ui->GetView<MultiDeviceSetupScreenHandler>()->AsWeakPtr(),
       base::BindRepeating(&WizardController::OnMultiDeviceSetupScreenExit,
                           weak_factory_.GetWeakPtr())));
   append(std::make_unique<PinSetupScreen>(
diff --git a/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc b/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc
index 71585bba..154f3ba 100644
--- a/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc
+++ b/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc
@@ -1606,7 +1606,7 @@
     run_loop.Run();
   }
 
-  auto check_shortcut = [&menu_model](size_t index, int shortcut_index,
+  auto check_shortcut = [&menu_model](int index, int shortcut_index,
                                       const std::u16string& label) {
     EXPECT_EQ(menu_model->GetTypeAt(index), ui::MenuModel::TYPE_COMMAND);
     EXPECT_EQ(menu_model->GetCommandIdAt(index),
@@ -1623,7 +1623,7 @@
   ui_test_utils::UrlLoadObserver url_observer(
       GURL("chrome://test-system-app/pwa.html#two"),
       content::NotificationService::AllSources());
-  menu_model->ActivatedAt(menu_model->GetIndexOfCommandId(command_id).value(),
+  menu_model->ActivatedAt(menu_model->GetIndexOfCommandId(command_id),
                           ui::EF_LEFT_MOUSE_BUTTON);
   url_observer.Wait();
 }
diff --git a/chrome/browser/autofill/autofill_context_menu_manager_unittest.cc b/chrome/browser/autofill/autofill_context_menu_manager_unittest.cc
index e026ad1a..0395a1d 100644
--- a/chrome/browser/autofill/autofill_context_menu_manager_unittest.cc
+++ b/chrome/browser/autofill/autofill_context_menu_manager_unittest.cc
@@ -105,7 +105,7 @@
   std::vector<std::u16string> all_added_strings;
 
   // Check for top level menu with autofill options.
-  ASSERT_EQ(2u, menu_model()->GetItemCount());
+  ASSERT_EQ(2, menu_model()->GetItemCount());
   ASSERT_EQ(u"Fill Address Info", menu_model()->GetLabelAt(0));
   ASSERT_EQ(u"Fill Payment", menu_model()->GetLabelAt(1));
   ASSERT_EQ(menu_model()->GetTypeAt(0), ui::MenuModel::ItemType::TYPE_SUBMENU);
@@ -113,7 +113,7 @@
 
   // Check for submenu with address descriptions.
   auto* address_menu_model = menu_model()->GetSubmenuModelAt(0);
-  ASSERT_EQ(address_menu_model->GetItemCount(), 3u);
+  ASSERT_EQ(address_menu_model->GetItemCount(), 3);
   ASSERT_EQ(u"John H. Doe, 666 Erebus St.", address_menu_model->GetLabelAt(0));
   ASSERT_EQ(address_menu_model->GetTypeAt(0),
             ui::MenuModel::ItemType::TYPE_SUBMENU);
@@ -123,7 +123,7 @@
 
   // Check for submenu with address details.
   auto* address_details_submenu = address_menu_model->GetSubmenuModelAt(0);
-  ASSERT_EQ(address_details_submenu->GetItemCount(), 8u);
+  ASSERT_EQ(address_details_submenu->GetItemCount(), 8);
   static constexpr std::array expected_address_values = {
       u"John H. Doe", u"", u"666 Erebus St.\nApt 8", u"Elysium",
       u"91111",       u"", u"16502111111",           u"johndoe@hades.com"};
@@ -135,7 +135,7 @@
 
   // Check for submenu with credit card descriptions.
   auto* card_menu_model = menu_model()->GetSubmenuModelAt(1);
-  ASSERT_EQ(card_menu_model->GetItemCount(), 3u);
+  ASSERT_EQ(card_menu_model->GetItemCount(), 3);
   ASSERT_EQ(
       u"Visa  "
       u"\x202A\x2022\x2060\x2006\x2060\x2022\x2060\x2006\x2060\x2022\x2060"
@@ -150,7 +150,7 @@
 
   // Check for submenu with credit card details.
   auto* card_details_submenu = card_menu_model->GetSubmenuModelAt(0);
-  ASSERT_EQ(card_details_submenu->GetItemCount(), 5u);
+  ASSERT_EQ(card_details_submenu->GetItemCount(), 5);
   static constexpr std::array expected_credit_card_values = {
       u"Test User", u"4111111111111111", u""};
   for (size_t i = 0; i < expected_credit_card_values.size(); i++) {
diff --git a/chrome/browser/autofill_assistant/password_change/apc_client_impl.cc b/chrome/browser/autofill_assistant/password_change/apc_client_impl.cc
index 3ca588d5..f449695 100644
--- a/chrome/browser/autofill_assistant/password_change/apc_client_impl.cc
+++ b/chrome/browser/autofill_assistant/password_change/apc_client_impl.cc
@@ -150,8 +150,8 @@
         debug_run_information_.value().socket_id;
   }
 
-  external_script_controller_ = CreateHeadlessScriptController();
   scrim_manager_ = CreateApcScrimManager();
+  external_script_controller_ = CreateHeadlessScriptController();
   scrim_manager_->Show();
   external_script_controller_->StartScript(
       params_map,
@@ -185,8 +185,9 @@
 
 std::unique_ptr<autofill_assistant::HeadlessScriptController>
 ApcClientImpl::CreateHeadlessScriptController() {
+  DCHECK(scrim_manager_);
   apc_external_action_delegate_ = std::make_unique<ApcExternalActionDelegate>(
-      side_panel_coordinator_.get());
+      side_panel_coordinator_.get(), scrim_manager_.get());
   apc_external_action_delegate_->SetupDisplay();
   apc_external_action_delegate_->ShowStartingScreen(url_);
 
diff --git a/chrome/browser/autofill_assistant/password_change/apc_client_impl_unittest.cc b/chrome/browser/autofill_assistant/password_change/apc_client_impl_unittest.cc
index f0761dd1..ab0c20fc 100644
--- a/chrome/browser/autofill_assistant/password_change/apc_client_impl_unittest.cc
+++ b/chrome/browser/autofill_assistant/password_change/apc_client_impl_unittest.cc
@@ -14,8 +14,8 @@
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/autofill_assistant/password_change/apc_onboarding_coordinator_impl.h"
 #include "chrome/browser/autofill_assistant/password_change/mock_apc_onboarding_coordinator.h"
+#include "chrome/browser/ui/autofill_assistant/password_change/mock_apc_scrim_manager.h"
 #include "chrome/browser/ui/autofill_assistant/password_change/mock_assistant_side_panel_coordinator.h"
-#include "chrome/browser/ui/autofill_assistant/password_change/mock_scrim_manager.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "components/autofill_assistant/browser/public/mock_headless_script_controller.h"
diff --git a/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.cc b/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.cc
index 1aa25d13..fc5f798 100644
--- a/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.cc
+++ b/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.cc
@@ -12,6 +12,7 @@
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/autofill_assistant/password_change/apc_scrim_manager.h"
 #include "chrome/browser/ui/autofill_assistant/password_change/assistant_display_delegate.h"
 #include "chrome/browser/ui/autofill_assistant/password_change/password_change_run_controller.h"
 #include "chrome/browser/ui/autofill_assistant/password_change/password_change_run_display.h"
@@ -19,6 +20,7 @@
 #include "components/autofill_assistant/browser/public/external_action.pb.h"
 #include "components/autofill_assistant/browser/public/external_action_delegate.h"
 #include "components/autofill_assistant/browser/public/password_change/proto/actions.pb.h"
+#include "components/autofill_assistant/browser/public/rectf.h"
 #include "components/url_formatter/url_formatter.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
@@ -26,9 +28,12 @@
 using autofill_assistant::password_change::GenericPasswordChangeSpecification;
 
 ApcExternalActionDelegate::ApcExternalActionDelegate(
-    AssistantDisplayDelegate* display_delegate)
-    : display_delegate_(display_delegate) {
+    AssistantDisplayDelegate* display_delegate,
+    ApcScrimManager* apc_scrim_manager)
+    : display_delegate_(display_delegate),
+      apc_scrim_manager_(apc_scrim_manager) {
   DCHECK(display_delegate_);
+  DCHECK(apc_scrim_manager_);
 }
 
 ApcExternalActionDelegate::~ApcExternalActionDelegate() = default;
@@ -98,8 +103,18 @@
   model_before_interrupt_.reset();
 }
 
-// PasswordChangeRunController
+void ApcExternalActionDelegate::OnTouchableAreaChanged(
+    const autofill_assistant::RectF& visual_viewport,
+    const std::vector<autofill_assistant::RectF>& touchable_areas,
+    const std::vector<autofill_assistant::RectF>& restricted_areas) {
+  if (!touchable_areas.empty()) {
+    apc_scrim_manager_->Hide();
+  } else {
+    apc_scrim_manager_->Show();
+  }
+}
 
+// PasswordChangeRunController
 void ApcExternalActionDelegate::SetTopIcon(
     autofill_assistant::password_change::TopIcon top_icon) {
   DCHECK(password_change_run_display_);
diff --git a/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.h b/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.h
index a7e83ee..c04be5aca 100644
--- a/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.h
+++ b/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.h
@@ -16,6 +16,11 @@
 
 class PasswordChangeRunDisplay;
 class AssistantDisplayDelegate;
+class ApcScrimManager;
+
+namespace autofill_assistant {
+struct RectF;
+}
 
 // Receives actions from the `HeadlessScriptController` and passes them on an
 // implementation of a `PasswordChangeRunDisplay`.
@@ -26,8 +31,8 @@
     : public autofill_assistant::ExternalActionDelegate,
       public PasswordChangeRunController {
  public:
-  explicit ApcExternalActionDelegate(
-      AssistantDisplayDelegate* display_delegate);
+  explicit ApcExternalActionDelegate(AssistantDisplayDelegate* display_delegate,
+                                     ApcScrimManager* apc_scrim_manager);
   ApcExternalActionDelegate(const ApcExternalActionDelegate&) = delete;
   ApcExternalActionDelegate& operator=(const ApcExternalActionDelegate&) =
       delete;
@@ -46,6 +51,11 @@
   void OnInterruptStarted() override;
   void OnInterruptFinished() override;
 
+  void OnTouchableAreaChanged(
+      const autofill_assistant::RectF& visual_viewport,
+      const std::vector<autofill_assistant::RectF>& touchable_areas,
+      const std::vector<autofill_assistant::RectF>& restricted_areas) override;
+
   // PasswordChangeRunController:
   void SetTopIcon(
       autofill_assistant::password_change::TopIcon top_icon) override;
@@ -122,6 +132,9 @@
   // The display where we render the UI for a password change run.
   raw_ptr<AssistantDisplayDelegate> display_delegate_ = nullptr;
 
+  // The scrim manager to update the overlay and html elements showcasting.
+  raw_ptr<ApcScrimManager> apc_scrim_manager_ = nullptr;
+
   // Factory for weak pointers to this class.
   base::WeakPtrFactory<PasswordChangeRunController> weak_ptr_factory_{this};
 };
diff --git a/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate_unittest.cc b/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate_unittest.cc
index 494609c..c23d5f8 100644
--- a/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate_unittest.cc
+++ b/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate_unittest.cc
@@ -11,12 +11,14 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/mock_callback.h"
+#include "chrome/browser/ui/autofill_assistant/password_change/mock_apc_scrim_manager.h"
 #include "chrome/browser/ui/autofill_assistant/password_change/mock_assistant_display_delegate.h"
 #include "chrome/browser/ui/autofill_assistant/password_change/mock_password_change_run_display.h"
 #include "chrome/browser/ui/autofill_assistant/password_change/password_change_run_display.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/autofill_assistant/browser/public/external_action.pb.h"
 #include "components/autofill_assistant/browser/public/password_change/proto/actions.pb.h"
+#include "components/autofill_assistant/browser/public/rectf.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -145,8 +147,8 @@
 class ApcExternalActionDelegateTest : public ::testing::Test {
  public:
   ApcExternalActionDelegateTest() {
-    action_delegate_ =
-        std::make_unique<ApcExternalActionDelegate>(display_delegate());
+    action_delegate_ = std::make_unique<ApcExternalActionDelegate>(
+        display_delegate(), apc_scrim_manager());
   }
 
   void SetUp() override {
@@ -158,6 +160,8 @@
     return &display_delegate_;
   }
 
+  MockApcScrimManager* apc_scrim_manager() { return &apc_scrim_manager_; }
+
   MockPasswordChangeRunDisplay* display() { return &display_; }
 
   ApcExternalActionDelegate* action_delegate() {
@@ -168,6 +172,7 @@
   // Supporting objects for testing.
   MockAssistantDisplayDelegate display_delegate_;
   MockPasswordChangeRunDisplay display_;
+  MockApcScrimManager apc_scrim_manager_;
 
   // The object to be tested.
   std::unique_ptr<ApcExternalActionDelegate> action_delegate_;
@@ -204,6 +209,24 @@
   action_delegate()->OnInterruptFinished();
 }
 
+TEST_F(ApcExternalActionDelegateTest, OnTouchableAreaChangedShowAndHideScrim) {
+  autofill_assistant::RectF visual_viewport;
+  std::vector<autofill_assistant::RectF> touchable_areas;
+  std::vector<autofill_assistant::RectF> restricted_areas;
+
+  // Hides the scrim when `touchable_areas` is not empty.
+  touchable_areas.emplace_back();
+  EXPECT_CALL(*apc_scrim_manager(), Hide);
+  action_delegate()->OnTouchableAreaChanged(visual_viewport, touchable_areas,
+                                            restricted_areas);
+
+  // Shows the scrim when `touchable_areas` is not empty.
+  touchable_areas.clear();
+  EXPECT_CALL(*apc_scrim_manager(), Show);
+  action_delegate()->OnTouchableAreaChanged(visual_viewport, touchable_areas,
+                                            restricted_areas);
+}
+
 TEST_F(ApcExternalActionDelegateTest, ShowStartingScreen) {
   const GURL url(kUrl);
 
diff --git a/chrome/browser/background/background_mode_manager_unittest.cc b/chrome/browser/background/background_mode_manager_unittest.cc
index 15e6018..b81cf22f 100644
--- a/chrome/browser/background/background_mode_manager_unittest.cc
+++ b/chrome/browser/background/background_mode_manager_unittest.cc
@@ -282,9 +282,11 @@
  protected:
   // From views::MenuModelAdapter::IsCommandEnabled with modification.
   bool IsCommandEnabled(ui::MenuModel* model, int id) const {
-    size_t index = 0;
-    return ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index) &&
-           model->IsEnabledAt(index);
+    int index = 0;
+    if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index))
+      return model->IsEnabledAt(index);
+
+    return false;
   }
 
   std::unique_ptr<TestBackgroundModeManager> manager_;
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
index c480da0..2dfc2c7 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
@@ -792,21 +792,18 @@
     return;
   }
 
-  api::file_manager_private::DriveQuotaMetadata quotaMetadata;
+  base::Value::Dict quotaMetadata;
 
-  quotaMetadata.user_type =
-      usage->user_type == drivefs::mojom::UserType::kUnmanaged
-          ? api::file_manager_private::UserType::USER_TYPE_KUNMANAGED
-          : api::file_manager_private::UserType::USER_TYPE_KORGANIZATION;
-  quotaMetadata.used_user_bytes = static_cast<double>(usage->used_user_bytes);
-  quotaMetadata.total_user_bytes = static_cast<double>(usage->total_user_bytes);
-  quotaMetadata.organization_limit_exceeded =
-      usage->organization_limit_exceeded;
-  quotaMetadata.organization_name = usage->organization_name;
+  quotaMetadata.Set("userType", static_cast<int>(usage->user_type));
+  quotaMetadata.Set("usedUserBytes",
+                    static_cast<double>(usage->used_user_bytes));
+  quotaMetadata.Set("totalUserBytes",
+                    static_cast<double>(usage->total_user_bytes));
+  quotaMetadata.Set("organizationLimitExceeded",
+                    usage->organization_limit_exceeded);
+  quotaMetadata.Set("organizationName", usage->organization_name);
 
-  Respond(ArgumentList(
-      api::file_manager_private::GetDriveQuotaMetadata::Results::Create(
-          quotaMetadata)));
+  Respond(OneArgument(base::Value(std::move(quotaMetadata))));
 }
 
 ExtensionFunction::ResponseAction
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc
index a2461c4..d4c18a2 100644
--- a/chrome/browser/client_hints/client_hints_browsertest.cc
+++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -506,14 +506,10 @@
         https_server_.GetURL("/meta_equiv_delegate_ch_delegation_bar.html");
     http_equiv_accept_ch_delegation_merge_ =
         https_server_.GetURL("/http_equiv_accept_ch_delegation_merge.html");
-    meta_name_accept_ch_delegation_merge_ =
-        https_server_.GetURL("/meta_name_accept_ch_delegation_merge.html");
     meta_equiv_delegate_ch_delegation_merge_ =
         https_server_.GetURL("/meta_equiv_delegate_ch_delegation_merge.html");
     http_equiv_accept_ch_merge_ =
         https_server_.GetURL("/http_equiv_accept_ch_merge.html");
-    meta_name_accept_ch_merge_ =
-        https_server_.GetURL("/meta_name_accept_ch_merge.html");
     meta_equiv_delegate_ch_merge_ =
         https_server_.GetURL("/meta_equiv_delegate_ch_merge.html");
 
@@ -740,9 +736,6 @@
   const GURL& http_equiv_accept_ch_delegation_merge() const {
     return http_equiv_accept_ch_delegation_merge_;
   }
-  const GURL& meta_name_accept_ch_delegation_merge() const {
-    return meta_name_accept_ch_delegation_merge_;
-  }
   const GURL& meta_equiv_delegate_ch_delegation_merge() const {
     return meta_equiv_delegate_ch_delegation_merge_;
   }
@@ -751,9 +744,6 @@
   const GURL& http_equiv_accept_ch_merge() const {
     return http_equiv_accept_ch_merge_;
   }
-  const GURL& meta_name_accept_ch_merge() const {
-    return meta_name_accept_ch_merge_;
-  }
   const GURL& meta_equiv_delegate_ch_merge() const {
     return meta_equiv_delegate_ch_merge_;
   }
@@ -1261,10 +1251,8 @@
   GURL meta_name_accept_ch_delegation_bar_;
   GURL meta_equiv_delegate_ch_delegation_bar_;
   GURL http_equiv_accept_ch_delegation_merge_;
-  GURL meta_name_accept_ch_delegation_merge_;
   GURL meta_equiv_delegate_ch_delegation_merge_;
   GURL http_equiv_accept_ch_merge_;
-  GURL meta_name_accept_ch_merge_;
   GURL meta_equiv_delegate_ch_merge_;
   GURL without_accept_ch_cross_origin_;
 
@@ -1349,7 +1337,7 @@
   base::HistogramTester histogram_tester;
 
   SetClientHintExpectationsOnMainFrame(false);
-  SetClientHintExpectationsOnSubresources(true);
+  SetClientHintExpectationsOnSubresources(false);
 
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
   histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
@@ -1932,13 +1920,11 @@
   // Go to a page which delegates hints to `foo.com`.
   GURL gurl = meta_name_accept_ch_delegation_foo();
   SetClientHintExpectationsOnMainFrame(false);
-  SetClientHintExpectationsOnSubresources(true);
+  SetClientHintExpectationsOnSubresources(false);
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
-  EXPECT_EQ(expected_client_hints_number * 2,
-            count_client_hints_headers_seen());
+  EXPECT_EQ(0u, count_client_hints_headers_seen());
   EXPECT_EQ(4u, third_party_unique_request_count_seen());
-  EXPECT_EQ(expected_requested_third_party_client_hints_number * 2 +
-                expected_default_third_party_client_hints_number * 2,
+  EXPECT_EQ(expected_default_third_party_client_hints_number * 4,
             third_party_client_hints_count_seen_on_unique_request());
 }
 
@@ -1972,13 +1958,11 @@
   // Go to a page which delegates hints to `bar.com`.
   GURL gurl = meta_name_accept_ch_delegation_bar();
   SetClientHintExpectationsOnMainFrame(false);
-  SetClientHintExpectationsOnSubresources(true);
+  SetClientHintExpectationsOnSubresources(false);
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
-  EXPECT_EQ(expected_client_hints_number * 2,
-            count_client_hints_headers_seen());
+  EXPECT_EQ(0u, count_client_hints_headers_seen());
   EXPECT_EQ(4u, third_party_unique_request_count_seen());
-  EXPECT_EQ(expected_requested_third_party_client_hints_number * 2 +
-                expected_default_third_party_client_hints_number * 2,
+  EXPECT_EQ(expected_default_third_party_client_hints_number * 4,
             third_party_client_hints_count_seen_on_unique_request());
 }
 
@@ -2010,19 +1994,6 @@
             third_party_client_hints_count_seen_on_unique_request());
 }
 
-IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, DelegateAndMerge_MetaName) {
-  // Go to a page which delegates hints in HTTP and HTML.
-  GURL gurl = meta_name_accept_ch_delegation_merge();
-  SetClientHintExpectationsOnMainFrame(false);
-  SetClientHintExpectationsOnSubresources(true);
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
-  EXPECT_EQ(expected_client_hints_number * 2,
-            count_client_hints_headers_seen());
-  EXPECT_EQ(4u, third_party_unique_request_count_seen());
-  EXPECT_EQ(expected_requested_third_party_client_hints_number * 4,
-            third_party_client_hints_count_seen_on_unique_request());
-}
-
 IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, DelegateAndMerge_MetaDelegate) {
   // Go to a page which delegates hints in HTTP and HTML.
   GURL gurl = meta_equiv_delegate_ch_delegation_merge();
@@ -2047,17 +2018,6 @@
   EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
 }
 
-IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, MergeAcceptCH_MetaName) {
-  // Go to page where some hints are enabled by headers, some by
-  // http-equiv. It shouldn't get hints itself (due to first visit),
-  // but subresources should get all the client hints.
-  GURL gurl = meta_name_accept_ch_merge();
-  SetClientHintExpectationsOnMainFrame(false);
-  SetClientHintExpectationsOnSubresources(true);
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
-  EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
-}
-
 IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, MergeAcceptCH_MetaDelegate) {
   // Go to page where some hints are enabled by headers, some by
   // http-equiv. It shouldn't get hints itself (due to first visit),
@@ -2164,7 +2124,8 @@
   base::HistogramTester histogram_tester;
 
   SetClientHintExpectationsOnMainFrame(false);
-  SetClientHintExpectationsOnSubresources(true);
+  SetClientHintExpectationsOnSubresources(GetParam() !=
+                                          network::MetaCHType::NameAcceptCH);
 
   // Add client hints for the embedded test server.
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
@@ -2175,7 +2136,10 @@
   EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
   EXPECT_EQ(2u, count_ua_platform_client_hints_headers_seen());
   EXPECT_EQ(0u, count_save_data_client_hints_headers_seen());
-  EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
+  EXPECT_EQ(GetParam() == network::MetaCHType::NameAcceptCH
+                ? 0u
+                : expected_client_hints_number,
+            count_client_hints_headers_seen());
 
   // Requests to third party servers should not have client hints attached.
   EXPECT_EQ(1u, third_party_request_count_seen());
@@ -3087,13 +3051,17 @@
           gurl, GURL(), ContentSettingsType::COOKIES, CONTENT_SETTING_BLOCK);
   base::RunLoop().RunUntilIdle();
 
-  SetClientHintExpectationsOnSubresources(true);
+  SetClientHintExpectationsOnSubresources(GetParam() !=
+                                          network::MetaCHType::NameAcceptCH);
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
   EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
   EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
   EXPECT_EQ(2u, count_ua_platform_client_hints_headers_seen());
   EXPECT_EQ(0u, count_save_data_client_hints_headers_seen());
-  EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
+  EXPECT_EQ(GetParam() == network::MetaCHType::NameAcceptCH
+                ? 0u
+                : expected_client_hints_number,
+            count_client_hints_headers_seen());
   EXPECT_EQ(1u, third_party_request_count_seen());
   EXPECT_EQ(3u, third_party_client_hints_count_seen());
 
@@ -3281,8 +3249,8 @@
   }
 
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
-
-  web_feature_waiter->Wait();
+  if (GetParam() != network::MetaCHType::NameAcceptCH)
+    web_feature_waiter->Wait();
 }
 
 class CriticalClientHintsBrowserTest : public InProcessBrowserTest {
diff --git a/chrome/browser/download/download_shelf_context_menu.cc b/chrome/browser/download/download_shelf_context_menu.cc
index 76c240d..8a2f9d8 100644
--- a/chrome/browser/download/download_shelf_context_menu.cc
+++ b/chrome/browser/download/download_shelf_context_menu.cc
@@ -52,7 +52,7 @@
 
   for (int command_int = 1; command_int < DownloadCommands::Command::MAX;
        command_int++) {
-    if (model->GetIndexOfCommandId(command_int).has_value() &&
+    if (model->GetIndexOfCommandId(command_int) != -1 &&
         IsCommandIdEnabled(command_int)) {
       DownloadCommands::Command download_command =
           static_cast<DownloadCommands::Command>(command_int);
diff --git a/chrome/browser/extensions/activity_log/activity_actions.cc b/chrome/browser/extensions/activity_log/activity_actions.cc
index 6f703477..cab9c8b 100644
--- a/chrome/browser/extensions/activity_log/activity_actions.cc
+++ b/chrome/browser/extensions/activity_log/activity_actions.cc
@@ -15,7 +15,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/values.h"
 #include "chrome/browser/extensions/activity_log/activity_action_constants.h"
 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h"
 #include "extensions/common/constants.h"
@@ -30,7 +29,7 @@
 
 namespace {
 
-std::string Serialize(const base::Value* value) {
+std::string Serialize(absl::optional<base::ValueView> value) {
   std::string value_as_text;
   if (!value) {
     value_as_text = "null";
@@ -54,9 +53,6 @@
       time_(time),
       action_type_(action_type),
       api_name_(api_name),
-      page_incognito_(false),
-      arg_incognito_(false),
-      count_(0),
       action_id_(action_id) {}
 
 Action::~Action() {}
@@ -68,8 +64,7 @@
   auto clone = base::MakeRefCounted<Action>(
       extension_id(), time(), action_type(), api_name(), action_id());
   if (args()) {
-    clone->set_args(
-        base::ListValue::From(base::Value::ToUniquePtrValue(args()->Clone())));
+    clone->set_args(args()->Clone());
   }
   clone->set_page_url(page_url());
   clone->set_page_title(page_title());
@@ -77,19 +72,19 @@
   clone->set_arg_url(arg_url());
   clone->set_arg_incognito(arg_incognito());
   if (other())
-    clone->set_other(base::WrapUnique(other()->DeepCopy()));
+    clone->set_other(other()->Clone());
   return clone;
 }
 
-void Action::set_args(std::unique_ptr<base::ListValue> args) {
+void Action::set_args(absl::optional<base::Value::List> args) {
   args_ = std::move(args);
 }
 
-base::ListValue* Action::mutable_args() {
-  if (!args_.get()) {
-    args_ = std::make_unique<base::ListValue>();
-  }
-  return args_.get();
+base::Value::List& Action::mutable_args() {
+  if (!args_)
+    args_.emplace();
+
+  return *args_;
 }
 
 void Action::set_page_url(const GURL& page_url) {
@@ -100,15 +95,15 @@
   arg_url_ = arg_url;
 }
 
-void Action::set_other(std::unique_ptr<base::DictionaryValue> other) {
+void Action::set_other(absl::optional<base::Value::Dict> other) {
   other_ = std::move(other);
 }
 
-base::DictionaryValue* Action::mutable_other() {
-  if (!other_.get()) {
-    other_ = std::make_unique<base::DictionaryValue>();
-  }
-  return other_.get();
+base::Value::Dict& Action::mutable_other() {
+  if (!other_)
+    other_.emplace();
+
+  return *other_;
 }
 
 std::string Action::SerializePageUrl() const {
@@ -192,20 +187,19 @@
     std::unique_ptr<ExtensionActivity::Other> other_field(
         new ExtensionActivity::Other);
     if (absl::optional<bool> prerender =
-            other()->FindBoolKey(constants::kActionPrerender)) {
+            other()->FindBool(constants::kActionPrerender)) {
       other_field->prerender = std::make_unique<bool>(*prerender);
     }
-    const base::DictionaryValue* web_request;
-    if (other()->GetDictionaryWithoutPathExpansion(constants::kActionWebRequest,
-                                                   &web_request)) {
+    if (const base::Value::Dict* web_request =
+            other()->FindDict(constants::kActionWebRequest)) {
       other_field->web_request = std::make_unique<std::string>(
-          ActivityLogPolicy::Util::Serialize(web_request));
+          ActivityLogPolicy::Util::Serialize(*web_request));
     }
-    const std::string* extra = other()->FindStringKey(constants::kActionExtra);
+    const std::string* extra = other()->FindString(constants::kActionExtra);
     if (extra)
       other_field->extra = std::make_unique<std::string>(*extra);
     if (absl::optional<int> dom_verb =
-            other()->FindIntKey(constants::kActionDomVerb)) {
+            other()->FindInt(constants::kActionDomVerb)) {
       switch (static_cast<DomActionType::Type>(dom_verb.value())) {
         case DomActionType::GETTER:
           other_field->dom_verb =
@@ -278,8 +272,8 @@
   }
 
   result += " API=" + api_name_;
-  if (args_.get()) {
-    result += " ARGS=" + Serialize(args_.get());
+  if (args_) {
+    result += " ARGS=" + Serialize(*args_);
   }
   if (page_url_.is_valid()) {
     if (page_incognito_)
@@ -289,7 +283,7 @@
   }
   if (!page_title_.empty()) {
     base::Value title(page_title_);
-    result += " PAGE_TITLE=" + Serialize(&title);
+    result += " PAGE_TITLE=" + Serialize(title);
   }
   if (arg_url_.is_valid()) {
     if (arg_incognito_)
@@ -297,8 +291,8 @@
     else
       result += " ARG_URL=" + arg_url_.spec();
   }
-  if (other_.get()) {
-    result += " OTHER=" + Serialize(other_.get());
+  if (other_) {
+    result += " OTHER=" + Serialize(*other_);
   }
 
   result += base::StringPrintf(" COUNT=%d", count_);
diff --git a/chrome/browser/extensions/activity_log/activity_actions.h b/chrome/browser/extensions/activity_log/activity_actions.h
index 35ce14c..00ff1ef 100644
--- a/chrome/browser/extensions/activity_log/activity_actions.h
+++ b/chrome/browser/extensions/activity_log/activity_actions.h
@@ -12,15 +12,11 @@
 
 #include "base/memory/ref_counted_memory.h"
 #include "base/time/time.h"
+#include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/api/activity_log_private.h"
 #include "url/gurl.h"
 
-namespace base {
-class ListValue;
-class DictionaryValue;
-}
-
 namespace extensions {
 
 // This is the interface for extension actions that are to be recorded in
@@ -79,9 +75,9 @@
   // mutable_args() returns a pointer to the list stored in the Action which
   // can be modified in place; if the list was null an empty list is created
   // first.
-  const base::ListValue* args() const { return args_.get(); }
-  void set_args(std::unique_ptr<base::ListValue> args);
-  base::ListValue* mutable_args();
+  const absl::optional<base::Value::List>& args() const { return args_; }
+  void set_args(absl::optional<base::Value::List> args);
+  base::Value::List& mutable_args();
 
   // The URL of the page which was modified or accessed.
   const GURL& page_url() const { return page_url_; }
@@ -103,9 +99,9 @@
   void set_arg_incognito(bool incognito) { arg_incognito_ = incognito; }
 
   // A dictionary where any additional data can be stored.
-  const base::DictionaryValue* other() const { return other_.get(); }
-  void set_other(std::unique_ptr<base::DictionaryValue> other);
-  base::DictionaryValue* mutable_other();
+  const absl::optional<base::Value::Dict>& other() const { return other_; }
+  void set_other(absl::optional<base::Value::Dict> other);
+  base::Value::Dict& mutable_other();
 
   // An ID that identifies an action stored in the Activity Log database. If the
   // action is not retrieved from the database, e.g., live stream, then the ID
@@ -140,14 +136,14 @@
   base::Time time_;
   ActionType action_type_;
   std::string api_name_;
-  std::unique_ptr<base::ListValue> args_;
+  absl::optional<base::Value::List> args_;
   GURL page_url_;
   std::string page_title_;
-  bool page_incognito_;
+  bool page_incognito_{false};
   GURL arg_url_;
-  bool arg_incognito_;
-  std::unique_ptr<base::DictionaryValue> other_;
-  int count_;
+  bool arg_incognito_{false};
+  absl::optional<base::Value::Dict> other_;
+  int count_{0};
   int64_t action_id_;
 };
 
diff --git a/chrome/browser/extensions/activity_log/activity_database_unittest.cc b/chrome/browser/extensions/activity_log/activity_database_unittest.cc
index 276e5c3..d618192f 100644
--- a/chrome/browser/extensions/activity_log/activity_database_unittest.cc
+++ b/chrome/browser/extensions/activity_log/activity_database_unittest.cc
@@ -263,7 +263,7 @@
   ActivityDatabase* activity_db = new ActivityDatabase(delegate);
   scoped_refptr<Action> action = new Action(
       "punky", base::Time::Now(), Action::ACTION_API_CALL, "brewster");
-  action->mutable_args()->Append("woof");
+  action->mutable_args().Append("woof");
   delegate->Record(activity_db, action);
   activity_db->Close();
 }
diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc
index 417b394..1f9e4952 100644
--- a/chrome/browser/extensions/activity_log/activity_log.cc
+++ b/chrome/browser/extensions/activity_log/activity_log.cc
@@ -262,8 +262,7 @@
   int url_index = api_info->arg_url_index;
 
   if (!action->args() || url_index < 0 ||
-      static_cast<size_t>(url_index) >=
-          action->args()->GetListDeprecated().size())
+      static_cast<size_t>(url_index) >= action->args()->size())
     return;
 
   // Do not overwrite an existing arg_url value in the Action, so that callers
@@ -271,7 +270,7 @@
   if (action->arg_url().is_valid())
     return;
 
-  base::Value::ListView args_list = action->mutable_args()->GetListDeprecated();
+  base::Value::List& args_list = action->mutable_args();
 
   GURL arg_url;
   bool arg_incognito = action->page_incognito();
@@ -297,11 +296,12 @@
       // valid URL.
       if (args_list[url_index].is_dict()) {
         const std::string* url_string =
-            args_list[url_index].FindStringPath(api_info->arg_url_dict_path);
+            args_list[url_index].GetDict().FindStringByDottedPath(
+                api_info->arg_url_dict_path);
         if (url_string &&
             ResolveUrl(action->page_url(), *url_string, &arg_url)) {
-          args_list[url_index].SetStringPath(api_info->arg_url_dict_path,
-                                             kArgUrlPlaceholder);
+          args_list[url_index].GetDict().SetByDottedPath(
+              api_info->arg_url_dict_path, kArgUrlPlaceholder);
         }
       }
       break;
@@ -320,8 +320,7 @@
         if (arg_url.is_valid())
           args_list[url_index] = base::Value(kArgUrlPlaceholder);
       } else if (args_list[url_index].is_list()) {
-        base::Value::ListView tab_list =
-            args_list[url_index].GetListDeprecated();
+        base::Value::List& tab_list = args_list[url_index].GetList();
         // A list of possible IDs to translate.  Work through in reverse order
         // so the last one translated is left in arg_url.
         int extracted_index = -1;  // Which list item is copied to arg_url?
@@ -388,8 +387,7 @@
 
   auto action = base::MakeRefCounted<Action>(extension_id, base::Time::Now(),
                                              type, activity_name);
-  action->set_args(
-      base::ListValue::From(std::make_unique<base::Value>(args.Clone())));
+  action->set_args(args.Clone());
   activity_log->LogAction(action);
 }
 
@@ -398,9 +396,6 @@
                  const std::string& extension_id,
                  const std::string& event_name,
                  const base::Value::List& args) {
-  auto list_value = std::make_unique<base::ListValue>();
-  for (const auto& value : args)
-    list_value->Append(value.Clone());
   LogApiActivity(browser_context, extension_id, event_name, args,
                  Action::ACTION_API_EVENT);
 }
@@ -433,7 +428,7 @@
       extension_id, base::Time::Now(), Action::ACTION_WEB_REQUEST, api_call);
   action->set_page_url(url);
   action->set_page_incognito(is_incognito);
-  action->mutable_other()->SetKey(
+  action->mutable_other().Set(
       activity_log_constants::kActionWebRequest,
       base::Value::FromUniquePtrValue(std::move(details)));
   activity_log->LogAction(action);
@@ -655,10 +650,10 @@
       base::StartsWith(action->api_name(), kDomXhrPrefix,
                        base::CompareCase::SENSITIVE) &&
       action->other()) {
-    base::DictionaryValue* other = action->mutable_other();
-    absl::optional<int> dom_verb = other->FindIntKey(constants::kActionDomVerb);
+    base::Value::Dict& other = action->mutable_other();
+    absl::optional<int> dom_verb = other.FindInt(constants::kActionDomVerb);
     if (dom_verb == DomActionType::METHOD)
-      other->SetIntKey(constants::kActionDomVerb, DomActionType::XHR);
+      other.Set(constants::kActionDomVerb, DomActionType::XHR);
   }
   if (IsDatabaseEnabled() && database_policy_)
     database_policy_->ProcessAction(action);
@@ -704,9 +699,9 @@
               profile_);
       if (no_state_prefetch_manager &&
           no_state_prefetch_manager->IsWebContentsPrefetching(web_contents))
-        action->mutable_other()->SetBoolKey(constants::kActionPrerender, true);
+        action->mutable_other().Set(constants::kActionPrerender, true);
       for (auto it2 = it->second.begin(); it2 != it->second.end(); ++it2) {
-        action->mutable_args()->Append(*it2);
+        action->mutable_args().Append(*it2);
       }
       LogAction(action);
     }
diff --git a/chrome/browser/extensions/activity_log/activity_log_policy.cc b/chrome/browser/extensions/activity_log/activity_log_policy.cc
index 2e36541..45ebb578 100644
--- a/chrome/browser/extensions/activity_log/activity_log_policy.cc
+++ b/chrome/browser/extensions/activity_log/activity_log_policy.cc
@@ -65,7 +65,8 @@
 }
 
 // static
-std::string ActivityLogPolicy::Util::Serialize(const base::Value* value) {
+std::string ActivityLogPolicy::Util::Serialize(
+    absl::optional<base::ValueView> value) {
   std::string value_as_text;
   if (value) {
     JSONStringValueSerializer serializer(&value_as_text);
@@ -105,11 +106,10 @@
   // Clear WebRequest details; only keep a record of which types of
   // modifications were performed.
   if (action->action_type() == Action::ACTION_WEB_REQUEST) {
-    base::DictionaryValue* details = NULL;
-    if (action->mutable_other()->GetDictionary(constants::kActionWebRequest,
-                                               &details)) {
-      for (auto detail : details->DictItems()) {
-        details->SetBoolPath(detail.first, true);
+    if (base::Value::Dict* details =
+            action->mutable_other().FindDict(constants::kActionWebRequest)) {
+      for (auto detail : *details) {
+        details->SetByDottedPath(detail.first, true);
       }
     }
   }
@@ -120,7 +120,7 @@
                                              scoped_refptr<Action> action) {
   if (api_allowlist.find(std::make_pair(
           action->action_type(), action->api_name())) == api_allowlist.end()) {
-    action->set_args(std::unique_ptr<base::ListValue>());
+    action->set_args(absl::nullopt);
   }
 }
 
diff --git a/chrome/browser/extensions/activity_log/activity_log_policy.h b/chrome/browser/extensions/activity_log/activity_log_policy.h
index d0a5415..aa58b7f6 100644
--- a/chrome/browser/extensions/activity_log/activity_log_policy.h
+++ b/chrome/browser/extensions/activity_log/activity_log_policy.h
@@ -102,7 +102,7 @@
 
     // Serialize a Value as a JSON string.  Returns an empty string if value is
     // null.
-    static std::string Serialize(const base::Value* value);
+    static std::string Serialize(absl::optional<base::ValueView> value);
 
     // Removes potentially privacy-sensitive data that should not be logged.
     // This should generally be called on an Action before logging, unless
diff --git a/chrome/browser/extensions/activity_log/activity_log_policy_unittest.cc b/chrome/browser/extensions/activity_log/activity_log_policy_unittest.cc
index 28d6eb4..aac2eac 100644
--- a/chrome/browser/extensions/activity_log/activity_log_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/activity_log_policy_unittest.cc
@@ -23,7 +23,7 @@
                  base::Time::Now(),
                  Action::ACTION_API_CALL,
                  "tabs.executeScript");
-  action->mutable_args()->Append("woof");
+  action->mutable_args().Append("woof");
   action->set_page_url(GURL("http://www.google.com/"));
   action->set_page_incognito(true);
   action->set_page_title("private");
@@ -43,14 +43,13 @@
 TEST_F(ActivityLogPolicyUtilTest, StripPrivacySensitiveWebRequest) {
   scoped_refptr<Action> action = new Action(
       "punky", base::Time::Now(), Action::ACTION_WEB_REQUEST, "webRequest");
-  action->mutable_other()->Set(
-      activity_log_constants::kActionWebRequest,
-      DictionaryBuilder()
-          .Set(activity_log_web_request_constants::kNewUrlKey,
-               "http://www.youtube.com/")
-          .Set(activity_log_web_request_constants::kAddedRequestHeadersKey,
-               ListBuilder().Append("arg").Build())
-          .Build());
+  base::Value::Dict root;
+  root.Set(activity_log_web_request_constants::kNewUrlKey,
+           "http://www.youtube.com/");
+  root.Set(activity_log_web_request_constants::kAddedRequestHeadersKey,
+           base::Value::List());
+  action->mutable_other().Set(activity_log_constants::kActionWebRequest,
+                              std::move(root));
 
   ActivityLogPolicy::Util::StripPrivacySensitiveFields(action);
 
@@ -71,14 +70,14 @@
                  base::Time::Now(),
                  Action::ACTION_API_CALL,
                  "tabs.executeScript");
-  action->mutable_args()->Append("woof");
+  action->mutable_args().Append("woof");
   ActivityLogPolicy::Util::StripArguments(allowlist, action);
   ASSERT_EQ("[\"woof\"]", ActivityLogPolicy::Util::Serialize(action->args()));
 
   // Not in allowlist: stripped.
   action = new Action(
       "punky", base::Time::Now(), Action::ACTION_API_CALL, "tabs.create");
-  action->mutable_args()->Append("woof");
+  action->mutable_args().Append("woof");
   ActivityLogPolicy::Util::StripArguments(allowlist, action);
   ASSERT_EQ("", ActivityLogPolicy::Util::Serialize(action->args()));
 }
diff --git a/chrome/browser/extensions/activity_log/activity_log_unittest.cc b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
index 4edd9a19..54a30c9 100644
--- a/chrome/browser/extensions/activity_log/activity_log_unittest.cc
+++ b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
@@ -225,8 +225,6 @@
 
   static void RetrieveActions_ArgUrlExtraction(
       std::unique_ptr<std::vector<scoped_refptr<Action>>> i) {
-    const base::DictionaryValue* other = NULL;
-
     ASSERT_EQ(4U, i->size());
     scoped_refptr<Action> action = i->at(0);
     ASSERT_EQ("XMLHttpRequest.open", action->api_name());
@@ -236,10 +234,10 @@
     // Test that the dom_verb field was changed to XHR (from METHOD).  This
     // could be tested on all retrieved XHR actions but it would be redundant,
     // so just test once.
-    other = action->other();
-    ASSERT_TRUE(other);
+    ASSERT_TRUE(action->other());
+    const base::Value::Dict& other = *action->other();
     absl::optional<int> dom_verb =
-        other->FindIntKey(activity_log_constants::kActionDomVerb);
+        other.FindInt(activity_log_constants::kActionDomVerb);
     ASSERT_EQ(DomActionType::XHR, dom_verb);
 
     action = i->at(1);
@@ -264,8 +262,6 @@
   static void RetrieveActions_ArgUrlApiCalls(
       std::unique_ptr<std::vector<scoped_refptr<Action>>> actions) {
     size_t api_calls_size = std::size(kUrlApiCalls);
-    const base::DictionaryValue* other = NULL;
-
     ASSERT_EQ(api_calls_size, actions->size());
 
     for (size_t i = 0; i < actions->size(); i++) {
@@ -276,10 +272,10 @@
       ASSERT_EQ("[\"\\u003Carg_url>\"]",
                 ActivityLogPolicy::Util::Serialize(action->args()));
       ASSERT_EQ("http://www.google.co.uk/", action->arg_url().spec());
-      other = action->other();
-      ASSERT_TRUE(other);
+      ASSERT_TRUE(action->other());
+      const base::Value::Dict& other = *action->other();
       absl::optional<int> dom_verb =
-          other->FindIntKey(activity_log_constants::kActionDomVerb);
+          other.FindInt(activity_log_constants::kActionDomVerb);
       ASSERT_EQ(DomActionType::SETTER, dom_verb);
     }
   }
@@ -367,10 +363,10 @@
                                             Action::ACTION_DOM_ACCESS,
                                             "XMLHttpRequest.open");
   action->set_page_url(GURL("http://www.google.com/"));
-  action->mutable_args()->Append("POST");
-  action->mutable_args()->Append("http://api.google.com/");
-  action->mutable_other()->SetIntKey(activity_log_constants::kActionDomVerb,
-                                     DomActionType::METHOD);
+  action->mutable_args().Append("POST");
+  action->mutable_args().Append("http://api.google.com/");
+  action->mutable_other().Set(activity_log_constants::kActionDomVerb,
+                              DomActionType::METHOD);
   activity_log->LogAction(action);
 
   // Submit a DOM API call with a relative URL in the argument, which should be
@@ -378,30 +374,30 @@
   action = new Action(kExtensionId, now - base::Seconds(1),
                       Action::ACTION_DOM_ACCESS, "XMLHttpRequest.open");
   action->set_page_url(GURL("http://www.google.com/"));
-  action->mutable_args()->Append("POST");
-  action->mutable_args()->Append("/api/");
-  action->mutable_other()->SetIntKey(activity_log_constants::kActionDomVerb,
-                                     DomActionType::METHOD);
+  action->mutable_args().Append("POST");
+  action->mutable_args().Append("/api/");
+  action->mutable_other().Set(activity_log_constants::kActionDomVerb,
+                              DomActionType::METHOD);
   activity_log->LogAction(action);
 
   // Submit a DOM API call with a relative URL but no base page URL against
   // which to resolve.
   action = new Action(kExtensionId, now - base::Seconds(2),
                       Action::ACTION_DOM_ACCESS, "XMLHttpRequest.open");
-  action->mutable_args()->Append("POST");
-  action->mutable_args()->Append("/api/");
-  action->mutable_other()->SetIntKey(activity_log_constants::kActionDomVerb,
-                                     DomActionType::METHOD);
+  action->mutable_args().Append("POST");
+  action->mutable_args().Append("/api/");
+  action->mutable_other().Set(activity_log_constants::kActionDomVerb,
+                              DomActionType::METHOD);
   activity_log->LogAction(action);
 
   // Submit an API call with an embedded URL.
   action = new Action(kExtensionId, now - base::Seconds(3),
                       Action::ACTION_API_CALL, "windows.create");
-  action->set_args(
-      ListBuilder()
-          .Append(
-              DictionaryBuilder().Set("url", "http://www.google.co.uk").Build())
-          .Build());
+  base::Value::List list;
+  base::Value::Dict item;
+  item.Set("url", "http://www.google.co.uk");
+  list.Append(std::move(item));
+  action->set_args(std::move(list));
   activity_log->LogAction(action);
 
   activity_log->GetFilteredActions(
@@ -450,9 +446,9 @@
   for (int i = 0; i < api_calls_size; i++) {
     action = new Action(kExtensionId, now - base::Seconds(i),
                         Action::ACTION_DOM_ACCESS, kUrlApiCalls[i]);
-    action->mutable_args()->Append("http://www.google.co.uk");
-    action->mutable_other()->SetIntKey(activity_log_constants::kActionDomVerb,
-                                       DomActionType::SETTER);
+    action->mutable_args().Append("http://www.google.co.uk");
+    action->mutable_other().Set(activity_log_constants::kActionDomVerb,
+                                DomActionType::SETTER);
     activity_log->LogAction(action);
   }
 
diff --git a/chrome/browser/extensions/activity_log/counting_policy.cc b/chrome/browser/extensions/activity_log/counting_policy.cc
index 3ba64e94..2356c137 100644
--- a/chrome/browser/extensions/activity_log/counting_policy.cc
+++ b/chrome/browser/extensions/activity_log/counting_policy.cc
@@ -496,11 +496,10 @@
         query.ColumnString(3), query.ColumnInt64(10));
 
     if (query.GetColumnType(4) != sql::ColumnType::kNull) {
-      std::unique_ptr<base::Value> parsed_value =
-          base::JSONReader::ReadDeprecated(query.ColumnString(4));
+      absl::optional<base::Value> parsed_value =
+          base::JSONReader::Read(query.ColumnString(4));
       if (parsed_value && parsed_value->is_list()) {
-        action->set_args(base::WrapUnique(
-            static_cast<base::ListValue*>(parsed_value.release())));
+        action->set_args(std::move(parsed_value->GetList()));
       }
     }
 
@@ -509,11 +508,10 @@
     action->ParseArgUrl(query.ColumnString(7));
 
     if (query.GetColumnType(8) != sql::ColumnType::kNull) {
-      std::unique_ptr<base::Value> parsed_value =
-          base::JSONReader::ReadDeprecated(query.ColumnString(8));
+      absl::optional<base::Value> parsed_value =
+          base::JSONReader::Read(query.ColumnString(8));
       if (parsed_value && parsed_value->is_dict()) {
-        action->set_other(base::WrapUnique(
-            static_cast<base::DictionaryValue*>(parsed_value.release())));
+        action->set_other(std::move(parsed_value->GetDict()));
       }
     }
     action->set_count(query.ColumnInt(9));
diff --git a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
index 0fbc4894..771c1d2c 100644
--- a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
@@ -314,7 +314,7 @@
     scoped_refptr<Action> action =
         new Action("punky1", mock_clock_.Now() - base::Minutes(40),
                    Action::ACTION_DOM_ACCESS, "lets1");
-    action->mutable_args()->Append("vamoose1");
+    action->mutable_args().Append("vamoose1");
     action->set_page_url(GURL("http://www.google1.com"));
     action->set_page_title("Google1");
     action->set_arg_url(GURL("http://www.args-url1.com"));
@@ -325,7 +325,7 @@
 
     action = new Action("punky2", mock_clock_.Now() - base::Minutes(30),
                         Action::ACTION_API_CALL, "lets2");
-    action->mutable_args()->Append("vamoose2");
+    action->mutable_args().Append("vamoose2");
     action->set_page_url(GURL("http://www.google2.com"));
     action->set_page_title("Google2");
     action->set_arg_url(GURL("http://www.args-url2.com"));
@@ -404,12 +404,11 @@
                            .Build())
           .Build();
   extension_service_->AddExtension(extension.get());
-  std::unique_ptr<base::ListValue> args(new base::ListValue());
   scoped_refptr<Action> action = new Action(extension->id(),
                                             base::Time::Now(),
                                             Action::ACTION_API_CALL,
                                             "tabs.testMethod");
-  action->set_args(std::move(args));
+  action->set_args(base::Value::List());
   policy->ProcessAction(action);
   policy->Close();
 }
@@ -427,9 +426,9 @@
           .Build();
   extension_service_->AddExtension(extension.get());
 
-  std::unique_ptr<base::ListValue> args(new base::ListValue());
-  args->Append("hello");
-  args->Append("world");
+  base::Value::List args;
+  args.Append("hello");
+  args.Append("world");
   scoped_refptr<Action> action = new Action(extension->id(),
                                             base::Time::Now(),
                                             Action::ACTION_API_CALL,
@@ -461,29 +460,29 @@
   scoped_refptr<Action> action =
       new Action("punky", mock_clock_.Now() - base::Minutes(40),
                  Action::ACTION_API_CALL, "brewster");
-  action->mutable_args()->Append("woof");
+  action->mutable_args().Append("woof");
   policy->ProcessAction(action);
 
   action = new Action("punky", mock_clock_.Now() - base::Minutes(30),
                       Action::ACTION_API_CALL, "brewster");
-  action->mutable_args()->Append("meow");
+  action->mutable_args().Append("meow");
   policy->ProcessAction(action);
 
   action = new Action("punky", mock_clock_.Now() - base::Minutes(20),
                       Action::ACTION_API_CALL, "extension.sendMessage");
-  action->mutable_args()->Append("not");
-  action->mutable_args()->Append("stripped");
+  action->mutable_args().Append("not");
+  action->mutable_args().Append("stripped");
   policy->ProcessAction(action);
 
   action =
       new Action("punky", mock_clock_.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   policy->ProcessAction(action);
 
   action = new Action("scoobydoo", mock_clock_.Now(), Action::ACTION_DOM_ACCESS,
                       "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   policy->ProcessAction(action);
 
@@ -508,24 +507,24 @@
   scoped_refptr<Action> action =
       new Action("punky", mock_clock_.Now() - base::Days(3) - base::Minutes(40),
                  Action::ACTION_API_CALL, "brewster");
-  action->mutable_args()->Append("woof");
+  action->mutable_args().Append("woof");
   policy->ProcessAction(action);
 
   action = new Action("punky", mock_clock_.Now() - base::Days(3),
                       Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   policy->ProcessAction(action);
 
   action =
       new Action("punky", mock_clock_.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("too new");
+  action->mutable_args().Append("too new");
   action->set_page_url(GURL("http://www.google.com"));
   policy->ProcessAction(action);
 
   action = new Action("punky", mock_clock_.Now() - base::Days(7),
                       Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("too old");
+  action->mutable_args().Append("too old");
   action->set_page_url(GURL("http://www.google.com"));
   policy->ProcessAction(action);
 
@@ -554,14 +553,14 @@
                                                 base::Time::Now(),
                                                 Action::ACTION_API_CALL,
                                                 "tabs.testMethod");
-  action_api->set_args(std::make_unique<base::ListValue>());
+  action_api->set_args(base::Value::List());
   policy->ProcessAction(action_api);
 
   scoped_refptr<Action> action_dom = new Action(extension->id(),
                                                 base::Time::Now(),
                                                 Action::ACTION_DOM_ACCESS,
                                                 "document.write");
-  action_dom->set_args(std::make_unique<base::ListValue>());
+  action_dom->set_args(base::Value::List());
   action_dom->set_page_url(gurl);
   policy->ProcessAction(action_dom);
 
@@ -840,7 +839,7 @@
   // Record some actions
   scoped_refptr<Action> action =
       new Action("punky", mock_clock_.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   action->set_page_title("Google");
   action->set_arg_url(GURL("http://www.args-url.com"));
@@ -849,7 +848,7 @@
   mock_clock_.Advance(base::Seconds(1));
   action =
       new Action("punky", mock_clock_.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google2.com"));
   action->set_page_title("Google");
   // Deliberately no arg url set to make sure it stills works if there is no arg
@@ -878,7 +877,7 @@
   // This should have the page url and args url cleared.
   scoped_refptr<Action> action =
       new Action("punky", mock_clock_.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google1.com"));
   action->set_page_title("Google");
   action->set_arg_url(GURL("http://www.google1.com"));
@@ -888,7 +887,7 @@
   mock_clock_.Advance(base::Seconds(1));
   action =
       new Action("punky", mock_clock_.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google1.com"));
   action->set_page_title("Google");
   action->set_arg_url(GURL("http://www.google.com"));
@@ -899,7 +898,7 @@
   mock_clock_.Advance(base::Seconds(1));
   action =
       new Action("punky", mock_clock_.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google2.com"));
   action->set_page_title("Google");
   policy->ProcessAction(action);
@@ -908,7 +907,7 @@
   mock_clock_.Advance(base::Seconds(1));
   action =
       new Action("punky", mock_clock_.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   action->set_page_title("Google");
   action->set_arg_url(GURL("http://www.google1.com"));
@@ -918,7 +917,7 @@
   mock_clock_.Advance(base::Seconds(1));
   action =
       new Action("punky", mock_clock_.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   action->set_page_title("Google");
   action->set_arg_url(GURL("http://www.args-url.com"));
@@ -950,7 +949,7 @@
   scoped_refptr<Action> action =
       new Action("deleteextensiondata", mock_clock_.Now(),
                  Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_title("Google");
   action->set_arg_url(GURL("http://www.google.com"));
   policy->ProcessAction(action);
@@ -959,7 +958,7 @@
 
   scoped_refptr<Action> action2 = new Action("dontdelete", mock_clock_.Now(),
                                              Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_title("Google");
   action->set_arg_url(GURL("http://www.google.com"));
   policy->ProcessAction(action2);
@@ -998,29 +997,29 @@
   scoped_refptr<Action> action =
       new Action("punky", mock_clock_.Now() - base::Minutes(40),
                  Action::ACTION_API_CALL, "brewster");
-  action->mutable_args()->Append("woof");
+  action->mutable_args().Append("woof");
   policy->ProcessAction(action);
 
   action = new Action("punky", mock_clock_.Now() - base::Minutes(30),
                       Action::ACTION_API_CALL, "brewster");
-  action->mutable_args()->Append("meow");
+  action->mutable_args().Append("meow");
   policy->ProcessAction(action);
 
   action = new Action("punky", mock_clock_.Now() - base::Minutes(20),
                       Action::ACTION_API_CALL, "extension.sendMessage");
-  action->mutable_args()->Append("not");
-  action->mutable_args()->Append("stripped");
+  action->mutable_args().Append("not");
+  action->mutable_args().Append("stripped");
   policy->ProcessAction(action);
 
   action =
       new Action("punky", mock_clock_.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   policy->ProcessAction(action);
 
   action = new Action("scoobydoo", mock_clock_.Now(), Action::ACTION_DOM_ACCESS,
                       "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   policy->ProcessAction(action);
 
@@ -1040,7 +1039,7 @@
   // https://code.google.com/p/chromium/issues/detail?id=341674.
   action =
       new Action("punky", mock_clock_.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   policy->ProcessAction(action);
 
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc b/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc
index f5b33da..45c9e0a9 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc
@@ -194,11 +194,10 @@
         query.ColumnString(3), query.ColumnInt64(9));
 
     if (query.GetColumnType(4) != sql::ColumnType::kNull) {
-      std::unique_ptr<base::Value> parsed_value =
-          base::JSONReader::ReadDeprecated(query.ColumnString(4));
+      absl::optional<base::Value> parsed_value =
+          base::JSONReader::Read(query.ColumnString(4));
       if (parsed_value && parsed_value->is_list()) {
-        action->set_args(base::WrapUnique(
-            static_cast<base::ListValue*>(parsed_value.release())));
+        action->set_args(std::move(parsed_value->GetList()));
       }
     }
 
@@ -207,11 +206,10 @@
     action->ParseArgUrl(query.ColumnString(7));
 
     if (query.GetColumnType(8) != sql::ColumnType::kNull) {
-      std::unique_ptr<base::Value> parsed_value =
-          base::JSONReader::ReadDeprecated(query.ColumnString(8));
+      absl::optional<base::Value> parsed_value =
+          base::JSONReader::Read(query.ColumnString(8));
       if (parsed_value && parsed_value->is_dict()) {
-        action->set_other(base::WrapUnique(
-            static_cast<base::DictionaryValue*>(parsed_value.release())));
+        action->set_other(std::move(parsed_value->GetDict()));
       }
     }
     actions->push_back(action);
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
index 0bd7360..4af89f6 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
@@ -243,7 +243,7 @@
     scoped_refptr<Action> action =
         new Action("punky1", mock_clock.Now() - base::Minutes(40),
                    Action::ACTION_DOM_ACCESS, "lets1");
-    action->mutable_args()->Append("vamoose1");
+    action->mutable_args().Append("vamoose1");
     action->set_page_url(GURL("http://www.google1.com"));
     action->set_page_title("Google1");
     action->set_arg_url(GURL("http://www.args-url1.com"));
@@ -254,7 +254,7 @@
 
     action = new Action("punky2", mock_clock.Now() - base::Minutes(30),
                         Action::ACTION_API_CALL, "lets2");
-    action->mutable_args()->Append("vamoose2");
+    action->mutable_args().Append("vamoose2");
     action->set_page_url(GURL("http://www.google2.com"));
     action->set_page_title("Google2");
     action->set_arg_url(GURL("http://www.args-url2.com"));
@@ -349,12 +349,11 @@
                            .Build())
           .Build();
   extension_service_->AddExtension(extension.get());
-  std::unique_ptr<base::ListValue> args(new base::ListValue());
   scoped_refptr<Action> action = new Action(extension->id(),
                                             base::Time::Now(),
                                             Action::ACTION_API_CALL,
                                             "tabs.testMethod");
-  action->set_args(std::move(args));
+  action->set_args(base::Value::List());
   policy->ProcessAction(action);
   policy->Close();
 }
@@ -378,14 +377,14 @@
                                                 base::Time::Now(),
                                                 Action::ACTION_API_CALL,
                                                 "tabs.testMethod");
-  action_api->set_args(std::make_unique<base::ListValue>());
+  action_api->set_args(base::Value::List());
   policy->ProcessAction(action_api);
 
   scoped_refptr<Action> action_dom = new Action(extension->id(),
                                                 base::Time::Now(),
                                                 Action::ACTION_DOM_ACCESS,
                                                 "document.write");
-  action_dom->set_args(std::make_unique<base::ListValue>());
+  action_dom->set_args(base::Value::List());
   action_dom->set_page_url(gurl);
   policy->ProcessAction(action_dom);
 
@@ -416,14 +415,14 @@
                                                 base::Time::Now(),
                                                 Action::ACTION_API_CALL,
                                                 "tabs.testMethod");
-  action_api->set_args(std::make_unique<base::ListValue>());
+  action_api->set_args(base::Value::List());
   policy->ProcessAction(action_api);
 
   scoped_refptr<Action> action_dom = new Action(extension->id(),
                                                 base::Time::Now(),
                                                 Action::ACTION_DOM_ACCESS,
                                                 "document.write");
-  action_dom->set_args(std::make_unique<base::ListValue>());
+  action_dom->set_args(base::Value::List());
   action_dom->set_page_url(gurl);
   policy->ProcessAction(action_dom);
 
@@ -490,9 +489,9 @@
           .Build();
   extension_service_->AddExtension(extension.get());
 
-  std::unique_ptr<base::ListValue> args(new base::ListValue());
-  args->Append("hello");
-  args->Append("world");
+  base::Value::List args;
+  args.Append("hello");
+  args.Append("world");
   scoped_refptr<Action> action = new Action(extension->id(),
                                             base::Time::Now(),
                                             Action::ACTION_API_CALL,
@@ -522,14 +521,14 @@
   scoped_refptr<Action> action =
       new Action("punky", mock_clock.Now() - base::Minutes(40),
                  Action::ACTION_API_CALL, "brewster");
-  action->mutable_args()->Append("woof");
+  action->mutable_args().Append("woof");
   action->set_arg_url(GURL("http://www.arg-url.com"));
   action->set_page_title("Page Title");
   policy->ProcessAction(action);
 
   action =
       new Action("punky", mock_clock.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   action->set_arg_url(GURL("http://www.arg-url.com"));
   action->set_page_title("Page Title");
@@ -537,7 +536,7 @@
 
   action = new Action("scoobydoo", mock_clock.Now(), Action::ACTION_DOM_ACCESS,
                       "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   action->set_arg_url(GURL("http://www.arg-url.com"));
   policy->ProcessAction(action);
@@ -563,24 +562,24 @@
   scoped_refptr<Action> action =
       new Action("punky", mock_clock.Now() - base::Days(3) - base::Minutes(40),
                  Action::ACTION_API_CALL, "brewster");
-  action->mutable_args()->Append("woof");
+  action->mutable_args().Append("woof");
   policy->ProcessAction(action);
 
   action = new Action("punky", mock_clock.Now() - base::Days(3),
                       Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   policy->ProcessAction(action);
 
   action =
       new Action("punky", mock_clock.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("too new");
+  action->mutable_args().Append("too new");
   action->set_page_url(GURL("http://www.google.com"));
   policy->ProcessAction(action);
 
   action = new Action("punky", mock_clock.Now() - base::Days(7),
                       Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("too old");
+  action->mutable_args().Append("too old");
   action->set_page_url(GURL("http://www.google.com"));
   policy->ProcessAction(action);
 
@@ -603,7 +602,7 @@
   // Record some actions
   scoped_refptr<Action> action =
       new Action("punky", mock_clock.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   action->set_page_title("Google");
   action->set_arg_url(GURL("http://www.google.com"));
@@ -612,7 +611,7 @@
   mock_clock.Advance(base::Seconds(1));
   action =
       new Action("punky", mock_clock.Now(), Action::ACTION_API_CALL, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google2.com"));
   action->set_page_title("Google");
   // Deliberately no arg url set to make sure it still works when there is no
@@ -642,7 +641,7 @@
   // This should have the page url and args url cleared.
   scoped_refptr<Action> action =
       new Action("punky", mock_clock.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google1.com"));
   action->set_page_title("Google");
   action->set_arg_url(GURL("http://www.google1.com"));
@@ -652,7 +651,7 @@
   mock_clock.Advance(base::Seconds(1));
   action =
       new Action("punky", mock_clock.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google1.com"));
   action->set_page_title("Google");
   action->set_arg_url(GURL("http://www.google.com"));
@@ -663,7 +662,7 @@
   mock_clock.Advance(base::Seconds(1));
   action =
       new Action("punky", mock_clock.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google2.com"));
   action->set_page_title("Google");
   policy->ProcessAction(action);
@@ -672,7 +671,7 @@
   mock_clock.Advance(base::Seconds(1));
   action =
       new Action("punky", mock_clock.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   action->set_page_title("Google");
   action->set_arg_url(GURL("http://www.google1.com"));
@@ -682,7 +681,7 @@
   mock_clock.Advance(base::Seconds(1));
   action =
       new Action("punky", mock_clock.Now(), Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   action->set_page_title("Google");
   action->set_arg_url(GURL("http://www.args-url.com"));
@@ -714,7 +713,7 @@
   scoped_refptr<Action> action =
       new Action("deleteextensiondata", mock_clock.Now(),
                  Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_title("Google");
   action->set_arg_url(GURL("http://www.google.com"));
   policy->ProcessAction(action);
@@ -723,7 +722,7 @@
 
   scoped_refptr<Action> action2 = new Action("dontdelete", mock_clock.Now(),
                                              Action::ACTION_DOM_ACCESS, "lets");
-  action->mutable_args()->Append("vamoose");
+  action->mutable_args().Append("vamoose");
   action->set_page_title("Google");
   action->set_arg_url(GURL("http://www.google.com"));
   policy->ProcessAction(action2);
@@ -788,14 +787,14 @@
                                                 base::Time::Now(),
                                                 Action::ACTION_API_CALL,
                                                 "tabs.testMethod");
-  action_api->set_args(std::make_unique<base::ListValue>());
+  action_api->set_args(base::Value::List());
   policy->ProcessAction(action_api);
 
   scoped_refptr<Action> action_dom = new Action(extension->id(),
                                                 base::Time::Now(),
                                                 Action::ACTION_DOM_ACCESS,
                                                 "document.write");
-  action_dom->set_args(std::make_unique<base::ListValue>());
+  action_dom->set_args(base::Value::List());
   action_dom->set_page_url(gurl);
   policy->ProcessAction(action_dom);
 
diff --git a/chrome/browser/extensions/api/activity_log_private/activity_log_private_api_unittest.cc b/chrome/browser/extensions/api/activity_log_private/activity_log_private_api_unittest.cc
index 107237f..db0ac5335 100644
--- a/chrome/browser/extensions/api/activity_log_private/activity_log_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/activity_log_private/activity_log_private_api_unittest.cc
@@ -28,9 +28,9 @@
 typedef testing::Test ActivityLogApiUnitTest;
 
 TEST_F(ActivityLogApiUnitTest, ConvertChromeApiAction) {
-  std::unique_ptr<base::ListValue> args(new base::ListValue());
-  args->Append("hello");
-  args->Append("world");
+  base::Value::List args;
+  args.Append("hello");
+  args.Append("world");
   scoped_refptr<Action> action(new Action(kExtensionId,
                                           base::Time::Now(),
                                           Action::ACTION_API_CALL,
@@ -46,9 +46,9 @@
 }
 
 TEST_F(ActivityLogApiUnitTest, ConvertDomAction) {
-  std::unique_ptr<base::ListValue> args(new base::ListValue());
-  args->Append("hello");
-  args->Append("world");
+  base::Value::List args;
+  args.Append("hello");
+  args.Append("world");
   scoped_refptr<Action> action(new Action(kExtensionId,
                                base::Time::Now(),
                                Action::ACTION_DOM_ACCESS,
@@ -57,10 +57,9 @@
   action->set_args(std::move(args));
   action->set_page_url(GURL("http://www.google.com"));
   action->set_page_title("Title");
-  action->mutable_other()->SetIntKey(activity_log_constants::kActionDomVerb,
-                                     DomActionType::INSERTED);
-  action->mutable_other()->SetBoolKey(activity_log_constants::kActionPrerender,
-                                      false);
+  action->mutable_other().Set(activity_log_constants::kActionDomVerb,
+                              DomActionType::INSERTED);
+  action->mutable_other().Set(activity_log_constants::kActionPrerender, false);
   ExtensionActivity result = action->ConvertToExtensionActivity();
   ASSERT_EQ(kExtensionId, *(result.extension_id.get()));
   ASSERT_EQ("http://www.google.com/", *(result.page_url.get()));
diff --git a/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc b/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc
index d20b85b..e15e657 100644
--- a/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc
+++ b/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc
@@ -123,7 +123,8 @@
 class ExtensionContextMenuVisibilityApiTest
     : public ExtensionContextMenuApiTest {
  public:
-  ExtensionContextMenuVisibilityApiTest() = default;
+  ExtensionContextMenuVisibilityApiTest()
+      : top_level_model_(nullptr), menu_(nullptr), top_level_index_(-1) {}
 
   ExtensionContextMenuVisibilityApiTest(
       const ExtensionContextMenuVisibilityApiTest&) = delete;
@@ -154,7 +155,7 @@
         menu_->extension_items().ConvertToExtensionsCustomCommandId(0),
         &top_level_model_, &top_level_index_);
 
-    EXPECT_GT(top_level_index(), 0u);
+    EXPECT_GT(top_level_index(), 0);
 
     return valid_setup;
   }
@@ -174,14 +175,14 @@
   void VerifyNumExtensionItemsInMenuModel(int num_items,
                                           ui::MenuModel::ItemType type) {
     int num_found = 0;
-    for (size_t i = 0; i < top_level_model_->GetItemCount(); ++i) {
+    for (int i = 0; i < top_level_model_->GetItemCount(); i++) {
       int command_id = top_level_model_->GetCommandIdAt(i);
       if (ContextMenuMatcher::IsExtensionsCustomCommandId(command_id) &&
           top_level_model_->GetTypeAt(i) == type) {
-        ++num_found;
+        num_found++;
       }
     }
-    ASSERT_EQ(num_found, num_items);
+    ASSERT_TRUE(num_found == num_items);
   }
 
   // Verifies that the context menu is valid and contains the given number of
@@ -195,7 +196,7 @@
   // Verifies a context menu item's visibility, title, and item type.
   void VerifyMenuItem(const std::string& title,
                       ui::MenuModel* model,
-                      size_t index,
+                      int index,
                       ui::MenuModel::ItemType type,
                       bool visible) {
     EXPECT_EQ(base::ASCIIToUTF16(title), model->GetLabelAt(index));
@@ -203,13 +204,13 @@
     EXPECT_EQ(visible, model->IsVisibleAt(index));
   }
 
-  size_t top_level_index() const { return top_level_index_; }
+  int top_level_index() { return top_level_index_; }
 
   TestRenderViewContextMenu* menu() { return menu_.get(); }
 
   const Extension* extension() { return extension_; }
 
-  ui::MenuModel* top_level_model_ = nullptr;
+  ui::MenuModel* top_level_model_;
 
  private:
   content::WebContents* GetBackgroundPage(const std::string& extension_id) {
@@ -220,9 +221,9 @@
 
   ProcessManager* process_manager() { return ProcessManager::Get(profile()); }
 
-  raw_ptr<const Extension> extension_ = nullptr;
+  raw_ptr<const Extension> extension_;
   std::unique_ptr<TestRenderViewContextMenu> menu_;
-  size_t top_level_index_ = 0;
+  int top_level_index_;
 };
 
 // Tests showing a single visible menu item in the top-level menu model, which
@@ -286,7 +287,7 @@
   ui::MenuModel* submodel =
       top_level_model_->GetSubmenuModelAt(top_level_index());
   ASSERT_TRUE(submodel);
-  EXPECT_EQ(2u, submodel->GetItemCount());
+  EXPECT_EQ(2, submodel->GetItemCount());
 
   VerifyMenuItem("child1", submodel, 0, ui::MenuModel::TYPE_COMMAND, false);
   VerifyMenuItem("child2", submodel, 1, ui::MenuModel::TYPE_COMMAND, false);
@@ -316,7 +317,7 @@
   ui::MenuModel* submodel =
       top_level_model_->GetSubmenuModelAt(top_level_index());
   ASSERT_TRUE(submodel);
-  EXPECT_EQ(2u, submodel->GetItemCount());
+  EXPECT_EQ(2, submodel->GetItemCount());
 
   // Though the children's internal visibility state remains unchanged, the ui
   // code will hide the children if the parent is hidden.
@@ -346,7 +347,7 @@
   ui::MenuModel* submodel =
       top_level_model_->GetSubmenuModelAt(top_level_index());
   ASSERT_TRUE(submodel);
-  EXPECT_EQ(2u, submodel->GetItemCount());
+  EXPECT_EQ(2, submodel->GetItemCount());
 
   VerifyMenuItem("child1", submodel, 0, ui::MenuModel::TYPE_COMMAND, false);
   VerifyMenuItem("child2", submodel, 1, ui::MenuModel::TYPE_COMMAND, false);
@@ -374,7 +375,7 @@
   ui::MenuModel* submodel =
       top_level_model_->GetSubmenuModelAt(top_level_index());
   ASSERT_TRUE(submodel);
-  EXPECT_EQ(2u, submodel->GetItemCount());
+  EXPECT_EQ(2, submodel->GetItemCount());
 
   VerifyMenuItem("child1", submodel, 0, ui::MenuModel::TYPE_COMMAND, true);
   VerifyMenuItem("child2", submodel, 1, ui::MenuModel::TYPE_COMMAND, false);
@@ -406,7 +407,7 @@
   ui::MenuModel* submodel =
       top_level_model_->GetSubmenuModelAt(top_level_index());
   ASSERT_TRUE(submodel);
-  EXPECT_EQ(1u, submodel->GetItemCount());
+  EXPECT_EQ(1, submodel->GetItemCount());
 
   // When a parent item is specified by the developer (as opposed to generated),
   // its visibility is determined by the specified state.
@@ -414,7 +415,7 @@
 
   submodel = submodel->GetSubmenuModelAt(0);
   ASSERT_TRUE(submodel);
-  EXPECT_EQ(2u, submodel->GetItemCount());
+  EXPECT_EQ(2, submodel->GetItemCount());
 
   VerifyMenuItem("child2", submodel, 0, ui::MenuModel::TYPE_COMMAND, false);
   VerifyMenuItem("child3", submodel, 1, ui::MenuModel::TYPE_COMMAND, false);
@@ -442,7 +443,7 @@
   ui::MenuModel* submodel =
       top_level_model_->GetSubmenuModelAt(top_level_index());
   ASSERT_TRUE(submodel);
-  EXPECT_EQ(3u, submodel->GetItemCount());
+  EXPECT_EQ(3, submodel->GetItemCount());
 
   VerifyMenuItem("item1", submodel, 0, ui::MenuModel::TYPE_COMMAND, false);
   VerifyMenuItem("item2", submodel, 1, ui::MenuModel::TYPE_COMMAND, false);
@@ -471,7 +472,7 @@
   ui::MenuModel* submodel =
       top_level_model_->GetSubmenuModelAt(top_level_index());
   ASSERT_TRUE(submodel);
-  EXPECT_EQ(1u, submodel->GetItemCount());
+  EXPECT_EQ(1, submodel->GetItemCount());
   VerifyMenuItem("child1", submodel, 0, ui::MenuModel::TYPE_COMMAND, false);
 
   // Update child1 to visible.
@@ -525,7 +526,7 @@
   ui::MenuModel* submodel =
       top_level_model_->GetSubmenuModelAt(top_level_index());
   ASSERT_TRUE(submodel);
-  EXPECT_EQ(3u, submodel->GetItemCount());
+  EXPECT_EQ(3, submodel->GetItemCount());
 
   VerifyMenuItem("item1", submodel, 0, ui::MenuModel::TYPE_COMMAND, true);
   VerifyMenuItem("item2", submodel, 1, ui::MenuModel::TYPE_COMMAND, true);
@@ -533,7 +534,7 @@
 
   ui::MenuModel* item3_submodel = submodel->GetSubmenuModelAt(2);
   ASSERT_TRUE(item3_submodel);
-  EXPECT_EQ(2u, item3_submodel->GetItemCount());
+  EXPECT_EQ(2, item3_submodel->GetItemCount());
 
   // Though the children's internal visibility state remains unchanged, the ui
   // code will hide the children if the parent is hidden.
diff --git a/chrome/browser/extensions/api/context_menus/extension_context_menu_browsertest.cc b/chrome/browser/extensions/api/context_menus/extension_context_menu_browsertest.cc
index 7507e8e..c226e5bf 100644
--- a/chrome/browser/extensions/api/context_menus/extension_context_menu_browsertest.cc
+++ b/chrome/browser/extensions/api/context_menus/extension_context_menu_browsertest.cc
@@ -216,7 +216,7 @@
       return false;
 
     MenuModel* model = nullptr;
-    size_t index = 0;
+    int index = -1;
     if (!menu->GetMenuModelAndItemIndex(command_id, &model, &index)) {
       return false;
     }
@@ -656,7 +656,7 @@
   std::unique_ptr<TestRenderViewContextMenu> menu(
       TestRenderViewContextMenu::Create(GetWebContents(), url, GURL(), GURL()));
 
-  size_t index = 0;
+  int index = 0;
   MenuModel* model = nullptr;
 
   ASSERT_TRUE(menu->GetMenuModelAndItemIndex(
@@ -676,7 +676,7 @@
 static void ExpectLabelAndType(const char* expected_label,
                                MenuModel::ItemType expected_type,
                                const MenuModel& menu,
-                               size_t index) {
+                               int index) {
   EXPECT_EQ(expected_type, menu.GetTypeAt(index));
   EXPECT_EQ(base::UTF8ToUTF16(expected_label), menu.GetLabelAt(index));
 }
@@ -698,11 +698,11 @@
   //  --separator--
   //  normal3
 
-  size_t index = 0;
+  int index = 0;
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  ASSERT_EQ(7u, menu.GetItemCount());
+  ASSERT_EQ(7, menu.GetItemCount());
 #else
-  ASSERT_EQ(11u, menu.GetItemCount());
+  ASSERT_EQ(11, menu.GetItemCount());
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   ExpectLabelAndType("radio1", MenuModel::TYPE_RADIO, menu, index++);
   ExpectLabelAndType("radio2", MenuModel::TYPE_RADIO, menu, index++);
@@ -747,7 +747,7 @@
   // The top-level item should be an "automagic parent" with the extension's
   // name.
   MenuModel* model = nullptr;
-  size_t index = 0;
+  int index = 0;
   std::u16string label;
   ASSERT_TRUE(menu->GetMenuModelAndItemIndex(
       ContextMenuMatcher::ConvertToExtensionsCustomCommandId(0),
diff --git a/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc b/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
index b78e9a2..cc2425d 100644
--- a/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
+++ b/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
@@ -338,14 +338,14 @@
     const api::passwords_private::InsecureCredential& credential,
     base::StringPiece new_password) {
   // Try to obtain the original CredentialUIEntry. Return false if fails.
-  const CredentialUIEntry* entry = FindMatchingEntry(credential);
-  if (!entry)
+  const CredentialUIEntry* original_credential = FindMatchingEntry(credential);
+  if (!original_credential)
     return false;
 
-  CredentialUIEntry credential_to_edit = *entry;
-  credential_to_edit.password = base::UTF8ToUTF16(new_password);
-  switch (
-      saved_passwords_presenter_->EditSavedCredentials(credential_to_edit)) {
+  CredentialUIEntry updated_credential = *original_credential;
+  updated_credential.password = base::UTF8ToUTF16(new_password);
+  switch (saved_passwords_presenter_->EditSavedCredentials(
+      *original_credential, updated_credential)) {
     case password_manager::SavedPasswordsPresenter::EditResult::kSuccess:
     case password_manager::SavedPasswordsPresenter::EditResult::kNothingChanged:
       return true;
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
index d220aa0..232dc182 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
@@ -30,6 +30,7 @@
 #include "chrome/common/extensions/api/passwords_private.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/keyed_service/core/service_access_type.h"
+#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
 #include "components/password_manager/core/browser/move_password_to_account_store_helper.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_features_util.h"
@@ -282,22 +283,24 @@
   // It may have 2 elements but only if it's the same password in two stores. In
   // this case updating only one of them is enough as
   // |saved_passwords_presenter_| will update both of them anyway.
-  const CredentialUIEntry* entry = credential_id_generator_.TryGetKey(ids[0]);
-  if (!entry)
+  const CredentialUIEntry* original_credential =
+      credential_id_generator_.TryGetKey(ids[0]);
+  if (!original_credential)
     return absl::nullopt;
 
-  CredentialUIEntry to_edit = *entry;
-  to_edit.username = base::UTF8ToUTF16(params.username);
-  to_edit.password = base::UTF8ToUTF16(params.password);
+  CredentialUIEntry updated_credential = *original_credential;
+  updated_credential.username = base::UTF8ToUTF16(params.username);
+  updated_credential.password = base::UTF8ToUTF16(params.password);
   if (params.note) {
-    to_edit.note = password_manager::PasswordNote(
+    updated_credential.note = password_manager::PasswordNote(
         base::UTF8ToUTF16(*params.note), base::Time::Now());
   }
   // Collect the credentials that will be edited before executing the edit
   // process.
-  auto forms_to_edit =
-      saved_passwords_presenter_.GetCorrespondingPasswordForms(entry->key());
-  switch (saved_passwords_presenter_.EditSavedCredentials(to_edit)) {
+  auto forms_to_edit = saved_passwords_presenter_.GetCorrespondingPasswordForms(
+      *original_credential);
+  switch (saved_passwords_presenter_.EditSavedCredentials(*original_credential,
+                                                          updated_credential)) {
     case password_manager::SavedPasswordsPresenter::EditResult::kSuccess:
     case password_manager::SavedPasswordsPresenter::EditResult::kNothingChanged:
       break;
@@ -309,8 +312,8 @@
   api::passwords_private::CredentialIds new_ids;
   for (auto& form : forms_to_edit) {
     // Calculate the new IDs using the new username and password.
-    form.username_value = to_edit.username;
-    form.password_value = to_edit.password;
+    form.username_value = updated_credential.username;
+    form.password_value = updated_credential.password;
 
     auto new_id = std::make_unique<int>(
         credential_id_generator_.GenerateId(CredentialUIEntry(form)));
@@ -436,6 +439,8 @@
       entry.password_note = base::UTF16ToUTF8(credential.note.value);
       entry.id = id;
       entry.stored_in = ConvertToAPIStore(credential.stored_in);
+      entry.is_android_credential =
+          password_manager::IsValidAndroidFacetURI(credential.signon_realm);
       if (!credential.federation_origin.opaque()) {
         std::u16string formatted_origin =
             url_formatter::FormatOriginForSecurityDisplay(
@@ -493,7 +498,7 @@
     }
 
     std::vector<password_manager::PasswordForm> corresponding_forms =
-        saved_passwords_presenter_.GetCorrespondingPasswordForms(entry->key());
+        saved_passwords_presenter_.GetCorrespondingPasswordForms(*entry);
     if (corresponding_forms.empty()) {
       continue;
     }
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
index 40a4e8d..79f10a2 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
@@ -198,7 +198,9 @@
   return testing::Value(expected.get().urls.link, arg.urls.link) &&
          testing::Value(expected.get().username, arg.username) &&
          testing::Value(expected.get().password_note, arg.password_note) &&
-         testing::Value(expected.get().stored_in, arg.stored_in);
+         testing::Value(expected.get().stored_in, arg.stored_in) &&
+         testing::Value(expected.get().is_android_credential,
+                        arg.is_android_credential);
 }
 
 }  // namespace
@@ -950,4 +952,27 @@
       2);
 }
 
+TEST_F(PasswordsPrivateDelegateImplTest, AndroidCredential) {
+  PasswordsPrivateDelegateImpl delegate(&profile_);
+
+  password_manager::PasswordForm android_form;
+  android_form.signon_realm = "android://hash@example.com";
+  android_form.username_value = u"test@gmail.com";
+  android_form.in_store = password_manager::PasswordForm::Store::kProfileStore;
+  SetUpPasswordStores({android_form});
+
+  base::MockCallback<PasswordsPrivateDelegate::UiEntriesCallback> callback;
+
+  api::passwords_private::PasswordUiEntry expected_entry;
+  expected_entry.urls.link =
+      "https://play.google.com/store/apps/details?id=example.com";
+  expected_entry.username = "test@gmail.com";
+  expected_entry.password_note = "";
+  expected_entry.is_android_credential = true;
+  expected_entry.stored_in = api::passwords_private::PASSWORD_STORE_SET_DEVICE;
+  EXPECT_CALL(callback, Run(testing::ElementsAre(PasswordUiEntryDataEquals(
+                            testing::ByRef(expected_entry)))));
+  delegate.GetSavedPasswordsList(callback.Get());
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/context_menu_matcher.cc b/chrome/browser/extensions/context_menu_matcher.cc
index 3a5b2d8c..dcaa4f6 100644
--- a/chrome/browser/extensions/context_menu_matcher.cc
+++ b/chrome/browser/extensions/context_menu_matcher.cc
@@ -149,7 +149,7 @@
 }
 
 bool ContextMenuMatcher::HasVisibleItems(ui::MenuModel* menu_model) const {
-  for (size_t index = 0; index < menu_model->GetItemCount(); ++index) {
+  for (int index = 0; index < menu_model->GetItemCount(); index++) {
     if (!menu_model->IsVisibleAt(index))
       continue;
 
@@ -209,13 +209,13 @@
   // be displayed only if it has an invisible submenu item.
   if (!item && ContextMenuMatcher::IsExtensionsCustomCommandId(command_id)) {
     ui::MenuModel* model = menu_model_;
-    size_t index = 0;
+    int index = 0;
     if (ui::MenuModel::GetModelAndIndexForCommandId(command_id, &model,
                                                     &index)) {
       ui::MenuModel* submenu_model = model->GetSubmenuModelAt(index);
       // TODO(ghazale): Find out why submenu_model might be null. In other
       // words, in which circumstance it can be an extensions custom command ID
-      // which does not have an associated item, but its submenu_model is null.
+      // which does not have an associated item, but it's submenu_model is null.
       if (submenu_model)
         return HasVisibleItems(submenu_model);
     }
@@ -379,13 +379,13 @@
 void ContextMenuMatcher::SetExtensionIcon(const std::string& extension_id) {
   MenuManager* menu_manager = MenuManager::Get(browser_context_);
 
-  size_t count = menu_model_->GetItemCount();
-  DCHECK_GT(count, 0u);
+  int index = menu_model_->GetItemCount() - 1;
+  DCHECK_GE(index, 0);
 
   gfx::Image icon = menu_manager->GetIconForExtension(extension_id);
   DCHECK_EQ(gfx::kFaviconSize, icon.Width());
   DCHECK_EQ(gfx::kFaviconSize, icon.Height());
-  menu_model_->SetIcon(count - 1, ui::ImageModel::FromImage(icon));
+  menu_model_->SetIcon(index, ui::ImageModel::FromImage(icon));
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/extension_context_menu_model.cc b/chrome/browser/extensions/extension_context_menu_model.cc
index 0ccd4872..8c21e13 100644
--- a/chrome/browser/extensions/extension_context_menu_model.cc
+++ b/chrome/browser/extensions/extension_context_menu_model.cc
@@ -435,7 +435,7 @@
                                            : IDS_EXTENSIONS_UNINSTALL;
     AddItem(UNINSTALL, l10n_util::GetStringUTF16(message_id));
     if (is_required_by_policy) {
-      size_t uninstall_index = GetIndexOfCommandId(UNINSTALL).value();
+      int uninstall_index = GetIndexOfCommandId(UNINSTALL);
       // TODO (kylixrd): Investigate the usage of the hard-coded color.
       SetIcon(uninstall_index,
               ui::ImageModel::FromVectorIcon(vector_icons::kBusinessIcon,
@@ -450,8 +450,7 @@
     DCHECK_NE(-1, visibility_string_id);
     AddItemWithStringId(TOGGLE_VISIBILITY, visibility_string_id);
     if (IsExtensionForcePinned(*extension, profile_)) {
-      size_t toggle_visibility_index =
-          GetIndexOfCommandId(TOGGLE_VISIBILITY).value();
+      int toggle_visibility_index = GetIndexOfCommandId(TOGGLE_VISIBILITY);
       SetIcon(toggle_visibility_index,
               ui::ImageModel::FromVectorIcon(vector_icons::kBusinessIcon,
                                              ui::kColorIcon, 16));
diff --git a/chrome/browser/extensions/extension_context_menu_model_unittest.cc b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
index 9301e54..b49ea6a 100644
--- a/chrome/browser/extensions/extension_context_menu_model_unittest.cc
+++ b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
@@ -199,7 +199,7 @@
   std::u16string expected_label = base::ASCIIToUTF16(kTestExtensionItemLabel);
   int num_items_found = 0;
   int num_custom_found = 0;
-  for (size_t i = 0; i < model.GetItemCount(); ++i) {
+  for (int i = 0; i < model.GetItemCount(); ++i) {
     std::u16string actual_label = model.GetLabelAt(i);
     int command_id = model.GetCommandIdAt(i);
     // If the command id is not visible, it should not be counted.
@@ -226,7 +226,7 @@
 void VerifyItems(const ExtensionContextMenuModel& model,
                  std::vector<std::string> item_number) {
   size_t j = 0;
-  for (size_t i = 0; i < model.GetItemCount(); i++) {
+  for (int i = 0; i < model.GetItemCount(); i++) {
     int command_id = model.GetCommandIdAt(i);
     if (ContextMenuMatcher::IsExtensionsCustomCommandId(command_id) &&
         model.IsCommandIdVisible(command_id)) {
@@ -377,7 +377,7 @@
 ExtensionContextMenuModelTest::GetCommandState(
     const ExtensionContextMenuModel& menu,
     int command_id) const {
-  bool is_present = menu.GetIndexOfCommandId(command_id).has_value();
+  bool is_present = menu.GetIndexOfCommandId(command_id) != -1;
   bool is_visible = menu.IsCommandIdVisible(command_id);
 
   // The command is absent if the menu entry is not present, or the entry is
@@ -408,12 +408,11 @@
     return CommandState::kAbsent;
 
   ui::MenuModel* submenu = menu.GetSubmenuModelAt(
-      menu.GetIndexOfCommandId(ExtensionContextMenuModel::PAGE_ACCESS_SUBMENU)
-          .value());
+      menu.GetIndexOfCommandId(ExtensionContextMenuModel::PAGE_ACCESS_SUBMENU));
   DCHECK(submenu);
 
   ui::MenuModel** menu_to_search = &submenu;
-  size_t index_unused = 0;
+  int index_unused = 0;
   if (!ui::MenuModel::GetModelAndIndexForCommandId(command, menu_to_search,
                                                    &index_unused)) {
     return CommandState::kAbsent;
@@ -494,8 +493,8 @@
   // uninstallation should be disabled.
   EXPECT_EQ(GetCommandState(menu, ExtensionContextMenuModel::UNINSTALL),
             CommandState::kDisabled);
-  size_t uninstall_index =
-      menu.GetIndexOfCommandId(ExtensionContextMenuModel::UNINSTALL).value();
+  int uninstall_index =
+      menu.GetIndexOfCommandId(ExtensionContextMenuModel::UNINSTALL);
   // There should also be an icon to visually indicate why uninstallation is
   // forbidden.
   ui::ImageModel icon = menu.GetIconAt(uninstall_index);
@@ -609,9 +608,8 @@
                                    ExtensionContextMenuModel::PINNED, nullptr,
                                    /* can_show_icon_in_toolbar=*/true,
                                    ContextMenuSource::kMenuItem);
-    EXPECT_FALSE(
-        menu.GetIndexOfCommandId(ExtensionContextMenuModel::TOGGLE_VISIBILITY)
-            .has_value());
+    EXPECT_EQ(-1, menu.GetIndexOfCommandId(
+                      ExtensionContextMenuModel::TOGGLE_VISIBILITY));
     EXPECT_EQ(
         GetCommandState(menu, ExtensionContextMenuModel::TOGGLE_VISIBILITY),
         CommandState::kAbsent);
@@ -752,18 +750,18 @@
     ExtensionContextMenuModel menu(page_action, browser,
                                    ExtensionContextMenuModel::PINNED, nullptr,
                                    true, ContextMenuSource::kToolbarAction);
-    absl::optional<size_t> index = menu.GetIndexOfCommandId(visibility_command);
-    ASSERT_TRUE(index.has_value());
-    EXPECT_EQ(unpin_string, menu.GetLabelAt(index.value()));
+    int index = menu.GetIndexOfCommandId(visibility_command);
+    EXPECT_NE(-1, index);
+    EXPECT_EQ(unpin_string, menu.GetLabelAt(index));
   }
 
   {
     ExtensionContextMenuModel menu(browser_action, browser,
                                    ExtensionContextMenuModel::PINNED, nullptr,
                                    true, ContextMenuSource::kToolbarAction);
-    absl::optional<size_t> index = menu.GetIndexOfCommandId(visibility_command);
-    ASSERT_TRUE(index.has_value());
-    EXPECT_EQ(unpin_string, menu.GetLabelAt(index.value()));
+    int index = menu.GetIndexOfCommandId(visibility_command);
+    EXPECT_NE(-1, index);
+    EXPECT_EQ(unpin_string, menu.GetLabelAt(index));
 
     // Pin before unpinning.
     ToolbarActionsModel::Get(profile())->SetActionVisibility(
@@ -776,9 +774,9 @@
     ExtensionContextMenuModel menu(browser_action, browser,
                                    ExtensionContextMenuModel::UNPINNED, nullptr,
                                    true, ContextMenuSource::kToolbarAction);
-    absl::optional<size_t> index = menu.GetIndexOfCommandId(visibility_command);
-    ASSERT_TRUE(index.has_value());
-    EXPECT_EQ(pin_string, menu.GetLabelAt(index.value()));
+    int index = menu.GetIndexOfCommandId(visibility_command);
+    EXPECT_NE(-1, index);
+    EXPECT_EQ(pin_string, menu.GetLabelAt(index));
   }
 
   {
@@ -788,9 +786,9 @@
         browser_action, browser,
         ExtensionContextMenuModel::TRANSITIVELY_VISIBLE, nullptr, true,
         ContextMenuSource::kToolbarAction);
-    absl::optional<size_t> index = menu.GetIndexOfCommandId(visibility_command);
-    ASSERT_TRUE(index.has_value());
-    EXPECT_EQ(pin_string, menu.GetLabelAt(index.value()));
+    int index = menu.GetIndexOfCommandId(visibility_command);
+    EXPECT_NE(-1, index);
+    EXPECT_EQ(pin_string, menu.GetLabelAt(index));
   }
 }
 
@@ -833,10 +831,10 @@
     ExtensionContextMenuModel menu(extension, browser,
                                    ExtensionContextMenuModel::PINNED, nullptr,
                                    true, ContextMenuSource::kToolbarAction);
-    absl::optional<size_t> index = menu.GetIndexOfCommandId(visibility_command);
-    ASSERT_TRUE(index.has_value());
-    EXPECT_TRUE(menu.IsEnabledAt(index.value()));
-    EXPECT_EQ(unpin_string, menu.GetLabelAt(index.value()));
+    int index = menu.GetIndexOfCommandId(visibility_command);
+    EXPECT_NE(-1, index);
+    EXPECT_TRUE(menu.IsEnabledAt(index));
+    EXPECT_EQ(unpin_string, menu.GetLabelAt(index));
   }
 
   {
@@ -844,10 +842,10 @@
     ExtensionContextMenuModel menu(force_pinned_extension, browser,
                                    ExtensionContextMenuModel::PINNED, nullptr,
                                    true, ContextMenuSource::kToolbarAction);
-    absl::optional<size_t> index = menu.GetIndexOfCommandId(visibility_command);
-    ASSERT_TRUE(index.has_value());
-    EXPECT_FALSE(menu.IsEnabledAt(index.value()));
-    EXPECT_EQ(force_pinned_string, menu.GetLabelAt(index.value()));
+    int index = menu.GetIndexOfCommandId(visibility_command);
+    EXPECT_NE(-1, index);
+    EXPECT_FALSE(menu.IsEnabledAt(index));
+    EXPECT_EQ(force_pinned_string, menu.GetLabelAt(index));
   }
 }
 
@@ -1121,10 +1119,8 @@
   ExtensionContextMenuModel single_host_menu(
       single_host_extension, GetBrowser(), ExtensionContextMenuModel::PINNED,
       nullptr, true, ContextMenuSource::kToolbarAction);
-  EXPECT_TRUE(
-      single_host_menu
-          .GetIndexOfCommandId(ExtensionContextMenuModel::PAGE_ACCESS_SUBMENU)
-          .has_value());
+  EXPECT_NE(-1, single_host_menu.GetIndexOfCommandId(
+                    ExtensionContextMenuModel::PAGE_ACCESS_SUBMENU));
 }
 
 // Tests different permission patterns when the site setting is set to
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index fec8717a..904719a 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -5051,6 +5051,11 @@
     "expiry_milestone": 105
   },
   {
+    "name": "password-strength-indicator",
+    "owners": ["mtimbur@google.com", "rgod@google.com", "mamir@chromium.org"],
+    "expiry_milestone": 110
+  },
+  {
     "name": "password-view-page-in-settings",
     "owners": ["mamir", "derinel@google.com"],
     "expiry_milestone": 108
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 01480df..06117eacc 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2176,6 +2176,11 @@
 const char kPasswordScriptsFetchingDescription[] =
     "Fetches scripts for password change flows.";
 
+const char kPasswordStrengthIndicatorName[] = "Password strength indicator";
+const char kPasswordStrengthIndicatorDescription[] =
+    "Enables password strength indicator when typing a password during a "
+    "sign-up and password change flows.";
+
 const char kForceEnablePasswordDomainCapabilitiesName[] =
     "Force enable password change capabilities for domains";
 const char kForceEnablePasswordDomainCapabilitiesDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index c6e14e5..137201c 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1214,6 +1214,9 @@
 extern const char kPasswordScriptsFetchingName[];
 extern const char kPasswordScriptsFetchingDescription[];
 
+extern const char kPasswordStrengthIndicatorName[];
+extern const char kPasswordStrengthIndicatorDescription[];
+
 extern const char kForceEnablePasswordDomainCapabilitiesName[];
 extern const char kForceEnablePasswordDomainCapabilitiesDescription[];
 
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc
index e81b790..fedb07a 100644
--- a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc
+++ b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc
@@ -78,7 +78,7 @@
 std::unique_ptr<base::ListValue> ChromeWebViewGuestDelegate::MenuModelToValue(
     const ui::SimpleMenuModel& menu_model) {
   std::unique_ptr<base::ListValue> items(new base::ListValue());
-  for (size_t i = 0; i < menu_model.GetItemCount(); ++i) {
+  for (int i = 0; i < menu_model.GetItemCount(); ++i) {
     base::Value::Dict item_value;
     // TODO(lazyboy): We need to expose some kind of enum equivalent of
     // |command_id| instead of plain integers.
diff --git a/chrome/browser/login_detection/login_detection_keyed_service_factory.cc b/chrome/browser/login_detection/login_detection_keyed_service_factory.cc
index 7e796fd..7bdbfdb 100644
--- a/chrome/browser/login_detection/login_detection_keyed_service_factory.cc
+++ b/chrome/browser/login_detection/login_detection_keyed_service_factory.cc
@@ -11,10 +11,20 @@
 #include "chrome/browser/password_manager/account_password_store_factory.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "content/public/browser/browser_context.h"
 
 namespace login_detection {
+namespace {
+
+ProfileSelections BuildLoginDetectionProfileSelection() {
+  if (!IsLoginDetectionFeatureEnabled()) {
+    return ProfileSelections::BuildNoServicesForAllProfiles();
+  }
+
+  return ProfileSelections::BuildDefault();
+}
+
+}  // namespace
 
 // static
 LoginDetectionKeyedService* LoginDetectionKeyedServiceFactory::GetForProfile(
@@ -31,9 +41,8 @@
 }
 
 LoginDetectionKeyedServiceFactory::LoginDetectionKeyedServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "LoginDetectionKeyedService",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("LoginDetectionKeyedService",
+                                 BuildLoginDetectionProfileSelection()) {
   DependsOn(AccountPasswordStoreFactory::GetInstance());
   DependsOn(PasswordStoreFactory::GetInstance());
   DependsOn(OptimizationGuideKeyedServiceFactory::GetInstance());
@@ -42,18 +51,6 @@
 LoginDetectionKeyedServiceFactory::~LoginDetectionKeyedServiceFactory() =
     default;
 
-content::BrowserContext*
-LoginDetectionKeyedServiceFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  if (context->IsOffTheRecord())
-    return nullptr;
-
-  if (!IsLoginDetectionFeatureEnabled())
-    return nullptr;
-
-  return context;
-}
-
 KeyedService* LoginDetectionKeyedServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
   return new LoginDetectionKeyedService(Profile::FromBrowserContext(context));
diff --git a/chrome/browser/login_detection/login_detection_keyed_service_factory.h b/chrome/browser/login_detection/login_detection_keyed_service_factory.h
index 6b3fb757..4b2afc04 100644
--- a/chrome/browser/login_detection/login_detection_keyed_service_factory.h
+++ b/chrome/browser/login_detection/login_detection_keyed_service_factory.h
@@ -6,11 +6,7 @@
 #define CHROME_BROWSER_LOGIN_DETECTION_LOGIN_DETECTION_KEYED_SERVICE_FACTORY_H_
 
 #include "base/no_destructor.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
-
-namespace content {
-class BrowserContext;
-}  // namespace content
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -20,8 +16,7 @@
 
 // LazyInstance that owns all LoginDetectionKeyedServices and associates them
 // with Profiles.
-class LoginDetectionKeyedServiceFactory
-    : public BrowserContextKeyedServiceFactory {
+class LoginDetectionKeyedServiceFactory : public ProfileKeyedServiceFactory {
  public:
   // Gets the LoginDetectionService for the profile.
   //
@@ -38,8 +33,6 @@
   ~LoginDetectionKeyedServiceFactory() override;
 
   // BrowserContextKeyedServiceFactory:
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
   bool ServiceIsCreatedWithBrowserContext() const override;
diff --git a/chrome/browser/metrics/family_link_user_metrics_provider.cc b/chrome/browser/metrics/family_link_user_metrics_provider.cc
index 15f62354..494c9c7 100644
--- a/chrome/browser/metrics/family_link_user_metrics_provider.cc
+++ b/chrome/browser/metrics/family_link_user_metrics_provider.cc
@@ -12,6 +12,14 @@
 constexpr char kFamilyLinkUserLogSegmentHistogramName[] =
     "FamilyLinkUser.LogSegment";
 
+bool AreParentalSupervisionCapabilitiesKnown(
+    const AccountCapabilities& capabilities) {
+  return capabilities.can_stop_parental_supervision() !=
+             signin::Tribool::kUnknown &&
+         capabilities.is_subject_to_parental_controls() !=
+             signin::Tribool::kUnknown;
+}
+
 }  // namespace
 
 FamilyLinkUserMetricsProvider::FamilyLinkUserMetricsProvider() {
@@ -54,30 +62,30 @@
 
 void FamilyLinkUserMetricsProvider::OnExtendedAccountInfoUpdated(
     const AccountInfo& account_info) {
+  if (!AreParentalSupervisionCapabilitiesKnown(account_info.capabilities)) {
+    // Because account info is fetched asynchronously it is possible for a
+    // subset of the info to be updated that does not include account
+    // capabilities. Only log metrics after the capability fetch completes.
+    return;
+  }
   auto is_subject_to_parental_controls =
       account_info.capabilities.is_subject_to_parental_controls();
-  switch (is_subject_to_parental_controls) {
-    case signin::Tribool::kFalse:
-    case signin::Tribool::kUnknown: {
-      // Log as unsupervised user if the account is not subject to parental
-      // controls or if the capability is not known.
-      SetLogSegment(LogSegment::kUnsupervised);
-      return;
+  if (is_subject_to_parental_controls == signin::Tribool::kTrue) {
+    auto can_stop_supervision =
+        account_info.capabilities.can_stop_parental_supervision();
+    if (can_stop_supervision == signin::Tribool::kTrue) {
+      // Log as a supervised user that has chosen to enable parental
+      // supervision on their account, e.g. Geller accounts.
+      SetLogSegment(LogSegment::kSupervisionEnabledByUser);
+    } else {
+      // Log as a supervised user that has parental supervision enabled
+      // by a policy applied to their account, e.g. Unicorn accounts.
+      SetLogSegment(LogSegment::kSupervisionEnabledByPolicy);
     }
-    case signin::Tribool::kTrue: {
-      auto can_stop_supervision =
-          account_info.capabilities.can_stop_parental_supervision();
-      if (can_stop_supervision == signin::Tribool::kTrue) {
-        // Log as a supervised user that has chosen to enable parental
-        // supervision on their account, e.g. Geller accounts.
-        SetLogSegment(LogSegment::kSupervisionEnabledByUser);
-      } else {
-        // Log as a supervised user that has parental supervision enabled
-        // by a policy applied to their account, e.g. Unicorn accounts.
-        SetLogSegment(LogSegment::kSupervisionEnabledByPolicy);
-      }
-      return;
-    }
+  } else {
+    // Log as unsupervised user if the account is not subject to parental
+    // controls.
+    SetLogSegment(LogSegment::kUnsupervised);
   }
 }
 
diff --git a/chrome/browser/metrics/family_link_user_metrics_provider_unittest.cc b/chrome/browser/metrics/family_link_user_metrics_provider_unittest.cc
index 8c8fb5a..99da852 100644
--- a/chrome/browser/metrics/family_link_user_metrics_provider_unittest.cc
+++ b/chrome/browser/metrics/family_link_user_metrics_provider_unittest.cc
@@ -59,13 +59,13 @@
   AccountInfo account = identity_test_env()->MakeAccountAvailable(kTestEmail);
   base::RunLoop().RunUntilIdle();
 
+  // Does not set account capabilities, default is unknown.
   base::HistogramTester histogram_tester;
   metrics_provider()->ProvideCurrentSessionData(/*uma_proto_unused=*/nullptr);
 
-  histogram_tester.ExpectUniqueSample(
+  histogram_tester.ExpectTotalCount(
       FamilyLinkUserMetricsProvider::GetHistogramNameForTesting(),
-      FamilyLinkUserMetricsProvider::LogSegment::kUnsupervised,
-      /*expected_bucket_count=*/1);
+      /*count=*/0);
 }
 
 TEST_F(FamilyLinkUserMetricsProviderTest, AdultUser) {
@@ -75,6 +75,7 @@
 
   AccountCapabilitiesTestMutator mutator(&account.capabilities);
   mutator.set_is_subject_to_parental_controls(false);
+  mutator.set_can_stop_parental_supervision(false);
   signin::UpdateAccountInfoForAccount(identity_manager(), account);
 
   AccountInfo updated_account =
@@ -154,6 +155,27 @@
   base::HistogramTester histogram_tester;
   metrics_provider()->ProvideCurrentSessionData(/*uma_proto_unused=*/nullptr);
 
+  histogram_tester.ExpectTotalCount(
+      FamilyLinkUserMetricsProvider::GetHistogramNameForTesting(),
+      /*count=*/0);
+}
+
+TEST_F(FamilyLinkUserMetricsProviderTest,
+       MetricsProviderInitAfterPrimaryAccountWithCapabilitiesAdded) {
+  AccountInfo account = identity_test_env()->MakePrimaryAccountAvailable(
+      kTestEmail, signin::ConsentLevel::kSignin);
+
+  AccountCapabilitiesTestMutator mutator(&account.capabilities);
+  mutator.set_is_subject_to_parental_controls(false);
+  mutator.set_can_stop_parental_supervision(false);
+  signin::UpdateAccountInfoForAccount(identity_manager(), account);
+
+  // Identity manager observer set after primary account is made available.
+  metrics_provider()->IdentityManagerCreated(identity_manager());
+
+  base::HistogramTester histogram_tester;
+  metrics_provider()->ProvideCurrentSessionData(/*uma_proto_unused=*/nullptr);
+
   histogram_tester.ExpectUniqueSample(
       FamilyLinkUserMetricsProvider::GetHistogramNameForTesting(),
       FamilyLinkUserMetricsProvider::LogSegment::kUnsupervised,
diff --git a/chrome/browser/password_entry_edit/android/credential_edit_bridge.cc b/chrome/browser/password_entry_edit/android/credential_edit_bridge.cc
index 5dcd588..759717d 100644
--- a/chrome/browser/password_entry_edit/android/credential_edit_bridge.cc
+++ b/chrome/browser/password_entry_edit/android/credential_edit_bridge.cc
@@ -89,10 +89,13 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jstring>& username,
     const base::android::JavaParamRef<jstring>& password) {
-  password_manager::CredentialUIEntry to_edit = credential_;
-  to_edit.username = base::android::ConvertJavaStringToUTF16(username);
-  to_edit.password = base::android::ConvertJavaStringToUTF16(password);
-  saved_passwords_presenter_->EditSavedCredentials(to_edit);
+  password_manager::CredentialUIEntry updated_credential = credential_;
+  updated_credential.username =
+      base::android::ConvertJavaStringToUTF16(username);
+  updated_credential.password =
+      base::android::ConvertJavaStringToUTF16(password);
+  saved_passwords_presenter_->EditSavedCredentials(credential_,
+                                                   updated_credential);
 }
 
 void CredentialEditBridge::DeleteCredential(JNIEnv* env) {
diff --git a/chrome/browser/privacy_budget/active_sampling.cc b/chrome/browser/privacy_budget/active_sampling.cc
index d51c921..ec2de89 100644
--- a/chrome/browser/privacy_budget/active_sampling.cc
+++ b/chrome/browser/privacy_budget/active_sampling.cc
@@ -4,14 +4,6 @@
 
 #include "chrome/browser/privacy_budget/active_sampling.h"
 
-#include "base/i18n/case_conversion.h"
-#include "base/location.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/task/task_traits.h"
-#include "base/task/thread_pool.h"
-#include "build/build_config.h"
-#include "chrome/common/privacy_budget/field_trial_param_conversions.h"
-#include "chrome/common/privacy_budget/privacy_budget_features.h"
 #include "content/public/common/user_agent.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
@@ -20,8 +12,6 @@
 #include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
 #include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
 #include "third_party/blink/public/common/privacy_budget/identifiable_token.h"
-#include "third_party/skia/include/core/SkFontMgr.h"
-#include "third_party/skia/include/core/SkTypeface.h"
 
 namespace {
 
@@ -43,61 +33,10 @@
                                                             ukm_source_id);
 }
 
-bool IsFontFamilyAvailable(const char* family, SkFontMgr* fm) {
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-  return !!fm->legacyMakeTypeface(family, SkFontStyle());
-#else
-  sk_sp<SkFontStyleSet> set(fm->matchFamily(family));
-  return set && set->count();
-#endif
-}
-
-void ReportAvailableFontFamilies(std::vector<std::string> fonts_to_check) {
-  sk_sp<SkFontMgr> fontManager(SkFontMgr::RefDefault());
-  ukm::SourceId ukm_source_id = ukm::NoURLSourceId();
-  blink::IdentifiabilityMetricBuilder builder(ukm_source_id);
-  for (const std::string& font : fonts_to_check) {
-    bool is_available = IsFontFamilyAvailable(font.c_str(), fontManager.get());
-
-    // Compute a case-insensitive (in a unicode-compatible way) hash for the
-    // surface key.
-    blink::IdentifiableToken font_family_name_token(
-        base::UTF16ToUTF8(base::i18n::FoldCase(base::UTF8ToUTF16(font))));
-    builder.Add(blink::IdentifiableSurface::FromTypeAndToken(
-                    blink::IdentifiableSurface::Type::kFontFamilyAvailable,
-                    font_family_name_token),
-                is_available);
-  }
-  ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get();
-  if (!ukm_recorder) {
-    return;
-  }
-  builder.Record(ukm_recorder);
-  blink::IdentifiabilitySampleCollector::Get()->FlushSource(ukm_recorder,
-                                                            ukm_source_id);
-}
-
-void ActivelySampleAvailableFonts() {
-  std::vector<std::string> font_families =
-      DecodeIdentifiabilityFieldTrialParam<std::vector<std::string>>(
-          features::kIdentifiabilityStudyActivelySampledFonts.Get());
-
-  if (font_families.empty())
-    return;
-
-  // Checking font availability can be expensive and might block.
-  base::ThreadPool::PostTask(
-      FROM_HERE,
-      {base::TaskPriority::BEST_EFFORT, base::MayBlock(),
-       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-      base::BindOnce(&ReportAvailableFontFamilies, std::move(font_families)));
-}
-
 }  // namespace
 
 void ActivelySampleIdentifiableSurfaces() {
   if (!blink::IdentifiabilityStudySettings::Get()->ShouldActivelySample())
     return;
   ActivelySampleUserAgentModel();
-  ActivelySampleAvailableFonts();
 }
diff --git a/chrome/browser/privacy_budget/active_sampling_unittest.cc b/chrome/browser/privacy_budget/active_sampling_unittest.cc
index 0e0a297..5b0aa0a 100644
--- a/chrome/browser/privacy_budget/active_sampling_unittest.cc
+++ b/chrome/browser/privacy_budget/active_sampling_unittest.cc
@@ -4,14 +4,12 @@
 
 #include "chrome/browser/privacy_budget/active_sampling.h"
 
-#include "base/barrier_closure.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
 #include "chrome/common/privacy_budget/privacy_budget_settings_provider.h"
 #include "chrome/common/privacy_budget/scoped_privacy_budget_config.h"
 #include "components/ukm/test_ukm_recorder.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
-#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
 
@@ -43,15 +41,13 @@
 
 TEST_F(PrivacyBudgetActiveSamplingTest, ActivelySampledSurfaces) {
   test::ScopedPrivacyBudgetConfig::Parameters parameters;
-  parameters.actively_sampled_fonts = {"Arial", "Helvetica"};
   parameters.enable_active_sampling = true;
   test::ScopedPrivacyBudgetConfig config(parameters);
   ScopedIdentifiabilityStudySettings scoped_settings;
 
   base::RunLoop run_loop;
   ukm_recorder().SetOnAddEntryCallback(
-      ukm::builders::Identifiability::kEntryName,
-      BarrierClosure(2u, run_loop.QuitClosure()));
+      ukm::builders::Identifiability::kEntryName, run_loop.QuitClosure());
   ActivelySampleIdentifiableSurfaces();
 
   // Wait for the metrics to come down the pipe.
@@ -66,10 +62,6 @@
       reported_surface_keys.push_back(metric.first);
     }
   }
-  EXPECT_THAT(reported_surface_keys,
-              testing::IsSupersetOf({
-                  18009598079355128088u,  // model
-                  9223784233214641190u,   // Arial
-                  10735872651981970214u,  // Helvetica
-              }));
+  EXPECT_EQ(reported_surface_keys,
+            std::vector<uint64_t>({18009598079355128088u}));
 }
diff --git a/chrome/browser/privacy_budget/identifiability_study_group_settings.cc b/chrome/browser/privacy_budget/identifiability_study_group_settings.cc
index 035515c1..c6af150 100644
--- a/chrome/browser/privacy_budget/identifiability_study_group_settings.cc
+++ b/chrome/browser/privacy_budget/identifiability_study_group_settings.cc
@@ -34,7 +34,8 @@
       features::kIdentifiabilityStudyAllowedRandomTypes.Get(),
       features::kIdentifiabilityStudyReidSurfaceBlocks.Get(),
       features::kIdentifiabilityStudyReidSurfaceBlocksSaltsRanges.Get(),
-      features::kIdentifiabilityStudyReidSurfaceBlocksBits.Get());
+      features::kIdentifiabilityStudyReidSurfaceBlocksBits.Get(),
+      features::kIdentifiabilityStudyReidBlocksNoiseProbabilities.Get());
 }
 
 // static
@@ -47,7 +48,8 @@
     const std::string& allowed_random_types,
     const std::string& reid_blocks,
     const std::string& reid_blocks_salts_ranges,
-    const std::string& reid_blocks_bits) {
+    const std::string& reid_blocks_bits,
+    const std::string& reid_blocks_noise_probabilities) {
   return IdentifiabilityStudyGroupSettings(
       enabled, expected_surface_count, surface_budget,
       DecodeIdentifiabilityFieldTrialParam<IdentifiableSurfaceBlocks>(blocks),
@@ -58,7 +60,9 @@
           reid_blocks),
       DecodeIdentifiabilityFieldTrialParam<std::vector<uint64_t>>(
           reid_blocks_salts_ranges),
-      DecodeIdentifiabilityFieldTrialParam<std::vector<int>>(reid_blocks_bits));
+      DecodeIdentifiabilityFieldTrialParam<std::vector<int>>(reid_blocks_bits),
+      DecodeIdentifiabilityFieldTrialParam<std::vector<double>>(
+          reid_blocks_noise_probabilities));
 }
 
 IdentifiabilityStudyGroupSettings::IdentifiabilityStudyGroupSettings(
@@ -70,7 +74,8 @@
     std::vector<blink::IdentifiableSurface::Type> allowed_random_types,
     IdentifiableSurfaceBlocks reid_blocks,
     std::vector<uint64_t> reid_blocks_salts_ranges,
-    std::vector<int> reid_blocks_bits)
+    std::vector<int> reid_blocks_bits,
+    std::vector<double> reid_blocks_noise_probabilities)
     : enabled_(enabled),
       expected_surface_count_(base::clamp<int>(
           expected_surface_count,
@@ -85,6 +90,8 @@
       reid_blocks_(std::move(reid_blocks)),
       reid_blocks_salts_ranges_(std::move(reid_blocks_salts_ranges)),
       reid_blocks_bits_(std::move(reid_blocks_bits)),
+      reid_blocks_noise_probabilities_(
+          std::move(reid_blocks_noise_probabilities)),
       allowed_random_types_(std::move(allowed_random_types)) {
   bool validates = Validate();
   UmaHistogramFinchConfigValidation(validates);
@@ -155,15 +162,22 @@
 
 bool IdentifiabilityStudyGroupSettings::ValidateReidBlockEstimator() {
   if (reid_blocks_salts_ranges_.size() != reid_blocks_.size() ||
-      reid_blocks_bits_.size() != reid_blocks_.size())
+      reid_blocks_bits_.size() != reid_blocks_.size() ||
+      reid_blocks_noise_probabilities_.size() != reid_blocks_.size())
     return false;
-  bool valid_ranges =
+  bool valid_params =
       base::ranges::all_of(reid_blocks_salts_ranges_,
                            [](uint64_t salt_range) { return salt_range > 0; });
-  return valid_ranges &&
-         base::ranges::all_of(reid_blocks_bits_, [](int reid_bits) {
-           return reid_bits > 0 && reid_bits <= 32;
-         });
+  valid_params = valid_params &&
+                 base::ranges::all_of(reid_blocks_bits_, [](int reid_bits) {
+                   return reid_bits > 0 && reid_bits <= 32;
+                 });
+
+  return valid_params && base::ranges::all_of(reid_blocks_noise_probabilities_,
+                                              [](double reid_noise) {
+                                                return reid_noise >= 0 &&
+                                                       reid_noise <= 1;
+                                              });
 }
 
 const IdentifiableSurfaceBlocks& IdentifiabilityStudyGroupSettings::blocks()
@@ -186,6 +200,11 @@
   return reid_blocks_bits_;
 }
 
+const std::vector<double>&
+IdentifiabilityStudyGroupSettings::reid_blocks_noise_probabilities() const {
+  return reid_blocks_noise_probabilities_;
+}
+
 const IdentifiableSurfaceBlocks&
 IdentifiabilityStudyGroupSettings::reid_blocks() const {
   return reid_blocks_;
diff --git a/chrome/browser/privacy_budget/identifiability_study_group_settings.h b/chrome/browser/privacy_budget/identifiability_study_group_settings.h
index 8556493..0c32a9c 100644
--- a/chrome/browser/privacy_budget/identifiability_study_group_settings.h
+++ b/chrome/browser/privacy_budget/identifiability_study_group_settings.h
@@ -28,7 +28,8 @@
       const std::string& allowed_random_types,
       const std::string& reid_blocks,
       const std::string& reid_blocks_salts_ranges,
-      const std::string& reid_blocks_bits);
+      const std::string& reid_blocks_bits,
+      const std::string& reid_blocks_noise_probabilities);
 
   IdentifiabilityStudyGroupSettings(const IdentifiabilityStudyGroupSettings&) =
       delete;
@@ -56,6 +57,7 @@
   const std::vector<double>& blocks_weights() const;
   const std::vector<uint64_t>& reid_blocks_salts_ranges() const;
   const std::vector<int>& reid_blocks_bits() const;
+  const std::vector<double>& reid_blocks_noise_probabilities() const;
   const std::vector<blink::IdentifiableSurface::Type>& allowed_random_types()
       const;
 
@@ -72,7 +74,8 @@
       std::vector<blink::IdentifiableSurface::Type> allowed_random_types,
       IdentifiableSurfaceBlocks reid_blocks,
       std::vector<uint64_t> reid_blocks_salts_ranges,
-      std::vector<int> reid_blocks_bits);
+      std::vector<int> reid_blocks_bits,
+      std::vector<double> reid_blocks_noise_probabilities);
 
   bool Validate();
   bool ValidateAssignedBlockSampling();
@@ -96,6 +99,8 @@
 
   const std::vector<int> reid_blocks_bits_;
 
+  const std::vector<double> reid_blocks_noise_probabilities_;
+
   // Surface types to sample from when random surface sampling is enabled. If
   // this vector is empty all surface types are allowed to be sampled.
   const std::vector<blink::IdentifiableSurface::Type> allowed_random_types_;
diff --git a/chrome/browser/privacy_budget/identifiability_study_group_settings_unittest.cc b/chrome/browser/privacy_budget/identifiability_study_group_settings_unittest.cc
index bcdc2bb7..e435840 100644
--- a/chrome/browser/privacy_budget/identifiability_study_group_settings_unittest.cc
+++ b/chrome/browser/privacy_budget/identifiability_study_group_settings_unittest.cc
@@ -14,7 +14,7 @@
 
 TEST_F(IdentifiabilityStudyGroupSettingsTest, Disabled) {
   auto settings = IdentifiabilityStudyGroupSettings::InitFrom(
-      false, 0, 0, "", "", "", "", "", "");
+      false, 0, 0, "", "", "", "", "", "", "");
   EXPECT_FALSE(settings.enabled());
   histogram_tester.ExpectUniqueSample(
       "PrivacyBudget.Identifiability.FinchConfigValidationResult", true, 1);
@@ -22,7 +22,7 @@
 
 TEST_F(IdentifiabilityStudyGroupSettingsTest, DisabledWithParams) {
   auto settings = IdentifiabilityStudyGroupSettings::InitFrom(
-      false, 10, 40, "", "", "", "", "", "");
+      false, 10, 40, "", "", "", "", "", "", "");
   EXPECT_FALSE(settings.enabled());
   histogram_tester.ExpectUniqueSample(
       "PrivacyBudget.Identifiability.FinchConfigValidationResult", true, 1);
@@ -30,7 +30,7 @@
 
 TEST_F(IdentifiabilityStudyGroupSettingsTest, DisabledBySurfaceCountZero) {
   auto settings = IdentifiabilityStudyGroupSettings::InitFrom(
-      true, 0, 40, "", "", "", "", "", "");
+      true, 0, 40, "", "", "", "", "", "", "");
   EXPECT_FALSE(settings.enabled());
   histogram_tester.ExpectUniqueSample(
       "PrivacyBudget.Identifiability.FinchConfigValidationResult", false, 1);
@@ -38,7 +38,7 @@
 
 TEST_F(IdentifiabilityStudyGroupSettingsTest, ValidRandomSurfaceSampling) {
   auto settings = IdentifiabilityStudyGroupSettings::InitFrom(
-      true, 10, 40, "", "", "1,4", "", "", "");
+      true, 10, 40, "", "", "1,4", "", "", "", "");
   EXPECT_TRUE(settings.enabled());
   EXPECT_FALSE(settings.IsUsingAssignedBlockSampling());
   EXPECT_TRUE(settings.IsUsingRandomSampling());
@@ -56,7 +56,7 @@
 
 TEST_F(IdentifiabilityStudyGroupSettingsTest, ValidAssignedBlockSampling) {
   auto settings = IdentifiabilityStudyGroupSettings::InitFrom(
-      true, 0, 0, "1;2,3;4,5;6", "1,1,1", "", "", "", "");
+      true, 0, 0, "1;2,3;4,5;6", "1,1,1", "", "", "", "", "");
   EXPECT_TRUE(settings.enabled());
   EXPECT_TRUE(settings.IsUsingAssignedBlockSampling());
   EXPECT_FALSE(settings.IsUsingRandomSampling());
@@ -67,7 +67,7 @@
 
 TEST_F(IdentifiabilityStudyGroupSettingsTest, InvalidNegativeWeight) {
   auto settings = IdentifiabilityStudyGroupSettings::InitFrom(
-      true, 0, 0, "1;2,3;4,5;6", "-1,1,1", "", "", "", "");
+      true, 0, 0, "1;2,3;4,5;6", "-1,1,1", "", "", "", "", "");
   EXPECT_FALSE(settings.enabled());
   histogram_tester.ExpectUniqueSample(
       "PrivacyBudget.Identifiability.FinchConfigValidationResult", false, 1);
@@ -75,7 +75,7 @@
 
 TEST_F(IdentifiabilityStudyGroupSettingsTest, InvalidSurfaceTooLikely) {
   auto settings = IdentifiabilityStudyGroupSettings::InitFrom(
-      true, 0, 0, "1;2,1;4,5;6", "1,1,1", "", "", "", "");
+      true, 0, 0, "1;2,1;4,5;6", "1,1,1", "", "", "", "", "");
   EXPECT_FALSE(settings.enabled());
   histogram_tester.ExpectUniqueSample(
       "PrivacyBudget.Identifiability.FinchConfigValidationResult", false, 1);
@@ -83,7 +83,7 @@
 
 TEST_F(IdentifiabilityStudyGroupSettingsTest, EnableSettingsForValidReidBlock) {
   auto settings = IdentifiabilityStudyGroupSettings::InitFrom(
-      true, 0, 0, "", "", "", "1;2,4;5;6", "2,2", "2,3");
+      true, 0, 0, "", "", "", "1;2,4;5;6", "2,2", "2,3", "0.1,0.2");
   EXPECT_TRUE(settings.IsUsingReidScoreEstimator());
   EXPECT_FALSE(settings.IsUsingSamplingOfSurfaces());
   EXPECT_TRUE(settings.enabled());
@@ -93,7 +93,7 @@
 
 TEST_F(IdentifiabilityStudyGroupSettingsTest, InvalidReidBlocks) {
   auto settings = IdentifiabilityStudyGroupSettings::InitFrom(
-      true, 0, 0, "", "", "", "1;2,4;5;6", "2", "2,3");
+      true, 0, 0, "", "", "", "1;2,4;5;6", "2", "2,3", "0.1,0.2");
   EXPECT_FALSE(settings.enabled());
   histogram_tester.ExpectUniqueSample(
       "PrivacyBudget.Identifiability.FinchConfigValidationResult", false, 1);
diff --git a/chrome/browser/privacy_budget/privacy_budget_browsertest.cc b/chrome/browser/privacy_budget/privacy_budget_browsertest.cc
index 4877f62..8cbf63c9 100644
--- a/chrome/browser/privacy_budget/privacy_budget_browsertest.cc
+++ b/chrome/browser/privacy_budget/privacy_budget_browsertest.cc
@@ -33,6 +33,7 @@
 #include "chrome/common/privacy_budget/privacy_budget_features.h"
 #include "chrome/common/privacy_budget/scoped_privacy_budget_config.h"
 #include "chrome/common/privacy_budget/types.h"
+#include "chrome/test/base/chrome_test_utils.h"
 #include "components/metrics_services_manager/metrics_services_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/sync/test/fake_server/fake_server.h"
@@ -649,6 +650,8 @@
 
 IN_PROC_BROWSER_TEST_F(PrivacyBudgetBrowserTestActiveSampling,
                        ActiveSamplingIsPerformed) {
+  content::NavigateToURLBlockUntilNavigationsComplete(
+      chrome_test_utils::GetActiveWebContents(this), GURL("about:blank"), 1);
   content::RunAllTasksUntilIdle();
   auto merged_entries = ukm_recorder().GetMergedEntriesByName(
       ukm::builders::Identifiability::kEntryName);
diff --git a/chrome/browser/privacy_budget/privacy_budget_reid_score_browsertest.cc b/chrome/browser/privacy_budget/privacy_budget_reid_score_browsertest.cc
index 3100734e..e29720ab 100644
--- a/chrome/browser/privacy_budget/privacy_budget_reid_score_browsertest.cc
+++ b/chrome/browser/privacy_budget/privacy_budget_reid_score_browsertest.cc
@@ -42,6 +42,7 @@
 
     parameters.reid_salts_ranges = {1};
     parameters.reid_bits = {1};
+    parameters.reid_noise = {0.01};
 
     scoped_config_.Apply(parameters);
   }
diff --git a/chrome/browser/privacy_budget/privacy_budget_reid_score_estimator.cc b/chrome/browser/privacy_budget/privacy_budget_reid_score_estimator.cc
index 46fd54d..bd27dfb 100644
--- a/chrome/browser/privacy_budget/privacy_budget_reid_score_estimator.cc
+++ b/chrome/browser/privacy_budget/privacy_budget_reid_score_estimator.cc
@@ -40,6 +40,8 @@
   IdentifiableSurfaceBlocks reid_blocks = state_settings.reid_blocks();
   reid_blocks_salts_ranges_ = state_settings.reid_blocks_salts_ranges();
   reid_blocks_bits_ = state_settings.reid_blocks_bits();
+  reid_blocks_noise_probabilities_ =
+      state_settings.reid_blocks_noise_probabilities();
 
   // Step 2: Get the type of the Reid surface.
   constexpr auto kReidScoreType =
@@ -93,7 +95,7 @@
           // Compute the Reid hash for the needed Reid block.
           uint64_t reid_hash = ComputeHashForReidScore(
               *surface_map, reid_blocks_salts_ranges_.at(i),
-              reid_blocks_bits_.at(i));
+              reid_blocks_bits_.at(i), reid_blocks_noise_probabilities_.at(i));
           // Report to UKM in a separate task in order to avoid re-entrancy.
           base::SequencedTaskRunnerHandle::Get()->PostTask(
               FROM_HERE, base::BindOnce(&ReportHashForReidScore, map_itr.first,
@@ -108,7 +110,8 @@
 uint64_t PrivacyBudgetReidScoreEstimator::ComputeHashForReidScore(
     const SurfacesAndOptionalValues& surface_map,
     uint64_t max_num_salt,
-    int reid_bits) {
+    int reid_bits,
+    double reid_noise_probability) {
   std::vector<uint64_t> tokens;
   uint64_t salt = base::RandGenerator(max_num_salt);
 
@@ -117,11 +120,18 @@
     tokens.emplace_back(
         static_cast<uint64_t>(surface_itr.second->ToUkmMetricValue()));
   }
-  // Use the hash function embedded in IdentifiableToken.
-  uint64_t reid_hash = blink::IdentifiabilityDigestOfBytes(
-      base::as_bytes(base::make_span(tokens)));
+  // Initialize Reid hash with random noise.
+  uint64_t reid_hash = base::RandUint64();
+  // Calculate the real hash if the random number is greater than the Reid noise
+  // probability.
+  if (base::RandDouble() >= reid_noise_probability) {
+    // Use the hash function embedded in IdentifiableToken.
+    reid_hash = blink::IdentifiabilityDigestOfBytes(
+        base::as_bytes(base::make_span(tokens)));
+  }
   // Create mask based on reid_bits required.
-  uint64_t mask = (1 << reid_bits) - 1;
+  constexpr uint64_t kTypedOne = 1;
+  uint64_t mask = (kTypedOne << reid_bits) - 1;
   uint64_t needed_bits = reid_hash & mask;
   // Return salt in the left 32 bits and Reid b-bits hash in the right 32 bits.
   return ((salt << 32) | needed_bits);
diff --git a/chrome/browser/privacy_budget/privacy_budget_reid_score_estimator.h b/chrome/browser/privacy_budget/privacy_budget_reid_score_estimator.h
index b251286..d8365df 100644
--- a/chrome/browser/privacy_budget/privacy_budget_reid_score_estimator.h
+++ b/chrome/browser/privacy_budget/privacy_budget_reid_score_estimator.h
@@ -43,6 +43,10 @@
   // surface block.
   std::vector<int> reid_blocks_bits_;
 
+  // Keeps track of the probability of noise that should be reported for every
+  // Reid surface block.
+  std::vector<double> reid_blocks_noise_probabilities_;
+
   // Keeps track of the number of reported surfaces in every Reid surface block.
   // The Reid surface map at index i is full when the count_flag_ at i is equal
   // to the number of surfaces in that map i.e. size of the map.
@@ -51,7 +55,8 @@
   // Compute the hash for estimating the REID score.
   uint64_t ComputeHashForReidScore(const SurfacesAndOptionalValues& surface_map,
                                    uint64_t max_num_salt,
-                                   int reid_bits);
+                                   int reid_bits,
+                                   double reid_noise_probability);
 };
 
 #endif  // CHROME_BROWSER_PRIVACY_BUDGET_PRIVACY_BUDGET_UKM_ENTRY_FILTER_H_
diff --git a/chrome/browser/privacy_budget/privacy_budget_reid_score_estimator_unittest.cc b/chrome/browser/privacy_budget/privacy_budget_reid_score_estimator_unittest.cc
index 611c6c0..d1881a0 100644
--- a/chrome/browser/privacy_budget/privacy_budget_reid_score_estimator_unittest.cc
+++ b/chrome/browser/privacy_budget/privacy_budget_reid_score_estimator_unittest.cc
@@ -5,6 +5,7 @@
 #include <cstdint>
 
 #include "base/barrier_closure.h"
+#include "base/containers/flat_set.h"
 #include "base/rand_util.h"
 #include "base/test/task_environment.h"
 #include "chrome/browser/privacy_budget/identifiability_study_group_settings.h"
@@ -17,7 +18,7 @@
 TEST(PrivacyBudgetReidScoreEstimatorStandaloneTest,
      ReportReidFixedTokenRandomSalt) {
   auto settings = IdentifiabilityStudyGroupSettings::InitFrom(
-      true, 0, 0, "", "", "", "2077075229;1122849309", "1000000", "1");
+      true, 0, 0, "", "", "", "2077075229;1122849309", "1000000", "1", "0");
 
   constexpr auto surface_1 =
       blink::IdentifiableSurface::FromMetricHash(2077075229u);
@@ -78,7 +79,7 @@
 TEST(PrivacyBudgetReidScoreEstimatorStandaloneTest,
      ReportReidRandomTokenFixedSalt) {
   auto settings = IdentifiabilityStudyGroupSettings::InitFrom(
-      true, 0, 0, "", "", "", "2077075229;1122849309", "1", "1");
+      true, 0, 0, "", "", "", "2077075229;1122849309", "1", "1", "0");
   constexpr auto surface_1 =
       blink::IdentifiableSurface::FromMetricHash(2077075229u);
   constexpr auto surface_2 =
@@ -134,3 +135,57 @@
   EXPECT_TRUE(has_value_0);
   EXPECT_TRUE(has_value_1);
 }
+
+TEST(PrivacyBudgetReidScoreEstimatorStandaloneTest,
+     ReportReidFixedTokenFixedSaltAllNoise) {
+  auto settings = IdentifiabilityStudyGroupSettings::InitFrom(
+      true, 0, 0, "", "", "", "2077075229;1122849309", "1", "32", "1");
+
+  constexpr auto surface_1 =
+      blink::IdentifiableSurface::FromMetricHash(2077075229u);
+  constexpr auto surface_2 =
+      blink::IdentifiableSurface::FromMetricHash(1122849309u);
+
+  int64_t token1 = 1234;
+  int64_t token2 = 12345;
+  constexpr int num_iterations = 50;
+  base::test::SingleThreadTaskEnvironment task_environment;
+  ukm::TestAutoSetUkmRecorder test_recorder;
+  base::RunLoop run_loop;
+  test_recorder.SetOnAddEntryCallback(
+      ukm::builders::Identifiability::kEntryName,
+      base::BarrierClosure(num_iterations, run_loop.QuitClosure()));
+  blink::test::ScopedIdentifiabilityTestSampleCollector collector;
+  for (int i = 0; i < num_iterations; ++i) {
+    auto reid_storage =
+        std::make_unique<PrivacyBudgetReidScoreEstimator>(settings);
+    // Process values for 2 surfaces.
+    reid_storage->ProcessForReidScore(surface_1,
+                                      blink::IdentifiableToken(token1));
+    reid_storage->ProcessForReidScore(surface_2,
+                                      blink::IdentifiableToken(token2));
+  }
+  // This should let the async tasks run.
+  run_loop.Run();
+  const auto& entries = collector.entries();
+  base::flat_set<uint32_t> reid_results;
+  int count = 0;
+  for (auto& entry : entries) {
+    for (auto& metric : entry.metrics) {
+      auto surface = metric.surface;
+      if (surface.GetType() ==
+          blink::IdentifiableSurface::Type::kReidScoreEstimator) {
+        EXPECT_EQ(metric.surface.ToUkmMetricHash(), 7415899889871487013u);
+        ++count;
+        uint64_t hash = static_cast<uint64_t>(metric.value.ToUkmMetricValue());
+        uint32_t reid_bits = hash & 0xFFFFFFFF;
+        // Result should be noise i.e. didn't appeared before.
+        EXPECT_FALSE(reid_results.contains(reid_bits));
+        reid_results.insert(reid_bits);
+        uint32_t salt = (hash >> 32);
+        EXPECT_EQ(salt, 0u);
+      }
+    }
+  }
+  EXPECT_EQ(count, num_iterations);
+}
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index e4af92bd..a225aad 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -438,6 +438,19 @@
   DCHECK(!path.empty()) << "Using an empty path will attempt to write "
                         << "profile files to the root directory!";
 
+  if (path == ProfileManager::GetGuestProfilePath()) {
+    profile_metrics::SetBrowserProfileType(
+        this, profile_metrics::BrowserProfileType::kGuest);
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
+  } else if (path == ProfileManager::GetSystemProfilePath()) {
+    profile_metrics::SetBrowserProfileType(
+        this, profile_metrics::BrowserProfileType::kSystem);
+#endif
+  } else {
+    profile_metrics::SetBrowserProfileType(
+        this, profile_metrics::BrowserProfileType::kRegular);
+  }
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   const bool is_regular_profile = ash::ProfileHelper::IsRegularProfile(this);
 
@@ -455,19 +468,6 @@
   }
 #endif
 
-  if (path == ProfileManager::GetGuestProfilePath()) {
-      profile_metrics::SetBrowserProfileType(
-          this, profile_metrics::BrowserProfileType::kGuest);
-#if !BUILDFLAG(IS_CHROMEOS_ASH)
-  } else if (path == ProfileManager::GetSystemProfilePath()) {
-    profile_metrics::SetBrowserProfileType(
-        this, profile_metrics::BrowserProfileType::kSystem);
-#endif
-  } else {
-    profile_metrics::SetBrowserProfileType(
-        this, profile_metrics::BrowserProfileType::kRegular);
-  }
-
   // The ProfileImpl can be created both synchronously and asynchronously.
   bool async_prefs = create_mode == CREATE_MODE_ASYNCHRONOUS;
 
diff --git a/chrome/browser/profiles/profile_keyed_service_browsertest.cc b/chrome/browser/profiles/profile_keyed_service_browsertest.cc
index 0fc758d..c11916fd 100644
--- a/chrome/browser/profiles/profile_keyed_service_browsertest.cc
+++ b/chrome/browser/profiles/profile_keyed_service_browsertest.cc
@@ -237,7 +237,6 @@
     "AccessCodeSinkService",
     "AccessContextAuditService",
     "AccessibilityLabelsService",
-    "AccountConsistencyModeManager",
     "AccountInvestigator",
     "AccountPasswordStore",
     "AccountReconcilor",
diff --git a/chrome/browser/profiles/profile_keyed_service_factory.cc b/chrome/browser/profiles/profile_keyed_service_factory.cc
new file mode 100644
index 0000000..77086652
--- /dev/null
+++ b/chrome/browser/profiles/profile_keyed_service_factory.cc
@@ -0,0 +1,164 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
+
+#include "base/memory/ptr_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "chrome/browser/ash/profiles/profile_helper.h"
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
+
+namespace {
+
+Profile* ApplyProfileSelection(Profile* profile, ProfileSelection selection) {
+  switch (selection) {
+    case ProfileSelection::kNone:
+      return nullptr;
+    case ProfileSelection::kOriginalOnly:
+      return profile->IsOffTheRecord() ? nullptr : profile;
+    case ProfileSelection::kOwnInstance:
+      return profile;
+    case ProfileSelection::kRedirectedToOriginal:
+      return profile->GetOriginalProfile();
+    case ProfileSelection::kOffTheRecordOnly:
+      return profile->IsOffTheRecord() ? profile : nullptr;
+  }
+}
+
+}  // namespace
+
+ProfileSelections::Builder::Builder()
+    : selections_(base::WrapUnique(new ProfileSelections())) {}
+
+ProfileSelections::Builder::~Builder() = default;
+
+ProfileSelections::Builder& ProfileSelections::Builder::WithRegular(
+    ProfileSelection selection) {
+  selections_->SetProfileSelectionForRegular(selection);
+  return *this;
+}
+
+ProfileSelections::Builder& ProfileSelections::Builder::WithGuest(
+    ProfileSelection selection) {
+  selections_->SetProfileSelectionForGuest(selection);
+  return *this;
+}
+
+ProfileSelections::Builder& ProfileSelections::Builder::WithSystem(
+    ProfileSelection selection) {
+  selections_->SetProfileSelectionForSystem(selection);
+  return *this;
+}
+
+ProfileSelections ProfileSelections::Builder::Build() {
+  DCHECK(selections_) << "Build() already called";
+
+  ProfileSelections to_return = *selections_;
+  selections_.reset();
+
+  return to_return;
+}
+
+ProfileSelections::ProfileSelections() = default;
+ProfileSelections::~ProfileSelections() = default;
+ProfileSelections::ProfileSelections(const ProfileSelections& other) = default;
+
+ProfileSelections ProfileSelections::BuildDefault() {
+  return ProfileSelections::Builder().Build();
+}
+
+ProfileSelections ProfileSelections::BuildNoServicesForAllProfiles() {
+  return ProfileSelections::Builder()
+      .WithRegular(ProfileSelection::kNone)
+      .Build();
+}
+
+ProfileSelections ProfileSelections::BuildServicesForRegularProfile() {
+  return ProfileSelections::Builder()
+      .WithGuest(ProfileSelection::kNone)
+      .WithSystem(ProfileSelection::kNone)
+      .Build();
+}
+
+ProfileSelections ProfileSelections::BuildServicesRedirectedInIncognito() {
+  return ProfileSelections::Builder()
+      .WithRegular(ProfileSelection::kRedirectedToOriginal)
+      .WithGuest(ProfileSelection::kNone)
+      .WithSystem(ProfileSelection::kNone)
+      .Build();
+}
+
+ProfileSelections ProfileSelections::BuildServicesRedirectedInOTR() {
+  return ProfileSelections::Builder()
+      .WithRegular(ProfileSelection::kRedirectedToOriginal)
+      .Build();
+}
+
+ProfileSelection ProfileSelections::GetProfileSelection(
+    Profile* profile) const {
+  // Treat other off the record profiles as Incognito (primary otr) Profiles.
+  if (profile->IsRegularProfile() || profile->IsIncognitoProfile() ||
+      profile_metrics::GetBrowserProfileType(profile) ==
+          profile_metrics::BrowserProfileType::kOtherOffTheRecordProfile)
+    return regular_profile_selection_;
+
+  if (profile->IsGuestSession()) {
+    // if the default value for GuestProfile is overridden, use it.
+    // otherwise, redirect to the old behavior (same as regular profile).
+    // This is used for both original guest profile (not user visible) and for
+    // the off-the-record guest (user visible, ui guest session).
+    return guest_profile_selection_.value_or(regular_profile_selection_);
+  }
+
+  if (profile->IsSystemProfile()) {
+    // if the default value for SystemProfile is overridden, use it.
+    // otherwise, redirect to the old behavior (same as regular profile).
+    // This is used for both original system profile (not user visible) and for
+    // the off-the-record system profile (used in the Profile Picker).
+    return system_profile_selection_.value_or(regular_profile_selection_);
+  }
+
+  NOTREACHED();
+  return ProfileSelection::kNone;
+}
+
+void ProfileSelections::SetProfileSelectionForRegular(
+    ProfileSelection selection) {
+  regular_profile_selection_ = selection;
+}
+
+void ProfileSelections::SetProfileSelectionForGuest(
+    ProfileSelection selection) {
+  guest_profile_selection_ = selection;
+}
+
+void ProfileSelections::SetProfileSelectionForSystem(
+    ProfileSelection selection) {
+  system_profile_selection_ = selection;
+}
+
+ProfileKeyedServiceFactory::ProfileKeyedServiceFactory(const char* name)
+    : ProfileKeyedServiceFactory(name, ProfileSelections::BuildDefault()) {}
+
+ProfileKeyedServiceFactory::ProfileKeyedServiceFactory(
+    const char* name,
+    const ProfileSelections& profile_selections)
+    : BrowserContextKeyedServiceFactory(
+          name,
+          BrowserContextDependencyManager::GetInstance()),
+      profile_selections_(profile_selections) {}
+
+ProfileKeyedServiceFactory::~ProfileKeyedServiceFactory() = default;
+
+// BrowserContextKeyedServiceFactory
+content::BrowserContext* ProfileKeyedServiceFactory::GetBrowserContextToUse(
+    content::BrowserContext* context) const {
+  Profile* profile = Profile::FromBrowserContext(context);
+  ProfileSelection selection = profile_selections_.GetProfileSelection(profile);
+
+  return ApplyProfileSelection(profile, selection);
+}
diff --git a/chrome/browser/profiles/profile_keyed_service_factory.h b/chrome/browser/profiles/profile_keyed_service_factory.h
new file mode 100644
index 0000000..9441097
--- /dev/null
+++ b/chrome/browser/profiles/profile_keyed_service_factory.h
@@ -0,0 +1,186 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PROFILES_PROFILE_KEYED_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_PROFILES_PROFILE_KEYED_SERVICE_FACTORY_H_
+
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+#include "base/containers/flat_map.h"
+#include "components/profile_metrics/browser_profile_type.h"
+
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+// Purpose of this API:
+// Provide a Profile type specific implementation logic for
+// `KeyedServiceFactory` under chrome/.
+//
+// - `ProfileSelection`: Enum used to map the logic of selecting the right
+// profile for the service to be created for, based on the given profile.
+// - `ProfileSelections`: Helper structure that contains a
+// `ProfileSelection` value for each main Profile type (Regular, Guest and
+// System).
+//     - `ProfileSelections::Builder`: Used to easily create
+//     `ProfileSelections`.
+// - `ProfileKeyedServiceFactory`: Intermediate Factory class that inherits from
+// `BrowserContextKeyedServiceFactory`. Main purpose of this intermediate class
+// is to provide an easy and efficient way to provide the redirection logic for
+// each main profile types using `ProfileSelections` instance.
+
+class Profile;
+
+// Enum that sets the Profile Redirection logic given a Profile.
+enum class ProfileSelection {
+  kNone,                  // Original: No Profile  --  OTR: No Profile
+  kOriginalOnly,          // Original: Self        --  OTR: No Profile
+  kOwnInstance,           // Original: Self        --  OTR: Self
+  kRedirectedToOriginal,  // Original: Self        --  OTR: Original
+  kOffTheRecordOnly       // Original: No Profile  --  OTR: Self
+};
+
+// Contains the logic for ProfileSelection for the different main Profile types
+// (Regular, Guest and System). Each of these profile types also have Off the
+// Record profiles equivalent, e.g. Incognito is Off the Record profile for
+// Regular profile, the Guest user-visible profile is off-the-record, the
+// Profile Picker uses the off-the-record System Profile.
+// Maps Profile types to `ProfileSelection`.
+class ProfileSelections {
+ public:
+  ProfileSelections(const ProfileSelections& other);
+  ~ProfileSelections();
+
+  // - Predefined `ProfileSelections`
+
+  // Default implementation, as of now:
+  // - No services in OTR.
+  // - Regular profile returns itself (original).
+  // - Guest and System profiles follow Regular profile behaviour.
+  //
+  // After the migration(crbug.com/1284664) this default behaviour will change.
+  // It will be similar to the current `BuildServicesForRegularProfile()`.
+  // - No services in OTR.
+  // - Regular profile returns itself (original).
+  // - No services for Guest and System profile.
+  static ProfileSelections BuildDefault();
+
+  // No services for all profiles.
+  static ProfileSelections BuildNoServicesForAllProfiles();
+
+  // Only build services for the regular profile.
+  static ProfileSelections BuildServicesForRegularProfile();
+
+  // Redirects building services for incognito profile to regular Profile.
+  static ProfileSelections BuildServicesRedirectedInIncognito();
+
+  // Redirects building services for both OTR and Original profile to Original
+  // Profile for all profile types (Regular, Guest and System).
+  static ProfileSelections BuildServicesRedirectedInOTR();
+
+  // Builder to construct the `ProfileSelections` parameters.
+  class Builder {
+   public:
+    Builder();
+    ~Builder();
+
+    // Builder setters
+    Builder& WithRegular(ProfileSelection selection);
+    Builder& WithGuest(ProfileSelection selection);
+    Builder& WithSystem(ProfileSelection selection);
+
+    // Builds the `ProfileSelections`.
+    ProfileSelections Build();
+
+   private:
+    std::unique_ptr<ProfileSelections> selections_;
+  };
+
+  // Returns the ProfileSelection based on the profile information through the
+  // set mapping.
+  ProfileSelection GetProfileSelection(Profile* profile) const;
+
+ private:
+  // Default constructor settings sets Regular Profile ->
+  // `ProfileSelection::kOriginalOnly`. It should be constructed through the
+  // Builder. Value for Guest and System profile not being overridden will
+  // default to the behaviour of Regular Profile.
+  ProfileSelections();
+
+  void SetProfileSelectionForRegular(ProfileSelection selection);
+  void SetProfileSelectionForGuest(ProfileSelection selection);
+  void SetProfileSelectionForSystem(ProfileSelection selection);
+
+  // Default value for the mapping of
+  // Regular Profile -> `ProfileSelection::kOriginalOnly`
+  // Not assigning values for Guest and System Profiles now defaults to the
+  // behavior of regular profiles This will change later on to default to kNone.
+  ProfileSelection regular_profile_selection_ = ProfileSelection::kOriginalOnly;
+  absl::optional<ProfileSelection> guest_profile_selection_;
+  absl::optional<ProfileSelection> system_profile_selection_;
+};
+
+// An intermediate interface to create KeyedServiceFactory under chrome/ that
+// provides a more restricted default creation of services for non regular
+// profiles.
+// Those profile choices are overridable by setting the proper combination of
+// `ProfileSelection` and Profile type in the `ProfileSelections` passed in the
+// constructor.
+//
+// - Example usage, for a factory redirecting in incognito.
+//
+// class MyRedirectingKeyedServiceFactory: public ProfileKeyedServiceFactory {
+//  private:
+//   MyRedirectingKeyedServiceFactory()
+//       : ProfileKeyedServiceFactory(
+//             "MyRedirectingKeyedService",
+//             ProfileSelections::BuildServicesRedirectedInIncognito()) {}
+//
+//   KeyedService* BuildServiceInstanceFor(
+//       content::BrowserContext* context) const override {
+//     return new MyRedirectingKeyedService();
+//   }
+// };
+//
+//
+// - Example service that does not exist in OTR (default behavior):
+//
+// class MyDefaultKeyedServiceFactory: public ProfileKeyedServiceFactory {
+//  private:
+//   MyDefaultKeyedServiceFactory()
+//       : ProfileKeyedServiceFactory("MyDefaultKeyedService") {}
+//
+//   KeyedService* BuildServiceInstanceFor(
+//       content::BrowserContext* context) const override {
+//     return new MyDefaultKeyedService();
+//   }
+// };
+class ProfileKeyedServiceFactory : public BrowserContextKeyedServiceFactory {
+ public:
+  ProfileKeyedServiceFactory(const ProfileKeyedServiceFactory&) = delete;
+  ProfileKeyedServiceFactory& operator=(const ProfileKeyedServiceFactory&) =
+      delete;
+
+ protected:
+  // Default constructor, will build the Factory with the default implementation
+  // for `ProfileSelections`.
+  explicit ProfileKeyedServiceFactory(const char* name);
+  // Constructor taking in the overridden `ProfileSelections` for customized
+  // Profile types service creation. This is the only way to override the
+  // `ProfileSelections` value.
+  ProfileKeyedServiceFactory(const char* name,
+                             const ProfileSelections& profile_selections);
+  ~ProfileKeyedServiceFactory() override;
+
+  // BrowserContextKeyedServiceFactory
+  // Final implementation of `GetBrowserContextToUse()`.
+  // Selects the given context to proper context to use based on the
+  // mapping in `ProfileSelections`.
+  content::BrowserContext* GetBrowserContextToUse(
+      content::BrowserContext* context) const final;
+
+ private:
+  // Value can only be set at construction.
+  ProfileSelections profile_selections_;
+};
+
+#endif  // !CHROME_BROWSER_PROFILES_PROFILE_KEYED_SERVICE_FACTORY_H_
diff --git a/chrome/browser/profiles/profile_window_browsertest.cc b/chrome/browser/profiles/profile_window_browsertest.cc
index 5361a3e..b8671de 100644
--- a/chrome/browser/profiles/profile_window_browsertest.cc
+++ b/chrome/browser/profiles/profile_window_browsertest.cc
@@ -296,14 +296,12 @@
   // Verify the normal browser has a bookmark menu.
   AppMenuModel model_normal_profile(&accelerator_handler, browser());
   model_normal_profile.Init();
-  EXPECT_TRUE(
-      model_normal_profile.GetIndexOfCommandId(IDC_BOOKMARKS_MENU).has_value());
+  EXPECT_NE(-1, model_normal_profile.GetIndexOfCommandId(IDC_BOOKMARKS_MENU));
 
   // Guest browser has no bookmark menu.
   Browser* guest_browser = CreateGuestBrowser();
   AppMenuModel model_guest_profile(&accelerator_handler, guest_browser);
-  EXPECT_FALSE(
-      model_guest_profile.GetIndexOfCommandId(IDC_BOOKMARKS_MENU).has_value());
+  EXPECT_EQ(-1, model_guest_profile.GetIndexOfCommandId(IDC_BOOKMARKS_MENU));
 }
 
 IN_PROC_BROWSER_TEST_F(ProfileWindowBrowserTest, OpenBrowserWindowForProfile) {
diff --git a/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc b/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc
index f280ed8..4926abc 100644
--- a/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc
@@ -136,7 +136,7 @@
   // them. This works in non-mock because of toolkit_delegate_ in RVCMBase.
   // TODO(yusukes,lazyboy): This is a hack. RVCMProxy should neither directly
   // know about but submenu items nor it should update them.
-  for (size_t i = 0; i < model->GetItemCount(); ++i) {
+  for (int i = 0; i < model->GetItemCount(); ++i) {
     MockMenuItem sub_item;
     sub_item.command_id = model->GetCommandIdAt(i);
     sub_item.enabled = model->IsEnabledAt(i);
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 0dbc60e..caeace74 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -1124,10 +1124,10 @@
   }
 
   // Remove any redundant trailing separator.
-  size_t count = menu_model_.GetItemCount();
-  if (count > 0 &&
-      menu_model_.GetTypeAt(count - 1) == ui::MenuModel::TYPE_SEPARATOR) {
-    menu_model_.RemoveItemAt(count - 1);
+  int index = menu_model_.GetItemCount() - 1;
+  if (index >= 0 &&
+      menu_model_.GetTypeAt(index) == ui::MenuModel::TYPE_SEPARATOR) {
+    menu_model_.RemoveItemAt(index);
   }
 
   // If there is only one item and it is the Accessibility labels item, remove
@@ -1984,8 +1984,7 @@
   if (!IsDevToolsURL(params_.page_url) &&
       !content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PRINT) &&
       (!menu_model_.GetItemCount() ||
-       menu_model_.GetIndexOfCommandId(IDC_CONTENT_CONTEXT_EMOJI)
-           .has_value())) {
+       menu_model_.GetIndexOfCommandId(IDC_CONTENT_CONTEXT_EMOJI) != -1)) {
     menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_UNDO,
                                     IDS_CONTENT_CONTEXT_UNDO);
     menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_REDO,
@@ -2015,8 +2014,7 @@
   if (clipboard_history_controller &&
       clipboard_history_controller->ShouldShowNewFeatureBadge()) {
     menu_model_.SetIsNewFeatureAt(
-        menu_model_.GetIndexOfCommandId(IDC_CONTENT_CLIPBOARD_HISTORY_MENU)
-            .value(),
+        menu_model_.GetIndexOfCommandId(IDC_CONTENT_CLIPBOARD_HISTORY_MENU),
         true);
     clipboard_history_controller->MarkNewFeatureBadgeShown();
   }
@@ -2138,10 +2136,10 @@
 }
 
 void RenderViewContextMenu::AppendSharingItems() {
-  size_t items_initial = menu_model_.GetItemCount();
+  int items_initial = menu_model_.GetItemCount();
   menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
   // Check if the starting separator got added.
-  size_t items_before_sharing = menu_model_.GetItemCount();
+  int items_before_sharing = menu_model_.GetItemCount();
   bool starting_separator_added = items_before_sharing > items_initial;
 
 #if !BUILDFLAG(IS_FUCHSIA)
@@ -2150,7 +2148,7 @@
 
   // Add an ending separator if there are sharing items, otherwise remove the
   // starting separator iff we added one above.
-  size_t sharing_items = menu_model_.GetItemCount() - items_before_sharing;
+  int sharing_items = menu_model_.GetItemCount() - items_before_sharing;
   if (sharing_items > 0)
     menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
   else if (starting_separator_added)
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
index 3a43dc9..de586700 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -1440,11 +1440,11 @@
     ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_COPYLINKLOCATION));
     // As soon as at least three profiles exist, we show all profiles in a
     // submenu.
-    ui::MenuModel* model = nullptr;
-    size_t index = 0;
+    ui::MenuModel* model = NULL;
+    int index = -1;
     ASSERT_TRUE(menu->GetMenuModelAndItemIndex(IDC_OPEN_LINK_IN_PROFILE_FIRST,
                                                &model, &index));
-    ASSERT_EQ(2u, model->GetItemCount());
+    ASSERT_EQ(2, model->GetItemCount());
     ASSERT_FALSE(menu->IsItemInRangePresent(IDC_OPEN_LINK_IN_PROFILE_FIRST,
                                             IDC_OPEN_LINK_IN_PROFILE_LAST));
   }
@@ -1508,11 +1508,11 @@
       CreateContextMenuMediaTypeNone(url, url));
 
   // Verify that the size of the menu is correct.
-  ui::MenuModel* model = nullptr;
-  size_t index = 0;
+  ui::MenuModel* model = NULL;
+  int index = -1;
   ASSERT_TRUE(menu->GetMenuModelAndItemIndex(IDC_OPEN_LINK_IN_PROFILE_FIRST,
                                              &model, &index));
-  ASSERT_EQ(profiles_in_menu.size(), model->GetItemCount());
+  ASSERT_EQ(static_cast<int>(profiles_in_menu.size()), model->GetItemCount());
 
   // Open the menu items. They should match their corresponding profiles in
   // |profiles_in_menu|.
@@ -1572,7 +1572,7 @@
 
   // Verify that the Open in Profile option is shown.
   ui::MenuModel* model = nullptr;
-  size_t index = 0;
+  int index;
   ASSERT_TRUE(menu.GetMenuModelAndItemIndex(IDC_OPEN_LINK_IN_PROFILE_FIRST,
                                             &model, &index));
 
@@ -2641,10 +2641,10 @@
     ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_COPYLINKLOCATION));
     // With at least two secondary profiles, they are displayed in a submenu.
     ui::MenuModel* model = nullptr;
-    size_t index = 0;
+    int index = -1;
     ASSERT_TRUE(menu->GetMenuModelAndItemIndex(IDC_OPEN_LINK_IN_PROFILE_FIRST,
                                                &model, &index));
-    ASSERT_EQ(2u, model->GetItemCount());
+    ASSERT_EQ(2, model->GetItemCount());
     ASSERT_FALSE(menu->IsItemInRangePresent(IDC_OPEN_LINK_IN_PROFILE_FIRST,
                                             IDC_OPEN_LINK_IN_PROFILE_LAST));
   }
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.cc
index 4f2659c..1d76d45 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.cc
@@ -80,7 +80,7 @@
 
   const ui::SimpleMenuModel& menu_model = context_menu->menu_model();
   captured_command_ids_.reserve(menu_model.GetItemCount());
-  for (size_t i = 0; i < menu_model.GetItemCount(); ++i)
+  for (int i = 0; i < menu_model.GetItemCount(); ++i)
     captured_command_ids_.push_back(menu_model.GetCommandIdAt(i));
 
   if (maybe_command_to_execute_)
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc
index 1a93587..19f2009 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc
@@ -40,13 +40,12 @@
 }
 
 bool TestRenderViewContextMenu::IsItemPresent(int command_id) const {
-  return menu_model_.GetIndexOfCommandId(command_id).has_value();
+  return menu_model_.GetIndexOfCommandId(command_id) != -1;
 }
 
 bool TestRenderViewContextMenu::IsItemChecked(int command_id) const {
-  const absl::optional<size_t> index =
-      menu_model_.GetIndexOfCommandId(command_id);
-  return index.has_value() && menu_model_.IsItemCheckedAt(index.value());
+  return menu_model_.IsItemCheckedAt(
+      menu_model_.GetIndexOfCommandId(command_id));
 }
 
 bool TestRenderViewContextMenu::IsItemInRangePresent(
@@ -64,14 +63,14 @@
 bool TestRenderViewContextMenu::GetMenuModelAndItemIndex(
     int command_id,
     MenuModel** found_model,
-    size_t* found_index) {
+    int* found_index) {
   std::vector<MenuModel*> models_to_search;
   models_to_search.push_back(&menu_model_);
 
   while (!models_to_search.empty()) {
     MenuModel* model = models_to_search.back();
     models_to_search.pop_back();
-    for (size_t i = 0; i < model->GetItemCount(); i++) {
+    for (int i = 0; i < model->GetItemCount(); i++) {
       if (model->GetCommandIdAt(i) == command_id) {
         *found_model = model;
         *found_index = i;
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h
index c75b006..27a661d 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h
@@ -72,7 +72,7 @@
   // returned in |found_model| and |found_index|. Otherwise returns false.
   bool GetMenuModelAndItemIndex(int command_id,
                                 ui::MenuModel** found_model,
-                                size_t* found_index);
+                                int* found_index);
 
   // Returns the command id of the menu item with the specified |path|.
   int GetCommandIDByProfilePath(const base::FilePath& path) const;
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc
index c850816..018a847 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc
@@ -433,7 +433,7 @@
   const ui::MenuModel& model = menu->menu_model();
   std::u16string expected_title = u"Added by an extension";
   int num_items_found = 0;
-  for (size_t i = 0; i < model.GetItemCount(); ++i) {
+  for (int i = 0; i < model.GetItemCount(); ++i) {
     if (expected_title == model.GetLabelAt(i))
       ++num_items_found;
   }
diff --git a/chrome/browser/renderer_host/chrome_extension_message_filter.cc b/chrome/browser/renderer_host/chrome_extension_message_filter.cc
index 6636018..a62aca5 100644
--- a/chrome/browser/renderer_host/chrome_extension_message_filter.cc
+++ b/chrome/browser/renderer_host/chrome_extension_message_filter.cc
@@ -194,11 +194,10 @@
   scoped_refptr<extensions::Action> action = new extensions::Action(
       extension_id, base::Time::Now(), extensions::Action::ACTION_API_CALL,
       params.api_call);
-  action->set_args(base::ListValue::From(
-      std::make_unique<base::Value>(params.arguments.Clone())));
+  action->set_args(params.arguments.Clone());
   if (!params.extra.empty()) {
-    action->mutable_other()->SetString(
-        activity_log_constants::kActionExtra, params.extra);
+    action->mutable_other().Set(activity_log_constants::kActionExtra,
+                                params.extra);
   }
   AddActionToExtensionActivityLog(profile_, activity_log_, action);
 }
@@ -212,12 +211,12 @@
   scoped_refptr<extensions::Action> action = new extensions::Action(
       extension_id, base::Time::Now(), extensions::Action::ACTION_DOM_ACCESS,
       params.api_call);
-  action->set_args(base::ListValue::From(
-      std::make_unique<base::Value>(params.arguments.Clone())));
+  if (params.arguments.is_list())
+    action->set_args(params.arguments.GetList().Clone());
   action->set_page_url(params.url);
   action->set_page_title(base::UTF16ToUTF8(params.url_title));
-  action->mutable_other()->SetInteger(activity_log_constants::kActionDomVerb,
-                                      params.call_type);
+  action->mutable_other().Set(activity_log_constants::kActionDomVerb,
+                              params.call_type);
   AddActionToExtensionActivityLog(profile_, activity_log_, action);
 }
 
@@ -230,11 +229,10 @@
   scoped_refptr<extensions::Action> action = new extensions::Action(
       extension_id, base::Time::Now(), extensions::Action::ACTION_API_EVENT,
       params.api_call);
-  action->set_args(base::ListValue::From(
-      std::make_unique<base::Value>(params.arguments.Clone())));
+  action->set_args(params.arguments.Clone());
   if (!params.extra.empty()) {
-    action->mutable_other()->SetString(activity_log_constants::kActionExtra,
-                                       params.extra);
+    action->mutable_other().Set(activity_log_constants::kActionExtra,
+                                params.extra);
   }
   AddActionToExtensionActivityLog(profile_, activity_log_, action);
 }
diff --git a/chrome/browser/resources/history/browser_service.ts b/chrome/browser/resources/history/browser_service.ts
index 26e2f09..4372235 100644
--- a/chrome/browser/resources/history/browser_service.ts
+++ b/chrome/browser/resources/history/browser_service.ts
@@ -38,7 +38,7 @@
   otherDevicesInitialized(): void;
   queryHistoryContinuation(): Promise<QueryResult>;
   queryHistory(searchTerm: string): Promise<QueryResult>;
-  startSignInFlow(): void;
+  startTurnOnSyncFlow(): void;
 }
 
 export class BrowserServiceImpl implements BrowserService {
@@ -128,8 +128,8 @@
     return sendWithPromise('queryHistory', searchTerm, RESULTS_PER_PAGE);
   }
 
-  startSignInFlow() {
-    chrome.send('startSignInFlow');
+  startTurnOnSyncFlow() {
+    chrome.send('startTurnOnSyncFlow');
   }
 
   static getInstance(): BrowserService {
diff --git a/chrome/browser/resources/history/synced_device_manager.html b/chrome/browser/resources/history/synced_device_manager.html
index 8658151..12d27b8 100644
--- a/chrome/browser/resources/history/synced_device_manager.html
+++ b/chrome/browser/resources/history/synced_device_manager.html
@@ -31,18 +31,18 @@
         text-align: center;
       }
 
-      #sign-in-promo {
+      #turn-on-sync-promo {
         font-size: 215%;
         margin-top: 40px;
       }
 
-      #sign-in-promo-desc {
+      #turn-on-sync-promo-desc {
         color: var(--cr-secondary-text-color);
         font-size: 123%;
         margin-top: 10px;
       }
 
-      #sign-in-button {
+      #turn-on-sync-button {
         margin: 24px 0;
       }
 
@@ -77,11 +77,11 @@
         hidden="[[!showSignInGuide(signInState, guestSession_,
                                    signInAllowed_)]]">
       <div id="illustration"></div>
-      <div id="sign-in-promo">$i18n{signInPromo}</div>
-      <div id="sign-in-promo-desc">$i18n{signInPromoDesc}</div>
-      <cr-button id="sign-in-button" class="action-button"
-          on-click="onSignInTap_">
-        $i18n{signInButton}
+      <div id="turn-on-sync-promo">$i18n{turnOnSyncPromo}</div>
+      <div id="turn-on-sync-promo-desc">$i18n{turnOnSyncPromoDesc}</div>
+      <cr-button id="turn-on-sync-button" class="action-button"
+          on-click="onTurnOnSyncTap_">
+        $i18n{turnOnSyncButton}
       </cr-button>
     </div>
 
diff --git a/chrome/browser/resources/history/synced_device_manager.ts b/chrome/browser/resources/history/synced_device_manager.ts
index e6b5bb8..78953cb 100644
--- a/chrome/browser/resources/history/synced_device_manager.ts
+++ b/chrome/browser/resources/history/synced_device_manager.ts
@@ -188,8 +188,8 @@
     };
   }
 
-  private onSignInTap_() {
-    BrowserServiceImpl.getInstance().startSignInFlow();
+  private onTurnOnSyncTap_() {
+    BrowserServiceImpl.getInstance().startTurnOnSyncFlow();
   }
 
   private onOpenMenu_(e: CustomEvent<{tag: string, target: HTMLElement}>) {
diff --git a/chrome/browser/resources/settings/autofill_page/multi_store_password_ui_entry.ts b/chrome/browser/resources/settings/autofill_page/multi_store_password_ui_entry.ts
index 2a59c03..0f2e2e2 100644
--- a/chrome/browser/resources/settings/autofill_page/multi_store_password_ui_entry.ts
+++ b/chrome/browser/resources/settings/autofill_page/multi_store_password_ui_entry.ts
@@ -51,6 +51,10 @@
     return this.contents_.storedIn;
   }
 
+  get isAndroidCredential(): boolean {
+    return this.contents_.isAndroidCredential;
+  }
+
   /**
    * @return Whether the credential is stored on the account.
    */
diff --git a/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts b/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts
index 5560e31c..6da3bfa5 100644
--- a/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts
@@ -154,8 +154,8 @@
    */
   private getSiteOrApp_(): string {
     return this.i18n(
-        this.item!.isAndroidCredential ? 'editCompromisedPasswordApp' :
-                                         'editCompromisedPasswordSite');
+        this.item!.isAndroidCredential ? 'editPasswordAppLabel' :
+                                         'editPasswordWebsiteLabel');
   }
 }
 
diff --git a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html
index 1751f01..b38474a 100644
--- a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html
+++ b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html
@@ -70,11 +70,12 @@
             $i18n{addPasswordStoreOptionDevice}
           </option>
         </select>
-        <cr-input id="websiteInput" label="$i18n{editPasswordWebsiteLabel}"
+        <cr-input id="websiteInput"
+            label="[[getLabelForWebsiteInput_(dialogMode, existingEntry)]]"
             class$="[[getClassForWebsiteInput_(websiteInputErrorMessage_)]]"
             autofocus="[[shouldAutofocusWebsiteInput_(isAccountStoreUser,
                 dialogMode)]]"
-            value="[[getWebsite_(dialogMode, existingEntry.urls.link)]]"
+            value="[[getWebsite_(dialogMode, existingEntry)]]"
             on-blur="onWebsiteInputBlur_" placeholder="example.com"
             on-input="validateWebsite_"
             required="[[isWebsiteEditable_(dialogMode)]]"
diff --git a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts
index 00e2187..e8dd630 100644
--- a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts
@@ -431,8 +431,12 @@
    * Gets the initial text to show in the website input.
    */
   private getWebsite_(): string {
-    return this.dialogMode === PasswordDialogMode.ADD ?
-        '' :
+    if (this.dialogMode === PasswordDialogMode.ADD) {
+      return '';
+    }
+
+    return this.existingEntry!.isAndroidCredential ?
+        this.existingEntry!.urls.shown :
         this.existingEntry!.urls.link;
   }
 
@@ -629,6 +633,15 @@
     }
   }
 
+  private getLabelForWebsiteInput_(): string {
+    if (this.dialogMode === PasswordDialogMode.ADD) {
+      return this.i18n('editPasswordWebsiteLabel');
+    }
+    return this.i18n(
+        this.existingEntry!.isAndroidCredential ? 'editPasswordAppLabel' :
+                                                  'editPasswordWebsiteLabel');
+  }
+
   private getClassForWebsiteInput_(): string {
     // If website input is empty, it is invalid, but has no error message.
     // To handle this, the error is shown only if 'has-error-message' is set.
diff --git a/chrome/browser/signin/about_signin_internals_factory.cc b/chrome/browser/signin/about_signin_internals_factory.cc
index 7e62dc9..dbd498b1 100644
--- a/chrome/browser/signin/about_signin_internals_factory.cc
+++ b/chrome/browser/signin/about_signin_internals_factory.cc
@@ -11,14 +11,11 @@
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/signin/signin_error_controller_factory.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/signin/core/browser/about_signin_internals.h"
 
 AboutSigninInternalsFactory::AboutSigninInternalsFactory()
-    : BrowserContextKeyedServiceFactory(
-        "AboutSigninInternals",
-        BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("AboutSigninInternals") {
   DependsOn(ChromeSigninClientFactory::GetInstance());
   DependsOn(SigninErrorControllerFactory::GetInstance());
   DependsOn(AccountReconcilorFactory::GetInstance());
diff --git a/chrome/browser/signin/about_signin_internals_factory.h b/chrome/browser/signin/about_signin_internals_factory.h
index c1b7cb5..284a762 100644
--- a/chrome/browser/signin/about_signin_internals_factory.h
+++ b/chrome/browser/signin/about_signin_internals_factory.h
@@ -6,14 +6,14 @@
 #define CHROME_BROWSER_SIGNIN_ABOUT_SIGNIN_INTERNALS_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class AboutSigninInternals;
 class Profile;
 
 // Singleton that owns all AboutSigninInternals and associates them with
 // Profiles.
-class AboutSigninInternalsFactory : public BrowserContextKeyedServiceFactory {
+class AboutSigninInternalsFactory : public ProfileKeyedServiceFactory {
  public:
   // Returns the instance of AboutSigninInternals associated with this profile,
   // creating one if none exists.
diff --git a/chrome/browser/signin/account_consistency_mode_manager_factory.cc b/chrome/browser/signin/account_consistency_mode_manager_factory.cc
index 10178f3..db15271 100644
--- a/chrome/browser/signin/account_consistency_mode_manager_factory.cc
+++ b/chrome/browser/signin/account_consistency_mode_manager_factory.cc
@@ -5,10 +5,7 @@
 #include "chrome/browser/signin/account_consistency_mode_manager_factory.h"
 
 #include "base/check.h"
-#include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
 // static
 AccountConsistencyModeManagerFactory*
@@ -25,9 +22,9 @@
 }
 
 AccountConsistencyModeManagerFactory::AccountConsistencyModeManagerFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "AccountConsistencyModeManager",
-          BrowserContextDependencyManager::GetInstance()) {}
+          ProfileSelections::BuildServicesForRegularProfile()) {}
 
 AccountConsistencyModeManagerFactory::~AccountConsistencyModeManagerFactory() =
     default;
@@ -37,9 +34,7 @@
   DCHECK(!context->IsOffTheRecord());
   Profile* profile = Profile::FromBrowserContext(context);
 
-  return AccountConsistencyModeManager::ShouldBuildServiceForProfile(profile)
-             ? new AccountConsistencyModeManager(profile)
-             : nullptr;
+  return new AccountConsistencyModeManager(profile);
 }
 
 void AccountConsistencyModeManagerFactory::RegisterProfilePrefs(
diff --git a/chrome/browser/signin/account_consistency_mode_manager_factory.h b/chrome/browser/signin/account_consistency_mode_manager_factory.h
index 7990d84..c8cbb0c1 100644
--- a/chrome/browser/signin/account_consistency_mode_manager_factory.h
+++ b/chrome/browser/signin/account_consistency_mode_manager_factory.h
@@ -6,11 +6,10 @@
 #define CHROME_BROWSER_SIGNIN_ACCOUNT_CONSISTENCY_MODE_MANAGER_FACTORY_H_
 
 #include "base/memory/singleton.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 #include "chrome/browser/signin/account_consistency_mode_manager.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
-class AccountConsistencyModeManagerFactory
-    : public BrowserContextKeyedServiceFactory {
+class AccountConsistencyModeManagerFactory : public ProfileKeyedServiceFactory {
  public:
   // Returns an instance of the factory singleton.
   static AccountConsistencyModeManagerFactory* GetInstance();
diff --git a/chrome/browser/signin/account_investigator_factory.cc b/chrome/browser/signin/account_investigator_factory.cc
index 731c8b4..04b039a 100644
--- a/chrome/browser/signin/account_investigator_factory.cc
+++ b/chrome/browser/signin/account_investigator_factory.cc
@@ -7,7 +7,6 @@
 #include "base/memory/singleton.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service_factory.h"
 #include "components/signin/core/browser/account_investigator.h"
@@ -26,9 +25,7 @@
 }
 
 AccountInvestigatorFactory::AccountInvestigatorFactory()
-    : BrowserContextKeyedServiceFactory(
-          "AccountInvestigator",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("AccountInvestigator") {
   DependsOn(IdentityManagerFactory::GetInstance());
 }
 
diff --git a/chrome/browser/signin/account_investigator_factory.h b/chrome/browser/signin/account_investigator_factory.h
index 6f1d56c..85ccb8d 100644
--- a/chrome/browser/signin/account_investigator_factory.h
+++ b/chrome/browser/signin/account_investigator_factory.h
@@ -5,9 +5,8 @@
 #ifndef CHROME_BROWSER_SIGNIN_ACCOUNT_INVESTIGATOR_FACTORY_H_
 #define CHROME_BROWSER_SIGNIN_ACCOUNT_INVESTIGATOR_FACTORY_H_
 
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
-class Profile;
 class AccountInvestigator;
 
 namespace base {
@@ -16,7 +15,7 @@
 }  // namespace base
 
 // Factory for BrowserKeyedService AccountInvestigator.
-class AccountInvestigatorFactory : public BrowserContextKeyedServiceFactory {
+class AccountInvestigatorFactory : public ProfileKeyedServiceFactory {
  public:
   static AccountInvestigator* GetForProfile(Profile* profile);
 
diff --git a/chrome/browser/signin/account_reconcilor_factory.cc b/chrome/browser/signin/account_reconcilor_factory.cc
index 400bb1ee..8fdf63b 100644
--- a/chrome/browser/signin/account_reconcilor_factory.cc
+++ b/chrome/browser/signin/account_reconcilor_factory.cc
@@ -15,7 +15,6 @@
 #include "chrome/browser/signin/account_consistency_mode_manager.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/signin/core/browser/account_reconcilor.h"
 #include "components/signin/core/browser/account_reconcilor_delegate.h"
 #include "components/signin/core/browser/mirror_account_reconcilor_delegate.h"
@@ -114,9 +113,7 @@
 }  // namespace
 
 AccountReconcilorFactory::AccountReconcilorFactory()
-    : BrowserContextKeyedServiceFactory(
-          "AccountReconcilor",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("AccountReconcilor") {
   DependsOn(ChromeSigninClientFactory::GetInstance());
   DependsOn(IdentityManagerFactory::GetInstance());
 }
diff --git a/chrome/browser/signin/account_reconcilor_factory.h b/chrome/browser/signin/account_reconcilor_factory.h
index 1358fa13..84e2df8d 100644
--- a/chrome/browser/signin/account_reconcilor_factory.h
+++ b/chrome/browser/signin/account_reconcilor_factory.h
@@ -8,23 +8,17 @@
 #include <memory>
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
-
-namespace signin {
-class IdentityManager;
-}
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 namespace signin {
 class AccountReconcilorDelegate;
 }
 
 class AccountReconcilor;
-class Profile;
-class SigninClient;
 
 // Singleton that owns all AccountReconcilors and associates them with
 // Profiles. Listens for the Profile's destruction notification and cleans up.
-class AccountReconcilorFactory : public BrowserContextKeyedServiceFactory {
+class AccountReconcilorFactory : public ProfileKeyedServiceFactory {
  public:
   // Returns the instance of AccountReconcilor associated with this profile
   // (creating one if none exists). Returns NULL if this profile cannot have an
diff --git a/chrome/browser/signin/chrome_signin_client_factory.cc b/chrome/browser/signin/chrome_signin_client_factory.cc
index 62c0d638..7dee9e14 100644
--- a/chrome/browser/signin/chrome_signin_client_factory.cc
+++ b/chrome/browser/signin/chrome_signin_client_factory.cc
@@ -6,12 +6,9 @@
 
 #include "chrome/browser/net/profile_network_context_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 ChromeSigninClientFactory::ChromeSigninClientFactory()
-    : BrowserContextKeyedServiceFactory(
-          "ChromeSigninClient",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("ChromeSigninClient") {
   DependsOn(ProfileNetworkContextServiceFactory::GetInstance());
 }
 
diff --git a/chrome/browser/signin/chrome_signin_client_factory.h b/chrome/browser/signin/chrome_signin_client_factory.h
index e88d3f23..168b00f 100644
--- a/chrome/browser/signin/chrome_signin_client_factory.h
+++ b/chrome/browser/signin/chrome_signin_client_factory.h
@@ -6,14 +6,14 @@
 #define CHROME_BROWSER_SIGNIN_CHROME_SIGNIN_CLIENT_FACTORY_H_
 
 #include "base/memory/singleton.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 #include "chrome/browser/signin/chrome_signin_client.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
 class Profile;
 
 // Singleton that owns all ChromeSigninClients and associates them with
 // Profiles.
-class ChromeSigninClientFactory : public BrowserContextKeyedServiceFactory {
+class ChromeSigninClientFactory : public ProfileKeyedServiceFactory {
  public:
   // Returns the instance of SigninClient associated with this profile
   // (creating one if none exists). Returns NULL if this profile cannot have an
diff --git a/chrome/browser/signin/cookie_reminter_factory.cc b/chrome/browser/signin/cookie_reminter_factory.cc
index f53de57d..63890b2 100644
--- a/chrome/browser/signin/cookie_reminter_factory.cc
+++ b/chrome/browser/signin/cookie_reminter_factory.cc
@@ -5,13 +5,10 @@
 #include "chrome/browser/signin/cookie_reminter_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/signin/core/browser/cookie_reminter.h"
 
 CookieReminterFactory::CookieReminterFactory()
-    : BrowserContextKeyedServiceFactory(
-          "CookieReminter",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("CookieReminter") {
   DependsOn(IdentityManagerFactory::GetInstance());
 }
 
diff --git a/chrome/browser/signin/cookie_reminter_factory.h b/chrome/browser/signin/cookie_reminter_factory.h
index 8ce4768..43c1f15 100644
--- a/chrome/browser/signin/cookie_reminter_factory.h
+++ b/chrome/browser/signin/cookie_reminter_factory.h
@@ -6,12 +6,12 @@
 #define CHROME_BROWSER_SIGNIN_COOKIE_REMINTER_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class CookieReminter;
 class Profile;
 
-class CookieReminterFactory : public BrowserContextKeyedServiceFactory {
+class CookieReminterFactory : public ProfileKeyedServiceFactory {
  public:
   static CookieReminter* GetForProfile(Profile* profile);
   static CookieReminterFactory* GetInstance();
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_factory.cc b/chrome/browser/signin/dice_web_signin_interceptor_factory.cc
index 9377d94..a1aec611 100644
--- a/chrome/browser/signin/dice_web_signin_interceptor_factory.cc
+++ b/chrome/browser/signin/dice_web_signin_interceptor_factory.cc
@@ -8,7 +8,6 @@
 #include "chrome/browser/signin/dice_web_signin_interceptor.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 // static
 DiceWebSigninInterceptor* DiceWebSigninInterceptorFactory::GetForProfile(
@@ -24,9 +23,7 @@
 }
 
 DiceWebSigninInterceptorFactory::DiceWebSigninInterceptorFactory()
-    : BrowserContextKeyedServiceFactory(
-          "DiceWebSigninInterceptor",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("DiceWebSigninInterceptor") {
   DependsOn(IdentityManagerFactory::GetInstance());
 }
 
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_factory.h b/chrome/browser/signin/dice_web_signin_interceptor_factory.h
index ad6aac1c..9867a949 100644
--- a/chrome/browser/signin/dice_web_signin_interceptor_factory.h
+++ b/chrome/browser/signin/dice_web_signin_interceptor_factory.h
@@ -6,13 +6,12 @@
 #define CHROME_BROWSER_SIGNIN_DICE_WEB_SIGNIN_INTERCEPTOR_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class DiceWebSigninInterceptor;
 class Profile;
 
-class DiceWebSigninInterceptorFactory
-    : public BrowserContextKeyedServiceFactory {
+class DiceWebSigninInterceptorFactory : public ProfileKeyedServiceFactory {
  public:
   static DiceWebSigninInterceptor* GetForProfile(Profile* profile);
   static DiceWebSigninInterceptorFactory* GetInstance();
diff --git a/chrome/browser/signin/identity_manager_factory.cc b/chrome/browser/signin/identity_manager_factory.cc
index 66ed056c1..bc37f69 100644
--- a/chrome/browser/signin/identity_manager_factory.cc
+++ b/chrome/browser/signin/identity_manager_factory.cc
@@ -17,7 +17,6 @@
 #include "chrome/browser/signin/account_consistency_mode_manager.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/identity_manager_provider.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/signin/public/base/signin_buildflags.h"
@@ -60,9 +59,7 @@
 }
 
 IdentityManagerFactory::IdentityManagerFactory()
-    : BrowserContextKeyedServiceFactory(
-          "IdentityManager",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("IdentityManager") {
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
   DependsOn(WebDataServiceFactory::GetInstance());
 #endif
diff --git a/chrome/browser/signin/identity_manager_factory.h b/chrome/browser/signin/identity_manager_factory.h
index a2e0590..08ca39fb 100644
--- a/chrome/browser/signin/identity_manager_factory.h
+++ b/chrome/browser/signin/identity_manager_factory.h
@@ -7,7 +7,7 @@
 
 #include "base/memory/singleton.h"
 #include "base/observer_list.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 namespace signin {
 class IdentityManager;
@@ -17,7 +17,7 @@
 
 // Singleton that owns all IdentityManager instances and associates them with
 // Profiles.
-class IdentityManagerFactory : public BrowserContextKeyedServiceFactory {
+class IdentityManagerFactory : public ProfileKeyedServiceFactory {
  public:
   class Observer : public base::CheckedObserver {
    public:
diff --git a/chrome/browser/signin/primary_account_policy_manager_factory.cc b/chrome/browser/signin/primary_account_policy_manager_factory.cc
index da80239..3465004 100644
--- a/chrome/browser/signin/primary_account_policy_manager_factory.cc
+++ b/chrome/browser/signin/primary_account_policy_manager_factory.cc
@@ -6,7 +6,6 @@
 
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 // static
 PrimaryAccountPolicyManagerFactory*
@@ -24,9 +23,7 @@
 }
 
 PrimaryAccountPolicyManagerFactory::PrimaryAccountPolicyManagerFactory()
-    : BrowserContextKeyedServiceFactory(
-          "PrimaryAccountPolicyManager",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("PrimaryAccountPolicyManager") {
   DependsOn(IdentityManagerFactory::GetInstance());
 }
 
diff --git a/chrome/browser/signin/primary_account_policy_manager_factory.h b/chrome/browser/signin/primary_account_policy_manager_factory.h
index a82b211..7702df8 100644
--- a/chrome/browser/signin/primary_account_policy_manager_factory.h
+++ b/chrome/browser/signin/primary_account_policy_manager_factory.h
@@ -6,13 +6,12 @@
 #define CHROME_BROWSER_SIGNIN_PRIMARY_ACCOUNT_POLICY_MANAGER_FACTORY_H_
 
 #include "base/no_destructor.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 #include "chrome/browser/signin/primary_account_policy_manager.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
 class Profile;
 
-class PrimaryAccountPolicyManagerFactory
-    : public BrowserContextKeyedServiceFactory {
+class PrimaryAccountPolicyManagerFactory : public ProfileKeyedServiceFactory {
  public:
   // Returns an instance of the factory singleton.
   static PrimaryAccountPolicyManagerFactory* GetInstance();
diff --git a/chrome/browser/signin/signin_error_controller_factory.cc b/chrome/browser/signin/signin_error_controller_factory.cc
index ebbd061..4b2a46f 100644
--- a/chrome/browser/signin/signin_error_controller_factory.cc
+++ b/chrome/browser/signin/signin_error_controller_factory.cc
@@ -9,12 +9,9 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/account_consistency_mode_manager.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 SigninErrorControllerFactory::SigninErrorControllerFactory()
-    : BrowserContextKeyedServiceFactory(
-          "SigninErrorController",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("SigninErrorController") {
   DependsOn(IdentityManagerFactory::GetInstance());
 }
 
diff --git a/chrome/browser/signin/signin_error_controller_factory.h b/chrome/browser/signin/signin_error_controller_factory.h
index 0d87f49..22b19056 100644
--- a/chrome/browser/signin/signin_error_controller_factory.h
+++ b/chrome/browser/signin/signin_error_controller_factory.h
@@ -6,14 +6,12 @@
 #define CHROME_BROWSER_SIGNIN_SIGNIN_ERROR_CONTROLLER_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 #include "components/signin/core/browser/signin_error_controller.h"
 
-class Profile;
-
 // Singleton that owns all SigninErrorControllers and associates them with
 // Profiles.
-class SigninErrorControllerFactory : public BrowserContextKeyedServiceFactory {
+class SigninErrorControllerFactory : public ProfileKeyedServiceFactory {
  public:
   // Returns the instance of SigninErrorController associated with this profile
   // (creating one if none exists). Returns NULL if this profile cannot have an
diff --git a/chrome/browser/signin/signin_manager_android_factory.cc b/chrome/browser/signin/signin_manager_android_factory.cc
index e2bd6ea..36fcd419 100644
--- a/chrome/browser/signin/signin_manager_android_factory.cc
+++ b/chrome/browser/signin/signin_manager_android_factory.cc
@@ -8,12 +8,9 @@
 #include "chrome/browser/android/signin/signin_manager_android.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 SigninManagerAndroidFactory::SigninManagerAndroidFactory()
-    : BrowserContextKeyedServiceFactory(
-          "SigninManagerAndroid",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("SigninManagerAndroid") {
   DependsOn(IdentityManagerFactory::GetInstance());
 }
 
diff --git a/chrome/browser/signin/signin_manager_android_factory.h b/chrome/browser/signin/signin_manager_android_factory.h
index fd1b07c2..dd8983e 100644
--- a/chrome/browser/signin/signin_manager_android_factory.h
+++ b/chrome/browser/signin/signin_manager_android_factory.h
@@ -7,12 +7,11 @@
 
 #include "base/android/scoped_java_ref.h"
 #include "base/no_destructor.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
-class Profile;
 class SigninManagerAndroid;
 
-class SigninManagerAndroidFactory : public BrowserContextKeyedServiceFactory {
+class SigninManagerAndroidFactory : public ProfileKeyedServiceFactory {
  public:
   static SigninManagerAndroid* GetForProfile(Profile* profile);
 
diff --git a/chrome/browser/signin/signin_manager_factory.cc b/chrome/browser/signin/signin_manager_factory.cc
index 7137cfd..f05de73 100644
--- a/chrome/browser/signin/signin_manager_factory.cc
+++ b/chrome/browser/signin/signin_manager_factory.cc
@@ -10,7 +10,6 @@
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/signin/signin_features.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 // static
 SigninManagerFactory* SigninManagerFactory::GetInstance() {
@@ -25,9 +24,7 @@
 }
 
 SigninManagerFactory::SigninManagerFactory()
-    : BrowserContextKeyedServiceFactory(
-          "SigninManager",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("SigninManager") {
   DependsOn(IdentityManagerFactory::GetInstance());
   DependsOn(ChromeSigninClientFactory::GetInstance());
 }
diff --git a/chrome/browser/signin/signin_manager_factory.h b/chrome/browser/signin/signin_manager_factory.h
index d0ca640e..fdb71f9 100644
--- a/chrome/browser/signin/signin_manager_factory.h
+++ b/chrome/browser/signin/signin_manager_factory.h
@@ -7,10 +7,10 @@
 
 #include "base/memory/singleton.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
-class SigninManagerFactory : public BrowserContextKeyedServiceFactory {
+class SigninManagerFactory : public ProfileKeyedServiceFactory {
  public:
   // Returns an instance of the factory singleton.
   static SigninManagerFactory* GetInstance();
diff --git a/chrome/browser/signin/signin_profile_attributes_updater_factory.cc b/chrome/browser/signin/signin_profile_attributes_updater_factory.cc
index 86c62a2..513b0cf 100644
--- a/chrome/browser/signin/signin_profile_attributes_updater_factory.cc
+++ b/chrome/browser/signin/signin_profile_attributes_updater_factory.cc
@@ -9,7 +9,17 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/signin/signin_profile_attributes_updater.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
+
+namespace {
+ProfileSelections BuildServicesForSigninProfileAttributesUpdater() {
+  // Some tests don't have a ProfileManager, disable this service.
+  if (!g_browser_process || !g_browser_process->profile_manager()) {
+    return ProfileSelections::BuildNoServicesForAllProfiles();
+  }
+
+  return ProfileSelections::BuildDefault();
+}
+}  // namespace
 
 // static
 SigninProfileAttributesUpdater*
@@ -25,9 +35,9 @@
 }
 
 SigninProfileAttributesUpdaterFactory::SigninProfileAttributesUpdaterFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "SigninProfileAttributesUpdater",
-          BrowserContextDependencyManager::GetInstance()) {
+          BuildServicesForSigninProfileAttributesUpdater()) {
   DependsOn(IdentityManagerFactory::GetInstance());
 }
 
@@ -37,9 +47,6 @@
 KeyedService* SigninProfileAttributesUpdaterFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
   Profile* profile = Profile::FromBrowserContext(context);
-  // Some tests don't have a ProfileManager, disable this service.
-  if (!g_browser_process->profile_manager())
-    return nullptr;
 
   return new SigninProfileAttributesUpdater(
       IdentityManagerFactory::GetForProfile(profile),
diff --git a/chrome/browser/signin/signin_profile_attributes_updater_factory.h b/chrome/browser/signin/signin_profile_attributes_updater_factory.h
index 78f990ab..23ff64f1 100644
--- a/chrome/browser/signin/signin_profile_attributes_updater_factory.h
+++ b/chrome/browser/signin/signin_profile_attributes_updater_factory.h
@@ -6,13 +6,13 @@
 #define CHROME_BROWSER_SIGNIN_SIGNIN_PROFILE_ATTRIBUTES_UPDATER_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 class SigninProfileAttributesUpdater;
 
 class SigninProfileAttributesUpdaterFactory
-    : public BrowserContextKeyedServiceFactory {
+    : public ProfileKeyedServiceFactory {
  public:
   // Returns nullptr if this profile cannot have a
   // SigninProfileAttributesUpdater (for example, if |profile| is incognito).
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial.js b/chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial.js
index a934e73..c28b511f 100644
--- a/chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial.js
+++ b/chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial.js
@@ -95,6 +95,7 @@
       $('remote-approvals-button').classList.add('secondary-button');
     }
     $('remote-approvals-button').onclick = function(event) {
+      $('remote-approvals-button').disabled = true;
       sendCommand('requestUrlAccessRemote');
     };
     $('local-approvals-button').onclick = function(event) {
@@ -178,7 +179,7 @@
     }
   } else {
     $('request-failed-message').hidden = false;
-    $('remote-approvals-button').hidden = false;
+    $('remote-approvals-button').disabled = false;
     $('show-details-link').hidden = false;
   }
 }
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc
index 166bd8a..3f4b166 100644
--- a/chrome/browser/sync/chrome_sync_client.cc
+++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -250,19 +250,21 @@
       account_password_store_,
       BookmarkSyncServiceFactory::GetForProfile(profile_));
 
+  signin::IdentityManager* identity_manager =
+      IdentityManagerFactory::GetForProfile(profile_);
+
 #if BUILDFLAG(IS_ANDROID)
-  trusted_vault_client_ = std::make_unique<TrustedVaultClientAndroid>();
+  trusted_vault_client_ = std::make_unique<TrustedVaultClientAndroid>(
+      /*gaia_account_info_by_gaia_id_cb=*/base::BindRepeating(
+          [](signin::IdentityManager* identity_manager,
+             const std::string& gaia_id) -> CoreAccountInfo {
+            return identity_manager->FindExtendedAccountInfoByGaiaId(gaia_id);
+          },
+          identity_manager));
 #else
-  // TODO(crbug.com/1113597): consider destroying/notifying
-  // |trusted_vault_client_| upon IdentityManager shutdown, to avoid its usages
-  // afterwards. This can be done by tranferring |trusted_vault_client_|
-  // ownership to SyncServiceImpl and acting on
-  // SyncServiceImpl::Shutdown() or by handling
-  // IdentityManagerFactory::Observer::IdentityManagerShutdown().
   trusted_vault_client_ =
       std::make_unique<syncer::StandaloneTrustedVaultClient>(
-          profile_->GetPath().Append(kTrustedVaultFilename),
-          IdentityManagerFactory::GetForProfile(profile_),
+          profile_->GetPath().Append(kTrustedVaultFilename), identity_manager,
           profile_->GetDefaultStoragePartition()
               ->GetURLLoaderFactoryForBrowserProcess());
 #endif  // BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/sync/test/integration/single_client_device_info_sync_test.cc b/chrome/browser/sync/test/integration/single_client_device_info_sync_test.cc
index c11155d..1ff3108 100644
--- a/chrome/browser/sync/test/integration/single_client_device_info_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_device_info_sync_test.cc
@@ -18,12 +18,8 @@
 #include "components/sync/base/features.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/base/time.h"
-#include "components/sync/driver/glue/sync_transport_data_prefs.h"
-#include "components/sync/engine/loopback_server/persistent_tombstone_entity.h"
-#include "components/sync/nigori/nigori_test_utils.h"
 #include "components/sync/protocol/device_info_specifics.pb.h"
 #include "components/sync/protocol/entity_specifics.pb.h"
-#include "components/sync/protocol/proto_value_conversions.h"
 #include "components/sync/protocol/sync.pb.h"
 #include "components/sync/protocol/sync_entity.pb.h"
 #include "components/sync/protocol/sync_enums.pb.h"
@@ -33,7 +29,6 @@
 #include "components/sync_device_info/device_info_tracker.h"
 #include "components/sync_device_info/device_info_util.h"
 #include "content/public/test/browser_test.h"
-#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
@@ -47,6 +42,7 @@
 using testing::Contains;
 using testing::ElementsAre;
 using testing::IsSupersetOf;
+using testing::Not;
 using testing::UnorderedElementsAre;
 
 MATCHER(HasFullHardwareClass, "") {
@@ -61,6 +57,19 @@
   return arg->guid() == expected_cache_guid;
 }
 
+MATCHER_P(HasInterestedDataType, expected_data_type, "") {
+  for (int32_t interested_data_type_id : arg.specifics()
+                                             .device_info()
+                                             .invalidation_fields()
+                                             .interested_data_type_ids()) {
+    if (interested_data_type_id ==
+        syncer::GetSpecificsFieldNumberFromModelType(expected_data_type)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 std::string CacheGuidForSuffix(int suffix) {
   return base::StringPrintf("cache guid %d", suffix);
 }
@@ -118,6 +127,37 @@
                          DefaultInterestedDataTypes());
 }
 
+// Waits for a DeviceInfo entity to be committed to the fake server (regardless
+// whether the commit succeeds or not). Note that it doesn't handle disabled
+// network case.
+class DeviceInfoCommitChecker : public SingleClientStatusChangeChecker {
+  // SingleClientStatusChangeChecker is used instead of
+  // FakeServerMatchStatusChecker because current checker is used when there is
+  // an HTTP error on the fake server.
+ public:
+  DeviceInfoCommitChecker(syncer::SyncServiceImpl* service,
+                          fake_server::FakeServer* fake_server)
+      : SingleClientStatusChangeChecker(service), fake_server_(fake_server) {}
+
+  // StatusChangeChecker overrides.
+  bool IsExitConditionSatisfied(std::ostream* os) override {
+    *os << "Waiting for DeviceInfo to be committed.";
+
+    sync_pb::ClientToServerMessage message;
+    fake_server_->GetLastCommitMessage(&message);
+    for (const sync_pb::SyncEntity& entity : message.commit().entries()) {
+      if (entity.specifics().has_device_info()) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+ private:
+  const raw_ptr<fake_server::FakeServer> fake_server_;
+};
+
 class SingleClientDeviceInfoSyncTest : public SyncTest {
  public:
   SingleClientDeviceInfoSyncTest() : SyncTest(SINGLE_CLIENT) {
@@ -161,6 +201,9 @@
             /*creation_time=*/0, /*last_modified_time=*/0));
   }
 
+  // SyncTest overrides.
+  bool UseConfigurationRefresher() override { return false; }
+
  private:
   base::test::ScopedFeatureList override_features_;
 };
@@ -519,6 +562,28 @@
                   .Wait());
 }
 
+IN_PROC_BROWSER_TEST_F(SingleClientDeviceInfoSyncTest,
+                       ShouldRetryDeviceInfoCommitOnAuthError) {
+  ASSERT_TRUE(SetupSync());
+
+  GetFakeServer()->SetHttpError(net::HTTP_UNAUTHORIZED);
+
+  // Disable another data type to trigger a commit of a new DeviceInfo entity.
+  // Create a checker to catch a commit request before disabling the data type.
+  DeviceInfoCommitChecker device_info_committer_checker(GetSyncService(0),
+                                                        GetFakeServer());
+  ASSERT_TRUE(
+      GetClient(0)->DisableSyncForType(syncer::UserSelectableType::kBookmarks));
+  ASSERT_TRUE(device_info_committer_checker.Wait());
+
+  GetFakeServer()->ClearHttpError();
+
+  // Wait for the DeviceInfo to be committed to the fake server again.
+  EXPECT_TRUE(ServerDeviceInfoMatchChecker(
+                  ElementsAre(Not(HasInterestedDataType(syncer::BOOKMARKS))))
+                  .Wait());
+}
+
 // PRE_* tests aren't supported on Android browser tests.
 #if !BUILDFLAG(IS_ANDROID)
 IN_PROC_BROWSER_TEST_F(SingleClientDeviceInfoSyncTest,
diff --git a/chrome/browser/sync/trusted_vault_client_android.cc b/chrome/browser/sync/trusted_vault_client_android.cc
index 5e3e7f8..8f44731 100644
--- a/chrome/browser/sync/trusted_vault_client_android.cc
+++ b/chrome/browser/sync/trusted_vault_client_android.cc
@@ -44,7 +44,20 @@
 TrustedVaultClientAndroid::OngoingGetIsRecoverabilityDegraded::
     ~OngoingGetIsRecoverabilityDegraded() = default;
 
-TrustedVaultClientAndroid::TrustedVaultClientAndroid() {
+TrustedVaultClientAndroid::OngoingAddTrustedRecoveryMethod::
+    OngoingAddTrustedRecoveryMethod(base::OnceClosure callback)
+    : callback(std::move(callback)) {}
+
+TrustedVaultClientAndroid::OngoingAddTrustedRecoveryMethod::
+    OngoingAddTrustedRecoveryMethod(OngoingAddTrustedRecoveryMethod&&) =
+        default;
+
+TrustedVaultClientAndroid::OngoingAddTrustedRecoveryMethod::
+    ~OngoingAddTrustedRecoveryMethod() = default;
+
+TrustedVaultClientAndroid::TrustedVaultClientAndroid(
+    const GetAccountInfoByGaiaIdCallback& gaia_account_info_by_gaia_id_cb)
+    : gaia_account_info_by_gaia_id_cb_(gaia_account_info_by_gaia_id_cb) {
   JNIEnv* const env = base::android::AttachCurrentThread();
   Java_TrustedVaultClient_registerNative(env, reinterpret_cast<intptr_t>(this));
 }
@@ -100,6 +113,18 @@
       .Run(!!is_degraded);
 }
 
+void TrustedVaultClientAndroid::AddTrustedRecoveryMethodCompleted(
+    JNIEnv* env,
+    jint request_id) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  OngoingRequest ongoing_request = GetAndUnregisterOngoingRequest(request_id);
+
+  std::move(
+      absl::get<OngoingAddTrustedRecoveryMethod>(ongoing_request).callback)
+      .Run();
+}
+
 void TrustedVaultClientAndroid::NotifyKeysChanged(JNIEnv* env) {
   for (Observer& observer : observer_list_) {
     observer.OnTrustedVaultKeysChanged();
@@ -193,8 +218,33 @@
     const std::vector<uint8_t>& public_key,
     int method_type_hint,
     base::OnceClosure cb) {
-  // Not invoked on Android.
-  NOTREACHED();
+  // Not invoked on Android, but this is about to change with crbug.com/1341279.
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  DCHECK(cb);
+
+  const CoreAccountInfo account_info =
+      gaia_account_info_by_gaia_id_cb_.Run(gaia_id);
+  if (account_info == CoreAccountInfo()) {
+    std::move(cb).Run();
+    return;
+  }
+
+  // Store for later completion when Java invokes
+  // AddTrustedRecoveryMethodCompleted().
+  const RequestId request_id =
+      RegisterNewOngoingRequest(OngoingAddTrustedRecoveryMethod(std::move(cb)));
+
+  JNIEnv* const env = base::android::AttachCurrentThread();
+  const base::android::ScopedJavaLocalRef<jobject> java_account_info =
+      ConvertToJavaCoreAccountInfo(env, account_info);
+
+  const base::android::ScopedJavaLocalRef<jbyteArray> java_public_key =
+      base::android::ToJavaByteArray(env, public_key);
+
+  // The Java implementation will eventually call
+  // AddTrustedRecoveryMethodCompleted().
+  Java_TrustedVaultClient_addTrustedRecoveryMethod(
+      env, request_id, java_account_info, java_public_key, method_type_hint);
 }
 
 void TrustedVaultClientAndroid::ClearDataForAccount(
diff --git a/chrome/browser/sync/trusted_vault_client_android.h b/chrome/browser/sync/trusted_vault_client_android.h
index fb8d42d2..4d069644 100644
--- a/chrome/browser/sync/trusted_vault_client_android.h
+++ b/chrome/browser/sync/trusted_vault_client_android.h
@@ -25,7 +25,13 @@
 // This class must be accessed from the UI thread.
 class TrustedVaultClientAndroid : public syncer::TrustedVaultClient {
  public:
-  TrustedVaultClientAndroid();
+  // Callback that returns account information identified by |gaia_id| or an
+  // empty CoreAccountInfo if the account is not found.
+  using GetAccountInfoByGaiaIdCallback =
+      base::RepeatingCallback<CoreAccountInfo(const std::string& gaia_id)>;
+
+  explicit TrustedVaultClientAndroid(
+      const GetAccountInfoByGaiaIdCallback& gaia_account_info_by_gaia_id_cb);
   ~TrustedVaultClientAndroid() override;
 
   TrustedVaultClientAndroid(const TrustedVaultClientAndroid&) = delete;
@@ -54,6 +60,11 @@
                                             jint request_id,
                                             jboolean is_degraded);
 
+  // Called from Java to notify the completion of a
+  // AddTrustedRecoveryMethod() operation previously initiated from C++ and
+  // identified by |request_id|.
+  void AddTrustedRecoveryMethodCompleted(JNIEnv* env, jint request_id);
+
   // Called from Java to notify that the keys in the vault may have changed.
   void NotifyKeysChanged(JNIEnv* env);
 
@@ -117,14 +128,27 @@
     base::OnceCallback<void(bool)> callback;
   };
 
+  // Struct representing an in-flight AddTrustedRecoveryMethod() invoked from
+  // C++.
+  struct OngoingAddTrustedRecoveryMethod {
+    explicit OngoingAddTrustedRecoveryMethod(base::OnceClosure callback);
+    OngoingAddTrustedRecoveryMethod(OngoingAddTrustedRecoveryMethod&&);
+    ~OngoingAddTrustedRecoveryMethod();
+
+    base::OnceClosure callback;
+  };
+
   using RequestId = int32_t;
   using OngoingRequest = absl::variant<OngoingFetchKeys,
                                        OngoingMarkLocalKeysAsStale,
-                                       OngoingGetIsRecoverabilityDegraded>;
+                                       OngoingGetIsRecoverabilityDegraded,
+                                       OngoingAddTrustedRecoveryMethod>;
 
   RequestId RegisterNewOngoingRequest(OngoingRequest request);
   OngoingRequest GetAndUnregisterOngoingRequest(RequestId id);
 
+  const GetAccountInfoByGaiaIdCallback gaia_account_info_by_gaia_id_cb_;
+
   // Each in-flight request gets assigned an auto-increment ID and gets cached
   // in a map, until the response from Java is received.
   RequestId last_request_id_ = 0;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 34f4ab94..62fd5e17 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -5749,6 +5749,8 @@
 
   if (!is_android) {
     sources += [
+      "autofill_assistant/password_change/mock_apc_scrim_manager.cc",
+      "autofill_assistant/password_change/mock_apc_scrim_manager.h",
       "autofill_assistant/password_change/mock_assistant_display_delegate.cc",
       "autofill_assistant/password_change/mock_assistant_display_delegate.h",
       "autofill_assistant/password_change/mock_assistant_onboarding_controller.cc",
@@ -5761,8 +5763,6 @@
       "autofill_assistant/password_change/mock_password_change_run_controller.h",
       "autofill_assistant/password_change/mock_password_change_run_display.cc",
       "autofill_assistant/password_change/mock_password_change_run_display.h",
-      "autofill_assistant/password_change/mock_scrim_manager.cc",
-      "autofill_assistant/password_change/mock_scrim_manager.h",
       "exclusive_access/exclusive_access_test.cc",
       "exclusive_access/exclusive_access_test.h",
       "exclusive_access/fullscreen_controller_state_test.cc",
diff --git a/chrome/browser/ui/app_list/app_context_menu_unittest.cc b/chrome/browser/ui/app_list/app_context_menu_unittest.cc
index 3a991a1b..8db101e 100644
--- a/chrome/browser/ui/app_list/app_context_menu_unittest.cc
+++ b/chrome/browser/ui/app_list/app_context_menu_unittest.cc
@@ -202,7 +202,7 @@
   };
 
   void ValidateItemState(const ui::MenuModel* menu_model,
-                         size_t index,
+                         int index,
                          const MenuState& state) {
     EXPECT_EQ(state.command_id, menu_model->GetCommandIdAt(index));
     if (state.command_id == -1)
@@ -215,7 +215,7 @@
                          const std::vector<MenuState>& states) {
     ASSERT_NE(nullptr, menu_model);
     size_t state_index = 0;
-    for (size_t i = 0; i < menu_model->GetItemCount(); ++i) {
+    for (int i = 0; i < menu_model->GetItemCount(); ++i) {
       ASSERT_LT(state_index, states.size());
       ValidateItemState(menu_model, i, states[state_index++]);
     }
@@ -425,10 +425,10 @@
   // Separators are not added to touchable app context menus. For touchable app
   // context menus, arc app has double separator, three more app shortcuts
   // provided by arc::FakeAppInstance and two separators between shortcuts.
-  const size_t expected_items = 10;
+  const int expected_items = 10;
 
   ASSERT_EQ(expected_items, menu->GetItemCount());
-  size_t index = 0;
+  int index = 0;
   ValidateItemState(menu.get(), index++, MenuState(ash::LAUNCH_NEW));
   ValidateItemState(menu.get(), index++, MenuState(ash::TOGGLE_PIN));
   ValidateItemState(menu.get(), index++, MenuState(ash::UNINSTALL));
@@ -455,7 +455,7 @@
   // Separators are not added to touchable app context menus except for arc app
   // shortcuts, which have double separator, three more app shortcuts provided
   // by arc::FakeAppInstance and two separators between shortcuts.
-  const size_t expected_items_app_open = 9;
+  const int expected_items_app_open = 9;
   ASSERT_EQ(expected_items_app_open, menu->GetItemCount());
   index = 0;
   ValidateItemState(menu.get(), index++, MenuState(ash::TOGGLE_PIN));
@@ -491,7 +491,7 @@
   // menus. For touchable app context menus, arc app has double separator,
   // three more app shortcuts provided by arc::FakeAppInstance and two
   // separators between shortcuts.
-  const size_t expected_items_reopen = 8;
+  const int expected_items_reopen = 8;
   ASSERT_EQ(expected_items_reopen, menu->GetItemCount());
   index = 0;
   ValidateItemState(menu.get(), index++, MenuState(ash::LAUNCH_NEW));
@@ -537,8 +537,8 @@
   // Separators are not added to touchable app context menus. For touchable app
   // context menus, arc app has double separator, three more app shortcuts
   // provided by arc::FakeAppInstance and two separators between shortcuts.
-  const size_t expected_items = 10;
-  size_t index = 0;
+  const int expected_items = 10;
+  int index = 0;
   ASSERT_EQ(expected_items, menu->GetItemCount());
   ValidateItemState(menu.get(), index++, MenuState(ash::LAUNCH_NEW));
   ValidateItemState(menu.get(), index++, MenuState(ash::TOGGLE_PIN));
@@ -564,7 +564,7 @@
   // menus. For touchable app context menus, arc app has double separator,
   // three more app shortcuts provided by arc::FakeAppInstance and two
   // separators between shortcuts.
-  const size_t expected_items_non_ready = 9;
+  const int expected_items_non_ready = 9;
   ASSERT_EQ(expected_items_non_ready, menu->GetItemCount());
   index = 0;
   ValidateItemState(menu.get(), index++, MenuState(ash::LAUNCH_NEW));
@@ -604,9 +604,9 @@
     // Separators are not added to touchable app context menus. For touchable
     // app context menus, arc app has double separator, three more app shortcuts
     // provided by arc::FakeAppInstance and two separators between shortcuts.
-    size_t expected_items = 9;
+    int expected_items = 9;
     ASSERT_EQ(expected_items, menu->GetItemCount());
-    size_t index = 0;
+    int index = 0;
     ValidateItemState(menu.get(), index++, MenuState(ash::LAUNCH_NEW));
     ValidateItemState(menu.get(), index++, MenuState(ash::TOGGLE_PIN));
     ValidateItemState(menu.get(), index++, MenuState(ash::SHOW_APP_INFO));
@@ -643,9 +643,9 @@
   // Separators are not added to touchable app context menus. For touchable
   // app context menus, arc app has double separator, three more app shortcuts
   // provided by arc::FakeAppInstance and two separators between shortcuts.
-  size_t expected_items = 8;
+  int expected_items = 8;
   ASSERT_EQ(expected_items, menu->GetItemCount());
-  size_t index = 0;
+  int index = 0;
   ValidateItemState(menu.get(), index++, MenuState(ash::TOGGLE_PIN));
   ValidateItemState(menu.get(), index++, MenuState(ash::SHOW_APP_INFO));
 
@@ -690,7 +690,7 @@
         GetAppListItem(profile(), internal_app.app_id);
     std::unique_ptr<ui::MenuModel> menu = GetContextMenuModel(item.get());
     ASSERT_NE(nullptr, menu);
-    EXPECT_EQ(1u, menu->GetItemCount());
+    EXPECT_EQ(1, menu->GetItemCount());
     ValidateItemState(menu.get(), 0, MenuState(ash::TOGGLE_PIN));
   }
 }
@@ -744,7 +744,7 @@
 
   // Verify expected menu items.
   // It should have, Open new window, Open incognito window, and app info.
-  EXPECT_EQ(menu_model->GetItemCount(), 3u);
+  EXPECT_EQ(menu_model->GetItemCount(), 3);
   std::vector<MenuState> states;
   AddToStates(menu, MenuState(ash::APP_CONTEXT_MENU_NEW_WINDOW), &states);
   AddToStates(menu, MenuState(ash::APP_CONTEXT_MENU_NEW_INCOGNITO_WINDOW),
diff --git a/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc b/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc
index 4f1693c..1fe7e63 100644
--- a/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc
+++ b/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc
@@ -357,10 +357,10 @@
   run_loop.Run();
   EXPECT_TRUE(menu_model);
 
-  size_t num_items = menu_model->GetItemCount();
-  EXPECT_GT(num_items, 0u);
+  int num_items = menu_model->GetItemCount();
+  EXPECT_LT(0, num_items);
 
-  for (size_t i = 0; i < num_items; i++) {
+  for (int i = 0; i < num_items; i++) {
     if (menu_model->GetTypeAt(i) == ui::MenuModel::TYPE_SEPARATOR)
       continue;
 
diff --git a/chrome/browser/ui/app_list/search/mixer.cc b/chrome/browser/ui/app_list/search/mixer.cc
index 7b777eb..f4b59ea1 100644
--- a/chrome/browser/ui/app_list/search/mixer.cc
+++ b/chrome/browser/ui/app_list/search/mixer.cc
@@ -100,7 +100,7 @@
 
     if (ranker)
       ranker->Rank(&results_);
-    std::sort(results_.begin(), results_.end());
+    std::stable_sort(results_.begin(), results_.end());
   }
 
   const SortedResults& results() const { return results_; }
@@ -165,7 +165,7 @@
     chip_ranker_->Rank(&results);
   }
 
-  std::sort(results.begin(), results.end());
+  std::stable_sort(results.begin(), results.end());
 
   const size_t original_size = results.size();
   if (original_size < num_max_results) {
@@ -180,7 +180,7 @@
     // 0.4) that the People result will be 5th, not 7th, because the Omnibox
     // group has a soft maximum of 4 results. (Otherwise, the People result
     // would not be seen at all once the result list is truncated.)
-    std::sort(results.begin() + original_size, results.end());
+    std::stable_sort(results.begin() + original_size, results.end());
   }
   RemoveDuplicates(&results);
 
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc
index 8965558..b108f1f 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc
@@ -439,9 +439,12 @@
 
   ranker->Rank(&results);
   ranker->OverrideZeroStateResults(&results);
-  EXPECT_THAT(results, WhenSorted(ElementsAre(
-                           HasId("Z1"), HasId("Z2"), HasId("Z3"), HasId("D1"),
-                           HasId("O1"), HasId("Z4"), HasId("Z5"))));
+  // Z4 and Z5 have equal order so use std::stable_sort instead of WhenSorted(),
+  // which uses std::sort.
+  std::stable_sort(results.begin(), results.end());
+  EXPECT_THAT(results,
+              ElementsAre(HasId("Z1"), HasId("Z2"), HasId("Z3"), HasId("D1"),
+                          HasId("O1"), HasId("Z4"), HasId("Z5")));
 }
 
 // If one group won't have shown results and has a new result in the list, but
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos_unittest.cc
index c4f26a86..9bff677 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos_unittest.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos_unittest.cc
@@ -104,13 +104,13 @@
     SetLoggedInUsers(2);
     std::unique_ptr<ui::MenuModel> menu = CreateMultiUserContextMenu(window());
     ASSERT_TRUE(menu.get());
-    EXPECT_EQ(1u, menu.get()->GetItemCount());
+    EXPECT_EQ(1, menu.get()->GetItemCount());
   }
   {
     SetLoggedInUsers(3);
     std::unique_ptr<ui::MenuModel> menu = CreateMultiUserContextMenu(window());
     ASSERT_TRUE(menu.get());
-    EXPECT_EQ(2u, menu.get()->GetItemCount());
+    EXPECT_EQ(2, menu.get()->GetItemCount());
   }
 }
 
diff --git a/chrome/browser/ui/ash/session_controller_client_impl.cc b/chrome/browser/ui/ash/session_controller_client_impl.cc
index 5f472d6..cb76ff1 100644
--- a/chrome/browser/ui/ash/session_controller_client_impl.cc
+++ b/chrome/browser/ui/ash/session_controller_client_impl.cc
@@ -205,7 +205,8 @@
 }
 
 void SessionControllerClientImpl::RunUnlockAnimation(
-    base::OnceClosure animation_finished_callback) {
+    ash::SessionController::RunUnlockAnimationCallback
+        animation_finished_callback) {
   session_controller_->RunUnlockAnimation(
       std::move(animation_finished_callback));
 }
diff --git a/chrome/browser/ui/ash/session_controller_client_impl.h b/chrome/browser/ui/ash/session_controller_client_impl.h
index a625f5a7..5933dde4c 100644
--- a/chrome/browser/ui/ash/session_controller_client_impl.h
+++ b/chrome/browser/ui/ash/session_controller_client_impl.h
@@ -71,7 +71,8 @@
 
   // Calls ash SessionController to run unlock animation.
   // |animation_finished_callback| will be invoked when the animation finishes.
-  void RunUnlockAnimation(base::OnceClosure animation_finished_callback);
+  void RunUnlockAnimation(ash::SessionController::RunUnlockAnimationCallback
+                              animation_finished_callback);
 
   // Asks the session controller to show the window teleportation dialog.
   void ShowTeleportWarningDialog(
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc
index d074862..254bc6d 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/ash/app_restore/app_restore_arc_task_handler.h"
-#include "chrome/browser/ash/app_restore/arc_window_handler.h"
+#include "chrome/browser/ash/app_restore/arc_ghost_window_handler.h"
 #include "chrome/browser/ash/arc/arc_optin_uma.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu_browsertest.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu_browsertest.cc
index cc2bb42d..9d0673286 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu_browsertest.cc
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu_browsertest.cc
@@ -40,7 +40,7 @@
   struct MenuSection {
     std::unique_ptr<ui::SimpleMenuModel> menu_model;
     ui::MenuModel* sub_model = nullptr;
-    size_t command_index = 0;
+    int command_index = -1;
   };
 
   absl::optional<MenuSection> GetContextMenuSectionForAppCommand(
@@ -62,7 +62,7 @@
     run_loop.Run();
 
     result.sub_model = result.menu_model.get();
-    result.command_index = 0;
+    result.command_index = -1;
     if (!ui::MenuModel::GetModelAndIndexForCommandId(
             command_id, &result.sub_model, &result.command_index)) {
       return absl::nullopt;
diff --git a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc
index 0607c59..a873941 100644
--- a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc
+++ b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc
@@ -390,7 +390,7 @@
         }));
     run_loop.Run();
     ui::MenuModel* menu_ptr = menu.get();
-    size_t index = 0;
+    int index = 0;
     return ui::MenuModel::GetModelAndIndexForCommandId(command_id, &menu_ptr,
                                                        &index);
   }
@@ -3056,7 +3056,7 @@
   // per-desk shelf feature is enabled or not.
   auto* model_adapter = ClickBrowserShelfButtonAndGetMenu();
   const bool is_per_desk_shelf_enabled = GetParam();
-  constexpr size_t kTitleAndSeparatorCount = 2;
+  constexpr int kTitleAndSeparatorCount = 2;
   if (is_per_desk_shelf_enabled) {
     EXPECT_EQ(2 + kTitleAndSeparatorCount,
               model_adapter->model()->GetItemCount());
diff --git a/chrome/browser/ui/ash/shelf/shelf_context_menu_unittest.cc b/chrome/browser/ui/ash/shelf/shelf_context_menu_unittest.cc
index f7570d5..93f1114 100644
--- a/chrome/browser/ui/ash/shelf/shelf_context_menu_unittest.cc
+++ b/chrome/browser/ui/ash/shelf/shelf_context_menu_unittest.cc
@@ -76,14 +76,14 @@
 
 bool IsItemPresentInMenu(ui::MenuModel* menu, int command_id) {
   ui::MenuModel* model = menu;
-  size_t index = 0;
+  int index = 0;
   return ui::MenuModel::GetModelAndIndexForCommandId(command_id, &model,
                                                      &index);
 }
 
 bool IsItemEnabledInMenu(ui::MenuModel* menu, int command_id) {
   ui::MenuModel* model = menu;
-  size_t index = 0;
+  int index = 0;
   return ui::MenuModel::GetModelAndIndexForCommandId(command_id, &model,
                                                      &index) &&
          menu->IsEnabledAt(index);
@@ -578,7 +578,7 @@
       GetContextMenu(item_delegate, primary_id);
 
   // Test that there are 9 items in an ARC app context menu.
-  EXPECT_EQ(9u, menu->GetItemCount());
+  EXPECT_EQ(9, menu->GetItemCount());
 }
 
 // Tests that the context menu of internal app  is correct.
@@ -632,7 +632,7 @@
     std::unique_ptr<ui::MenuModel> menu =
         GetContextMenu(item_delegate, primary_id);
 
-    const size_t expected_options_num = internal_app.show_in_launcher ? 2 : 1;
+    const int expected_options_num = internal_app.show_in_launcher ? 2 : 1;
     EXPECT_EQ(expected_options_num, menu->GetItemCount());
   }
 }
@@ -666,7 +666,7 @@
       GetContextMenu(item_delegate, primary_id);
 
   // Check that every menu item has an icon
-  for (size_t i = 0; i < menu->GetItemCount(); ++i)
+  for (int i = 0; i < menu->GetItemCount(); ++i)
     EXPECT_FALSE(menu->GetIconAt(i).IsEmpty());
 
   // Precisely which density option is shown is not important to us, we only
@@ -695,7 +695,7 @@
   std::unique_ptr<ui::MenuModel> menu =
       GetContextMenu(item_delegate, primary_id);
 
-  EXPECT_EQ(menu->GetItemCount(), 1u);
+  EXPECT_EQ(menu->GetItemCount(), 1);
   EXPECT_FALSE(
       IsItemEnabledInMenu(menu.get(), ash::APP_CONTEXT_MENU_NEW_WINDOW));
 }
@@ -720,7 +720,7 @@
       GetContextMenu(item_delegate, primary_id);
 
   // Check that every menu item has an icon
-  for (size_t i = 0; i < menu->GetItemCount(); ++i)
+  for (int i = 0; i < menu->GetItemCount(); ++i)
     EXPECT_FALSE(menu->GetIconAt(i).IsEmpty());
 
   EXPECT_TRUE(IsItemEnabledInMenu(menu.get(), ash::UNINSTALL));
diff --git a/chrome/browser/ui/ash/test_session_controller.cc b/chrome/browser/ui/ash/test_session_controller.cc
index 3eb27c80..761f01e 100644
--- a/chrome/browser/ui/ash/test_session_controller.cc
+++ b/chrome/browser/ui/ash/test_session_controller.cc
@@ -49,7 +49,7 @@
 
 void TestSessionController::RunUnlockAnimation(
     RunUnlockAnimationCallback callback) {
-  std::move(callback).Run();
+  std::move(callback).Run(false);
 }
 
 void TestSessionController::NotifyChromeTerminating() {}
diff --git a/chrome/browser/ui/autofill_assistant/password_change/mock_scrim_manager.cc b/chrome/browser/ui/autofill_assistant/password_change/mock_apc_scrim_manager.cc
similarity index 93%
rename from chrome/browser/ui/autofill_assistant/password_change/mock_scrim_manager.cc
rename to chrome/browser/ui/autofill_assistant/password_change/mock_apc_scrim_manager.cc
index 627ab07..28d2f3e 100644
--- a/chrome/browser/ui/autofill_assistant/password_change/mock_scrim_manager.cc
+++ b/chrome/browser/ui/autofill_assistant/password_change/mock_apc_scrim_manager.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/autofill_assistant/password_change/mock_scrim_manager.h"
+#include "chrome/browser/ui/autofill_assistant/password_change/mock_apc_scrim_manager.h"
 
 MockApcScrimManager::MockApcScrimManager() = default;
 
diff --git a/chrome/browser/ui/autofill_assistant/password_change/mock_scrim_manager.h b/chrome/browser/ui/autofill_assistant/password_change/mock_apc_scrim_manager.h
similarity index 91%
rename from chrome/browser/ui/autofill_assistant/password_change/mock_scrim_manager.h
rename to chrome/browser/ui/autofill_assistant/password_change/mock_apc_scrim_manager.h
index a35b582..646fd19 100644
--- a/chrome/browser/ui/autofill_assistant/password_change/mock_scrim_manager.h
+++ b/chrome/browser/ui/autofill_assistant/password_change/mock_apc_scrim_manager.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_AUTOFILL_ASSISTANT_PASSWORD_CHANGE_MOCK_SCRIM_MANAGER_H_
-#define CHROME_BROWSER_UI_AUTOFILL_ASSISTANT_PASSWORD_CHANGE_MOCK_SCRIM_MANAGER_H_
+#ifndef CHROME_BROWSER_UI_AUTOFILL_ASSISTANT_PASSWORD_CHANGE_MOCK_APC_SCRIM_MANAGER_H_
+#define CHROME_BROWSER_UI_AUTOFILL_ASSISTANT_PASSWORD_CHANGE_MOCK_APC_SCRIM_MANAGER_H_
 
 #include "chrome/browser/ui/autofill_assistant/password_change/apc_scrim_manager.h"
 
@@ -20,4 +20,4 @@
   MOCK_METHOD(bool, GetVisible, (), (override));
 };
 
-#endif  // CHROME_BROWSER_UI_AUTOFILL_ASSISTANT_PASSWORD_CHANGE_MOCK_SCRIM_MANAGER_H_
+#endif  // CHROME_BROWSER_UI_AUTOFILL_ASSISTANT_PASSWORD_CHANGE_MOCK_APC_SCRIM_MANAGER_H_
diff --git a/chrome/browser/ui/cocoa/color_chooser_mac.mm b/chrome/browser/ui/cocoa/color_chooser_mac.mm
index c8f7367..a15f8e7 100644
--- a/chrome/browser/ui/cocoa/color_chooser_mac.mm
+++ b/chrome/browser/ui/cocoa/color_chooser_mac.mm
@@ -15,7 +15,7 @@
 
 namespace {
 // The currently active color chooser.
-raw_ptr<ColorChooserMac> g_current_color_chooser = nullptr;
+ColorChooserMac* g_current_color_chooser = nullptr;
 }  // namespace
 
 // static
@@ -28,7 +28,7 @@
   // Note that WebContentsImpl::ColorChooser ultimately takes ownership (and
   // deletes) the returned pointer.
   g_current_color_chooser = new ColorChooserMac(web_contents, initial_color);
-  return base::WrapUnique(g_current_color_chooser.get());
+  return base::WrapUnique(g_current_color_chooser);
 }
 
 ColorChooserMac::ColorChooserMac(content::WebContents* web_contents,
diff --git a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm
index 318b7d5..96ab721 100644
--- a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm
+++ b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm
@@ -102,14 +102,15 @@
     // In case the user has selected a word that triggers spelling suggestions,
     // show the dictionary lookup under the group that contains the command to
     // “Add to Dictionary.”
-    const absl::optional<size_t> index_opt =
+    int index =
         menu_model_.GetIndexOfCommandId(IDC_SPELLCHECK_ADD_TO_DICTIONARY);
-    size_t index = index_opt.value_or(0);
-    if (index_opt.has_value()) {
+    if (index < 0) {
+      index = 0;
+    } else {
       while (menu_model_.GetTypeAt(index) != ui::MenuModel::TYPE_SEPARATOR) {
         index++;
       }
-      ++index;  // Place it below the separator.
+      index += 1; // Place it below the separator.
     }
 
     std::u16string printable_selection_text = PrintableSelectionText();
diff --git a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm
index 94cb06fc..43c018d 100644
--- a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm
+++ b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm
@@ -38,7 +38,7 @@
 NSMenuItem* GetMenuItemByID(ui::MenuModel* model,
                             NSMenu* menu,
                             int command_id) {
-  for (size_t i = 0; i < model->GetItemCount(); ++i) {
+  for (int i = 0; i < model->GetItemCount(); ++i) {
     NSMenuItem* item = [menu itemAtIndex:i];
     if (model->GetCommandIdAt(i) == command_id)
       return item;
diff --git a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_unittest.mm b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_unittest.mm
index 403fb20..c8a49ad4 100644
--- a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_unittest.mm
+++ b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_unittest.mm
@@ -46,7 +46,7 @@
 };
 
 bool MenuHasItemWithCommand(const ui::MenuModel& menu, int command) {
-  for (size_t i = 0; i < menu.GetItemCount(); ++i) {
+  for (int i = 0; i < menu.GetItemCount(); ++i) {
     if (menu.GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU) {
       ui::MenuModel* submenu = menu.GetSubmenuModelAt(i);
       if (MenuHasItemWithCommand(*submenu, command))
diff --git a/chrome/browser/ui/extensions/extension_action_view_controller_unittest.cc b/chrome/browser/ui/extensions/extension_action_view_controller_unittest.cc
index 18b1096b..68b3e7f 100644
--- a/chrome/browser/ui/extensions/extension_action_view_controller_unittest.cc
+++ b/chrome/browser/ui/extensions/extension_action_view_controller_unittest.cc
@@ -340,11 +340,11 @@
     ui::SimpleMenuModel* context_menu = static_cast<ui::SimpleMenuModel*>(
         action->GetContextMenu(extensions::ExtensionContextMenuModel::
                                    ContextMenuSource::kToolbarAction));
-    absl::optional<size_t> visibility_index = context_menu->GetIndexOfCommandId(
+    int visibility_index = context_menu->GetIndexOfCommandId(
         extensions::ExtensionContextMenuModel::TOGGLE_VISIBILITY);
-    ASSERT_TRUE(visibility_index.has_value());
+    ASSERT_GE(visibility_index, 0);
     std::u16string visibility_label =
-        context_menu->GetLabelAt(visibility_index.value());
+        context_menu->GetLabelAt(visibility_index);
     EXPECT_EQ(l10n_util::GetStringUTF16(expected_visibility_string),
               visibility_label);
   };
diff --git a/chrome/browser/ui/tabs/existing_base_sub_menu_model.cc b/chrome/browser/ui/tabs/existing_base_sub_menu_model.cc
index a43ac9a..4796dd1 100644
--- a/chrome/browser/ui/tabs/existing_base_sub_menu_model.cc
+++ b/chrome/browser/ui/tabs/existing_base_sub_menu_model.cc
@@ -21,7 +21,7 @@
       parent_new_command_id_(parent_new_command_id) {}
 
 const gfx::FontList* ExistingBaseSubMenuModel::GetLabelFontListAt(
-    size_t index) const {
+    int index) const {
   if (GetTypeAt(index) == ui::MenuModel::TYPE_TITLE) {
     return &ui::ResourceBundle::GetSharedInstance().GetFontList(
         ui::ResourceBundle::BoldFont);
@@ -75,7 +75,7 @@
   int command_id = min_command_id_ + 1;
   for (size_t i = 0; i < menu_item_infos.size(); ++i) {
     const MenuItemInfo& item = menu_item_infos[i];
-    if (command_id > min_command_id_ + static_cast<int>(max_size))
+    if (command_id > min_command_id_ + max_size)
       break;
 
     if (item.target_index.has_value()) {
@@ -107,7 +107,7 @@
   return command_id == min_command_id_;
 }
 
-void ExistingBaseSubMenuModel::ExecuteExistingCommand(size_t target_index) {}
+void ExistingBaseSubMenuModel::ExecuteExistingCommand(int target_index) {}
 
 int ExistingBaseSubMenuModel::GetContextIndex() const {
   return model_->GetIndexOfWebContents(context_contents_);
diff --git a/chrome/browser/ui/tabs/existing_base_sub_menu_model.h b/chrome/browser/ui/tabs/existing_base_sub_menu_model.h
index d7c2196..c2eba01d 100644
--- a/chrome/browser/ui/tabs/existing_base_sub_menu_model.h
+++ b/chrome/browser/ui/tabs/existing_base_sub_menu_model.h
@@ -36,7 +36,7 @@
                            int parent_new_command_id_);
 
   // ui::SimpleMenuModel
-  const gfx::FontList* GetLabelFontListAt(size_t index) const override;
+  const gfx::FontList* GetLabelFontListAt(int index) const override;
 
   // ui::SimpleMenuModel::Delegate
   bool IsCommandIdAlerted(int command_id) const override;
@@ -51,7 +51,7 @@
 
   ~ExistingBaseSubMenuModel() override;
 
-  const base::flat_map<int, size_t>& command_id_to_target_index_for_testing() {
+  const base::flat_map<int, int>& command_id_to_target_index_for_testing() {
     return command_id_to_target_index_;
   }
 
@@ -73,7 +73,7 @@
     // The target index for this item. E.g. tab group index or browser
     // index. If this field is not provided then the entry for this item will be
     // a title and have no corresponding command.
-    absl::optional<size_t> target_index;
+    absl::optional<int> target_index;
 
     // An optionally provided accessible name for this menu item. If
     // |accessible_name| is empty, then the default accessible name will be used
@@ -96,10 +96,10 @@
 
   // Performs the action for adding the tab to an existing object model (e.g.
   // group or window) at |target_index|.
-  virtual void ExecuteExistingCommand(size_t target_index);
+  virtual void ExecuteExistingCommand(int target_index);
 
   // Maximum number of entries for a submenu.
-  static constexpr size_t max_size = 200;
+  static constexpr int max_size = 200;
 
   ui::SimpleMenuModel::Delegate* parent_delegate() const {
     return parent_delegate_;
@@ -116,7 +116,7 @@
 
   // Stores a mapping from a menu item's command id to its target index (e.g.
   // tab-group index or browser index).
-  base::flat_map<int, size_t> command_id_to_target_index_;
+  base::flat_map<int, int> command_id_to_target_index_;
 };
 
 #endif  // CHROME_BROWSER_UI_TABS_EXISTING_BASE_SUB_MENU_MODEL_H_
diff --git a/chrome/browser/ui/tabs/existing_base_sub_menu_model_unittest.cc b/chrome/browser/ui/tabs/existing_base_sub_menu_model_unittest.cc
index a724ca4..3c85af6 100644
--- a/chrome/browser/ui/tabs/existing_base_sub_menu_model_unittest.cc
+++ b/chrome/browser/ui/tabs/existing_base_sub_menu_model_unittest.cc
@@ -66,17 +66,17 @@
     Build(IDS_TAB_CXMENU_SUBMENU_NEW_GROUP, infos_);
   }
 
-  const std::vector<size_t> existing_commands() const {
+  const std::vector<int> existing_commands() const {
     return existing_commands_;
   }
 
  protected:
-  void ExecuteExistingCommand(size_t target_index) override {
+  void ExecuteExistingCommand(int target_index) override {
     existing_commands_.push_back(target_index);
   }
 
  private:
-  std::vector<size_t> existing_commands_;
+  std::vector<int> existing_commands_;
   std::vector<MenuItemInfo> infos_;
 };
 
@@ -127,5 +127,5 @@
 TEST_F(ExistingBaseSubMenuModelTest, ExecuteCommand_Existing) {
   test_model()->ExecuteCommand(kMinCommandId + 1, kExpectedFlags);
   test_model()->ExecuteCommand(kMinCommandId + 2, kExpectedFlags);
-  EXPECT_THAT(test_model()->existing_commands(), testing::ElementsAre(1u, 2u));
+  EXPECT_THAT(test_model()->existing_commands(), testing::ElementsAre(1, 2));
 }
diff --git a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc
index 73ed033..a95ee61d 100644
--- a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc
+++ b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc
@@ -59,7 +59,7 @@
   // `target_index_to_group_mapping_`.
   CHECK_EQ(menu_item_infos.size(), groups.size());
   for (const auto& group : groups) {
-    size_t index = target_index_to_group_mapping_.size();
+    int index = target_index_to_group_mapping_.size();
     menu_item_infos[index].target_index = index;
     target_index_to_group_mapping_.emplace(index, group);
   }
@@ -82,7 +82,7 @@
       CHECK_EQ(menu_item_infos.size(),
                groups.size() + target_index_to_group_mapping_.size());
       for (const auto& group : groups) {
-        size_t index = target_index_to_group_mapping_.size();
+        int index = target_index_to_group_mapping_.size();
         menu_item_infos[index].target_index = index;
         target_index_to_group_mapping_.emplace(index, group);
       }
@@ -159,12 +159,12 @@
   return false;
 }
 
-std::u16string ExistingTabGroupSubMenuModel::GetLabelAt(size_t index) const {
+std::u16string ExistingTabGroupSubMenuModel::GetLabelAt(int index) const {
   return ui::EscapeMenuLabelAmpersands(
       ExistingBaseSubMenuModel::GetLabelAt(index));
 }
 
-void ExistingTabGroupSubMenuModel::ExecuteExistingCommand(size_t target_index) {
+void ExistingTabGroupSubMenuModel::ExecuteExistingCommand(int target_index) {
   DCHECK_LE(size_t(target_index), target_index_to_group_mapping_.size());
   TabGroupModel* group_model = model()->group_model();
   if (!group_model)
@@ -180,7 +180,7 @@
     return;
   }
 
-  absl::optional<size_t> browser_index;
+  int browser_index = -1;
   std::vector<Browser*> browsers =
       tab_menu_model_delegate_->GetExistingWindowsForMoveMenu();
   for (size_t i = 0; i < browsers.size(); ++i) {
@@ -192,7 +192,7 @@
     }
   }
 
-  if (!browser_index.has_value())
+  if (browser_index < 0)
     return;
 
   std::vector<int> selected_indices;
@@ -204,8 +204,7 @@
     selected_indices =
         std::vector<int>(selection_indices.begin(), selection_indices.end());
   }
-  TabStripModel* found_model =
-      browsers[browser_index.value()]->tab_strip_model();
+  TabStripModel* found_model = browsers[browser_index]->tab_strip_model();
   std::vector<int> selected_indices_in_found_model;
   const ui::ListSelectionModel::SelectedIndices selection_indices =
       found_model->selection_model().selected_indices();
@@ -215,8 +214,7 @@
   // At the time this was written, all tabs moved to a new window via
   // MoveToExistingWindow() are placed at the end of the tabstrip, and any
   // previously selected tabs in the new window are unselected.
-  model()->delegate()->MoveToExistingWindow(selected_indices,
-                                            browser_index.value());
+  model()->delegate()->MoveToExistingWindow(selected_indices, browser_index);
 
   // DCHECK that previously selected indices in the new model are now
   // unselected.
@@ -257,6 +255,6 @@
 }
 
 void ExistingTabGroupSubMenuModel::ExecuteExistingCommandForTesting(
-    size_t target_index) {
+    int target_index) {
   ExecuteExistingCommand(target_index);
 }
diff --git a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.h b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.h
index 1d4a85ce..9fa71cd 100644
--- a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.h
+++ b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.h
@@ -34,14 +34,14 @@
   static bool ShouldShowSubmenu(TabStripModel* model, int context_index);
 
   // ExistingBaseSubMenuModel:
-  std::u16string GetLabelAt(size_t index) const override;
+  std::u16string GetLabelAt(int index) const override;
 
   // Used for testing.
-  void ExecuteExistingCommandForTesting(size_t target_index);
+  void ExecuteExistingCommandForTesting(int target_index);
 
  private:
   // ExistingBaseSubMenuModel
-  void ExecuteExistingCommand(size_t target_index) override;
+  void ExecuteExistingCommand(int target_index) override;
 
   // Retrieves all tab groups ids from the given model.
   const std::vector<tab_groups::TabGroupId> GetGroupsFromModel(
@@ -61,7 +61,7 @@
   // be used in cases where the tab groups returned from
   // GetOrderedTabGroupsInSubMenu changes after the menu has been opened but
   // before the action is taken from the menumodel.
-  std::map<size_t, tab_groups::TabGroupId> target_index_to_group_mapping_;
+  std::map<int, tab_groups::TabGroupId> target_index_to_group_mapping_;
 
   // Used to retrieve a list of browsers which potentially hold tab groups.
   const raw_ptr<TabMenuModelDelegate> tab_menu_model_delegate_;
diff --git a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model_unittest.cc b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model_unittest.cc
index e85cfc9..07db517 100644
--- a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model_unittest.cc
+++ b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model_unittest.cc
@@ -53,13 +53,13 @@
   ASSERT_EQ(model->count(), 3);
 
   ExistingTabGroupSubMenuModel menu1(nullptr, nullptr, model, 0);
-  EXPECT_EQ(3u, menu1.GetItemCount());
+  EXPECT_EQ(3, menu1.GetItemCount());
 
   ExistingTabGroupSubMenuModel menu2(nullptr, nullptr, model, 1);
-  EXPECT_EQ(3u, menu2.GetItemCount());
+  EXPECT_EQ(3, menu2.GetItemCount());
 
   ExistingTabGroupSubMenuModel menu3(nullptr, nullptr, model, 2);
-  EXPECT_EQ(4u, menu3.GetItemCount());
+  EXPECT_EQ(4, menu3.GetItemCount());
 }
 
 // Verify tabs can be added tab groups in the same window.
@@ -72,7 +72,7 @@
   model->AddToNewGroup({0});
   model->AddToNewGroup({1});
   ExistingTabGroupSubMenuModel menu(nullptr, nullptr, model, 2);
-  EXPECT_EQ(4u, menu.GetItemCount());
+  EXPECT_EQ(4, menu.GetItemCount());
 
   // Move the tab at index 2 into the group with the tab at index 0.
   menu.ExecuteExistingCommandForTesting(0);
@@ -83,7 +83,7 @@
                    ->tab_count());
 
   ExistingTabGroupSubMenuModel menu2(nullptr, nullptr, model, 2);
-  EXPECT_EQ(3u, menu2.GetItemCount());
+  EXPECT_EQ(3, menu2.GetItemCount());
 }
 
 // Verify non-selected tabs can be added tab groups in the same window.
@@ -102,7 +102,7 @@
 
   // Create the menu on the tab at index 3.
   ExistingTabGroupSubMenuModel menu(nullptr, nullptr, model, 3);
-  EXPECT_EQ(4u, menu.GetItemCount());
+  EXPECT_EQ(4, menu.GetItemCount());
 
   // Move the tab at index 2 into the group with the tab at index 0.
   menu.ExecuteExistingCommandForTesting(0);
@@ -115,8 +115,8 @@
   ExistingTabGroupSubMenuModel menu2(nullptr, nullptr, model, 2);
   ExistingTabGroupSubMenuModel menu3(nullptr, nullptr, model, 3);
 
-  EXPECT_EQ(3u, menu2.GetItemCount());
-  EXPECT_EQ(4u, menu3.GetItemCount());
+  EXPECT_EQ(3, menu2.GetItemCount());
+  EXPECT_EQ(4, menu3.GetItemCount());
 }
 
 // Verify tabs can be added to tab groups in other browser windows.
@@ -163,7 +163,7 @@
   std::vector<int> selected_indices =
       std::vector<int>(selection_indices.begin(), selection_indices.end());
   EXPECT_EQ(selected_indices.size(), size_t(3));
-  EXPECT_EQ(4u, menu_1.GetItemCount());
+  EXPECT_EQ(4, menu_1.GetItemCount());
 
   // Move the 3 selected indices in model_1 to model_2.
   menu_1.ExecuteExistingCommandForTesting(1);
diff --git a/chrome/browser/ui/tabs/existing_window_sub_menu_model.cc b/chrome/browser/ui/tabs/existing_window_sub_menu_model.cc
index 36a8ab0..2ec52c8 100644
--- a/chrome/browser/ui/tabs/existing_window_sub_menu_model.cc
+++ b/chrome/browser/ui/tabs/existing_window_sub_menu_model.cc
@@ -106,11 +106,11 @@
         browser->GetWindowTitleForMaxWidth(kWindowTitleForMenuMaxWidth);
     menu_item_infos.emplace_back(window_title);
     menu_item_infos.back().may_have_mnemonics = false;
-    menu_item_infos.back().target_index = i;
+    menu_item_infos.back().target_index = static_cast<int>(i);
   }
   return menu_item_infos;
 }
 
-void ExistingWindowSubMenuModel::ExecuteExistingCommand(size_t target_index) {
+void ExistingWindowSubMenuModel::ExecuteExistingCommand(int target_index) {
   model()->ExecuteAddToExistingWindowCommand(GetContextIndex(), target_index);
 }
diff --git a/chrome/browser/ui/tabs/existing_window_sub_menu_model.h b/chrome/browser/ui/tabs/existing_window_sub_menu_model.h
index 3f27dc9..8b1b5bc 100644
--- a/chrome/browser/ui/tabs/existing_window_sub_menu_model.h
+++ b/chrome/browser/ui/tabs/existing_window_sub_menu_model.h
@@ -66,7 +66,7 @@
 
  private:
   // ExistingBaseSubMenuModel:
-  void ExecuteExistingCommand(size_t target_index) override;
+  void ExecuteExistingCommand(int target_index) override;
 };
 
 #endif  // CHROME_BROWSER_UI_TABS_EXISTING_WINDOW_SUB_MENU_MODEL_H_
diff --git a/chrome/browser/ui/tabs/existing_window_sub_menu_model_unittest.cc b/chrome/browser/ui/tabs/existing_window_sub_menu_model_unittest.cc
index ec39457c..9caa2d4 100644
--- a/chrome/browser/ui/tabs/existing_window_sub_menu_model_unittest.cc
+++ b/chrome/browser/ui/tabs/existing_window_sub_menu_model_unittest.cc
@@ -233,7 +233,7 @@
   auto menu1 = ExistingWindowSubMenuModel::Create(
       nullptr, browser()->tab_menu_model_delegate(),
       browser()->tab_strip_model(), 0);
-  ASSERT_EQ(5u, menu1->GetItemCount());
+  ASSERT_EQ(5, menu1->GetItemCount());
   CheckBrowserTitle(menu1->GetLabelAt(2), kLongTabTitleExample, 3);
   CheckBrowserTitle(menu1->GetLabelAt(3), "Browser 3 Tab 2", 2);
   CheckBrowserTitle(menu1->GetLabelAt(4), kLongTabTitleExample, 1);
@@ -242,7 +242,7 @@
   auto menu2 = ExistingWindowSubMenuModel::Create(
       nullptr, browser_2->tab_menu_model_delegate(),
       browser_2->tab_strip_model(), 0);
-  ASSERT_EQ(5u, menu2->GetItemCount());
+  ASSERT_EQ(5, menu2->GetItemCount());
   CheckBrowserTitle(menu2->GetLabelAt(2), kLongTabTitleExample, 3);
   CheckBrowserTitle(menu2->GetLabelAt(3), "Browser 3 Tab 2", 2);
   CheckBrowserTitle(menu2->GetLabelAt(4), "Browser 1", 1);
@@ -254,7 +254,7 @@
   auto menu3 = ExistingWindowSubMenuModel::Create(
       nullptr, browser_3->tab_menu_model_delegate(),
       browser_3->tab_strip_model(), 0);
-  ASSERT_EQ(5u, menu3->GetItemCount());
+  ASSERT_EQ(5, menu3->GetItemCount());
   CheckBrowserTitle(menu3->GetLabelAt(2), kLongTabTitleExample, 1);
   CheckBrowserTitle(menu3->GetLabelAt(3), "Browser 1", 1);
   CheckBrowserTitle(menu3->GetLabelAt(4), kLongTabTitleExample, 3);
@@ -291,7 +291,7 @@
   auto menu = ExistingWindowSubMenuModel::Create(
       nullptr, browser()->tab_menu_model_delegate(),
       browser()->tab_strip_model(), 0);
-  ASSERT_EQ(4u, menu->GetItemCount());
+  ASSERT_EQ(4, menu->GetItemCount());
   ASSERT_EQ(kBrowser3ExpectedTitle, menu->GetLabelAt(2));
   ASSERT_EQ(kBrowser2ExpectedTitle, menu->GetLabelAt(3));
 
@@ -299,7 +299,7 @@
   auto menu_incognito = ExistingWindowSubMenuModel::Create(
       nullptr, incognito_browser_1->tab_menu_model_delegate(),
       incognito_browser_1->tab_strip_model(), 0);
-  ASSERT_EQ(3u, menu_incognito->GetItemCount());
+  ASSERT_EQ(3, menu_incognito->GetItemCount());
   ASSERT_EQ(kIncognitoBrowser2ExpectedTitle, menu_incognito->GetLabelAt(2));
 
   // Clean up.
@@ -329,7 +329,7 @@
   auto menu = ExistingWindowSubMenuModel::Create(
       nullptr, browser()->tab_menu_model_delegate(),
       browser()->tab_strip_model(), 0);
-  ASSERT_EQ(4u, menu->GetItemCount());
+  ASSERT_EQ(4, menu->GetItemCount());
   ASSERT_EQ(kBrowser3ExpectedTitle, menu->GetLabelAt(2));
   ASSERT_EQ(kBrowser2ExpectedTitle, menu->GetLabelAt(3));
 
@@ -397,7 +397,7 @@
   auto menu1 = ExistingWindowSubMenuModel::Create(
       nullptr, browser()->tab_menu_model_delegate(),
       browser()->tab_strip_model(), 0);
-  ASSERT_EQ(15u, menu1->GetItemCount());
+  ASSERT_EQ(15, menu1->GetItemCount());
   EXPECT_EQ(u"Desk 1 (Current)", menu1->GetLabelAt(2));
   CheckBrowserTitle(menu1->GetLabelAt(3), kBrowser2TabTitle, 1);
   EXPECT_EQ(ui::SPACING_SEPARATOR, menu1->GetSeparatorTypeAt(4));
diff --git a/chrome/browser/ui/tabs/tab_menu_model_unittest.cc b/chrome/browser/ui/tabs/tab_menu_model_unittest.cc
index eeab4ac68..2a9df4d4 100644
--- a/chrome/browser/ui/tabs/tab_menu_model_unittest.cc
+++ b/chrome/browser/ui/tabs/tab_menu_model_unittest.cc
@@ -27,7 +27,7 @@
 
   // Verify it has items. The number varies by platform, so we don't check
   // the exact number.
-  EXPECT_GT(model.GetItemCount(), 5u);
+  EXPECT_GT(model.GetItemCount(), 5);
 
   int item_count = 0;
   CountEnabledExecutable(&model, &item_count);
@@ -42,9 +42,8 @@
                      browser()->tab_strip_model(), 0);
 
   // Verify that CommandMoveTabsToNewWindow is in the menu.
-  EXPECT_TRUE(
-      model.GetIndexOfCommandId(TabStripModel::CommandMoveTabsToNewWindow)
-          .has_value());
+  EXPECT_GT(
+      model.GetIndexOfCommandId(TabStripModel::CommandMoveTabsToNewWindow), -1);
 }
 
 TEST_F(TabMenuModelTest, AddToExistingGroupSubmenu) {
@@ -62,13 +61,12 @@
   TabMenuModel menu(&delegate_, browser()->tab_menu_model_delegate(),
                     tab_strip_model, 3);
 
-  size_t submenu_index =
-      menu.GetIndexOfCommandId(TabStripModel::CommandAddToExistingGroup)
-          .value();
+  int submenu_index =
+      menu.GetIndexOfCommandId(TabStripModel::CommandAddToExistingGroup);
   ui::MenuModel* submenu = menu.GetSubmenuModelAt(submenu_index);
 
   EXPECT_TRUE(submenu->HasIcons());
-  EXPECT_EQ(submenu->GetItemCount(), 5u);
+  EXPECT_EQ(submenu->GetItemCount(), 5);
   EXPECT_EQ(submenu->GetCommandIdAt(0),
             ExistingBaseSubMenuModel::kMinExistingTabGroupCommandId);
   EXPECT_EQ(submenu->GetTypeAt(1), ui::MenuModel::TYPE_SEPARATOR);
@@ -95,13 +93,12 @@
   TabMenuModel menu(&delegate_, browser()->tab_menu_model_delegate(),
                     tab_strip_model, 1);
 
-  size_t submenu_index =
-      menu.GetIndexOfCommandId(TabStripModel::CommandAddToExistingGroup)
-          .value();
+  int submenu_index =
+      menu.GetIndexOfCommandId(TabStripModel::CommandAddToExistingGroup);
   ui::MenuModel* submenu = menu.GetSubmenuModelAt(submenu_index);
 
   EXPECT_TRUE(submenu->HasIcons());
-  EXPECT_EQ(submenu->GetItemCount(), 4u);
+  EXPECT_EQ(submenu->GetItemCount(), 4);
   EXPECT_EQ(submenu->GetCommandIdAt(0),
             ExistingBaseSubMenuModel::kMinExistingTabGroupCommandId);
   EXPECT_EQ(submenu->GetTypeAt(1), ui::MenuModel::TYPE_SEPARATOR);
@@ -126,12 +123,11 @@
   TabMenuModel menu(&delegate_, browser()->tab_menu_model_delegate(),
                     tab_strip_model, 1);
 
-  size_t submenu_index =
-      menu.GetIndexOfCommandId(TabStripModel::CommandAddToExistingGroup)
-          .value();
+  int submenu_index =
+      menu.GetIndexOfCommandId(TabStripModel::CommandAddToExistingGroup);
   ui::MenuModel* submenu = menu.GetSubmenuModelAt(submenu_index);
 
-  EXPECT_EQ(submenu->GetItemCount(), 3u);
+  EXPECT_EQ(submenu->GetItemCount(), 3);
 
   // Ungroup the tab at 0 to make the group in the menu dangle.
   tab_strip_model->RemoveFromGroup({0});
@@ -187,10 +183,8 @@
         std::string());
     TabMenuModel menu(&delegate_, browser()->tab_menu_model_delegate(),
                       tab_strip, 0);
-    EXPECT_FALSE(
-        menu.GetIndexOfCommandId(TabStripModel::CommandFollowSite).has_value());
-    EXPECT_FALSE(menu.GetIndexOfCommandId(TabStripModel::CommandUnfollowSite)
-                     .has_value());
+    EXPECT_EQ(-1, menu.GetIndexOfCommandId(TabStripModel::CommandFollowSite));
+    EXPECT_EQ(-1, menu.GetIndexOfCommandId(TabStripModel::CommandUnfollowSite));
   }
 
   // "Unfollow site" should be added when all sites are in kFollowed state.
@@ -206,10 +200,8 @@
         std::string());
     TabMenuModel menu(&delegate_, browser()->tab_menu_model_delegate(),
                       tab_strip, 0);
-    EXPECT_FALSE(
-        menu.GetIndexOfCommandId(TabStripModel::CommandFollowSite).has_value());
-    EXPECT_TRUE(menu.GetIndexOfCommandId(TabStripModel::CommandUnfollowSite)
-                    .has_value());
+    EXPECT_EQ(-1, menu.GetIndexOfCommandId(TabStripModel::CommandFollowSite));
+    EXPECT_NE(-1, menu.GetIndexOfCommandId(TabStripModel::CommandUnfollowSite));
   }
 
   // "Follow site" should be added when not all sites are in kFollowed state.
@@ -225,10 +217,8 @@
         TabWebFeedFollowState::kNotFollowed, std::string());
     TabMenuModel menu(&delegate_, browser()->tab_menu_model_delegate(),
                       tab_strip, 0);
-    EXPECT_TRUE(
-        menu.GetIndexOfCommandId(TabStripModel::CommandFollowSite).has_value());
-    EXPECT_FALSE(menu.GetIndexOfCommandId(TabStripModel::CommandUnfollowSite)
-                     .has_value());
+    EXPECT_NE(-1, menu.GetIndexOfCommandId(TabStripModel::CommandFollowSite));
+    EXPECT_EQ(-1, menu.GetIndexOfCommandId(TabStripModel::CommandUnfollowSite));
   }
 
   // Neither "Follow site" nor "Unfollow site" should be added when the recorded
@@ -246,9 +236,7 @@
         std::string());
     TabMenuModel menu(&delegate_, browser()->tab_menu_model_delegate(),
                       tab_strip, 0);
-    EXPECT_FALSE(
-        menu.GetIndexOfCommandId(TabStripModel::CommandFollowSite).has_value());
-    EXPECT_FALSE(menu.GetIndexOfCommandId(TabStripModel::CommandUnfollowSite)
-                     .has_value());
+    EXPECT_EQ(-1, menu.GetIndexOfCommandId(TabStripModel::CommandFollowSite));
+    EXPECT_EQ(-1, menu.GetIndexOfCommandId(TabStripModel::CommandUnfollowSite));
   }
 }
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc
index 5d3ee40..f3e1413 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -198,22 +198,21 @@
     if (base::FeatureList::IsEnabled(features::kChromeTipsInMainMenu)) {
       AddItem(IDC_CHROME_TIPS, l10n_util::GetStringUTF16(IDS_CHROME_TIPS));
       if (base::FeatureList::IsEnabled(features::kChromeTipsInMainMenuNewBadge))
-        SetIsNewFeatureAt(GetIndexOfCommandId(IDC_CHROME_TIPS).value(), true);
+        SetIsNewFeatureAt(GetIndexOfCommandId(IDC_CHROME_TIPS), true);
     }
     if (base::FeatureList::IsEnabled(features::kChromeWhatsNewUI)) {
       AddItem(IDC_CHROME_WHATS_NEW,
               l10n_util::GetStringUTF16(IDS_CHROME_WHATS_NEW));
       if (base::FeatureList::IsEnabled(
               features::kChromeWhatsNewInMainMenuNewBadge)) {
-        SetIsNewFeatureAt(GetIndexOfCommandId(IDC_CHROME_WHATS_NEW).value(),
-                          true);
+        SetIsNewFeatureAt(GetIndexOfCommandId(IDC_CHROME_WHATS_NEW), true);
       }
     }
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
     AddItemWithStringId(IDC_HELP_PAGE_VIA_MENU, help_string_id);
     if (browser_defaults::kShowHelpMenuItemIcon) {
       ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-      SetIcon(GetIndexOfCommandId(IDC_HELP_PAGE_VIA_MENU).value(),
+      SetIcon(GetIndexOfCommandId(IDC_HELP_PAGE_VIA_MENU),
               ui::ImageModel::FromImage(rb.GetNativeImageNamed(IDR_HELP_MENU)));
     }
     if (browser->profile()->GetPrefs()->GetBoolean(prefs::kUserFeedbackAllowed))
@@ -821,7 +820,7 @@
 // - Browser relaunch, quit.
 void AppMenuModel::Build() {
   // Build (and, by extension, Init) should only be called once.
-  DCHECK_EQ(0u, GetItemCount());
+  DCHECK_EQ(0, GetItemCount());
 
   bool need_separator = false;
   if (IsCommandIdVisible(IDC_UPGRADE_DIALOG)) {
@@ -855,11 +854,11 @@
         std::make_unique<RecentTabsSubMenuModel>(provider_, browser_));
     AddSubMenuWithStringId(IDC_RECENT_TABS_MENU, IDS_HISTORY_MENU,
                            sub_menus_.back().get());
-    SetElementIdentifierAt(GetIndexOfCommandId(IDC_RECENT_TABS_MENU).value(),
+    SetElementIdentifierAt(GetIndexOfCommandId(IDC_RECENT_TABS_MENU),
                            kHistoryMenuItem);
   }
   AddItemWithStringId(IDC_SHOW_DOWNLOADS, IDS_SHOW_DOWNLOADS);
-  SetElementIdentifierAt(GetIndexOfCommandId(IDC_SHOW_DOWNLOADS).value(),
+  SetElementIdentifierAt(GetIndexOfCommandId(IDC_SHOW_DOWNLOADS),
                          kDownloadsMenuItem);
   if (!browser_->profile()->IsGuestSession()) {
     bookmark_sub_menu_model_ =
@@ -1018,7 +1017,7 @@
     DCHECK(error);
     if (error->HasMenuItem()) {
       AddItem(error->MenuItemCommandID(), error->MenuItemLabel());
-      SetIcon(GetIndexOfCommandId(error->MenuItemCommandID()).value(),
+      SetIcon(GetIndexOfCommandId(error->MenuItemCommandID()),
               error->MenuItemIcon());
       menu_items_added = true;
     }
@@ -1038,23 +1037,23 @@
           policy::SystemFeature::kBrowserSettings,
           g_browser_process->local_state());
 
-  absl::optional<size_t> index = GetIndexOfCommandId(IDC_OPTIONS);
-  if (index.has_value())
-    SetEnabledAt(index.value(), !is_disabled);
+  int index = GetIndexOfCommandId(IDC_OPTIONS);
+  if (index != -1)
+    SetEnabledAt(index, !is_disabled);
 
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
   index = GetIndexOfCommandId(IDC_HELP_MENU);
-  if (index.has_value()) {
+  if (index != -1) {
     ui::SimpleMenuModel* help_menu =
-        static_cast<ui::SimpleMenuModel*>(GetSubmenuModelAt(index.has_value()));
+        static_cast<ui::SimpleMenuModel*>(GetSubmenuModelAt(index));
     index = help_menu->GetIndexOfCommandId(IDC_ABOUT);
-    if (index.has_value())
-      help_menu->SetEnabledAt(index.value(), !is_disabled);
+    if (index != -1)
+      help_menu->SetEnabledAt(index, !is_disabled);
   }
 #else   // BUILDFLAG(GOOGLE_CHROME_BRANDING)
   index = GetIndexOfCommandId(IDC_ABOUT);
-  if (index.has_value())
-    SetEnabledAt(index.value(), !is_disabled);
+  if (index != -1)
+    SetEnabledAt(index, !is_disabled);
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
 }
 #endif  // BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/ui/toolbar/app_menu_model_unittest.cc b/chrome/browser/ui/toolbar/app_menu_model_unittest.cc
index 2cbb6248..2e3de9c 100644
--- a/chrome/browser/ui/toolbar/app_menu_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model_unittest.cc
@@ -171,11 +171,11 @@
                                                  &fake_delegate);
   TestAppMenuModel model(this, browser(), &app_menu_icon_controller);
   model.Init();
-  size_t item_count = model.GetItemCount();
+  int itemCount = model.GetItemCount();
 
   // Verify it has items. The number varies by platform, so we don't check
   // the exact number.
-  EXPECT_GT(item_count, 10u);
+  EXPECT_GT(itemCount, 10);
 
   // Verify that the upgrade item is visible if supported.
   EXPECT_EQ(browser_defaults::kShowUpgradeMenuItem,
@@ -189,14 +189,14 @@
   // delegate is internal, it doesn't use the one we pass in.
   // Note: the second item in the menu may be a separator if the browser
   // supports showing upgrade status in the app menu.
-  size_t item_index = 1;
+  int item_index = 1;
   if (model.GetTypeAt(item_index) == ui::MenuModel::TYPE_SEPARATOR)
     ++item_index;
   model.ActivatedAt(item_index);
   EXPECT_TRUE(model.IsEnabledAt(item_index));
   // Make sure to use the index that is not separator in all configurations.
-  model.ActivatedAt(item_count - 1);
-  EXPECT_TRUE(model.IsEnabledAt(item_count - 1));
+  model.ActivatedAt(itemCount - 1);
+  EXPECT_TRUE(model.IsEnabledAt(itemCount - 1));
 
   EXPECT_EQ(model.execute_count_, 2);
   EXPECT_EQ(model.enable_count_, 2);
@@ -206,21 +206,21 @@
 
   // Choose something from the bookmark submenu and make sure it makes it back
   // to the delegate as well.
-  size_t bookmarks_model_index = 0;
-  for (size_t i = 0; i < item_count; ++i) {
+  int bookmarks_model_index = -1;
+  for (int i = 0; i < itemCount; ++i) {
     if (model.GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU) {
       // The bookmarks submenu comes after the Tabs and Downloads items.
       bookmarks_model_index = i + 2;
       break;
     }
   }
-  EXPECT_GT(bookmarks_model_index, 0u);
+  EXPECT_GT(bookmarks_model_index, -1);
   ui::MenuModel* bookmarks_model =
       model.GetSubmenuModelAt(bookmarks_model_index);
   EXPECT_TRUE(bookmarks_model);
   // The bookmarks model may be empty until we tell it we're going to show it.
   bookmarks_model->MenuWillShow();
-  EXPECT_GT(bookmarks_model->GetItemCount(), 1u);
+  EXPECT_GT(bookmarks_model->GetItemCount(), 1);
 
   // Bookmark manager item.
   bookmarks_model->ActivatedAt(4);
@@ -243,19 +243,19 @@
 
   AppMenuModel model(this, browser());
   model.Init();
-  absl::optional<size_t> index1 = model.GetIndexOfCommandId(command1);
-  ASSERT_TRUE(index1.has_value());
-  absl::optional<size_t> index2 = model.GetIndexOfCommandId(command2);
-  ASSERT_TRUE(index2.has_value());
+  int index1 = model.GetIndexOfCommandId(command1);
+  EXPECT_GT(index1, -1);
+  int index2 = model.GetIndexOfCommandId(command2);
+  EXPECT_GT(index2, -1);
 
-  EXPECT_TRUE(model.IsEnabledAt(index1.value()));
+  EXPECT_TRUE(model.IsEnabledAt(index1));
   EXPECT_EQ(0, error1->execute_count());
-  model.ActivatedAt(index1.value());
+  model.ActivatedAt(index1);
   EXPECT_EQ(1, error1->execute_count());
 
-  EXPECT_TRUE(model.IsEnabledAt(index2.value()));
+  EXPECT_TRUE(model.IsEnabledAt(index2));
   EXPECT_EQ(0, error2->execute_count());
-  model.ActivatedAt(index2.value());
+  model.ActivatedAt(index2);
   EXPECT_EQ(1, error1->execute_count());
 }
 
@@ -265,18 +265,17 @@
 TEST_F(AppMenuModelTest, DisableSettingsItem) {
   AppMenuModel model(this, browser());
   model.Init();
-  const size_t options_index = model.GetIndexOfCommandId(IDC_OPTIONS).value();
+  const int options_index = model.GetIndexOfCommandId(IDC_OPTIONS);
   EXPECT_TRUE(model.IsEnabledAt(options_index));
 
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-  const size_t help_menu_index =
-      model.GetIndexOfCommandId(IDC_HELP_MENU).value();
+  const int help_menu_index = model.GetIndexOfCommandId(IDC_HELP_MENU);
   ui::SimpleMenuModel* help_menu = static_cast<ui::SimpleMenuModel*>(
       model.GetSubmenuModelAt(help_menu_index));
-  const size_t about_index = help_menu->GetIndexOfCommandId(IDC_ABOUT).value();
+  const int about_index = help_menu->GetIndexOfCommandId(IDC_ABOUT);
   EXPECT_TRUE(help_menu->IsEnabledAt(about_index));
 #else
-  const size_t about_index = model.GetIndexOfCommandId(IDC_ABOUT).value();
+  const int about_index = model.GetIndexOfCommandId(IDC_ABOUT);
   EXPECT_TRUE(model.IsEnabledAt(about_index));
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
 
diff --git a/chrome/browser/ui/toolbar/back_forward_menu_model.cc b/chrome/browser/ui/toolbar/back_forward_menu_model.cc
index 6ab722c..8513a3e 100644
--- a/chrome/browser/ui/toolbar/back_forward_menu_model.cc
+++ b/chrome/browser/ui/toolbar/back_forward_menu_model.cc
@@ -42,8 +42,8 @@
 using content::NavigationEntry;
 using content::WebContents;
 
-const size_t BackForwardMenuModel::kMaxHistoryItems = 12;
-const size_t BackForwardMenuModel::kMaxChapterStops = 5;
+const int BackForwardMenuModel::kMaxHistoryItems = 12;
+const int BackForwardMenuModel::kMaxChapterStops = 5;
 static const int kMaxBackForwardMenuWidth = 700;
 
 BackForwardMenuModel::BackForwardMenuModel(Browser* browser,
@@ -56,12 +56,12 @@
   return true;
 }
 
-size_t BackForwardMenuModel::GetItemCount() const {
-  size_t items = GetHistoryItemCount();
-  if (items == 0)
+int BackForwardMenuModel::GetItemCount() const {
+  int items = GetHistoryItemCount();
+  if (items <= 0)
     return items;
 
-  size_t chapter_stops = 0;
+  int chapter_stops = 0;
 
   // Next, we count ChapterStops, if any.
   if (items == kMaxHistoryItems)
@@ -81,20 +81,20 @@
   return items;
 }
 
-ui::MenuModel::ItemType BackForwardMenuModel::GetTypeAt(size_t index) const {
+ui::MenuModel::ItemType BackForwardMenuModel::GetTypeAt(int index) const {
   return IsSeparator(index) ? TYPE_SEPARATOR : TYPE_COMMAND;
 }
 
 ui::MenuSeparatorType BackForwardMenuModel::GetSeparatorTypeAt(
-    size_t index) const {
+    int index) const {
   return ui::NORMAL_SEPARATOR;
 }
 
-int BackForwardMenuModel::GetCommandIdAt(size_t index) const {
-  return static_cast<int>(index);
+int BackForwardMenuModel::GetCommandIdAt(int index) const {
+  return index;
 }
 
-std::u16string BackForwardMenuModel::GetLabelAt(size_t index) const {
+std::u16string BackForwardMenuModel::GetLabelAt(int index) const {
   // Return label "Show Full History" for the last item of the menu.
   if (ShouldShowFullHistoryBeVisible() && index == GetItemCount() - 1)
     return l10n_util::GetStringUTF16(IDS_HISTORY_SHOWFULLHISTORY_LINK);
@@ -114,13 +114,13 @@
   return menu_text;
 }
 
-bool BackForwardMenuModel::IsItemDynamicAt(size_t index) const {
+bool BackForwardMenuModel::IsItemDynamicAt(int index) const {
   // This object is only used for a single showing of a menu.
   return false;
 }
 
 bool BackForwardMenuModel::GetAcceleratorAt(
-    size_t index,
+    int index,
     ui::Accelerator* accelerator) const {
   return false;
 }
@@ -129,11 +129,11 @@
   return false;
 }
 
-int BackForwardMenuModel::GetGroupIdAt(size_t index) const {
+int BackForwardMenuModel::GetGroupIdAt(int index) const {
   return false;
 }
 
-ui::ImageModel BackForwardMenuModel::GetIconAt(size_t index) const {
+ui::ImageModel BackForwardMenuModel::GetIconAt(int index) const {
   if (!ItemHasIcon(index))
     return ui::ImageModel();
 
@@ -142,45 +142,45 @@
     return ui::ImageModel::FromImage(
         ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
             IDR_HISTORY_FAVICON));
+  } else {
+    NavigationEntry* entry = GetNavigationEntry(index);
+    content::FaviconStatus fav_icon = entry->GetFavicon();
+    if (!fav_icon.valid && menu_model_delegate()) {
+      // FetchFavicon is not const because it caches the result, but GetIconAt
+      // is const because it is not be apparent to outside observers that an
+      // internal change is taking place. Compared to spreading const in
+      // unintuitive places (e.g. making menu_model_delegate() const but
+      // returning a non-const while sprinkling virtual on member variables),
+      // this const_cast is the lesser evil.
+      const_cast<BackForwardMenuModel*>(this)->FetchFavicon(entry);
+    }
+    return ui::ImageModel::FromImage(fav_icon.image);
   }
-  NavigationEntry* entry = GetNavigationEntry(index);
-  content::FaviconStatus fav_icon = entry->GetFavicon();
-  if (!fav_icon.valid && menu_model_delegate()) {
-    // FetchFavicon is not const because it caches the result, but GetIconAt
-    // is const because it is not be apparent to outside observers that an
-    // internal change is taking place. Compared to spreading const in
-    // unintuitive places (e.g. making menu_model_delegate() const but
-    // returning a non-const while sprinkling virtual on member variables),
-    // this const_cast is the lesser evil.
-    const_cast<BackForwardMenuModel*>(this)->FetchFavicon(entry);
-  }
-  return ui::ImageModel::FromImage(fav_icon.image);
 }
 
 ui::ButtonMenuItemModel* BackForwardMenuModel::GetButtonMenuItemAt(
-    size_t index) const {
+    int index) const {
   return nullptr;
 }
 
-bool BackForwardMenuModel::IsEnabledAt(size_t index) const {
+bool BackForwardMenuModel::IsEnabledAt(int index) const {
   return index < GetItemCount() && !IsSeparator(index);
 }
 
-ui::MenuModel* BackForwardMenuModel::GetSubmenuModelAt(size_t index) const {
+ui::MenuModel* BackForwardMenuModel::GetSubmenuModelAt(int index) const {
   return nullptr;
 }
 
-void BackForwardMenuModel::ActivatedAt(size_t index) {
+void BackForwardMenuModel::ActivatedAt(int index) {
   ActivatedAt(index, 0);
 }
 
-void BackForwardMenuModel::ActivatedAt(size_t index, int event_flags) {
+void BackForwardMenuModel::ActivatedAt(int index, int event_flags) {
   DCHECK(!IsSeparator(index));
 
   // Execute the command for the last item: "Show Full History".
   if (ShouldShowFullHistoryBeVisible() && index == GetItemCount() - 1) {
-    base::RecordComputedAction(
-        BuildActionName("ShowFullHistory", absl::nullopt));
+    base::RecordComputedAction(BuildActionName("ShowFullHistory", -1));
     NavigateParams params(GetSingletonTabNavigateParams(
         browser_, GURL(chrome::kChromeUIHistoryURL)));
     ShowSingletonTabOverwritingNTP(browser_, &params);
@@ -188,49 +188,46 @@
   }
 
   // Log whether it was a history or chapter click.
-  size_t items = GetHistoryItemCount();
+  int items = GetHistoryItemCount();
   if (index < items) {
     base::RecordComputedAction(BuildActionName("HistoryClick", index));
   } else {
-    const auto chapter_index = (index == items)
-                                   ? absl::nullopt
-                                   : absl::make_optional(index - items - 1);
+    const int chapter_index = index - items - 1;
     base::RecordComputedAction(BuildActionName("ChapterClick", chapter_index));
   }
 
-  absl::optional<size_t> controller_index = MenuIndexToNavEntryIndex(index);
-  DCHECK(controller_index.has_value());
+  int controller_index = MenuIndexToNavEntryIndex(index);
 
   UMA_HISTOGRAM_BOOLEAN(
       "Navigation.BackForward.NavigatingToEntryMarkedToBeSkipped",
       GetWebContents()->GetController().IsEntryMarkedToBeSkipped(
-          controller_index.value()));
+          controller_index));
 
   WindowOpenDisposition disposition =
       ui::DispositionFromEventFlags(event_flags);
-  chrome::NavigateToIndexWithDisposition(browser_, controller_index.value(),
+  chrome::NavigateToIndexWithDisposition(browser_, controller_index,
                                          disposition);
 }
 
 void BackForwardMenuModel::MenuWillShow() {
-  base::RecordComputedAction(BuildActionName("Popup", absl::nullopt));
+  base::RecordComputedAction(BuildActionName("Popup", -1));
   requested_favicons_.clear();
   cancelable_task_tracker_.TryCancelAll();
 }
 
-bool BackForwardMenuModel::IsSeparator(size_t index) const {
-  size_t history_items = GetHistoryItemCount();
+bool BackForwardMenuModel::IsSeparator(int index) const {
+  int history_items = GetHistoryItemCount();
   // If the index is past the number of history items + separator,
   // we then consider if it is a chapter-stop entry.
   if (index > history_items) {
     // We either are in ChapterStop area, or at the end of the list (the "Show
     // Full History" link).
-    size_t chapter_stops = GetChapterStopCount(history_items);
+    int chapter_stops = GetChapterStopCount(history_items);
     if (chapter_stops == 0)
       return false;  // We must have reached the "Show Full History" link.
     // Otherwise, look to see if we have reached the separator for the
     // chapter-stops. If not, this is a chapter stop.
-    return index == history_items + 1 + chapter_stops;
+    return (index == history_items + 1 + chapter_stops);
   }
 
   // Look to see if we have reached the separator for the history items.
@@ -265,8 +262,8 @@
 
   // Find the current model_index for the unique id.
   NavigationEntry* entry = nullptr;
-  size_t model_index = 0;
-  for (size_t i = 0; i + 1 < GetItemCount(); ++i) {
+  int model_index = -1;
+  for (int i = 0; i < GetItemCount() - 1; i++) {
     if (IsSeparator(i))
       continue;
     if (GetNavigationEntry(i)->GetUniqueID() == navigation_entry_unique_id) {
@@ -293,64 +290,64 @@
   }
 }
 
-size_t BackForwardMenuModel::GetHistoryItemCount() const {
+int BackForwardMenuModel::GetHistoryItemCount() const {
   WebContents* contents = GetWebContents();
   if (!contents)
     return 0;
 
-  size_t items = contents->GetController().GetCurrentEntryIndex();
+  int items = contents->GetController().GetCurrentEntryIndex();
   if (model_type_ == ModelType::kForward) {
     // Only count items from n+1 to end (if n is current entry)
     items = contents->GetController().GetEntryCount() - items - 1;
   }
 
-  return std::min(items, kMaxHistoryItems);
+  return base::clamp(items, 0, kMaxHistoryItems);
 }
 
-size_t BackForwardMenuModel::GetChapterStopCount(size_t history_items) const {
+int BackForwardMenuModel::GetChapterStopCount(int history_items) const {
   if (history_items != kMaxHistoryItems)
     return 0;
 
   WebContents* contents = GetWebContents();
-  size_t current_entry = contents->GetController().GetCurrentEntryIndex();
+  int current_entry = contents->GetController().GetCurrentEntryIndex();
 
   const bool forward = model_type_ == ModelType::kForward;
-  size_t chapter_id = current_entry;
-  if (!forward && chapter_id < history_items)
-    return 0;
-  chapter_id =
-      forward ? (chapter_id + history_items) : (chapter_id - history_items);
+  int chapter_id = current_entry;
+  if (forward)
+    chapter_id += history_items;
+  else
+    chapter_id -= history_items;
 
-  size_t chapter_stops = 0;
+  int chapter_stops = 0;
   do {
-    const absl::optional<size_t> index =
-        GetIndexOfNextChapterStop(chapter_id, forward);
-    if (!index.has_value())
+    chapter_id = GetIndexOfNextChapterStop(chapter_id, forward);
+    if (chapter_id == -1)
       break;
-    chapter_id = index.value();
     ++chapter_stops;
   } while (chapter_stops < kMaxChapterStops);
 
   return chapter_stops;
 }
 
-absl::optional<size_t> BackForwardMenuModel::GetIndexOfNextChapterStop(
-    size_t start_from,
-    bool forward) const {
+int BackForwardMenuModel::GetIndexOfNextChapterStop(int start_from,
+                                                    bool forward) const {
+  if (start_from < 0)
+    return -1;  // Out of bounds.
+
   // We want to advance over the current chapter stop, so we add one.
   // We don't need to do this when direction is backwards.
   if (forward)
     start_from++;
 
   NavigationController& controller = GetWebContents()->GetController();
-  const size_t max_count = controller.GetEntryCount();
+  const int max_count = controller.GetEntryCount();
   if (start_from >= max_count)
-    return absl::nullopt;  // Out of bounds.
+    return -1;  // Out of bounds.
 
   NavigationEntry* start_entry = controller.GetEntryAtIndex(start_from);
   const GURL& url = start_entry->GetURL();
 
-  auto same_domain_func = [&controller, &url](size_t i) {
+  auto same_domain_func = [&controller, &url](int i) {
     return net::registry_controlled_domains::SameDomainOrHost(
         url, controller.GetEntryAtIndex(i)->GetURL(),
         net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
@@ -359,7 +356,7 @@
   if (forward) {
     // When going forwards we return the entry before the entry that has a
     // different domain.
-    for (size_t i = start_from + 1; i < max_count; ++i) {
+    for (int i = start_from + 1; i < max_count; ++i) {
       if (!same_domain_func(i))
         return i - 1;
     }
@@ -369,39 +366,36 @@
 
   // When going backwards we return the first entry we find that has a
   // different domain.
-  for (size_t i = start_from; i > 0; --i) {
-    if (!same_domain_func(i - 1))
-      return i - 1;
+  for (int i = start_from - 1; i >= 0; --i) {
+    if (!same_domain_func(i))
+      return i;
   }
   // We have reached the beginning without finding a chapter stop.
-  return absl::nullopt;
+  return -1;
 }
 
-absl::optional<size_t> BackForwardMenuModel::FindChapterStop(
-    size_t offset,
-    bool forward,
-    size_t skip) const {
+int BackForwardMenuModel::FindChapterStop(int offset,
+                                          bool forward,
+                                          int skip) const {
+  if (offset < 0 || skip < 0)
+    return -1;
+
+  if (!forward)
+    offset *= -1;
+
   WebContents* contents = GetWebContents();
-  size_t entry = contents->GetController().GetCurrentEntryIndex();
-  if (!forward && entry < offset)
-    return absl::nullopt;
-  entry = forward ? (entry + offset) : (entry - offset);
-  for (size_t i = 0; i <= skip; ++i) {
-    const absl::optional<size_t> index =
-        GetIndexOfNextChapterStop(entry, forward);
-    if (!index.has_value())
-      return absl::nullopt;
-    entry = index.value();
-  }
+  int entry = contents->GetController().GetCurrentEntryIndex() + offset;
+  for (int i = 0; i < skip + 1; i++)
+    entry = GetIndexOfNextChapterStop(entry, forward);
 
   return entry;
 }
 
-bool BackForwardMenuModel::ItemHasCommand(size_t index) const {
+bool BackForwardMenuModel::ItemHasCommand(int index) const {
   return index < GetItemCount() && !IsSeparator(index);
 }
 
-bool BackForwardMenuModel::ItemHasIcon(size_t index) const {
+bool BackForwardMenuModel::ItemHasIcon(int index) const {
   return index < GetItemCount() && !IsSeparator(index);
 }
 
@@ -416,56 +410,56 @@
              : browser_->tab_strip_model()->GetActiveWebContents();
 }
 
-absl::optional<size_t> BackForwardMenuModel::MenuIndexToNavEntryIndex(
-    size_t index) const {
+int BackForwardMenuModel::MenuIndexToNavEntryIndex(int index) const {
   WebContents* contents = GetWebContents();
-  size_t history_items = GetHistoryItemCount();
+  int history_items = GetHistoryItemCount();
+
+  DCHECK_GE(index, 0);
 
   // Convert anything above the History items separator.
   if (index < history_items) {
-    const size_t current_index =
-        contents->GetController().GetCurrentEntryIndex();
-    const bool forward = model_type_ == ModelType::kForward;
-    if (!forward && current_index <= index)
-      return absl::nullopt;
-    return forward ? (current_index + index + 1)
-                   : (current_index - (index + 1));
+    if (model_type_ == ModelType::kForward) {
+      index += contents->GetController().GetCurrentEntryIndex() + 1;
+    } else {
+      // Back menu is reverse.
+      index = contents->GetController().GetCurrentEntryIndex() - (index + 1);
+    }
+    return index;
   }
   if (index == history_items)
-    return absl::nullopt;  // Don't translate the separator for history items.
+    return -1;  // Don't translate the separator for history items.
 
   if (index >= history_items + 1 + GetChapterStopCount(history_items))
-    return absl::nullopt;  // This is beyond the last chapter stop so we abort.
+    return -1;  // This is beyond the last chapter stop so we abort.
 
   // This menu item is a chapter stop located between the two separators.
   return FindChapterStop(history_items, model_type_ == ModelType::kForward,
                          index - history_items - 1);
 }
 
-NavigationEntry* BackForwardMenuModel::GetNavigationEntry(size_t index) const {
-  absl::optional<size_t> controller_index = MenuIndexToNavEntryIndex(index);
+NavigationEntry* BackForwardMenuModel::GetNavigationEntry(int index) const {
+  int controller_index = MenuIndexToNavEntryIndex(index);
   NavigationController& controller = GetWebContents()->GetController();
 
-  DCHECK(controller_index.has_value());
-  DCHECK_LT(controller_index.value(),
-            static_cast<size_t>(controller.GetEntryCount()));
+  DCHECK_GE(controller_index, 0);
+  DCHECK_LT(controller_index, controller.GetEntryCount());
 
-  return controller.GetEntryAtIndex(controller_index.value());
+  return controller.GetEntryAtIndex(controller_index);
 }
 
 std::string BackForwardMenuModel::BuildActionName(
-    const std::string& action,
-    absl::optional<size_t> index) const {
+    const std::string& action, int index) const {
   DCHECK(!action.empty());
+  DCHECK_GE(index, -1);
   std::string metric_string;
   if (model_type_ == ModelType::kForward)
     metric_string += "ForwardMenu_";
   else
     metric_string += "BackMenu_";
   metric_string += action;
-  if (index.has_value()) {
+  if (index != -1) {
     // +1 is for historical reasons (indices used to start at 1).
-    metric_string += base::NumberToString(index.value() + 1);
+    metric_string += base::NumberToString(index + 1);
   }
   return metric_string;
 }
diff --git a/chrome/browser/ui/toolbar/back_forward_menu_model.h b/chrome/browser/ui/toolbar/back_forward_menu_model.h
index 27b2b2c..72c7716 100644
--- a/chrome/browser/ui/toolbar/back_forward_menu_model.h
+++ b/chrome/browser/ui/toolbar/back_forward_menu_model.h
@@ -52,26 +52,25 @@
   // chapter-stops, separators and the Show Full History link. This function
   // uses GetHistoryItemCount() and GetChapterStopCount() internally to figure
   // out the total number of items to show.
-  size_t GetItemCount() const override;
-  ItemType GetTypeAt(size_t index) const override;
-  ui::MenuSeparatorType GetSeparatorTypeAt(size_t index) const override;
-  int GetCommandIdAt(size_t index) const override;
-  std::u16string GetLabelAt(size_t index) const override;
-  bool IsItemDynamicAt(size_t index) const override;
-  bool GetAcceleratorAt(size_t index,
-                        ui::Accelerator* accelerator) const override;
+  int GetItemCount() const override;
+  ItemType GetTypeAt(int index) const override;
+  ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override;
+  int GetCommandIdAt(int index) const override;
+  std::u16string GetLabelAt(int index) const override;
+  bool IsItemDynamicAt(int index) const override;
+  bool GetAcceleratorAt(int index, ui::Accelerator* accelerator) const override;
   bool IsItemCheckedAt(size_t index) const override;
-  int GetGroupIdAt(size_t index) const override;
-  ui::ImageModel GetIconAt(size_t index) const override;
-  ui::ButtonMenuItemModel* GetButtonMenuItemAt(size_t index) const override;
-  bool IsEnabledAt(size_t index) const override;
-  MenuModel* GetSubmenuModelAt(size_t index) const override;
-  void ActivatedAt(size_t index) override;
-  void ActivatedAt(size_t index, int event_flags) override;
+  int GetGroupIdAt(int index) const override;
+  ui::ImageModel GetIconAt(int index) const override;
+  ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override;
+  bool IsEnabledAt(int index) const override;
+  MenuModel* GetSubmenuModelAt(int index) const override;
+  void ActivatedAt(int index) override;
+  void ActivatedAt(int index, int event_flags) override;
   void MenuWillShow() override;
 
   // Is the item at |index| a separator?
-  bool IsSeparator(size_t index) const;
+  bool IsSeparator(int index) const;
 
  private:
   friend class BackFwdMenuModelTest;
@@ -107,26 +106,25 @@
   // not report more than kMaxHistoryItems. The number returned also does not
   // include the separator line after the history items (nor the separator for
   // the "Show Full History" link).
-  size_t GetHistoryItemCount() const;
+  int GetHistoryItemCount() const;
 
   // Returns how many chapter-stop items the menu should show. For the
   // definition of a chapter-stop, see GetIndexOfNextChapterStop(). The number
   // returned does not include the separator lines before and after the
   // chapter-stops.
-  size_t GetChapterStopCount(size_t history_items) const;
+  int GetChapterStopCount(int history_items) const;
 
   // Finds the next chapter-stop in the NavigationEntryList starting from
   // the index specified in |start_from| and continuing in the direction
   // specified (|forward|) until either a chapter-stop is found or we reach the
-  // end, in which case nullopt is returned. If |start_from| is out of bounds,
-  // nullopt will also be returned. A chapter-stop is defined as the last page
-  // the user browsed to within the same domain. For example, if the user's
-  // homepage is Google and they navigate to Google pages G1, G2 and G3 before
-  // heading over to WikiPedia for pages W1 and W2 and then back to Google for
-  // pages G4 and G5 then G3, W2 and G5 are considered chapter-stops. The return
-  // value from this function is an index into the NavigationEntryList vector.
-  absl::optional<size_t> GetIndexOfNextChapterStop(size_t start_from,
-                                                   bool forward) const;
+  // end, in which case -1 is returned. If |start_from| is out of bounds, -1
+  // will also be returned. A chapter-stop is defined as the last page the user
+  // browsed to within the same domain. For example, if the user's homepage is
+  // Google and they navigate to Google pages G1, G2 and G3 before heading over
+  // to WikiPedia for pages W1 and W2 and then back to Google for pages G4 and
+  // G5 then G3, W2 and G5 are considered chapter-stops. The return value from
+  // this function is an index into the NavigationEntryList vector.
+  int GetIndexOfNextChapterStop(int start_from, bool forward) const;
 
   // Finds a given chapter-stop starting at the currently active entry in the
   // NavigationEntryList vector advancing first forward or backward by |offset|
@@ -141,34 +139,32 @@
   // NOTE: Both |offset| and |skip| must be non-negative. The return value from
   // this function is an index into the NavigationEntryList vector. If |offset|
   // is out of bounds or if we skip too far (run out of chapter-stops) this
-  // function returns nullopt.
-  absl::optional<size_t> FindChapterStop(size_t offset,
-                                         bool forward,
-                                         size_t skip) const;
+  // function returns -1.
+  int FindChapterStop(int offset, bool forward, int skip) const;
 
   // How many items (max) to show in the back/forward history menu dropdown.
-  static const size_t kMaxHistoryItems;
+  static const int kMaxHistoryItems;
 
   // How many chapter-stops (max) to show in the back/forward dropdown list.
-  static const size_t kMaxChapterStops;
+  static const int kMaxChapterStops;
 
   // Takes a menu item index as passed in through one of the menu delegate
   // functions and converts it into an index into the NavigationEntryList
   // vector. |index| can point to a separator, or the
-  // "Show Full History" link in which case this function returns nullopt.
-  absl::optional<size_t> MenuIndexToNavEntryIndex(size_t index) const;
+  // "Show Full History" link in which case this function returns -1.
+  int MenuIndexToNavEntryIndex(int index) const;
 
   // Does the item have a command associated with it?
-  bool ItemHasCommand(size_t index) const;
+  bool ItemHasCommand(int index) const;
 
   // Returns true if there is an icon for this menu item.
-  bool ItemHasIcon(size_t index) const;
+  bool ItemHasIcon(int index) const;
 
   // Allow the unit test to use the "Show Full History" label.
   std::u16string GetShowFullHistoryLabel() const;
 
   // Looks up a NavigationEntry by menu id.
-  content::NavigationEntry* GetNavigationEntry(size_t index) const;
+  content::NavigationEntry* GetNavigationEntry(int index) const;
 
   // Retrieves the WebContents pointer to use, which is either the one that
   // the unit test sets (using set_test_web_contents) or the one from
@@ -178,9 +174,8 @@
   // Build a string version of a user action on this menu, used as an
   // identifier for logging user behavior.
   // E.g. BuildActionName("Click", 2) returns "BackMenu_Click2".
-  // An index of nullopt means no index.
-  std::string BuildActionName(const std::string& name,
-                              absl::optional<size_t> index) const;
+  // An index of -1 means no index.
+  std::string BuildActionName(const std::string& name, int index) const;
 
   // Returns true if "Show Full History" item should be visible. It is visible
   // only in outside incognito mode.
diff --git a/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc b/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc
index ea6aa50..bdfdc014 100644
--- a/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc
@@ -77,11 +77,10 @@
              FaviconServiceFactory::GetDefaultFactory()}};
   }
 
-  void ValidateModel(BackForwardMenuModel* model,
-                     size_t history_items,
-                     size_t chapter_stops) {
-    size_t h = std::min(BackForwardMenuModel::kMaxHistoryItems, history_items);
-    size_t c = std::min(BackForwardMenuModel::kMaxChapterStops, chapter_stops);
+  void ValidateModel(BackForwardMenuModel* model, int history_items,
+                     int chapter_stops) {
+    int h = std::min(BackForwardMenuModel::kMaxHistoryItems, history_items);
+    int c = std::min(BackForwardMenuModel::kMaxChapterStops, chapter_stops);
     EXPECT_EQ(h, model->GetHistoryItemCount());
     EXPECT_EQ(c, model->GetChapterStopCount(h));
     if (h > 0)
@@ -143,8 +142,8 @@
       browser.get(), BackForwardMenuModel::ModelType::kForward));
   forward_model->set_test_web_contents(web_contents());
 
-  EXPECT_EQ(0u, back_model->GetItemCount());
-  EXPECT_EQ(0u, forward_model->GetItemCount());
+  EXPECT_EQ(0, back_model->GetItemCount());
+  EXPECT_EQ(0, forward_model->GetItemCount());
   EXPECT_FALSE(back_model->ItemHasCommand(1));
 
   // Seed the controller with a few URLs
@@ -158,8 +157,8 @@
   LoadURLAndUpdateState("http://www.c.com/3", "C3");
 
   // There're two more items here: a separator and a "Show Full History".
-  EXPECT_EQ(9u, back_model->GetItemCount());
-  EXPECT_EQ(0u, forward_model->GetItemCount());
+  EXPECT_EQ(9, back_model->GetItemCount());
+  EXPECT_EQ(0, forward_model->GetItemCount());
   EXPECT_EQ(u"C2", back_model->GetLabelAt(0));
   EXPECT_EQ(u"A1", back_model->GetLabelAt(6));
   EXPECT_EQ(back_model->GetShowFullHistoryLabel(),
@@ -174,8 +173,8 @@
 
   NavigateToOffset(-7);
 
-  EXPECT_EQ(0u, back_model->GetItemCount());
-  EXPECT_EQ(9u, forward_model->GetItemCount());
+  EXPECT_EQ(0, back_model->GetItemCount());
+  EXPECT_EQ(9, forward_model->GetItemCount());
   EXPECT_EQ(u"A2", forward_model->GetLabelAt(0));
   EXPECT_EQ(u"C3", forward_model->GetLabelAt(6));
   EXPECT_EQ(forward_model->GetShowFullHistoryLabel(),
@@ -190,8 +189,8 @@
 
   NavigateToOffset(4);
 
-  EXPECT_EQ(6u, back_model->GetItemCount());
-  EXPECT_EQ(5u, forward_model->GetItemCount());
+  EXPECT_EQ(6, back_model->GetItemCount());
+  EXPECT_EQ(5, forward_model->GetItemCount());
   EXPECT_EQ(u"B1", back_model->GetLabelAt(0));
   EXPECT_EQ(u"A1", back_model->GetLabelAt(3));
   EXPECT_EQ(back_model->GetShowFullHistoryLabel(),
@@ -250,10 +249,10 @@
   LoadURLAndUpdateState("http://www.k.com/2", "K2");
 
   // Also there're two more for a separator and a "Show Full History".
-  size_t chapter_stop_offset = 6;
+  int chapter_stop_offset = 6;
   EXPECT_EQ(BackForwardMenuModel::kMaxHistoryItems + 2 + chapter_stop_offset,
             back_model->GetItemCount());
-  EXPECT_EQ(0u, forward_model->GetItemCount());
+  EXPECT_EQ(0, forward_model->GetItemCount());
   EXPECT_EQ(u"K1", back_model->GetLabelAt(0));
   EXPECT_EQ(back_model->GetShowFullHistoryLabel(),
       back_model->GetLabelAt(BackForwardMenuModel::kMaxHistoryItems + 1 +
@@ -272,7 +271,7 @@
 
   EXPECT_EQ(BackForwardMenuModel::kMaxHistoryItems + 2 + chapter_stop_offset,
             forward_model->GetItemCount());
-  EXPECT_EQ(0u, back_model->GetItemCount());
+  EXPECT_EQ(0, back_model->GetItemCount());
   EXPECT_EQ(u"A2", forward_model->GetLabelAt(0));
   EXPECT_EQ(forward_model->GetShowFullHistoryLabel(),
       forward_model->GetLabelAt(BackForwardMenuModel::kMaxHistoryItems + 1 +
@@ -302,7 +301,7 @@
   forward_model->set_test_web_contents(web_contents());
 
   // Seed the controller with 32 URLs.
-  size_t i = 0;
+  int i = 0;
   LoadURLAndUpdateState("http://www.a.com/1", "A1");
   ValidateModel(back_model.get(), i++, 0);
   LoadURLAndUpdateState("http://www.a.com/2", "A2");
@@ -381,7 +380,7 @@
   // browsed to within the same domain.
 
   // Check to see if the chapter stops have the right labels.
-  size_t index = BackForwardMenuModel::kMaxHistoryItems;
+  int index = BackForwardMenuModel::kMaxHistoryItems;
   // Empty string indicates item is a separator.
   EXPECT_EQ(std::u16string(), back_model->GetLabelAt(index++));
   EXPECT_EQ(u"F3", back_model->GetLabelAt(index++));
@@ -414,7 +413,7 @@
   NavigateToOffset(6);
 
   // Go back enough to make sure no chapter stops should appear.
-  NavigateToOffset(-static_cast<int>(BackForwardMenuModel::kMaxHistoryItems));
+  NavigateToOffset(-BackForwardMenuModel::kMaxHistoryItems);
   ValidateModel(forward_model.get(), BackForwardMenuModel::kMaxHistoryItems, 0);
   // Go forward (still no chapter stop)
   NavigationSimulator::GoForward(web_contents());
@@ -458,23 +457,23 @@
   EXPECT_EQ(u"K3", forward_model->GetLabelAt(index));
 
   // Now test the boundary cases by using the chapter stop function directly.
-  // Out of bounds, first decrementing, then incrementing.
-  EXPECT_FALSE(back_model->GetIndexOfNextChapterStop(33, false).has_value());
-  EXPECT_FALSE(back_model->GetIndexOfNextChapterStop(33, true).has_value());
+  // Out of bounds, first too far right (incrementing), then too far left.
+  EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(33, false));
+  EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(-1, true));
   // Test being at end and going right, then at beginning going left.
-  EXPECT_FALSE(back_model->GetIndexOfNextChapterStop(32, true).has_value());
-  EXPECT_FALSE(back_model->GetIndexOfNextChapterStop(0, false).has_value());
+  EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(32, true));
+  EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(0, false));
   // Test success: beginning going right and end going left.
-  EXPECT_EQ(2u, back_model->GetIndexOfNextChapterStop(0, true));
-  EXPECT_EQ(29u, back_model->GetIndexOfNextChapterStop(32, false));
+  EXPECT_EQ(2,  back_model->GetIndexOfNextChapterStop(0, true));
+  EXPECT_EQ(29, back_model->GetIndexOfNextChapterStop(32, false));
   // Now see when the chapter stops begin to show up.
-  EXPECT_FALSE(back_model->GetIndexOfNextChapterStop(1, false).has_value());
-  EXPECT_FALSE(back_model->GetIndexOfNextChapterStop(2, false).has_value());
-  EXPECT_EQ(2u, back_model->GetIndexOfNextChapterStop(3, false));
+  EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(1, false));
+  EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(2, false));
+  EXPECT_EQ(2,  back_model->GetIndexOfNextChapterStop(3, false));
   // Now see when the chapter stops end.
-  EXPECT_EQ(32u, back_model->GetIndexOfNextChapterStop(30, true));
-  EXPECT_EQ(32u, back_model->GetIndexOfNextChapterStop(31, true));
-  EXPECT_FALSE(back_model->GetIndexOfNextChapterStop(32, true).has_value());
+  EXPECT_EQ(32, back_model->GetIndexOfNextChapterStop(30, true));
+  EXPECT_EQ(32, back_model->GetIndexOfNextChapterStop(31, true));
+  EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(32, true));
 
   if (content::BackForwardCache::IsSameSiteBackForwardCacheFeatureEnabled()) {
     // The case below currently fails on the linux-bfcache-rel bot with
@@ -488,8 +487,8 @@
   // Go to A1;
   NavigateToIndex(0);
   LoadURLAndUpdateState("http://www.b.com/1", "B1");
-  EXPECT_EQ(0u, back_model->GetIndexOfNextChapterStop(1, false));
-  EXPECT_EQ(1u, back_model->GetIndexOfNextChapterStop(0, true));
+  EXPECT_EQ(0, back_model->GetIndexOfNextChapterStop(1, false));
+  EXPECT_EQ(1, back_model->GetIndexOfNextChapterStop(0, true));
 
   // Now see if it counts 'www.x.com' and 'mail.x.com' as same domain, which
   // it should.
@@ -499,15 +498,15 @@
   LoadURLAndUpdateState("http://www.b.com/1", "B1");
   LoadURLAndUpdateState("http://mail.b.com/2", "B2-mai");
   LoadURLAndUpdateState("http://new.site.com", "new");
-  EXPECT_EQ(1u, back_model->GetIndexOfNextChapterStop(0, true));
-  EXPECT_EQ(3u, back_model->GetIndexOfNextChapterStop(1, true));
-  EXPECT_EQ(3u, back_model->GetIndexOfNextChapterStop(2, true));
-  EXPECT_EQ(4u, back_model->GetIndexOfNextChapterStop(3, true));
+  EXPECT_EQ(1, back_model->GetIndexOfNextChapterStop(0, true));
+  EXPECT_EQ(3, back_model->GetIndexOfNextChapterStop(1, true));
+  EXPECT_EQ(3, back_model->GetIndexOfNextChapterStop(2, true));
+  EXPECT_EQ(4, back_model->GetIndexOfNextChapterStop(3, true));
   // And try backwards as well.
-  EXPECT_EQ(3u, back_model->GetIndexOfNextChapterStop(4, false));
-  EXPECT_EQ(1u, back_model->GetIndexOfNextChapterStop(3, false));
-  EXPECT_EQ(1u, back_model->GetIndexOfNextChapterStop(2, false));
-  EXPECT_FALSE(back_model->GetIndexOfNextChapterStop(1, false).has_value());
+  EXPECT_EQ(3, back_model->GetIndexOfNextChapterStop(4, false));
+  EXPECT_EQ(1, back_model->GetIndexOfNextChapterStop(3, false));
+  EXPECT_EQ(1, back_model->GetIndexOfNextChapterStop(2, false));
+  EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(1, false));
 }
 
 TEST_F(BackFwdMenuModelTest, EscapeLabel) {
@@ -519,7 +518,7 @@
       browser.get(), BackForwardMenuModel::ModelType::kBackward));
   back_model->set_test_web_contents(web_contents());
 
-  EXPECT_EQ(0u, back_model->GetItemCount());
+  EXPECT_EQ(0, back_model->GetItemCount());
   EXPECT_FALSE(back_model->ItemHasCommand(1));
 
   LoadURLAndUpdateState("http://www.a.com/1", "A B");
@@ -528,7 +527,7 @@
   LoadURLAndUpdateState("http://www.a.com/4", "A &&& B");
   LoadURLAndUpdateState("http://www.a.com/5", "");
 
-  EXPECT_EQ(6u, back_model->GetItemCount());
+  EXPECT_EQ(6, back_model->GetItemCount());
 
   EXPECT_EQ(u"A B", back_model->GetLabelAt(3));
   EXPECT_EQ(u"A && B", back_model->GetLabelAt(2));
@@ -610,7 +609,7 @@
 
   back_model->set_test_web_contents(web_contents());
 
-  EXPECT_EQ(0u, back_model->GetItemCount());
+  EXPECT_EQ(0, back_model->GetItemCount());
   EXPECT_FALSE(back_model->ItemHasCommand(1));
 
   // Seed the controller with a few URLs
@@ -620,7 +619,7 @@
 
   // There're should be only the visited pages but not "Show Full History" item
   // and its separator.
-  EXPECT_EQ(2u, back_model->GetItemCount());
+  EXPECT_EQ(2, back_model->GetItemCount());
   EXPECT_EQ(u"A2", back_model->GetLabelAt(0));
   EXPECT_EQ(u"A1", back_model->GetLabelAt(1));
 
diff --git a/chrome/browser/ui/toolbar/media_router_contextual_menu.cc b/chrome/browser/ui/toolbar/media_router_contextual_menu.cc
index 26c5b3a0..5643924b 100644
--- a/chrome/browser/ui/toolbar/media_router_contextual_menu.cc
+++ b/chrome/browser/ui/toolbar/media_router_contextual_menu.cc
@@ -63,9 +63,9 @@
   if (shown_by_policy_) {
     menu_model->AddItemWithStringId(IDC_MEDIA_ROUTER_SHOWN_BY_POLICY,
                                     IDS_MEDIA_ROUTER_SHOWN_BY_POLICY);
+    // TODO (kylixrd): Review the use of the hard-coded color constant.
     menu_model->SetIcon(
-        menu_model->GetIndexOfCommandId(IDC_MEDIA_ROUTER_SHOWN_BY_POLICY)
-            .value(),
+        menu_model->GetIndexOfCommandId(IDC_MEDIA_ROUTER_SHOWN_BY_POLICY),
         ui::ImageModel::FromVectorIcon(vector_icons::kBusinessIcon,
                                        ui::kColorIcon, 16));
   } else {
diff --git a/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc b/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc
index 9eb66dc..e827ad66 100644
--- a/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc
+++ b/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc
@@ -38,7 +38,7 @@
 constexpr bool kShownByUser = false;
 
 bool HasCommandId(ui::MenuModel* menu_model, int command_id) {
-  for (size_t i = 0; i < menu_model->GetItemCount(); ++i) {
+  for (int i = 0; i < menu_model->GetItemCount(); i++) {
     if (menu_model->GetCommandIdAt(i) == command_id)
       return true;
   }
@@ -131,7 +131,7 @@
   // Report an issue
 
   // Number of menu items, including separators.
-  size_t expected_number_items = 6;
+  int expected_number_items = 6;
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
   expected_number_items += 2;
 #endif
@@ -140,7 +140,7 @@
   std::unique_ptr<ui::SimpleMenuModel> model = menu.CreateMenuModel();
   EXPECT_EQ(model->GetItemCount(), expected_number_items);
 
-  for (size_t i = 0; i < expected_number_items; ++i) {
+  for (int i = 0; i < expected_number_items; i++) {
     EXPECT_TRUE(model->IsEnabledAt(i));
     EXPECT_TRUE(model->IsVisibleAt(i));
   }
@@ -152,7 +152,7 @@
   // Run the same checks as before. All existing menu items should be now
   // enabled and visible.
   EXPECT_EQ(model->GetItemCount(), expected_number_items);
-  for (size_t i = 0; i < expected_number_items; ++i) {
+  for (int i = 0; i < expected_number_items; i++) {
     EXPECT_TRUE(model->IsEnabledAt(i));
     EXPECT_TRUE(model->IsVisibleAt(i));
   }
@@ -163,10 +163,8 @@
 // incognito.
 TEST_F(MediaRouterContextualMenuUnitTest, EnableAndDisableReportIssue) {
   MediaRouterContextualMenu menu(browser(), kShownByPolicy, &observer_);
-  EXPECT_TRUE(
-      menu.CreateMenuModel()
-          ->GetIndexOfCommandId(IDC_MEDIA_TOOLBAR_CONTEXT_REPORT_CAST_ISSUE)
-          .has_value());
+  EXPECT_NE(-1, menu.CreateMenuModel()->GetIndexOfCommandId(
+                    IDC_MEDIA_TOOLBAR_CONTEXT_REPORT_CAST_ISSUE));
 
   std::unique_ptr<BrowserWindow> window(CreateBrowserWindow());
   std::unique_ptr<Browser> incognito_browser(
@@ -175,10 +173,8 @@
 
   MediaRouterContextualMenu incognito_menu(incognito_browser.get(),
                                            kShownByPolicy, &observer_);
-  EXPECT_FALSE(
-      incognito_menu.CreateMenuModel()
-          ->GetIndexOfCommandId(IDC_MEDIA_TOOLBAR_CONTEXT_REPORT_CAST_ISSUE)
-          .has_value());
+  EXPECT_EQ(-1, incognito_menu.CreateMenuModel()->GetIndexOfCommandId(
+                    IDC_MEDIA_TOOLBAR_CONTEXT_REPORT_CAST_ISSUE));
 }
 #endif
 
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
index 8d0191ff..4e298894 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
@@ -121,8 +121,8 @@
   SubMenuItem(int command_id,
               std::unique_ptr<ui::SimpleMenuModel> sub_menu_model)
       : parent_id(command_id), menu_model(std::move(sub_menu_model)) {
-    const size_t child_id_count = menu_model->GetItemCount();
-    for (size_t i = 0; i < child_id_count; ++i) {
+    const int child_id_count = menu_model->GetItemCount();
+    for (int i = 0; i < child_id_count; i++) {
       child_ids.insert(menu_model->GetCommandIdAt(i));
     }
   }
@@ -191,19 +191,17 @@
   // the header, otherwise, we show it beside the first item underneath it.
   // If the first item underneath it is a submenu, we instead show it beside
   // the first item in that submenu.
-  const absl::optional<size_t> index_in_menu = GetIndexOfCommandId(command_id);
-  const absl::optional<size_t> header_index =
-      GetIndexOfCommandId(kRecentlyClosedHeaderCommandId);
+  const int index_in_menu = GetIndexOfCommandId(command_id);
+  const int header_index = GetIndexOfCommandId(kRecentlyClosedHeaderCommandId);
   const int parent_id = GetParentCommandId(command_id);
-  const absl::optional<size_t> parent_index =
-      parent_id == -1 ? absl::nullopt : GetIndexOfCommandId(parent_id);
+  const int parent_index =
+      parent_id == -1 ? -1 : GetIndexOfCommandId(parent_id);
   if ((command_id == kDisabledRecentlyClosedHeaderCommandId ||
-       (header_index.has_value() && !IsSubMenuModelCommandId(command_id) &&
-        index_in_menu == header_index.value() + 1) ||
-       (header_index.has_value() &&
-        (command_id == local_window_items_.begin()->first ||
-         command_id == local_group_items_.begin()->first) &&
-        parent_index == header_index.value() + 1)) &&
+       ((header_index != -1 && (!IsSubMenuModelCommandId(command_id) &&
+                                index_in_menu == header_index + 1)) ||
+        ((command_id == local_window_items_.begin()->first ||
+          command_id == local_group_items_.begin()->first) &&
+         parent_index == header_index + 1))) &&
       reopen_closed_tab_accelerator_.key_code() != ui::VKEY_UNKNOWN) {
     *accelerator = reopen_closed_tab_accelerator_;
     return true;
@@ -307,7 +305,7 @@
 }
 
 const gfx::FontList* RecentTabsSubMenuModel::GetLabelFontListAt(
-    size_t index) const {
+    int index) const {
   const int command_id = GetCommandIdAt(index);
   if (command_id == kRecentlyClosedHeaderCommandId ||
       IsDeviceNameCommandId(command_id)) {
@@ -317,7 +315,7 @@
   return nullptr;
 }
 
-int RecentTabsSubMenuModel::GetMaxWidthForItemAtIndex(size_t item_index) const {
+int RecentTabsSubMenuModel::GetMaxWidthForItemAtIndex(int item_index) const {
   const int command_id = GetCommandIdAt(item_index);
   if (command_id == IDC_RECENT_TABS_NO_DEVICE_TABS ||
       command_id == kRecentlyClosedHeaderCommandId ||
@@ -328,7 +326,7 @@
 }
 
 bool RecentTabsSubMenuModel::GetURLAndTitleForItemAtIndex(
-    size_t index,
+    int index,
     std::string* url,
     std::u16string* title) {
   const int command_id = GetCommandIdAt(index);
@@ -417,7 +415,7 @@
       ++added_count;
     }
   }
-  DCHECK_GE(last_local_model_index_, 0u);
+  DCHECK_GE(last_local_model_index_, 0);
 }
 
 void RecentTabsSubMenuModel::BuildTabsFromOtherDevices() {
@@ -468,7 +466,7 @@
   }  // for all sessions
 
   // We are not supposed to get here unless at least some items were added.
-  DCHECK_GT(GetItemCount(), 0u);
+  DCHECK_GT(GetItemCount(), 0);
 }
 
 void RecentTabsSubMenuModel::BuildLocalTabItem(
@@ -476,7 +474,7 @@
     absl::optional<tab_groups::TabGroupVisualData> visual_data,
     const std::u16string& title,
     const GURL& url,
-    size_t curr_model_index) {
+    int curr_model_index) {
   TabNavigationItem item(std::string(), session_id, title, url);
   const int command_id = GetAndIncrementNextMenuID();
   // See comments in BuildLocalEntries() about usage of InsertItem*At().
@@ -485,14 +483,13 @@
                title.empty() ? base::UTF8ToUTF16(item.url.spec()) : title);
   local_tab_navigation_items_.emplace(command_id, item);
   AddTabFavicon(command_id, this, item.url);
-  const absl::optional<size_t> header_index =
-      GetIndexOfCommandId(kRecentlyClosedHeaderCommandId);
+  const int header_index = GetIndexOfCommandId(kRecentlyClosedHeaderCommandId);
   // We shouldn't get here if there is no recently closed header.
-  DCHECK(header_index.has_value());
+  DCHECK_GT(header_index, -1);
   // visual_data should only be populated if the tab was part of a tab group
   // when closed. We shouldn't set the minor icon for the item most recently
   // closed, as this creates visual clutter alongside the shortcut text.
-  if (visual_data.has_value() && curr_model_index > header_index.value() + 1) {
+  if (visual_data.has_value() && curr_model_index > header_index + 1) {
     const ui::ColorProvider* color_provider =
         browser_->window()->GetColorProvider();
     const ui::ColorId color_id =
@@ -508,13 +505,13 @@
 void RecentTabsSubMenuModel::BuildLocalWindowItem(
     SessionID window_id,
     std::unique_ptr<ui::SimpleMenuModel> window_model,
-    size_t num_tabs,
-    size_t curr_model_index) {
+    int num_tabs,
+    int curr_model_index) {
   const int command_id = GetAndIncrementNextMenuID();
-  InsertSubMenuAt(curr_model_index, command_id,
-                  l10n_util::GetPluralStringFUTF16(IDS_RECENTLY_CLOSED_WINDOW,
-                                                   static_cast<int>(num_tabs)),
-                  window_model.get());
+  InsertSubMenuAt(
+      curr_model_index, command_id,
+      l10n_util::GetPluralStringFUTF16(IDS_RECENTLY_CLOSED_WINDOW, num_tabs),
+      window_model.get());
   local_sub_menu_items_.emplace(
       command_id, SubMenuItem(command_id, std::move(window_model)));
   SetIcon(curr_model_index, CreateFavicon(kTabIcon));
@@ -524,8 +521,8 @@
     SessionID session_id,
     tab_groups::TabGroupVisualData visual_data,
     std::unique_ptr<ui::SimpleMenuModel> group_model,
-    size_t num_tabs,
-    size_t curr_model_index) {
+    int num_tabs,
+    int curr_model_index) {
   const int command_id = GetAndIncrementNextMenuID();
   // Set the item label to the name of the group and the number of tabs.
   std::u16string item_label = GetGroupItemLabel(visual_data.title(), num_tabs);
@@ -670,14 +667,14 @@
 }
 
 std::u16string RecentTabsSubMenuModel::GetGroupItemLabel(std::u16string title,
-                                                         size_t num_tabs) {
+                                                         int num_tabs) {
   std::u16string item_label;
   if (title.empty()) {
     item_label = l10n_util::GetPluralStringFUTF16(
-        IDS_RECENTLY_CLOSED_GROUP_UNNAMED, static_cast<int>(num_tabs));
+        IDS_RECENTLY_CLOSED_GROUP_UNNAMED, num_tabs);
   } else {
-    item_label = l10n_util::GetPluralStringFUTF16(IDS_RECENTLY_CLOSED_GROUP,
-                                                  static_cast<int>(num_tabs));
+    item_label =
+        l10n_util::GetPluralStringFUTF16(IDS_RECENTLY_CLOSED_GROUP, num_tabs);
     item_label = base::ReplaceStringPlaceholders(item_label, {title}, nullptr);
   }
   return item_label;
@@ -694,7 +691,7 @@
 }
 
 void RecentTabsSubMenuModel::AddDeviceFavicon(
-    size_t index_in_menu,
+    int index_in_menu,
     sync_pb::SyncEnums::DeviceType device_type) {
   const gfx::VectorIcon* favicon = nullptr;
   switch (device_type) {
@@ -722,8 +719,7 @@
 void RecentTabsSubMenuModel::AddTabFavicon(int command_id,
                                            ui::SimpleMenuModel* menu_model,
                                            const GURL& url) {
-  const size_t index_in_menu =
-      menu_model->GetIndexOfCommandId(command_id).value();
+  const int index_in_menu = menu_model->GetIndexOfCommandId(command_id);
   // Set default icon first.
   menu_model->SetIcon(index_in_menu,
                       ui::ImageModel::FromImage(favicon::GetDefaultFavicon()));
@@ -770,10 +766,9 @@
     // Default icon has already been set.
     return;
   }
-  const absl::optional<size_t> index_in_menu =
-      menu_model->GetIndexOfCommandId(command_id);
-  DCHECK(index_in_menu.has_value());
-  menu_model->SetIcon(index_in_menu.value(),
+  const int index_in_menu = menu_model->GetIndexOfCommandId(command_id);
+  DCHECK_GT(index_in_menu, -1);
+  menu_model->SetIcon(index_in_menu,
                       ui::ImageModel::FromImage(image_result.image));
   ui::MenuModelDelegate* delegate = menu_model_delegate();
   if (delegate)
@@ -812,10 +807,10 @@
 }
 
 void RecentTabsSubMenuModel::ClearTabsFromOtherDevices() {
-  for (size_t index = GetItemCount(); index > last_local_model_index_ + 1;
-       --index) {
-    RemoveItemAt(index - 1);
-  }
+  DCHECK_GE(last_local_model_index_, 0);
+  const int count = GetItemCount();
+  for (int index = count - 1; index > last_local_model_index_; --index)
+    RemoveItemAt(index);
 
   weak_ptr_factory_for_other_devices_tab_.InvalidateWeakPtrs();
 
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
index 78c082c4..4bcfb37 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
@@ -79,10 +79,10 @@
   bool GetAcceleratorForCommandId(int command_id,
                                   ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
-  const gfx::FontList* GetLabelFontListAt(size_t index) const override;
+  const gfx::FontList* GetLabelFontListAt(int index) const override;
 
-  int GetMaxWidthForItemAtIndex(size_t item_index) const;
-  bool GetURLAndTitleForItemAtIndex(size_t index,
+  int GetMaxWidthForItemAtIndex(int item_index) const;
+  bool GetURLAndTitleForItemAtIndex(int index,
                                     std::string* url,
                                     std::u16string* title);
 
@@ -97,7 +97,7 @@
 
   // Index of the separator that follows the history menu item. Used as a
   // reference position for inserting local entries.
-  static constexpr size_t kHistorySeparatorIndex = 1;
+  static constexpr int kHistorySeparatorIndex = 1;
 
   // Build the menu items by populating the menumodel.
   void Build();
@@ -115,22 +115,22 @@
       absl::optional<tab_groups::TabGroupVisualData> visual_data,
       const std::u16string& title,
       const GURL& url,
-      size_t curr_model_index);
+      int curr_model_index);
 
   // Build the recently closed window item with parameters needed to restore it,
   // and add it to the menumodel at |curr_model_index|.
   void BuildLocalWindowItem(SessionID window_id,
                             std::unique_ptr<ui::SimpleMenuModel> window_model,
-                            size_t num_tabs,
-                            size_t curr_model_index);
+                            int num_tabs,
+                            int curr_model_index);
 
   // Build the recently closed group item with parameters needed to restore it,
   // and add it to the menumodel at |curr_model_index|.
   void BuildLocalGroupItem(SessionID session_id,
                            tab_groups::TabGroupVisualData visual_data,
                            std::unique_ptr<ui::SimpleMenuModel> group_model,
-                           size_t num_tabs,
-                           size_t curr_model_index);
+                           int num_tabs,
+                           int curr_model_index);
 
   // Build the tab item for other devices with parameters needed to restore it.
   void BuildOtherDevicesTabItem(const std::string& session_tag,
@@ -151,7 +151,7 @@
 
   // Return the appropriate menu item label for a tab group, given its title
   // and the number of tabs it contains.
-  std::u16string GetGroupItemLabel(std::u16string title, size_t num_tabs);
+  std::u16string GetGroupItemLabel(std::u16string title, int num_tabs);
 
   // Return the command id of the given id's parent submenu, if it has one that
   // is created by this menu model. Otherwise, return -1. This will be the case
@@ -159,7 +159,7 @@
   int GetParentCommandId(int command_id) const;
 
   // Add the favicon for the device section header.
-  void AddDeviceFavicon(size_t index_in_menu,
+  void AddDeviceFavicon(int index_in_menu,
                         sync_pb::SyncEnums::DeviceType device_type);
 
   // Add the favicon for a local or other devices' tab asynchronously,
@@ -264,7 +264,7 @@
 
   // Index of the last local entry (recently closed tab or window or group) in
   // the menumodel.
-  size_t last_local_model_index_ = kHistorySeparatorIndex;
+  int last_local_model_index_ = kHistorySeparatorIndex;
 
   base::CancelableTaskTracker local_tab_cancelable_task_tracker_;
 
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc
index 831f625..95b1b81c 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc
@@ -198,7 +198,7 @@
   // 3           <separator>
   // 4           No tabs from other Devices
 
-  EXPECT_EQ(5u, model.GetItemCount());
+  EXPECT_EQ(5, model.GetItemCount());
   EXPECT_FALSE(model.IsEnabledAt(2));
   EXPECT_FALSE(model.IsEnabledAt(4));
   EXPECT_EQ(0, model.enable_count());
@@ -242,7 +242,7 @@
   // 4           <tab for http://foo/1>
   // 5           <separator>
   // 6           No tabs from other Devices
-  EXPECT_EQ(7u, model.GetItemCount());
+  EXPECT_EQ(7, model.GetItemCount());
   EXPECT_TRUE(model.IsEnabledAt(0));
   model.ActivatedAt(0);
   EXPECT_TRUE(model.IsEnabledAt(1));
@@ -305,7 +305,7 @@
   // 4           <group1>
   // 5           <separator>
   // 6           No tabs from other Devices
-  EXPECT_EQ(7u, model.GetItemCount());
+  EXPECT_EQ(7, model.GetItemCount());
   EXPECT_TRUE(model.IsEnabledAt(0));
   model.ActivatedAt(0);
   EXPECT_TRUE(model.IsEnabledAt(1));
@@ -313,11 +313,11 @@
   EXPECT_TRUE(model.IsEnabledAt(3));
   EXPECT_EQ(ui::MenuModel::TYPE_SUBMENU, model.GetTypeAt(3));
   const ui::MenuModel* sub_menu_model_3 = model.GetSubmenuModelAt(3);
-  EXPECT_EQ(3u, sub_menu_model_3->GetItemCount());
+  EXPECT_EQ(3, sub_menu_model_3->GetItemCount());
   EXPECT_TRUE(model.IsEnabledAt(4));
   EXPECT_EQ(ui::MenuModel::TYPE_SUBMENU, model.GetTypeAt(4));
   const ui::MenuModel* sub_menu_model_4 = model.GetSubmenuModelAt(4);
-  EXPECT_EQ(2u, sub_menu_model_4->GetItemCount());
+  EXPECT_EQ(2, sub_menu_model_4->GetItemCount());
   model.ActivatedAt(3);
   model.ActivatedAt(4);
   EXPECT_FALSE(model.IsEnabledAt(6));
@@ -411,7 +411,7 @@
   // 3           <separator>
   // 4           No tabs from other Devices
 
-  EXPECT_EQ(5u, model.GetItemCount());
+  EXPECT_EQ(5, model.GetItemCount());
   EXPECT_TRUE(model.IsEnabledAt(0));
   EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, model.GetTypeAt(1));
   EXPECT_FALSE(model.IsEnabledAt(2));
@@ -438,7 +438,7 @@
 
   EXPECT_TRUE(delegate.got_changes());
 
-  EXPECT_EQ(8u, model.GetItemCount());
+  EXPECT_EQ(8, model.GetItemCount());
 
   EXPECT_TRUE(model.IsEnabledAt(0));
   model.ActivatedAt(0);
@@ -448,11 +448,11 @@
   EXPECT_TRUE(model.IsEnabledAt(3));
   EXPECT_EQ(ui::MenuModel::TYPE_SUBMENU, model.GetTypeAt(3));
   const ui::MenuModel* const window_sub_menu_model = model.GetSubmenuModelAt(3);
-  EXPECT_EQ(3u, window_sub_menu_model->GetItemCount());
+  EXPECT_EQ(3, window_sub_menu_model->GetItemCount());
   EXPECT_EQ(ui::MenuModel::TYPE_SUBMENU, window_sub_menu_model->GetTypeAt(2));
   const ui::MenuModel* const group_sub_menu_model =
       window_sub_menu_model->GetSubmenuModelAt(2);
-  EXPECT_EQ(1u, group_sub_menu_model->GetItemCount());
+  EXPECT_EQ(1, group_sub_menu_model->GetItemCount());
   EXPECT_TRUE(model.IsEnabledAt(4));
   EXPECT_TRUE(model.IsEnabledAt(5));
   model.ActivatedAt(3);
@@ -531,7 +531,7 @@
   // 11-12       <2 tabs of window 1 of session 2>
 
   TestRecentTabsSubMenuModel model(nullptr, browser());
-  EXPECT_EQ(13u, model.GetItemCount());
+  EXPECT_EQ(13, model.GetItemCount());
   model.ActivatedAt(0);
   EXPECT_TRUE(model.IsEnabledAt(0));
   model.ActivatedAt(1);
@@ -614,7 +614,7 @@
   // 4           No tabs from other Devices
 
   TestRecentTabsSubMenuModel model(nullptr, browser());
-  EXPECT_EQ(5u, model.GetItemCount());
+  EXPECT_EQ(5, model.GetItemCount());
   model.ActivatedAt(4);
   EXPECT_FALSE(model.IsEnabledAt(4));
 
@@ -644,7 +644,7 @@
   // 4           <section header for 1st session>
   // 5           <tab of the only window of session 0>
 
-  EXPECT_EQ(6u, model.GetItemCount());
+  EXPECT_EQ(6, model.GetItemCount());
   model.ActivatedAt(4);
   EXPECT_FALSE(model.IsEnabledAt(4));
   model.ActivatedAt(5);
@@ -682,7 +682,7 @@
   // 5           <new added tab of the only window of session 0>
   // 6           <tab of the only window of session 0>
 
-  EXPECT_EQ(7u, model.GetItemCount());
+  EXPECT_EQ(7, model.GetItemCount());
   model.ActivatedAt(4);
   EXPECT_FALSE(model.IsEnabledAt(4));
   model.ActivatedAt(5);
@@ -731,7 +731,7 @@
   // 11          <the only tab of the only window of session 1>
 
   TestRecentTabsSubMenuModel model(nullptr, browser());
-  EXPECT_EQ(12u, model.GetItemCount());
+  EXPECT_EQ(12, model.GetItemCount());
 
   std::vector<std::u16string> tab_titles =
       recent_tabs_builder.GetTabTitlesSortedByRecency();
@@ -767,7 +767,7 @@
   // 5-8         <4 most-recent tabs of session>
 
   TestRecentTabsSubMenuModel model(nullptr, browser());
-  EXPECT_EQ(9u, model.GetItemCount());
+  EXPECT_EQ(9, model.GetItemCount());
 
   std::vector<std::u16string> tab_titles =
       recent_tabs_builder.GetTabTitlesSortedByRecency();
@@ -795,7 +795,7 @@
   // 5           <the only tab of the only window of session 1>
 
   TestRecentTabsSubMenuModel model(nullptr, browser());
-  EXPECT_EQ(6u, model.GetItemCount());
+  EXPECT_EQ(6, model.GetItemCount());
   EXPECT_EQ(-1, model.GetMaxWidthForItemAtIndex(2));
   EXPECT_NE(-1, model.GetMaxWidthForItemAtIndex(3));
   EXPECT_NE(-1, model.GetMaxWidthForItemAtIndex(4));
@@ -815,7 +815,7 @@
   // 4           No tabs from other Devices
 
   TestRecentTabsSubMenuModel model(nullptr, browser());
-  EXPECT_EQ(5u, model.GetItemCount());
+  EXPECT_EQ(5, model.GetItemCount());
   EXPECT_EQ(-1, model.GetMaxWidthForItemAtIndex(2));
   EXPECT_NE(-1, model.GetMaxWidthForItemAtIndex(3));
   EXPECT_EQ(-1, model.GetMaxWidthForItemAtIndex(4));
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_context_menu.cc b/chrome/browser/ui/views/bookmarks/bookmark_context_menu.cc
index a35fa33..116e2b8 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_context_menu.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_context_menu.cc
@@ -66,7 +66,7 @@
       observer_(nullptr),
       close_on_remove_(close_on_remove) {
   ui::SimpleMenuModel* menu_model = controller_->menu_model();
-  for (size_t i = 0; i < menu_model->GetItemCount(); ++i) {
+  for (int i = 0; i < menu_model->GetItemCount(); ++i) {
     views::MenuModelAdapter::AppendMenuItemFromModel(
         menu_model, i, menu_, menu_model->GetCommandIdAt(i));
   }
diff --git a/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.cc b/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.cc
index 9eb4f90..0607b8f 100644
--- a/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.cc
+++ b/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.cc
@@ -6,7 +6,6 @@
 
 #include "base/callback_helpers.h"
 #include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ash/crostini/crostini_pref_names.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
 #include "chrome/browser/profiles/profile.h"
@@ -83,19 +82,6 @@
 void CrostiniAnsibleSoftwareConfigView::OnAnsibleSoftwareConfigurationStarted(
     const guest_os::GuestId& container_id) {}
 
-void CrostiniAnsibleSoftwareConfigView::OnAnsibleSoftwareConfigurationProgress(
-    const guest_os::GuestId& container_id,
-    const std::vector<std::string>& status_lines) {
-  std::u16string status_string;
-  if (!base::UTF8ToUTF16(status_lines.back().c_str(),
-                         status_lines.back().size(), &status_string)) {
-    LOG(ERROR) << "Failed to convert status line into a UTF16 string: "
-               << status_lines.back();
-  } else {
-    progress_label_->SetText(status_string);
-  }
-}
-
 void CrostiniAnsibleSoftwareConfigView::OnAnsibleSoftwareConfigurationFinished(
     const guest_os::GuestId& container_id,
     bool success) {
@@ -120,11 +106,6 @@
   return subtext_label_->GetText();
 }
 
-std::u16string
-CrostiniAnsibleSoftwareConfigView::GetProgressLabelStringForTesting() {
-  return progress_label_->GetText();
-}
-
 // static
 CrostiniAnsibleSoftwareConfigView*
 CrostiniAnsibleSoftwareConfigView::GetActiveViewForTesting() {
@@ -154,19 +135,13 @@
   subtext_label_ = AddChildView(std::move(subtext_label));
 
   // Add infinite progress bar.
+  // TODO(crbug.com/1000173): add progress reporting and display text above
+  // progress bar indicating current process.
   auto progress_bar = std::make_unique<views::ProgressBar>();
   // Values outside the range [0,1] display an infinite loading animation.
   progress_bar->SetValue(-1);
   progress_bar_ = AddChildView(std::move(progress_bar));
 
-  // Adds text below the infinite progress bar stating the last action.
-  // Currently can't really display the full progress since Ansible doesn't
-  // expose this by default w/o specific playbook hacks.
-  auto progress_label = std::make_unique<views::Label>();
-  progress_label->SetMultiLine(true);
-  progress_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  progress_label_ = AddChildView(std::move(progress_label));
-
   default_container_ansible_filepath_ = profile->GetPrefs()->GetFilePath(
       crostini::prefs::kCrostiniAnsiblePlaybookFilePath);
 
diff --git a/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.h b/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.h
index dcfa1ca..c91a776 100644
--- a/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.h
+++ b/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.h
@@ -35,15 +35,11 @@
   // crostini::AnsibleManagementService::Observer:
   void OnAnsibleSoftwareConfigurationStarted(
       const guest_os::GuestId& container_id) override;
-  void OnAnsibleSoftwareConfigurationProgress(
-      const guest_os::GuestId& container_id,
-      const std::vector<std::string>& status_lines) override;
   void OnAnsibleSoftwareConfigurationFinished(
       const guest_os::GuestId& container_id,
       bool success) override;
 
   std::u16string GetSubtextLabelStringForTesting();
-  std::u16string GetProgressLabelStringForTesting();
 
   static CrostiniAnsibleSoftwareConfigView* GetActiveViewForTesting();
 
@@ -65,7 +61,6 @@
   crostini::AnsibleManagementService* ansible_management_service_ = nullptr;
 
   views::Label* subtext_label_ = nullptr;
-  views::Label* progress_label_ = nullptr;
   views::ProgressBar* progress_bar_ = nullptr;
   base::FilePath default_container_ansible_filepath_;
 
diff --git a/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view_browsertest.cc
index ffc9c73..55da189f 100644
--- a/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view_browsertest.cc
+++ b/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view_browsertest.cc
@@ -4,10 +4,7 @@
 
 #include "chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.h"
 
-#include <string>
-
 #include "base/callback_helpers.h"
-#include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
 #include "chrome/browser/ash/crostini/ansible/ansible_management_service.h"
 #include "chrome/browser/ash/crostini/ansible/ansible_management_test_helper.h"
@@ -26,8 +23,6 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/chromeos/devicetype_utils.h"
 
-constexpr char kProgressString[] = "Yesh milord. More work?";
-
 class CrostiniAnsibleSoftwareConfigViewBrowserTest
     : public CrostiniDialogBrowserTest,
       public crostini::AnsibleManagementService::Observer {
@@ -53,27 +48,11 @@
   // crostini::AnsibleManagementService::Observer
   void OnAnsibleSoftwareConfigurationStarted(
       const guest_os::GuestId& container_id) override {}
-
-  void OnAnsibleSoftwareConfigurationProgress(
-      const guest_os::GuestId& container_id,
-      const std::vector<std::string>& status_lines) override {}
-
   void OnAnsibleSoftwareConfigurationFinished(
       const guest_os::GuestId& container_id,
       bool success) override {}
 
   void OnApplyAnsiblePlaybook(const guest_os::GuestId& container_id) override {
-    if (send_ansible_progress_) {
-      EXPECT_NE(nullptr, ActiveView());
-      vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal signal;
-      signal.set_status(
-          vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::IN_PROGRESS);
-      signal.set_vm_name(crostini::DefaultContainerId().vm_name);
-      signal.set_container_name(crostini::DefaultContainerId().container_name);
-      signal.add_status_string(kProgressString);
-      ansible_management_service()->OnApplyAnsiblePlaybookProgress(signal);
-      status_string_ = ActiveView()->GetProgressLabelStringForTesting();
-    }
     if (is_apply_ansible_success_) {
       EXPECT_NE(nullptr, ActiveView());
       vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal signal;
@@ -175,12 +154,7 @@
     is_install_ansible_success_ = success;
   }
 
-  void SetSendAnsibleProgress(bool show_progress) {
-    send_ansible_progress_ = show_progress;
-  }
-
   guest_os::GuestId container_id_;
-  std::u16string status_string_;
 
  private:
   bool HasAcceptButton() { return ActiveView()->GetOkButton() != nullptr; }
@@ -216,7 +190,6 @@
 
   bool is_install_ansible_success_;
   bool is_apply_ansible_success_;
-  bool send_ansible_progress_;
   std::unique_ptr<network::TestNetworkConnectionTracker>
       network_connection_tracker_;
   std::unique_ptr<crostini::AnsibleManagementTestHelper> test_helper_;
@@ -324,25 +297,6 @@
 }
 
 IN_PROC_BROWSER_TEST_F(CrostiniAnsibleSoftwareConfigViewBrowserTest,
-                       AnsibleConfigFlowWithProgress_Successful) {
-  SetSendAnsibleProgress(true);
-  ansible_management_service()->ConfigureContainer(
-      crostini::DefaultContainerId(),
-      browser()->profile()->GetPrefs()->GetFilePath(
-          crostini::prefs::kCrostiniAnsiblePlaybookFilePath),
-      base::BindLambdaForTesting([&](bool success) { run_loop()->Quit(); }));
-
-  run_loop()->Run();
-  std::u16string expected;
-  // -1 to anti the null at the end of the string.
-  ASSERT_TRUE(base::UTF8ToUTF16(kProgressString, sizeof(kProgressString) - 1,
-                                &expected));
-  EXPECT_EQ(status_string_, expected);
-
-  EXPECT_TRUE(HasNoView());
-}
-
-IN_PROC_BROWSER_TEST_F(CrostiniAnsibleSoftwareConfigViewBrowserTest,
                        AnsibleConfigFlow_InstallationFailed) {
   // Set install failure. No need to set apply because it should never reach
   // there.
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view_interactive_uitest.cc b/chrome/browser/ui/views/extensions/extensions_menu_view_interactive_uitest.cc
index efeda77..83e20bc5 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/extensions/extensions_menu_view_interactive_uitest.cc
@@ -560,11 +560,10 @@
       extensions_container->GetActionForId(extensions()[0]->id())
           ->GetContextMenu(extensions::ExtensionContextMenuModel::
                                ContextMenuSource::kToolbarAction));
-  absl::optional<size_t> visibility_index = context_menu->GetIndexOfCommandId(
+  int visibility_index = context_menu->GetIndexOfCommandId(
       extensions::ExtensionContextMenuModel::TOGGLE_VISIBILITY);
-  ASSERT_TRUE(visibility_index.has_value());
-  std::u16string visibility_label =
-      context_menu->GetLabelAt(visibility_index.value());
+  ASSERT_GE(visibility_index, 0);
+  std::u16string visibility_label = context_menu->GetLabelAt(visibility_index);
   EXPECT_EQ(visibility_label, u"Unpin");
 }
 
@@ -593,11 +592,10 @@
       extensions_container->GetActionForId(extensions()[0]->id())
           ->GetContextMenu(extensions::ExtensionContextMenuModel::
                                ContextMenuSource::kToolbarAction));
-  absl::optional<size_t> visibility_index = context_menu->GetIndexOfCommandId(
+  int visibility_index = context_menu->GetIndexOfCommandId(
       extensions::ExtensionContextMenuModel::TOGGLE_VISIBILITY);
-  ASSERT_TRUE(visibility_index.has_value());
-  std::u16string visibility_label =
-      context_menu->GetLabelAt(visibility_index.value());
+  ASSERT_GE(visibility_index, 0);
+  std::u16string visibility_label = context_menu->GetLabelAt(visibility_index);
   EXPECT_EQ(visibility_label, u"Pin");
 }
 
diff --git a/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view_interactive_uitest.cc b/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view_interactive_uitest.cc
index 075d39ca..da4f3ae 100644
--- a/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view_interactive_uitest.cc
@@ -329,11 +329,10 @@
       visible_actions[0]->view_controller()->GetContextMenu(
           extensions::ExtensionContextMenuModel::ContextMenuSource::
               kToolbarAction));
-  absl::optional<size_t> visibility_index = context_menu->GetIndexOfCommandId(
+  int visibility_index = context_menu->GetIndexOfCommandId(
       extensions::ExtensionContextMenuModel::TOGGLE_VISIBILITY);
-  ASSERT_TRUE(visibility_index.has_value());
-  std::u16string visibility_label =
-      context_menu->GetLabelAt(visibility_index.value());
+  ASSERT_GE(visibility_index, 0);
+  std::u16string visibility_label = context_menu->GetLabelAt(visibility_index);
   EXPECT_EQ(visibility_label, u"Unpin");
 
   // Trigger the pinned extension.
@@ -367,11 +366,10 @@
       visible_actions[0]->view_controller()->GetContextMenu(
           extensions::ExtensionContextMenuModel::ContextMenuSource::
               kToolbarAction));
-  absl::optional<size_t> visibility_index = context_menu->GetIndexOfCommandId(
+  int visibility_index = context_menu->GetIndexOfCommandId(
       extensions::ExtensionContextMenuModel::TOGGLE_VISIBILITY);
-  ASSERT_TRUE(visibility_index.has_value());
-  std::u16string visibility_label =
-      context_menu->GetLabelAt(visibility_index.value());
+  ASSERT_GE(visibility_index, 0);
+  std::u16string visibility_label = context_menu->GetLabelAt(visibility_index);
   EXPECT_EQ(visibility_label, u"Pin");
 }
 
diff --git a/chrome/browser/ui/views/frame/dbus_appmenu.cc b/chrome/browser/ui/views/frame/dbus_appmenu.cc
index 3f28222c..43a24111 100644
--- a/chrome/browser/ui/views/frame/dbus_appmenu.cc
+++ b/chrome/browser/ui/views/frame/dbus_appmenu.cc
@@ -160,8 +160,8 @@
 void FindMenuItemsForCommandAux(
     ui::MenuModel* menu,
     int command,
-    std::vector<std::pair<ui::MenuModel*, size_t>>* menu_items) {
-  for (size_t i = 0; i < menu->GetItemCount(); ++i) {
+    std::vector<std::pair<ui::MenuModel*, int>>* menu_items) {
+  for (int i = 0; i < menu->GetItemCount(); i++) {
     if (menu->GetCommandIdAt(i) == command)
       menu_items->push_back({menu, i});
     if (menu->GetTypeAt(i) == ui::SimpleMenuModel::ItemType::TYPE_SUBMENU) {
@@ -171,10 +171,10 @@
   }
 }
 
-std::vector<std::pair<ui::MenuModel*, size_t>> FindMenuItemsForCommand(
+std::vector<std::pair<ui::MenuModel*, int>> FindMenuItemsForCommand(
     ui::MenuModel* menu,
     int command) {
-  std::vector<std::pair<ui::MenuModel*, size_t>> menu_items;
+  std::vector<std::pair<ui::MenuModel*, int>> menu_items;
   FindMenuItemsForCommandAux(menu, command, &menu_items);
   return menu_items;
 }
@@ -297,7 +297,7 @@
     if (command_id == kSeparator) {
       // Use InsertSeparatorAt() instead of AddSeparator() because the latter
       // refuses to add a separator to an empty menu.
-      size_t old_item_count = menu->GetItemCount();
+      int old_item_count = menu->GetItemCount();
       menu->InsertSeparatorAt(old_item_count,
                               ui::MenuSeparatorType::SPACING_SEPARATOR);
 
diff --git a/chrome/browser/ui/views/frame/system_menu_model_builder_browsertest_chromeos.cc b/chrome/browser/ui/views/frame/system_menu_model_builder_browsertest_chromeos.cc
index b1a4e61..6678935c 100644
--- a/chrome/browser/ui/views/frame/system_menu_model_builder_browsertest_chromeos.cc
+++ b/chrome/browser/ui/views/frame/system_menu_model_builder_browsertest_chromeos.cc
@@ -70,7 +70,7 @@
       BrowserView::GetBrowserViewForBrowser(settings_browser);
   ui::MenuModel* menu = browser_view->frame()->GetSystemMenuModel();
   std::set<int> commands;
-  for (size_t i = 0; i < menu->GetItemCount(); ++i)
+  for (int i = 0; i < menu->GetItemCount(); i++)
     commands.insert(menu->GetCommandIdAt(i));
 
   // Standard WebUI commands are available.
diff --git a/chrome/browser/ui/views/global_media_controls/media_toolbar_button_contextual_menu_unittest.cc b/chrome/browser/ui/views/global_media_controls/media_toolbar_button_contextual_menu_unittest.cc
index 22932ec2c9..68d1d33 100644
--- a/chrome/browser/ui/views/global_media_controls/media_toolbar_button_contextual_menu_unittest.cc
+++ b/chrome/browser/ui/views/global_media_controls/media_toolbar_button_contextual_menu_unittest.cc
@@ -54,11 +54,11 @@
   auto menu = MediaToolbarButtonContextualMenu::Create(browser());
   auto model = menu->CreateMenuModel();
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-  EXPECT_EQ(model->GetItemCount(), 2u);
+  EXPECT_EQ(model->GetItemCount(), 2);
   EXPECT_EQ(model->GetCommandIdAt(1),
             IDC_MEDIA_TOOLBAR_CONTEXT_REPORT_CAST_ISSUE);
 #else
-  EXPECT_EQ(model->GetItemCount(), 1u);
+  EXPECT_EQ(model->GetItemCount(), 1);
 #endif
   EXPECT_EQ(model->GetCommandIdAt(0),
             IDC_MEDIA_TOOLBAR_CONTEXT_SHOW_OTHER_SESSIONS);
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc b/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc
index 9e698dd..ff71bb5d 100644
--- a/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc
+++ b/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc
@@ -232,7 +232,7 @@
   views::test::ButtonTestApi(sources_button()).NotifyClick(CreateMouseEvent());
   // The items should be "tab" (includes tab mirroring and presentation) and
   // "desktop".
-  EXPECT_EQ(2u, sources_menu_model()->GetItemCount());
+  EXPECT_EQ(2, sources_menu_model()->GetItemCount());
   EXPECT_EQ(CastDialogView::kTab, sources_menu_model()->GetCommandIdAt(0));
   EXPECT_EQ(CastDialogView::kDesktop, sources_menu_model()->GetCommandIdAt(1));
 
@@ -250,7 +250,7 @@
   // Press the button to show the sources menu.
   views::test::ButtonTestApi(sources_button()).NotifyClick(CreateMouseEvent());
   // There should be two sources: tab and desktop.
-  ASSERT_EQ(2u, sources_menu_model()->GetItemCount());
+  ASSERT_EQ(2, sources_menu_model()->GetItemCount());
 
   EXPECT_CALL(controller_, StartCasting(model.media_sinks()[0].id, TAB_MIRROR));
   sources_menu_model()->ActivatedAt(0);
diff --git a/chrome/browser/ui/views/media_router/media_router_ui_interactive_uitest.cc b/chrome/browser/ui/views/media_router/media_router_ui_interactive_uitest.cc
index 513c7992..4d4f0bd 100644
--- a/chrome/browser/ui/views/media_router/media_router_ui_interactive_uitest.cc
+++ b/chrome/browser/ui/views/media_router/media_router_ui_interactive_uitest.cc
@@ -199,10 +199,8 @@
   EXPECT_TRUE(ToolbarIconExists());
   // Pin the icon via its context menu.
   ui::SimpleMenuModel* context_menu = GetIconContextMenu();
-  const size_t command_index =
-      context_menu
-          ->GetIndexOfCommandId(IDC_MEDIA_ROUTER_ALWAYS_SHOW_TOOLBAR_ACTION)
-          .value();
+  const int command_index = context_menu->GetIndexOfCommandId(
+      IDC_MEDIA_ROUTER_ALWAYS_SHOW_TOOLBAR_ACTION);
   context_menu->ActivatedAt(command_index);
 
   views::test::WidgetDestroyedWaiter waiter(GetDialogWidget());
diff --git a/chrome/browser/ui/views/menu_model_adapter_test.cc b/chrome/browser/ui/views/menu_model_adapter_test.cc
index fe13376..51bae0b 100644
--- a/chrome/browser/ui/views/menu_model_adapter_test.cc
+++ b/chrome/browser/ui/views/menu_model_adapter_test.cc
@@ -50,36 +50,34 @@
   // ui::MenuModel implementation.
   bool HasIcons() const override { return false; }
 
-  bool IsItemDynamicAt(size_t index) const override { return false; }
+  bool IsItemDynamicAt(int index) const override { return false; }
 
-  bool GetAcceleratorAt(size_t index,
+  bool GetAcceleratorAt(int index,
                         ui::Accelerator* accelerator) const override {
     return false;
   }
 
-  ui::MenuSeparatorType GetSeparatorTypeAt(size_t index) const override {
+  ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override {
     return ui::NORMAL_SEPARATOR;
   }
 
   bool IsItemCheckedAt(size_t index) const override { return false; }
 
-  int GetGroupIdAt(size_t index) const override { return 0; }
+  int GetGroupIdAt(int index) const override { return 0; }
 
-  ui::ImageModel GetIconAt(size_t index) const override {
+  ui::ImageModel GetIconAt(int index) const override {
     return ui::ImageModel();
   }
 
-  ui::ButtonMenuItemModel* GetButtonMenuItemAt(size_t index) const override {
+  ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override {
     return nullptr;
   }
 
-  bool IsEnabledAt(size_t index) const override { return true; }
+  bool IsEnabledAt(int index) const override { return true; }
 
-  ui::MenuModel* GetSubmenuModelAt(size_t index) const override {
-    return nullptr;
-  }
+  ui::MenuModel* GetSubmenuModelAt(int index) const override { return nullptr; }
 
-  void ActivatedAt(size_t index) override {}
+  void ActivatedAt(int index) override {}
 };
 
 class SubMenuModel : public CommonMenuModel {
@@ -99,15 +97,15 @@
 
  private:
   // ui::MenuModel implementation.
-  size_t GetItemCount() const override { return 1; }
+  int GetItemCount() const override { return 1; }
 
-  ItemType GetTypeAt(size_t index) const override { return TYPE_COMMAND; }
+  ItemType GetTypeAt(int index) const override { return TYPE_COMMAND; }
 
-  int GetCommandIdAt(size_t index) const override {
-    return static_cast<int>(index) + kSubMenuBaseId;
+  int GetCommandIdAt(int index) const override {
+    return index + kSubMenuBaseId;
   }
 
-  std::u16string GetLabelAt(size_t index) const override { return u"Item"; }
+  std::u16string GetLabelAt(int index) const override { return u"Item"; }
 
   void MenuWillShow() override { showing_ = true; }
 
@@ -133,17 +131,17 @@
 
  private:
   // ui::MenuModel implementation.
-  size_t GetItemCount() const override { return 1; }
+  int GetItemCount() const override { return 1; }
 
-  ItemType GetTypeAt(size_t index) const override { return TYPE_SUBMENU; }
+  ItemType GetTypeAt(int index) const override { return TYPE_SUBMENU; }
 
-  int GetCommandIdAt(size_t index) const override {
-    return static_cast<int>(index) + kTopMenuBaseId;
+  int GetCommandIdAt(int index) const override {
+    return index + kTopMenuBaseId;
   }
 
-  std::u16string GetLabelAt(size_t index) const override { return u"submenu"; }
+  std::u16string GetLabelAt(int index) const override { return u"submenu"; }
 
-  MenuModel* GetSubmenuModelAt(size_t index) const override {
+  MenuModel* GetSubmenuModelAt(int index) const override {
     return &sub_menu_model_;
   }
 
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index 2ea13cc..05644a9 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -1809,11 +1809,10 @@
 void OmniboxViewViews::UpdateContextMenu(ui::SimpleMenuModel* menu_contents) {
   MaybeAddSendTabToSelfItem(menu_contents);
 
-  absl::optional<size_t> paste_position =
-      menu_contents->GetIndexOfCommandId(Textfield::kPaste);
-  DCHECK(paste_position.has_value());
-  menu_contents->InsertItemWithStringIdAt(paste_position.value() + 1,
-                                          IDC_PASTE_AND_GO, IDS_PASTE_AND_GO);
+  int paste_position = menu_contents->GetIndexOfCommandId(Textfield::kPaste);
+  DCHECK_GE(paste_position, 0);
+  menu_contents->InsertItemWithStringIdAt(paste_position + 1, IDC_PASTE_AND_GO,
+                                          IDS_PASTE_AND_GO);
 
   menu_contents->AddSeparator(ui::NORMAL_SEPARATOR);
 
@@ -1919,7 +1918,7 @@
     return;
   }
 
-  size_t index = menu_contents->GetIndexOfCommandId(Textfield::kUndo).value();
+  int index = menu_contents->GetIndexOfCommandId(Textfield::kUndo);
   // Add a separator if this is not the first item.
   if (index) {
     menu_contents->InsertSeparatorAt(index++, ui::NORMAL_SEPARATOR);
diff --git a/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc b/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc
index 71b72a6..9767f0d 100644
--- a/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc
+++ b/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc
@@ -203,14 +203,14 @@
       IDC_CONTENT_CONTEXT_SHARING_CLICK_TO_CALL_MULTIPLE_DEVICES));
 
   ui::MenuModel* sub_menu_model = nullptr;
-  size_t device_id = 0;
+  int device_id = -1;
   ASSERT_TRUE(menu->GetMenuModelAndItemIndex(kSubMenuFirstDeviceCommandId,
                                              &sub_menu_model, &device_id));
-  EXPECT_EQ(2u, sub_menu_model->GetItemCount());
-  EXPECT_EQ(0u, device_id);
+  EXPECT_EQ(2, sub_menu_model->GetItemCount());
+  EXPECT_EQ(0, device_id);
 
   for (auto& device : devices) {
-    EXPECT_EQ(kSubMenuFirstDeviceCommandId + static_cast<int>(device_id),
+    EXPECT_EQ(kSubMenuFirstDeviceCommandId + device_id,
               sub_menu_model->GetCommandIdAt(device_id));
     sub_menu_model->ActivatedAt(device_id);
 
@@ -236,14 +236,14 @@
       IDC_CONTENT_CONTEXT_SHARING_CLICK_TO_CALL_MULTIPLE_DEVICES));
 
   ui::MenuModel* sub_menu_model = nullptr;
-  size_t device_id = 0;
+  int device_id = -1;
   ASSERT_TRUE(menu->GetMenuModelAndItemIndex(kSubMenuFirstDeviceCommandId,
                                              &sub_menu_model, &device_id));
-  EXPECT_EQ(2u, sub_menu_model->GetItemCount());
-  EXPECT_EQ(0u, device_id);
+  EXPECT_EQ(2, sub_menu_model->GetItemCount());
+  EXPECT_EQ(0, device_id);
 
   for (auto& device : devices) {
-    EXPECT_EQ(kSubMenuFirstDeviceCommandId + static_cast<int>(device_id),
+    EXPECT_EQ(kSubMenuFirstDeviceCommandId + device_id,
               sub_menu_model->GetCommandIdAt(device_id));
     sub_menu_model->ActivatedAt(device_id);
 
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_font_combobox.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_font_combobox.cc
index c9d0c4fd..e644d71 100644
--- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_font_combobox.cc
+++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_font_combobox.cc
@@ -28,7 +28,7 @@
 
   // The Read Anything font combobox will use a different FontList for each
   // item in the menu. This will give a preview of the font to the user.
-  const gfx::FontList* GetLabelFontListAt(size_t index) const override {
+  const gfx::FontList* GetLabelFontListAt(int index) const override {
     return new gfx::FontList(static_cast<ReadAnythingFontModel*>(GetModel())
                                  ->GetLabelFontListAt(index));
   }
diff --git a/chrome/browser/ui/views/status_icons/concat_menu_model.cc b/chrome/browser/ui/views/status_icons/concat_menu_model.cc
index 510498a..e9bf6501 100644
--- a/chrome/browser/ui/views/status_icons/concat_menu_model.cc
+++ b/chrome/browser/ui/views/status_icons/concat_menu_model.cc
@@ -13,39 +13,39 @@
   return m1_->HasIcons() || m2_->HasIcons();
 }
 
-size_t ConcatMenuModel::GetItemCount() const {
+int ConcatMenuModel::GetItemCount() const {
   return m1_->GetItemCount() + m2_->GetItemCount();
 }
 
-ui::MenuModel::ItemType ConcatMenuModel::GetTypeAt(size_t index) const {
+ui::MenuModel::ItemType ConcatMenuModel::GetTypeAt(int index) const {
   return GetterImpl(&ui::MenuModel::GetTypeAt, index);
 }
 
-ui::MenuSeparatorType ConcatMenuModel::GetSeparatorTypeAt(size_t index) const {
+ui::MenuSeparatorType ConcatMenuModel::GetSeparatorTypeAt(int index) const {
   return GetterImpl(&ui::MenuModel::GetSeparatorTypeAt, index);
 }
 
-int ConcatMenuModel::GetCommandIdAt(size_t index) const {
+int ConcatMenuModel::GetCommandIdAt(int index) const {
   return GetterImpl(&ui::MenuModel::GetCommandIdAt, index);
 }
 
-std::u16string ConcatMenuModel::GetLabelAt(size_t index) const {
+std::u16string ConcatMenuModel::GetLabelAt(int index) const {
   return GetterImpl(&ui::MenuModel::GetLabelAt, index);
 }
 
-std::u16string ConcatMenuModel::GetMinorTextAt(size_t index) const {
+std::u16string ConcatMenuModel::GetMinorTextAt(int index) const {
   return GetterImpl(&ui::MenuModel::GetMinorTextAt, index);
 }
 
-ui::ImageModel ConcatMenuModel::GetMinorIconAt(size_t index) const {
+ui::ImageModel ConcatMenuModel::GetMinorIconAt(int index) const {
   return GetterImpl(&ui::MenuModel::GetMinorIconAt, index);
 }
 
-bool ConcatMenuModel::IsItemDynamicAt(size_t index) const {
+bool ConcatMenuModel::IsItemDynamicAt(int index) const {
   return GetterImpl(&ui::MenuModel::IsItemDynamicAt, index);
 }
 
-bool ConcatMenuModel::GetAcceleratorAt(size_t index,
+bool ConcatMenuModel::GetAcceleratorAt(int index,
                                        ui::Accelerator* accelerator) const {
   return GetterImpl(&ui::MenuModel::GetAcceleratorAt, index, accelerator);
 }
@@ -54,36 +54,35 @@
   return GetterImpl(&ui::MenuModel::IsItemCheckedAt, index);
 }
 
-int ConcatMenuModel::GetGroupIdAt(size_t index) const {
+int ConcatMenuModel::GetGroupIdAt(int index) const {
   return GetterImpl(&ui::MenuModel::GetGroupIdAt, index);
 }
 
-ui::ImageModel ConcatMenuModel::GetIconAt(size_t index) const {
+ui::ImageModel ConcatMenuModel::GetIconAt(int index) const {
   return GetterImpl(&ui::MenuModel::GetIconAt, index);
 }
 
-ui::ButtonMenuItemModel* ConcatMenuModel::GetButtonMenuItemAt(
-    size_t index) const {
+ui::ButtonMenuItemModel* ConcatMenuModel::GetButtonMenuItemAt(int index) const {
   return GetterImpl(&ui::MenuModel::GetButtonMenuItemAt, index);
 }
 
-bool ConcatMenuModel::IsEnabledAt(size_t index) const {
+bool ConcatMenuModel::IsEnabledAt(int index) const {
   return GetterImpl(&ui::MenuModel::IsEnabledAt, index);
 }
 
-bool ConcatMenuModel::IsVisibleAt(size_t index) const {
+bool ConcatMenuModel::IsVisibleAt(int index) const {
   return GetterImpl(&ui::MenuModel::IsVisibleAt, index);
 }
 
-void ConcatMenuModel::ActivatedAt(size_t index) {
+void ConcatMenuModel::ActivatedAt(int index) {
   GetMenuAndIndex(&index)->ActivatedAt(index);
 }
 
-void ConcatMenuModel::ActivatedAt(size_t index, int event_flags) {
+void ConcatMenuModel::ActivatedAt(int index, int event_flags) {
   GetMenuAndIndex(&index)->ActivatedAt(index, event_flags);
 }
 
-ui::MenuModel* ConcatMenuModel::GetSubmenuModelAt(size_t index) const {
+ui::MenuModel* ConcatMenuModel::GetSubmenuModelAt(int index) const {
   return GetterImpl(&ui::MenuModel::GetSubmenuModelAt, index);
 }
 
@@ -97,12 +96,12 @@
   m2_->MenuWillClose();
 }
 
-ui::MenuModel* ConcatMenuModel::GetMenuAndIndex(size_t* index) const {
-  size_t m1_count = m1_->GetItemCount();
+ui::MenuModel* ConcatMenuModel::GetMenuAndIndex(int* index) const {
+  int m1_count = m1_->GetItemCount();
   if (*index < m1_count)
     return m1_;
 
+  DCHECK_LT(*index - m1_count, m2_->GetItemCount());
   *index -= m1_count;
-  DCHECK_LT(*index, m2_->GetItemCount());
   return m2_;
 }
diff --git a/chrome/browser/ui/views/status_icons/concat_menu_model.h b/chrome/browser/ui/views/status_icons/concat_menu_model.h
index 047a8a8a..761cca4f 100644
--- a/chrome/browser/ui/views/status_icons/concat_menu_model.h
+++ b/chrome/browser/ui/views/status_icons/concat_menu_model.h
@@ -23,37 +23,36 @@
 
   // MenuModel:
   bool HasIcons() const override;
-  size_t GetItemCount() const override;
-  ItemType GetTypeAt(size_t index) const override;
-  ui::MenuSeparatorType GetSeparatorTypeAt(size_t index) const override;
-  int GetCommandIdAt(size_t index) const override;
-  std::u16string GetLabelAt(size_t index) const override;
-  std::u16string GetMinorTextAt(size_t index) const override;
-  ui::ImageModel GetMinorIconAt(size_t index) const override;
-  bool IsItemDynamicAt(size_t index) const override;
-  bool GetAcceleratorAt(size_t index,
-                        ui::Accelerator* accelerator) const override;
+  int GetItemCount() const override;
+  ItemType GetTypeAt(int index) const override;
+  ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override;
+  int GetCommandIdAt(int index) const override;
+  std::u16string GetLabelAt(int index) const override;
+  std::u16string GetMinorTextAt(int index) const override;
+  ui::ImageModel GetMinorIconAt(int index) const override;
+  bool IsItemDynamicAt(int index) const override;
+  bool GetAcceleratorAt(int index, ui::Accelerator* accelerator) const override;
   bool IsItemCheckedAt(size_t index) const override;
-  int GetGroupIdAt(size_t index) const override;
-  ui::ImageModel GetIconAt(size_t index) const override;
-  ui::ButtonMenuItemModel* GetButtonMenuItemAt(size_t index) const override;
-  bool IsEnabledAt(size_t index) const override;
-  bool IsVisibleAt(size_t index) const override;
-  void ActivatedAt(size_t index) override;
-  void ActivatedAt(size_t index, int event_flags) override;
-  MenuModel* GetSubmenuModelAt(size_t index) const override;
+  int GetGroupIdAt(int index) const override;
+  ui::ImageModel GetIconAt(int index) const override;
+  ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override;
+  bool IsEnabledAt(int index) const override;
+  bool IsVisibleAt(int index) const override;
+  void ActivatedAt(int index) override;
+  void ActivatedAt(int index, int event_flags) override;
+  MenuModel* GetSubmenuModelAt(int index) const override;
   void MenuWillShow() override;
   void MenuWillClose() override;
 
  private:
   template <typename F, typename... Ts>
-  auto GetterImpl(F&& f, size_t index, Ts&&... args) const {
+  auto GetterImpl(F&& f, int index, Ts&&... args) const {
     return (GetMenuAndIndex(&index)->*f)(index, args...);
   }
 
   // Returns either |m1_| or |m2_| for the input |index|.  |index| will be
   // adjusted for the returned menu.
-  ui::MenuModel* GetMenuAndIndex(size_t* index) const;
+  ui::MenuModel* GetMenuAndIndex(int* index) const;
 
   const raw_ptr<ui::MenuModel> m1_;
   const raw_ptr<ui::MenuModel> m2_;
diff --git a/chrome/browser/ui/views/toolbar/app_menu.cc b/chrome/browser/ui/views/toolbar/app_menu.cc
index 00f299c..1033888a 100644
--- a/chrome/browser/ui/views/toolbar/app_menu.cc
+++ b/chrome/browser/ui/views/toolbar/app_menu.cc
@@ -198,7 +198,7 @@
 };
 
 std::u16string GetAccessibleNameForAppMenuItem(ButtonMenuItemModel* model,
-                                               size_t item_index,
+                                               int item_index,
                                                int accessible_string_id,
                                                bool add_accelerator_text) {
   std::u16string accessible_name =
@@ -284,7 +284,7 @@
       views::Button::PressedCallback callback,
       int string_id,
       InMenuButtonBackground::ButtonType type,
-      size_t index) {
+      int index) {
     return CreateButtonWithAccessibleName(
         std::move(callback), string_id, type, index, string_id,
         /*add_accelerator_text=*/true,
@@ -295,7 +295,7 @@
       views::Button::PressedCallback callback,
       int string_id,
       InMenuButtonBackground::ButtonType type,
-      size_t index,
+      int index,
       int accessible_name_id,
       bool add_accelerator_text,
       bool use_accessible_name_as_tooltip_text) {
@@ -342,7 +342,7 @@
   METADATA_HEADER(FullscreenButton);
   explicit FullscreenButton(PressedCallback callback,
                             ButtonMenuItemModel* menu_model,
-                            size_t fullscreen_index,
+                            int fullscreen_index,
                             bool is_in_fullscreen)
       : ImageButton(std::move(callback)) {
     // Since |fullscreen_button_| will reside in a menu, make it ALWAYS
@@ -400,12 +400,12 @@
   METADATA_HEADER(CutCopyPasteView);
   CutCopyPasteView(AppMenu* menu,
                    ButtonMenuItemModel* menu_model,
-                   size_t cut_index,
-                   size_t copy_index,
-                   size_t paste_index)
+                   int cut_index,
+                   int copy_index,
+                   int paste_index)
       : AppMenuView(menu, menu_model) {
     const auto cancel_and_evaluate =
-        [](AppMenu* menu, ButtonMenuItemModel* menu_model, size_t index) {
+        [](AppMenu* menu, ButtonMenuItemModel* menu_model, int index) {
           menu->CancelAndEvaluate(menu_model, index);
         };
     CreateAndConfigureButton(
@@ -467,9 +467,9 @@
   METADATA_HEADER(ZoomView);
   ZoomView(AppMenu* menu,
            ButtonMenuItemModel* menu_model,
-           size_t decrement_index,
-           size_t increment_index,
-           size_t fullscreen_index)
+           int decrement_index,
+           int increment_index,
+           int fullscreen_index)
       : AppMenuView(menu, menu_model),
         increment_button_(nullptr),
         zoom_label_(nullptr),
@@ -483,7 +483,7 @@
                 base::BindRepeating(&AppMenu::ZoomView::OnZoomLevelChanged,
                                     base::Unretained(this)));
 
-    const auto activate = [](ButtonMenuItemModel* menu_model, size_t index) {
+    const auto activate = [](ButtonMenuItemModel* menu_model, int index) {
       menu_model->ActivatedAt(index);
     };
     decrement_button_ = CreateButtonWithAccessibleName(
@@ -518,7 +518,7 @@
 
     fullscreen_button_ = new FullscreenButton(
         base::BindRepeating(
-            [](AppMenu* menu, ButtonMenuItemModel* menu_model, size_t index) {
+            [](AppMenu* menu, ButtonMenuItemModel* menu_model, int index) {
               menu->CancelAndEvaluate(menu_model, index);
             },
             menu, menu_model, fullscreen_index),
@@ -713,8 +713,9 @@
 
   const gfx::FontList* GetLabelFontListForCommandId(int command_id) const {
     ui::MenuModel* model = model_;
-    size_t index = 0;
+    int index = -1;
     AppMenuModel::GetModelAndIndexForCommandId(command_id, &model, &index);
+    DCHECK_GT(index, -1);
     return model->GetLabelFontListAt(index);
   }
 
@@ -722,7 +723,7 @@
 
   void OnIconChanged(int command_id) override {
     ui::MenuModel* model = model_;
-    size_t index;
+    int index;
     model_->GetModelAndIndexForCommandId(command_id, &model, &index);
     views::MenuItemView* item = menu_item_->GetMenuItemByID(command_id);
     DCHECK(item);
@@ -767,8 +768,8 @@
   void BuildMenu(MenuItemView* menu, ui::MenuModel* model) {
     DCHECK(menu);
     DCHECK(model);
-    const size_t item_count = model->GetItemCount();
-    for (size_t i = 0; i < item_count; ++i) {
+    const int item_count = model->GetItemCount();
+    for (int i = 0; i < item_count; ++i) {
       MenuItemView* const item =
           app_menu_->AddMenuItem(menu, i, model, i, model->GetTypeAt(i));
       if (model->GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU ||
@@ -784,8 +785,8 @@
   // Populates out_set with all command ids referenced by the model, including
   // those referenced by sub menu models.
   void GetDescendantCommandIds(MenuModel* model, base::flat_set<int>* out_set) {
-    const size_t item_count = model->GetItemCount();
-    for (size_t i = 0; i < item_count; ++i) {
+    const int item_count = model->GetItemCount();
+    for (int i = 0; i < item_count; i++) {
       out_set->insert(model->GetCommandIdAt(i));
       if (model->GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU ||
           model->GetTypeAt(i) == ui::MenuModel::TYPE_ACTIONABLE_SUBMENU) {
@@ -1100,11 +1101,12 @@
 }
 
 void AppMenu::PopulateMenu(MenuItemView* parent, MenuModel* model) {
-  for (size_t i = 0, max = model->GetItemCount(); i < max; ++i) {
+  for (int i = 0, max = model->GetItemCount(); i < max; ++i) {
     // Add the menu item at the end.
-    size_t menu_index = parent->HasSubmenu()
-                            ? parent->GetSubmenu()->children().size()
-                            : size_t{0};
+    int menu_index =
+        parent->HasSubmenu()
+            ? static_cast<int>(parent->GetSubmenu()->children().size())
+            : 0;
     MenuItemView* item =
         AddMenuItem(parent, menu_index, model, i, model->GetTypeAt(i));
 
@@ -1179,9 +1181,9 @@
 }
 
 MenuItemView* AppMenu::AddMenuItem(MenuItemView* parent,
-                                   size_t menu_index,
+                                   int menu_index,
                                    MenuModel* model,
-                                   size_t model_index,
+                                   int model_index,
                                    MenuModel::ItemType menu_type) {
   int command_id = model->GetCommandIdAt(model_index);
   DCHECK(command_id > -1 ||
@@ -1224,7 +1226,7 @@
   return menu_item;
 }
 
-void AppMenu::CancelAndEvaluate(ButtonMenuItemModel* model, size_t index) {
+void AppMenu::CancelAndEvaluate(ButtonMenuItemModel* model, int index) {
   selected_menu_model_ = model;
   selected_index_ = index;
   root_->Cancel();
@@ -1256,7 +1258,7 @@
                                 BOOKMARK_LAUNCH_LOCATION_APP_MENU);
 }
 
-size_t AppMenu::ModelIndexFromCommandId(int command_id) const {
+int AppMenu::ModelIndexFromCommandId(int command_id) const {
   auto ix = command_id_to_entry_.find(command_id);
   DCHECK(ix != command_id_to_entry_.end());
   return ix->second.second;
diff --git a/chrome/browser/ui/views/toolbar/app_menu.h b/chrome/browser/ui/views/toolbar/app_menu.h
index 2b89f8fc..f0c067a 100644
--- a/chrome/browser/ui/views/toolbar/app_menu.h
+++ b/chrome/browser/ui/views/toolbar/app_menu.h
@@ -108,7 +108,7 @@
   class RecentTabsMenuModelDelegate;
   class ZoomView;
 
-  typedef std::pair<ui::MenuModel*, size_t> Entry;
+  typedef std::pair<ui::MenuModel*,int> Entry;
   typedef std::map<int,Entry> CommandIDToEntry;
 
   // Populates |parent| with all the child menus in |model|. Recursively invokes
@@ -124,14 +124,14 @@
   // The returned item's MenuItemView::GetCommand() is the same as that of
   // |model|->GetCommandIdAt(|model_index|).
   views::MenuItemView* AddMenuItem(views::MenuItemView* parent,
-                                   size_t menu_index,
+                                   int menu_index,
                                    ui::MenuModel* model,
-                                   size_t model_index,
+                                   int model_index,
                                    ui::MenuModel::ItemType menu_type);
 
   // Invoked from the cut/copy/paste menus. Cancels the current active menu and
   // activates the menu item in |model| at |index|.
-  void CancelAndEvaluate(ui::ButtonMenuItemModel* model, size_t index);
+  void CancelAndEvaluate(ui::ButtonMenuItemModel* model, int index);
 
   // Creates the bookmark menu if necessary. Does nothing if already created or
   // the bookmark model isn't loaded.
@@ -139,7 +139,7 @@
 
   // Returns the index of the MenuModel/index pair representing the |command_id|
   // in |command_id_to_entry_|.
-  size_t ModelIndexFromCommandId(int command_id) const;
+  int ModelIndexFromCommandId(int command_id) const;
 
   // The views menu. Owned by |menu_runner_|.
   raw_ptr<views::MenuItemView> root_ = nullptr;
@@ -158,7 +158,7 @@
   // ActivatedAt is invoked. This is done so that ActivatedAt isn't invoked
   // while the message loop is nested.
   raw_ptr<ui::ButtonMenuItemModel> selected_menu_model_ = nullptr;
-  size_t selected_index_ = 0;
+  int selected_index_ = 0;
 
   // Used for managing the bookmark menu items.
   std::unique_ptr<BookmarkMenuDelegate> bookmark_menu_delegate_;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button_unittest.cc b/chrome/browser/ui/views/toolbar/toolbar_button_unittest.cc
index bf715fef..c716875 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button_unittest.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_button_unittest.cc
@@ -67,7 +67,7 @@
   ~CheckActiveWebContentsMenuModel() override = default;
 
   // ui::SimpleMenuModel:
-  size_t GetItemCount() const override {
+  int GetItemCount() const override {
     EXPECT_TRUE(tab_strip_model_->GetActiveWebContents());
     return 0;
   }
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc b/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc
index 6dd988e..6ef2392 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc
+++ b/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc
@@ -259,10 +259,8 @@
   EXPECT_FALSE(denial_button_clicked());
   TriggerOptionsMenu();
 
-  const size_t index =
-      bubble_->options_menu_model_
-          ->GetIndexOfCommandId(TranslateBubbleView::NEVER_TRANSLATE_LANGUAGE)
-          .value();
+  const int index = bubble_->options_menu_model_->GetIndexOfCommandId(
+      TranslateBubbleView::NEVER_TRANSLATE_LANGUAGE);
   bubble_->options_menu_model_->ActivatedAt(index);
 
   EXPECT_TRUE(denial_button_clicked());
@@ -285,10 +283,8 @@
   EXPECT_FALSE(bubble_->GetWidget()->IsClosed());
 
   TriggerOptionsMenu();
-  const size_t index =
-      bubble_->options_menu_model_
-          ->GetIndexOfCommandId(TranslateBubbleView::NEVER_TRANSLATE_SITE)
-          .value();
+  const int index = bubble_->options_menu_model_->GetIndexOfCommandId(
+      TranslateBubbleView::NEVER_TRANSLATE_SITE);
   bubble_->options_menu_model_->ActivatedAt(index);
 
   EXPECT_TRUE(denial_button_clicked());
@@ -320,7 +316,8 @@
   EXPECT_TRUE(mock_model_->translate_called_);
   EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_TRANSLATING,
             bubble_->GetViewState());
-  EXPECT_EQ(bubble_->tabbed_pane_->GetSelectedTabIndex(), size_t{1});
+  EXPECT_EQ(bubble_->tabbed_pane_->GetSelectedTabIndex(),
+            static_cast<size_t>(1));
   histogram_tester.ExpectBucketCount(
       translate::kTranslateBubbleUiEventHistogramName,
       translate::TranslateBubbleUiEvent::ALWAYS_TRANSLATE_CHECKED, 1);
@@ -509,15 +506,12 @@
 
   TriggerOptionsMenu();
   // NEVER_TRANSLATE_SITE shouldn't show up for sites that can't be blocklisted.
-  EXPECT_FALSE(
-      bubble_->options_menu_model_
-          ->GetIndexOfCommandId(TranslateBubbleView::NEVER_TRANSLATE_SITE)
-          .has_value());
+  EXPECT_EQ(-1, bubble_->options_menu_model_->GetIndexOfCommandId(
+                    TranslateBubbleView::NEVER_TRANSLATE_SITE));
   // Verify that the menu is populated so previous check makes sense.
-  EXPECT_TRUE(
-      bubble_->options_menu_model_
-          ->GetIndexOfCommandId(TranslateBubbleView::NEVER_TRANSLATE_LANGUAGE)
-          .has_value());
+  EXPECT_GE(bubble_->options_menu_model_->GetIndexOfCommandId(
+                TranslateBubbleView::NEVER_TRANSLATE_LANGUAGE),
+            0);
 }
 
 TEST_F(TranslateBubbleViewTest, MenuOptionsHiddenOnUnknownSource) {
@@ -528,29 +522,22 @@
   TriggerOptionsMenu();
   // NEVER_TRANSLATE_LANGUAGE and ALWAYS_TRANSLATE_LANGUAGE shouldn't show when
   // the source language is "Unknown".
-  EXPECT_FALSE(
-      bubble_->options_menu_model_
-          ->GetIndexOfCommandId(TranslateBubbleView::NEVER_TRANSLATE_LANGUAGE)
-          .has_value());
-  EXPECT_FALSE(
-      bubble_->options_menu_model_
-          ->GetIndexOfCommandId(TranslateBubbleView::ALWAYS_TRANSLATE_LANGUAGE)
-          .has_value());
+  EXPECT_EQ(-1, bubble_->options_menu_model_->GetIndexOfCommandId(
+                    TranslateBubbleView::NEVER_TRANSLATE_LANGUAGE));
+  EXPECT_EQ(-1, bubble_->options_menu_model_->GetIndexOfCommandId(
+                    TranslateBubbleView::ALWAYS_TRANSLATE_LANGUAGE));
   // Verify that the menu is populated so previous checks make sense.
-  EXPECT_TRUE(
-      bubble_->options_menu_model_
-          ->GetIndexOfCommandId(TranslateBubbleView::CHANGE_TARGET_LANGUAGE)
-          .has_value());
+  EXPECT_GE(bubble_->options_menu_model_->GetIndexOfCommandId(
+                TranslateBubbleView::CHANGE_TARGET_LANGUAGE),
+            0);
 }
 
 TEST_F(TranslateBubbleViewTest, AlwaysTranslateLanguageMenuItem) {
   CreateAndShowBubble();
 
   TriggerOptionsMenu();
-  const size_t index =
-      bubble_->options_menu_model_
-          ->GetIndexOfCommandId(TranslateBubbleView::ALWAYS_TRANSLATE_LANGUAGE)
-          .value();
+  const int index = bubble_->options_menu_model_->GetIndexOfCommandId(
+      TranslateBubbleView::ALWAYS_TRANSLATE_LANGUAGE);
 
   EXPECT_FALSE(mock_model_->ShouldAlwaysTranslate());
   EXPECT_FALSE(bubble_->options_menu_model_->IsItemCheckedAt(index));
@@ -595,10 +582,8 @@
   CreateAndShowBubble();
 
   TriggerOptionsMenu();
-  const size_t index =
-      bubble_->options_menu_model_
-          ->GetIndexOfCommandId(TranslateBubbleView::ALWAYS_TRANSLATE_LANGUAGE)
-          .value();
+  const int index = bubble_->options_menu_model_->GetIndexOfCommandId(
+      TranslateBubbleView::ALWAYS_TRANSLATE_LANGUAGE);
 
   EXPECT_FALSE(mock_model_->ShouldAlwaysTranslate());
   EXPECT_FALSE(bubble_->options_menu_model_->IsItemCheckedAt(index));
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc
index 7e217ff..0a9cd97 100644
--- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc
@@ -120,10 +120,12 @@
         /*provider=*/nullptr, helper()->app_browser());
     app_menu_model->Init();
     ui::MenuModel* model = app_menu_model.get();
-    size_t index = 0;
-    return app_menu_model->GetModelAndIndexForCommandId(command_id, &model,
-                                                        &index) &&
-           model->IsEnabledAt(index);
+    int index = -1;
+    if (!app_menu_model->GetModelAndIndexForCommandId(command_id, &model,
+                                                      &index)) {
+      return false;
+    }
+    return model->IsEnabledAt(index);
   }
 
  private:
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
index ec6280d..ee1a04cf 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -1423,7 +1423,7 @@
       std::make_unique<WebAppMenuModel>(/*provider=*/nullptr, app_browser);
   app_menu_model->Init();
   ui::MenuModel* model = app_menu_model.get();
-  size_t index = 0;
+  int index = -1;
   const bool found = app_menu_model->GetModelAndIndexForCommandId(
       WebAppMenuModel::kUninstallAppCommandId, &model, &index);
   EXPECT_TRUE(found);
diff --git a/chrome/browser/ui/views/webauthn/authenticator_request_dialog_view.cc b/chrome/browser/ui/views/webauthn/authenticator_request_dialog_view.cc
index add15cd0..b497c23f 100644
--- a/chrome/browser/ui/views/webauthn/authenticator_request_dialog_view.cc
+++ b/chrome/browser/ui/views/webauthn/authenticator_request_dialog_view.cc
@@ -320,7 +320,7 @@
   auto* other_mechanisms_menu_model =
       sheet_->model()->GetOtherMechanismsMenuModel();
   DCHECK(other_mechanisms_menu_model);
-  DCHECK_GE(other_mechanisms_menu_model->GetItemCount(), 1u);
+  DCHECK_GE(other_mechanisms_menu_model->GetItemCount(), 1);
 
   other_mechanisms_menu_runner_ = std::make_unique<views::MenuRunner>(
       other_mechanisms_menu_model, views::MenuRunner::COMBOBOX);
diff --git a/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc b/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
index b100f2e..0b9e0ddb2 100644
--- a/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
+++ b/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
@@ -1096,7 +1096,7 @@
     ASSERT_TRUE(menu);
     ui::MenuModel* model = menu.get();
 
-    size_t command_index;
+    int command_index;
     ui::MenuModel::GetModelAndIndexForCommandId(command_id, &model,
                                                 &command_index);
     EXPECT_TRUE(menu->IsEnabledAt(command_index));
diff --git a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc
index fcb23cba..c06f40a 100644
--- a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc
+++ b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc
@@ -321,7 +321,7 @@
   auto app_menu_model = std::make_unique<AppMenuModel>(nullptr, browser);
   app_menu_model->Init();
   ui::MenuModel* model = app_menu_model.get();
-  size_t index = 0;
+  int index = -1;
   if (!app_menu_model->GetModelAndIndexForCommandId(command_id, &model,
                                                     &index)) {
     return kNotPresent;
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc
index 4a038ac..4f29db14 100644
--- a/chrome/browser/ui/web_applications/web_app_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -934,7 +934,7 @@
       std::make_unique<AppMenuModel>(nullptr, incognito_browser);
   app_menu_model->Init();
   ui::MenuModel* model = app_menu_model.get();
-  size_t index = 0;
+  int index = -1;
   ASSERT_TRUE(app_menu_model->GetModelAndIndexForCommandId(
       IDC_OPEN_IN_PWA_WINDOW, &model, &index));
   EXPECT_FALSE(model->IsEnabledAt(index));
@@ -968,7 +968,7 @@
       /*provider=*/nullptr, app_browser);
   app_menu_model->Init();
   ui::MenuModel* model = app_menu_model.get();
-  size_t index = 0;
+  int index = -1;
   const bool found = app_menu_model->GetModelAndIndexForCommandId(
       WebAppMenuModel::kUninstallAppCommandId, &model, &index);
 #if BUILDFLAG(IS_CHROMEOS)
@@ -1494,7 +1494,7 @@
   auto app_menu_model = std::make_unique<AppMenuModel>(nullptr, browser());
   app_menu_model->Init();
   ui::MenuModel* model = app_menu_model.get();
-  size_t index = 0;
+  int index = -1;
   EXPECT_TRUE(app_menu_model->GetModelAndIndexForCommandId(IDC_INSTALL_PWA,
                                                            &model, &index));
   EXPECT_EQ(app_menu_model.get(), model);
diff --git a/chrome/browser/ui/web_applications/web_app_menu_model.cc b/chrome/browser/ui/web_applications/web_app_menu_model.cc
index f3fd09c..5b7b9ea 100644
--- a/chrome/browser/ui/web_applications/web_app_menu_model.cc
+++ b/chrome/browser/ui/web_applications/web_app_menu_model.cc
@@ -96,7 +96,7 @@
 void WebAppMenuModel::Build() {
   AddItemWithStringId(IDC_WEB_APP_MENU_APP_INFO,
                       IDS_APP_CONTEXT_MENU_SHOW_INFO);
-  size_t app_info_index = GetItemCount() - 1;
+  int app_info_index = GetItemCount() - 1;
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
   if (web_contents) {
diff --git a/chrome/browser/ui/webui/chromeos/login/multidevice_setup_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/multidevice_setup_screen_handler.cc
index a76a3a6..f0360da 100644
--- a/chrome/browser/ui/webui/chromeos/login/multidevice_setup_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/multidevice_setup_screen_handler.cc
@@ -13,13 +13,8 @@
 
 namespace chromeos {
 
-constexpr StaticOobeScreenId MultiDeviceSetupScreenView::kScreenId;
-
 MultiDeviceSetupScreenHandler::MultiDeviceSetupScreenHandler()
-    : BaseScreenHandler(kScreenId) {
-  set_user_acted_method_path_deprecated(
-      "login.MultiDeviceSetupScreen.userActed");
-}
+    : BaseScreenHandler(kScreenId) {}
 
 MultiDeviceSetupScreenHandler::~MultiDeviceSetupScreenHandler() = default;
 
@@ -28,10 +23,6 @@
   multidevice_setup::AddLocalizedValuesToBuilder(builder);
 }
 
-void MultiDeviceSetupScreenHandler::Bind(MultiDeviceSetupScreen* screen) {
-  BaseScreenHandler::SetBaseScreenDeprecated(screen);
-}
-
 void MultiDeviceSetupScreenHandler::Show() {
   ShowInWebUI();
   FireWebUIListenerWhenAllowed("multidevice_setup.initializeSetupFlow");
@@ -43,8 +34,4 @@
             base::Value(ash::features::IsWifiSyncAndroidEnabled()));
 }
 
-void MultiDeviceSetupScreenHandler::Hide() {}
-
-void MultiDeviceSetupScreenHandler::InitializeDeprecated() {}
-
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/multidevice_setup_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/multidevice_setup_screen_handler.h
index 6b5d717..ecada60 100644
--- a/chrome/browser/ui/webui/chromeos/login/multidevice_setup_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/multidevice_setup_screen_handler.h
@@ -5,26 +5,23 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_MULTIDEVICE_SETUP_SCREEN_HANDLER_H_
 #define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_MULTIDEVICE_SETUP_SCREEN_HANDLER_H_
 
+#include "base/memory/weak_ptr.h"
 #include "base/values.h"
 #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
 
-namespace ash {
-class MultiDeviceSetupScreen;
-}
-
 namespace chromeos {
 
 // Interface for dependency injection between MultiDeviceSetupScreen and its
 // WebUI representation.
-class MultiDeviceSetupScreenView {
+class MultiDeviceSetupScreenView
+    : public base::SupportsWeakPtr<MultiDeviceSetupScreenView> {
  public:
-  constexpr static StaticOobeScreenId kScreenId{"multidevice-setup-screen"};
+  inline constexpr static StaticOobeScreenId kScreenId{
+      "multidevice-setup-screen", "MultiDeviceSetupScreen"};
 
   virtual ~MultiDeviceSetupScreenView() = default;
 
-  virtual void Bind(ash::MultiDeviceSetupScreen* screen) = 0;
   virtual void Show() = 0;
-  virtual void Hide() = 0;
 };
 
 // Concrete MultiDeviceSetupScreenView WebUI-based implementation.
@@ -47,13 +44,7 @@
   void GetAdditionalParameters(base::Value::Dict* dict) override;
 
   // MultiDeviceSetupScreenView:
-  void Bind(ash::MultiDeviceSetupScreen* screen) override;
   void Show() override;
-  void Hide() override;
-
- private:
-  // BaseScreenHandler:
-  void InitializeDeprecated() override;
 };
 
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/history/history_login_handler.cc b/chrome/browser/ui/webui/history/history_login_handler.cc
index 6cebd1c..db05954 100644
--- a/chrome/browser/ui/webui/history/history_login_handler.cc
+++ b/chrome/browser/ui/webui/history/history_login_handler.cc
@@ -31,8 +31,8 @@
                           base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
-      "startSignInFlow",
-      base::BindRepeating(&HistoryLoginHandler::HandleStartSignInFlow,
+      "startTurnOnSyncFlow",
+      base::BindRepeating(&HistoryLoginHandler::HandleTurnOnSyncFlow,
                           base::Unretained(this)));
 }
 
@@ -61,7 +61,7 @@
   FireWebUIListener("sign-in-state-changed", base::Value(signed_in));
 }
 
-void HistoryLoginHandler::HandleStartSignInFlow(
+void HistoryLoginHandler::HandleTurnOnSyncFlow(
     const base::Value::List& /*args*/) {
   Profile* profile = Profile::FromWebUI(web_ui());
   signin_ui_util::EnableSyncFromSingleAccountPromo(
diff --git a/chrome/browser/ui/webui/history/history_login_handler.h b/chrome/browser/ui/webui/history/history_login_handler.h
index 2c064f92..ec1f2458 100644
--- a/chrome/browser/ui/webui/history/history_login_handler.h
+++ b/chrome/browser/ui/webui/history/history_login_handler.h
@@ -31,8 +31,8 @@
   // Handler for the "otherDevicesInitialized" message. No args.
   void HandleOtherDevicesInitialized(const base::Value::List& args);
 
-  // Handler for the "startSignInFlow" message. No args.
-  void HandleStartSignInFlow(const base::Value::List& args);
+  // Handler for the "startTurnOnSyncFlow" message. No args.
+  void HandleTurnOnSyncFlow(const base::Value::List& args);
 
   // Called by |profile_info_watcher_| on desktop if profile info changes.
   void ProfileInfoChanged();
diff --git a/chrome/browser/ui/webui/history/history_ui.cc b/chrome/browser/ui/webui/history/history_ui.cc
index f035df1..8f17a4a 100644
--- a/chrome/browser/ui/webui/history/history_ui.cc
+++ b/chrome/browser/ui/webui/history/history_ui.cc
@@ -99,9 +99,9 @@
       {"searchPrompt", IDS_HISTORY_SEARCH_PROMPT},
       {"searchResult", IDS_HISTORY_SEARCH_RESULT},
       {"searchResults", IDS_HISTORY_SEARCH_RESULTS},
-      {"signInButton", IDS_HISTORY_SIGN_IN_BUTTON},
-      {"signInPromo", IDS_HISTORY_SIGN_IN_PROMO},
-      {"signInPromoDesc", IDS_HISTORY_SIGN_IN_PROMO_DESC},
+      {"turnOnSyncButton", IDS_HISTORY_TURN_ON_SYNC_BUTTON},
+      {"turnOnSyncPromo", IDS_HISTORY_TURN_ON_SYNC_PROMO},
+      {"turnOnSyncPromoDesc", IDS_HISTORY_TURN_ON_SYNC_PROMO_DESC},
       {"title", IDS_HISTORY_TITLE},
   };
   source->AddLocalizedStrings(kStrings);
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index cef07af..94edebc6 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -932,10 +932,6 @@
        IDS_SETTINGS_REMOVE_COMPROMISED_PASSWORD_CONFIRMATION_TITLE},
       {"removeCompromisedPasswordConfirmationDescription",
        IDS_SETTINGS_REMOVE_COMPROMISED_PASSWORD_CONFIRMATION_DESCRIPTION},
-      {"editCompromisedPasswordSite",
-       IDS_SETTINGS_COMPROMISED_EDIT_PASSWORD_SITE},
-      {"editCompromisedPasswordApp",
-       IDS_SETTINGS_COMPROMISED_EDIT_PASSWORD_APP},
       {"alreadyChangedPasswordLink",
        IDS_SETTINGS_COMPROMISED_ALREADY_CHANGED_PASSWORD},
       {"editDisclaimerTitle", IDS_SETTINGS_COMPROMISED_EDIT_DISCLAIMER_TITLE},
@@ -1043,6 +1039,7 @@
       {"passwordStoredInAccountAndOnDevice",
        IDS_SETTINGS_PASSWORD_STORED_IN_ACCOUNT_AND_ON_DEVICE},
       {"editPasswordWebsiteLabel", IDS_SETTINGS_PASSWORDS_WEBSITE},
+      {"editPasswordAppLabel", IDS_SETTINGS_COMPROMISED_EDIT_PASSWORD_APP},
       {"editPasswordUsernameLabel", IDS_SETTINGS_PASSWORDS_USERNAME},
       {"editPasswordPasswordLabel", IDS_SETTINGS_PASSWORDS_PASSWORD},
       {"passwordNoteLabel", IDS_SETTINGS_PASSWORDS_NOTE},
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc
index 7a573c9..91c9fda 100644
--- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc
+++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc
@@ -98,11 +98,10 @@
 
  private:
   void AddItem(int command_id) {
-    ui::SimpleMenuModel::AddItem(command_id,
-                                 controller_->menu_model()->GetLabelAt(
-                                     controller_->menu_model()
-                                         ->GetIndexOfCommandId(command_id)
-                                         .value()));
+    ui::SimpleMenuModel::AddItem(
+        command_id,
+        controller_->menu_model()->GetLabelAt(
+            controller_->menu_model()->GetIndexOfCommandId(command_id)));
   }
   base::WeakPtr<ui::MojoBubbleWebUIController::Embedder> embedder_;
   std::unique_ptr<BookmarkContextMenuController> controller_;
diff --git a/chrome/browser/web_applications/app_service/web_apps_chromeos_browsertest.cc b/chrome/browser/web_applications/app_service/web_apps_chromeos_browsertest.cc
index b295abc..7fa9ace2 100644
--- a/chrome/browser/web_applications/app_service/web_apps_chromeos_browsertest.cc
+++ b/chrome/browser/web_applications/app_service/web_apps_chromeos_browsertest.cc
@@ -33,7 +33,7 @@
 namespace {
 
 void CheckShortcut(const ui::SimpleMenuModel& model,
-                   size_t index,
+                   int index,
                    int shortcut_index,
                    const std::u16string& label,
                    absl::optional<SkColor> color) {
@@ -51,7 +51,7 @@
   }
 }
 
-void CheckSeparator(const ui::SimpleMenuModel& model, size_t index) {
+void CheckSeparator(const ui::SimpleMenuModel& model, int index) {
   EXPECT_EQ(model.GetTypeAt(index), ui::MenuModel::TYPE_SEPARATOR);
   EXPECT_EQ(model.GetCommandIdAt(index), -1);
 }
@@ -91,7 +91,7 @@
 
   // Shortcuts appear last in the context menu.
   // See /web_app_shortcuts/shortcuts.json for shortcut icon definitions.
-  size_t index = menu_model->GetItemCount() - 11;
+  int index = menu_model->GetItemCount() - 11;
 
   // Purpose |any| by default.
   CheckShortcut(*menu_model, index++, 0, u"One", SK_ColorGREEN);
@@ -116,7 +116,7 @@
   ui_test_utils::UrlLoadObserver url_observer(
       https_server()->GetURL("/web_app_shortcuts/shortcuts.html#four"),
       content::NotificationService::AllSources());
-  menu_model->ActivatedAt(menu_model->GetIndexOfCommandId(command_id).value(),
+  menu_model->ActivatedAt(menu_model->GetIndexOfCommandId(command_id),
                           ui::EF_LEFT_MOUSE_BUTTON);
   url_observer.Wait();
 }
diff --git a/chrome/browser/web_applications/commands/install_from_sync_command.cc b/chrome/browser/web_applications/commands/install_from_sync_command.cc
index b748eca0..c31eae9 100644
--- a/chrome/browser/web_applications/commands/install_from_sync_command.cc
+++ b/chrome/browser/web_applications/commands/install_from_sync_command.cc
@@ -230,7 +230,7 @@
 
   const bool manifest_has_icons = opt_manifest && !opt_manifest->icons.empty();
 
-  std::vector<GURL> icon_urls = GetValidIconUrlsToDownload(*install_info_);
+  base::flat_set<GURL> icon_urls = GetValidIconUrlsToDownload(*install_info_);
   data_retriever_->GetIcons(
       shared_web_contents(), std::move(icon_urls),
       /*skip_page_favicons=*/manifest_has_icons,
@@ -280,7 +280,7 @@
   DCHECK(code != webapps::InstallResultCode::kWebContentsDestroyed);
   DCHECK(code != webapps::InstallResultCode::kInstallTaskDestroyed);
 
-  std::vector<GURL> icon_urls =
+  base::flat_set<GURL> icon_urls =
       GetValidIconUrlsToDownload(*fallback_install_info_);
 
   base::UmaHistogramEnumeration("WebApp.Install.SyncFallbackInstallInitiated",
diff --git a/chrome/browser/web_applications/isolated_app_browsertest.cc b/chrome/browser/web_applications/isolated_app_browsertest.cc
index 6b9e7349..9ccb6eb 100644
--- a/chrome/browser/web_applications/isolated_app_browsertest.cc
+++ b/chrome/browser/web_applications/isolated_app_browsertest.cc
@@ -284,7 +284,7 @@
       /*provider=*/nullptr, app_browser);
   app_menu_model->Init();
   ui::MenuModel* model = app_menu_model.get();
-  size_t index = 0;
+  int index = -1;
   const bool found = app_menu_model->GetModelAndIndexForCommandId(
       IDC_OPEN_IN_CHROME, &model, &index);
   EXPECT_FALSE(found);
diff --git a/chrome/browser/web_applications/manifest_update_task.cc b/chrome/browser/web_applications/manifest_update_task.cc
index 1920036..f16f914 100644
--- a/chrome/browser/web_applications/manifest_update_task.cc
+++ b/chrome/browser/web_applications/manifest_update_task.cc
@@ -467,7 +467,8 @@
   stage_ = Stage::kPendingIconDownload;
 
   DCHECK(install_info_.has_value());
-  std::vector<GURL> icon_urls = GetValidIconUrlsToDownload(*install_info_);
+  base::flat_set<GURL> icon_urls = GetValidIconUrlsToDownload(*install_info_);
+
   icon_downloader_.emplace(
       web_contents(), std::move(icon_urls),
       base::BindOnce(&ManifestUpdateTask::OnIconsDownloaded, AsWeakPtr()));
diff --git a/chrome/browser/web_applications/test/fake_data_retriever.cc b/chrome/browser/web_applications/test/fake_data_retriever.cc
index bce7e2c1..9aaa1ff 100644
--- a/chrome/browser/web_applications/test/fake_data_retriever.cc
+++ b/chrome/browser/web_applications/test/fake_data_retriever.cc
@@ -41,7 +41,7 @@
 }
 
 void FakeDataRetriever::GetIcons(content::WebContents* web_contents,
-                                 std::vector<GURL> icon_urls,
+                                 base::flat_set<GURL> icon_urls,
                                  bool skip_page_favicons,
                                  GetIconsCallback callback) {
   if (get_icons_delegate_) {
diff --git a/chrome/browser/web_applications/test/fake_data_retriever.h b/chrome/browser/web_applications/test/fake_data_retriever.h
index fb0101b..1dc667a 100644
--- a/chrome/browser/web_applications/test/fake_data_retriever.h
+++ b/chrome/browser/web_applications/test/fake_data_retriever.h
@@ -35,7 +35,7 @@
       bool bypass_service_worker_check,
       CheckInstallabilityCallback callback) override;
   void GetIcons(content::WebContents* web_contents,
-                std::vector<GURL> icon_urls,
+                base::flat_set<GURL> icon_urls,
                 bool skip_page_favicons,
                 GetIconsCallback callback) override;
 
@@ -51,7 +51,7 @@
   void SetIcons(IconsMap icons_map);
   using GetIconsDelegate =
       base::RepeatingCallback<IconsMap(content::WebContents* web_contents,
-                                       const std::vector<GURL>& icon_urls,
+                                       const base::flat_set<GURL>& icon_urls,
                                        bool skip_page_favicons)>;
   void SetGetIconsDelegate(GetIconsDelegate get_icons_delegate);
 
diff --git a/chrome/browser/web_applications/test/mock_data_retriever.h b/chrome/browser/web_applications/test/mock_data_retriever.h
index 249840c..0e80b8dc 100644
--- a/chrome/browser/web_applications/test/mock_data_retriever.h
+++ b/chrome/browser/web_applications/test/mock_data_retriever.h
@@ -5,7 +5,6 @@
 #ifndef CHROME_BROWSER_WEB_APPLICATIONS_TEST_MOCK_DATA_RETRIEVER_H_
 #define CHROME_BROWSER_WEB_APPLICATIONS_TEST_MOCK_DATA_RETRIEVER_H_
 
-#include <vector>
 #include "chrome/browser/web_applications/web_app_data_retriever.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "url/gurl.h"
@@ -37,7 +36,7 @@
   MOCK_METHOD(void,
               GetIcons,
               (content::WebContents * web_contents,
-               std::vector<GURL> icon_urls,
+               base::flat_set<GURL> icon_urls,
                bool skip_page_favicons,
                GetIconsCallback callback),
               (override));
diff --git a/chrome/browser/web_applications/web_app_data_retriever.cc b/chrome/browser/web_applications/web_app_data_retriever.cc
index 5f521b8..d529335 100644
--- a/chrome/browser/web_applications/web_app_data_retriever.cc
+++ b/chrome/browser/web_applications/web_app_data_retriever.cc
@@ -115,7 +115,7 @@
 }
 
 void WebAppDataRetriever::GetIcons(content::WebContents* web_contents,
-                                   std::vector<GURL> icon_urls,
+                                   base::flat_set<GURL> icon_urls,
                                    bool skip_page_favicons,
                                    GetIconsCallback callback) {
   DCHECK(!web_contents->IsBeingDestroyed());
diff --git a/chrome/browser/web_applications/web_app_data_retriever.h b/chrome/browser/web_applications/web_app_data_retriever.h
index a8a42f3..2ba9dc2 100644
--- a/chrome/browser/web_applications/web_app_data_retriever.h
+++ b/chrome/browser/web_applications/web_app_data_retriever.h
@@ -75,7 +75,7 @@
   // Downloads icons from |icon_urls|. Runs |callback| with a map of
   // the retrieved icons.
   virtual void GetIcons(content::WebContents* web_contents,
-                        std::vector<GURL> icon_urls,
+                        base::flat_set<GURL> icon_urls,
                         bool skip_page_favicons,
                         GetIconsCallback callback);
 
diff --git a/chrome/browser/web_applications/web_app_data_retriever_unittest.cc b/chrome/browser/web_applications/web_app_data_retriever_unittest.cc
index 1e00e92b..1c18a979 100644
--- a/chrome/browser/web_applications/web_app_data_retriever_unittest.cc
+++ b/chrome/browser/web_applications/web_app_data_retriever_unittest.cc
@@ -329,7 +329,7 @@
 
   base::RunLoop run_loop;
   WebAppDataRetriever retriever;
-  retriever.GetIcons(web_contents(), /*icon_urls=*/std::vector<GURL>(),
+  retriever.GetIcons(web_contents(), /*icon_urls=*/base::flat_set<GURL>(),
                      skip_page_favicons,
                      base::BindLambdaForTesting(
                          [&](IconsDownloadedResult result, IconsMap icons_map,
diff --git a/chrome/browser/web_applications/web_app_icon_downloader.cc b/chrome/browser/web_applications/web_app_icon_downloader.cc
index 9dac002..fb882c5 100644
--- a/chrome/browser/web_applications/web_app_icon_downloader.cc
+++ b/chrome/browser/web_applications/web_app_icon_downloader.cc
@@ -18,7 +18,7 @@
 
 WebAppIconDownloader::WebAppIconDownloader(
     content::WebContents* web_contents,
-    std::vector<GURL> extra_favicon_urls,
+    base::flat_set<GURL> extra_favicon_urls,
     WebAppIconDownloaderCallback callback)
     : content::WebContentsObserver(web_contents),
       extra_favicon_urls_(std::move(extra_favicon_urls)),
@@ -89,7 +89,7 @@
   FetchIcons(urls);
 }
 
-void WebAppIconDownloader::FetchIcons(const std::vector<GURL>& urls) {
+void WebAppIconDownloader::FetchIcons(const base::flat_set<GURL>& urls) {
   // Download icons; put their download ids into |in_progress_requests_| and
   // their urls into |processed_urls_|.
   for (const GURL& url : urls) {
diff --git a/chrome/browser/web_applications/web_app_icon_downloader.h b/chrome/browser/web_applications/web_app_icon_downloader.h
index bb6bffe..d636979d 100644
--- a/chrome/browser/web_applications/web_app_icon_downloader.h
+++ b/chrome/browser/web_applications/web_app_icon_downloader.h
@@ -38,7 +38,7 @@
   // |extra_favicon_urls| allows callers to provide icon urls that aren't
   // provided by the renderer (e.g touch icons on non-android environments).
   WebAppIconDownloader(content::WebContents* web_contents,
-                       std::vector<GURL> extra_favicon_urls,
+                       base::flat_set<GURL> extra_favicon_urls,
                        WebAppIconDownloaderCallback callback);
   WebAppIconDownloader(const WebAppIconDownloader&) = delete;
   WebAppIconDownloader& operator=(const WebAppIconDownloader&) = delete;
@@ -66,7 +66,7 @@
   // Fetches icons for the given urls.
   // |callback_| is run when all downloads complete.
   void FetchIcons(const std::vector<blink::mojom::FaviconURLPtr>& favicon_urls);
-  void FetchIcons(const std::vector<GURL>& urls);
+  void FetchIcons(const base::flat_set<GURL>& urls);
 
   // Icon download callback.
   void DidDownloadFavicon(int id,
@@ -96,7 +96,7 @@
   // URLs that aren't given by WebContentsObserver::DidUpdateFaviconURL() that
   // should be used for this favicon. This is necessary in order to get touch
   // icons on non-android environments.
-  std::vector<GURL> extra_favicon_urls_;
+  base::flat_set<GURL> extra_favicon_urls_;
 
   // The icons which were downloaded. Populated by FetchIcons().
   IconsMap icons_map_;
diff --git a/chrome/browser/web_applications/web_app_install_task.cc b/chrome/browser/web_applications/web_app_install_task.cc
index 70f5db1..2a3c83c0 100644
--- a/chrome/browser/web_applications/web_app_install_task.cc
+++ b/chrome/browser/web_applications/web_app_install_task.cc
@@ -667,7 +667,7 @@
     }
   }
 
-  std::vector<GURL> icon_urls = GetValidIconUrlsToDownload(*web_app_info);
+  base::flat_set<GURL> icon_urls = GetValidIconUrlsToDownload(*web_app_info);
 
   // A system app should always have a manifest icon.
   if (install_surface_ == webapps::WebappInstallSource::SYSTEM_DEFAULT) {
@@ -686,7 +686,7 @@
 void WebAppInstallTask::CheckForPlayStoreIntentOrGetIcons(
     blink::mojom::ManifestPtr opt_manifest,
     std::unique_ptr<WebAppInstallInfo> web_app_info,
-    std::vector<GURL> icon_urls,
+    base::flat_set<GURL> icon_urls,
     bool skip_page_favicons) {
   bool is_create_shortcut = flow_ == WebAppInstallFlow::kCreateShortcut;
   // Background installations are not a user-triggered installs, and thus
@@ -743,7 +743,7 @@
 
 void WebAppInstallTask::OnDidCheckForIntentToPlayStore(
     std::unique_ptr<WebAppInstallInfo> web_app_info,
-    std::vector<GURL> icon_urls,
+    base::flat_set<GURL> icon_urls,
     bool skip_page_favicons,
     const std::string& intent,
     bool should_intent_to_store) {
@@ -790,7 +790,7 @@
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
 void WebAppInstallTask::OnDidCheckForIntentToPlayStoreLacros(
     std::unique_ptr<WebAppInstallInfo> web_app_info,
-    std::vector<GURL> icon_urls,
+    base::flat_set<GURL> icon_urls,
     bool skip_page_favicons,
     const std::string& intent,
     crosapi::mojom::IsInstallableResult result) {
diff --git a/chrome/browser/web_applications/web_app_install_task.h b/chrome/browser/web_applications/web_app_install_task.h
index e424d9ad..472578b 100644
--- a/chrome/browser/web_applications/web_app_install_task.h
+++ b/chrome/browser/web_applications/web_app_install_task.h
@@ -222,14 +222,14 @@
   void CheckForPlayStoreIntentOrGetIcons(
       blink::mojom::ManifestPtr opt_manifest,
       std::unique_ptr<WebAppInstallInfo> web_app_info,
-      std::vector<GURL> icon_urls,
+      base::flat_set<GURL> icon_urls,
       bool skip_page_favicons);
 
   // Called when the asynchronous check for whether an intent to the Play Store
   // should be made returns.
   void OnDidCheckForIntentToPlayStore(
       std::unique_ptr<WebAppInstallInfo> web_app_info,
-      std::vector<GURL> icon_urls,
+      base::flat_set<GURL> icon_urls,
       bool skip_page_favicons,
       const std::string& intent,
       bool should_intent_to_store);
@@ -240,7 +240,7 @@
   // |OnDidCheckForIntentToPlayStore| based on |result|).
   void OnDidCheckForIntentToPlayStoreLacros(
       std::unique_ptr<WebAppInstallInfo> web_app_info,
-      std::vector<GURL> icon_urls,
+      base::flat_set<GURL> icon_urls,
       bool skip_page_favicons,
       const std::string& intent,
       crosapi::mojom::IsInstallableResult result);
diff --git a/chrome/browser/web_applications/web_app_install_utils.cc b/chrome/browser/web_applications/web_app_install_utils.cc
index 2ebd6dd..df8afcd 100644
--- a/chrome/browser/web_applications/web_app_install_utils.cc
+++ b/chrome/browser/web_applications/web_app_install_utils.cc
@@ -595,14 +595,14 @@
   web_app_info->tab_strip = manifest.tab_strip;
 }
 
-std::vector<GURL> GetValidIconUrlsToDownload(
+base::flat_set<GURL> GetValidIconUrlsToDownload(
     const WebAppInstallInfo& web_app_info) {
-  std::vector<GURL> web_app_info_icon_urls;
+  base::flat_set<GURL> web_app_info_icon_urls;
   // App icons.
   for (const apps::IconInfo& info : web_app_info.manifest_icons) {
     if (!info.url.is_valid())
       continue;
-    web_app_info_icon_urls.push_back(info.url);
+    web_app_info_icon_urls.insert(info.url);
   }
 
   // Shortcut icons.
@@ -612,7 +612,7 @@
            shortcut.GetShortcutIconInfosForPurpose(purpose)) {
         if (!icon.url.is_valid())
           continue;
-        web_app_info_icon_urls.push_back(icon.url);
+        web_app_info_icon_urls.insert(icon.url);
       }
     }
   }
@@ -622,7 +622,7 @@
     for (const auto& icon : file_handler.downloaded_icons) {
       if (!icon.url.is_valid())
         continue;
-      web_app_info_icon_urls.push_back(icon.url);
+      web_app_info_icon_urls.insert(icon.url);
     }
   }
 
diff --git a/chrome/browser/web_applications/web_app_install_utils.h b/chrome/browser/web_applications/web_app_install_utils.h
index 91944be..8ebbf54 100644
--- a/chrome/browser/web_applications/web_app_install_utils.h
+++ b/chrome/browser/web_applications/web_app_install_utils.h
@@ -59,7 +59,7 @@
                                   WebAppInstallInfo* web_app_info);
 
 // Form a list of icons to download: Remove icons with invalid urls.
-std::vector<GURL> GetValidIconUrlsToDownload(
+base::flat_set<GURL> GetValidIconUrlsToDownload(
     const WebAppInstallInfo& web_app_info);
 
 // Populate non-product icons in WebAppInstallInfo using the IconsMap. This
diff --git a/chrome/browser/web_applications/web_app_install_utils_unittest.cc b/chrome/browser/web_applications/web_app_install_utils_unittest.cc
index 25b9b3ec..ab385524e 100644
--- a/chrome/browser/web_applications/web_app_install_utils_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_utils_unittest.cc
@@ -1263,6 +1263,138 @@
   }
 }
 
+// Test duplicate icon download urls that from the manifest.
+TEST(WebAppInstallUtils, DuplicateIconDownloadURLs) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitWithFeatures({blink::features::kFileHandlingIcons}, {});
+
+  WebAppInstallInfo web_app_info;
+
+  // manifest icons
+  {
+    apps::IconInfo info;
+    info.url = GURL("http://www.chromium.org/image/icon1.png");
+    web_app_info.manifest_icons.push_back(info);
+  }
+  {
+    apps::IconInfo info;
+    info.url = GURL("http://www.chromium.org/image/icon2.png");
+    web_app_info.manifest_icons.push_back(info);
+  }
+
+  // shortcut icons
+  {
+    WebAppShortcutsMenuItemInfo shortcut_item;
+    {
+      std::vector<WebAppShortcutsMenuItemInfo::Icon> shortcut_manifest_icons;
+      {
+        WebAppShortcutsMenuItemInfo::Icon icon;
+        icon.url = GURL("http://www.chromium.org/image/icon2.png");
+        shortcut_manifest_icons.push_back(icon);
+      }
+      {
+        WebAppShortcutsMenuItemInfo::Icon icon;
+        icon.url = GURL("http://www.chromium.org/image/icon3.png");
+        shortcut_manifest_icons.push_back(icon);
+      }
+      shortcut_item.SetShortcutIconInfosForPurpose(
+          IconPurpose::ANY, std::move(shortcut_manifest_icons));
+    }
+    {
+      std::vector<WebAppShortcutsMenuItemInfo::Icon> shortcut_manifest_icons;
+      {
+        WebAppShortcutsMenuItemInfo::Icon icon;
+        icon.url = GURL("http://www.chromium.org/image/icon3.png");
+        shortcut_manifest_icons.push_back(icon);
+      }
+      {
+        WebAppShortcutsMenuItemInfo::Icon icon;
+        icon.url = GURL("http://www.chromium.org/image/icon4.png");
+        shortcut_manifest_icons.push_back(icon);
+      }
+      shortcut_item.SetShortcutIconInfosForPurpose(
+          IconPurpose::MONOCHROME, std::move(shortcut_manifest_icons));
+    }
+    web_app_info.shortcuts_menu_item_infos.push_back(std::move(shortcut_item));
+  }
+  {
+    WebAppShortcutsMenuItemInfo shortcut_item;
+    {
+      std::vector<WebAppShortcutsMenuItemInfo::Icon> shortcut_manifest_icons;
+      {
+        WebAppShortcutsMenuItemInfo::Icon icon;
+        icon.url = GURL("http://www.chromium.org/image/icon4.png");
+        shortcut_manifest_icons.push_back(icon);
+      }
+      {
+        WebAppShortcutsMenuItemInfo::Icon icon;
+        icon.url = GURL("http://www.chromium.org/image/icon5.png");
+        shortcut_manifest_icons.push_back(icon);
+      }
+      shortcut_item.SetShortcutIconInfosForPurpose(
+          IconPurpose::ANY, std::move(shortcut_manifest_icons));
+    }
+    {
+      std::vector<WebAppShortcutsMenuItemInfo::Icon> shortcut_manifest_icons;
+      {
+        WebAppShortcutsMenuItemInfo::Icon icon;
+        icon.url = GURL("http://www.chromium.org/image/icon5.png");
+        shortcut_manifest_icons.push_back(icon);
+      }
+      {
+        WebAppShortcutsMenuItemInfo::Icon icon;
+        icon.url = GURL("http://www.chromium.org/image/icon6.png");
+        shortcut_manifest_icons.push_back(icon);
+      }
+      shortcut_item.SetShortcutIconInfosForPurpose(
+          IconPurpose::MASKABLE, std::move(shortcut_manifest_icons));
+    }
+    web_app_info.shortcuts_menu_item_infos.push_back(std::move(shortcut_item));
+  }
+
+  // file handler icons
+  {
+    apps::FileHandler file_handler;
+    std::vector<apps::IconInfo> downloaded_icons;
+    {
+      apps::IconInfo info;
+      info.url = GURL("http://www.chromium.org/image/icon6.png");
+      web_app_info.manifest_icons.push_back(info);
+    }
+    {
+      apps::IconInfo info;
+      info.url = GURL("http://www.chromium.org/image/icon7.png");
+      web_app_info.manifest_icons.push_back(info);
+    }
+    web_app_info.file_handlers.push_back(file_handler);
+  }
+  {
+    apps::FileHandler file_handler;
+    std::vector<apps::IconInfo> downloaded_icons;
+    {
+      apps::IconInfo info;
+      info.url = GURL("http://www.chromium.org/image/icon7.png");
+      web_app_info.manifest_icons.push_back(info);
+    }
+    {
+      apps::IconInfo info;
+      info.url = GURL("http://www.chromium.org/image/icon8.png");
+      web_app_info.manifest_icons.push_back(info);
+    }
+    web_app_info.file_handlers.push_back(file_handler);
+  }
+
+  base::flat_set<GURL> download_urls = GetValidIconUrlsToDownload(web_app_info);
+
+  const size_t download_urls_size = 8;
+  EXPECT_EQ(download_urls_size, download_urls.size());
+  for (size_t i = 0; i < download_urls_size; i++) {
+    std::string url_str = "http://www.chromium.org/image/icon" +
+                          base::NumberToString(i + 1) + ".png";
+    EXPECT_EQ(1u, download_urls.count(GURL(url_str)));
+  }
+}
+
 INSTANTIATE_TEST_SUITE_P(, FileHandlersFromManifestTest, testing::Bool());
 
 #if BUILDFLAG(IS_WIN)
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 997cfa23..ef00185 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1658274933-355d2716c80bd4170fc244bc070cde51bc17da79.profdata
+chrome-linux-main-1658317990-d11c01a0b2a0c77ac07ae6113b98ac29dd4d6310.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index a66d694..b547609 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1658274933-63817084fd43bbf557bfefe00c28308baab662be.profdata
+chrome-mac-arm-main-1658296671-dfd0ec06cf2f2f792f4715bfbf1e83fa09bdbe58.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index c07eb29..e8bb245a 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1658274933-37605cd3911bb83b7e324d4e81fc9d044acda3d2.profdata
+chrome-mac-main-1658296671-cda5ef93770125e79a81a7ba784fd6972a390e49.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 79e468dd1..605e209 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1658274933-b1783bf8ed9af7fbc56a0b31217a1b18513899a5.profdata
+chrome-win32-main-1658307270-8cbd3621f3ee22a6478dd32857ec8cb99e4d1a44.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 2a895d7..9cea922 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1658274933-518c90a91b841f96a73d8cd59333549cb8c53f66.profdata
+chrome-win64-main-1658307270-7f4ed894dcb461af846a4e9d7cae1933ef07be33.profdata
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc
index 2cd7c41..37dc334 100644
--- a/chrome/common/chrome_content_client.cc
+++ b/chrome/common/chrome_content_client.cc
@@ -252,8 +252,8 @@
 #if BUILDFLAG(ENABLE_EXTENSIONS)
     extensions::kExtensionScheme,
 #endif
-    chrome::kChromeNativeScheme,        chrome::kChromeSearchScheme,
-    dom_distiller::kDomDistillerScheme,
+    chrome::kIsolatedAppScheme,   chrome::kChromeNativeScheme,
+    chrome::kChromeSearchScheme,  dom_distiller::kDomDistillerScheme,
 #if BUILDFLAG(IS_ANDROID)
     content::kAndroidAppScheme,
 #endif
@@ -314,6 +314,11 @@
       url::kWebcalScheme, chrome::kChromeOSDefaultWebcalHandler);
 #endif
 
+  schemes->secure_schemes.push_back(chrome::kIsolatedAppScheme);
+  schemes->cors_enabled_schemes.push_back(chrome::kIsolatedAppScheme);
+  schemes->service_worker_schemes.push_back(chrome::kIsolatedAppScheme);
+  url::AddWebStorageScheme(chrome::kIsolatedAppScheme);
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   schemes->local_schemes.push_back(content::kExternalFileScheme);
 #endif
diff --git a/chrome/common/chrome_content_client_unittest.cc b/chrome/common/chrome_content_client_unittest.cc
index 7df450d..bbbc6c81 100644
--- a/chrome/common/chrome_content_client_unittest.cc
+++ b/chrome/common/chrome_content_client_unittest.cc
@@ -122,6 +122,7 @@
     "chrome://foo/",
     "chrome-untrusted://foo/",
     "chrome-search://foo/",
+    "isolated-app://foo/",
 #if BUILDFLAG(ENABLE_EXTENSIONS)
     "chrome-extension://foo/",
 #endif
diff --git a/chrome/common/extensions/api/passwords_private.idl b/chrome/common/extensions/api/passwords_private.idl
index 3945aa0..284d760b 100644
--- a/chrome/common/extensions/api/passwords_private.idl
+++ b/chrome/common/extensions/api/passwords_private.idl
@@ -95,6 +95,9 @@
     // Corresponds to where the credential is stored.
     PasswordStoreSet storedIn;
 
+    // Indicates whether this credential belongs to an Android app.
+    boolean isAndroidCredential;
+
     // The value of the attached note.
     DOMString passwordNote;
   };
diff --git a/chrome/common/privacy_budget/privacy_budget_features.cc b/chrome/common/privacy_budget/privacy_budget_features.cc
index fffd844e..8745ba8 100644
--- a/chrome/common/privacy_budget/privacy_budget_features.cc
+++ b/chrome/common/privacy_budget/privacy_budget_features.cc
@@ -62,5 +62,8 @@
 const base::FeatureParam<std::string>
     kIdentifiabilityStudyReidSurfaceBlocksBits = {&kIdentifiabilityStudy,
                                                   "ReidBlocksBits", ""};
+const base::FeatureParam<std::string>
+    kIdentifiabilityStudyReidBlocksNoiseProbabilities = {
+        &kIdentifiabilityStudy, "ReidBlocksNoiseProbabilities", ""};
 
 }  // namespace features
diff --git a/chrome/common/privacy_budget/privacy_budget_features.h b/chrome/common/privacy_budget/privacy_budget_features.h
index 627c0db..472a26a 100644
--- a/chrome/common/privacy_budget/privacy_budget_features.h
+++ b/chrome/common/privacy_budget/privacy_budget_features.h
@@ -400,6 +400,27 @@
 extern const base::FeatureParam<std::string>
     kIdentifiabilityStudyReidSurfaceBlocksBits;
 
+// Probabilities of reporting noise in Reid estimation.
+//
+// Parameter name: "ReidBlocksNoiseProbabilities"
+// Parameter type: Comma separated list of noise probabilities represented as
+// decimals.
+//
+// If this parameter is specified then it must specify the probability of noise
+// that should be reported for each block that is defined using the `ReidBlocks`
+// parameter. The probability should be a decimal between 0 and 1.
+//
+// * All probabilities must be positive decimals between 0 and 1.
+//
+// * There must be exactly as many Reid noise probabilities as there are Reid
+// blocks. If not, disable the Reid estimator feature.
+//
+// E.g.:
+//   * "0.1,0.05": Assigns probabilities of noise that should be reported from
+//   two Reid Blocks sent in the `ReidBlocks` parameter.
+extern const base::FeatureParam<std::string>
+    kIdentifiabilityStudyReidBlocksNoiseProbabilities;
+
 }  // namespace features
 
 #endif  // CHROME_COMMON_PRIVACY_BUDGET_PRIVACY_BUDGET_FEATURES_H_
diff --git a/chrome/common/privacy_budget/privacy_budget_settings_provider.cc b/chrome/common/privacy_budget/privacy_budget_settings_provider.cc
index 63da8b9f..ea18de0 100644
--- a/chrome/common/privacy_budget/privacy_budget_settings_provider.cc
+++ b/chrome/common/privacy_budget/privacy_budget_settings_provider.cc
@@ -51,3 +51,9 @@
 bool PrivacyBudgetSettingsProvider::ShouldActivelySample() const {
   return active_sampling_enabled_;
 }
+
+std::vector<std::string>
+PrivacyBudgetSettingsProvider::FontFamiliesToActivelySample() const {
+  return DecodeIdentifiabilityFieldTrialParam<std::vector<std::string>>(
+      features::kIdentifiabilityStudyActivelySampledFonts.Get());
+}
diff --git a/chrome/common/privacy_budget/privacy_budget_settings_provider.h b/chrome/common/privacy_budget/privacy_budget_settings_provider.h
index 3e64a37b..d3078e2 100644
--- a/chrome/common/privacy_budget/privacy_budget_settings_provider.h
+++ b/chrome/common/privacy_budget/privacy_budget_settings_provider.h
@@ -45,6 +45,7 @@
   bool IsSurfaceAllowed(blink::IdentifiableSurface surface) const override;
   bool IsTypeAllowed(blink::IdentifiableSurface::Type type) const override;
   bool ShouldActivelySample() const override;
+  std::vector<std::string> FontFamiliesToActivelySample() const override;
 
  private:
   // Set of identifiable surfaces for which we will NOT collect metrics. This
diff --git a/chrome/common/privacy_budget/scoped_privacy_budget_config.cc b/chrome/common/privacy_budget/scoped_privacy_budget_config.cc
index b2375db..505895c6 100644
--- a/chrome/common/privacy_budget/scoped_privacy_budget_config.cc
+++ b/chrome/common/privacy_budget/scoped_privacy_budget_config.cc
@@ -130,6 +130,11 @@
     ftp.insert({features::kIdentifiabilityStudyReidSurfaceBlocksBits.name,
                 EncodeIdentifiabilityFieldTrialParam(parameters.reid_bits)});
   }
+  if (!parameters.reid_noise.empty()) {
+    ftp.insert(
+        {features::kIdentifiabilityStudyReidBlocksNoiseProbabilities.name,
+         EncodeIdentifiabilityFieldTrialParam(parameters.reid_noise)});
+  }
   if (!parameters.per_surface_cost.empty()) {
     ftp.insert(
         {features::kIdentifiabilityStudyPerHashCost.name,
diff --git a/chrome/common/privacy_budget/scoped_privacy_budget_config.h b/chrome/common/privacy_budget/scoped_privacy_budget_config.h
index d4e32b61..befb6fac 100644
--- a/chrome/common/privacy_budget/scoped_privacy_budget_config.h
+++ b/chrome/common/privacy_budget/scoped_privacy_budget_config.h
@@ -67,6 +67,7 @@
     IdentifiableSurfaceBlocks reid_blocks;
     std::vector<uint64_t> reid_salts_ranges;
     std::vector<int> reid_bits;
+    std::vector<double> reid_noise;
     std::vector<blink::IdentifiableSurface::Type> allowed_random_types;
     bool enable_active_sampling = false;
     std::vector<std::string> actively_sampled_fonts;
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index 91674a5..3badab5 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -83,6 +83,8 @@
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
+const char kIsolatedAppScheme[] = "isolated-app";
+
 const char kChromeNativeScheme[] = "chrome-native";
 
 const char kChromeSearchLocalNtpHost[] = "local-ntp";
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index 53d59a6..6bfeedc 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -77,6 +77,10 @@
 extern const char kChromeOsHelpViaWebUIURL[];
 #endif
 
+// The isolated-app: scheme is used for Isolated Web Apps. A public explainer
+// can be found here: https://github.com/reillyeon/isolated-web-apps
+extern const char kIsolatedAppScheme[];
+
 // The chrome-native: scheme is used show pages rendered with platform specific
 // widgets instead of using HTML.
 extern const char kChromeNativeScheme[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index a829b3b..8ec15cb 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -6899,6 +6899,7 @@
       "//chrome/browser/ui/webui/new_tab_page:mojo_bindings",
       "//chrome/browser/web_applications:web_applications_test_support",
       "//components/app_constants",
+      "//components/autofill_assistant/browser/public",
       "//components/autofill_assistant/browser/public:proto",
       "//components/autofill_assistant/browser/public:unit_test_support",
       "//components/autofill_assistant/browser/public/password_change/proto:proto",
diff --git a/chrome/test/base/menu_model_test.cc b/chrome/test/base/menu_model_test.cc
index eb29e45..1c96f08 100644
--- a/chrome/test/base/menu_model_test.cc
+++ b/chrome/test/base/menu_model_test.cc
@@ -24,7 +24,7 @@
 // match the number of times the delegate is called to ensure every item works.
 void MenuModelTest::CountEnabledExecutable(ui::MenuModel* model,
                                            int* count) {
-  for (size_t i = 0; i < model->GetItemCount(); ++i) {
+  for (int i = 0; i < model->GetItemCount(); ++i) {
     ui::MenuModel::ItemType type = model->GetTypeAt(i);
     switch (type) {
       case ui::MenuModel::TYPE_SEPARATOR:
diff --git a/chrome/test/data/client_hints/meta_name_accept_ch_delegation_merge.html b/chrome/test/data/client_hints/meta_name_accept_ch_delegation_merge.html
deleted file mode 100644
index 86a37e5f..0000000
--- a/chrome/test/data/client_hints/meta_name_accept_ch_delegation_merge.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<html>
-<meta name="Accept-CH" content="dpr=(https://bar.com/),sec-ch-dpr=(https://bar.com/),device-memory=(https://bar.com/),sec-ch-device-memory=(https://bar.com/),viewport-width=(https://bar.com/),sec-ch-viewport-width=(https://bar.com/),rtt=(https://bar.com/),downlink=(https://bar.com/),ect=(https://bar.com/),sec-ch-ua-arch=(https://bar.com/),sec-ch-ua-platform-version=(https://bar.com/),sec-ch-ua-model=(https://bar.com/),sec-ch-ua-full-version=(https://bar.com/),sec-ch-prefers-color-scheme=(https://bar.com/),sec-ch-ua-bitness=(https://bar.com/),sec-ch-viewport-height=(https://bar.com/),sec-ch-ua-full-version-list=(https://bar.com/),sec-ch-ua-wow64=(https://bar.com/)">
-<link rel="icon" href="data:;base64,=">
-<body>
-    <img src="test_img.jpg"></img>
-    <img src="https://foo.com/non-existing-image.jpg"></img>
-    <iframe src="https://foo.com/non-existing-iframe.html"></iframe>
-    <script type="text/javascript">
-        document.body.innerHTML += '<img src="test_img.jpg?foo"></img>';
-        document.body.innerHTML += '<img src="https://bar.com/non-existing-image.jpg"></img>';
-        document.body.innerHTML += '<iframe src="https://bar.com/non-existing-iframe.html"></iframe>';
-    </script>
-</body>
-</html>
diff --git a/chrome/test/data/client_hints/meta_name_accept_ch_delegation_merge.html.mock-http-headers b/chrome/test/data/client_hints/meta_name_accept_ch_delegation_merge.html.mock-http-headers
deleted file mode 100644
index bf7cf79..0000000
--- a/chrome/test/data/client_hints/meta_name_accept_ch_delegation_merge.html.mock-http-headers
+++ /dev/null
@@ -1,3 +0,0 @@
-HTTP/1.1 200 OK
-Accept-CH: dpr,sec-ch-dpr,device-memory,sec-ch-device-memory,viewport-width,sec-ch-viewport-width,rtt,downlink,ect,sec-ch-ua-arch,sec-ch-ua-platform-version,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-prefers-color-scheme,sec-ch-ua-bitness,sec-ch-viewport-height,sec-ch-ua-full-version-list,sec-ch-ua-wow64
-Permissions-Policy: ch-dpr=(*),ch-device-memory=(self "https://foo.com/"),ch-viewport-width=(*),ch-rtt=(self "https://foo.com/"),ch-downlink=(*),ch-ect=(self "https://foo.com/"),ch-ua-arch=(*),ch-ua-platform-version=(self "https://foo.com/"),ch-ua-model=(*),ch-ua-full-version=(self "https://foo.com/"),ch-prefers-color-scheme=(*),ch-ua-bitness=(self "https://foo.com/"),ch-viewport-height=(*),ch-ua-full-version-list=(self "https://foo.com/"),ch-ua-wow64=(*)
diff --git a/chrome/test/data/client_hints/meta_name_accept_ch_merge.html b/chrome/test/data/client_hints/meta_name_accept_ch_merge.html
deleted file mode 100644
index b0ebc3cb..0000000
--- a/chrome/test/data/client_hints/meta_name_accept_ch_merge.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<html>
-<!-- This is split in two since data from header may round trip quickly
-  enough from browser to be used, so this makes sure we actually merge -->
-<meta name="Accept-CH" content="sec-ch-ua-arch,sec-ch-ua-platform">
-<meta name="Accept-CH" content="sec-ch-ua-platform-version,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-prefers-color-scheme,sec-ch-ua-bitness,sec-ch-viewport-height,sec-ch-ua-full-version-list,sec-ch-ua-wow64">
-<link rel="icon" href="data:;base64,=">
-<!-- A subresource! -->
-<img src="non-existing-image.jpg"></img>
-</html>
diff --git a/chrome/test/data/client_hints/meta_name_accept_ch_merge.html.mock-http-headers b/chrome/test/data/client_hints/meta_name_accept_ch_merge.html.mock-http-headers
deleted file mode 100644
index 12c0516..0000000
--- a/chrome/test/data/client_hints/meta_name_accept_ch_merge.html.mock-http-headers
+++ /dev/null
@@ -1,2 +0,0 @@
-HTTP/1.1 200 OK
-Accept-CH: dpr,sec-ch-dpr,device-memory,sec-ch-device-memory,viewport-width,sec-ch-viewport-width,rtt,downlink,ect
diff --git a/chrome/test/data/webui/history/test_browser_service.ts b/chrome/test/data/webui/history/test_browser_service.ts
index fb03426..a79bcda5 100644
--- a/chrome/test/data/webui/history/test_browser_service.ts
+++ b/chrome/test/data/webui/history/test_browser_service.ts
@@ -32,7 +32,7 @@
       'recordHistogram',
       'recordLongTime',
       'removeVisits',
-      'startSignInFlow',
+      'startTurnOnSyncFlow',
     ]);
 
     this.queryResult_ = {info: createHistoryInfo(), value: []};
@@ -166,5 +166,5 @@
   }
 
   removeBookmark() {}
-  startSignInFlow() {}
+  startTurnOnSyncFlow() {}
 }
diff --git a/chrome/test/data/webui/settings/password_edit_dialog_test.ts b/chrome/test/data/webui/settings/password_edit_dialog_test.ts
index 1ec4ed1d..47ed5d4 100644
--- a/chrome/test/data/webui/settings/password_edit_dialog_test.ts
+++ b/chrome/test/data/webui/settings/password_edit_dialog_test.ts
@@ -10,11 +10,11 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {PasswordDialogMode, PasswordEditDialogElement, SettingsTextareaElement} from 'chrome://settings/lazy_load.js';
-import {PasswordManagerImpl} from 'chrome://settings/settings.js';
+import {PasswordManagerImpl, MultiStorePasswordUiEntry} from 'chrome://settings/settings.js';
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {eventToPromise, flushTasks, isVisible} from 'chrome://webui-test/test_util.js';
 
-import {createMultiStorePasswordEntry, PasswordSectionElementFactory} from './passwords_and_autofill_fake_data.js';
+import {createPasswordEntry, createMultiStorePasswordEntry, PasswordSectionElementFactory} from './passwords_and_autofill_fake_data.js';
 import {TestPasswordManagerProxy} from './test_password_manager_proxy.js';
 
 // clang-format on
@@ -239,6 +239,17 @@
         passwordDialog.$.footnote.innerText.trim());
   });
 
+  test('hasCorrectInitialStateWhenEditAndroidCredential', function() {
+    const androidEntry = createPasswordEntry(
+        {url: 'app.com', username: 'bart', isAndroidCredential: true});
+    const passwordDialog = elementFactory.createPasswordEditDialog(
+        new MultiStorePasswordUiEntry(androidEntry));
+    assertEquals(androidEntry.urls.shown, passwordDialog.$.websiteInput.value);
+    assertEquals(
+        passwordDialog.i18n('editPasswordAppLabel'),
+        passwordDialog.$.websiteInput.label);
+  });
+
   test('hasCorrectInitialStateWhenEditPassword', function() {
     const commonEntry = createMultiStorePasswordEntry(
         {url: 'goo.gl', username: 'bart', accountId: 42});
diff --git a/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.ts b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.ts
index b53ce293..eae8b0e3 100644
--- a/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.ts
+++ b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.ts
@@ -19,6 +19,7 @@
   id?: number,
   inAccountStore?: boolean,
   inProfileStore?: boolean,
+  isAndroidCredential?: boolean,
   note?: string,
 };
 
@@ -59,6 +60,7 @@
     federationText: params.federationText,
     id: id,
     storedIn: storeType,
+    isAndroidCredential: params.isAndroidCredential || false,
     passwordNote: note,
   };
 }
diff --git a/chromeos/components/string_matching/fuzzy_tokenized_string_match_unittest.cc b/chromeos/components/string_matching/fuzzy_tokenized_string_match_unittest.cc
index 2bd94350..ddffb2f 100644
--- a/chromeos/components/string_matching/fuzzy_tokenized_string_match_unittest.cc
+++ b/chromeos/components/string_matching/fuzzy_tokenized_string_match_unittest.cc
@@ -16,11 +16,20 @@
 
 namespace {
 
+constexpr float kEps = 1e-5f;
+
 // Default parameters.
 constexpr bool kUseWeightedRatio = false;
 constexpr bool kUseEditDistance = false;
 constexpr double kPartialMatchPenaltyRate = 0.9;
 
+void ExpectAllNearlyEqual(const std::vector<double>& scores,
+                          double epsilon = kEps) {
+  for (size_t i = 1; i < scores.size(); ++i) {
+    EXPECT_NEAR(scores[0], scores[i], epsilon);
+  }
+}
+
 void ExpectIncreasing(const std::vector<double>& scores,
                       int start_index,
                       int end_index,
@@ -93,8 +102,95 @@
  * Benchmarking tests                                                 *
  **********************************************************************/
 // The tests in this section perform benchmarking on the quality of
-// relevance scores. See the README for details.
-// TODO(crbug.com/1336160): Expand benchmarking tests.
+// relevance scores. See the README for details. These tests are divided into
+// two sections:
+//
+//   1) Abstract test cases - which illustrate our intended string matching
+//   principles generically.
+//   2) Non-abstract test cases - which use real-world examples to:
+//      a) support the principles in (1).
+//      b) document bugs.
+//
+//  Both sections will variously cover the following dimensions:
+//
+// - Special characters:
+//   - Upper/lower case
+//   - Numerals
+//   - Punctuation
+// - Typos and misspellings
+// - Full vs. partial matches
+// - Prefix-related logic
+// - Single- vs. multi-token texts
+// - Single- vs. multi-token queries
+// - Single vs. multiple possible matches
+// - Duplicate tokens
+//
+// Some test cases cover an intersection of multiple dimensions.
+//
+// Future benchmarking work may cover:
+//
+// - Special token delimiters
+//   - Camel case
+//   - Non-whitespace token delimiters
+
+/**********************************************************************
+ * Benchmarking section 1 - Abstract test cases                       *
+ **********************************************************************/
+// TODO(crbug.com/1336160): Expand abstract benchmarking tests.
+
+TEST_F(FuzzyTokenizedStringMatchTest, BenchmarkCaseInsensitivity) {
+  std::u16string text = u"abcde";
+  std::vector<std::u16string> queries = {u"abcde", u"Abcde", u"aBcDe",
+                                         u"ABCDE"};
+  std::vector<double> scores;
+  for (const auto& query : queries) {
+    const double relevance = CalculateRelevance(query, text);
+    scores.push_back(relevance);
+    VLOG(1) << FormatRelevanceResult(query, text, relevance,
+                                     /*query_first*/ false);
+  }
+  ExpectAllNearlyEqual(scores);
+}
+
+TEST_F(FuzzyTokenizedStringMatchTest, BenchmarkNumerals) {
+  // TODO(crbug.com/1336160): This test is a placeholder to remember to
+  // consider numerals, and should be refined/removed/expanded as appropriate
+  // later.
+  std::u16string text = u"abc123";
+  std::u16string query = u"abc 123";
+  const double relevance = CalculateRelevance(query, text);
+  VLOG(1) << FormatRelevanceResult(query, text, relevance,
+                                   /*query_first*/ false);
+}
+
+TEST_F(FuzzyTokenizedStringMatchTest, BenchmarkPunctuation) {
+  std::u16string text = u"abcde'fg";
+  std::vector<std::u16string> queries = {u"abcde'fg", u"abcdefg"};
+  for (const auto& query : queries) {
+    const double relevance = CalculateRelevance(query, text);
+    VLOG(1) << FormatRelevanceResult(query, text, relevance,
+                                     /*query_first*/ false);
+  }
+  // TODO(crbug.com/1336160): Enforce/check that scores are close, after this
+  // behavior is implemented.
+}
+
+TEST_F(FuzzyTokenizedStringMatchTest, BenchmarkCamelCase) {
+  std::u16string text = u"AbcdeFghIj";
+  std::vector<std::u16string> queries = {u"AbcdeFghIj", u"abcde fgh ij",
+                                         u"abcdefghij", u"abcde fghij"};
+  for (const auto& query : queries) {
+    const double relevance = CalculateRelevance(query, text);
+    VLOG(1) << FormatRelevanceResult(query, text, relevance,
+                                     /*query_first*/ false);
+  }
+  // TODO(crbug.com/1336160): Enforce/check that scores are close, after this
+  // behavior is implemented.
+}
+
+/**********************************************************************
+ * Benchmarking section 2 - Non-abstract test cases                   *
+ **********************************************************************/
 
 // TODO(crbug.com/1288662): Make matching less permissive where the strings
 // are short and the matching is multi-block (e.g. "chat" vs "caret").
diff --git a/chromeos/tast_control.gni b/chromeos/tast_control.gni
index 1eb4338..79cde9f 100644
--- a/chromeos/tast_control.gni
+++ b/chromeos/tast_control.gni
@@ -266,6 +266,9 @@
   # http://crbug.com/1309278
   "policy.ChromeOsLockOnIdleSuspend",
 
+  # https://crbug.com/1340557
+  "apps.LaunchSystemWebAppsFromURL",
+
   # https://crbug.com/1341074
   "launcher.BubbleLaunchApp.enable_launcher_app_sort",
 
diff --git a/chromeos/ui/frame/desks/move_to_desks_menu_model.cc b/chromeos/ui/frame/desks/move_to_desks_menu_model.cc
index 7c0f7ac9..0fb04ef 100644
--- a/chromeos/ui/frame/desks/move_to_desks_menu_model.cc
+++ b/chromeos/ui/frame/desks/move_to_desks_menu_model.cc
@@ -37,7 +37,7 @@
 
 MoveToDesksMenuModel::~MoveToDesksMenuModel() {}
 
-bool MoveToDesksMenuModel::MayHaveMnemonicsAt(size_t index) const {
+bool MoveToDesksMenuModel::MayHaveMnemonicsAt(int index) const {
   // If the label is a user-created desk name, the user might have ampersands so
   // don't process mnemonics for them.
   return (index == assign_to_all_desks_item_index_);
diff --git a/chromeos/ui/frame/desks/move_to_desks_menu_model.h b/chromeos/ui/frame/desks/move_to_desks_menu_model.h
index 44fc95c..7889f5d2 100644
--- a/chromeos/ui/frame/desks/move_to_desks_menu_model.h
+++ b/chromeos/ui/frame/desks/move_to_desks_menu_model.h
@@ -42,7 +42,7 @@
   };
 
   // SimpleMenuModel:
-  bool MayHaveMnemonicsAt(size_t index) const override;
+  bool MayHaveMnemonicsAt(int index) const override;
 
  private:
   // A menu delegate used to determine which labels are shown and enabled. Also
@@ -50,7 +50,7 @@
   std::unique_ptr<ui::SimpleMenuModel::Delegate> delegate_;
 
   // This is the index of the assign to all desks item in the menu model.
-  size_t assign_to_all_desks_item_index_;
+  int assign_to_all_desks_item_index_;
 };
 
 }  // namespace chromeos
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 10c4d88..0956911 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -362,6 +362,7 @@
       "//components/offline_pages:unit_tests",
       "//components/optimization_guide/content/browser:unit_tests",
       "//components/optimization_guide/content/renderer:unit_tests",
+      "//components/origin_trials:unit_tests",
       "//components/page_image_annotation/content/renderer:unit_tests",
       "//components/page_image_annotation/core:unit_tests",
       "//components/page_info/core:unit_tests",
diff --git a/components/autofill_assistant/android/BUILD.gn b/components/autofill_assistant/android/BUILD.gn
index 4570b13..8f31e3bc 100644
--- a/components/autofill_assistant/android/BUILD.gn
+++ b/components/autofill_assistant/android/BUILD.gn
@@ -105,6 +105,7 @@
     "java/src/org/chromium/components/autofill_assistant/form/AssistantFormSelectionChoice.java",
     "java/src/org/chromium/components/autofill_assistant/form/AssistantFormSelectionInput.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantColor.java",
+    "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDeviceConfig.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDimension.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDrawable.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantGenericUiCoordinator.java",
@@ -286,6 +287,7 @@
     "java/src/org/chromium/components/autofill_assistant/form/AssistantFormInput.java",
     "java/src/org/chromium/components/autofill_assistant/form/AssistantFormModel.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantColor.java",
+    "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDeviceConfig.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDimension.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDrawable.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantGenericUiDelegate.java",
diff --git a/components/autofill_assistant/android/internal/java/res/layout/autofill_assistant_info_box.xml b/components/autofill_assistant/android/internal/java/res/layout/autofill_assistant_info_box.xml
index 6c939df2..e57bae9 100644
--- a/components/autofill_assistant/android/internal/java/res/layout/autofill_assistant_info_box.xml
+++ b/components/autofill_assistant/android/internal/java/res/layout/autofill_assistant_info_box.xml
@@ -2,9 +2,22 @@
 <!-- Copyright 2019 The Chromium Authors. All rights reserved.
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
-
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+  xmlns:android="http://schemas.android.com/apk/res/android"
+  android:layout_width="match_parent"
+  xmlns:tools="http://schemas.android.com/tools"
+  android:layout_height="wrap_content"
+  android:orientation="vertical"
+  android:layout_gravity="center"
+  tools:ignore="UseCompoundDrawables" >
+  <ImageView
+    android:id="@+id/info_box_image"
+    android:layout_marginTop="16dp"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    tools:ignore="ContentDescription" />
+  <TextView
     android:id="@+id/info_box_explanation"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -14,3 +27,6 @@
     android:paddingBottom="@dimen/autofill_assistant_info_box_spacing"
     android:drawablePadding="@dimen/autofill_assistant_bottombar_vertical_spacing"
     android:textAppearance="@style/TextAppearance.TextLarge.Primary"/>
+
+
+</LinearLayout>
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDeviceConfig.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDeviceConfig.java
new file mode 100644
index 0000000..79a3625
--- /dev/null
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDeviceConfig.java
@@ -0,0 +1,41 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.autofill_assistant.generic_ui;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.util.DisplayMetrics;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+
+/**
+ * Contains methods to provide information about device configuration. It is used to select device
+ * configuration specific resources.
+ */
+@JNINamespace("autofill_assistant")
+public abstract class AssistantDeviceConfig {
+    @CalledByNative
+    public static boolean isDarkModeEnabled(Context context) {
+        return (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
+                == Configuration.UI_MODE_NIGHT_YES;
+    }
+
+    @CalledByNative
+    public static String getDevicePixelDensity(Context context) {
+        int densityDpi = context.getResources().getDisplayMetrics().densityDpi;
+        if (densityDpi <= DisplayMetrics.DENSITY_LOW) {
+            return "ldpi";
+        } else if (densityDpi <= DisplayMetrics.DENSITY_MEDIUM) {
+            return "mdpi";
+        } else if (densityDpi <= DisplayMetrics.DENSITY_HIGH) {
+            return "hdpi";
+        } else if (densityDpi <= DisplayMetrics.DENSITY_XHIGH) {
+            return "xhdpi";
+        } else {
+            return "xxhdpi";
+        }
+    }
+}
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDrawable.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDrawable.java
index 307d0988..775713f 100644
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDrawable.java
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDrawable.java
@@ -49,6 +49,12 @@
         return new AssistantBitmapDrawable(imageFetcher, url, widthInPixels, heightInPixels);
     }
 
+    @CalledByNative
+    public static AssistantDrawable createFromUrlWithIntrinsicDimensions(
+            ImageFetcher imageFetcher, String url) {
+        return new AssistantBitmapDrawable(imageFetcher, url);
+    }
+
     /** Returns whether {@code resourceId} is a valid resource identifier. */
     @CalledByNative
     public static boolean isValidDrawableResource(Context context, String resourceId) {
@@ -116,12 +122,22 @@
         private final String mUrl;
         private final int mWidthInPixels;
         private final int mHeightInPixels;
+        private final boolean mUseInstrinicDimensions;
 
         AssistantBitmapDrawable(ImageFetcher imageFetcher, String url, int width, int height) {
             mImageFetcher = imageFetcher;
             mUrl = url;
             mWidthInPixels = width;
             mHeightInPixels = height;
+            mUseInstrinicDimensions = false;
+        }
+
+        AssistantBitmapDrawable(ImageFetcher imageFetcher, String url) {
+            mImageFetcher = imageFetcher;
+            mUrl = url;
+            mWidthInPixels = 0;
+            mHeightInPixels = 0;
+            mUseInstrinicDimensions = true;
         }
 
         @Override
@@ -131,9 +147,11 @@
                     mUrl, ImageFetcher.ASSISTANT_DETAILS_UMA_CLIENT_NAME);
             mImageFetcher.fetchImage(params, result -> {
                 if (result != null) {
-                    callback.onResult(new BitmapDrawable(context.getResources(),
-                            Bitmap.createScaledBitmap(
-                                    result, mWidthInPixels, mHeightInPixels, true)));
+                    if (!mUseInstrinicDimensions) {
+                        result = Bitmap.createScaledBitmap(
+                                result, mWidthInPixels, mHeightInPixels, true);
+                    }
+                    callback.onResult(new BitmapDrawable(context.getResources(), result));
                 } else {
                     callback.onResult(null);
                 }
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantViewFactory.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantViewFactory.java
index 5fff80f3..06d8024 100644
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantViewFactory.java
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantViewFactory.java
@@ -158,7 +158,8 @@
     /** Creates a {@code EditorTextField} view. */
     @CalledByNative
     public static View createTextInputView(Context context, AssistantGenericUiDelegate delegate,
-            String viewIdentifier, int type, String hint, String modelIdentifier) {
+            String viewIdentifier, int type, String hint, String modelIdentifier,
+            boolean focusAndShowKeyboard) {
         View view = new EditorTextField(context,
                 EditorFieldModel.createTextInput(type, hint, /* suggestions = */ null,
                         /* formatter = */ null, /* validator = */ null,
@@ -180,7 +181,7 @@
                         delegate.onValueChanged(modelIdentifier,
                                 AssistantValue.createForStrings(new String[] {value.toString()}));
                     }
-                }, /* focusAndShowKeyboard= */ false);
+                }, focusAndShowKeyboard);
         view.setTag(viewIdentifier);
         return view;
     }
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBox.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBox.java
index 0e6ad399..610b9a8e 100644
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBox.java
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBox.java
@@ -4,35 +4,43 @@
 
 package org.chromium.components.autofill_assistant.infobox;
 
+import androidx.annotation.Nullable;
+
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.components.autofill_assistant.generic_ui.AssistantDrawable;
 
-/**
- * Java side equivalent of autofill_assistant::InfoBoxProto.
- */
+/** Java side equivalent of autofill_assistant::InfoBoxProto. */
 @JNINamespace("autofill_assistant")
 public class AssistantInfoBox {
-    private final String mImagePath;
+    @Nullable
+    private final AssistantDrawable mDrawable;
     private final String mExplanation;
+    private final boolean mUseIntrinsicDimensions;
 
-    public AssistantInfoBox(String imagePath, String explanation) {
-        this.mImagePath = imagePath;
+    public AssistantInfoBox(@Nullable AssistantDrawable drawable, String explanation,
+            boolean useIntrinsicDimensions) {
+        this.mDrawable = drawable;
         this.mExplanation = explanation;
+        this.mUseIntrinsicDimensions = useIntrinsicDimensions;
     }
 
-    public String getImagePath() {
-        return mImagePath;
+    public AssistantDrawable getDrawable() {
+        return mDrawable;
     }
 
     public String getExplanation() {
         return mExplanation;
     }
 
-    /**
-     * Create infobox with the given values.
-     */
+    public boolean getUseIntrinsicDimensions() {
+        return mUseIntrinsicDimensions;
+    }
+
+    /** Create infobox with the given values. */
     @CalledByNative
-    private static AssistantInfoBox create(String imagePath, String explanation) {
-        return new AssistantInfoBox(imagePath, explanation);
+    private static AssistantInfoBox create(@Nullable AssistantDrawable drawable, String explanation,
+            boolean useIntrinsicDimensions) {
+        return new AssistantInfoBox(drawable, explanation, useIntrinsicDimensions);
     }
 }
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java
index aec64ba..ef5858b4 100644
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java
@@ -62,6 +62,6 @@
 
     private boolean isEmpty(AssistantInfoBox infoBox) {
         return infoBox == null
-                || (infoBox.getImagePath().isEmpty() && infoBox.getExplanation().isEmpty());
+                || (infoBox.getDrawable() == null && infoBox.getExplanation().isEmpty());
     }
 }
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxViewBinder.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxViewBinder.java
index f855189c..c571c1c 100644
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxViewBinder.java
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxViewBinder.java
@@ -5,9 +5,9 @@
 package org.chromium.components.autofill_assistant.infobox;
 
 import android.content.Context;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.view.View;
+import android.widget.ImageView;
 import android.widget.TextView;
 
 import org.chromium.components.autofill_assistant.AssistantTextUtils;
@@ -24,13 +24,13 @@
 class AssistantInfoBoxViewBinder
         implements PropertyModelChangeProcessor.ViewBinder<AssistantInfoBoxModel,
                 AssistantInfoBoxViewBinder.ViewHolder, PropertyKey> {
-    /**
-     * A wrapper class that holds the different views of the info box.
-     */
+    /** A wrapper class that holds the different views of the info box. */
     static class ViewHolder {
+        final ImageView mImageView;
         final TextView mExplanationView;
 
         public ViewHolder(Context context, View infoBoxView) {
+            mImageView = infoBoxView.findViewById(R.id.info_box_image);
             mExplanationView = infoBoxView.findViewById(R.id.info_box_explanation);
         }
     }
@@ -43,10 +43,7 @@
         mContext = context;
         mImageFetcher = imageFetcher;
     }
-
-    /**
-     * Explicitly clean up.
-     */
+    /** Explicitly clean up. */
     public void destroy() {
         mImageFetcher.destroy();
         mImageFetcher = null;
@@ -72,18 +69,39 @@
         AssistantTextUtils.applyVisualAppearanceTags(
                 viewHolder.mExplanationView, explanation, null);
         viewHolder.mExplanationView.announceForAccessibility(viewHolder.mExplanationView.getText());
-        if (infoBox.getImagePath().isEmpty()) {
-            viewHolder.mExplanationView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
+        if (infoBox.getDrawable() == null) {
+            hideLegacyImage(viewHolder);
+            hideImageView(viewHolder);
         } else {
-            ImageFetcher.Params params = ImageFetcher.Params.create(
-                    infoBox.getImagePath(), ImageFetcher.ASSISTANT_INFO_BOX_UMA_CLIENT_NAME);
-            mImageFetcher.fetchImage(params, image -> {
+            infoBox.getDrawable().getDrawable(mContext, image -> {
                 if (image != null) {
-                    Drawable d = new BitmapDrawable(mContext.getResources(), image);
-                    viewHolder.mExplanationView.setCompoundDrawablesWithIntrinsicBounds(
-                            null, d, null, null);
+                    if (infoBox.getUseIntrinsicDimensions()) {
+                        showLegacyImage(viewHolder, image);
+                    } else {
+                        showImageView(viewHolder, image);
+                    }
                 }
             });
         }
     }
+
+    private void hideLegacyImage(ViewHolder viewHolder) {
+        viewHolder.mExplanationView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
+    }
+
+    private void showLegacyImage(ViewHolder viewHolder, Drawable image) {
+        hideImageView(viewHolder);
+        viewHolder.mExplanationView.setCompoundDrawablesWithIntrinsicBounds(
+                null, image, null, null);
+    }
+
+    private void hideImageView(ViewHolder viewHolder) {
+        viewHolder.mImageView.setVisibility(View.GONE);
+    }
+
+    private void showImageView(ViewHolder viewHolder, Drawable image) {
+        hideLegacyImage(viewHolder);
+        viewHolder.mImageView.setVisibility(View.VISIBLE);
+        viewHolder.mImageView.setImageDrawable(image);
+    }
 }
diff --git a/components/autofill_assistant/browser/android/generic_ui_nested_controller_android.cc b/components/autofill_assistant/browser/android/generic_ui_nested_controller_android.cc
index f17be27..8b5037d 100644
--- a/components/autofill_assistant/browser/android/generic_ui_nested_controller_android.cc
+++ b/components/autofill_assistant/browser/android/generic_ui_nested_controller_android.cc
@@ -267,7 +267,8 @@
           base::android::ConvertUTF8ToJavaString(
               env, proto.text_input_view().hint()),
           base::android::ConvertUTF8ToJavaString(
-              env, proto.text_input_view().model_identifier()));
+              env, proto.text_input_view().model_identifier()),
+          proto.text_input_view().focus_and_show_keyboard());
       break;
     }
     case ViewProto::kToggleButtonView:
diff --git a/components/autofill_assistant/browser/android/ui_controller_android.cc b/components/autofill_assistant/browser/android/ui_controller_android.cc
index e7f1e362..fb9a722 100644
--- a/components/autofill_assistant/browser/android/ui_controller_android.cc
+++ b/components/autofill_assistant/browser/android/ui_controller_android.cc
@@ -69,6 +69,7 @@
 namespace autofill_assistant {
 
 namespace {
+
 std::vector<float> ToFloatVector(const std::vector<RectF>& areas) {
   std::vector<float> flattened;
   for (const auto& rect : areas) {
@@ -1976,9 +1977,38 @@
   }
 
   const InfoBoxProto& proto = info_box->proto().info_box();
+  auto jcontext =
+      Java_AutofillAssistantUiController_getContext(env, java_object_);
+  absl::optional<DrawableProto> drawable_proto;
+  bool use_instrinsic_dimensions = false;
+  switch (proto.image_case()) {
+    case InfoBoxProto::ImageCase::kImagePath: {
+      if (!proto.image_path().empty()) {
+        drawable_proto.emplace();
+        auto* bitmap_proto = drawable_proto->mutable_bitmap();
+        bitmap_proto->set_url(proto.image_path());
+        bitmap_proto->set_use_instrinsic_dimensions(true);
+        use_instrinsic_dimensions = true;
+      }
+      break;
+    }
+    case InfoBoxProto::ImageCase::kDrawable: {
+      drawable_proto = proto.drawable();
+      break;
+    }
+    case InfoBoxProto::ImageCase::IMAGE_NOT_SET: {
+      break;
+    }
+  }
+  base::android::ScopedJavaLocalRef<jobject> jdrawable = nullptr;
+  if (drawable_proto.has_value()) {
+    jdrawable = ui_controller_android_utils::CreateJavaDrawable(
+        env, jcontext, *dependencies_, *drawable_proto,
+        execution_delegate_->GetUserModel());
+  }
   auto jinfo_box = Java_AssistantInfoBox_create(
-      env, ConvertUTF8ToJavaString(env, proto.image_path()),
-      ConvertUTF8ToJavaString(env, proto.explanation()));
+      env, jdrawable, ConvertUTF8ToJavaString(env, proto.explanation()),
+      use_instrinsic_dimensions);
   Java_AssistantInfoBoxModel_setInfoBox(env, jmodel, jinfo_box);
 }
 
diff --git a/components/autofill_assistant/browser/android/ui_controller_android_utils.cc b/components/autofill_assistant/browser/android/ui_controller_android_utils.cc
index ae134a5..88b4310e 100644
--- a/components/autofill_assistant/browser/android/ui_controller_android_utils.cc
+++ b/components/autofill_assistant/browser/android/ui_controller_android_utils.cc
@@ -16,6 +16,7 @@
 #include "components/autofill_assistant/android/jni_headers/AssistantChip_jni.h"
 #include "components/autofill_assistant/android/jni_headers/AssistantColor_jni.h"
 #include "components/autofill_assistant/android/jni_headers/AssistantDateTime_jni.h"
+#include "components/autofill_assistant/android/jni_headers/AssistantDeviceConfig_jni.h"
 #include "components/autofill_assistant/android/jni_headers/AssistantDialogButton_jni.h"
 #include "components/autofill_assistant/android/jni_headers/AssistantDimension_jni.h"
 #include "components/autofill_assistant/android/jni_headers/AssistantDrawable_jni.h"
@@ -43,6 +44,8 @@
 using ::base::android::ConvertUTF8ToJavaString;
 using ::base::android::JavaRef;
 
+constexpr char kNightModePrefix[] = "night-";
+
 DrawableIcon MapDrawableIcon(DrawableProto::Icon icon) {
   switch (icon) {
     case DrawableProto::DRAWABLE_ICON_UNDEFINED:
@@ -97,6 +100,81 @@
   }
 }
 
+const std::pair<std::string, std::string> RemoveDarkQualifier(
+    std::string resource_qualifier,
+    std::string url) {
+  if (resource_qualifier.rfind(kNightModePrefix, 0) == 0) {
+    resource_qualifier =
+        resource_qualifier.substr(std::string(kNightModePrefix).length());
+  }
+  return {resource_qualifier, url};
+}
+
+std::map<std::string, std::string> FilterConfigBasedOnDayNightSetting(
+    bool is_dark_mode_enabled,
+    const ConfigBasedUrlProto& url_config) {
+  std::map<std::string, std::string> daynight_specific_config;
+  for (auto config_entry : url_config.url()) {
+    std::string resource_qualifier = config_entry.first;
+    std::string url = config_entry.second;
+    bool dark_mode_qualified =
+        resource_qualifier.rfind(kNightModePrefix, 0) == 0;
+    if (is_dark_mode_enabled == dark_mode_qualified) {
+      daynight_specific_config.insert(
+          RemoveDarkQualifier(resource_qualifier, url));
+    }
+  }
+  std::map<std::string, std::string> dpi_url_config;
+  if (daynight_specific_config.empty()) {
+    for (auto config_entry : url_config.url()) {
+      daynight_specific_config.insert(
+          RemoveDarkQualifier(config_entry.first, config_entry.second));
+    }
+  }
+  return daynight_specific_config;
+}
+
+const std::string GetBitmapImageUrlBasedOnDeviceConfig(
+    JNIEnv* env,
+    const JavaRef<jobject>& jcontext,
+    const ConfigBasedUrlProto& url_config) {
+  bool is_dark_mode_enabled =
+      Java_AssistantDeviceConfig_isDarkModeEnabled(env, jcontext);
+  std::map<std::string, std::string> daynight_specific_config =
+      FilterConfigBasedOnDayNightSetting(is_dark_mode_enabled, url_config);
+
+  // Return image for the device pixel density. If not available, fallback to
+  // mdpi. Caller has to specify mdpi image.
+  std::string device_density = ConvertJavaStringToUTF8(
+      Java_AssistantDeviceConfig_getDevicePixelDensity(env, jcontext));
+  auto pos_it = daynight_specific_config.find(device_density);
+  if (pos_it != daynight_specific_config.end()) {
+    return pos_it->second;
+  }
+  if (daynight_specific_config.find("mdpi") == daynight_specific_config.end()) {
+    return "";
+  }
+  return daynight_specific_config.find("mdpi")->second;
+}
+
+const std::string GetBitmapImageUrl(JNIEnv* env,
+                                    const JavaRef<jobject>& jcontext,
+                                    const BitmapDrawableProto& bitmap) {
+  switch (bitmap.image_url_case()) {
+    case BitmapDrawableProto::ImageUrlCase::kUrl: {
+      return bitmap.url();
+    }
+    case BitmapDrawableProto::ImageUrlCase::kConfigBasedUrl: {
+      return GetBitmapImageUrlBasedOnDeviceConfig(env, jcontext,
+                                                  bitmap.config_based_url());
+    }
+    case BitmapDrawableProto::ImageUrlCase::IMAGE_URL_NOT_SET: {
+      VLOG(1) << "Image url not set in bitmap image request.";
+      return "";
+    }
+  }
+}
+
 }  // namespace
 
 base::android::ScopedJavaLocalRef<jobject> GetJavaColor(
@@ -189,14 +267,21 @@
           env, base::android::ConvertUTF8ToJavaString(
                    env, proto.resource_identifier()));
     case DrawableProto::kBitmap: {
-      int width_pixels = ui_controller_android_utils::GetPixelSizeOrDefault(
-          env, jcontext, proto.bitmap().width(), 0);
-      int height_pixels = ui_controller_android_utils::GetPixelSizeOrDefault(
-          env, jcontext, proto.bitmap().height(), 0);
-      return Java_AssistantDrawable_createFromUrl(
-          env, dependencies.CreateImageFetcher(),
-          base::android::ConvertUTF8ToJavaString(env, proto.bitmap().url()),
-          width_pixels, height_pixels);
+      std::string url = GetBitmapImageUrl(env, jcontext, proto.bitmap());
+      if (proto.bitmap().use_instrinsic_dimensions()) {
+        return Java_AssistantDrawable_createFromUrlWithIntrinsicDimensions(
+            env, dependencies.CreateImageFetcher(),
+            base::android::ConvertUTF8ToJavaString(env, url));
+      } else {
+        int width_pixels = ui_controller_android_utils::GetPixelSizeOrDefault(
+            env, jcontext, proto.bitmap().width(), 0);
+        int height_pixels = ui_controller_android_utils::GetPixelSizeOrDefault(
+            env, jcontext, proto.bitmap().height(), 0);
+        return Java_AssistantDrawable_createFromUrl(
+            env, dependencies.CreateImageFetcher(),
+            base::android::ConvertUTF8ToJavaString(env, url), width_pixels,
+            height_pixels);
+      }
     }
     case DrawableProto::kShape: {
       switch (proto.shape().shape_case()) {
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto
index b9a67abc..cab9551f 100644
--- a/components/autofill_assistant/browser/service.proto
+++ b/components/autofill_assistant/browser/service.proto
@@ -3032,9 +3032,13 @@
 }
 
 message InfoBoxProto {
-  // Optional path to an image. Ok tick used if not set.
-  optional string image_path = 1;
-
+  oneof image {
+    // Optional path to an image.
+    // This is deprecated and will be removed in M108.
+    string image_path = 1;
+    // Drawable shown in a separate ImageView above TextView.
+    DrawableProto drawable = 4;
+  }
   // The explanation to show in the box. Not setting this field will clear an
   // existing info box.
   optional string explanation = 2;
diff --git a/components/autofill_assistant/browser/view_layout.proto b/components/autofill_assistant/browser/view_layout.proto
index f549607..5c6138e9 100644
--- a/components/autofill_assistant/browser/view_layout.proto
+++ b/components/autofill_assistant/browser/view_layout.proto
@@ -67,10 +67,18 @@
   optional ColorProto stroke_color = 4;
 }
 
+message ConfigBasedUrlProto {
+  map<string, string> url = 1;
+}
+
 message BitmapDrawableProto {
-  optional string url = 1;
+  oneof image_url {
+    string url = 1;
+    ConfigBasedUrlProto config_based_url = 4;
+  }
   optional ClientDimensionProto width = 2;
   optional ClientDimensionProto height = 3;
+  optional bool use_instrinsic_dimensions = 5;
 }
 
 message FaviconDrawableProto {
@@ -288,6 +296,8 @@
   // Both input and output. The model identifier containing this view's text.
   // Should point to a single string value.
   optional string model_identifier = 3;
+  // A flag to autofocus the input text box and show keyboard.
+  optional bool focus_and_show_keyboard = 4;
 }
 
 // A generic read-only popup message.
diff --git a/components/autofill_assistant/guided_browsing/android/BUILD.gn b/components/autofill_assistant/guided_browsing/android/BUILD.gn
index 6367779..511e067 100644
--- a/components/autofill_assistant/guided_browsing/android/BUILD.gn
+++ b/components/autofill_assistant/guided_browsing/android/BUILD.gn
@@ -15,6 +15,7 @@
     "//base:base_java",
     "//content/public/android:content_java",
     "//third_party/androidx:androidx_appcompat_appcompat_java",
+    "//third_party/androidx:androidx_core_core_java",
     "//ui/android:ui_java",
   ]
 
@@ -30,6 +31,12 @@
     "java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/camera_scan/AssistantQrCodeCameraScanDialog.java",
     "java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/camera_scan/AssistantQrCodeCameraScanModel.java",
     "java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/camera_scan/AssistantQrCodeCameraScanView.java",
+    "java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerBinder.java",
+    "java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerCallbacks.java",
+    "java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerCoordinator.java",
+    "java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerDialog.java",
+    "java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerModel.java",
+    "java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerView.java",
     "java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/permission/AssistantQrCodePermissionBinder.java",
     "java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/permission/AssistantQrCodePermissionCallback.java",
     "java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/permission/AssistantQrCodePermissionCoordinator.java",
@@ -44,7 +51,8 @@
 
 android_resources("java_resources") {
   sources = [
-    "java/res/layout/autofill_assistant_qr_code_camera_scan_dialog.xml",
+    "java/res/drawable/folder_img.xml",
+    "java/res/layout/autofill_assistant_qr_code_dialog.xml",
     "java/res/layout/autofill_assistant_qr_code_permission_layout.xml",
     "java/res/values-v17/dimens.xml",
   ]
diff --git a/components/autofill_assistant/guided_browsing/android/java/res/drawable/folder_img.xml b/components/autofill_assistant/guided_browsing/android/java/res/drawable/folder_img.xml
new file mode 100644
index 0000000..46c31070
--- /dev/null
+++ b/components/autofill_assistant/guided_browsing/android/java/res/drawable/folder_img.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2022 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:height="104dp"
+    android:tint="@macro/default_icon_color_accent1"
+    android:viewportHeight="24"
+    android:viewportWidth="24"
+    android:width="104dp"
+    tools:ignore="UnusedResources">
+  <path android:fillColor="@macro/default_icon_color_accent1" android:pathData="M10,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8c0,-1.1 -0.9,-2 -2,-2h-8l-2,-2z"/>
+</vector>
\ No newline at end of file
diff --git a/components/autofill_assistant/guided_browsing/android/java/res/layout/autofill_assistant_qr_code_camera_scan_dialog.xml b/components/autofill_assistant/guided_browsing/android/java/res/layout/autofill_assistant_qr_code_dialog.xml
similarity index 100%
rename from components/autofill_assistant/guided_browsing/android/java/res/layout/autofill_assistant_qr_code_camera_scan_dialog.xml
rename to components/autofill_assistant/guided_browsing/android/java/res/layout/autofill_assistant_qr_code_dialog.xml
diff --git a/components/autofill_assistant/guided_browsing/android/java/res/layout/autofill_assistant_qr_code_permission_layout.xml b/components/autofill_assistant/guided_browsing/android/java/res/layout/autofill_assistant_qr_code_permission_layout.xml
index 338edd26..29fb308 100644
--- a/components/autofill_assistant/guided_browsing/android/java/res/layout/autofill_assistant_qr_code_permission_layout.xml
+++ b/components/autofill_assistant/guided_browsing/android/java/res/layout/autofill_assistant_qr_code_permission_layout.xml
@@ -20,7 +20,7 @@
         android:importantForAccessibility="no"/>
 
     <org.chromium.ui.widget.ChromeImageView
-        android:id="@+id/camera_icon"
+        android:id="@+id/permission_image"
         android:layout_marginTop="112dp"
         android:layout_gravity="center_horizontal"
         android:layout_width="150dp"
diff --git a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/AssistantQrCodeController.java b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/AssistantQrCodeController.java
index c31a742..44a6e52 100644
--- a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/AssistantQrCodeController.java
+++ b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/AssistantQrCodeController.java
@@ -8,14 +8,23 @@
 
 import org.chromium.components.autofill_assistant.guided_browsing.qr_code.camera_scan.AssistantQrCodeCameraScanDialog;
 import org.chromium.components.autofill_assistant.guided_browsing.qr_code.camera_scan.AssistantQrCodeCameraScanModel;
+import org.chromium.components.autofill_assistant.guided_browsing.qr_code.image_picker.AssistantQrCodeImagePickerDialog;
+import org.chromium.components.autofill_assistant.guided_browsing.qr_code.image_picker.AssistantQrCodeImagePickerModel;
 import org.chromium.ui.base.WindowAndroid;
 
 /** Controller to expose QR Code Scan functionality. */
 public class AssistantQrCodeController {
-    /** Prompts the user for QR Code Scanning. */
-    public static void promptQrCodeScan(
+    /** Prompts the user for QR Code Scanning via Camera Preview. */
+    public static void promptQrCodeCameraScan(
             Activity activity, WindowAndroid windowAndroid, AssistantQrCodeCameraScanModel model) {
         AssistantQrCodeCameraScanDialog.newInstance(activity, windowAndroid, model)
                 .show(activity.getFragmentManager(), /* tag= */ null);
     }
-}
+
+    /** Prompts the user for QR Code Scanning via Image Picker. */
+    public static void promptQrCodeImagePicker(
+            Activity activity, WindowAndroid windowAndroid, AssistantQrCodeImagePickerModel model) {
+        AssistantQrCodeImagePickerDialog.newInstance(activity, windowAndroid, model)
+                .show(activity.getFragmentManager(), /* tag= */ null);
+    }
+}
\ No newline at end of file
diff --git a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/AssistantQrCodeDelegate.java b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/AssistantQrCodeDelegate.java
index 01451fe..41b5744 100644
--- a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/AssistantQrCodeDelegate.java
+++ b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/AssistantQrCodeDelegate.java
@@ -12,6 +12,9 @@
     /** Called when QR Code Scan is cancelled. */
     public void onScanCancelled();
 
+    /** Called when QR Code Scan does not produce any valid output. */
+    public void onScanFailure();
+
     /** Called when QR Code Scan fails because of Camera Error. */
     public void onCameraError();
 }
diff --git a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/camera_scan/AssistantQrCodeCameraScanCoordinator.java b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/camera_scan/AssistantQrCodeCameraScanCoordinator.java
index a2aca12..c800ada 100644
--- a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/camera_scan/AssistantQrCodeCameraScanCoordinator.java
+++ b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/camera_scan/AssistantQrCodeCameraScanCoordinator.java
@@ -10,7 +10,6 @@
 import org.chromium.components.autofill_assistant.guided_browsing.qr_code.AssistantQrCodeDelegate;
 import org.chromium.components.autofill_assistant.guided_browsing.qr_code.permission.AssistantQrCodePermissionCallback;
 import org.chromium.components.autofill_assistant.guided_browsing.qr_code.permission.AssistantQrCodePermissionCoordinator;
-import org.chromium.components.autofill_assistant.guided_browsing.qr_code.permission.AssistantQrCodePermissionModel;
 import org.chromium.components.autofill_assistant.guided_browsing.qr_code.permission.AssistantQrCodePermissionType;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
@@ -46,11 +45,8 @@
         mWindowAndroid = windowAndroid;
         mCameraScanModel = cameraScanModel;
 
-        AssistantQrCodePermissionModel permissionModel =
-                mCameraScanModel.getCameraPermissionModel();
-
         mPermissionCoordinator = new AssistantQrCodePermissionCoordinator(mContext, mWindowAndroid,
-                permissionModel, AssistantQrCodePermissionType.CAMERA,
+                mCameraScanModel.getCameraPermissionModel(), AssistantQrCodePermissionType.CAMERA,
                 new AssistantQrCodePermissionCallback() {
                     @Override
                     public void onPermissionsChanged(boolean hasPermission) {
@@ -60,13 +56,11 @@
                     }
                 });
 
-        View permissionView = mPermissionCoordinator.getView();
-
         AssistantQrCodeCameraCallbacks cameraCallbacks =
                 new AssistantQrCodeCameraCallbacks(context, cameraScanModel, dialogCallbacks);
-        mCameraScanView = new AssistantQrCodeCameraScanView(context, permissionView,
-                cameraCallbacks::onPreviewFrame, cameraCallbacks::onError,
-                new AssistantQrCodeCameraScanView.Delegate() {
+        mCameraScanView = new AssistantQrCodeCameraScanView(context,
+                mPermissionCoordinator.getView(), cameraCallbacks::onPreviewFrame,
+                cameraCallbacks::onError, new AssistantQrCodeCameraScanView.Delegate() {
                     @Override
                     public void onScanCancelled() {
                         AssistantQrCodeDelegate delegate =
@@ -103,4 +97,4 @@
         mViewHolder = null;
         mPermissionCoordinator.destroy();
     }
-}
\ No newline at end of file
+}
diff --git a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/camera_scan/AssistantQrCodeCameraScanView.java b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/camera_scan/AssistantQrCodeCameraScanView.java
index 50ac2a73..a44c794 100644
--- a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/camera_scan/AssistantQrCodeCameraScanView.java
+++ b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/camera_scan/AssistantQrCodeCameraScanView.java
@@ -69,7 +69,7 @@
      */
     private View createRootView() {
         View dialogView = LayoutUtils.createInflater(mContext).inflate(
-                R.layout.autofill_assistant_qr_code_camera_scan_dialog, /* root= */ null);
+                R.layout.autofill_assistant_qr_code_dialog, /* root= */ null);
 
         ChromeImageButton closeButton = dialogView.findViewById(R.id.close_button);
         closeButton.setOnClickListener(v -> { mViewDelegate.onScanCancelled(); });
@@ -161,4 +161,4 @@
             mCameraPreview = null;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerBinder.java b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerBinder.java
new file mode 100644
index 0000000..c061f58
--- /dev/null
+++ b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerBinder.java
@@ -0,0 +1,47 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.autofill_assistant.guided_browsing.qr_code.image_picker;
+
+import android.widget.TextView;
+
+import org.chromium.components.autofill_assistant.guided_browsing.R;
+import org.chromium.ui.modelutil.PropertyKey;
+import org.chromium.ui.modelutil.PropertyModelChangeProcessor.ViewBinder;
+
+/**
+ * This class is responsible for pushing updates to the Autofill Assistant UI for QR Code Scanning
+ * via Image Picker. These updates are pulled from the {@link AssistantQrCodeImagePickerModel} when
+ * a notification of an update is received.
+ */
+class AssistantQrCodeImagePickerBinder implements ViewBinder<AssistantQrCodeImagePickerModel,
+        AssistantQrCodeImagePickerBinder.ViewHolder, PropertyKey> {
+    /**
+     * A wrapper class that holds the different views of the QR Code Image Picker UI.
+     */
+    static class ViewHolder {
+        private final AssistantQrCodeImagePickerView mImagePickerView;
+        private final TextView mTitleView;
+
+        public ViewHolder(AssistantQrCodeImagePickerView imagePickerView) {
+            mImagePickerView = imagePickerView;
+            mTitleView = imagePickerView.getRootView().findViewById(R.id.toolbar_title);
+        }
+    }
+
+    @Override
+    public void bind(
+            AssistantQrCodeImagePickerModel model, ViewHolder viewHolder, PropertyKey propertyKey) {
+        if (propertyKey == AssistantQrCodeImagePickerModel.DELEGATE) {
+            // Do nothing. Subsequent notifications will be sent to the new delegate.
+        } else if (propertyKey == AssistantQrCodeImagePickerModel.IS_ON_FOREGROUND) {
+            viewHolder.mImagePickerView.onForegroundChanged(
+                    model.get(AssistantQrCodeImagePickerModel.IS_ON_FOREGROUND));
+        } else if (propertyKey == AssistantQrCodeImagePickerModel.TOOLBAR_TITLE) {
+            viewHolder.mTitleView.setText(model.get(AssistantQrCodeImagePickerModel.TOOLBAR_TITLE));
+        } else {
+            assert false : "Unhandled property detected in AssistantQrCodeImagePickerBinder!";
+        }
+    }
+}
diff --git a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerCallbacks.java b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerCallbacks.java
new file mode 100644
index 0000000..0050d6132
--- /dev/null
+++ b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerCallbacks.java
@@ -0,0 +1,150 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.autofill_assistant.guided_browsing.qr_code.image_picker;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.provider.MediaStore;
+import android.util.SparseArray;
+
+import com.google.android.gms.vision.Frame;
+import com.google.android.gms.vision.barcode.Barcode;
+import com.google.android.gms.vision.barcode.BarcodeDetector;
+
+import org.chromium.base.task.AsyncTask;
+import org.chromium.base.task.PostTask;
+import org.chromium.components.autofill_assistant.guided_browsing.qr_code.AssistantQrCodeDelegate;
+import org.chromium.content_public.browser.UiThreadTaskTraits;
+import org.chromium.ui.base.WindowAndroid.IntentCallback;
+
+import java.io.IOException;
+
+/**
+ * AssistantQrCodeImagePickerCallbacks provides the callbacks needed for QR scanning via image
+ * picker.
+ */
+public class AssistantQrCodeImagePickerCallbacks implements IntentCallback {
+    private final Context mContext;
+    private final AssistantQrCodeImagePickerModel mImagePickerModel;
+    private final AssistantQrCodeImagePickerCoordinator.DialogCallbacks mDialogCallbacks;
+
+    private BarcodeDetector mDetector;
+
+    /**
+     * The AssistantQrCodeImagePickerCallbacks constructor.
+     */
+    AssistantQrCodeImagePickerCallbacks(Context context,
+            AssistantQrCodeImagePickerModel imagePickerModel,
+            AssistantQrCodeImagePickerCoordinator.DialogCallbacks dialogCallbacks) {
+        mContext = context;
+        mImagePickerModel = imagePickerModel;
+        mDialogCallbacks = dialogCallbacks;
+
+        // Set detector to null until it gets initialized asynchronously.
+        mDetector = null;
+        initBarcodeDetectorAsync();
+    }
+
+    /**
+     * Callback when the image picker intent finishes. Inspects the image for any QR Code. In case
+     * of successful QR Code detection, sends the output value using the |AssistantQrCodeDelegate|
+     * and dismisses the QR Code Image Picker dialog UI.
+     */
+    @Override
+    public void onIntentCompleted(int resultCode, Intent data) {
+        // When the user presses back button, the resultCode will not be RESULT_OK.
+        if (resultCode != Activity.RESULT_OK) {
+            onQrCodeScanCancel();
+            return;
+        }
+        if (data == null || mDetector == null) {
+            onQrCodeScanFailure();
+            return;
+        }
+
+        Uri imageUri = data.getData();
+        try {
+            Bitmap bitmap =
+                    MediaStore.Images.Media.getBitmap(mContext.getContentResolver(), imageUri);
+            Frame frame = new Frame.Builder().setBitmap(bitmap).build();
+            SparseArray<Barcode> barcodes = mDetector.detect(frame);
+            if (barcodes.size() == 0 || barcodes.valueAt(0).rawValue.isEmpty()) {
+                onQrCodeScanFailure();
+                return;
+            }
+            Barcode firstCode = barcodes.valueAt(0);
+            PostTask.postTask(UiThreadTaskTraits.DEFAULT, new Runnable() {
+                @Override
+                public void run() {
+                    AssistantQrCodeDelegate delegate =
+                            mImagePickerModel.get(AssistantQrCodeImagePickerModel.DELEGATE);
+                    if (delegate != null) {
+                        delegate.onScanResult(firstCode.rawValue);
+                    }
+                }
+            });
+            // Dismiss the QR Code scan UI dialog.
+            mDialogCallbacks.dismiss();
+        } catch (IOException e) {
+            onQrCodeScanFailure();
+            return;
+        }
+    }
+
+    /**
+     * Sends back the CANCEL response using the |AssistantQrCodeDelegate| and dismisses the QR Code
+     * Image Picker dialog UI.
+     */
+    private void onQrCodeScanCancel() {
+        PostTask.postTask(UiThreadTaskTraits.DEFAULT, new Runnable() {
+            @Override
+            public void run() {
+                AssistantQrCodeDelegate delegate =
+                        mImagePickerModel.get(AssistantQrCodeImagePickerModel.DELEGATE);
+                if (delegate != null) {
+                    delegate.onScanCancelled();
+                }
+            }
+        });
+        // Dismiss the QR Code scan UI dialog.
+        mDialogCallbacks.dismiss();
+    }
+
+    /**
+     * Sends back the FAILURE response using the |AssistantQrCodeDelegate| and dismisses the QR
+     * Code Image Picker dialog UI.
+     */
+    private void onQrCodeScanFailure() {
+        PostTask.postTask(UiThreadTaskTraits.DEFAULT, new Runnable() {
+            @Override
+            public void run() {
+                AssistantQrCodeDelegate delegate =
+                        mImagePickerModel.get(AssistantQrCodeImagePickerModel.DELEGATE);
+                if (delegate != null) {
+                    delegate.onScanFailure();
+                }
+            }
+        });
+        // Dismiss the QR Code scan UI dialog.
+        mDialogCallbacks.dismiss();
+    }
+
+    private void initBarcodeDetectorAsync() {
+        new AsyncTask<BarcodeDetector>() {
+            @Override
+            protected BarcodeDetector doInBackground() {
+                return new BarcodeDetector.Builder(mContext).build();
+            }
+
+            @Override
+            protected void onPostExecute(BarcodeDetector detector) {
+                mDetector = detector;
+            }
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+    }
+}
diff --git a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerCoordinator.java b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerCoordinator.java
new file mode 100644
index 0000000..f8347589
--- /dev/null
+++ b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerCoordinator.java
@@ -0,0 +1,112 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.autofill_assistant.guided_browsing.qr_code.image_picker;
+
+import android.content.Context;
+import android.view.View;
+
+import org.chromium.base.BuildInfo;
+import org.chromium.components.autofill_assistant.guided_browsing.qr_code.AssistantQrCodeDelegate;
+import org.chromium.components.autofill_assistant.guided_browsing.qr_code.permission.AssistantQrCodePermissionCallback;
+import org.chromium.components.autofill_assistant.guided_browsing.qr_code.permission.AssistantQrCodePermissionCoordinator;
+import org.chromium.components.autofill_assistant.guided_browsing.qr_code.permission.AssistantQrCodePermissionType;
+import org.chromium.ui.base.WindowAndroid;
+import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
+
+/**
+ * Creates and represents the QR Code image picker UI.
+ */
+public class AssistantQrCodeImagePickerCoordinator {
+    /**
+     * Callbacks to parent dialog.
+     */
+    public interface DialogCallbacks {
+        /**
+         * Called when component UI is to be dismissed.
+         */
+        void dismiss();
+    }
+
+    private final Context mContext;
+    private final WindowAndroid mWindowAndroid;
+    private final AssistantQrCodeImagePickerModel mImagePickerModel;
+    private final AssistantQrCodeImagePickerView mImagePickerView;
+    private AssistantQrCodeImagePickerBinder.ViewHolder mViewHolder;
+    private final AssistantQrCodePermissionCoordinator mPermissionCoordinator;
+
+    /**
+     * The AssistantQrCodeImagePickerCoordinator constructor.
+     */
+    public AssistantQrCodeImagePickerCoordinator(Context context, WindowAndroid windowAndroid,
+            AssistantQrCodeImagePickerModel imagePickerModel,
+            AssistantQrCodeImagePickerCoordinator.DialogCallbacks dialogCallbacks) {
+        mContext = context;
+        mWindowAndroid = windowAndroid;
+        mImagePickerModel = imagePickerModel;
+
+        mPermissionCoordinator = new AssistantQrCodePermissionCoordinator(mContext, mWindowAndroid,
+                mImagePickerModel.getReadImagesPermissionModel(),
+                getPermissionTypeForReadingImages(), new AssistantQrCodePermissionCallback() {
+                    @Override
+                    public void onPermissionsChanged(boolean hasPermission) {
+                        if (mImagePickerView != null) {
+                            mImagePickerView.onPermissionsChanged(hasPermission);
+                        }
+                    }
+                });
+
+        AssistantQrCodeImagePickerCallbacks imagePickerCallbacks =
+                new AssistantQrCodeImagePickerCallbacks(context, imagePickerModel, dialogCallbacks);
+        mImagePickerView = new AssistantQrCodeImagePickerView(context, mWindowAndroid,
+                mPermissionCoordinator.getView(), imagePickerCallbacks::onIntentCompleted,
+                new AssistantQrCodeImagePickerView.Delegate() {
+                    @Override
+                    public void onScanCancelled() {
+                        AssistantQrCodeDelegate delegate =
+                                imagePickerModel.get(AssistantQrCodeImagePickerModel.DELEGATE);
+                        if (delegate != null) {
+                            delegate.onScanCancelled();
+                        }
+                        dialogCallbacks.dismiss();
+                    }
+                });
+
+        mViewHolder = new AssistantQrCodeImagePickerBinder.ViewHolder(mImagePickerView);
+        PropertyModelChangeProcessor.create(
+                imagePickerModel, mViewHolder, new AssistantQrCodeImagePickerBinder());
+        mPermissionCoordinator.updatePermissionSettings();
+    }
+
+    public View getView() {
+        return mImagePickerView.getRootView();
+    }
+
+    public void resume() {
+        mPermissionCoordinator.updatePermissionSettings();
+        mImagePickerModel.set(AssistantQrCodeImagePickerModel.IS_ON_FOREGROUND, true);
+    }
+
+    public void pause() {
+        mImagePickerModel.set(AssistantQrCodeImagePickerModel.IS_ON_FOREGROUND, false);
+    }
+
+    public void destroy() {
+        // Explicitly clean up view holder.
+        mViewHolder = null;
+        mPermissionCoordinator.destroy();
+    }
+
+    /**
+     * Returns permission type for reading images based on android version.
+     */
+    private AssistantQrCodePermissionType getPermissionTypeForReadingImages() {
+        if (BuildInfo.isAtLeastT()) {
+            // |READ_MEDIA_IMAGES| is to be used from API Version |T|
+            // https://developer.android.com/reference/android/Manifest.permission#READ_MEDIA_IMAGES
+            return AssistantQrCodePermissionType.READ_MEDIA_IMAGES;
+        }
+        return AssistantQrCodePermissionType.READ_EXTERNAL_STORAGE;
+    }
+}
diff --git a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerDialog.java b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerDialog.java
new file mode 100644
index 0000000..4b9d84cd
--- /dev/null
+++ b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerDialog.java
@@ -0,0 +1,78 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.autofill_assistant.guided_browsing.qr_code.image_picker;
+
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.appcompat.app.AlertDialog;
+
+import org.chromium.components.autofill_assistant.guided_browsing.R;
+import org.chromium.ui.base.WindowAndroid;
+
+/**
+ * Main Dialog Fragment to trigger QR Code Scanning via Image Picker.
+ */
+public class AssistantQrCodeImagePickerDialog extends DialogFragment {
+    private Context mContext;
+    private WindowAndroid mWindowAndroid;
+    private AssistantQrCodeImagePickerModel mImagePickerModel;
+    private AssistantQrCodeImagePickerCoordinator mImagePickerCoordinator;
+
+    /**
+     * Create a new instance of {@link AssistantQrCodeImagePickerDialog}.
+     */
+    public static AssistantQrCodeImagePickerDialog newInstance(Context context,
+            WindowAndroid windowAndroid, AssistantQrCodeImagePickerModel imagePickerModel) {
+        AssistantQrCodeImagePickerDialog assistantQrCodeImagePickerDialog =
+                new AssistantQrCodeImagePickerDialog();
+        assistantQrCodeImagePickerDialog.setContext(context);
+        assistantQrCodeImagePickerDialog.setWindowAndroid(windowAndroid);
+        assistantQrCodeImagePickerDialog.setImagePickerModel(imagePickerModel);
+        return assistantQrCodeImagePickerDialog;
+    }
+
+    public void setContext(Context context) {
+        mContext = context;
+    }
+
+    public void setWindowAndroid(WindowAndroid windowAndroid) {
+        mWindowAndroid = windowAndroid;
+    }
+
+    public void setImagePickerModel(AssistantQrCodeImagePickerModel imagePickerModel) {
+        mImagePickerModel = imagePickerModel;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        mImagePickerCoordinator = new AssistantQrCodeImagePickerCoordinator(
+                mContext, mWindowAndroid, mImagePickerModel, this::dismiss);
+        AlertDialog.Builder builder =
+                new AlertDialog.Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_Fullscreen);
+        builder.setView(mImagePickerCoordinator.getView());
+        return builder.create();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        mImagePickerCoordinator.resume();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        mImagePickerCoordinator.pause();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mImagePickerCoordinator.destroy();
+    }
+}
diff --git a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerModel.java b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerModel.java
new file mode 100644
index 0000000..f5110d88
--- /dev/null
+++ b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerModel.java
@@ -0,0 +1,64 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.autofill_assistant.guided_browsing.qr_code.image_picker;
+
+import org.chromium.components.autofill_assistant.guided_browsing.qr_code.AssistantQrCodeDelegate;
+import org.chromium.components.autofill_assistant.guided_browsing.qr_code.permission.AssistantQrCodePermissionModel;
+import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey;
+
+/**
+ * State for the QR Code Image Picker UI.
+ */
+public class AssistantQrCodeImagePickerModel extends PropertyModel {
+    /** Assistant QR Code delegate. */
+    static final WritableObjectPropertyKey<AssistantQrCodeDelegate> DELEGATE =
+            new WritableObjectPropertyKey<>();
+
+    /** Is the application in foreground. */
+    static final WritableBooleanPropertyKey IS_ON_FOREGROUND = new WritableBooleanPropertyKey();
+
+    /** Image Picker Toolbar Title. */
+    static final WritableObjectPropertyKey<String> TOOLBAR_TITLE =
+            new WritableObjectPropertyKey<>();
+
+    private final AssistantQrCodePermissionModel mPermissionModel;
+
+    /**
+     * The AssistantQrCodeImagePickerModel constructor.
+     */
+    public AssistantQrCodeImagePickerModel() {
+        super(DELEGATE, IS_ON_FOREGROUND, TOOLBAR_TITLE);
+        mPermissionModel = new AssistantQrCodePermissionModel();
+    }
+
+    AssistantQrCodePermissionModel getReadImagesPermissionModel() {
+        return mPermissionModel;
+    }
+
+    public void setDelegate(AssistantQrCodeDelegate delegate) {
+        set(DELEGATE, delegate);
+    }
+
+    public void setToolbarTitle(String text) {
+        set(TOOLBAR_TITLE, text);
+    }
+
+    public void setPermissionText(String text) {
+        mPermissionModel.setPermissionText(text);
+    }
+
+    public void setPermissionButtonText(String text) {
+        mPermissionModel.setPermissionButtonText(text);
+    }
+
+    public void setOpenSettingsText(String text) {
+        mPermissionModel.setOpenSettingsText(text);
+    }
+
+    public void setOpenSettingsButtonText(String text) {
+        mPermissionModel.setOpenSettingsButtonText(text);
+    }
+}
diff --git a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerView.java b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerView.java
new file mode 100644
index 0000000..bd62383c
--- /dev/null
+++ b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/image_picker/AssistantQrCodeImagePickerView.java
@@ -0,0 +1,143 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.autofill_assistant.guided_browsing.qr_code.image_picker;
+
+import android.content.Context;
+import android.content.Intent;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import org.chromium.components.autofill_assistant.guided_browsing.LayoutUtils;
+import org.chromium.components.autofill_assistant.guided_browsing.R;
+import org.chromium.ui.base.WindowAndroid;
+import org.chromium.ui.base.WindowAndroid.IntentCallback;
+import org.chromium.ui.widget.ChromeImageButton;
+
+/**
+ * Manages the Android View representing the QR Code Image Picker panel. It manages between showing
+ * the permission view and triggering android image picker based on the permissions.
+ */
+class AssistantQrCodeImagePickerView {
+    /** Interface used to delegate various user interactions to the coordinator. */
+    public interface Delegate {
+        /** Called when user cancels the QR Code Scanning */
+        void onScanCancelled();
+    }
+
+    private static final String IMAGE_TYPE = "image";
+    private final Context mContext;
+    private final AssistantQrCodeImagePickerView.Delegate mViewDelegate;
+    private final IntentCallback mImagePickerCallback;
+    private final WindowAndroid mWindowAndroid;
+
+    private final View mRootView;
+    // Will be used to update the main body of the view based on state.
+    private final FrameLayout mBodyView;
+    private final View mReadImagesPermissionView;
+
+    private boolean mHasReadImagesPermission;
+    private boolean mIsOnForeground;
+
+    /**
+     * The AssistantQrCodeImagePickerView constructor.
+     */
+    AssistantQrCodeImagePickerView(Context context, WindowAndroid windowAndroid,
+            View readImagesPermissionView, IntentCallback imagePickerCallback,
+            AssistantQrCodeImagePickerView.Delegate delegate) {
+        mContext = context;
+        mViewDelegate = delegate;
+        mWindowAndroid = windowAndroid;
+        mImagePickerCallback = imagePickerCallback;
+
+        mBodyView = new FrameLayout(context);
+        mRootView = createRootView();
+        mReadImagesPermissionView = readImagesPermissionView;
+    }
+
+    View getRootView() {
+        return mRootView;
+    }
+
+    /**
+     * Updates the state of the view based on the updated value of |isOnForeground|.
+     *
+     * @param isOnForeground Indicates whether this component UI is currently on foreground.
+     */
+    void onForegroundChanged(Boolean isOnForeground) {
+        mIsOnForeground = isOnForeground;
+        if (mIsOnForeground) {
+            displayUpdatedView();
+        }
+    }
+
+    /**
+     * Updates the state of the view based on the updated value of |hasReadImagesPermission|.
+     *
+     * @param hasReadImagesPermission Indicates whether this component UI has permission to read
+     *        images or not.
+     */
+    void onPermissionsChanged(boolean hasReadImagesPermission) {
+        mHasReadImagesPermission = hasReadImagesPermission;
+        displayUpdatedView();
+    }
+
+    /**
+     * Creates the root view for the QR Code Image Picker Dialog.
+     */
+    private View createRootView() {
+        View dialogView = LayoutUtils.createInflater(mContext).inflate(
+                R.layout.autofill_assistant_qr_code_dialog, /* root= */ null);
+
+        ChromeImageButton closeButton = dialogView.findViewById(R.id.close_button);
+        closeButton.setOnClickListener(v -> { mViewDelegate.onScanCancelled(); });
+
+        FrameLayout layout = dialogView.findViewById(R.id.qr_code_view);
+        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
+                FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
+        layout.addView(mBodyView, params);
+
+        return dialogView;
+    }
+
+    /**
+     * Update the view based on various state parameters:
+     * - app is in the foreground
+     * - user has given permission to read images.
+     * - user can be prompted for permission to read images.
+     */
+    private void displayUpdatedView() {
+        // The scan tab is not in the foreground so don't do any rendering.
+        if (!mIsOnForeground) {
+            return;
+        }
+
+        if (mHasReadImagesPermission) {
+            openAndroidImagePicker();
+        } else {
+            displayReadImagesPermissionView();
+        }
+    }
+
+    /**
+     * Opens the android image picker. Caller should check that we already have the read images
+     * permissions.
+     */
+    private void openAndroidImagePicker() {
+        mBodyView.removeAllViews();
+        Intent openAndroidImagePickerIntent = new Intent(Intent.ACTION_PICK);
+        openAndroidImagePickerIntent.setType(IMAGE_TYPE + "/*");
+        mWindowAndroid.showIntent(
+                openAndroidImagePickerIntent, mImagePickerCallback, R.string.low_memory_error);
+    }
+
+    /**
+     * Displays the permission dialog. Caller should check that the user can be prompted and hasn't
+     * permanently denied permission.
+     */
+    private void displayReadImagesPermissionView() {
+        mBodyView.removeAllViews();
+        mBodyView.addView(mReadImagesPermissionView);
+    }
+}
diff --git a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/permission/AssistantQrCodePermissionCoordinator.java b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/permission/AssistantQrCodePermissionCoordinator.java
index 6f3de91..84b1fba 100644
--- a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/permission/AssistantQrCodePermissionCoordinator.java
+++ b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/permission/AssistantQrCodePermissionCoordinator.java
@@ -38,7 +38,7 @@
         mRequiredPermission = requiredPermission;
 
         mPermissionView = new AssistantQrCodePermissionView(
-                context, new AssistantQrCodePermissionView.Delegate() {
+                context, requiredPermission, new AssistantQrCodePermissionView.Delegate() {
                     @Override
                     public void promptForPermission() {
                         AssistantQrCodePermissionUtils.promptForPermission(
@@ -83,4 +83,4 @@
         // Clean up view holder.
         mViewHolder = null;
     }
-}
\ No newline at end of file
+}
diff --git a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/permission/AssistantQrCodePermissionType.java b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/permission/AssistantQrCodePermissionType.java
index 70400a52..2941d42f 100644
--- a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/permission/AssistantQrCodePermissionType.java
+++ b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/permission/AssistantQrCodePermissionType.java
@@ -6,17 +6,27 @@
 
 import android.Manifest.permission;
 
+import org.chromium.ui.permissions.PermissionConstants;
+
 public enum AssistantQrCodePermissionType {
     // List of permissions should be mentioned here
-    CAMERA(permission.CAMERA);
+    CAMERA(permission.CAMERA, "camera_img"),
+    READ_MEDIA_IMAGES(PermissionConstants.READ_MEDIA_IMAGES, "folder_img"),
+    READ_EXTERNAL_STORAGE(permission.READ_EXTERNAL_STORAGE, "folder_img");
 
     private String mAndroidPermission;
+    private String mAndroidPermissionImage;
 
     public String getAndroidPermission() {
         return this.mAndroidPermission;
     }
 
-    private AssistantQrCodePermissionType(String permission) {
-        this.mAndroidPermission = permission;
+    public String getAndroidPermissionImage() {
+        return this.mAndroidPermissionImage;
     }
-}
\ No newline at end of file
+
+    private AssistantQrCodePermissionType(String permission, String permissionImage) {
+        this.mAndroidPermission = permission;
+        this.mAndroidPermissionImage = permissionImage;
+    }
+}
diff --git a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/permission/AssistantQrCodePermissionView.java b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/permission/AssistantQrCodePermissionView.java
index 2d51986a..0c3fd926 100644
--- a/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/permission/AssistantQrCodePermissionView.java
+++ b/components/autofill_assistant/guided_browsing/android/java/src/org/chromium/components/autofill_assistant/guided_browsing/qr_code/permission/AssistantQrCodePermissionView.java
@@ -9,9 +9,12 @@
 import android.view.View.OnClickListener;
 import android.widget.TextView;
 
+import androidx.core.content.ContextCompat;
+
 import org.chromium.components.autofill_assistant.guided_browsing.LayoutUtils;
 import org.chromium.components.autofill_assistant.guided_browsing.R;
 import org.chromium.ui.widget.ButtonCompat;
+import org.chromium.ui.widget.ChromeImageView;
 
 /**
  * Manages the Android View representing the QR Code permission.
@@ -39,7 +42,7 @@
     /**
      * The AssistantQrCodePermissionView constructor.
      */
-    public AssistantQrCodePermissionView(Context context,
+    public AssistantQrCodePermissionView(Context context, AssistantQrCodePermissionType permission,
             AssistantQrCodePermissionView.Delegate delegate,
             AssistantQrCodePermissionCallback permissionCallback) {
         mContext = context;
@@ -52,6 +55,13 @@
         mPermissionTextView = mPermissionView.findViewById(R.id.permission_text);
         mPermissionButton = mPermissionView.findViewById(R.id.permission_button);
 
+        // Updating permission view image based on the permission type.
+        ChromeImageView permissionImageView = mPermissionView.findViewById(R.id.permission_image);
+        int permissionImageResouce = mContext.getResources().getIdentifier(
+                permission.getAndroidPermissionImage(), "drawable", mContext.getPackageName());
+        permissionImageView.setImageDrawable(
+                ContextCompat.getDrawable(mContext, permissionImageResouce));
+
         updatePermissionButtonBehaviour();
     }
 
@@ -111,4 +121,4 @@
         // settings, hence attach relevant listener.
         updatePermissionButtonBehaviour();
     }
-}
\ No newline at end of file
+}
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java
index 39dcaa7..f2a40d9 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java
@@ -209,10 +209,9 @@
                     setTestingSystemHttpURLConnection(false);
                     base.evaluate();
                 } catch (Throwable e) {
-                    throw new AssertionError("CronetTestBase#runTest failed for "
-                                    + (testingSystemHttpURLConnection() ? "System" : "Cronet")
-                                    + " implementation.",
-                            e);
+                    Log.e(TAG, "CronetTestBase#runTest failed for %s implementation.",
+                            testingSystemHttpURLConnection() ? "System" : "Cronet");
+                    throw e;
                 }
             } else {
                 // For all other tests.
@@ -230,9 +229,9 @@
                     base.evaluate();
                 }
             } catch (Throwable e) {
-                throw new AssertionError("CronetTestBase#runTest failed for "
-                                + (testingJavaImpl() ? "Java" : "Native") + " implementation.",
-                        e);
+                Log.e(TAG, "CronetTestBase#runTest failed for %s implementation.",
+                        testingJavaImpl() ? "Java" : "Native");
+                throw e;
             }
         } else {
             base.evaluate();
diff --git a/components/dbus/menu/menu.cc b/components/dbus/menu/menu.cc
index 9da0bec..aaff5c9 100644
--- a/components/dbus/menu/menu.cc
+++ b/components/dbus/menu/menu.cc
@@ -100,7 +100,7 @@
                              std::vector<int32_t>&& children,
                              ui::MenuModel* menu,
                              ui::MenuModel* containing_menu,
-                             size_t containing_menu_index)
+                             int containing_menu_index)
     : id(id),
       properties(std::move(properties)),
       children(std::move(children)),
@@ -210,7 +210,7 @@
   MenuPropertyChanges removed_props;
   for (const auto& menu_item : menu_items) {
     ui::MenuModel* menu = menu_item.first;
-    size_t index = menu_item.second;
+    int index = menu_item.second;
     MenuItem* parent = FindMenuItemForModel(menu, items_[0].get());
     MenuItem* item = nullptr;
     for (int32_t id : parent->children) {
@@ -475,7 +475,7 @@
     return items;
   items.reserve(menu->GetItemCount());
 
-  for (size_t i = 0; i < menu->GetItemCount(); ++i) {
+  for (int i = 0; i < menu->GetItemCount(); ++i) {
     ui::MenuModel* submenu = menu->GetSubmenuModelAt(i);
     std::vector<int32_t> children = ConvertMenu(submenu);
 
diff --git a/components/dbus/menu/menu.h b/components/dbus/menu/menu.h
index 376e8c4..ddb50aa 100644
--- a/components/dbus/menu/menu.h
+++ b/components/dbus/menu/menu.h
@@ -31,7 +31,7 @@
 class COMPONENT_EXPORT(DBUS) DbusMenu {
  public:
   using InitializedCallback = base::OnceCallback<void(bool success)>;
-  using MenuItemReference = std::pair<ui::MenuModel*, size_t>;
+  using MenuItemReference = std::pair<ui::MenuModel*, int>;
 
   // The exported DBus object will not be unregistered upon deletion.  It is the
   // responsibility of the caller to remove it after |this| is deleted.
@@ -62,7 +62,7 @@
              std::vector<int32_t>&& children,
              ui::MenuModel* menu,
              ui::MenuModel* containing_menu,
-             size_t containing_menu_index);
+             int containing_menu_index);
 
     MenuItem(const MenuItem&) = delete;
     MenuItem& operator=(const MenuItem&) = delete;
@@ -79,7 +79,7 @@
     // |containing_menu| will be null for the root item.  If it's null, then
     // |containing_menu_index| is meaningless.
     const raw_ptr<ui::MenuModel> containing_menu;
-    const size_t containing_menu_index;
+    const int containing_menu_index;
   };
 
   class ScopedMethodResponse {
diff --git a/components/dbus/menu/menu_property_list.cc b/components/dbus/menu/menu_property_list.cc
index 5f76227..9b9baf3 100644
--- a/components/dbus/menu/menu_property_list.cc
+++ b/components/dbus/menu/menu_property_list.cc
@@ -55,7 +55,7 @@
 }  // namespace
 
 MenuItemProperties ComputeMenuPropertiesForMenuItem(ui::MenuModel* menu,
-                                                    size_t i) {
+                                                    int i) {
   // Properties should only be set if they differ from the default values.
   MenuItemProperties properties;
 
diff --git a/components/dbus/menu/menu_property_list.h b/components/dbus/menu/menu_property_list.h
index 3b709d4..c2cf0e79 100644
--- a/components/dbus/menu/menu_property_list.h
+++ b/components/dbus/menu/menu_property_list.h
@@ -21,8 +21,7 @@
 
 // Computes properties for the menu item with index |i| in |menu|.
 COMPONENT_EXPORT(DBUS)
-MenuItemProperties ComputeMenuPropertiesForMenuItem(ui::MenuModel* menu,
-                                                    size_t i);
+MenuItemProperties ComputeMenuPropertiesForMenuItem(ui::MenuModel* menu, int i);
 
 // Given inputs |old_properties| and |new_properties|, computes outputs
 // |item_updated_props| and |item_removed_props| suitable for use in
diff --git a/components/dbus/menu/menu_property_list_unittest.cc b/components/dbus/menu/menu_property_list_unittest.cc
index e2e66f52..0261bc8 100644
--- a/components/dbus/menu/menu_property_list_unittest.cc
+++ b/components/dbus/menu/menu_property_list_unittest.cc
@@ -53,8 +53,8 @@
 
  protected:
   // ui::MenuModel::
-  bool IsItemDynamicAt(size_t index) const override {
-    EXPECT_EQ(index, 0u);
+  bool IsItemDynamicAt(int index) const override {
+    EXPECT_LE(index, 0);
     // Return true so that GetIconForCommandId() will always be called.
     return true;
   }
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn
index 4a7310c0..c608ef8 100644
--- a/components/exo/BUILD.gn
+++ b/components/exo/BUILD.gn
@@ -108,7 +108,6 @@
     "//third_party/blink/public/common",
     "//ui/accessibility:ax_base",
     "//ui/aura",
-    "//ui/aura/cursor",
     "//ui/base/dragdrop:types",
     "//ui/base/dragdrop/mojom",
     "//ui/base/ime",
diff --git a/components/exo/pointer.cc b/components/exo/pointer.cc
index 2ce7607..18ea4cb 100644
--- a/components/exo/pointer.cc
+++ b/components/exo/pointer.cc
@@ -28,7 +28,6 @@
 #include "ui/aura/client/capture_client.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/client/drag_drop_client.h"
-#include "ui/aura/cursor/cursor_util.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
 #include "ui/base/cursor/cursor_factory.h"
@@ -45,6 +44,7 @@
 #include "ui/gfx/geometry/vector2d_conversions.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/core/cursor_util.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/constants/ash_features.h"
@@ -942,8 +942,8 @@
 
     // Use panel_rotation() rather than "natural" rotation, as it actually
     // relates to the hardware you're about to draw the cursor bitmap on.
-    aura::ScaleAndRotateCursorBitmapAndHotpoint(scale, display.panel_rotation(),
-                                                &bitmap, &hotspot);
+    wm::ScaleAndRotateCursorBitmapAndHotpoint(scale, display.panel_rotation(),
+                                              &bitmap, &hotspot);
 
     // TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers
     // and use that here instead of the current bitmap API.
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 10e6a7ec..9b69aa2 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
@@ -1403,11 +1403,15 @@
     }
 
     /**
-     * If some third-party app launched this app with an intent, and the URL got redirected, and the
-     * user explicitly chose this app over other intent handlers, stay in the app unless there was a
-     * new intent handler after redirection or the app cannot handle it internally any more.
-     * Custom tabs are an exception to this rule, since at no point, the user sees an intent picker
-     * and "picking the Chrome app" is handled inside the support library.
+     * If another app, or the user, chose to launch this app for an intent, we should keep that
+     * navigation within this app through redirects until it resolves to a new app or external
+     * protocol given this app was intentionally chosen. Custom tabs always explicitly target the
+     * browser and this issue is handled elsewhere through
+     * {@link RedirectHandler#intentPrefersToStayInChrome()}.
+     *
+     * Usually this covers cases like https://www.youtube.com/ redirecting to
+     * https://m.youtube.com/. Note that this isn't covered by {@link #shouldStayWithinHost()} as
+     * for intent navigation there is no previously committed URL.
      */
     private boolean shouldKeepIntentRedirectInApp(ExternalNavigationParams params,
             boolean incomingIntentRedirect, List<ResolveInfo> resolvingInfos,
@@ -1416,7 +1420,7 @@
                 && !params.getRedirectHandler().isFromCustomTabIntent()
                 && !params.getRedirectHandler().hasNewResolver(
                         resolvingInfos, (Intent intent) -> queryIntentActivities(intent))) {
-            if (DEBUG) Log.i(TAG, "Custom tab redirect no handled");
+            if (DEBUG) Log.i(TAG, "Intent navigation with no new handlers.");
             return true;
         }
         return false;
diff --git a/components/history/core/browser/sync/history_sync_bridge.cc b/components/history/core/browser/sync/history_sync_bridge.cc
index eb19f2a..a276e51 100644
--- a/components/history/core/browser/sync/history_sync_bridge.cc
+++ b/components/history/core/browser/sync/history_sync_bridge.cc
@@ -365,6 +365,13 @@
     RecordDatabaseError(
         SyncHistoryDatabaseError::kApplySyncChangesWriteMetadata);
   }
+
+  // ApplySyncChanges() gets called both for incoming remote changes (i.e. for
+  // GetUpdates) and after a successful Commit. In either case, there's now
+  // likely some local metadata that's not needed anymore, so go and clean that
+  // up.
+  UntrackAndClearMetadataForSyncedEntities();
+
   return metadata_error;
 }
 
@@ -669,6 +676,19 @@
   return true;
 }
 
+void HistorySyncBridge::UntrackAndClearMetadataForSyncedEntities() {
+  for (const std::string& storage_key :
+       change_processor()->GetAllTrackedStorageKeys()) {
+    if (change_processor()->IsEntityUnsynced(storage_key)) {
+      // "Unsynced" entities (i.e. those with local changes that still need to
+      // be committed) have to be tracked, so *don't* clear their metadata.
+      continue;
+    }
+    sync_metadata_database_->ClearSyncMetadata(syncer::HISTORY, storage_key);
+    change_processor()->UntrackEntityForStorageKey(storage_key);
+  }
+}
+
 std::string HistorySyncBridge::GetLocalCacheGuid() const {
   // Before the processor is tracking metadata, the cache GUID isn't known.
   DCHECK(change_processor()->IsTrackingMetadata());
diff --git a/components/history/core/browser/sync/history_sync_bridge.h b/components/history/core/browser/sync/history_sync_bridge.h
index f99e50e3..5abf1932 100644
--- a/components/history/core/browser/sync/history_sync_bridge.h
+++ b/components/history/core/browser/sync/history_sync_bridge.h
@@ -92,6 +92,11 @@
   bool UpdateEntityInBackend(VisitIDRemapper* id_remapper,
                              const sync_pb::HistorySpecifics& specifics);
 
+  // Untracks all entities from the processor, and clears their (persisted)
+  // metadata, except for entities that are "unsynced", i.e. that are waiting to
+  // be committed.
+  void UntrackAndClearMetadataForSyncedEntities();
+
   // Returns the cache GUID of the Sync client on this device. Must only be
   // called after `change_processor()->IsTrackingMetadata()` returns true
   // (because before that, the cache GUID isn't known).
diff --git a/components/history/core/browser/sync/history_sync_bridge_unittest.cc b/components/history/core/browser/sync/history_sync_bridge_unittest.cc
index 0881303..08ee5136 100644
--- a/components/history/core/browser/sync/history_sync_bridge_unittest.cc
+++ b/components/history/core/browser/sync/history_sync_bridge_unittest.cc
@@ -4,6 +4,9 @@
 
 #include "components/history/core/browser/sync/history_sync_bridge.h"
 
+#include <map>
+#include <memory>
+#include <set>
 #include <string>
 #include <utility>
 #include <vector>
@@ -14,9 +17,10 @@
 #include "components/sync/base/page_transition_conversion.h"
 #include "components/sync/model/metadata_batch.h"
 #include "components/sync/model/metadata_change_list.h"
+#include "components/sync/model/model_type_change_processor.h"
 #include "components/sync/protocol/entity_metadata.pb.h"
 #include "components/sync/protocol/history_specifics.pb.h"
-#include "components/sync/test/model/mock_model_type_change_processor.h"
+#include "components/sync/test/model/forwarding_model_type_change_processor.h"
 #include "sql/database.h"
 #include "sql/meta_table.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -49,6 +53,159 @@
   return data;
 }
 
+class FakeModelTypeChangeProcessor : public syncer::ModelTypeChangeProcessor {
+ public:
+  FakeModelTypeChangeProcessor() = default;
+  ~FakeModelTypeChangeProcessor() override = default;
+
+  void SetIsTrackingMetadata(bool is_tracking_metadata) {
+    is_tracking_metadata_ = is_tracking_metadata;
+  }
+
+  void MarkEntitySynced(const std::string& storage_key) {
+    DCHECK(unsynced_entities_.count(storage_key));
+    unsynced_entities_.erase(storage_key);
+  }
+
+  void AddRemoteEntity(const std::string& storage_key,
+                       syncer::EntityData entity_data) {
+    // Remote entities are tracked, but *not* unsynced.
+    tracked_entities_[storage_key] = entity_data.client_tag_hash;
+    entities_[storage_key] = std::move(entity_data);
+  }
+
+  const std::map<std::string, syncer::EntityData>& GetEntities() const {
+    return entities_;
+  }
+
+  void Put(const std::string& storage_key,
+           std::unique_ptr<syncer::EntityData> entity_data,
+           syncer::MetadataChangeList* metadata_change_list) override {
+    // Update the persisted metadata.
+    sync_pb::EntityMetadata metadata;
+    metadata.set_sequence_number(1);
+    metadata_change_list->UpdateMetadata(storage_key, metadata);
+    // Store the entity, and mark it as tracked and unsynced.
+    tracked_entities_[storage_key] = entity_data->client_tag_hash;
+    unsynced_entities_.insert(storage_key);
+    entities_[storage_key] = std::move(*entity_data);
+  }
+
+  void Delete(const std::string& storage_key,
+              syncer::MetadataChangeList* metadata_change_list) override {
+    NOTREACHED();
+  }
+
+  void UpdateStorageKey(
+      const syncer::EntityData& entity_data,
+      const std::string& storage_key,
+      syncer::MetadataChangeList* metadata_change_list) override {
+    NOTREACHED();
+  }
+
+  void UntrackEntityForStorageKey(const std::string& storage_key) override {
+    tracked_entities_.erase(storage_key);
+    // If the entity isn't tracked anymore, it also can't be unsynced.
+    unsynced_entities_.erase(storage_key);
+  }
+
+  void UntrackEntityForClientTagHash(
+      const syncer::ClientTagHash& client_tag_hash) override {
+    for (const auto& [storage_key, cth] : tracked_entities_) {
+      if (cth == client_tag_hash) {
+        UntrackEntityForStorageKey(storage_key);
+        // Note: This modified `tracked_entities_`, so it's not safe to continue
+        // the loop.
+        break;
+      }
+    }
+  }
+
+  std::vector<std::string> GetAllTrackedStorageKeys() const override {
+    std::vector<std::string> storage_keys;
+    for (const auto& [storage_key, cth] : tracked_entities_) {
+      storage_keys.push_back(storage_key);
+    }
+    return storage_keys;
+  }
+
+  bool IsEntityUnsynced(const std::string& storage_key) override {
+    return unsynced_entities_.count(storage_key) > 0;
+  }
+
+  base::Time GetEntityCreationTime(
+      const std::string& storage_key) const override {
+    NOTREACHED();
+    return base::Time();
+  }
+
+  base::Time GetEntityModificationTime(
+      const std::string& storage_key) const override {
+    NOTREACHED();
+    return base::Time();
+  }
+
+  void OnModelStarting(syncer::ModelTypeSyncBridge* bridge) override {}
+
+  void ModelReadyToSync(std::unique_ptr<syncer::MetadataBatch> batch) override {
+  }
+
+  bool IsTrackingMetadata() const override { return is_tracking_metadata_; }
+
+  std::string TrackedAccountId() const override {
+    if (!IsTrackingMetadata()) {
+      return "";
+    }
+    return "account_id";
+  }
+
+  std::string TrackedCacheGuid() const override {
+    if (!IsTrackingMetadata()) {
+      return "";
+    }
+    return "local_cache_guid";
+  }
+
+  void ReportError(const syncer::ModelError& error) override {
+    ADD_FAILURE() << "ReportError: " << error.ToString();
+  }
+
+  absl::optional<syncer::ModelError> GetError() const override {
+    return absl::nullopt;
+  }
+
+  base::WeakPtr<syncer::ModelTypeControllerDelegate> GetControllerDelegate()
+      override {
+    NOTREACHED();
+    return nullptr;
+  }
+
+  const sync_pb::EntitySpecifics& GetPossiblyTrimmedRemoteSpecifics(
+      const std::string& storage_key) const override {
+    NOTREACHED();
+    return sync_pb::EntitySpecifics::default_instance();
+  }
+
+  std::unique_ptr<ModelTypeChangeProcessor> CreateForwardingProcessor() {
+    return base::WrapUnique<ModelTypeChangeProcessor>(
+        new syncer::ForwardingModelTypeChangeProcessor(this));
+  }
+
+ private:
+  bool is_tracking_metadata_ = false;
+
+  // Map from storage key to EntityData for all entities passed to Put().
+  std::map<std::string, syncer::EntityData> entities_;
+
+  // Map from storage key to ClientTagHash for all entities currently tracked by
+  // the processor.
+  std::map<std::string, syncer::ClientTagHash> tracked_entities_;
+
+  // Set of storage keys of all unsynced entities (i.e. with local changes that
+  // are pending commit).
+  std::set<std::string> unsynced_entities_;
+};
+
 class HistorySyncBridgeTest : public testing::Test {
  public:
   HistorySyncBridgeTest() : metadata_db_(&db_, &meta_table_) {}
@@ -60,25 +217,10 @@
     metadata_db_.Init();
     meta_table_.Init(&db_, /*version=*/1, /*compatible_version=*/1);
 
-    // HistorySyncBridge never issues deletions (they're handled via
-    // DeleteDirectives instead).
-    EXPECT_CALL(*processor(), Delete).Times(0);
-
     // Creating the bridge triggers loading of the metadata, which is
     // synchronous.
-    EXPECT_CALL(*processor(), ModelReadyToSync);
     bridge_ = std::make_unique<HistorySyncBridge>(
-        &backend_, &metadata_db_, mock_processor_.CreateForwardingProcessor());
-
-    // Set up the processor to store metadata on Put().
-    ON_CALL(*processor(), Put)
-        .WillByDefault([](const std::string& storage_key,
-                          std::unique_ptr<syncer::EntityData> entity_data,
-                          syncer::MetadataChangeList* metadata_change_list) {
-          sync_pb::EntityMetadata metadata;
-          metadata.set_sequence_number(1);
-          metadata_change_list->UpdateMetadata(storage_key, metadata);
-        });
+        &backend_, &metadata_db_, fake_processor_.CreateForwardingProcessor());
   }
 
   void TearDown() override {
@@ -87,7 +229,7 @@
   }
 
   TestHistoryBackendForSync* backend() { return &backend_; }
-  syncer::MockModelTypeChangeProcessor* processor() { return &mock_processor_; }
+  FakeModelTypeChangeProcessor* processor() { return &fake_processor_; }
   HistorySyncBridge* bridge() { return bridge_.get(); }
 
   std::pair<URLRow, VisitRow> AddVisitToBackendAndAdvanceClock(
@@ -124,6 +266,8 @@
     syncer::EntityChangeList entity_change_list;
     for (const sync_pb::HistorySpecifics& specifics : specifics_vector) {
       syncer::EntityData data = SpecificsToEntityData(specifics);
+      data.client_tag_hash = syncer::ClientTagHash::FromUnhashed(
+          syncer::HISTORY, bridge_->GetClientTag(data));
       std::string storage_key = bridge_->GetStorageKey(data);
       entity_change_list.push_back(
           syncer::EntityChange::CreateAdd(storage_key, std::move(data)));
@@ -134,18 +278,62 @@
   void MergeSyncData(
       const std::vector<sync_pb::HistorySpecifics>& specifics_vector) {
     // Just before the merge, the processor starts tracking metadata.
-    ON_CALL(*processor(), IsTrackingMetadata()).WillByDefault(Return(true));
-    ON_CALL(*processor(), TrackedCacheGuid())
-        .WillByDefault(Return("local_cache_guid"));
+    processor()->SetIsTrackingMetadata(true);
+
+    // Populate a MetadataChangeList with an update for each entity.
+    std::unique_ptr<syncer::MetadataChangeList> metadata_changes =
+        bridge()->CreateMetadataChangeList();
+    for (const sync_pb::HistorySpecifics& specifics : specifics_vector) {
+      syncer::EntityData data = SpecificsToEntityData(specifics);
+      data.client_tag_hash = syncer::ClientTagHash::FromUnhashed(
+          syncer::HISTORY, bridge_->GetClientTag(data));
+      std::string storage_key = bridge_->GetStorageKey(data);
+      // Note: Don't bother actually populating the EntityMetadata - the bridge
+      // doesn't inspect it anyway.
+      metadata_changes->UpdateMetadata(storage_key, sync_pb::EntityMetadata());
+      processor()->AddRemoteEntity(storage_key, std::move(data));
+    }
 
     absl::optional<syncer::ModelError> error =
-        bridge()->MergeSyncData(bridge()->CreateMetadataChangeList(),
+        bridge()->MergeSyncData(std::move(metadata_changes),
                                 CreateAddEntityChangeList(specifics_vector));
     if (error) {
       ADD_FAILURE() << "MergeSyncData failed: " << error->ToString();
     }
   }
 
+  void ApplySyncChanges(
+      const std::vector<sync_pb::HistorySpecifics>& specifics_vector,
+      const std::vector<std::string> extra_updated_metadata_storage_keys = {}) {
+    // Populate a MetadataChangeList with the given updates/clears.
+    std::unique_ptr<syncer::MetadataChangeList> metadata_changes =
+        bridge()->CreateMetadataChangeList();
+    // By default, add a metadata update for each new/changed entity.
+    for (const sync_pb::HistorySpecifics& specifics : specifics_vector) {
+      syncer::EntityData data = SpecificsToEntityData(specifics);
+      data.client_tag_hash = syncer::ClientTagHash::FromUnhashed(
+          syncer::HISTORY, bridge_->GetClientTag(data));
+      std::string storage_key = bridge_->GetStorageKey(data);
+      // Note: Don't bother actually populating the EntityMetadata - the bridge
+      // doesn't inspect it anyway.
+      metadata_changes->UpdateMetadata(storage_key, sync_pb::EntityMetadata());
+      processor()->AddRemoteEntity(storage_key, std::move(data));
+    }
+    // Add additional metadata updates, if specified.
+    for (const std::string& storage_key : extra_updated_metadata_storage_keys) {
+      // Note: Don't bother actually populating the EntityMetadata - the bridge
+      // doesn't inspect it anyway.
+      metadata_changes->UpdateMetadata(storage_key, sync_pb::EntityMetadata());
+    }
+
+    absl::optional<syncer::ModelError> error =
+        bridge()->ApplySyncChanges(std::move(metadata_changes),
+                                   CreateAddEntityChangeList(specifics_vector));
+    if (error) {
+      ADD_FAILURE() << "ApplySyncChanges failed: " << error->ToString();
+    }
+  }
+
   void ApplyStopSyncChanges() {
     syncer::MetadataBatch all_metadata;
     metadata_db_.GetAllSyncMetadata(&all_metadata);
@@ -160,7 +348,7 @@
     bridge()->ApplyStopSyncChanges(std::move(delete_all_metadata));
 
     // After stopping sync, metadata is not tracked anymore.
-    ON_CALL(*processor(), IsTrackingMetadata()).WillByDefault(Return(false));
+    processor()->SetIsTrackingMetadata(false);
   }
 
   syncer::EntityMetadataMap GetAllMetadata() {
@@ -181,7 +369,7 @@
 
   TestHistoryBackendForSync backend_;
 
-  testing::NiceMock<syncer::MockModelTypeChangeProcessor> mock_processor_;
+  FakeModelTypeChangeProcessor fake_processor_;
 
   std::unique_ptr<HistorySyncBridge> bridge_;
 };
@@ -190,12 +378,12 @@
   AddVisitToBackendAndAdvanceClock(GURL("https://www.url.com"),
                                    ui::PAGE_TRANSITION_LINK);
 
-  // The local data should *not* get uploaded to Sync.
-  EXPECT_CALL(*processor(), Put).Times(0);
-
   MergeSyncData({});
 
-  // The local data should still exist.
+  // The data should *not* have been uploaded to Sync.
+  EXPECT_TRUE(processor()->GetEntities().empty());
+
+  // The local data should still exist though.
   EXPECT_EQ(backend()->GetURLs().size(), 1u);
   EXPECT_EQ(backend()->GetVisits().size(), 1u);
 }
@@ -296,18 +484,17 @@
                                 ui::PAGE_TRANSITION_FROM_ADDRESS_BAR));
 
   // Notify the bridge about the visit - it should be sent to the processor.
-  syncer::EntityData entity;
-  EXPECT_CALL(*processor(),
-              Put(HistorySyncMetadataDatabase::StorageKeyFromVisitTime(
-                      visit_row.visit_time),
-                  _, _))
-      .WillOnce([&](const std::string& storage_key,
-                    std::unique_ptr<syncer::EntityData> put_entity,
-                    auto* metadata_cl) { entity = std::move(*put_entity); });
   bridge()->OnURLVisited(
       /*history_backend=*/nullptr, visit_row.transition, url_row,
       visit_row.visit_time);
 
+  const std::string storage_key =
+      HistorySyncMetadataDatabase::StorageKeyFromVisitTime(
+          visit_row.visit_time);
+  EXPECT_EQ(processor()->GetEntities().size(), 1u);
+  ASSERT_EQ(processor()->GetEntities().count(storage_key), 1u);
+  const syncer::EntityData& entity = processor()->GetEntities().at(storage_key);
+
   // Spot check some fields of the resulting entity.
   ASSERT_TRUE(entity.specifics.has_history());
   const sync_pb::HistorySpecifics& history = entity.specifics.history();
@@ -334,27 +521,29 @@
       GURL("https://www.url.com"), ui::PAGE_TRANSITION_TYPED);
 
   // Notify the bridge about the visit - it should be sent to the processor.
-  const std::string storage_key =
-      HistorySyncMetadataDatabase::StorageKeyFromVisitTime(
-          visit_row.visit_time);
-  EXPECT_CALL(*processor(), Put(storage_key, _, _));
   bridge()->OnURLVisited(
       /*history_backend=*/nullptr, visit_row.transition, url_row,
       visit_row.visit_time);
 
-  // Update the visit by adding a duration. This should result in a Put().
+  const std::string storage_key =
+      HistorySyncMetadataDatabase::StorageKeyFromVisitTime(
+          visit_row.visit_time);
+  EXPECT_EQ(processor()->GetEntities().size(), 1u);
+  EXPECT_EQ(processor()->GetEntities().count(storage_key), 1u);
+
+  // Update the visit by adding a duration.
   const base::TimeDelta visit_duration = base::Seconds(10);
   visit_row.visit_duration = visit_duration;
-  EXPECT_CALL(*processor(), Put(storage_key, _, _))
-      .WillOnce([&](const std::string& storage_key,
-                    std::unique_ptr<syncer::EntityData> entity,
-                    auto* metadata_cl) {
-        EXPECT_EQ(base::Microseconds(
-                      entity->specifics.history().visit_duration_micros()),
-                  visit_duration);
-      });
   ASSERT_TRUE(backend()->UpdateVisit(visit_row));
   bridge()->OnVisitUpdated(visit_row);
+
+  // The updated data should have been sent to the processor.
+  EXPECT_EQ(processor()->GetEntities().size(), 1u);
+  ASSERT_EQ(processor()->GetEntities().count(storage_key), 1u);
+  const syncer::EntityData& entity = processor()->GetEntities().at(storage_key);
+  EXPECT_EQ(
+      base::Microseconds(entity.specifics.history().visit_duration_micros()),
+      visit_duration);
 }
 
 TEST_F(HistorySyncBridgeTest, UploadsLocalVisitWithRedirects) {
@@ -396,16 +585,7 @@
       ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CHAIN_END);
   backend()->AddVisit(visit_row3);
 
-  // Notify the bridge about all of the visits - the whole chain should result
-  // in a single entity being Put().
-  syncer::EntityData entity;
-  EXPECT_CALL(
-      *processor(),
-      Put(HistorySyncMetadataDatabase::StorageKeyFromVisitTime(visit_time), _,
-          _))
-      .WillOnce([&](const std::string& storage_key,
-                    std::unique_ptr<syncer::EntityData> put_entity,
-                    auto* metadata_cl) { entity = std::move(*put_entity); });
+  // Notify the bridge about all of the visits.
   bridge()->OnURLVisited(
       /*history_backend=*/nullptr, visit_row1.transition, url_row1, visit_time);
   bridge()->OnURLVisited(
@@ -413,6 +593,13 @@
   bridge()->OnURLVisited(
       /*history_backend=*/nullptr, visit_row3.transition, url_row3, visit_time);
 
+  // The whole chain should have resulting in a single entity being Put().
+  const std::string storage_key =
+      HistorySyncMetadataDatabase::StorageKeyFromVisitTime(visit_time);
+  EXPECT_EQ(processor()->GetEntities().size(), 1u);
+  ASSERT_EQ(processor()->GetEntities().count(storage_key), 1u);
+  const syncer::EntityData& entity = processor()->GetEntities().at(storage_key);
+
   // Check that the resulting entity contains the redirect chain.
   ASSERT_TRUE(entity.specifics.has_history());
   const sync_pb::HistorySpecifics& history = entity.specifics.history();
@@ -430,6 +617,97 @@
       ui::PAGE_TRANSITION_LINK));
 }
 
+TEST_F(HistorySyncBridgeTest, UntracksEntitiesAfterCommit) {
+  // Start syncing (with no data yet).
+  MergeSyncData({});
+
+  // Visit some URLs.
+  auto [url_row1, visit_row1] = AddVisitToBackendAndAdvanceClock(
+      GURL("https://url1.com"), ui::PAGE_TRANSITION_TYPED);
+  auto [url_row2, visit_row2] = AddVisitToBackendAndAdvanceClock(
+      GURL("https://url2.com"), ui::PAGE_TRANSITION_LINK);
+
+  // Notify the bridge about the visits - they should be sent to the processor.
+  bridge()->OnURLVisited(
+      /*history_backend=*/nullptr, visit_row1.transition, url_row1,
+      visit_row1.visit_time);
+  bridge()->OnURLVisited(
+      /*history_backend=*/nullptr, visit_row2.transition, url_row2,
+      visit_row2.visit_time);
+
+  EXPECT_EQ(processor()->GetEntities().size(), 2u);
+  // The metadata for these entities should now be tracked.
+  EXPECT_EQ(GetAllMetadata().size(), 2u);
+
+  // Simulate a successful commit, which results in an ApplySyncChanges() call
+  // to the bridge, updating the committed entities' metadata.
+  std::vector<std::string> updated_storage_keys;
+  for (const auto& [storage_key, metadata] : GetAllMetadata()) {
+    processor()->MarkEntitySynced(storage_key);
+    updated_storage_keys.push_back(storage_key);
+  }
+  ApplySyncChanges({}, updated_storage_keys);
+
+  // Now the metadata should not be tracked anymore.
+  EXPECT_EQ(GetAllMetadata().size(), 0u);
+  EXPECT_TRUE(GetAllMetadata().empty());
+}
+
+TEST_F(HistorySyncBridgeTest, UntracksRemoteEntities) {
+  // Start Sync with an initial remote entity.
+  MergeSyncData(
+      {CreateSpecifics(base::Time::Now() - base::Seconds(10),
+                       "remote_cache_guid", GURL("https://remote.com"))});
+  ASSERT_EQ(backend()->GetURLs().size(), 1u);
+  ASSERT_EQ(backend()->GetVisits().size(), 1u);
+  ASSERT_EQ(backend()->GetVisits()[0].visit_duration, base::TimeDelta());
+
+  // The entity should have been untracked immediately.
+  EXPECT_TRUE(GetAllMetadata().empty());
+
+  // Another remote entity comes in.
+  ApplySyncChanges(
+      {CreateSpecifics(base::Time::Now() - base::Seconds(5),
+                       "remote_cache_guid", GURL("https://remote2.com"))});
+
+  // This entity should also have been untracked immediately.
+  EXPECT_TRUE(GetAllMetadata().empty());
+}
+
+TEST_F(HistorySyncBridgeTest, DoesNotUntrackEntityPendingCommit) {
+  // Start syncing (with no data yet).
+  MergeSyncData({});
+
+  // Visit a URL locally.
+  auto [url_row1, visit_row1] = AddVisitToBackendAndAdvanceClock(
+      GURL("https://url1.com"), ui::PAGE_TRANSITION_TYPED);
+
+  const std::string storage_key =
+      HistorySyncMetadataDatabase::StorageKeyFromVisitTime(
+          visit_row1.visit_time);
+
+  // Notify the bridge about the visit.
+  bridge()->OnURLVisited(
+      /*history_backend=*/nullptr, visit_row1.transition, url_row1,
+      visit_row1.visit_time);
+
+  EXPECT_EQ(processor()->GetEntities().size(), 1u);
+
+  // The metadata for this entity should now be tracked.
+  ASSERT_EQ(GetAllMetadata().size(), 1u);
+
+  // Before the entity gets committed (and thus untracked), a remote entity
+  // comes in.
+  ApplySyncChanges({CreateSpecifics(base::Time::Now(), "remote_cache_guid",
+                                    GURL("https://remote.com"))});
+
+  // The remote entity should have been untracked immediately, but the local
+  // entity pending commit should still be tracked.
+  syncer::EntityMetadataMap metadata = GetAllMetadata();
+  EXPECT_EQ(metadata.size(), 1u);
+  EXPECT_EQ(metadata.count(storage_key), 1u);
+}
+
 TEST_F(HistorySyncBridgeTest, UntracksEntityOnIndividualDeletion) {
   // Start syncing (with no data yet).
   MergeSyncData({});
@@ -441,8 +719,6 @@
       GURL("https://url2.com"), ui::PAGE_TRANSITION_LINK);
 
   // Notify the bridge about the visits - they should be sent to the processor.
-  syncer::EntityData entity;
-  EXPECT_CALL(*processor(), Put).Times(2);
   bridge()->OnURLVisited(
       /*history_backend=*/nullptr, visit_row1.transition, url_row1,
       visit_row1.visit_time);
@@ -451,16 +727,13 @@
       visit_row2.visit_time);
   ASSERT_EQ(GetAllMetadata().size(), 2u);
 
-  // Now delete the first URL+visit and notify the bridge. This should not
-  // result in any Put() or Delete() calls to the processor (deletions are
-  // handled through the separate HISTORY_DELETE_DIRECTIVES data type), but it
-  // should untrack the deleted entity.
-  EXPECT_CALL(*processor(), Put).Times(0);
-  EXPECT_CALL(*processor(), Delete).Times(0);
-  EXPECT_CALL(*processor(),
-              UntrackEntityForStorageKey(
-                  HistorySyncMetadataDatabase::StorageKeyFromVisitTime(
-                      visit_row1.visit_time)));
+  EXPECT_EQ(processor()->GetEntities().size(), 2u);
+
+  // Now, *before* the entities get committed successfully (and thus would get
+  // untracked anyway), delete the first URL+visit and notify the bridge. This
+  // should not result in any Put() or Delete() calls to the processor
+  // (deletions are handled through the separate HISTORY_DELETE_DIRECTIVES data
+  // type), but it should untrack the deleted entity.
   backend()->RemoveURLAndVisits(url_row1.id());
 
   bridge()->OnVisitDeleted(visit_row1);
@@ -482,7 +755,6 @@
       GURL("https://url2.com"), ui::PAGE_TRANSITION_LINK);
 
   // Notify the bridge about the visits - they should be sent to the processor.
-  EXPECT_CALL(*processor(), Put).Times(2);
   bridge()->OnURLVisited(
       /*history_backend=*/nullptr, visit_row1.transition, url_row1,
       visit_row1.visit_time);
@@ -491,19 +763,20 @@
       visit_row2.visit_time);
   ASSERT_EQ(GetAllMetadata().size(), 2u);
 
-  // Now simulate a delete-all-history operation. This should not result in any
-  // Put() or Delete() calls on the processor (deletions are handled through the
-  // separate HISTORY_DELETE_DIRECTIVES data type), but it should untrack all
-  // entities.
-  EXPECT_CALL(*processor(), Put).Times(0);
-  EXPECT_CALL(*processor(), Delete).Times(0);
-  EXPECT_CALL(*processor(), UntrackEntityForStorageKey).Times(2);
+  EXPECT_EQ(processor()->GetEntities().size(), 2u);
+
+  // Now, *before* the entities get committed successfully (and thus would get
+  // untracked anyway), simulate a delete-all-history operation. This should not
+  // result in any Put() or Delete() calls on the processor (deletions are
+  // handled through the separate HISTORY_DELETE_DIRECTIVES data type), but it
+  // should untrack all entities.
   backend()->Clear();
   // Deleting all history does *not* result in OnVisitDeleted() calls, and also
   // does not include the actual deleted URLs in OnURLsDeleted().
   bridge()->OnURLsDeleted(/*history_backend=*/nullptr, /*all_history=*/true,
                           /*expired=*/false, /*deleted_rows=*/{},
                           /*favicon_urls=*/{});
+
   EXPECT_TRUE(GetAllMetadata().empty());
 }
 
diff --git a/components/history/core/browser/sync/history_sync_metadata_database.cc b/components/history/core/browser/sync/history_sync_metadata_database.cc
index 1bc4f3b..d96b1b2a 100644
--- a/components/history/core/browser/sync/history_sync_metadata_database.cc
+++ b/components/history/core/browser/sync/history_sync_metadata_database.cc
@@ -125,8 +125,6 @@
   DCHECK_EQ(storage_key.size(), sizeof(microseconds_since_windows_epoch));
   base::ReadBigEndian(reinterpret_cast<const uint8_t*>(storage_key.data()),
                       &microseconds_since_windows_epoch);
-  // Make sure microseconds_since_windows_epoch is set.
-  DCHECK_NE(microseconds_since_windows_epoch, 0u);
   return microseconds_since_windows_epoch;
 }
 
diff --git a/components/origin_trials/BUILD.gn b/components/origin_trials/BUILD.gn
new file mode 100644
index 0000000..ce3537e
--- /dev/null
+++ b/components/origin_trials/BUILD.gn
@@ -0,0 +1,48 @@
+# Copyright 2022 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("browser") {
+  sources = [
+    "browser/origin_trials.cc",
+    "browser/origin_trials.h",
+  ]
+  deps = [
+    ":common",
+    "//base",
+    "//third_party/blink/public/common:headers",
+    "//url:url",
+  ]
+}
+
+source_set("common") {
+  sources = [
+    "common/origin_trials_persistence_provider.h",
+    "common/persisted_trial_token.cc",
+    "common/persisted_trial_token.h",
+  ]
+  deps = [
+    "//base",
+    "//third_party/blink/public/common:headers",
+    "//url:url",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "browser/origin_trials_unittests.cc",
+    "common/persisted_trial_token_unittest.cc",
+  ]
+  deps = [
+    ":browser",
+    ":common",
+    "./test",
+    "//base",
+    "//base/test:test_support",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/blink/public:test_headers",
+    "//url:url",
+  ]
+}
diff --git a/components/origin_trials/DIR_METADATA b/components/origin_trials/DIR_METADATA
new file mode 100644
index 0000000..14641a38
--- /dev/null
+++ b/components/origin_trials/DIR_METADATA
@@ -0,0 +1 @@
+mixins: "//third_party/blink/common/origin_trials/COMMON_METADATA"
diff --git a/components/origin_trials/OWNERS b/components/origin_trials/OWNERS
new file mode 100644
index 0000000..824903f2
--- /dev/null
+++ b/components/origin_trials/OWNERS
@@ -0,0 +1,4 @@
+file://third_party/blink/common/origin_trials/OWNERS
+
+peter@chromium.org
+rayankans@chromium.org
diff --git a/components/origin_trials/README.md b/components/origin_trials/README.md
new file mode 100644
index 0000000..6992ae3
--- /dev/null
+++ b/components/origin_trials/README.md
@@ -0,0 +1,8 @@
+The origin trial component implements browser-side support for origin trials.
+
+This component is meant to supplement the implementation that exists in Blink,
+by supplying an implementation for persistent origin trials.
+
+The code is implemented as a component since it needs to be shared between
+content embedders, to make it easier to use origin trials in the browser
+process.
\ No newline at end of file
diff --git a/components/origin_trials/browser/DEPS b/components/origin_trials/browser/DEPS
new file mode 100644
index 0000000..12e8e47
--- /dev/null
+++ b/components/origin_trials/browser/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+  "+components/origin_trials/common",
+
+  "+third_party/blink/public/common/origin_trials",
+]
diff --git a/components/origin_trials/browser/origin_trials.cc b/components/origin_trials/browser/origin_trials.cc
new file mode 100644
index 0000000..e49be46
--- /dev/null
+++ b/components/origin_trials/browser/origin_trials.cc
@@ -0,0 +1,90 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/origin_trials/browser/origin_trials.h"
+
+#include <algorithm>
+
+#include "components/origin_trials/common/persisted_trial_token.h"
+#include "third_party/blink/public/common/origin_trials/origin_trials.h"
+#include "third_party/blink/public/common/origin_trials/trial_token.h"
+#include "third_party/blink/public/common/origin_trials/trial_token_result.h"
+#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace origin_trials {
+
+OriginTrials::OriginTrials(
+    std::unique_ptr<OriginTrialsPersistenceProvider> persistence_provider,
+    std::unique_ptr<blink::TrialTokenValidator> token_validator)
+    : persistence_provider_(std::move(persistence_provider)),
+      trial_token_validator_(std::move(token_validator)) {}
+
+OriginTrials::~OriginTrials() = default;
+
+base::flat_set<std::string> OriginTrials::GetPersistedTrialsForOrigin(
+    const url::Origin& origin,
+    const base::Time current_time) const {
+  return GetPersistedTrialsForOriginWithMatch(origin, current_time,
+                                              absl::nullopt);
+}
+
+bool OriginTrials::IsTrialPersistedForOrigin(
+    const url::Origin& origin,
+    const base::StringPiece trial_name,
+    const base::Time current_time) const {
+  return !GetPersistedTrialsForOriginWithMatch(origin, current_time, trial_name)
+              .empty();
+}
+
+void OriginTrials::PersistTrialsFromTokens(
+    const url::Origin& origin,
+    const base::span<const base::StringPiece> header_tokens,
+    const base::Time current_time) {
+  base::flat_set<PersistedTrialToken> enabled_persistent_trial_tokens;
+
+  for (const base::StringPiece token : header_tokens) {
+    blink::TrialTokenResult validation_result =
+        trial_token_validator_->ValidateTokenAndTrial(token, origin,
+                                                      current_time);
+    const blink::TrialToken* parsed_token = validation_result.ParsedToken();
+    if (validation_result.Status() == blink::OriginTrialTokenStatus::kSuccess &&
+        blink::origin_trials::IsTrialPersistentToNextResponse(
+            parsed_token->feature_name())) {
+      enabled_persistent_trial_tokens.emplace(
+          parsed_token->feature_name(), parsed_token->expiry_time(),
+          parsed_token->usage_restriction(), parsed_token->signature());
+    }
+  }
+  persistence_provider_->SavePersistentTrialTokens(
+      origin, std::move(enabled_persistent_trial_tokens));
+}
+
+base::flat_set<std::string> OriginTrials::GetPersistedTrialsForOriginWithMatch(
+    const url::Origin& origin,
+    const base::Time current_time,
+    const absl::optional<const base::StringPiece> trial_name_match) const {
+  base::flat_set<PersistedTrialToken> saved_tokens =
+      persistence_provider_->GetPersistentTrialTokens(origin);
+
+  base::flat_set<std::string> enabled_trials;
+  for (const PersistedTrialToken& token : saved_tokens) {
+    if (!trial_name_match || token.trial_name == *trial_name_match) {
+      bool valid = trial_token_validator_->RevalidateTokenAndTrial(
+          token.trial_name, token.token_expiry, token.usage_restriction,
+          token.token_signature, current_time);
+      bool persistent = blink::origin_trials::IsTrialPersistentToNextResponse(
+          token.trial_name);
+      if (valid && persistent) {
+        // Move the string into the flat_set to avoid extra heap allocations
+        enabled_trials.insert(std::move(token.trial_name));
+      }
+    }
+  }
+
+  return enabled_trials;
+}
+
+}  // namespace origin_trials
diff --git a/components/origin_trials/browser/origin_trials.h b/components/origin_trials/browser/origin_trials.h
new file mode 100644
index 0000000..6598d6dd
--- /dev/null
+++ b/components/origin_trials/browser/origin_trials.h
@@ -0,0 +1,84 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ORIGIN_TRIALS_BROWSER_ORIGIN_TRIALS_H_
+#define COMPONENTS_ORIGIN_TRIALS_BROWSER_ORIGIN_TRIALS_H_
+
+#include <memory>
+#include <string>
+
+#include "base/containers/flat_set.h"
+#include "base/containers/span.h"
+#include "base/strings/string_piece.h"
+#include "base/time/time.h"
+#include "components/origin_trials/common/origin_trials_persistence_provider.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
+
+namespace url {
+class Origin;
+}
+
+namespace origin_trials {
+
+// Implementation of persistent origin trials for the browser process.
+//
+// This class manages persistent origin trials, allowing the browser to check
+// if a given trial is enabled or not.
+//
+// Persisting the enabled trials is handled by the |persistence_provider| passed
+// in through the constructor.
+class OriginTrials {
+ public:
+  OriginTrials(
+      std::unique_ptr<OriginTrialsPersistenceProvider> persistence_provider,
+      std::unique_ptr<blink::TrialTokenValidator> token_validator);
+
+  OriginTrials(const OriginTrials&) = delete;
+  OriginTrials(const OriginTrials&&) = delete;
+  OriginTrials& operator=(const OriginTrials&) = delete;
+  OriginTrials& operator=(const OriginTrials&&) = delete;
+
+  ~OriginTrials();
+
+  // Return the list of persistent origin trials that have been saved for
+  // |origin| and haven't expired given the |current_time| parameter.
+  base::flat_set<std::string> GetPersistedTrialsForOrigin(
+      const url::Origin& origin,
+      base::Time current_time) const;
+
+  // Returns |true| if |trial_name| has been persisted for |origin| and is still
+  // valid.
+  // Prefer using this over |GetPersistedTrialsForOrigin| when checking
+  // individual trials, as it does less work.
+  bool IsTrialPersistedForOrigin(const url::Origin& origin,
+                                 const base::StringPiece trial_name,
+                                 const base::Time current_time) const;
+
+  // Persist all enabled and persistable tokens in the |header_tokens|.
+  // Subsequent calls to this method will overwrite the list of persisted trials
+  // for the |origin|.
+  void PersistTrialsFromTokens(
+      const url::Origin& origin,
+      const base::span<const base::StringPiece> header_tokens,
+      const base::Time current_time);
+
+ private:
+  std::unique_ptr<OriginTrialsPersistenceProvider> persistence_provider_;
+  std::unique_ptr<blink::TrialTokenValidator> trial_token_validator_;
+
+  // Helper to return the still-valid persisted trials, with an optional
+  // |trial_name_match| which can be passed to ensure we only validate
+  // and return the trial if it matches the passed name.
+  // If no |trial_name_match| is provided, it will return all persisted trials
+  // that are still valid.
+  base::flat_set<std::string> GetPersistedTrialsForOriginWithMatch(
+      const url::Origin& origin,
+      const base::Time current_time,
+      const absl::optional<const base::StringPiece> trial_name_match) const;
+};
+
+}  // namespace origin_trials
+
+#endif  // COMPONENTS_ORIGIN_TRIALS_BROWSER_ORIGIN_TRIALS_H_
diff --git a/components/origin_trials/browser/origin_trials_unittests.cc b/components/origin_trials/browser/origin_trials_unittests.cc
new file mode 100644
index 0000000..f8803c7
--- /dev/null
+++ b/components/origin_trials/browser/origin_trials_unittests.cc
@@ -0,0 +1,312 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <vector>
+
+#include "base/containers/flat_set.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/strings/string_piece.h"
+#include "base/time/time.h"
+#include "components/origin_trials/browser/origin_trials.h"
+#include "components/origin_trials/common/persisted_trial_token.h"
+#include "components/origin_trials/test/test_persistence_provider.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/origin_trials/scoped_test_origin_trial_policy.h"
+#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace origin_trials {
+namespace {
+
+const char kPersistentTrialName[] = "FrobulatePersistent";
+const char kNonPersistentTrialName[] = "Frobulate";
+const char kInvalidTrialName[] = "InvalidTrial";
+
+// A dummy value that hasn't been explicitly disabled
+const char kDummyTokenSignature[] = "";
+
+const base::Time kValidTime = base::Time::FromTimeT(1000000000);
+const base::Time kExpiryTime = base::Time::FromTimeT(2000000000);
+
+// Valid header token for FrobulatePersistent
+// generated with
+// tools/origin_trials/generate_token.py enabled.example.com FrobulatePersistent
+// --expire-timestamp=2000000000
+const char kFrobulatePersistentToken[] =
+    "A5J4wscfmyiy3zsOMNASl25jJffHq/XGKNoFCSWoAsL0aXv+ugtTQoE/"
+    "Cs3a6pDezyQpKfYy10kcbdVC4i1n8AQAAABleyJvcmlnaW4iOiAiaHR0cHM6Ly9lbmFibGVkLm"
+    "V4YW1wbGUuY29tOjQ0MyIsICJmZWF0dXJlIjogIkZyb2J1bGF0ZVBlcnNpc3RlbnQiLCAiZXhw"
+    "aXJ5IjogMjAwMDAwMDAwMH0=";
+
+// Valid header token for Frobulate
+// generated with
+// tools/origin_trials/generate_token.py enabled.example.com Frobulate
+// --expire-timestamp=2000000000
+const char kFrobulateToken[] =
+    "A2QF2oWLF7q+qYSwt+"
+    "AvY6DSGE5QAb9Aeg7eOmbanVINtCJcCjZtNAtUUE88BB5UlvOMpPUUQjfgs3LTO0YXzAcAAABb"
+    "eyJvcmlnaW4iOiAiaHR0cHM6Ly9lbmFibGVkLmV4YW1wbGUuY29tOjQ0MyIsICJmZWF0dXJlIj"
+    "ogIkZyb2J1bGF0ZSIsICJleHBpcnkiOiAyMDAwMDAwMDAwfQ==";
+
+const char kFrobulateManualCompletionToken[] =
+    "A4TCodS8fnQFVyShubc4TKr+"
+    "Ss6br97EBk4Kh1bQiskjJHwHXKjhxMjwviiL60RD4byiVF3D9UmoPdXcz7Kg8w8AAAB2eyJvcm"
+    "lnaW4iOiAiaHR0cHM6Ly9lbmFibGVkLmV4YW1wbGUuY29tOjQ0MyIsICJmZWF0dXJlIjogIkZy"
+    "b2J1bGF0ZVBlcnNpc3RlbnRFeHBpcnlHcmFjZVBlcmlvZCIsICJleHBpcnkiOiAyMDAwMDAwMD"
+    "AwfQ==";
+
+class OpenScopedTestOriginTrialPolicy
+    : public blink::ScopedTestOriginTrialPolicy {
+ public:
+  OpenScopedTestOriginTrialPolicy() = default;
+  ~OpenScopedTestOriginTrialPolicy() override = default;
+
+  // Check if the passed |trial_name| has been disabled.
+  bool IsFeatureDisabled(base::StringPiece trial_name) const override {
+    return disabled_trials_.contains(trial_name);
+  }
+
+  bool IsTokenDisabled(base::StringPiece token_signature) const override {
+    return disabled_signatures_.contains(token_signature);
+  }
+
+  // Check if the passed |trial_name| has been disabled.
+  bool IsFeatureDisabledForUser(base::StringPiece trial_name) const override {
+    return user_disabled_trials_.contains(trial_name);
+  }
+
+  void DisableTrial(base::StringPiece trial) {
+    disabled_trials_.emplace(trial);
+  }
+
+  void DisableToken(base::StringPiece token_signature) {
+    disabled_signatures_.emplace(token_signature);
+  }
+
+  void DisableTrialForUser(base::StringPiece trial_name) {
+    user_disabled_trials_.emplace(trial_name);
+  }
+
+ private:
+  base::flat_set<std::string> disabled_trials_;
+  base::flat_set<std::string> disabled_signatures_;
+  base::flat_set<std::string> user_disabled_trials_;
+};
+
+class OriginTrialsTest : public testing::Test {
+ public:
+  OriginTrialsTest()
+      : origin_trials_(std::make_unique<test::TestPersistenceProvider>(),
+                       std::make_unique<blink::TrialTokenValidator>()),
+        trial_enabled_origin_(
+            url::Origin::Create(GURL("https://enabled.example.com"))) {}
+
+  OriginTrialsTest(const OriginTrialsTest&) = delete;
+  OriginTrialsTest& operator=(const OriginTrialsTest&) = delete;
+
+  ~OriginTrialsTest() override = default;
+
+ protected:
+  OriginTrials origin_trials_;
+  url::Origin trial_enabled_origin_;
+  OpenScopedTestOriginTrialPolicy origin_trial_policy_;
+};
+
+TEST_F(OriginTrialsTest, CleanObjectHasNoPersistentTrials) {
+  EXPECT_TRUE(
+      origin_trials_
+          .GetPersistedTrialsForOrigin(trial_enabled_origin_, kValidTime)
+          .empty());
+}
+
+TEST_F(OriginTrialsTest, EnabledTrialsArePersisted) {
+  std::vector<base::StringPiece> tokens = {kFrobulatePersistentToken};
+  origin_trials_.PersistTrialsFromTokens(trial_enabled_origin_, tokens,
+                                         kValidTime);
+
+  base::flat_set<std::string> enabled_trials =
+      origin_trials_.GetPersistedTrialsForOrigin(trial_enabled_origin_,
+                                                 kValidTime);
+  ASSERT_EQ(1ul, enabled_trials.size());
+  EXPECT_TRUE(enabled_trials.contains(kPersistentTrialName));
+}
+
+TEST_F(OriginTrialsTest, OnlyPersistentTrialsAreEnabled) {
+  std::vector<base::StringPiece> tokens = {kFrobulateToken,
+                                           kFrobulatePersistentToken};
+  origin_trials_.PersistTrialsFromTokens(trial_enabled_origin_, tokens,
+                                         kValidTime);
+
+  base::flat_set<std::string> enabled_trials =
+      origin_trials_.GetPersistedTrialsForOrigin(trial_enabled_origin_,
+                                                 kValidTime);
+  ASSERT_EQ(1ul, enabled_trials.size());
+  EXPECT_TRUE(enabled_trials.contains(kPersistentTrialName));
+  EXPECT_FALSE(enabled_trials.contains(kNonPersistentTrialName));
+}
+
+TEST_F(OriginTrialsTest, ResetClearsPersistedTrials) {
+  std::vector<base::StringPiece> tokens = {kFrobulatePersistentToken};
+  origin_trials_.PersistTrialsFromTokens(trial_enabled_origin_, tokens,
+                                         kValidTime);
+
+  EXPECT_FALSE(
+      origin_trials_
+          .GetPersistedTrialsForOrigin(trial_enabled_origin_, kValidTime)
+          .empty());
+
+  tokens = {};
+  origin_trials_.PersistTrialsFromTokens(trial_enabled_origin_, tokens,
+                                         kValidTime);
+
+  EXPECT_TRUE(
+      origin_trials_
+          .GetPersistedTrialsForOrigin(trial_enabled_origin_, kValidTime)
+          .empty());
+}
+
+TEST_F(OriginTrialsTest, TrialNotEnabledByDefault) {
+  EXPECT_FALSE(origin_trials_.IsTrialPersistedForOrigin(
+      trial_enabled_origin_, kPersistentTrialName, kValidTime));
+}
+
+TEST_F(OriginTrialsTest, TrialEnablesFeature) {
+  std::vector<base::StringPiece> tokens = {kFrobulatePersistentToken};
+  origin_trials_.PersistTrialsFromTokens(trial_enabled_origin_, tokens,
+                                         kValidTime);
+
+  EXPECT_TRUE(origin_trials_.IsTrialPersistedForOrigin(
+      trial_enabled_origin_, kPersistentTrialName, kValidTime));
+}
+
+TEST_F(OriginTrialsTest, TrialDoesNotEnableOtherFeatures) {
+  std::vector<base::StringPiece> tokens = {kFrobulatePersistentToken};
+  origin_trials_.PersistTrialsFromTokens(trial_enabled_origin_, tokens,
+                                         kValidTime);
+
+  EXPECT_FALSE(origin_trials_.IsTrialPersistedForOrigin(
+      trial_enabled_origin_, kNonPersistentTrialName, kValidTime));
+}
+
+// Check that a stored trial name is not returned if that trial is no longer
+// valid or configured to be persistent
+TEST_F(OriginTrialsTest, StoredEnabledTrialNotReturnedIfNoLongerPersistent) {
+  std::unique_ptr<test::TestPersistenceProvider> persistence_provider =
+      std::make_unique<test::TestPersistenceProvider>();
+
+  base::Time token_expiry = base::Time::FromTimeT(2000000000);
+  base::flat_set<PersistedTrialToken> stored_tokens = {
+      {kNonPersistentTrialName, token_expiry,
+       blink::TrialToken::UsageRestriction::kNone, kDummyTokenSignature},
+      {kInvalidTrialName, token_expiry,
+       blink::TrialToken::UsageRestriction::kNone, kDummyTokenSignature},
+      {kPersistentTrialName, token_expiry,
+       blink::TrialToken::UsageRestriction::kNone, kDummyTokenSignature}};
+  persistence_provider->SavePersistentTrialTokens(trial_enabled_origin_,
+                                                  stored_tokens);
+
+  OriginTrials origin_trials(std::move(persistence_provider),
+                             std::make_unique<blink::TrialTokenValidator>());
+  base::flat_set<std::string> enabled_trials =
+      origin_trials.GetPersistedTrialsForOrigin(trial_enabled_origin_,
+                                                kValidTime);
+  ASSERT_EQ(1ul, enabled_trials.size());
+  EXPECT_EQ(kPersistentTrialName, *(enabled_trials.begin()));
+}
+
+// Check that a saved trial name is not returned if it has been disabled by
+// policy
+TEST_F(OriginTrialsTest, DisabledTrialsNotReturned) {
+  std::unique_ptr<test::TestPersistenceProvider> persistence_provider =
+      std::make_unique<test::TestPersistenceProvider>();
+
+  base::Time token_expiry = base::Time::FromTimeT(2000000000);
+  base::flat_set<PersistedTrialToken> stored_tokens = {
+      {kPersistentTrialName, token_expiry,
+       blink::TrialToken::UsageRestriction::kNone, kDummyTokenSignature}};
+  persistence_provider->SavePersistentTrialTokens(trial_enabled_origin_,
+                                                  stored_tokens);
+
+  origin_trial_policy_.DisableTrial(kPersistentTrialName);
+
+  OriginTrials origin_trials(std::move(persistence_provider),
+                             std::make_unique<blink::TrialTokenValidator>());
+  base::flat_set<std::string> enabled_trials =
+      origin_trials.GetPersistedTrialsForOrigin(trial_enabled_origin_,
+                                                kValidTime);
+  EXPECT_TRUE(enabled_trials.empty());
+}
+
+// Check that a saved token is not returned if its signature has been disabled
+// by policy
+TEST_F(OriginTrialsTest, DisabledTokensNotReturned) {
+  std::unique_ptr<test::TestPersistenceProvider> persistence_provider =
+      std::make_unique<test::TestPersistenceProvider>();
+
+  base::Time token_expiry = base::Time::FromTimeT(2000000000);
+  base::flat_set<PersistedTrialToken> stored_tokens = {
+      {kPersistentTrialName, token_expiry,
+       blink::TrialToken::UsageRestriction::kNone, kDummyTokenSignature}};
+  persistence_provider->SavePersistentTrialTokens(trial_enabled_origin_,
+                                                  stored_tokens);
+
+  origin_trial_policy_.DisableToken(kDummyTokenSignature);
+
+  OriginTrials origin_trials(std::move(persistence_provider),
+                             std::make_unique<blink::TrialTokenValidator>());
+  base::flat_set<std::string> enabled_trials =
+      origin_trials.GetPersistedTrialsForOrigin(trial_enabled_origin_,
+                                                kValidTime);
+  EXPECT_TRUE(enabled_trials.empty());
+}
+
+TEST_F(OriginTrialsTest, UserDisabledTokensNotReturned) {
+  std::unique_ptr<test::TestPersistenceProvider> persistence_provider =
+      std::make_unique<test::TestPersistenceProvider>();
+
+  base::Time token_expiry = base::Time::FromTimeT(2000000000);
+  base::flat_set<PersistedTrialToken> stored_tokens = {
+      {kPersistentTrialName, token_expiry,
+       blink::TrialToken::UsageRestriction::kSubset, kDummyTokenSignature}};
+  persistence_provider->SavePersistentTrialTokens(trial_enabled_origin_,
+                                                  stored_tokens);
+
+  origin_trial_policy_.DisableTrialForUser(kPersistentTrialName);
+
+  OriginTrials origin_trials(std::move(persistence_provider),
+                             std::make_unique<blink::TrialTokenValidator>());
+  base::flat_set<std::string> enabled_trials =
+      origin_trials.GetPersistedTrialsForOrigin(trial_enabled_origin_,
+                                                kValidTime);
+  EXPECT_TRUE(enabled_trials.empty());
+}
+
+TEST_F(OriginTrialsTest, GracePeriodIsRespected) {
+  std::vector<base::StringPiece> tokens = {kFrobulateManualCompletionToken};
+  origin_trials_.PersistTrialsFromTokens(trial_enabled_origin_, tokens,
+                                         kValidTime);
+
+  base::flat_set<std::string> enabled_trials =
+      origin_trials_.GetPersistedTrialsForOrigin(trial_enabled_origin_,
+                                                 kExpiryTime);
+  EXPECT_EQ(1ul, enabled_trials.size())
+      << "Expect trial to be valid at the expiry time limit";
+
+  base::Time in_grace_period = kExpiryTime + base::Days(1);
+  enabled_trials = origin_trials_.GetPersistedTrialsForOrigin(
+      trial_enabled_origin_, in_grace_period);
+  EXPECT_EQ(1ul, enabled_trials.size())
+      << "Expect trial to be valid within the grace period";
+
+  base::Time end_of_grace_period = kExpiryTime + blink::kExpiryGracePeriod;
+  enabled_trials = origin_trials_.GetPersistedTrialsForOrigin(
+      trial_enabled_origin_, end_of_grace_period);
+  EXPECT_EQ(0ul, enabled_trials.size())
+      << "Do not expect the trial to be valid after the grace period ends";
+}
+
+}  // namespace
+}  // namespace origin_trials
\ No newline at end of file
diff --git a/components/origin_trials/common/DEPS b/components/origin_trials/common/DEPS
new file mode 100644
index 0000000..1e4fbf9
--- /dev/null
+++ b/components/origin_trials/common/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  # Specific import to get the trial_token UsageRestriction enum
+  "+third_party/blink/public/common/origin_trials/trial_token.h",
+]
diff --git a/components/origin_trials/common/origin_trials_persistence_provider.h b/components/origin_trials/common/origin_trials_persistence_provider.h
new file mode 100644
index 0000000..94f57d2
--- /dev/null
+++ b/components/origin_trials/common/origin_trials_persistence_provider.h
@@ -0,0 +1,34 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ORIGIN_TRIALS_COMMON_ORIGIN_TRIALS_PERSISTENCE_PROVIDER_H_
+#define COMPONENTS_ORIGIN_TRIALS_COMMON_ORIGIN_TRIALS_PERSISTENCE_PROVIDER_H_
+
+#include "base/containers/flat_set.h"
+#include "components/origin_trials/common/persisted_trial_token.h"
+
+namespace url {
+class Origin;
+}
+
+namespace origin_trials {
+
+class OriginTrialsPersistenceProvider {
+ public:
+  virtual ~OriginTrialsPersistenceProvider() = default;
+
+  // Return the list of persistent origin trial tokens that were previously
+  // saved for |origin|.
+  virtual base::flat_set<PersistedTrialToken> GetPersistentTrialTokens(
+      const url::Origin& origin) const = 0;
+
+  // Save the list of enabled trial tokens for |origin|.
+  virtual void SavePersistentTrialTokens(
+      const url::Origin& origin,
+      const base::flat_set<PersistedTrialToken> tokens) = 0;
+};
+
+}  // namespace origin_trials
+
+#endif  // COMPONENTS_ORIGIN_TRIALS_COMMON_ORIGIN_TRIALS_PERSISTENCE_PROVIDER_H_
diff --git a/components/origin_trials/common/persisted_trial_token.cc b/components/origin_trials/common/persisted_trial_token.cc
new file mode 100644
index 0000000..96cb855
--- /dev/null
+++ b/components/origin_trials/common/persisted_trial_token.cc
@@ -0,0 +1,22 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/origin_trials/common/persisted_trial_token.h"
+
+namespace origin_trials {
+
+bool operator<(const PersistedTrialToken& a, const PersistedTrialToken& b) {
+  if (a.trial_name != b.trial_name) {
+    return a.trial_name < b.trial_name;
+  }
+  if (a.token_expiry != b.token_expiry) {
+    return a.token_expiry < b.token_expiry;
+  }
+  if (a.usage_restriction != b.usage_restriction) {
+    return a.usage_restriction < b.usage_restriction;
+  }
+  return a.token_signature < b.token_signature;
+}
+
+}  // namespace origin_trials
diff --git a/components/origin_trials/common/persisted_trial_token.h b/components/origin_trials/common/persisted_trial_token.h
new file mode 100644
index 0000000..3bf3945
--- /dev/null
+++ b/components/origin_trials/common/persisted_trial_token.h
@@ -0,0 +1,37 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ORIGIN_TRIALS_COMMON_PERSISTED_TRIAL_TOKEN_H_
+#define COMPONENTS_ORIGIN_TRIALS_COMMON_PERSISTED_TRIAL_TOKEN_H_
+
+#include <string>
+
+#include "base/time/time.h"
+#include "third_party/blink/public/common/origin_trials/trial_token.h"
+
+namespace origin_trials {
+
+// Parsed information about a token to be persisted.
+struct PersistedTrialToken {
+  std::string trial_name;
+  base::Time token_expiry;
+  blink::TrialToken::UsageRestriction usage_restriction;
+  std::string token_signature;
+
+  PersistedTrialToken(std::string name,
+                      base::Time expiry,
+                      blink::TrialToken::UsageRestriction usage,
+                      std::string signature)
+      : trial_name(std::move(name)),
+        token_expiry(expiry),
+        usage_restriction(usage),
+        token_signature(std::move(signature)) {}
+};
+
+// Comparison operator to let us store PersistedTokens in a flat_set
+bool operator<(const PersistedTrialToken& a, const PersistedTrialToken& b);
+
+}  // namespace origin_trials
+
+#endif  // COMPONENTS_ORIGIN_TRIALS_COMMON_PERSISTED_TRIAL_TOKEN_H_
diff --git a/components/origin_trials/common/persisted_trial_token_unittest.cc b/components/origin_trials/common/persisted_trial_token_unittest.cc
new file mode 100644
index 0000000..b03d6e6
--- /dev/null
+++ b/components/origin_trials/common/persisted_trial_token_unittest.cc
@@ -0,0 +1,67 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/origin_trials/common/persisted_trial_token.h"
+
+#include <string>
+
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace origin_trials {
+
+namespace {
+
+TEST(PersistedTrialTokenTest, TestLessThan) {
+  base::Time expiry = base::Time::Now();
+  base::Time higher_expiry = expiry + base::Hours(1);
+  std::string signature = "signature_a";
+  std::string higher_signature = "signature_b";
+
+  blink::TrialToken::UsageRestriction restriction_none =
+      blink::TrialToken::UsageRestriction::kNone;
+  blink::TrialToken::UsageRestriction restriction_subset =
+      blink::TrialToken::UsageRestriction::kSubset;
+
+  // Tokens should be sorted by name all else being equal
+  EXPECT_LT(PersistedTrialToken("a", expiry, restriction_none, signature),
+            PersistedTrialToken("b", expiry, restriction_none, signature));
+  // Tokens should be sorted by expiry all else being equal
+  EXPECT_LT(
+      PersistedTrialToken("a", expiry, restriction_none, signature),
+      PersistedTrialToken("a", higher_expiry, restriction_none, signature));
+  // Tokens should be sorted by usage restriction all else being equal
+  EXPECT_LT(PersistedTrialToken("a", expiry, restriction_none, signature),
+            PersistedTrialToken("a", expiry, restriction_subset, signature));
+  // Tokens should be sorted by signature all else being equal
+  EXPECT_LT(
+      PersistedTrialToken("a", expiry, restriction_none, signature),
+      PersistedTrialToken("a", expiry, restriction_none, higher_signature));
+
+  // Name should be the primary sorting factor
+  EXPECT_LT(
+      PersistedTrialToken("a", higher_expiry, restriction_none, signature),
+      PersistedTrialToken("b", expiry, restriction_none, signature));
+  EXPECT_LT(PersistedTrialToken("a", expiry, restriction_subset, signature),
+            PersistedTrialToken("b", expiry, restriction_none, signature));
+  EXPECT_LT(
+      PersistedTrialToken("a", expiry, restriction_none, higher_signature),
+      PersistedTrialToken("b", expiry, restriction_none, signature));
+
+  // Expiry should be the secondary sorting factor
+  EXPECT_LT(
+      PersistedTrialToken("a", expiry, restriction_subset, signature),
+      PersistedTrialToken("a", higher_expiry, restriction_none, signature));
+  EXPECT_LT(
+      PersistedTrialToken("a", expiry, restriction_none, higher_signature),
+      PersistedTrialToken("a", higher_expiry, restriction_none, signature));
+  // Subset should be the third sorting factor
+  EXPECT_LT(
+      PersistedTrialToken("a", expiry, restriction_none, higher_signature),
+      PersistedTrialToken("a", expiry, restriction_subset, signature));
+}
+
+}  // namespace
+
+}  // namespace origin_trials
diff --git a/components/origin_trials/test/BUILD.gn b/components/origin_trials/test/BUILD.gn
new file mode 100644
index 0000000..003886f
--- /dev/null
+++ b/components/origin_trials/test/BUILD.gn
@@ -0,0 +1,17 @@
+# Copyright 2022 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+testonly = true
+
+source_set("test") {
+  sources = [
+    "test_persistence_provider.cc",
+    "test_persistence_provider.h",
+  ]
+  deps = [
+    "//base",
+    "//components/origin_trials:common",
+    "//url",
+  ]
+}
diff --git a/components/origin_trials/test/DEPS b/components/origin_trials/test/DEPS
new file mode 100644
index 0000000..02bf1cbe
--- /dev/null
+++ b/components/origin_trials/test/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+components/origin_trials/common",
+]
diff --git a/components/origin_trials/test/test_persistence_provider.cc b/components/origin_trials/test/test_persistence_provider.cc
new file mode 100644
index 0000000..5a3b78c6
--- /dev/null
+++ b/components/origin_trials/test/test_persistence_provider.cc
@@ -0,0 +1,35 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/origin_trials/test/test_persistence_provider.h"
+
+namespace origin_trials::test {
+
+TestPersistenceProvider::TestPersistenceProvider() = default;
+
+TestPersistenceProvider::~TestPersistenceProvider() = default;
+
+base::flat_set<origin_trials::PersistedTrialToken>
+TestPersistenceProvider::GetPersistentTrialTokens(
+    const url::Origin& origin) const {
+  std::map<url::Origin,
+           base::flat_set<origin_trials::PersistedTrialToken>>::const_iterator
+      entry = storage_.find(origin);
+  if (entry != storage_.end()) {
+    return entry->second;
+  }
+  return {};
+}
+
+void TestPersistenceProvider::SavePersistentTrialTokens(
+    const url::Origin& origin,
+    const base::flat_set<origin_trials::PersistedTrialToken> tokens) {
+  if (tokens.empty()) {
+    storage_.erase(origin);
+  } else {
+    storage_[origin] = tokens;
+  }
+}
+
+}  // namespace origin_trials::test
diff --git a/components/origin_trials/test/test_persistence_provider.h b/components/origin_trials/test/test_persistence_provider.h
new file mode 100644
index 0000000..1a9a6f06
--- /dev/null
+++ b/components/origin_trials/test/test_persistence_provider.h
@@ -0,0 +1,43 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ORIGIN_TRIALS_TEST_TEST_PERSISTENCE_PROVIDER_H_
+#define COMPONENTS_ORIGIN_TRIALS_TEST_TEST_PERSISTENCE_PROVIDER_H_
+
+#include <map>
+#include <string>
+
+#include "base/containers/flat_set.h"
+#include "base/strings/string_piece.h"
+#include "components/origin_trials/common/origin_trials_persistence_provider.h"
+#include "components/origin_trials/common/persisted_trial_token.h"
+#include "url/origin.h"
+
+namespace origin_trials::test {
+
+// Class that provides in-memory implementation of
+// OriginTrialsPersistenceProvider to be used for testing.
+class TestPersistenceProvider : public OriginTrialsPersistenceProvider {
+ public:
+  TestPersistenceProvider();
+  TestPersistenceProvider(const TestPersistenceProvider&) = delete;
+  TestPersistenceProvider(const TestPersistenceProvider&&) = delete;
+
+  ~TestPersistenceProvider() override;
+
+  // OriginTrialsPersistenceProvider
+  base::flat_set<origin_trials::PersistedTrialToken> GetPersistentTrialTokens(
+      const url::Origin& origin) const override;
+  void SavePersistentTrialTokens(
+      const url::Origin& origin,
+      const base::flat_set<origin_trials::PersistedTrialToken> tokens) override;
+
+ private:
+  std::map<url::Origin, base::flat_set<origin_trials::PersistedTrialToken>>
+      storage_;
+};
+
+}  // namespace origin_trials::test
+
+#endif  // COMPONENTS_ORIGIN_TRIALS_TEST_TEST_PERSISTENCE_PROVIDER_H_
diff --git a/components/password_manager/core/browser/password_list_sorter.cc b/components/password_manager/core/browser/password_list_sorter.cc
index 0c47725..d5b0085 100644
--- a/components/password_manager/core/browser/password_list_sorter.cc
+++ b/components/password_manager/core/browser/password_list_sorter.cc
@@ -10,6 +10,7 @@
 #include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_ui_utils.h"
+#include "components/password_manager/core/browser/ui/credential_ui_entry.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "url/gurl.h"
 
@@ -27,10 +28,23 @@
 }  // namespace
 
 std::string CreateSortKey(const PasswordForm& form, IgnoreStore ignore_store) {
-  auto [shown_origin, link_url] = GetShownOriginAndLinkUrl(form);
+  std::string key = CreateSortKey(CredentialUIEntry(form));
+
+  if (ignore_store)
+    return key;
+
+  if (form.in_store == PasswordForm::Store::kAccountStore) {
+    return key + kSortKeyPartsSeparator + std::string("account");
+  }
+
+  return key;
+}
+
+std::string CreateSortKey(const CredentialUIEntry& credential) {
+  std::string shown_origin = GetShownOrigin(credential);
 
   const auto facet_uri =
-      FacetURI::FromPotentiallyInvalidSpec(form.signon_realm);
+      FacetURI::FromPotentiallyInvalidSpec(credential.signon_realm);
   const bool is_android_uri = facet_uri.IsValidAndroidFacetURI();
 
   if (is_android_uri) {
@@ -57,23 +71,19 @@
   key += is_android_uri ? facet_uri.canonical_spec()
                         : SplitByDotAndReverse(shown_origin);
 
-  if (!form.blocked_by_user) {
-    key += kSortKeyPartsSeparator + base::UTF16ToUTF8(form.username_value) +
-           kSortKeyPartsSeparator + base::UTF16ToUTF8(form.password_value);
+  if (!credential.blocked_by_user) {
+    key += kSortKeyPartsSeparator + base::UTF16ToUTF8(credential.username) +
+           kSortKeyPartsSeparator + base::UTF16ToUTF8(credential.password);
 
     key += kSortKeyPartsSeparator;
-    if (!form.federation_origin.opaque())
-      key += form.federation_origin.host();
+    if (!credential.federation_origin.opaque())
+      key += credential.federation_origin.host();
     else
       key += kSortKeyNoFederationSymbol;
   }
 
   // To separate HTTP/HTTPS credentials, add the scheme to the key.
-  key += kSortKeyPartsSeparator + link_url.scheme();
-
-  if (!ignore_store && form.in_store == PasswordForm::Store::kAccountStore) {
-    key += kSortKeyPartsSeparator + std::string("account");
-  }
+  key += kSortKeyPartsSeparator + GetShownUrl(credential).scheme();
 
   return key;
 }
@@ -85,7 +95,7 @@
       keys_to_forms;
   keys_to_forms.reserve(list->size());
   for (auto& form : *list) {
-    std::string key = CreateSortKey(*form);
+    std::string key = CreateSortKey(*form, IgnoreStore(false));
     keys_to_forms.emplace_back(std::move(key), std::move(form));
   }
 
diff --git a/components/password_manager/core/browser/password_list_sorter.h b/components/password_manager/core/browser/password_list_sorter.h
index 5b0a1e1b..5603b2a 100644
--- a/components/password_manager/core/browser/password_list_sorter.h
+++ b/components/password_manager/core/browser/password_list_sorter.h
@@ -15,6 +15,7 @@
 namespace password_manager {
 
 struct PasswordForm;
+struct CredentialUIEntry;
 
 // Multimap from sort key to password forms.
 using DuplicatesMap = std::multimap<std::string, std::unique_ptr<PasswordForm>>;
@@ -28,8 +29,10 @@
 // credentials the canocial spec is included.
 // If |ignore_store| is true, forms differing only by the originating password
 // store will map to the same key.
-std::string CreateSortKey(const PasswordForm& form,
-                          IgnoreStore ignore_store = IgnoreStore(false));
+std::string CreateSortKey(const PasswordForm& form, IgnoreStore ignore_store);
+// Same as |CreateSortKey| for |PasswordForm| but it always ignores store.
+// TODO(vsemeniuk): find a better name for this function.
+std::string CreateSortKey(const CredentialUIEntry& credential);
 
 // Sort entries of |list| based on sort key. The key is the concatenation of
 // origin, entry type (non-Android credential, Android w/ affiliated web realm
diff --git a/components/password_manager/core/browser/ui/credential_ui_entry.cc b/components/password_manager/core/browser/ui/credential_ui_entry.cc
index 2b5d8d8..33997dae 100644
--- a/components/password_manager/core/browser/ui/credential_ui_entry.cc
+++ b/components/password_manager/core/browser/ui/credential_ui_entry.cc
@@ -9,6 +9,11 @@
 
 namespace password_manager {
 
+bool CredentialUIEntry::Less::operator()(const CredentialUIEntry& lhs,
+                                         const CredentialUIEntry& rhs) const {
+  return CreateSortKey(lhs) < CreateSortKey(rhs);
+}
+
 CredentialUIEntry::CredentialUIEntry() = default;
 
 CredentialUIEntry::CredentialUIEntry(const PasswordForm& form)
@@ -21,8 +26,7 @@
       federation_origin(form.federation_origin),
       password_issues(form.password_issues),
       blocked_by_user(form.blocked_by_user),
-      last_used_time(form.date_last_used),
-      key_(CredentialKey(CreateSortKey(form, IgnoreStore(true)))) {
+      last_used_time(form.date_last_used) {
   // Only one-note with an empty `unique_display_name` is supported in the
   // settings UI.
   for (const PasswordNote& n : form.notes) {
@@ -68,7 +72,7 @@
 }
 
 bool operator==(const CredentialUIEntry& lhs, const CredentialUIEntry& rhs) {
-  return lhs.key() == rhs.key();
+  return CreateSortKey(lhs) == CreateSortKey(rhs);
 }
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/ui/credential_ui_entry.h b/components/password_manager/core/browser/ui/credential_ui_entry.h
index f1418dd..346b648 100644
--- a/components/password_manager/core/browser/ui/credential_ui_entry.h
+++ b/components/password_manager/core/browser/ui/credential_ui_entry.h
@@ -14,17 +14,13 @@
 
 namespace password_manager {
 
-using CredentialKey = base::StrongAlias<class CredentialKeyTag, std::string>;
-
 // Simple struct that represents an entry inside Settings UI. Allows implicit
 // construction from PasswordForm for convenience. A single entry might
 // correspond to multiple PasswordForms.
 struct CredentialUIEntry {
   struct Less {
     bool operator()(const CredentialUIEntry& lhs,
-                    const CredentialUIEntry& rhs) const {
-      return lhs.key() < rhs.key();
-    }
+                    const CredentialUIEntry& rhs) const;
   };
 
   CredentialUIEntry();
@@ -84,17 +80,11 @@
   // site. Defaults to |date_created|.
   base::Time last_used_time;
 
-  const CredentialKey& key() const { return key_; }
-
   // Information about password insecurities.
   bool IsLeaked() const;
   bool IsPhished() const;
 
   const base::Time GetLastLeakedOrPhishedTime() const;
-
- private:
-  // Key which is constructed from an original PasswordForm.
-  CredentialKey key_;
 };
 
 bool operator==(const CredentialUIEntry& lhs, const CredentialUIEntry& rhs);
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager.cc b/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
index 030e7b6..b4c8450 100644
--- a/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
+++ b/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
@@ -288,7 +288,7 @@
       password_issue.second.is_muted = IsMuted(true);
     }
   }
-  return presenter_->EditSavedCredentials(updated_credential) ==
+  return presenter_->EditSavedCredentials(credential, updated_credential) ==
          SavedPasswordsPresenter::EditResult::kSuccess;
 }
 
@@ -301,7 +301,7 @@
       password_issue.second.is_muted = IsMuted(false);
     }
   }
-  return presenter_->EditSavedCredentials(updated_credential) ==
+  return presenter_->EditSavedCredentials(credential, updated_credential) ==
          SavedPasswordsPresenter::EditResult::kSuccess;
 }
 
diff --git a/components/password_manager/core/browser/ui/saved_passwords_presenter.cc b/components/password_manager/core/browser/ui/saved_passwords_presenter.cc
index 229ee37..fd34e24 100644
--- a/components/password_manager/core/browser/ui/saved_passwords_presenter.cc
+++ b/components/password_manager/core/browser/ui/saved_passwords_presenter.cc
@@ -135,12 +135,12 @@
 bool SavedPasswordsPresenter::RemoveCredential(
     const CredentialUIEntry& credential) {
   const auto range =
-      sort_key_to_password_forms_.equal_range(credential.key().value());
+      sort_key_to_password_forms_.equal_range(CreateSortKey(credential));
   bool removed = false;
   undo_helper_->StartGroupingActions();
   std::for_each(range.first, range.second, [&](const auto& pair) {
     const auto& current_form = pair.second;
-    // Make sure |form| and |current_form| share the same store.
+    // Make sure |credential| and |current_form| share the same store.
     if (credential.stored_in.contains(current_form.in_store)) {
       // |current_form| is unchanged result obtained from
       // 'OnGetPasswordStoreResultsFrom'. So it can be present only in one store
@@ -199,9 +199,10 @@
 
 bool SavedPasswordsPresenter::EditPassword(const PasswordForm& form,
                                            std::u16string new_password) {
-  CredentialUIEntry entry(form);
-  entry.password = new_password;
-  return EditSavedCredentials(entry) == EditResult::kSuccess;
+  CredentialUIEntry updated_credential(form);
+  updated_credential.password = new_password;
+  return EditSavedCredentials(CredentialUIEntry(form), updated_credential) ==
+         EditResult::kSuccess;
 }
 
 bool SavedPasswordsPresenter::EditSavedPasswords(
@@ -210,37 +211,39 @@
     const std::u16string& new_password) {
   // TODO(crbug.com/1184691): Change desktop settings and maybe iOS to use this
   // presenter for updating the duplicates.
-  CredentialUIEntry entry(form);
-  entry.password = new_password;
-  entry.username = new_username;
-  return EditSavedCredentials(entry) == EditResult::kSuccess;
+  CredentialUIEntry updated_credential(form);
+  updated_credential.password = new_password;
+  updated_credential.username = new_username;
+  return EditSavedCredentials(CredentialUIEntry(form), updated_credential) ==
+         EditResult::kSuccess;
 }
 
 SavedPasswordsPresenter::EditResult
 SavedPasswordsPresenter::EditSavedCredentials(
-    const CredentialUIEntry& credential) {
+    const CredentialUIEntry& original_credential,
+    const CredentialUIEntry& updated_credential) {
   std::vector<PasswordForm> forms_to_change =
-      GetCorrespondingPasswordForms(credential.key());
+      GetCorrespondingPasswordForms(original_credential);
   if (forms_to_change.empty())
     return EditResult::kNotFound;
 
-  IsUsernameChanged username_changed(credential.username !=
-                                     forms_to_change[0].username_value);
-  IsPasswordChanged password_changed(credential.password !=
-                                     forms_to_change[0].password_value);
+  IsUsernameChanged username_changed(updated_credential.username !=
+                                     original_credential.username);
+  IsPasswordChanged password_changed(updated_credential.password !=
+                                     original_credential.password);
   IsPasswordNoteChanged note_changed =
-      IsNoteChanged(forms_to_change[0], credential.note);
+      IsNoteChanged(forms_to_change[0], updated_credential.note);
 
   bool issues_changed =
-      credential.password_issues != forms_to_change[0].password_issues;
+      updated_credential.password_issues != forms_to_change[0].password_issues;
 
   // Password can't be empty.
-  if (credential.password.empty())
+  if (updated_credential.password.empty())
     return EditResult::kEmptyPassword;
 
   // Username can't be changed to the existing one.
-  if (username_changed &&
-      IsUsernameAlreadyUsed(passwords_, forms_to_change, credential.username)) {
+  if (username_changed && IsUsernameAlreadyUsed(passwords_, forms_to_change,
+                                                updated_credential.username)) {
     return EditResult::kAlreadyExisits;
   }
 
@@ -257,25 +260,25 @@
     PasswordForm new_form = old_form;
 
     if (issues_changed) {
-      new_form.password_issues = credential.password_issues;
+      new_form.password_issues = updated_credential.password_issues;
     }
 
     if (password_changed) {
-      new_form.password_value = credential.password;
+      new_form.password_value = updated_credential.password;
       new_form.date_password_modified = base::Time::Now();
       new_form.password_issues.clear();
     }
 
     if (note_changed) {
       PasswordNoteAction note_action =
-          UpdateNoteInPasswordForm(new_form, credential.note);
+          UpdateNoteInPasswordForm(new_form, updated_credential.note);
       metrics_util::LogPasswordNoteActionInSettings(note_action);
     }
 
     // An updated username implies a change in the primary key, thus we need
     // to make sure to call the right API.
     if (username_changed) {
-      new_form.username_value = credential.username;
+      new_form.username_value = updated_credential.username;
       // Phished and leaked issues are no longer relevant on username change.
       // Weak and reused issues are still relevant.
       new_form.password_issues.erase(InsecureType::kPhished);
@@ -332,8 +335,9 @@
 
 std::vector<PasswordForm>
 SavedPasswordsPresenter::GetCorrespondingPasswordForms(
-    const CredentialKey& key) const {
-  const auto range = sort_key_to_password_forms_.equal_range(key.value());
+    const CredentialUIEntry& credential) const {
+  const auto range =
+      sort_key_to_password_forms_.equal_range(CreateSortKey(credential));
   std::vector<PasswordForm> forms;
   base::ranges::transform(range.first, range.second, std::back_inserter(forms),
                           [](const auto& pair) { return pair.second; });
diff --git a/components/password_manager/core/browser/ui/saved_passwords_presenter.h b/components/password_manager/core/browser/ui/saved_passwords_presenter.h
index bf65d80..5a40829 100644
--- a/components/password_manager/core/browser/ui/saved_passwords_presenter.h
+++ b/components/password_manager/core/browser/ui/saved_passwords_presenter.h
@@ -112,9 +112,11 @@
                           const std::u16string& new_username,
                           const std::u16string& new_password);
 
-  // Modifies all the saved credentials with a matching key. Only username,
-  // password and notes are modified.
-  EditResult EditSavedCredentials(const CredentialUIEntry& credential);
+  // Modifies all the saved credentials matching |original_credential| to
+  // |updated_credential|. Only username, password, notes and password issues
+  // are modifiable.
+  EditResult EditSavedCredentials(const CredentialUIEntry& original_credential,
+                                  const CredentialUIEntry& updated_credential);
 
   // Returns a list of the currently saved credentials.
   SavedPasswordsView GetSavedPasswords() const;
@@ -129,9 +131,9 @@
   std::vector<PasswordForm> GetUniquePasswordForms() const;
   std::vector<CredentialUIEntry> GetSavedCredentials() const;
 
-  // Returns PasswordForms corresponding to |key|.
+  // Returns PasswordForms corresponding to |credential|.
   std::vector<PasswordForm> GetCorrespondingPasswordForms(
-      const CredentialKey& key) const;
+      const CredentialUIEntry& credential) const;
 
   // Allows clients and register and de-register themselves.
   void AddObserver(Observer* observer);
diff --git a/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc b/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc
index f2c79b24..6e1b2c28 100644
--- a/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc
+++ b/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc
@@ -287,7 +287,8 @@
   EXPECT_CALL(observer, OnEdited(updated_username));
   EXPECT_CALL(observer, OnSavedPasswordsChanged(ElementsAre(updated_username)));
   EXPECT_EQ(SavedPasswordsPresenter::EditResult::kSuccess,
-            presenter().EditSavedCredentials(credential_to_edit));
+            presenter().EditSavedCredentials(CredentialUIEntry(form),
+                                             credential_to_edit));
   RunUntilIdle();
   EXPECT_THAT(
       store().stored_passwords(),
@@ -342,7 +343,8 @@
   EXPECT_CALL(observer, OnEdited(updated_username));
   EXPECT_CALL(observer, OnSavedPasswordsChanged(ElementsAre(updated_username)));
   EXPECT_EQ(SavedPasswordsPresenter::EditResult::kSuccess,
-            presenter().EditSavedCredentials(credential_to_edit));
+            presenter().EditSavedCredentials(CredentialUIEntry(form),
+                                             credential_to_edit));
   RunUntilIdle();
   EXPECT_THAT(
       store().stored_passwords(),
@@ -384,7 +386,8 @@
   EXPECT_CALL(observer, OnEdited(updated_password));
   EXPECT_CALL(observer, OnSavedPasswordsChanged(ElementsAre(updated_password)));
   EXPECT_EQ(SavedPasswordsPresenter::EditResult::kSuccess,
-            presenter().EditSavedCredentials(credential_to_edit));
+            presenter().EditSavedCredentials(CredentialUIEntry(form),
+                                             credential_to_edit));
   RunUntilIdle();
   EXPECT_THAT(
       store().stored_passwords(),
@@ -415,7 +418,8 @@
 
   base::HistogramTester histogram_tester;
   EXPECT_EQ(SavedPasswordsPresenter::EditResult::kSuccess,
-            presenter().EditSavedCredentials(credential_to_edit));
+            presenter().EditSavedCredentials(CredentialUIEntry(form),
+                                             credential_to_edit));
   RunUntilIdle();
 
   // The note with the non-empty display name should be untouched. Another note
@@ -448,7 +452,8 @@
   credential_to_edit.note = PasswordNote(kNewNoteValue, base::Time::Now());
 
   EXPECT_EQ(SavedPasswordsPresenter::EditResult::kSuccess,
-            presenter().EditSavedCredentials(credential_to_edit));
+            presenter().EditSavedCredentials(CredentialUIEntry(form),
+                                             credential_to_edit));
   RunUntilIdle();
 
   PasswordForm expected_updated_form = form;
@@ -477,7 +482,8 @@
 
   base::HistogramTester histogram_tester;
   EXPECT_EQ(SavedPasswordsPresenter::EditResult::kSuccess,
-            presenter().EditSavedCredentials(credential_to_edit));
+            presenter().EditSavedCredentials(CredentialUIEntry(form),
+                                             credential_to_edit));
   RunUntilIdle();
 
   PasswordForm expected_updated_form = form;
@@ -504,7 +510,8 @@
 
   base::HistogramTester histogram_tester;
   EXPECT_EQ(SavedPasswordsPresenter::EditResult::kSuccess,
-            presenter().EditSavedCredentials(credential_to_edit));
+            presenter().EditSavedCredentials(CredentialUIEntry(form),
+                                             credential_to_edit));
 
   RunUntilIdle();
 
@@ -580,7 +587,8 @@
   EXPECT_CALL(observer, OnEdited(updated_both));
   EXPECT_CALL(observer, OnSavedPasswordsChanged(ElementsAre(updated_both)));
   EXPECT_EQ(SavedPasswordsPresenter::EditResult::kSuccess,
-            presenter().EditSavedCredentials(credential_to_edit));
+            presenter().EditSavedCredentials(CredentialUIEntry(form),
+                                             credential_to_edit));
   RunUntilIdle();
   EXPECT_THAT(store().stored_passwords(),
               ElementsAre(Pair(form.signon_realm, ElementsAre(updated_both))));
@@ -610,7 +618,8 @@
   // Updating the form with the username which is already used for same website
   // fails.
   EXPECT_EQ(SavedPasswordsPresenter::EditResult::kAlreadyExisits,
-            presenter().EditSavedCredentials(credential_to_edit));
+            presenter().EditSavedCredentials(CredentialUIEntry(form1),
+                                             credential_to_edit));
   RunUntilIdle();
   EXPECT_THAT(store().stored_passwords(),
               ElementsAre(Pair(form1.signon_realm, ElementsAre(form1, form2))));
@@ -619,7 +628,8 @@
   credential_to_edit.password = u"";
   // Updating the form with the empty password fails.
   EXPECT_EQ(SavedPasswordsPresenter::EditResult::kEmptyPassword,
-            presenter().EditSavedCredentials(credential_to_edit));
+            presenter().EditSavedCredentials(CredentialUIEntry(form1),
+                                             credential_to_edit));
   RunUntilIdle();
   EXPECT_THAT(store().stored_passwords(),
               ElementsAre(Pair(form1.signon_realm, ElementsAre(form1, form2))));
@@ -646,7 +656,8 @@
   EXPECT_CALL(observer, OnSavedPasswordsChanged).Times(0);
 
   EXPECT_EQ(SavedPasswordsPresenter::EditResult::kNothingChanged,
-            presenter().EditSavedCredentials(CredentialUIEntry(form)));
+            presenter().EditSavedCredentials(CredentialUIEntry(form),
+                                             CredentialUIEntry(form)));
   RunUntilIdle();
   histogram_tester.ExpectBucketCount(
       "PasswordManager.PasswordEditUpdatedValues",
@@ -659,7 +670,7 @@
   CredentialUIEntry credential(
       CreateTestPasswordForm(PasswordForm::Store::kProfileStore));
   EXPECT_EQ(SavedPasswordsPresenter::EditResult::kNotFound,
-            presenter().EditSavedCredentials(credential));
+            presenter().EditSavedCredentials(credential, credential));
 }
 
 TEST_F(SavedPasswordsPresenterTest, EditUpdatesDuplicates) {
@@ -1042,7 +1053,8 @@
   credential_to_edit.username = new_username;
 
   EXPECT_EQ(SavedPasswordsPresenter::EditResult::kSuccess,
-            presenter().EditSavedCredentials(credential_to_edit));
+            presenter().EditSavedCredentials(
+                CredentialUIEntry(profile_store_form), credential_to_edit));
   RunUntilIdle();
   profile_store_form.username_value = new_username;
   profile_store_form.password_issues.clear();
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc
index b8d8145..6e630dc 100644
--- a/components/password_manager/core/common/password_manager_features.cc
+++ b/components/password_manager/core/common/password_manager_features.cc
@@ -171,6 +171,10 @@
 const base::Feature kSecondaryServerFieldPredictions = {
     "SecondaryServerFieldPredictions", base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Enables the password strength indicator.
+const base::Feature kPasswordStrengthIndicator = {
+    "PasswordStrengthIndicator", base::FEATURE_DISABLED_BY_DEFAULT};
+
 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
 // Enables biometric authentication in settings
 const base::Feature kEnableBiometricAuthenticationInSettings = {
diff --git a/components/password_manager/core/common/password_manager_features.h b/components/password_manager/core/common/password_manager_features.h
index 6fda581..1cfb6fc4 100644
--- a/components/password_manager/core/common/password_manager_features.h
+++ b/components/password_manager/core/common/password_manager_features.h
@@ -52,6 +52,7 @@
 extern const base::Feature kPasswordReuseDetectionEnabled;
 extern const base::Feature kPasswordsAccountStorageRevisedOptInFlow;
 extern const base::Feature kPasswordScriptsFetching;
+extern const base::Feature kPasswordStrengthIndicator;
 extern const base::Feature kRecoverFromNeverSaveAndroid;
 extern const base::Feature kSecondaryServerFieldPredictions;
 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
diff --git a/components/renderer_context_menu/render_view_context_menu_base.cc b/components/renderer_context_menu/render_view_context_menu_base.cc
index 9600ae2..92bf0cec 100644
--- a/components/renderer_context_menu/render_view_context_menu_base.cc
+++ b/components/renderer_context_menu/render_view_context_menu_base.cc
@@ -247,13 +247,13 @@
                                                bool enabled,
                                                bool hidden,
                                                const std::u16string& label) {
-  absl::optional<size_t> index = menu_model_.GetIndexOfCommandId(command_id);
-  if (!index.has_value())
+  int index = menu_model_.GetIndexOfCommandId(command_id);
+  if (index == -1)
     return;
 
-  menu_model_.SetLabel(index.value(), label);
-  menu_model_.SetEnabledAt(index.value(), enabled);
-  menu_model_.SetVisibleAt(index.value(), !hidden);
+  menu_model_.SetLabel(index, label);
+  menu_model_.SetEnabledAt(index, enabled);
+  menu_model_.SetVisibleAt(index, !hidden);
   if (toolkit_delegate_) {
 #if BUILDFLAG(IS_MAC)
     toolkit_delegate_->UpdateMenuItem(command_id, enabled, hidden, label);
@@ -265,11 +265,11 @@
 
 void RenderViewContextMenuBase::UpdateMenuIcon(int command_id,
                                                const ui::ImageModel& icon) {
-  absl::optional<size_t> index = menu_model_.GetIndexOfCommandId(command_id);
-  if (!index.has_value())
+  int index = menu_model_.GetIndexOfCommandId(command_id);
+  if (index == -1)
     return;
 
-  menu_model_.SetIcon(index.value(), icon);
+  menu_model_.SetIcon(index, icon);
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   if (toolkit_delegate_)
     toolkit_delegate_->RebuildMenu();
@@ -277,11 +277,11 @@
 }
 
 void RenderViewContextMenuBase::RemoveMenuItem(int command_id) {
-  absl::optional<size_t> index = menu_model_.GetIndexOfCommandId(command_id);
-  if (!index.has_value())
+  int index = menu_model_.GetIndexOfCommandId(command_id);
+  if (index == -1)
     return;
 
-  menu_model_.RemoveItemAt(index.value());
+  menu_model_.RemoveItemAt(index);
   if (toolkit_delegate_)
     toolkit_delegate_->RebuildMenu();
 }
@@ -289,15 +289,15 @@
 // Removes separators so that if there are two separators next to each other,
 // only one of them remains.
 void RenderViewContextMenuBase::RemoveAdjacentSeparators() {
-  size_t num_items = menu_model_.GetItemCount();
-  for (size_t index = num_items; index > 1; --index) {
-    ui::MenuModel::ItemType curr_type = menu_model_.GetTypeAt(index - 1);
-    ui::MenuModel::ItemType prev_type = menu_model_.GetTypeAt(index - 2);
+  int num_items = menu_model_.GetItemCount();
+  for (int index = num_items - 1; index > 0; --index) {
+    ui::MenuModel::ItemType curr_type = menu_model_.GetTypeAt(index);
+    ui::MenuModel::ItemType prev_type = menu_model_.GetTypeAt(index - 1);
 
     if (curr_type == ui::MenuModel::ItemType::TYPE_SEPARATOR &&
         prev_type == ui::MenuModel::ItemType::TYPE_SEPARATOR) {
       // We found adjacent separators, remove the one at the bottom.
-      menu_model_.RemoveItemAt(index - 1);
+      menu_model_.RemoveItemAt(index);
     }
   }
 
@@ -306,16 +306,16 @@
 }
 
 void RenderViewContextMenuBase::RemoveSeparatorBeforeMenuItem(int command_id) {
-  absl::optional<size_t> index = menu_model_.GetIndexOfCommandId(command_id);
-  // Ignore if command not found or if it's the first menu item.
-  if (!index.has_value() || index == size_t{0})
+  int index = menu_model_.GetIndexOfCommandId(command_id);
+  // Ignore if command not found (index == -1) or if it's the first menu item.
+  if (index <= 0)
     return;
 
-  ui::MenuModel::ItemType prev_type = menu_model_.GetTypeAt(index.value() - 1);
+  ui::MenuModel::ItemType prev_type = menu_model_.GetTypeAt(index - 1);
   if (prev_type != ui::MenuModel::ItemType::TYPE_SEPARATOR)
     return;
 
-  menu_model_.RemoveItemAt(index.value() - 1);
+  menu_model_.RemoveItemAt(index - 1);
 
   if (toolkit_delegate_)
     toolkit_delegate_->RebuildMenu();
@@ -408,7 +408,7 @@
 }
 
 void RenderViewContextMenuBase::OnMenuWillShow(ui::SimpleMenuModel* source) {
-  for (size_t i = 0; i < source->GetItemCount(); ++i) {
+  for (int i = 0; i < source->GetItemCount(); ++i) {
     if (source->IsVisibleAt(i) &&
         source->GetTypeAt(i) != ui::MenuModel::TYPE_SEPARATOR) {
       RecordShownItem(source->GetCommandIdAt(i),
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h
index a71d331a..216d89c 100644
--- a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h
+++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h
@@ -197,6 +197,8 @@
                            RetryBackoff);
   FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceDelegateChromeOSTest,
                            BackOffIsTriggerredForTransientErrors);
+  FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceDelegateTest,
+                           UpdateAuthError_TransientErrors);
 
   // List of observers to notify when refresh token availability changes.
   // Makes sure list is empty on destruction.
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_unittest.cc b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_unittest.cc
index 4b0432e..27048180 100644
--- a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_unittest.cc
+++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_unittest.cc
@@ -15,26 +15,36 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+class MockOAuth2TokenServiceObserver
+    : public ProfileOAuth2TokenServiceObserver {
+ public:
+  MOCK_METHOD2(OnAuthErrorChanged,
+               void(const CoreAccountId&, const GoogleServiceAuthError&));
+};
+
+class ProfileOAuth2TokenServiceDelegateTest : public testing::Test {
+ public:
+  ProfileOAuth2TokenServiceDelegateTest() { delegate_.AddObserver(&observer_); }
+
+  ~ProfileOAuth2TokenServiceDelegateTest() override {
+    delegate_.RemoveObserver(&observer_);
+  }
+
+  // Note: Tests in this suite tests the default base implementation of
+  //       'ProfileOAuth2TokenServiceDelegate'.
+  FakeProfileOAuth2TokenServiceDelegate delegate_;
+  MockOAuth2TokenServiceObserver observer_;
+};
+
 // The default implementation of
 // ProfileOAuth2TokenServiceDelegate::InvalidateTokensForMultilogin is used on
 // mobile where refresh tokens are not accessible. This test checks that refresh
 // tokens are not affected on INVALID_TOKENS Multilogin error.
-TEST(ProfileOAuth2TokenServiceDelegateTest, InvalidateTokensForMultilogin) {
-  class TestOAuth2TokenServiceObserver
-      : public ProfileOAuth2TokenServiceObserver {
-   public:
-    MOCK_METHOD2(OnAuthErrorChanged,
-                 void(const CoreAccountId&, const GoogleServiceAuthError&));
-  };
-
-  FakeProfileOAuth2TokenServiceDelegate delegate;
-
-  TestOAuth2TokenServiceObserver observer;
-  delegate.AddObserver(&observer);
+TEST_F(ProfileOAuth2TokenServiceDelegateTest, InvalidateTokensForMultilogin) {
   // Check that OnAuthErrorChanged is not fired from
   // InvalidateTokensForMultilogin and refresh tokens are not set in error.
   EXPECT_CALL(
-      observer,
+      observer_,
       OnAuthErrorChanged(::testing::_,
                          GoogleServiceAuthError(
                              GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)))
@@ -43,15 +53,125 @@
   const CoreAccountId account_id1("account_id1");
   const CoreAccountId account_id2("account_id2");
 
-  delegate.UpdateCredentials(account_id1, "refresh_token1");
-  delegate.UpdateCredentials(account_id2, "refresh_token2");
+  delegate_.UpdateCredentials(account_id1, "refresh_token1");
+  delegate_.UpdateCredentials(account_id2, "refresh_token2");
 
-  delegate.InvalidateTokenForMultilogin(account_id1);
+  delegate_.InvalidateTokenForMultilogin(account_id1);
 
-  EXPECT_EQ(delegate.GetAuthError(account_id1).state(),
+  EXPECT_EQ(delegate_.GetAuthError(account_id1).state(),
             GoogleServiceAuthError::NONE);
-  EXPECT_EQ(delegate.GetAuthError(account_id2).state(),
+  EXPECT_EQ(delegate_.GetAuthError(account_id2).state(),
             GoogleServiceAuthError::NONE);
+}
 
-  delegate.RemoveObserver(&observer);
+const GoogleServiceAuthError::State table[] = {
+    GoogleServiceAuthError::NONE,
+    GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
+    GoogleServiceAuthError::USER_NOT_SIGNED_UP,
+    GoogleServiceAuthError::CONNECTION_FAILED,
+    GoogleServiceAuthError::SERVICE_UNAVAILABLE,
+    GoogleServiceAuthError::REQUEST_CANCELED,
+    GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE,
+    GoogleServiceAuthError::SERVICE_ERROR,
+};
+
+TEST_F(ProfileOAuth2TokenServiceDelegateTest, UpdateAuthError_PersistenErrors) {
+  const CoreAccountId account_id("account_id");
+  delegate_.UpdateCredentials(account_id, "refresh_token");
+
+  static_assert(
+      std::size(table) == GoogleServiceAuthError::NUM_STATES -
+                              GoogleServiceAuthError::kDeprecatedStateCount,
+      "table size should match number of auth error types");
+
+  for (GoogleServiceAuthError::State state : table) {
+    GoogleServiceAuthError error(state);
+    if (!error.IsPersistentError())
+      continue;
+
+    EXPECT_CALL(observer_, OnAuthErrorChanged(account_id, error)).Times(1);
+
+    delegate_.UpdateAuthError(account_id, error);
+    EXPECT_EQ(delegate_.GetAuthError(account_id), error);
+    // Backoff only used for transient errors.
+    EXPECT_EQ(delegate_.BackoffEntry()->failure_count(), 0);
+    testing::Mock::VerifyAndClearExpectations(&observer_);
+  }
+}
+
+TEST_F(ProfileOAuth2TokenServiceDelegateTest, UpdateAuthError_TransientErrors) {
+  const CoreAccountId account_id("account_id");
+  delegate_.UpdateCredentials(account_id, "refresh_token");
+
+  static_assert(
+      std::size(table) == GoogleServiceAuthError::NUM_STATES -
+                              GoogleServiceAuthError::kDeprecatedStateCount,
+      "table size should match number of auth error types");
+
+  EXPECT_TRUE(delegate_.BackoffEntry());
+  int failure_count = 0;
+  for (GoogleServiceAuthError::State state : table) {
+    GoogleServiceAuthError error(state);
+    if (!error.IsTransientError())
+      continue;
+
+    EXPECT_CALL(observer_, OnAuthErrorChanged(account_id, ::testing::_))
+        .Times(0);
+
+    failure_count++;
+    delegate_.UpdateAuthError(account_id, error);
+    EXPECT_EQ(delegate_.GetAuthError(account_id),
+              GoogleServiceAuthError::AuthErrorNone());
+    EXPECT_GT(delegate_.BackoffEntry()->GetTimeUntilRelease(),
+              base::TimeDelta());
+    EXPECT_EQ(delegate_.BackoffEntry()->failure_count(), failure_count);
+    EXPECT_EQ(delegate_.BackOffError(), error);
+    testing::Mock::VerifyAndClearExpectations(&observer_);
+  }
+}
+
+TEST_F(ProfileOAuth2TokenServiceDelegateTest,
+       UpdateAuthError_RefreshTokenNotAvailable) {
+  const CoreAccountId account_id("account_id");
+  EXPECT_FALSE(delegate_.RefreshTokenIsAvailable(account_id));
+  EXPECT_CALL(observer_, OnAuthErrorChanged(::testing::_, ::testing::_))
+      .Times(0);
+  delegate_.UpdateAuthError(
+      account_id,
+      GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
+  EXPECT_EQ(delegate_.GetAuthError(account_id),
+            GoogleServiceAuthError::AuthErrorNone());
+  testing::Mock::VerifyAndClearExpectations(&observer_);
+  // Backoff only used for transient errors.
+  EXPECT_EQ(delegate_.BackoffEntry()->failure_count(), 0);
+}
+
+TEST_F(ProfileOAuth2TokenServiceDelegateTest, AuthErrorChanged) {
+  const CoreAccountId account_id("account_id");
+  delegate_.UpdateCredentials(account_id, "refresh_token");
+
+  GoogleServiceAuthError error(
+      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
+  EXPECT_CALL(observer_, OnAuthErrorChanged(account_id, error)).Times(1);
+  delegate_.UpdateAuthError(account_id, error);
+  EXPECT_EQ(delegate_.GetAuthError(account_id), error);
+
+  // Update the error but without changing it should not fire a notification.
+  delegate_.UpdateAuthError(account_id, error);
+  testing::Mock::VerifyAndClearExpectations(&observer_);
+
+  // Change the error.
+  EXPECT_CALL(
+      observer_,
+      OnAuthErrorChanged(account_id, GoogleServiceAuthError::AuthErrorNone()))
+      .Times(1);
+  delegate_.UpdateAuthError(account_id,
+                            GoogleServiceAuthError::AuthErrorNone());
+  EXPECT_EQ(delegate_.GetAuthError(account_id),
+            GoogleServiceAuthError::AuthErrorNone());
+
+  // Update to none again should not fire any notification.
+  delegate_.UpdateAuthError(account_id,
+                            GoogleServiceAuthError::AuthErrorNone());
+  testing::Mock::VerifyAndClearExpectations(&observer_);
 }
diff --git a/components/stylus_handwriting/android/java/src/org/chromium/components/stylus_handwriting/DirectWritingConstants.java b/components/stylus_handwriting/android/java/src/org/chromium/components/stylus_handwriting/DirectWritingConstants.java
index 24751c2..f84803d0 100644
--- a/components/stylus_handwriting/android/java/src/org/chromium/components/stylus_handwriting/DirectWritingConstants.java
+++ b/components/stylus_handwriting/android/java/src/org/chromium/components/stylus_handwriting/DirectWritingConstants.java
@@ -15,6 +15,11 @@
     static final String SERVICE_CLS_NAME =
             "com.samsung.android.directwriting.service.DirectWritingService";
 
+    // The fingerprint of valid Samsung Direct Writing service package.
+    static final String SERVICE_PKG_SHA_256_FINGERPRINT =
+            "C8:A2:E9:BC:CF:59:7C:2F:B6:DC:66:BE:E2:93:FC:13"
+            + ":F2:FC:47:EC:77:BC:6B:2B:0D:52:C1:1F:51:19:2A:B8";
+
     /**
      * Set text and selection from service callback
      */
diff --git a/components/stylus_handwriting/android/java/src/org/chromium/components/stylus_handwriting/DirectWritingServiceBinder.java b/components/stylus_handwriting/android/java/src/org/chromium/components/stylus_handwriting/DirectWritingServiceBinder.java
index 4babf79e..3df1adb5 100644
--- a/components/stylus_handwriting/android/java/src/org/chromium/components/stylus_handwriting/DirectWritingServiceBinder.java
+++ b/components/stylus_handwriting/android/java/src/org/chromium/components/stylus_handwriting/DirectWritingServiceBinder.java
@@ -20,6 +20,9 @@
 import android.widget.directwriting.IDirectWritingService;
 
 import org.chromium.base.Log;
+import org.chromium.base.PackageUtils;
+
+import java.util.List;
 
 /**
  * Direct writing Service connection handler class. Takes care of calling DW Service APIs for
@@ -92,10 +95,20 @@
             Log.d(TAG, "bindService already requested");
             return;
         }
+
+        // Verify that connecting service package fingerprint matches with expected fingerprint of
+        // Direct Writing service package. This is to prevent any attacker from spoofing the package
+        // name and tricking Chrome into connecting to it.
+        List<String> fingerprints = PackageUtils.getCertificateSHA256FingerprintForPackage(
+                context.getPackageManager(), DirectWritingConstants.SERVICE_PKG_NAME);
+        if (fingerprints == null || fingerprints.size() > 1
+                || !fingerprints.get(0).equals(
+                        DirectWritingConstants.SERVICE_PKG_SHA_256_FINGERPRINT)) {
+            Log.e(TAG, "Don't connect to service due to package fingerprint mismatch");
+            return;
+        }
         try {
             Intent intent = new Intent();
-            // TODO(mahesh.ma): Check the signature of Direct writing service so that a non-Samsung
-            // device cannot trick us into connecting to it.
             intent.setComponent(new ComponentName(DirectWritingConstants.SERVICE_PKG_NAME,
                     DirectWritingConstants.SERVICE_CLS_NAME));
             context.bindService(intent, mConnection, BIND_AUTO_CREATE);
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn
index 4f1789b..6ab684c 100644
--- a/components/sync/BUILD.gn
+++ b/components/sync/BUILD.gn
@@ -94,6 +94,8 @@
     "test/model/fake_model_type_sync_bridge.h",
     "test/model/fake_sync_change_processor.cc",
     "test/model/fake_sync_change_processor.h",
+    "test/model/forwarding_model_type_change_processor.cc",
+    "test/model/forwarding_model_type_change_processor.h",
     "test/model/mock_model_type_change_processor.cc",
     "test/model/mock_model_type_change_processor.h",
     "test/model/model_type_store_test_util.cc",
diff --git a/components/sync/model/client_tag_based_model_type_processor.cc b/components/sync/model/client_tag_based_model_type_processor.cc
index c434ef6..97b8381 100644
--- a/components/sync/model/client_tag_based_model_type_processor.cc
+++ b/components/sync/model/client_tag_based_model_type_processor.cc
@@ -512,6 +512,18 @@
   entity_tracker_->RemoveEntityForClientTagHash(client_tag_hash);
 }
 
+std::vector<std::string>
+ClientTagBasedModelTypeProcessor::GetAllTrackedStorageKeys() const {
+  std::vector<std::string> storage_keys;
+  if (entity_tracker_) {
+    for (const ProcessorEntity* entity :
+         entity_tracker_->GetAllEntitiesIncludingTombstones()) {
+      storage_keys.push_back(entity->storage_key());
+    }
+  }
+  return storage_keys;
+}
+
 bool ClientTagBasedModelTypeProcessor::IsEntityUnsynced(
     const std::string& storage_key) {
   if (!entity_tracker_) {
diff --git a/components/sync/model/client_tag_based_model_type_processor.h b/components/sync/model/client_tag_based_model_type_processor.h
index ab8d053..dcbf54aa 100644
--- a/components/sync/model/client_tag_based_model_type_processor.h
+++ b/components/sync/model/client_tag_based_model_type_processor.h
@@ -9,6 +9,7 @@
 #include <memory>
 #include <string>
 #include <unordered_set>
+#include <vector>
 
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
@@ -74,6 +75,7 @@
   void UntrackEntityForStorageKey(const std::string& storage_key) override;
   void UntrackEntityForClientTagHash(
       const ClientTagHash& client_tag_hash) override;
+  std::vector<std::string> GetAllTrackedStorageKeys() const override;
   bool IsEntityUnsynced(const std::string& storage_key) override;
   base::Time GetEntityCreationTime(
       const std::string& storage_key) const override;
diff --git a/components/sync/model/model_type_change_processor.h b/components/sync/model/model_type_change_processor.h
index 74ceec4f..46d9d5f 100644
--- a/components/sync/model/model_type_change_processor.h
+++ b/components/sync/model/model_type_change_processor.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
@@ -67,6 +68,9 @@
   virtual void UntrackEntityForClientTagHash(
       const ClientTagHash& client_tag_hash) = 0;
 
+  // Returns the storage keys for all tracked entities (including tombstones).
+  virtual std::vector<std::string> GetAllTrackedStorageKeys() const = 0;
+
   // Returns true if a tracked entity has local changes. A commit may or may not
   // be in progress at this time.
   virtual bool IsEntityUnsynced(const std::string& storage_key) = 0;
diff --git a/components/sync/test/model/forwarding_model_type_change_processor.cc b/components/sync/test/model/forwarding_model_type_change_processor.cc
new file mode 100644
index 0000000..e0d10be8
--- /dev/null
+++ b/components/sync/test/model/forwarding_model_type_change_processor.cc
@@ -0,0 +1,112 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sync/test/model/forwarding_model_type_change_processor.h"
+
+#include <utility>
+
+#include "components/sync/model/metadata_batch.h"
+#include "components/sync/protocol/entity_data.h"
+
+namespace syncer {
+
+ForwardingModelTypeChangeProcessor::ForwardingModelTypeChangeProcessor(
+    ModelTypeChangeProcessor* other)
+    : other_(other) {}
+ForwardingModelTypeChangeProcessor::~ForwardingModelTypeChangeProcessor() =
+    default;
+
+void ForwardingModelTypeChangeProcessor::Put(
+    const std::string& client_tag,
+    std::unique_ptr<EntityData> entity_data,
+    MetadataChangeList* metadata_change_list) {
+  other_->Put(client_tag, std::move(entity_data), metadata_change_list);
+}
+
+void ForwardingModelTypeChangeProcessor::Delete(
+    const std::string& client_tag,
+    MetadataChangeList* metadata_change_list) {
+  other_->Delete(client_tag, metadata_change_list);
+}
+
+void ForwardingModelTypeChangeProcessor::UpdateStorageKey(
+    const EntityData& entity_data,
+    const std::string& storage_key,
+    MetadataChangeList* metadata_change_list) {
+  other_->UpdateStorageKey(entity_data, storage_key, metadata_change_list);
+}
+
+void ForwardingModelTypeChangeProcessor::UntrackEntityForStorageKey(
+    const std::string& storage_key) {
+  other_->UntrackEntityForStorageKey(storage_key);
+}
+
+void ForwardingModelTypeChangeProcessor::UntrackEntityForClientTagHash(
+    const ClientTagHash& client_tag_hash) {
+  other_->UntrackEntityForClientTagHash(client_tag_hash);
+}
+
+std::vector<std::string>
+ForwardingModelTypeChangeProcessor::GetAllTrackedStorageKeys() const {
+  return other_->GetAllTrackedStorageKeys();
+}
+
+bool ForwardingModelTypeChangeProcessor::IsEntityUnsynced(
+    const std::string& storage_key) {
+  return other_->IsEntityUnsynced(storage_key);
+}
+
+base::Time ForwardingModelTypeChangeProcessor::GetEntityCreationTime(
+    const std::string& storage_key) const {
+  return other_->GetEntityCreationTime(storage_key);
+}
+
+base::Time ForwardingModelTypeChangeProcessor::GetEntityModificationTime(
+    const std::string& storage_key) const {
+  return other_->GetEntityModificationTime(storage_key);
+}
+
+void ForwardingModelTypeChangeProcessor::OnModelStarting(
+    ModelTypeSyncBridge* bridge) {
+  other_->OnModelStarting(bridge);
+}
+
+void ForwardingModelTypeChangeProcessor::ModelReadyToSync(
+    std::unique_ptr<MetadataBatch> batch) {
+  other_->ModelReadyToSync(std::move(batch));
+}
+
+bool ForwardingModelTypeChangeProcessor::IsTrackingMetadata() const {
+  return other_->IsTrackingMetadata();
+}
+
+std::string ForwardingModelTypeChangeProcessor::TrackedAccountId() const {
+  return other_->TrackedAccountId();
+}
+
+std::string ForwardingModelTypeChangeProcessor::TrackedCacheGuid() const {
+  return other_->TrackedCacheGuid();
+}
+
+void ForwardingModelTypeChangeProcessor::ReportError(const ModelError& error) {
+  other_->ReportError(error);
+}
+
+absl::optional<ModelError> ForwardingModelTypeChangeProcessor::GetError()
+    const {
+  return other_->GetError();
+}
+
+base::WeakPtr<ModelTypeControllerDelegate>
+ForwardingModelTypeChangeProcessor::GetControllerDelegate() {
+  return other_->GetControllerDelegate();
+}
+
+const sync_pb::EntitySpecifics&
+ForwardingModelTypeChangeProcessor::GetPossiblyTrimmedRemoteSpecifics(
+    const std::string& storage_key) const {
+  return other_->GetPossiblyTrimmedRemoteSpecifics(storage_key);
+}
+
+}  // namespace syncer
diff --git a/components/sync/test/model/forwarding_model_type_change_processor.h b/components/sync/test/model/forwarding_model_type_change_processor.h
new file mode 100644
index 0000000..62e5576a
--- /dev/null
+++ b/components/sync/test/model/forwarding_model_type_change_processor.h
@@ -0,0 +1,60 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SYNC_TEST_MODEL_FORWARDING_MODEL_TYPE_CHANGE_PROCESSOR_H_
+#define COMPONENTS_SYNC_TEST_MODEL_FORWARDING_MODEL_TYPE_CHANGE_PROCESSOR_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/memory/raw_ptr.h"
+#include "components/sync/model/model_type_change_processor.h"
+
+namespace syncer {
+
+// A ModelTypeChangeProcessor implementation that forwards all calls to another
+// ModelTypeChangeProcessor instance, useful when a client wants ownership of
+// the processor.
+class ForwardingModelTypeChangeProcessor : public ModelTypeChangeProcessor {
+ public:
+  // |other| must not be nullptr and must outlive this object.
+  explicit ForwardingModelTypeChangeProcessor(ModelTypeChangeProcessor* other);
+  ~ForwardingModelTypeChangeProcessor() override;
+
+  void Put(const std::string& client_tag,
+           std::unique_ptr<EntityData> entity_data,
+           MetadataChangeList* metadata_change_list) override;
+  void Delete(const std::string& client_tag,
+              MetadataChangeList* metadata_change_list) override;
+  void UpdateStorageKey(const EntityData& entity_data,
+                        const std::string& storage_key,
+                        MetadataChangeList* metadata_change_list) override;
+  void UntrackEntityForStorageKey(const std::string& storage_key) override;
+  void UntrackEntityForClientTagHash(
+      const ClientTagHash& client_tag_hash) override;
+  std::vector<std::string> GetAllTrackedStorageKeys() const override;
+  bool IsEntityUnsynced(const std::string& storage_key) override;
+  base::Time GetEntityCreationTime(
+      const std::string& storage_key) const override;
+  base::Time GetEntityModificationTime(
+      const std::string& storage_key) const override;
+  void OnModelStarting(ModelTypeSyncBridge* bridge) override;
+  void ModelReadyToSync(std::unique_ptr<MetadataBatch> batch) override;
+  bool IsTrackingMetadata() const override;
+  std::string TrackedAccountId() const override;
+  std::string TrackedCacheGuid() const override;
+  void ReportError(const ModelError& error) override;
+  absl::optional<ModelError> GetError() const override;
+  base::WeakPtr<ModelTypeControllerDelegate> GetControllerDelegate() override;
+  const sync_pb::EntitySpecifics& GetPossiblyTrimmedRemoteSpecifics(
+      const std::string& storage_key) const override;
+
+ private:
+  raw_ptr<ModelTypeChangeProcessor> other_;
+};
+
+}  // namespace syncer
+
+#endif  // COMPONENTS_SYNC_TEST_MODEL_FORWARDING_MODEL_TYPE_CHANGE_PROCESSOR_H_
diff --git a/components/sync/test/model/mock_model_type_change_processor.cc b/components/sync/test/model/mock_model_type_change_processor.cc
index 391b16b6..2ae29e6e 100644
--- a/components/sync/test/model/mock_model_type_change_processor.cc
+++ b/components/sync/test/model/mock_model_type_change_processor.cc
@@ -6,107 +6,15 @@
 
 #include <utility>
 
-#include "base/bind.h"
 #include "base/memory/ptr_util.h"
-#include "base/memory/raw_ptr.h"
 #include "components/sync/model/metadata_batch.h"
+#include "components/sync/test/model/forwarding_model_type_change_processor.h"
 
 namespace syncer {
-namespace {
 
 using testing::_;
 using testing::Invoke;
 
-class ForwardingModelTypeChangeProcessor : public ModelTypeChangeProcessor {
- public:
-  // |other| must not be nullptr and must outlive this object.
-  explicit ForwardingModelTypeChangeProcessor(ModelTypeChangeProcessor* other)
-      : other_(other) {}
-  ~ForwardingModelTypeChangeProcessor() override = default;
-
-  void Put(const std::string& client_tag,
-           std::unique_ptr<EntityData> entity_data,
-           MetadataChangeList* metadata_change_list) override {
-    other_->Put(client_tag, std::move(entity_data), metadata_change_list);
-  }
-
-  void Delete(const std::string& client_tag,
-              MetadataChangeList* metadata_change_list) override {
-    other_->Delete(client_tag, metadata_change_list);
-  }
-
-  void UpdateStorageKey(const EntityData& entity_data,
-                        const std::string& storage_key,
-                        MetadataChangeList* metadata_change_list) override {
-    other_->UpdateStorageKey(entity_data, storage_key, metadata_change_list);
-  }
-
-  void UntrackEntityForStorageKey(const std::string& storage_key) override {
-    other_->UntrackEntityForStorageKey(storage_key);
-  }
-
-  void UntrackEntityForClientTagHash(
-      const ClientTagHash& client_tag_hash) override {
-    other_->UntrackEntityForClientTagHash(client_tag_hash);
-  }
-
-  bool IsEntityUnsynced(const std::string& storage_key) override {
-    return other_->IsEntityUnsynced(storage_key);
-  }
-
-  base::Time GetEntityCreationTime(
-      const std::string& storage_key) const override {
-    return other_->GetEntityCreationTime(storage_key);
-  }
-
-  base::Time GetEntityModificationTime(
-      const std::string& storage_key) const override {
-    return other_->GetEntityModificationTime(storage_key);
-  }
-
-  void OnModelStarting(ModelTypeSyncBridge* bridge) override {
-    other_->OnModelStarting(bridge);
-  }
-
-  void ModelReadyToSync(std::unique_ptr<MetadataBatch> batch) override {
-    other_->ModelReadyToSync(std::move(batch));
-  }
-
-  bool IsTrackingMetadata() const override {
-    return other_->IsTrackingMetadata();
-  }
-
-  std::string TrackedAccountId() const override {
-    return other_->TrackedAccountId();
-  }
-
-  std::string TrackedCacheGuid() const override {
-    return other_->TrackedCacheGuid();
-  }
-
-  void ReportError(const ModelError& error) override {
-    other_->ReportError(error);
-  }
-
-  absl::optional<ModelError> GetError() const override {
-    return other_->GetError();
-  }
-
-  base::WeakPtr<ModelTypeControllerDelegate> GetControllerDelegate() override {
-    return other_->GetControllerDelegate();
-  }
-
-  const sync_pb::EntitySpecifics& GetPossiblyTrimmedRemoteSpecifics(
-      const std::string& storage_key) const override {
-    return other_->GetPossiblyTrimmedRemoteSpecifics(storage_key);
-  }
-
- private:
-  raw_ptr<ModelTypeChangeProcessor> other_;
-};
-
-}  // namespace
-
 MockModelTypeChangeProcessor::MockModelTypeChangeProcessor() = default;
 
 MockModelTypeChangeProcessor::~MockModelTypeChangeProcessor() = default;
diff --git a/components/sync/test/model/mock_model_type_change_processor.h b/components/sync/test/model/mock_model_type_change_processor.h
index 3fbb49d..26f783b0 100644
--- a/components/sync/test/model/mock_model_type_change_processor.h
+++ b/components/sync/test/model/mock_model_type_change_processor.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "components/sync/model/metadata_batch.h"
 #include "components/sync/model/model_type_change_processor.h"
@@ -50,6 +51,10 @@
               UntrackEntityForClientTagHash,
               (const ClientTagHash& client_tag_hash),
               (override));
+  MOCK_METHOD(std::vector<std::string>,
+              GetAllTrackedStorageKeys,
+              (),
+              (const override));
   MOCK_METHOD(bool,
               IsEntityUnsynced,
               (const std::string& storage_key),
diff --git a/components/sync_bookmarks/bookmark_model_observer_impl.cc b/components/sync_bookmarks/bookmark_model_observer_impl.cc
index 6072ff4..1035d50a 100644
--- a/components/sync_bookmarks/bookmark_model_observer_impl.cc
+++ b/components/sync_bookmarks/bookmark_model_observer_impl.cc
@@ -502,14 +502,6 @@
   // determined here by comparing hashes.
   if (entity->MatchesSpecificsHash(specifics)) {
     // Specifics haven't actually changed, so the local change can be ignored.
-    //
-    // This is an opportunity to populate the favicon hash in sync metadata if
-    // it hasn't been populated yet. This is needed because the proto field that
-    // stores favicon hashes was introduced late. The fact that hashed specifics
-    // match implies that the favicon (which is part of specifics) must also
-    // match, hence the proto field can be safely populated.
-    bookmark_tracker_->PopulateFaviconHashIfUnset(
-        entity, specifics.bookmark().favicon());
     return;
   }
 
diff --git a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
index 1c79460e..5f61bb1 100644
--- a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
+++ b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
@@ -142,6 +142,10 @@
           .value());
   *bookmark_metadata.mutable_metadata()->mutable_unique_position() =
       unique_position.ToProto();
+  // Required by SyncedBookmarkTracker during validation of local metadata.
+  if (!node->is_folder()) {
+    bookmark_metadata.mutable_metadata()->set_bookmark_favicon_hash(123);
+  }
   return bookmark_metadata;
 }
 
diff --git a/components/sync_bookmarks/synced_bookmark_tracker.cc b/components/sync_bookmarks/synced_bookmark_tracker.cc
index 97884f5..4881c8fb 100644
--- a/components/sync_bookmarks/synced_bookmark_tracker.cc
+++ b/components/sync_bookmarks/synced_bookmark_tracker.cc
@@ -246,13 +246,6 @@
       server_version);
 }
 
-void SyncedBookmarkTracker::PopulateFaviconHashIfUnset(
-    const SyncedBookmarkTrackerEntity* entity,
-    const std::string& favicon_png_bytes) {
-  DCHECK(entity);
-  AsMutableEntity(entity)->PopulateFaviconHashIfUnset(favicon_png_bytes);
-}
-
 void SyncedBookmarkTracker::MarkCommitMayHaveStarted(
     const SyncedBookmarkTrackerEntity* entity) {
   DCHECK(entity);
@@ -517,6 +510,16 @@
       }
     }
 
+    // The code populates |bookmark_favicon_hash| for all new nodes, including
+    // folders, but it is possible that folders are tracked that predate the
+    // introduction of |bookmark_favicon_hash|, which never got it populated
+    // because for some time it got populated opportunistically upon favicon
+    // load, which never triggers for folders.
+    if (!node->is_folder() &&
+        !bookmark_metadata.metadata().has_bookmark_favicon_hash()) {
+      return CorruptionReason::MISSING_FAVICON_HASH;
+    }
+
     auto entity = std::make_unique<SyncedBookmarkTrackerEntity>(
         node, std::move(*bookmark_metadata.mutable_metadata()));
 
diff --git a/components/sync_bookmarks/synced_bookmark_tracker.h b/components/sync_bookmarks/synced_bookmark_tracker.h
index 96efb7b..49a6d95 100644
--- a/components/sync_bookmarks/synced_bookmark_tracker.h
+++ b/components/sync_bookmarks/synced_bookmark_tracker.h
@@ -104,11 +104,6 @@
   void UpdateServerVersion(const SyncedBookmarkTrackerEntity* entity,
                            int64_t server_version);
 
-  // Populates the metadata field representing the hashed favicon. This method
-  // is effectively used to backfill the proto field, which was introduced late.
-  void PopulateFaviconHashIfUnset(const SyncedBookmarkTrackerEntity* entity,
-                                  const std::string& favicon_png_bytes);
-
   // Marks an existing entry that a commit request might have been sent to the
   // server. |entity| must be owned by this tracker.
   void MarkCommitMayHaveStarted(const SyncedBookmarkTrackerEntity* entity);
@@ -236,8 +231,9 @@
     DUPLICATED_CLIENT_TAG_HASH = 10,
     TRACKED_MANAGED_NODE = 11,
     MISSING_CLIENT_TAG_HASH = 12,
+    MISSING_FAVICON_HASH = 13,
 
-    kMaxValue = MISSING_CLIENT_TAG_HASH
+    kMaxValue = MISSING_FAVICON_HASH
   };
 
   SyncedBookmarkTracker(
diff --git a/components/sync_bookmarks/synced_bookmark_tracker_entity.cc b/components/sync_bookmarks/synced_bookmark_tracker_entity.cc
index 9561a2e..8e05503 100644
--- a/components/sync_bookmarks/synced_bookmark_tracker_entity.cc
+++ b/components/sync_bookmarks/synced_bookmark_tracker_entity.cc
@@ -74,15 +74,6 @@
          base::PersistentHash(favicon_png_bytes);
 }
 
-void SyncedBookmarkTrackerEntity::PopulateFaviconHashIfUnset(
-    const std::string& favicon_png_bytes) {
-  if (metadata_.has_bookmark_favicon_hash()) {
-    return;
-  }
-
-  metadata_.set_bookmark_favicon_hash(base::PersistentHash(favicon_png_bytes));
-}
-
 syncer::ClientTagHash SyncedBookmarkTrackerEntity::GetClientTagHash() const {
   return syncer::ClientTagHash::FromHashed(metadata_.client_tag_hash());
 }
diff --git a/components/sync_bookmarks/synced_bookmark_tracker_entity.h b/components/sync_bookmarks/synced_bookmark_tracker_entity.h
index b49d5381..9a370de 100644
--- a/components/sync_bookmarks/synced_bookmark_tracker_entity.h
+++ b/components/sync_bookmarks/synced_bookmark_tracker_entity.h
@@ -80,8 +80,6 @@
     commit_may_have_started_ = value;
   }
 
-  void PopulateFaviconHashIfUnset(const std::string& favicon_png_bytes);
-
   syncer::ClientTagHash GetClientTagHash() const;
 
   // Returns the estimate of dynamically allocated memory in bytes.
diff --git a/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc b/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
index 6ae6a09..d1e04c5a 100644
--- a/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
+++ b/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
@@ -55,8 +55,9 @@
   DUPLICATED_CLIENT_TAG_HASH = 10,
   TRACKED_MANAGED_NODE = 11,
   MISSING_CLIENT_TAG_HASH = 12,
+  MISSING_FAVICON_HASH = 13,
 
-  kMaxValue = MISSING_CLIENT_TAG_HASH
+  kMaxValue = MISSING_FAVICON_HASH
 };
 
 sync_pb::EntitySpecifics GenerateSpecifics(const std::string& title,
@@ -82,6 +83,10 @@
       syncer::ClientTagHash::FromUnhashed(syncer::BOOKMARKS,
                                           node->guid().AsLowercaseString())
           .value());
+  // Required by the validation logic.
+  if (!node->is_folder()) {
+    bookmark_metadata.mutable_metadata()->set_bookmark_favicon_hash(123);
+  }
   return bookmark_metadata;
 }
 
@@ -927,6 +932,34 @@
       /*expected_bucket_count=*/1);
 }
 
+TEST(SyncedBookmarkTrackerTest, ShouldInvalidateMetadataIfMissingFaviconHash) {
+  std::unique_ptr<bookmarks::BookmarkModel> model =
+      bookmarks::TestBookmarkClient::CreateModel();
+
+  const bookmarks::BookmarkNode* bookmark_bar_node = model->bookmark_bar_node();
+  const bookmarks::BookmarkNode* node0 =
+      model->AddURL(/*parent=*/bookmark_bar_node, /*index=*/0, u"Title",
+                    GURL("http://www.url.com"));
+
+  sync_pb::BookmarkModelMetadata model_metadata =
+      CreateMetadataForPermanentNodes(model.get());
+  sync_pb::BookmarkMetadata* node0_metadata =
+      model_metadata.add_bookmarks_metadata();
+  *node0_metadata = CreateNodeMetadata(node0, /*server_id=*/"id0");
+
+  node0_metadata->mutable_metadata()->clear_bookmark_favicon_hash();
+
+  base::HistogramTester histogram_tester;
+  EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
+                  model.get(), std::move(model_metadata)),
+              IsNull());
+
+  histogram_tester.ExpectUniqueSample(
+      "Sync.BookmarksModelMetadataCorruptionReason",
+      /*sample=*/ExpectedCorruptionReason::MISSING_FAVICON_HASH,
+      /*expected_bucket_count=*/1);
+}
+
 TEST(SyncedBookmarkTrackerTest,
      ShouldMatchModelWithUnsyncableNodesAndMetadata) {
   auto client = std::make_unique<bookmarks::TestBookmarkClient>();
@@ -1009,7 +1042,6 @@
   const SyncedBookmarkTrackerEntity* entity =
       tracker->GetEntityForSyncId(kSyncId);
   ASSERT_THAT(entity, NotNull());
-  ASSERT_FALSE(entity->metadata().has_bookmark_favicon_hash());
   ASSERT_FALSE(entity->MatchesFaviconHash(kFaviconPngBytes));
 
   sync_pb::EntitySpecifics specifics = GenerateSpecifics(kTitle, kUrl.spec());
@@ -1022,45 +1054,6 @@
   EXPECT_FALSE(entity->MatchesFaviconHash("otherhash"));
 }
 
-TEST(SyncedBookmarkTrackerTest, ShouldPopulateFaviconHashExplicitly) {
-  const std::string kSyncId = "SYNC_ID";
-  const std::string kFaviconPngBytes = "fakefaviconbytes";
-
-  std::unique_ptr<bookmarks::BookmarkModel> model =
-      bookmarks::TestBookmarkClient::CreateModel();
-
-  const bookmarks::BookmarkNode* bookmark_bar_node = model->bookmark_bar_node();
-  const bookmarks::BookmarkNode* node =
-      model->AddURL(/*parent=*/bookmark_bar_node, /*index=*/0, u"Title",
-                    GURL("http://www.url.com"));
-
-  sync_pb::BookmarkModelMetadata model_metadata =
-      CreateMetadataForPermanentNodes(model.get());
-
-  // Add entry for the URL node.
-  *model_metadata.add_bookmarks_metadata() = CreateNodeMetadata(node, kSyncId);
-
-  std::unique_ptr<SyncedBookmarkTracker> tracker =
-      SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
-          model.get(), std::move(model_metadata));
-  ASSERT_THAT(tracker, NotNull());
-
-  const SyncedBookmarkTrackerEntity* entity =
-      tracker->GetEntityForSyncId(kSyncId);
-  ASSERT_THAT(entity, NotNull());
-  ASSERT_FALSE(entity->metadata().has_bookmark_favicon_hash());
-  ASSERT_FALSE(entity->MatchesFaviconHash(kFaviconPngBytes));
-
-  tracker->PopulateFaviconHashIfUnset(entity, kFaviconPngBytes);
-  EXPECT_TRUE(entity->metadata().has_bookmark_favicon_hash());
-  EXPECT_TRUE(entity->MatchesFaviconHash(kFaviconPngBytes));
-  EXPECT_FALSE(entity->MatchesFaviconHash("otherhash"));
-
-  // Further calls should be ignored.
-  tracker->PopulateFaviconHashIfUnset(entity, "otherpngbytes");
-  EXPECT_TRUE(entity->MatchesFaviconHash(kFaviconPngBytes));
-}
-
 TEST(SyncedBookmarkTrackerTest, ShouldNotReuploadEntitiesAfterMergeAndRestart) {
   base::test::ScopedFeatureList override_features;
   override_features.InitAndEnableFeature(switches::kSyncReuploadBookmarks);
diff --git a/components/sync_device_info/DEPS b/components/sync_device_info/DEPS
index d016c1f..766edb2 100644
--- a/components/sync_device_info/DEPS
+++ b/components/sync_device_info/DEPS
@@ -5,6 +5,7 @@
   "+components/metrics",
   "+components/prefs",
   "+components/sync/base",
+  "+components/sync/engine",
   "+components/sync/invalidations",
   "+components/sync/model",
   "+components/sync/protocol",
diff --git a/components/sync_device_info/device_info_sync_bridge.cc b/components/sync_device_info/device_info_sync_bridge.cc
index 3922345..93b28026 100644
--- a/components/sync_device_info/device_info_sync_bridge.cc
+++ b/components/sync_device_info/device_info_sync_bridge.cc
@@ -18,10 +18,10 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/observer_list.h"
-#include "base/strings/string_util.h"
 #include "base/time/time.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/base/time.h"
+#include "components/sync/engine/commit_and_get_updates_types.h"
 #include "components/sync/model/data_type_activation_request.h"
 #include "components/sync/model/entity_change.h"
 #include "components/sync/model/metadata_batch.h"
@@ -530,6 +530,26 @@
   }
 }
 
+ModelTypeSyncBridge::CommitAttemptFailedBehavior
+DeviceInfoSyncBridge::OnCommitAttemptFailed(
+    syncer::SyncCommitError commit_error) {
+  // DeviceInfo is normally committed once a day and hence it's important to
+  // retry on the next sync cycle in case of auth or network errors. For other
+  // errors, do not retry to prevent blocking sync for other data types if
+  // DeviceInfo entity causes the error. OnCommitAttemptErrors would show that
+  // something is wrong with the DeviceInfo entity from the last commit request
+  // but those errors are not retried at the moment since it's a very tiny
+  // fraction.
+  switch (commit_error) {
+    case syncer::SyncCommitError::kAuthError:
+    case syncer::SyncCommitError::kNetworkError:
+      return CommitAttemptFailedBehavior::kShouldRetryOnNextCycle;
+    case syncer::SyncCommitError::kBadServerResponse:
+    case syncer::SyncCommitError::kServerError:
+      return CommitAttemptFailedBehavior::kDontRetryOnNextCycle;
+  }
+}
+
 bool DeviceInfoSyncBridge::IsSyncing() const {
   // Both conditions are neecessary due to the following possible cases:
   // 1. This method is called from MergeSyncData() when IsTrackingMetadata()
diff --git a/components/sync_device_info/device_info_sync_bridge.h b/components/sync_device_info/device_info_sync_bridge.h
index 9775461..d3422bcc 100644
--- a/components/sync_device_info/device_info_sync_bridge.h
+++ b/components/sync_device_info/device_info_sync_bridge.h
@@ -83,6 +83,8 @@
   std::string GetStorageKey(const EntityData& entity_data) override;
   void ApplyStopSyncChanges(
       std::unique_ptr<MetadataChangeList> delete_metadata_change_list) override;
+  ModelTypeSyncBridge::CommitAttemptFailedBehavior OnCommitAttemptFailed(
+      syncer::SyncCommitError commit_error) override;
 
   // DeviceInfoTracker implementation.
   bool IsSyncing() const override;
diff --git a/components/user_education/common/scoped_new_badge_tracker_base.h b/components/user_education/common/scoped_new_badge_tracker_base.h
index 12d723c4..16efd24 100644
--- a/components/user_education/common/scoped_new_badge_tracker_base.h
+++ b/components/user_education/common/scoped_new_badge_tracker_base.h
@@ -44,7 +44,7 @@
 //
 //   // In OnMenuWillShow(menu):
 //   menu->SetIsNewFeatureAt(
-//       menu->GetIndexOfCommandId(IDC_MY_FEATURE).value(),
+//       menu->GetIndexOfCommandId(IDC_MY_FEATURE),
 //       new_badge_tracker_.TryShowNewBadge(
 //           feature_engagement::kIPHMyFeatureNewBadge,
 //           &ui_features::kMyFeature));
diff --git a/components/web_package/BUILD.gn b/components/web_package/BUILD.gn
index 923b566..f1288842 100644
--- a/components/web_package/BUILD.gn
+++ b/components/web_package/BUILD.gn
@@ -8,6 +8,8 @@
   sources = [
     "input_reader.cc",
     "input_reader.h",
+    "shared_file.cc",
+    "shared_file.h",
     "signed_web_bundles/ed25519_public_key.cc",
     "signed_web_bundles/ed25519_public_key.h",
     "signed_web_bundles/integrity_block_parser.cc",
diff --git a/components/web_package/shared_file.cc b/components/web_package/shared_file.cc
new file mode 100644
index 0000000..f5911cba
--- /dev/null
+++ b/components/web_package/shared_file.cc
@@ -0,0 +1,122 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/web_package/shared_file.h"
+
+#include <limits>
+
+#include "base/numerics/safe_math.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "mojo/public/cpp/system/file_data_source.h"
+
+namespace web_package {
+
+SharedFile::SharedFile(
+    base::OnceCallback<std::unique_ptr<base::File>()> open_file_callback) {
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE, {base::MayBlock()}, std::move(open_file_callback),
+      base::BindOnce(&SharedFile::SetFile, base::RetainedRef(this)));
+}
+
+void SharedFile::DuplicateFile(base::OnceCallback<void(base::File)> callback) {
+  // Basically this interface expects this method is called at most once. Have
+  // a DCHECK for the case that does not work for a clear reason, just in case.
+  // The call site also have another DCHECK for external callers not to cause
+  // such problematic cases.
+  DCHECK(duplicate_callback_.is_null());
+  duplicate_callback_ = std::move(callback);
+
+  if (file_)
+    SetFile(std::move(file_));
+}
+
+base::File* SharedFile::operator->() {
+  DCHECK(file_);
+  return file_.get();
+}
+
+SharedFile::~SharedFile() {
+  // Move the last reference to |file_| that leads an internal blocking call
+  // that is not permitted here.
+  base::ThreadPool::PostTask(
+      FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
+      base::BindOnce([](std::unique_ptr<base::File> file) {},
+                     std::move(file_)));
+}
+
+void SharedFile::SetFile(std::unique_ptr<base::File> file) {
+  file_ = std::move(file);
+
+  if (duplicate_callback_.is_null())
+    return;
+
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE, {base::MayBlock()},
+      base::BindOnce(
+          [](base::File* file) -> base::File { return file->Duplicate(); },
+          file_.get()),
+      std::move(duplicate_callback_));
+}
+
+std::unique_ptr<SharedFile::SharedFileDataSource> SharedFile::CreateDataSource(
+    uint64_t offset,
+    uint64_t length) {
+  return std::make_unique<SharedFile::SharedFileDataSource>(this, offset,
+                                                            length);
+}
+
+SharedFile::SharedFileDataSource::SharedFileDataSource(
+    scoped_refptr<SharedFile> file,
+    uint64_t offset,
+    uint64_t length)
+    : file_(std::move(file)), offset_(offset), length_(length) {
+  error_ = mojo::FileDataSource::ConvertFileErrorToMojoResult(
+      (*file_)->error_details());
+
+  // base::File::Read takes int64_t as an offset. So, offset + length should
+  // not overflow in int64_t.
+  uint64_t max_offset;
+  if (!base::CheckAdd(offset, length).AssignIfValid(&max_offset) ||
+      (std::numeric_limits<int64_t>::max() < max_offset)) {
+    error_ = MOJO_RESULT_INVALID_ARGUMENT;
+  }
+};
+
+SharedFile::SharedFileDataSource::~SharedFileDataSource() = default;
+
+uint64_t SharedFile::SharedFileDataSource::GetLength() const {
+  return length_;
+}
+
+SharedFile::SharedFileDataSource::ReadResult
+SharedFile::SharedFileDataSource::Read(uint64_t offset,
+                                       base::span<char> buffer) {
+  ReadResult result;
+  result.result = error_;
+
+  if (length_ < offset)
+    result.result = MOJO_RESULT_INVALID_ARGUMENT;
+
+  if (result.result != MOJO_RESULT_OK)
+    return result;
+
+  uint64_t readable_size = length_ - offset;
+  uint64_t writable_size = buffer.size();
+  uint64_t copyable_size =
+      std::min(std::min(readable_size, writable_size),
+               static_cast<uint64_t>(std::numeric_limits<int>::max()));
+
+  int bytes_read =
+      (*file_)->Read(offset_ + offset, buffer.data(), copyable_size);
+  if (bytes_read < 0) {
+    result.result = mojo::FileDataSource::ConvertFileErrorToMojoResult(
+        (*file_)->GetLastFileError());
+  } else {
+    result.bytes_read = bytes_read;
+  }
+  return result;
+}
+
+}  // namespace web_package
diff --git a/components/web_package/shared_file.h b/components/web_package/shared_file.h
new file mode 100644
index 0000000..9466c58
--- /dev/null
+++ b/components/web_package/shared_file.h
@@ -0,0 +1,72 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_WEB_PACKAGE_SHARED_FILE_H_
+#define COMPONENTS_WEB_PACKAGE_SHARED_FILE_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "mojo/public/cpp/system/data_pipe_producer.h"
+
+namespace web_package {
+
+// A simple wrapper class to share a single base::File instance among multiple
+// SharedFileDataSource instances.
+class SharedFile final : public base::RefCountedThreadSafe<SharedFile> {
+ public:
+  // The callback passed to the constructor will run on a thread that allows
+  // blocking disk IO.
+  explicit SharedFile(
+      base::OnceCallback<std::unique_ptr<base::File>()> open_file_callback);
+
+  SharedFile(const SharedFile&) = delete;
+  SharedFile& operator=(const SharedFile&) = delete;
+
+  void DuplicateFile(base::OnceCallback<void(base::File)> callback);
+  base::File* operator->();
+
+  class SharedFileDataSource final : public mojo::DataPipeProducer::DataSource {
+   public:
+    SharedFileDataSource(scoped_refptr<SharedFile> file,
+                         uint64_t offset,
+                         uint64_t length);
+
+    SharedFileDataSource(const SharedFileDataSource&) = delete;
+    SharedFileDataSource& operator=(const SharedFileDataSource&) = delete;
+
+    ~SharedFileDataSource() override;
+
+   private:
+    // Implements mojo::DataPipeProducer::DataSource. Following methods are
+    // called on a blockable sequenced task runner.
+    uint64_t GetLength() const override;
+    ReadResult Read(uint64_t offset, base::span<char> buffer) override;
+
+    scoped_refptr<SharedFile> file_;
+    MojoResult error_;
+    const uint64_t offset_;
+    const uint64_t length_;
+  };
+
+  std::unique_ptr<SharedFileDataSource> CreateDataSource(uint64_t offset,
+                                                         uint64_t length);
+
+ private:
+  friend class base::RefCountedThreadSafe<SharedFile>;
+  ~SharedFile();
+
+  void SetFile(std::unique_ptr<base::File> file);
+
+  base::FilePath file_path_;
+  std::unique_ptr<base::File> file_;
+  base::OnceCallback<void(base::File)> duplicate_callback_;
+};
+
+}  // namespace web_package
+
+#endif  // COMPONENTS_WEB_PACKAGE_SHARED_FILE_H_
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index cfc8837..adb79b5 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -2598,7 +2598,6 @@
         "media/capture/aura_window_video_capture_device.h",
         "media/capture/mouse_cursor_overlay_controller_aura.cc",
       ]
-      deps += [ "//ui/aura/cursor" ]
     }
 
     if (is_mac) {
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc
index a09bb1b..a73acfbf 100644
--- a/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -1746,8 +1746,15 @@
     return const_cast<BrowserAccessibilityManager*>(this);
 
   BrowserAccessibilityManager* parent_manager = GetParentManager();
-  if (!parent_manager)
+  if (!parent_manager) {
+    // This can occur when the child frame has an embedding token, but the
+    // parent element (e.g. <iframe>) does not yet know about the child.
+    // Attempting to change this to a DCHECK() will currently cause a number of
+    // tests to fail. Ideally, we would not need this if Blink always serialized
+    // the embedding token in the child tree owning element first, before
+    // serializing the child tree.
     return nullptr;
+  }
 
   return parent_manager->GetRootManager();
 }
@@ -1793,7 +1800,7 @@
   if (!delegate_)
     return GetTreeData().parent_tree_id == ui::AXTreeIDUnknown();
 
-  bool is_root_tree = delegate_ && delegate_->AccessibilityIsMainFrame();
+  bool is_root_tree = delegate_->AccessibilityIsMainFrame();
   DCHECK(!is_root_tree || GetParentTreeID() == ui::AXTreeIDUnknown())
       << "Root tree has parent tree id of: " << GetParentTreeID();
   return is_root_tree;
diff --git a/content/browser/media/capture/mouse_cursor_overlay_controller_aura.cc b/content/browser/media/capture/mouse_cursor_overlay_controller_aura.cc
index 6b6fcf8..b3c0089 100644
--- a/content/browser/media/capture/mouse_cursor_overlay_controller_aura.cc
+++ b/content/browser/media/capture/mouse_cursor_overlay_controller_aura.cc
@@ -5,13 +5,13 @@
 #include "content/browser/media/capture/mouse_cursor_overlay_controller.h"
 
 #include "base/memory/raw_ptr.h"
-#include "ui/aura/cursor/cursor_lookup.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
 #include "ui/events/event.h"
 #include "ui/events/event_handler.h"
+#include "ui/wm/core/cursor_lookup.h"
 #include "ui/wm/public/activation_client.h"
 
 namespace content {
@@ -171,7 +171,7 @@
     const gfx::Size window_size = window->bounds().size();
     if (!window_size.IsEmpty()) {
       if (auto* root_window = window->GetRootWindow()) {
-        const SkBitmap& bitmap = aura::GetCursorBitmap(cursor);
+        const SkBitmap& bitmap = wm::GetCursorBitmap(cursor);
         const float scale_factor = cursor.image_scale_factor();
         DCHECK_GT(scale_factor, 0.0f);
 
@@ -181,7 +181,7 @@
 
         // Compute the hotspot in terms of DIP coordinates.
         const gfx::PointF hotspot = gfx::ScalePoint(
-            gfx::PointF(aura::GetCursorHotspot(cursor)), 1.0f / scale_factor);
+            gfx::PointF(wm::GetCursorHotspot(cursor)), 1.0f / scale_factor);
 
         // Finally, put it all together: Scale the absolute bounds of the
         // overlay by the window size to produce relative coordinates.
@@ -208,7 +208,7 @@
 // static
 SkBitmap MouseCursorOverlayController::GetCursorImage(
     const gfx::NativeCursor& cursor) {
-  return aura::GetCursorBitmap(cursor);
+  return wm::GetCursorBitmap(cursor);
 }
 
 }  // namespace content
diff --git a/content/browser/renderer_host/render_frame_host.cc b/content/browser/renderer_host/render_frame_host.cc
index a65fe78..4336fc6c 100644
--- a/content/browser/renderer_host/render_frame_host.cc
+++ b/content/browser/renderer_host/render_frame_host.cc
@@ -8,5 +8,5 @@
 // impact on build time. Try not to raise this limit unless necessary. See
 // https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md
 #ifndef NACL_TC_REV
-#pragma clang max_tokens_here 710000
+#pragma clang max_tokens_here 760000
 #endif
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 33560a9..26b52c6 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -3132,6 +3132,12 @@
   GetContentClient()->browser()->AppendExtraCommandLineSwitches(command_line,
                                                                 GetID());
 
+  static bool first_renderer_process = true;
+  if (first_renderer_process) {
+    command_line->AppendSwitch(kFirstRendererProcess);
+    first_renderer_process = false;
+  }
+
   if (IsPdf())
     command_line->AppendSwitch(switches::kPdfRenderer);
 
diff --git a/content/browser/shared_storage/shared_storage_worklet_host.h b/content/browser/shared_storage/shared_storage_worklet_host.h
index 2d4472e..b3f3c0a 100644
--- a/content/browser/shared_storage/shared_storage_worklet_host.h
+++ b/content/browser/shared_storage/shared_storage_worklet_host.h
@@ -182,10 +182,9 @@
   base::WeakPtr<PageImpl> page_;
 
   // Both `this` and `shared_storage_manager_` live in the `StoragePartition`.
-  // `shared_storage_manager_` almost always outlives `this` (thus is valid)
-  // except for inside `~SharedStorageWorkletHost()`.
-  raw_ptr<storage::SharedStorageManager, DanglingUntriaged>
-      shared_storage_manager_;
+  // `shared_storage_manager_` always outlives `this` because `this` will be
+  // destroyed before `shared_storage_manager_` in ~StoragePartition.
+  raw_ptr<storage::SharedStorageManager> shared_storage_manager_;
 
   // Pointer to the `BrowserContext`, saved to be able to call
   // `IsSharedStorageAllowed()`.
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index a6ea98e..3eaa89f 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -617,8 +617,6 @@
   scoped_refptr<storage::DatabaseTracker> database_tracker_;
   scoped_refptr<DOMStorageContextWrapper> dom_storage_context_;
   std::unique_ptr<LockManager> lock_manager_;
-  std::unique_ptr<SharedStorageWorkletHostManager>
-      shared_storage_worklet_host_manager_;
   std::unique_ptr<IndexedDBControlWrapper> indexed_db_control_wrapper_;
   std::unique_ptr<CacheStorageControlWrapper> cache_storage_control_wrapper_;
   scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
@@ -660,6 +658,13 @@
   // Owning pointer to the SharedStorageManager for this partition.
   std::unique_ptr<storage::SharedStorageManager> shared_storage_manager_;
 
+  // This needs to be declared after `shared_storage_manager_` because
+  // `shared_storage_worklet_host` (managed by
+  // `shared_storage_worklet_host_manager_`) ultimately stores a raw pointer on
+  // it.
+  std::unique_ptr<SharedStorageWorkletHostManager>
+      shared_storage_worklet_host_manager_;
+
   // ReceiverSet for DomStorage, using the
   // ChildProcessSecurityPolicyImpl::Handle as the binding context type. The
   // handle can subsequently be used during interface method calls to
diff --git a/content/browser/web_package/web_bundle_reader.cc b/content/browser/web_package/web_bundle_reader.cc
index 4d3e9668..b41de20 100644
--- a/content/browser/web_package/web_bundle_reader.cc
+++ b/content/browser/web_package/web_bundle_reader.cc
@@ -4,141 +4,27 @@
 
 #include "content/browser/web_package/web_bundle_reader.h"
 
-#include <limits>
-
 #include "base/check_op.h"
-#include "base/numerics/safe_math.h"
-#include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
+#include "components/web_package/shared_file.h"
 #include "content/browser/web_package/web_bundle_blob_data_source.h"
 #include "content/browser/web_package/web_bundle_source.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/system/data_pipe_producer.h"
-#include "mojo/public/cpp/system/file_data_source.h"
-#include "mojo/public/cpp/system/platform_handle.h"
 #include "net/base/url_util.h"
 #include "services/network/public/cpp/resource_request.h"
-#include "third_party/blink/public/common/web_package/web_package_request_matcher.h"
 
 namespace content {
 
-WebBundleReader::SharedFile::SharedFile(
-    std::unique_ptr<WebBundleSource> source) {
-  base::ThreadPool::PostTaskAndReplyWithResult(
-      FROM_HERE, {base::MayBlock()},
-      base::BindOnce(
-          [](std::unique_ptr<WebBundleSource> source)
-              -> std::unique_ptr<base::File> { return source->OpenFile(); },
-          std::move(source)),
-      base::BindOnce(&SharedFile::SetFile, base::RetainedRef(this)));
-}
-
-void WebBundleReader::SharedFile::DuplicateFile(
-    base::OnceCallback<void(base::File)> callback) {
-  // Basically this interface expects this method is called at most once. Have
-  // a DCHECK for the case that does not work for a clear reason, just in case.
-  // The call site also have another DCHECK for external callers not to cause
-  // such problematic cases.
-  DCHECK(duplicate_callback_.is_null());
-  duplicate_callback_ = std::move(callback);
-
-  if (file_)
-    SetFile(std::move(file_));
-}
-
-base::File* WebBundleReader::SharedFile::operator->() {
-  DCHECK(file_);
-  return file_.get();
-}
-
-WebBundleReader::SharedFile::~SharedFile() {
-  // Move the last reference to |file_| that leads an internal blocking call
-  // that is not permitted here.
-  base::ThreadPool::PostTask(
-      FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
-      base::BindOnce([](std::unique_ptr<base::File> file) {},
-                     std::move(file_)));
-}
-
-void WebBundleReader::SharedFile::SetFile(std::unique_ptr<base::File> file) {
-  file_ = std::move(file);
-
-  if (duplicate_callback_.is_null())
-    return;
-
-  base::ThreadPool::PostTaskAndReplyWithResult(
-      FROM_HERE, {base::MayBlock()},
-      base::BindOnce(
-          [](base::File* file) -> base::File { return file->Duplicate(); },
-          file_.get()),
-      std::move(duplicate_callback_));
-}
-
-class WebBundleReader::SharedFileDataSource final
-    : public mojo::DataPipeProducer::DataSource {
- public:
-  SharedFileDataSource(scoped_refptr<WebBundleReader::SharedFile> file,
-                       uint64_t offset,
-                       uint64_t length)
-      : file_(std::move(file)), offset_(offset), length_(length) {
-    error_ = mojo::FileDataSource::ConvertFileErrorToMojoResult(
-        (*file_)->error_details());
-
-    // base::File::Read takes int64_t as an offset. So, offset + length should
-    // not overflow in int64_t.
-    uint64_t max_offset;
-    if (!base::CheckAdd(offset, length).AssignIfValid(&max_offset) ||
-        (std::numeric_limits<int64_t>::max() < max_offset)) {
-      error_ = MOJO_RESULT_INVALID_ARGUMENT;
-    }
-  }
-
-  SharedFileDataSource(const SharedFileDataSource&) = delete;
-  SharedFileDataSource& operator=(const SharedFileDataSource&) = delete;
-
- private:
-  // Implements mojo::DataPipeProducer::DataSource. Following methods are called
-  // on a blockable sequenced task runner.
-  uint64_t GetLength() const override { return length_; }
-  ReadResult Read(uint64_t offset, base::span<char> buffer) override {
-    ReadResult result;
-    result.result = error_;
-
-    if (length_ < offset)
-      result.result = MOJO_RESULT_INVALID_ARGUMENT;
-
-    if (result.result != MOJO_RESULT_OK)
-      return result;
-
-    uint64_t readable_size = length_ - offset;
-    uint64_t writable_size = buffer.size();
-    uint64_t copyable_size =
-        std::min(std::min(readable_size, writable_size),
-                 static_cast<uint64_t>(std::numeric_limits<int>::max()));
-
-    int bytes_read =
-        (*file_)->Read(offset_ + offset, buffer.data(), copyable_size);
-    if (bytes_read < 0) {
-      result.result = mojo::FileDataSource::ConvertFileErrorToMojoResult(
-          (*file_)->GetLastFileError());
-    } else {
-      result.bytes_read = bytes_read;
-    }
-    return result;
-  }
-
-  scoped_refptr<WebBundleReader::SharedFile> file_;
-  MojoResult error_;
-  const uint64_t offset_;
-  const uint64_t length_;
-};
-
 WebBundleReader::WebBundleReader(std::unique_ptr<WebBundleSource> source)
     : source_(std::move(source)),
       parser_(std::make_unique<data_decoder::SafeWebBundleParser>()),
-      file_(base::MakeRefCounted<SharedFile>(source_->Clone())) {
+      file_(base::MakeRefCounted<web_package::SharedFile>(base::BindOnce(
+          [](std::unique_ptr<WebBundleSource> source)
+              -> std::unique_ptr<base::File> { return source->OpenFile(); },
+          source_->Clone()))) {
   DCHECK(source_->is_trusted_file() || source_->is_file());
 }
 
@@ -290,8 +176,8 @@
         std::make_unique<mojo::DataPipeProducer>(std::move(producer_handle));
     mojo::DataPipeProducer* raw_producer = data_producer.get();
     raw_producer->Write(
-        std::make_unique<SharedFileDataSource>(file_, response->payload_offset,
-                                               response->payload_length),
+        file_->CreateDataSource(response->payload_offset,
+                                response->payload_length),
         base::BindOnce(
             [](std::unique_ptr<mojo::DataPipeProducer> producer,
                BodyCompletionCallback callback, MojoResult result) {
diff --git a/content/browser/web_package/web_bundle_reader.h b/content/browser/web_package/web_bundle_reader.h
index 94caf7f..9f23ce9 100644
--- a/content/browser/web_package/web_bundle_reader.h
+++ b/content/browser/web_package/web_bundle_reader.h
@@ -9,15 +9,12 @@
 
 #include "base/containers/flat_map.h"
 #include "base/files/file.h"
-#include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
-#include "base/task/sequenced_task_runner.h"
+#include "components/web_package/shared_file.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/browser_context.h"
-#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/system/data_pipe_producer.h"
 #include "net/base/net_errors.h"
 #include "services/data_decoder/public/cpp/safe_web_bundle_parser.h"
@@ -100,30 +97,6 @@
  private:
   friend class base::RefCounted<WebBundleReader>;
 
-  // A simple wrapper class to share a single base::File instance among multiple
-  // SharedFileDataSource instances.
-  class SharedFile final : public base::RefCountedThreadSafe<SharedFile> {
-   public:
-    explicit SharedFile(std::unique_ptr<WebBundleSource> source);
-
-    SharedFile(const SharedFile&) = delete;
-    SharedFile& operator=(const SharedFile&) = delete;
-
-    void DuplicateFile(base::OnceCallback<void(base::File)> callback);
-    base::File* operator->();
-
-   private:
-    friend class base::RefCountedThreadSafe<SharedFile>;
-    ~SharedFile();
-
-    void SetFile(std::unique_ptr<base::File> file);
-
-    base::FilePath file_path_;
-    std::unique_ptr<base::File> file_;
-    base::OnceCallback<void(base::File)> duplicate_callback_;
-  };
-  class SharedFileDataSource;
-
   enum class State {
     kInitial,
     kMetadataReady,
@@ -155,7 +128,7 @@
 
   std::unique_ptr<data_decoder::SafeWebBundleParser> parser_;
   // Used when loading a web bundle from file.
-  scoped_refptr<SharedFile> file_;
+  scoped_refptr<web_package::SharedFile> file_;
   // Used when loading a web bundle from network.
   std::unique_ptr<WebBundleBlobDataSource> blob_data_source_;
 
diff --git a/content/browser/webauth/authenticator_common.cc b/content/browser/webauth/authenticator_common.cc
index c08d270e..9897bc3 100644
--- a/content/browser/webauth/authenticator_common.cc
+++ b/content/browser/webauth/authenticator_common.cc
@@ -174,11 +174,11 @@
 }
 
 // Parses the FIDO transport types extension from the DER-encoded, X.509
-// certificate in |der_cert| and adds any transport types found to
-// |out_transports|. Returns true if any transports were added.
-bool AddTransportsFromCertificate(
+// certificate in |der_cert| and appends any unique transport types found to
+// |out_transports|.
+void AppendUniqueTransportsFromCertificate(
     base::span<const uint8_t> der_cert,
-    base::flat_set<device::FidoTransportProtocol>* out_transports) {
+    std::vector<device::FidoTransportProtocol>* out_transports) {
   // See
   // https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-authenticator-transports-extension-v1.2-ps-20170411.html#fido-u2f-certificate-transports-extension
   static constexpr uint8_t kTransportTypesOID[] = {
@@ -192,7 +192,7 @@
                             sizeof(kTransportTypesOID)),
           &present, &critical, &contents) ||
       !present) {
-    return false;
+    return;
   }
 
   const net::der::Input contents_der(contents);
@@ -200,7 +200,7 @@
   absl::optional<net::der::BitString> transport_bits =
       contents_parser.ReadBitString();
   if (!transport_bits) {
-    return false;
+    return;
   }
 
   // The certificate extension contains a BIT STRING where different bits
@@ -218,15 +218,12 @@
       {4, device::FidoTransportProtocol::kInternal},
   };
 
-  bool ret = false;
   for (const auto& mapping : kTransportMapping) {
-    if (transport_bits->AssertsBit(mapping.bit_index)) {
-      out_transports->insert(mapping.transport);
-      ret |= true;
+    if (transport_bits->AssertsBit(mapping.bit_index) &&
+        !base::Contains(*out_transports, mapping.transport)) {
+      out_transports->push_back(mapping.transport);
     }
   }
-
-  return ret;
 }
 
 enum class AttestationErasureOption {
@@ -1657,34 +1654,23 @@
                 *response_data.transport_used())
           : device::AuthenticatorAttachment::kAny;
 
-  base::flat_set<device::FidoTransportProtocol> transports;
-  // transports_authoritative tracks whether the contents of `transports` are
-  // considered to be sufficient complete to report back to the website.
-  bool transports_authoritative = false;
-
+  // The transport list must not contain duplicates but the order doesn't matter
+  // because Blink will sort the resulting strings before returning them.
+  std::vector<device::FidoTransportProtocol> transports;
   if (response_data.transport_used()) {
-    transports.insert(*response_data.transport_used());
+    transports.push_back(*response_data.transport_used());
   }
-  if (response_data.transports) {
-    transports.insert(response_data.transports->begin(),
-                      response_data.transports->end());
-    transports_authoritative = true;
-  }
-  // Also include any transports from the attestation certificate.
+  // If the attestation certificate specifies that the token supports any other
+  // transports, include them in the list.
   absl::optional<base::span<const uint8_t>> leaf_cert =
       response_data.attestation_object()
           .attestation_statement()
           .GetLeafCertificate();
   if (leaf_cert) {
-    transports_authoritative |=
-        AddTransportsFromCertificate(*leaf_cert, &transports);
+    AppendUniqueTransportsFromCertificate(*leaf_cert, &transports);
   }
 
-  // The order of transports doesn't matter because Blink will sort the
-  // resulting strings before returning them.
-  if (transports_authoritative) {
-    response->transports.assign(transports.begin(), transports.end());
-  }
+  response->transports = std::move(transports);
 
   bool did_create_hmac_secret = false;
   bool did_store_cred_blob = false;
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index f8ba28e..8953fcc 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -15,7 +15,6 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/compiler_specific.h"
-#include "base/containers/flat_set.h"
 #include "base/files/file.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
@@ -3845,49 +3844,7 @@
             std::get<0>(*failure_reason_receiver.result()));
 }
 
-TEST_F(AuthenticatorImplTest, NoNonAuthoritativeTransports) {
-  NavigateAndCommit(GURL(kTestOrigin1));
-  virtual_device_factory_->SetSupportedProtocol(
-      device::ProtocolVersion::kCtap2);
-  device::VirtualCtap2Device::Config config;
-  // If there are no transports in the attestation certificate, and none from
-  // getInfo, then none should be reported because there isn't enough
-  // information to say.
-  config.include_transports_in_attestation_certificate = false;
-  virtual_device_factory_->SetCtap2Config(config);
-
-  MakeCredentialResult result = AuthenticatorMakeCredential();
-  ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
-
-  EXPECT_TRUE(result.response->transports.empty());
-}
-
-TEST_F(AuthenticatorImplTest, TransportsFromGetInfo) {
-  NavigateAndCommit(GURL(kTestOrigin1));
-  virtual_device_factory_->SetSupportedProtocol(
-      device::ProtocolVersion::kCtap2);
-  device::VirtualCtap2Device::Config config;
-  config.include_transports_in_attestation_certificate = false;
-  config.transports_in_get_info = {
-      device::FidoTransportProtocol::kBluetoothLowEnergy};
-  virtual_device_factory_->SetCtap2Config(config);
-
-  MakeCredentialResult result = AuthenticatorMakeCredential();
-  ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
-
-  base::flat_set<device::FidoTransportProtocol> reported(
-      result.response->transports.begin(), result.response->transports.end());
-  EXPECT_EQ(reported.size(), 2u);
-  // The transports from the getInfo are authoritative and so they should be
-  // reported. In addition to 'ble' from getInfo, 'usb' should be included
-  // because that's what was used to communicate with the virtual authenticator.
-  EXPECT_TRUE(
-      reported.contains(device::FidoTransportProtocol::kBluetoothLowEnergy));
-  EXPECT_TRUE(reported.contains(
-      device::FidoTransportProtocol::kUsbHumanInterfaceDevice));
-}
-
-TEST_F(AuthenticatorImplTest, TransportsInAttestationCertificate) {
+TEST_F(AuthenticatorImplTest, Transports) {
   NavigateAndCommit(GURL(kTestOrigin1));
 
   for (auto protocol :
diff --git a/content/browser/webrtc/resources/peer_connection_update_table.js b/content/browser/webrtc/resources/peer_connection_update_table.js
index ecc210e..6b75c8e 100644
--- a/content/browser/webrtc/resources/peer_connection_update_table.js
+++ b/content/browser/webrtc/resources/peer_connection_update_table.js
@@ -139,8 +139,6 @@
     // Highlight ICE/DTLS failures and failure callbacks.
     if ((update.type === 'iceconnectionstatechange' &&
          update.value === 'failed') ||
-        (update.type === 'iceconnectionstatechange (legacy)' &&
-         update.value === 'failed') ||
         (update.type === 'connectionstatechange' &&
          update.value === 'failed') ||
         update.type.indexOf('OnFailure') !== -1 ||
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 71c71d58..1ac4a63 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -327,7 +327,7 @@
   }
 
   if (use_aura) {
-    deps += [ "//ui/aura/cursor" ]
+    deps += [ "//ui/wm" ]
   } else {
     sources -= [ "cursors/webcursor_aura.cc" ]
   }
diff --git a/content/common/content_switches_internal.cc b/content/common/content_switches_internal.cc
index 9418b79..373f532 100644
--- a/content/common/content_switches_internal.cc
+++ b/content/common/content_switches_internal.cc
@@ -64,6 +64,11 @@
 
 }  // namespace
 
+// This switch is passed from the browser to the first renderer process it
+// creates. Useful for performing some actions only once, from one renderer
+// process.
+const char kFirstRendererProcess[] = "first-renderer-process";
+
 bool IsPinchToZoomEnabled() {
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
diff --git a/content/common/content_switches_internal.h b/content/common/content_switches_internal.h
index 57072bf..47eb75285 100644
--- a/content/common/content_switches_internal.h
+++ b/content/common/content_switches_internal.h
@@ -15,6 +15,8 @@
 
 namespace content {
 
+extern const char kFirstRendererProcess[];
+
 bool IsPinchToZoomEnabled();
 
 blink::mojom::V8CacheOptions GetV8CacheOptions();
diff --git a/content/common/cursors/webcursor_aura.cc b/content/common/cursors/webcursor_aura.cc
index d3472950..071cfa4 100644
--- a/content/common/cursors/webcursor_aura.cc
+++ b/content/common/cursors/webcursor_aura.cc
@@ -5,10 +5,10 @@
 #include "content/common/cursors/webcursor.h"
 
 #include "base/check_op.h"
-#include "ui/aura/cursor/cursor_util.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/cursor/cursor_factory.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
+#include "ui/wm/core/cursor_util.h"
 
 namespace content {
 
@@ -39,8 +39,7 @@
   *bitmap = cursor_.custom_bitmap();
   *hotspot = cursor_.custom_hotspot();
   *scale = GetCursorScaleFactor(bitmap);
-  aura::ScaleAndRotateCursorBitmapAndHotpoint(*scale, rotation_, bitmap,
-                                              hotspot);
+  wm::ScaleAndRotateCursorBitmapAndHotpoint(*scale, rotation_, bitmap, hotspot);
 }
 
 #if !defined(USE_OZONE)
diff --git a/content/common/url_schemes.cc b/content/common/url_schemes.cc
index 4d2b52b..bb1c570 100644
--- a/content/common/url_schemes.cc
+++ b/content/common/url_schemes.cc
@@ -63,7 +63,6 @@
   url::AddStandardScheme(kChromeUIUntrustedScheme, url::SCHEME_WITH_HOST);
   url::AddStandardScheme(kGuestScheme, url::SCHEME_WITH_HOST);
   url::AddStandardScheme(kChromeErrorScheme, url::SCHEME_WITH_HOST);
-  url::AddStandardScheme(kIsolatedAppScheme, url::SCHEME_WITH_HOST);
   for (auto& scheme : schemes.standard_schemes)
     url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITH_HOST);
 
@@ -74,7 +73,6 @@
   schemes.secure_schemes.push_back(kChromeUIScheme);
   schemes.secure_schemes.push_back(kChromeUIUntrustedScheme);
   schemes.secure_schemes.push_back(kChromeErrorScheme);
-  schemes.secure_schemes.push_back(kIsolatedAppScheme);
   for (auto& scheme : schemes.secure_schemes)
     url::AddSecureScheme(scheme.c_str());
 
@@ -90,7 +88,6 @@
 
   schemes.cors_enabled_schemes.push_back(kChromeUIScheme);
   schemes.cors_enabled_schemes.push_back(kChromeUIUntrustedScheme);
-  schemes.cors_enabled_schemes.push_back(kIsolatedAppScheme);
   for (auto& scheme : schemes.cors_enabled_schemes)
     url::AddCorsEnabledScheme(scheme.c_str());
 
@@ -110,7 +107,6 @@
   for (auto& [scheme, handler] : schemes.predefined_handler_schemes)
     url::AddPredefinedHandlerScheme(scheme.c_str(), handler.c_str());
 
-  schemes.service_worker_schemes.push_back(kIsolatedAppScheme);
   // This should only be registered if the
   // kEnableServiceWorkerForChromeUntrusted feature is enabled but checking
   // it here causes a crash when --no-sandbox is enabled. See crbug.com/1313812
@@ -119,8 +115,6 @@
   // enabled.
   schemes.service_worker_schemes.push_back(kChromeUIUntrustedScheme);
 
-  url::AddWebStorageScheme(kIsolatedAppScheme);
-
   // Prevent future modification of the scheme lists. This is to prevent
   // accidental creation of data races in the program. Add*Scheme aren't
   // threadsafe so must be called when GURL isn't used on any other thread. This
diff --git a/content/public/common/url_constants.cc b/content/public/common/url_constants.cc
index 53e29fc..a502f88 100644
--- a/content/public/common/url_constants.cc
+++ b/content/public/common/url_constants.cc
@@ -23,7 +23,6 @@
 #if BUILDFLAG(IS_ANDROID)
 const char kAndroidAppScheme[] = "android-app";
 #endif
-const char kIsolatedAppScheme[] = "isolated-app";
 const char kGoogleChromeScheme[] = "googlechrome";
 
 const char kChromeUIAttributionInternalsHost[] = "attribution-internals";
diff --git a/content/public/common/url_constants.h b/content/public/common/url_constants.h
index 9b7dd13..ebbb5796 100644
--- a/content/public/common/url_constants.h
+++ b/content/public/common/url_constants.h
@@ -29,7 +29,6 @@
 #if BUILDFLAG(IS_ANDROID)
 CONTENT_EXPORT extern const char kAndroidAppScheme[];
 #endif
-CONTENT_EXPORT extern const char kIsolatedAppScheme[];
 
 // The `googlechrome:` scheme is registered on several platforms, and is
 // both interesting and dangerous.
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 549bac2..914ecff 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -37,6 +37,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task/bind_post_task.h"
+#include "base/task/sequenced_task_runner.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/simple_thread.h"
@@ -66,6 +67,7 @@
 #include "content/child/runtime_features.h"
 #include "content/common/buildflags.h"
 #include "content/common/content_constants_internal.h"
+#include "content/common/content_switches_internal.h"
 #include "content/common/partition_alloc_support.h"
 #include "content/common/process_visibility_tracker.h"
 #include "content/common/pseudonymization_salt.h"
@@ -123,12 +125,15 @@
 #include "net/base/url_util.h"
 #include "ppapi/buildflags/buildflags.h"
 #include "services/metrics/public/cpp/mojo_ukm_recorder.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
 #include "services/network/public/cpp/network_switches.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
 #include "services/viz/public/cpp/gpu/gpu.h"
 #include "skia/ext/skia_memory_dump_provider.h"
 #include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/privacy_budget/active_sampling.h"
+#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
 #include "third_party/blink/public/common/switches.h"
 #include "third_party/blink/public/platform/modules/video_capture/web_video_capture_impl_manager.h"
 #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
@@ -687,6 +692,32 @@
     base::ThreadPool::PostTask(FROM_HERE,
                                base::BindOnce([] { SkFontMgr::RefDefault(); }));
   }
+
+  bool should_actively_sample_fonts =
+      command_line.HasSwitch(kFirstRendererProcess) &&
+      blink::IdentifiabilityStudySettings::Get()->ShouldActivelySample() &&
+      !blink::IdentifiabilityStudySettings::Get()
+           ->FontFamiliesToActivelySample()
+           .empty();
+  if (should_actively_sample_fonts) {
+    mojo::PendingRemote<ukm::mojom::UkmRecorderInterface> recorder;
+    RenderThread::Get()->BindHostReceiver(
+        recorder.InitWithNewPipeAndPassReceiver());
+    scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner =
+        base::ThreadPool::CreateSequencedTaskRunner(
+            {base::TaskPriority::BEST_EFFORT, base::MayBlock(),
+             base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
+    sequenced_task_runner->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            [](mojo::PendingRemote<ukm::mojom::UkmRecorderInterface> recorder) {
+              auto ukm_recorder =
+                  std::make_unique<ukm::MojoUkmRecorder>(std::move(recorder));
+              blink::IdentifiabilityActiveSampler::ActivelySampleAvailableFonts(
+                  ukm_recorder.get());
+            },
+            std::move(recorder)));
+  }
 }
 
 RenderThreadImpl::~RenderThreadImpl() {
diff --git a/device/fido/authenticator_get_info_response.cc b/device/fido/authenticator_get_info_response.cc
index 9e5a50f..68ae03e1 100644
--- a/device/fido/authenticator_get_info_response.cc
+++ b/device/fido/authenticator_get_info_response.cc
@@ -104,14 +104,6 @@
         0x08, base::strict_cast<int64_t>(*response.max_credential_id_length));
   }
 
-  if (response.transports) {
-    std::vector<cbor::Value> transport_values;
-    for (FidoTransportProtocol transport : *response.transports) {
-      transport_values.emplace_back(ToString(transport));
-    }
-    device_info_map.emplace(0x09, std::move(transport_values));
-  }
-
   if (response.remaining_discoverable_credentials) {
     device_info_map.emplace(0x14,
                             base::strict_cast<int64_t>(
diff --git a/device/fido/authenticator_get_info_response.h b/device/fido/authenticator_get_info_response.h
index 49df86b..a670cac 100644
--- a/device/fido/authenticator_get_info_response.h
+++ b/device/fido/authenticator_get_info_response.h
@@ -14,7 +14,6 @@
 #include "base/containers/flat_set.h"
 #include "device/fido/authenticator_supported_options.h"
 #include "device/fido/fido_constants.h"
-#include "device/fido/fido_transport_protocol.h"
 #include "device/fido/fido_types.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -58,7 +57,6 @@
   absl::optional<uint32_t> remaining_discoverable_credentials;
   absl::optional<bool> force_pin_change;
   absl::optional<uint32_t> min_pin_length;
-  absl::optional<base::flat_set<FidoTransportProtocol>> transports;
 
   // max_cred_blob_length is the maximum size credBlob that the authenticator
   // supports per credential, or nullopt if credBlob is not supported. If
diff --git a/device/fido/authenticator_make_credential_response.h b/device/fido/authenticator_make_credential_response.h
index 9aae4db5..85b0b32 100644
--- a/device/fido/authenticator_make_credential_response.h
+++ b/device/fido/authenticator_make_credential_response.h
@@ -11,7 +11,6 @@
 #include <vector>
 
 #include "base/component_export.h"
-#include "base/containers/flat_set.h"
 #include "base/containers/span.h"
 #include "device/fido/attestation_object.h"
 #include "device/fido/fido_constants.h"
@@ -97,10 +96,6 @@
   // |AuthenticatorCommon| based on enterprise policy.
   bool attestation_should_be_filtered = false;
 
-  // transports contains the full set of transports supported by the
-  // authenticator, if known.
-  absl::optional<base::flat_set<FidoTransportProtocol>> transports;
-
  private:
   AttestationObject attestation_object_;
 
diff --git a/device/fido/cros/authenticator.cc b/device/fido/cros/authenticator.cc
index 06ecbb3..a3375fbe 100644
--- a/device/fido/cros/authenticator.cc
+++ b/device/fido/cros/authenticator.cc
@@ -229,14 +229,11 @@
   auto statement = std::make_unique<OpaqueAttestationStatement>(
       response->attestation_format(), std::move(*statement_map));
 
-  AuthenticatorMakeCredentialResponse fido_response(
-      FidoTransportProtocol::kInternal,
-      AttestationObject(std::move(*authenticator_data), std::move(statement)));
-  fido_response.transports.emplace();
-  fido_response.transports->insert(FidoTransportProtocol::kInternal);
-
   std::move(callback).Run(CtapDeviceResponseCode::kSuccess,
-                          std::move(fido_response));
+                          AuthenticatorMakeCredentialResponse(
+                              FidoTransportProtocol::kInternal,
+                              AttestationObject(std::move(*authenticator_data),
+                                                std::move(statement))));
 }
 
 void ChromeOSAuthenticator::GetAssertion(CtapGetAssertionRequest request,
diff --git a/device/fido/device_response_converter.cc b/device/fido/device_response_converter.cc
index 6bd096a..f61d2aa8 100644
--- a/device/fido/device_response_converter.cc
+++ b/device/fido/device_response_converter.cc
@@ -22,7 +22,6 @@
 #include "device/fido/authenticator_supported_options.h"
 #include "device/fido/features.h"
 #include "device/fido/fido_constants.h"
-#include "device/fido/fido_transport_protocol.h"
 #include "device/fido/opaque_attestation_statement.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -528,24 +527,6 @@
         base::saturated_cast<uint32_t>(it->second.GetUnsigned());
   }
 
-  it = response_map.find(CBOR(0x09));
-  if (it != response_map.end()) {
-    if (!it->second.is_array())
-      return absl::nullopt;
-
-    response.transports.emplace();
-    for (const auto& transport_str : it->second.GetArray()) {
-      if (!transport_str.is_string())
-        return absl::nullopt;
-
-      absl::optional<FidoTransportProtocol> maybe_transport(
-          ConvertToFidoTransportProtocol(transport_str.GetString()));
-      if (maybe_transport.has_value()) {
-        response.transports->insert(*maybe_transport);
-      }
-    }
-  }
-
   it = response_map.find(CBOR(0x0a));
   if (it != response_map.end()) {
     if (!it->second.is_array()) {
diff --git a/device/fido/mac/make_credential_operation.mm b/device/fido/mac/make_credential_operation.mm
index d93bed2..b9cf467 100644
--- a/device/fido/mac/make_credential_operation.mm
+++ b/device/fido/mac/make_credential_operation.mm
@@ -151,8 +151,6 @@
               CoseAlgorithmIdentifier::kEs256, std::move(*signature),
               /*x509_certificates=*/std::vector<std::vector<uint8_t>>())));
   response.is_resident_key = request_.resident_key_required;
-  response.transports.emplace();
-  response.transports->insert(FidoTransportProtocol::kInternal);
   std::move(callback_).Run(CtapDeviceResponseCode::kSuccess,
                            std::move(response));
 }
diff --git a/device/fido/make_credential_task.cc b/device/fido/make_credential_task.cc
index 1f58abb..33fbccc 100644
--- a/device/fido/make_credential_task.cc
+++ b/device/fido/make_credential_task.cc
@@ -97,10 +97,6 @@
     }
   }
 
-  if (device->device_info() && device->device_info()->transports) {
-    response->transports = *device->device_info()->transports;
-  }
-
   return response;
 }
 
diff --git a/device/fido/virtual_ctap2_device.cc b/device/fido/virtual_ctap2_device.cc
index 591b1ac..714ade8e 100644
--- a/device/fido/virtual_ctap2_device.cc
+++ b/device/fido/virtual_ctap2_device.cc
@@ -661,10 +661,6 @@
     device_info_->min_pin_length = mutable_state()->min_pin_length;
     device_info_->force_pin_change = mutable_state()->force_pin_change;
   }
-
-  if (!config.transports_in_get_info.empty()) {
-    device_info_->transports = config.transports_in_get_info;
-  }
 }
 
 VirtualCtap2Device::~VirtualCtap2Device() = default;
@@ -1264,9 +1260,8 @@
     if (config_.always_return_enterprise_attestation) {
       enterprise_attestation_requested = true;
     }
-    attestation_cert = GenerateAttestationCertificate(
-        enterprise_attestation_requested,
-        config_.include_transports_in_attestation_certificate);
+    attestation_cert =
+        GenerateAttestationCertificate(enterprise_attestation_requested);
     if (!attestation_cert) {
       DLOG(ERROR) << "Failed to generate attestation certificate.";
       return CtapDeviceResponseCode::kCtap2ErrOther;
diff --git a/device/fido/virtual_ctap2_device.h b/device/fido/virtual_ctap2_device.h
index c0a1d0c..49517912 100644
--- a/device/fido/virtual_ctap2_device.h
+++ b/device/fido/virtual_ctap2_device.h
@@ -83,13 +83,6 @@
     // as a fixed size area for the large blob.
     size_t available_large_blob_storage = 1024;
     bool cred_blob_support = false;
-    // include_transports_in_attestation_certificate controls whether a
-    // transports extension will be included in the attestation certificate
-    // returned from a makeCredential operation.
-    bool include_transports_in_attestation_certificate = true;
-    // transports_in_get_info, if not empty, contains the transports that will
-    // be reported via getInfo.
-    std::vector<FidoTransportProtocol> transports_in_get_info;
 
     IncludeCredential include_credential_in_assertion_response =
         IncludeCredential::ONLY_IF_NEEDED;
diff --git a/device/fido/virtual_fido_device.cc b/device/fido/virtual_fido_device.cc
index 22fcc9b..ab7a8b9 100644
--- a/device/fido/virtual_fido_device.cc
+++ b/device/fido/virtual_fido_device.cc
@@ -515,8 +515,7 @@
 
 absl::optional<std::vector<uint8_t>>
 VirtualFidoDevice::GenerateAttestationCertificate(
-    bool individual_attestation_requested,
-    bool include_transports) const {
+    bool individual_attestation_requested) const {
   std::unique_ptr<crypto::ECPrivateKey> attestation_private_key =
       crypto::ECPrivateKey::CreateFromPrivateKeyInfo(GetAttestationKey());
   constexpr uint32_t kAttestationCertSerialNumber = 1;
@@ -561,13 +560,10 @@
       0x00,  // zero bytes long
   };
 
-  std::vector<net::x509_util::Extension> extensions = {
+  const std::vector<net::x509_util::Extension> extensions = {
+      {kTransportTypesOID, /*critical=*/false, kTransportTypesContents},
       {kBasicContraintsOID, /*critical=*/true, kBasicContraintsContents},
   };
-  if (include_transports) {
-    extensions.push_back(
-        {kTransportTypesOID, /*critical=*/false, kTransportTypesContents});
-  }
 
   // https://w3c.github.io/webauthn/#sctn-packed-attestation-cert-requirements
   // Make the certificate expire about 20 years from now.
diff --git a/device/fido/virtual_fido_device.h b/device/fido/virtual_fido_device.h
index 71333bb..9052498 100644
--- a/device/fido/virtual_fido_device.h
+++ b/device/fido/virtual_fido_device.h
@@ -348,8 +348,7 @@
   // attestation statement and FIDO-U2F attestation statement.
   // https://w3c.github.io/webauthn/#defined-attestation-formats
   absl::optional<std::vector<uint8_t>> GenerateAttestationCertificate(
-      bool individual_attestation_requested,
-      bool include_transports) const;
+      bool individual_attestation_requested) const;
 
   void StoreNewKey(base::span<const uint8_t> key_handle,
                    VirtualFidoDevice::RegistrationData registration_data);
diff --git a/device/fido/virtual_u2f_device.cc b/device/fido/virtual_u2f_device.cc
index 1e306d6..6224a7d0 100644
--- a/device/fido/virtual_u2f_device.cc
+++ b/device/fido/virtual_u2f_device.cc
@@ -176,8 +176,8 @@
   // The spec says that the other bits of P1 should be zero. However, Chrome
   // sends Test User Presence (0x03) so we ignore those bits.
   bool individual_attestation_requested = p1 & kP1IndividualAttestation;
-  const auto attestation_cert = GenerateAttestationCertificate(
-      individual_attestation_requested, /*include_transports=*/true);
+  const auto attestation_cert =
+      GenerateAttestationCertificate(individual_attestation_requested);
   if (!attestation_cert)
     return ErrorStatus(apdu::ApduResponse::Status::SW_INS_NOT_SUPPORTED);
 
diff --git a/docs/ios/unrealized_web_state.md b/docs/ios/unrealized_web_state.md
index 2ad030e..a3d627c4 100644
--- a/docs/ios/unrealized_web_state.md
+++ b/docs/ios/unrealized_web_state.md
@@ -1,6 +1,6 @@
 # Unrealized `WebState`
 
-> **Status**: implementation in progress.
+> **Status**: launched.
 
 On iOS, each tab is implemented by a `WebState` and some TabHelpers. As users
 can have many tabs open at the same time, but only few of them visible, an
diff --git a/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc b/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc
index ad74c211..f61b7ef 100644
--- a/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc
+++ b/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc
@@ -4,7 +4,6 @@
 
 #include "extensions/renderer/api/automation/automation_ax_tree_wrapper.h"
 
-#include "automation_ax_tree_wrapper.h"
 #include "base/containers/contains.h"
 #include "base/containers/cxx20_erase.h"
 #include "base/no_destructor.h"
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn
index 54e265c..48d1e89 100644
--- a/extensions/shell/BUILD.gn
+++ b/extensions/shell/BUILD.gn
@@ -195,7 +195,6 @@
       "browser/shell_native_app_window_aura.h",
     ]
     deps += [
-      "//ui/aura/cursor",
       "//ui/base/cursor",
       "//ui/base/cursor/mojom:cursor_type",
       "//ui/platform_window",
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.cc b/extensions/shell/browser/shell_desktop_controller_aura.cc
index 74ead5764..8291f557 100644
--- a/extensions/shell/browser/shell_desktop_controller_aura.cc
+++ b/extensions/shell/browser/shell_desktop_controller_aura.cc
@@ -17,7 +17,6 @@
 #include "extensions/browser/app_window/native_app_window.h"
 #include "extensions/shell/browser/shell_app_window_client.h"
 #include "ui/aura/client/cursor_client.h"
-#include "ui/aura/cursor/cursor_loader.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/cursor/cursor.h"
@@ -30,6 +29,7 @@
 #include "ui/gfx/native_widget_types.h"
 #include "ui/wm/core/base_focus_rules.h"
 #include "ui/wm/core/compound_event_filter.h"
+#include "ui/wm/core/cursor_loader.h"
 #include "ui/wm/core/cursor_manager.h"
 #include "ui/wm/core/focus_controller.h"
 #include "ui/wm/core/native_cursor_manager.h"
@@ -121,7 +121,7 @@
 
   raw_ptr<ShellDesktopControllerAura> desktop_controller_;  // Not owned.
 
-  aura::CursorLoader cursor_loader_{/*use_platform_cursors=*/false};
+  wm::CursorLoader cursor_loader_{/*use_platform_cursors=*/false};
 };
 
 class AppsFocusRules : public wm::BaseFocusRules {
diff --git a/ios/chrome/browser/crash_report/crash_restore_helper.mm b/ios/chrome/browser/crash_report/crash_restore_helper.mm
index 86bdc8c2..19c6c7b 100644
--- a/ios/chrome/browser/crash_report/crash_restore_helper.mm
+++ b/ios/chrome/browser/crash_report/crash_restore_helper.mm
@@ -72,7 +72,7 @@
 namespace {
 
 // The size of the symbol image.
-NSInteger kSymbolImagePointSize = 18;
+const CGFloat kSymbolImagePointSize = 18;
 
 // The name if the popup symbol.
 NSString* const kRestoreSessionSymbol = @"exclamationmark.triangle.fill";
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index 61d7d73..311f998 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -835,11 +835,6 @@
     {"remove-extra-ntps", flag_descriptions::kRemoveExcessNTPsExperimentName,
      flag_descriptions::kRemoveExcessNTPsExperimentDescription,
      flags_ui::kOsIos, FEATURE_VALUE_TYPE(kRemoveExcessNTPs)},
-    {"lazily-create-web-state-on-restoration",
-     flag_descriptions::kLazilyCreateWebStateOnRestorationName,
-     flag_descriptions::kLazilyCreateWebStateOnRestorationDescription,
-     flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(web::features::kEnableUnrealizedWebStates)},
     {"enable-shortened-password-auto-fill-instruction",
      flag_descriptions::kEnableShortenedPasswordAutoFillInstructionName,
      flag_descriptions::kEnableShortenedPasswordAutoFillInstructionDescription,
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index 6e1920fb..b857ca2 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -419,10 +419,6 @@
     "Enables improvements to text fragments UI, including a menu for removing "
     "or resharing a highlight.";
 
-const char kLazilyCreateWebStateOnRestorationName[] = "Unrealized WebStates";
-const char kLazilyCreateWebStateOnRestorationDescription[] =
-    "Create WebState in unrealized state upon session restoration.";
-
 const char kLeakDetectionUnauthenticatedName[] =
     "Leak detection for signed out users";
 const char kLeakDetectionUnauthenticatedDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index 0826c70..8de24c02 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -372,10 +372,6 @@
 extern const char kIOSSharedHighlightingV2Name[];
 extern const char kIOSSharedHighlightingV2Description[];
 
-// Title and description for the flag to enable unrealized WebStates.
-extern const char kLazilyCreateWebStateOnRestorationName[];
-extern const char kLazilyCreateWebStateOnRestorationDescription[];
-
 // Title and description for the flag to enable leak detection for signed out
 // users.
 extern const char kLeakDetectionUnauthenticatedName[];
diff --git a/ios/chrome/browser/ui/bubble/bubble_view.mm b/ios/chrome/browser/ui/bubble/bubble_view.mm
index 3526c7f..d888c46 100644
--- a/ios/chrome/browser/ui/bubble/bubble_view.mm
+++ b/ios/chrome/browser/ui/bubble/bubble_view.mm
@@ -99,7 +99,7 @@
 const CGFloat kSnoozeButtonFontSize = 15.0f;
 
 // The size of symbol action images.
-const NSInteger kSymbolBubblePointSize = 17;
+const CGFloat kSymbolBubblePointSize = 17;
 
 // Returns a background view for BubbleView.
 UIView* BubbleBackgroundView() {
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tile_constants.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tile_constants.mm
index 4d641c9..824a429 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tile_constants.mm
+++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tile_constants.mm
@@ -18,10 +18,10 @@
 namespace {
 
 // The size of the symbol image used in content suggestions.
-NSInteger kSymbolContentSuggestionsPointSize = 22;
+const CGFloat kSymbolContentSuggestionsPointSize = 22;
 
 // Specific symbols used in the content suggestions.
-NSString* kContentSuggestionsBookmarksSymbol = @"star.fill";
+NSString* const kContentSuggestionsBookmarksSymbol = @"star.fill";
 
 }  // namespace
 
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm
index 8694d207..87f0a9e 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm
@@ -63,8 +63,7 @@
 const CGFloat kGoogleSearchLogoShrunkHeight = 36;
 
 // The size of the symbol image.
-NSInteger kSymbolContentSuggestionsPointSize = 18;
-
+const CGFloat kSymbolContentSuggestionsPointSize = 18;
 }
 
 namespace content_suggestions {
diff --git a/ios/chrome/browser/ui/first_run/BUILD.gn b/ios/chrome/browser/ui/first_run/BUILD.gn
index 87917ce..fc8980e 100644
--- a/ios/chrome/browser/ui/first_run/BUILD.gn
+++ b/ios/chrome/browser/ui/first_run/BUILD.gn
@@ -244,11 +244,9 @@
     "//components/policy/core/common:common_constants",
     "//components/policy/test_support:test_support",
     "//components/signin/ios/browser:features",
-    "//ios/chrome/app/strings",
     "//ios/chrome/app/strings:ios_chromium_strings_grit",
     "//ios/chrome/app/strings:ios_strings_grit",
     "//ios/chrome/browser/policy:eg_test_support+eg2",
-    "//ios/chrome/browser/policy:policy_util",
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/authentication:authentication_constants",
     "//ios/chrome/browser/ui/authentication:eg_test_support+eg2",
diff --git a/ios/chrome/browser/ui/first_run/first_run_two_steps_egtest.mm b/ios/chrome/browser/ui/first_run/first_run_two_steps_egtest.mm
index b7039ba..c60c14fc 100644
--- a/ios/chrome/browser/ui/first_run/first_run_two_steps_egtest.mm
+++ b/ios/chrome/browser/ui/first_run/first_run_two_steps_egtest.mm
@@ -2,14 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "base/i18n/number_formatting.h"
-#import "base/strings/string_util.h"
-#import "base/strings/sys_string_conversions.h"
-#import "components/policy/core/common/policy_loader_ios_constants.h"
-#import "components/policy/policy_constants.h"
 #import "components/signin/ios/browser/features.h"
-#import "ios/chrome/browser/policy/policy_earl_grey_utils.h"
-#import "ios/chrome/browser/policy/policy_util.h"
 #import "ios/chrome/browser/ui/authentication/signin_earl_grey.h"
 #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui_test_util.h"
 #import "ios/chrome/browser/ui/authentication/signin_matchers.h"
@@ -21,7 +14,6 @@
 #import "ios/chrome/browser/ui/ui_feature_flags.h"
 #import "ios/chrome/common/ui/promo_style/constants.h"
 #import "ios/chrome/common/ui/table_view/table_view_cells_constants.h"
-#import "ios/chrome/grit/ios_google_chrome_strings.h"
 #import "ios/chrome/grit/ios_strings.h"
 #import "ios/chrome/test/earl_grey/chrome_actions.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
@@ -31,9 +23,7 @@
 #import "ios/chrome/test/earl_grey/test_switches.h"
 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h"
 #import "ios/testing/earl_grey/app_launch_configuration.h"
-#import "ios/testing/earl_grey/app_launch_manager.h"
 #import "ios/testing/earl_grey/earl_grey_test.h"
-#import "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -41,18 +31,6 @@
 
 namespace {
 
-// Type of FRE sign-in screen intent.
-typedef NS_ENUM(NSUInteger, FRESigninIntent) {
-  // FRE without enterprise policy.
-  FRESigninIntentRegular,
-  // FRE without forced sign-in policy.
-  FRESigninIntentSigninForcedByPolicy,
-  // FRE without disabled sign-in policy.
-  FRESigninIntentSigninDisabledByPolicy,
-  // FRE with an enterprise policy.
-  FRESigninIntentSigninWithPolicy,
-};
-
 NSString* const kSyncPassphrase = @"hello";
 
 // Returns matcher for the primary action button.
@@ -126,8 +104,7 @@
 // Tests FRE with UMA default value and without sign-in.
 - (void)testWithUMACheckedAndNoSignin {
   // Verify 2 step FRE.
-  [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-            FRESigninIntentRegular];
+  [self verifyWelcomeScreenIsDisplayed];
   // Skip sign-in.
   [[self
       elementInteractionWithGreyMatcher:PromoStyleSecondaryActionButtonMatcher()
@@ -145,8 +122,7 @@
 // Tests FRE with UMA off and without sign-in.
 - (void)testWithUMAUncheckedAndNoSignin {
   // Verify 2 step FRE.
-  [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-            FRESigninIntentRegular];
+  [self verifyWelcomeScreenIsDisplayed];
   // Scroll down and open the UMA dialog.
   [[self elementInteractionWithGreyMatcher:grey_allOf(
                                                ManageUMALinkMatcher(),
@@ -182,8 +158,7 @@
 // Tests FRE with UMA off, reopen UMA dialog and close the FRE without sign-in.
 - (void)testUMAUncheckedWhenOpenedSecondTime {
   // Verify 2 step FRE.
-  [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-            FRESigninIntentRegular];
+  [self verifyWelcomeScreenIsDisplayed];
   // Scroll down and open the UMA dialog.
   id<GREYMatcher> manageUMALinkMatcher =
       grey_allOf(ManageUMALinkMatcher(), grey_sufficientlyVisible(), nil);
@@ -235,8 +210,7 @@
 // Tests to turn off UMA, and open the UMA dialog to turn it back on.
 - (void)testUMAUncheckedAndCheckItAgain {
   // Verify 2 step FRE.
-  [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-            FRESigninIntentRegular];
+  [self verifyWelcomeScreenIsDisplayed];
   // Scroll down and open the UMA dialog.
   id<GREYMatcher> manageUMALinkMatcher =
       grey_allOf(ManageUMALinkMatcher(), grey_sufficientlyVisible(), nil);
@@ -291,8 +265,7 @@
   FakeChromeIdentity* fakeIdentity = [FakeChromeIdentity fakeIdentity1];
   [SigninEarlGrey addFakeIdentity:fakeIdentity];
   // Verify 2 step FRE.
-  [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-            FRESigninIntentRegular];
+  [self verifyWelcomeScreenIsDisplayed];
   // Scroll down and open the UMA dialog.
   [[self elementInteractionWithGreyMatcher:grey_allOf(
                                                ManageUMALinkMatcher(),
@@ -340,8 +313,7 @@
   FakeChromeIdentity* fakeIdentity = [FakeChromeIdentity fakeIdentity1];
   [SigninEarlGrey addFakeIdentity:fakeIdentity];
   // Verify 2 step FRE.
-  [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-            FRESigninIntentRegular];
+  [self verifyWelcomeScreenIsDisplayed];
   // Accept sign-in.
   [[self
       elementInteractionWithGreyMatcher:PromoStylePrimaryActionButtonMatcher()
@@ -371,8 +343,7 @@
   FakeChromeIdentity* fakeIdentity = [FakeChromeIdentity fakeIdentity1];
   [SigninEarlGrey addFakeIdentity:fakeIdentity];
   // Verify 2 step FRE.
-  [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-            FRESigninIntentRegular];
+  [self verifyWelcomeScreenIsDisplayed];
   // Accept sign-in.
   [[self
       elementInteractionWithGreyMatcher:PromoStylePrimaryActionButtonMatcher()
@@ -402,8 +373,7 @@
   FakeChromeIdentity* fakeIdentity = [FakeChromeIdentity fakeIdentity1];
   [SigninEarlGrey addFakeIdentity:fakeIdentity];
   // Verify 2 step FRE.
-  [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-            FRESigninIntentRegular];
+  [self verifyWelcomeScreenIsDisplayed];
   // Accept sign-in.
   [[self
       elementInteractionWithGreyMatcher:PromoStylePrimaryActionButtonMatcher()
@@ -483,8 +453,7 @@
   FakeChromeIdentity* fakeIdentity = [FakeChromeIdentity fakeIdentity1];
   [SigninEarlGrey addFakeIdentity:fakeIdentity];
   // Verify 2 step FRE.
-  [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-            FRESigninIntentRegular];
+  [self verifyWelcomeScreenIsDisplayed];
   // Accept sign-in.
   [[self
       elementInteractionWithGreyMatcher:PromoStylePrimaryActionButtonMatcher()
@@ -517,323 +486,14 @@
   [SigninEarlGrey verifySyncUIEnabled:YES];
 }
 
-#pragma mark - Enterprise
-
-// Tests FRE with disabled sign-in policy.
-- (void)testSignInDisabledByPolicy {
-  // Configure the policy to disable SignIn.
-  [self relaunchAppWithBrowserSigninMode:BrowserSigninMode::kDisabled];
-  // Verify 2 step FRE with disabled sign-in policy.
-  [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-            FRESigninIntentSigninDisabledByPolicy];
-  // Accept FRE.
-  [[self
-      elementInteractionWithGreyMatcher:PromoStylePrimaryActionButtonMatcher()
-                   scrollViewIdentifier:
-                       kPromoStyleScrollViewAccessibilityIdentifier]
-      performAction:grey_tap()];
-  // Check that UMA is on.
-  GREYAssertTrue(
-      [FirstRunAppInterface isUMACollectionEnabled],
-      @"kMetricsReportingEnabled pref was unexpectedly false by default.");
-  // Check signed out.
-  [SigninEarlGrey verifySignedOut];
-}
-
-// Tests forced sign-in policy, and accept sync.
-- (void)testForceSigninByPolicy {
-  // Configure the policy to force sign-in.
-  [self relaunchAppWithBrowserSigninMode:BrowserSigninMode::kForced];
-  // Add identity.
-  FakeChromeIdentity* fakeIdentity = [FakeChromeIdentity fakeIdentity1];
-  [SigninEarlGrey addFakeIdentity:fakeIdentity];
-  // Verify 2 step FRE with forced sign-in policy.
-  [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-            FRESigninIntentSigninForcedByPolicy];
-  // Accept sign-in.
-  [[self
-      elementInteractionWithGreyMatcher:PromoStylePrimaryActionButtonMatcher()
-                   scrollViewIdentifier:
-                       kPromoStyleScrollViewAccessibilityIdentifier]
-      performAction:grey_tap()];
-  // Accept sync.
-  [[self
-      elementInteractionWithGreyMatcher:PromoStylePrimaryActionButtonMatcher()
-                   scrollViewIdentifier:
-                       kPromoStyleScrollViewAccessibilityIdentifier]
-      performAction:grey_tap()];
-  // Check that UMA is on.
-  GREYAssertTrue(
-      [FirstRunAppInterface isUMACollectionEnabled],
-      @"kMetricsReportingEnabled pref was unexpectedly false by default.");
-  // Check signed in.
-  [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity];
-  // Check sync is on.
-  [ChromeEarlGreyUI openSettingsMenu];
-  [SigninEarlGrey verifySyncUIEnabled:YES];
-  // Close settings.
-  [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsDoneButton()]
-      performAction:grey_tap()];
-}
-
-// Tests forced sign-in policy, and refuse sync.
-- (void)testForceSigninByPolicyWithoutSync {
-  // Configure the policy to force sign-in.
-  [self relaunchAppWithBrowserSigninMode:BrowserSigninMode::kForced];
-  // Add identity.
-  FakeChromeIdentity* fakeIdentity = [FakeChromeIdentity fakeIdentity1];
-  [SigninEarlGrey addFakeIdentity:fakeIdentity];
-  // Verify 2 step FRE with forced sign-in policy.
-  [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-            FRESigninIntentSigninForcedByPolicy];
-  // Accept sign-in.
-  [[self
-      elementInteractionWithGreyMatcher:PromoStylePrimaryActionButtonMatcher()
-                   scrollViewIdentifier:
-                       kPromoStyleScrollViewAccessibilityIdentifier]
-      performAction:grey_tap()];
-  // Refuse sync.
-  [[self
-      elementInteractionWithGreyMatcher:PromoStyleSecondaryActionButtonMatcher()
-                   scrollViewIdentifier:
-                       kPromoStyleScrollViewAccessibilityIdentifier]
-      performAction:grey_tap()];
-  // Check that UMA is on.
-  GREYAssertTrue(
-      [FirstRunAppInterface isUMACollectionEnabled],
-      @"kMetricsReportingEnabled pref was unexpectedly false by default.");
-  // Check signed in.
-  [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity];
-  // Check sync is on.
-  [ChromeEarlGreyUI openSettingsMenu];
-  [SigninEarlGrey verifySyncUIEnabled:NO];
-  // Close settings.
-  [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsDoneButton()]
-      performAction:grey_tap()];
-}
-
-// Tests sign-in with sync disabled policy.
-- (void)testSyncDisabledByPolicy {
-  [self relaunchAppWithPolicyKey:policy::key::kSyncDisabled
-                  xmlPolicyValue:"<true/>"];
-  // Add identity.
-  FakeChromeIdentity* fakeIdentity = [FakeChromeIdentity fakeIdentity1];
-  [SigninEarlGrey addFakeIdentity:fakeIdentity];
-  // Verify 2 step FRE with forced sign-in policy.
-  [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-            FRESigninIntentSigninWithPolicy];
-  // Accept sign-in.
-  [[self
-      elementInteractionWithGreyMatcher:PromoStylePrimaryActionButtonMatcher()
-                   scrollViewIdentifier:
-                       kPromoStyleScrollViewAccessibilityIdentifier]
-      performAction:grey_tap()];
-  // Check that UMA is on.
-  GREYAssertTrue(
-      [FirstRunAppInterface isUMACollectionEnabled],
-      @"kMetricsReportingEnabled pref was unexpectedly false by default.");
-  // Check signed in.
-  [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity];
-  // Check sync is on.
-  [ChromeEarlGreyUI openSettingsMenu];
-  [SigninEarlGrey verifySyncUIEnabled:NO];
-}
-
-// Tests sign-in and no sync with forced policy.
-- (void)testSigninWithOnlyBookmarkSyncDataTypeEnabled {
-  // Configure the policy to force sign-in.
-  [self relaunchAppWithPolicyKey:policy::key::kSyncTypesListDisabled
-                  xmlPolicyValue:"<array><string>bookmarks</string></array>"];
-  // Add identity.
-  FakeChromeIdentity* fakeIdentity = [FakeChromeIdentity fakeIdentity1];
-  [SigninEarlGrey addFakeIdentity:fakeIdentity];
-  // Verify 2 step FRE with forced sign-in policy.
-  [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-            FRESigninIntentSigninWithPolicy];
-  // Accept sign-in.
-  [[self
-      elementInteractionWithGreyMatcher:PromoStylePrimaryActionButtonMatcher()
-                   scrollViewIdentifier:
-                       kPromoStyleScrollViewAccessibilityIdentifier]
-      performAction:grey_tap()];
-  // Open advanced sync settings.
-  [[EarlGrey selectElementWithMatcher:GetSyncSettings()]
-      performAction:grey_tap()];
-  // Check "Sync Everything" is off
-  [[EarlGrey selectElementWithMatcher:
-                 grey_allOf(grey_accessibilityID(
-                                kSyncEverythingItemAccessibilityIdentifier),
-                            grey_descendant(grey_text(
-                                l10n_util::GetNSString(IDS_IOS_SETTING_OFF))),
-                            nil)] assertWithMatcher:grey_notNil()];
-  // Check "Bookmarks" is off
-  [[EarlGrey selectElementWithMatcher:grey_allOf(grey_accessibilityID(
-                                                     kSyncBookmarksIdentifier),
-                                                 grey_descendant(grey_text(
-                                                     l10n_util::GetNSString(
-                                                         IDS_IOS_SETTING_OFF))),
-                                                 nil)]
-      assertWithMatcher:grey_notNil()];
-  // Close the advanced sync settings.
-  [[EarlGrey selectElementWithMatcher:
-                 chrome_test_util::AdvancedSyncSettingsDoneButtonMatcher()]
-      performAction:grey_tap()];
-  // Accept sync.
-  [[self
-      elementInteractionWithGreyMatcher:PromoStylePrimaryActionButtonMatcher()
-                   scrollViewIdentifier:
-                       kPromoStyleScrollViewAccessibilityIdentifier]
-      performAction:grey_tap()];
-  // Check that UMA is on.
-  GREYAssertTrue(
-      [FirstRunAppInterface isUMACollectionEnabled],
-      @"kMetricsReportingEnabled pref was unexpectedly false by default.");
-  // Check signed in.
-  [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity];
-  // Check sync is on.
-  [ChromeEarlGreyUI openSettingsMenu];
-  [SigninEarlGrey verifySyncUIEnabled:YES];
-}
-
-// Tests enterprise policy wording on FRE when incognito policy is set.
-- (void)testIncognitoPolicy {
-  // Configure the policy to force sign-in.
-  [self relaunchAppWithPolicyKey:policy::key::kIncognitoModeAvailability
-                  xmlPolicyValue:"<integer>1</integer>"];
-  // Add identity.
-  FakeChromeIdentity* fakeIdentity = [FakeChromeIdentity fakeIdentity1];
-  [SigninEarlGrey addFakeIdentity:fakeIdentity];
-  // Verify 2 step FRE with forced sign-in policy.
-  [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-            FRESigninIntentSigninWithPolicy];
-  // Refuse sign-in.
-  [[self
-      elementInteractionWithGreyMatcher:PromoStyleSecondaryActionButtonMatcher()
-                   scrollViewIdentifier:
-                       kPromoStyleScrollViewAccessibilityIdentifier]
-      performAction:grey_tap()];
-  // Check that UMA is on.
-  GREYAssertTrue(
-      [FirstRunAppInterface isUMACollectionEnabled],
-      @"kMetricsReportingEnabled pref was unexpectedly false by default.");
-  // Check signed out.
-  [SigninEarlGrey verifySignedOut];
-}
-
 #pragma mark Helper
 
-- (void)relaunchAppWithBrowserSigninMode:(BrowserSigninMode)mode {
-  std::string xmlPolicyValue("<integer>");
-  xmlPolicyValue += std::to_string(static_cast<int>(mode));
-  xmlPolicyValue += "</integer>";
-  [self relaunchAppWithPolicyKey:policy::key::kBrowserSignin
-                  xmlPolicyValue:xmlPolicyValue];
-}
-
-// Sets policy value and relaunches the app.
-- (void)relaunchAppWithPolicyKey:(std::string)policyKey
-                  xmlPolicyValue:(std::string)xmlPolicyValue {
-  std::string policyData = std::string("<dict><key>") + policyKey + "</key>" +
-                           xmlPolicyValue + "</dict>";
-  // Configure the policy to force sign-in.
-  AppLaunchConfiguration config = self.appConfigurationForTestCase;
-  config.additional_args.push_back(
-      "-" + base::SysNSStringToUTF8(kPolicyLoaderIOSConfigurationKey));
-  config.additional_args.push_back(policyData);
-  // Relaunch the app to take the configuration into account.
-  [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config];
-}
-
-// Checks that the sign-in screen for enterprise is displayed.
-- (void)verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
-    (FRESigninIntent)FRESigninIntent {
+// Checks that the sign-in screen is displayed.
+- (void)verifyWelcomeScreenIsDisplayed {
   [[EarlGrey selectElementWithMatcher:
                  grey_accessibilityID(
                      first_run::kFirstRunSignInScreenAccessibilityIdentifier)]
       assertWithMatcher:grey_notNil()];
-  NSString* title = nil;
-  NSString* subtitle = nil;
-  NSMutableArray* disclaimerStrings = [NSMutableArray array];
-  switch (FRESigninIntent) {
-    case FRESigninIntentRegular:
-      title = l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SIGNIN_TITLE);
-      subtitle =
-          l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SIGNIN_SUBTITLE_SHORT);
-      break;
-    case FRESigninIntentSigninForcedByPolicy:
-      title =
-          l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SIGNIN_TITLE_SIGNIN_FORCED);
-      subtitle = l10n_util::GetNSString(
-          IDS_IOS_FIRST_RUN_SIGNIN_SUBTITLE_SIGNIN_FORCED);
-      [disclaimerStrings
-          addObject:l10n_util::GetNSString(
-                        IDS_IOS_FIRST_RUN_WELCOME_SCREEN_BROWSER_MANAGED)];
-      break;
-    case FRESigninIntentSigninDisabledByPolicy:
-      if ([ChromeEarlGrey isIPadIdiom]) {
-        title =
-            l10n_util::GetNSString(IDS_IOS_FIRST_RUN_WELCOME_SCREEN_TITLE_IPAD);
-      } else {
-        title = l10n_util::GetNSString(
-            IDS_IOS_FIRST_RUN_WELCOME_SCREEN_TITLE_IPHONE);
-      }
-      subtitle =
-          l10n_util::GetNSString(IDS_IOS_FIRST_RUN_WELCOME_SCREEN_SUBTITLE);
-      [disclaimerStrings
-          addObject:l10n_util::GetNSString(
-                        IDS_IOS_FIRST_RUN_WELCOME_SCREEN_BROWSER_MANAGED)];
-      break;
-    case FRESigninIntentSigninWithPolicy:
-      title = l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SIGNIN_TITLE);
-      subtitle =
-          l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SIGNIN_SUBTITLE_SHORT);
-      [disclaimerStrings
-          addObject:l10n_util::GetNSString(
-                        IDS_IOS_FIRST_RUN_WELCOME_SCREEN_BROWSER_MANAGED)];
-      break;
-  }
-  [disclaimerStrings
-      addObject:l10n_util::GetNSString(
-                    IDS_IOS_FIRST_RUN_WELCOME_SCREEN_TERMS_OF_SERVICE)];
-  [disclaimerStrings
-      addObject:l10n_util::GetNSString(
-                    IDS_IOS_FIRST_RUN_WELCOME_SCREEN_METRIC_REPORTING)];
-  // Validate the Title text.
-  [[self elementInteractionWithGreyMatcher:grey_allOf(
-                                               grey_text(title),
-                                               grey_sufficientlyVisible(), nil)
-                      scrollViewIdentifier:
-                          kPromoStyleScrollViewAccessibilityIdentifier]
-      assertWithMatcher:grey_notNil()];
-  // Validate the Subtitle text.
-  [[self elementInteractionWithGreyMatcher:grey_allOf(
-                                               grey_text(subtitle),
-                                               grey_sufficientlyVisible(), nil)
-                      scrollViewIdentifier:
-                          kPromoStyleScrollViewAccessibilityIdentifier]
-      assertWithMatcher:grey_notNil()];
-  // Validate the Managed text.
-  [self verifyDisclaimerFooterWithStrings:disclaimerStrings];
-}
-
-// Checks the disclaimer footer with the list of strings. |strings| can contain
-// "BEGIN_LINK" and "END_LINK" for URL tags.
-- (void)verifyDisclaimerFooterWithStrings:(NSArray*)strings {
-  NSString* disclaimerText = [strings componentsJoinedByString:@" "];
-  // Remove URL tags.
-  disclaimerText =
-      [disclaimerText stringByReplacingOccurrencesOfString:@"BEGIN_LINK"
-                                                withString:@""];
-  disclaimerText =
-      [disclaimerText stringByReplacingOccurrencesOfString:@"END_LINK"
-                                                withString:@""];
-  // Check the footer.
-  [[self elementInteractionWithGreyMatcher:grey_allOf(
-                                               grey_text(disclaimerText),
-                                               grey_sufficientlyVisible(), nil)
-                      scrollViewIdentifier:
-                          kPromoStyleScrollViewAccessibilityIdentifier]
-      assertWithMatcher:grey_notNil()];
 }
 
 // Returns GREYElementInteraction for `matcher`, using `scrollViewMatcher` to
diff --git a/ios/chrome/browser/ui/fullscreen/BUILD.gn b/ios/chrome/browser/ui/fullscreen/BUILD.gn
index 06dc1ca..d196cb6 100644
--- a/ios/chrome/browser/ui/fullscreen/BUILD.gn
+++ b/ios/chrome/browser/ui/fullscreen/BUILD.gn
@@ -175,6 +175,7 @@
     "//base",
     "//base/test:test_support",
     "//components/translate/core/browser:translate_pref_names",
+    "//ios/chrome/browser/ui/fullscreen:feature_flags",
     "//ios/chrome/browser/ui/fullscreen/test:eg_test_support+eg2",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/test:eg_test_support+eg2",
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
index ed3510e..af05874 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
@@ -9,6 +9,7 @@
 #include "base/strings/utf_string_conversions.h"
 #import "base/test/ios/wait_util.h"
 #include "components/translate/core/browser/translate_pref_names.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h"
 #import "ios/chrome/browser/ui/fullscreen/test/fullscreen_app_interface.h"
 #include "ios/chrome/browser/ui/util/ui_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
@@ -91,6 +92,19 @@
 
 @implementation FullscreenTestCase
 
+// TODO(crbug.com/1345810): Remove when iOS16/kSmoothScrollingDefault is fixed.
+- (AppLaunchConfiguration)appConfigurationForTestCase {
+  AppLaunchConfiguration config = [super appConfigurationForTestCase];
+  if (@available(iOS 16, *)) {
+    NSString* bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
+    if ([bundleIdentifier hasPrefix:@"org.chromium.ost.chrome"]) {
+      config.features_disabled.push_back(
+          fullscreen::features::kSmoothScrollingDefault);
+    }
+  }
+  return config;
+}
+
 - (void)setUp {
   [super setUp];
 
diff --git a/ios/chrome/browser/ui/icons/action_icon.h b/ios/chrome/browser/ui/icons/action_icon.h
index e974681..c388c93 100644
--- a/ios/chrome/browser/ui/icons/action_icon.h
+++ b/ios/chrome/browser/ui/icons/action_icon.h
@@ -8,27 +8,27 @@
 #import <UIKit/UIKit.h>
 
 // The size of the symbol image used in UIActions.
-extern NSInteger kSymbolActionPointSize;
+extern const CGFloat kSymbolActionPointSize;
 
 // Specific symbols used to create UIActions.
-extern NSString* kLinkActionSymbol;
-extern NSString* kQRCodeFinderActionSymbol;
-extern NSString* kNewTabActionSymbol;
-extern NSString* kNewTabCircleActionSymbol;
-extern NSString* kClipboardActionSymbol;
-extern NSString* kDeleteActionSymbol;
-extern NSString* kEditActionSymbol;
-extern NSString* kMarkAsReadActionSymbol;
-extern NSString* kReadLaterActionSymbol;
-extern NSString* kAddBookmarkActionSymbol;
-extern NSString* kCopyActionSymbol;
-extern NSString* kNewWindowActionSymbol;
-extern NSString* kHideActionSymbol;
-extern NSString* kRequestDesktopActionSymbol;
-extern NSString* kRequestMobileActionSymbol;
-extern NSString* kFindInPageActionSymbol;
-extern NSString* kZoomTextActionSymbol;
-extern NSString* kSaveImageActionSymbol;
-extern NSString* kOpenImageActionSymbol;
+extern NSString* const kLinkActionSymbol;
+extern NSString* const kQRCodeFinderActionSymbol;
+extern NSString* const kNewTabActionSymbol;
+extern NSString* const kNewTabCircleActionSymbol;
+extern NSString* const kClipboardActionSymbol;
+extern NSString* const kDeleteActionSymbol;
+extern NSString* const kEditActionSymbol;
+extern NSString* const kMarkAsReadActionSymbol;
+extern NSString* const kReadLaterActionSymbol;
+extern NSString* const kAddBookmarkActionSymbol;
+extern NSString* const kCopyActionSymbol;
+extern NSString* const kNewWindowActionSymbol;
+extern NSString* const kHideActionSymbol;
+extern NSString* const kRequestDesktopActionSymbol;
+extern NSString* const kRequestMobileActionSymbol;
+extern NSString* const kFindInPageActionSymbol;
+extern NSString* const kZoomTextActionSymbol;
+extern NSString* const kSaveImageActionSymbol;
+extern NSString* const kOpenImageActionSymbol;
 
 #endif  // IOS_CHROME_BROWSER_UI_ICONS_ACTION_ICON_H_
diff --git a/ios/chrome/browser/ui/icons/action_icon.mm b/ios/chrome/browser/ui/icons/action_icon.mm
index 8af47447..b278e7a 100644
--- a/ios/chrome/browser/ui/icons/action_icon.mm
+++ b/ios/chrome/browser/ui/icons/action_icon.mm
@@ -8,24 +8,24 @@
 #error "This file requires ARC support."
 #endif
 
-NSInteger kSymbolActionPointSize = 18;
+extern const CGFloat kSymbolActionPointSize = 18;
 
-NSString* kLinkActionSymbol = @"link";
-NSString* kQRCodeFinderActionSymbol = @"qrcode.viewfinder";
-NSString* kNewTabActionSymbol = @"plus.square";
-NSString* kNewTabCircleActionSymbol = @"plus.circle";
-NSString* kClipboardActionSymbol = @"doc.on.clipboard";
-NSString* kDeleteActionSymbol = @"trash";
-NSString* kEditActionSymbol = @"pencil";
-NSString* kMarkAsReadActionSymbol = @"text.badge.checkmark";
-NSString* kReadLaterActionSymbol = @"text.badge.plus";
-NSString* kAddBookmarkActionSymbol = @"star";
-NSString* kCopyActionSymbol = @"doc.on.doc";
-NSString* kNewWindowActionSymbol = @"square.split.2x1";
-NSString* kHideActionSymbol = @"eye.slash";
-NSString* kRequestDesktopActionSymbol = @"desktopcomputer";
-NSString* kRequestMobileActionSymbol = @"iphone";
-NSString* kFindInPageActionSymbol = @"doc.text.magnifyingglass";
-NSString* kZoomTextActionSymbol = @"plus.magnifyingglass";
-NSString* kSaveImageActionSymbol = @"square.and.arrow.down";
-NSString* kOpenImageActionSymbol = @"arrow.up.right.square";
+NSString* const kLinkActionSymbol = @"link";
+NSString* const kQRCodeFinderActionSymbol = @"qrcode.viewfinder";
+NSString* const kNewTabActionSymbol = @"plus.square";
+NSString* const kNewTabCircleActionSymbol = @"plus.circle";
+NSString* const kClipboardActionSymbol = @"doc.on.clipboard";
+NSString* const kDeleteActionSymbol = @"trash";
+NSString* const kEditActionSymbol = @"pencil";
+NSString* const kMarkAsReadActionSymbol = @"text.badge.checkmark";
+NSString* const kReadLaterActionSymbol = @"text.badge.plus";
+NSString* const kAddBookmarkActionSymbol = @"star";
+NSString* const kCopyActionSymbol = @"doc.on.doc";
+NSString* const kNewWindowActionSymbol = @"square.split.2x1";
+NSString* const kHideActionSymbol = @"eye.slash";
+NSString* const kRequestDesktopActionSymbol = @"desktopcomputer";
+NSString* const kRequestMobileActionSymbol = @"iphone";
+NSString* const kFindInPageActionSymbol = @"doc.text.magnifyingglass";
+NSString* const kZoomTextActionSymbol = @"plus.magnifyingglass";
+NSString* const kSaveImageActionSymbol = @"square.and.arrow.down";
+NSString* const kOpenImageActionSymbol = @"arrow.up.right.square";
diff --git a/ios/chrome/browser/ui/icons/settings_icon.h b/ios/chrome/browser/ui/icons/settings_icon.h
index 267c3abc..d9cee73f 100644
--- a/ios/chrome/browser/ui/icons/settings_icon.h
+++ b/ios/chrome/browser/ui/icons/settings_icon.h
@@ -17,7 +17,7 @@
 extern NSString* const kPrivacySecuritySymbol;
 
 // The size of the symbol image displayed in the Settings root screen.
-extern NSInteger kSettingsRootSymbolImagePointSize;
+extern const CGFloat kSettingsRootSymbolImagePointSize;
 
 // Returns a SF symbol named `symbol_name` configured for the Settings root
 // screen.
diff --git a/ios/chrome/browser/ui/icons/settings_icon.mm b/ios/chrome/browser/ui/icons/settings_icon.mm
index 19fe1f9..41fd0bd 100644
--- a/ios/chrome/browser/ui/icons/settings_icon.mm
+++ b/ios/chrome/browser/ui/icons/settings_icon.mm
@@ -10,7 +10,7 @@
 #error "This file requires ARC support."
 #endif
 
-NSInteger kSettingsRootSymbolImagePointSize = 18;
+const CGFloat kSettingsRootSymbolImagePointSize = 18;
 
 // Custom symbol names.
 NSString* const kSyncDisabledSymbol = @"arrow_triangle_slash_circlepath";
diff --git a/ios/chrome/browser/ui/menu/action_factory.mm b/ios/chrome/browser/ui/menu/action_factory.mm
index cf97ae9..6be4db4 100644
--- a/ios/chrome/browser/ui/menu/action_factory.mm
+++ b/ios/chrome/browser/ui/menu/action_factory.mm
@@ -19,8 +19,6 @@
 #error "This file requires ARC support."
 #endif
 
-NSInteger kSymbolToolbarPointSize = 18;
-
 @interface ActionFactory ()
 
 // Histogram to record executed actions.
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_util.mm b/ios/chrome/browser/ui/omnibox/omnibox_util.mm
index 0c91b9e..c4e1fb6 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_util.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_util.mm
@@ -17,7 +17,7 @@
 namespace {
 
 // The size of symbol images.
-NSInteger kSymbolLocationBarPointSize = 10;
+const CGFloat kSymbolLocationBarPointSize = 10;
 
 }  // namespace
 
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_table_view_item.mm b/ios/chrome/browser/ui/reading_list/reading_list_table_view_item.mm
index f7ff2008..97cbbbb 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_table_view_item.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_table_view_item.mm
@@ -31,7 +31,7 @@
 namespace {
 
 // The size of the symbol badge image.
-NSInteger kSymbolBadgeImagePointSize = 13;
+const CGFloat kSymbolBadgeImagePointSize = 13;
 
 // The string format used to append the distillation date to the URL host.
 NSString* const kURLAndDistillationDateFormat = @"%@ • %@";
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm
index c307122e..a1fe9403 100644
--- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm
@@ -91,11 +91,11 @@
 };
 
 // The size of the symbol image used in the 'Clear Browsing Data' view.
-NSInteger kSymbolPointSize = 22;
+const CGFloat kSymbolPointSize = 22;
 
 // Specific symbols used in the 'Clear Browsing Data' view.
-NSString* kCachedDataSymbol = @"photo.on.rectangle";
-NSString* kAutofillDataSymbol = @"wand.and.rays";
+NSString* const kCachedDataSymbol = @"photo.on.rectangle";
+NSString* const kAutofillDataSymbol = @"wand.and.rays";
 
 // Returns the symbol coresponding to the given itemType.
 UIImage* SymbolForItemType(ClearBrowsingDataItemType itemType) {
diff --git a/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm b/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm
index 26930c8f..a9464ec 100644
--- a/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm
@@ -63,7 +63,7 @@
 namespace {
 
 // The size of the symbol image.
-NSInteger kSymbolAddAccountPointSize = 20;
+const CGFloat kSymbolAddAccountPointSize = 20;
 
 typedef NS_ENUM(NSInteger, SectionIdentifier) {
   SectionIdentifierAccounts = kSectionIdentifierEnumZero,
diff --git a/ios/chrome/browser/ui/settings/password/password_manager_view_controller.mm b/ios/chrome/browser/ui/settings/password/password_manager_view_controller.mm
index 6fdde70..3192b6b 100644
--- a/ios/chrome/browser/ui/settings/password/password_manager_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/password/password_manager_view_controller.mm
@@ -126,7 +126,8 @@
     return false;
 
   for (size_t i = 0; i < lhs.size(); i++) {
-    if (CreateSortKey(lhs[i]) != CreateSortKey(rhs[i]))
+    if (CreateSortKey(lhs[i], password_manager::IgnoreStore(false)) !=
+        CreateSortKey(rhs[i], password_manager::IgnoreStore(false)))
       return false;
   }
   return true;
@@ -137,10 +138,12 @@
     const std::vector<password_manager::PasswordForm>& to_delete) {
   std::unordered_set<std::string> sort_keys_to_delete;
   base::ranges::for_each(to_delete, [&sort_keys_to_delete](const auto& form) {
-    sort_keys_to_delete.insert(CreateSortKey(form));
+    sort_keys_to_delete.insert(
+        CreateSortKey(form, password_manager::IgnoreStore(false)));
   });
   base::EraseIf(forms, [&sort_keys_to_delete](const auto& form) {
-    return sort_keys_to_delete.find(CreateSortKey(form)) !=
+    return sort_keys_to_delete.find(
+               CreateSortKey(form, password_manager::IgnoreStore(false))) !=
            sort_keys_to_delete.end();
   });
 }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_new_tab_button.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_new_tab_button.mm
index 472e622..5cb44533 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_new_tab_button.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_new_tab_button.mm
@@ -20,7 +20,7 @@
 namespace {
 
 // The size of the symbol image.
-NSInteger kSymbolNewTabPointSize = 24;
+const CGFloat kSymbolNewTabPointSize = 24;
 
 }  // namespace
 
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_top_toolbar.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_top_toolbar.mm
index b978cc4..027d695 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_top_toolbar.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_top_toolbar.mm
@@ -25,7 +25,7 @@
 const int kSearchBarTrailingSpace = 24;
 
 // The size of top toolbar search symbol image.
-NSInteger kSymbolSearchImagePointSize = 22;
+const CGFloat kSymbolSearchImagePointSize = 22;
 }
 
 @interface TabGridTopToolbar () <UIToolbarDelegate>
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm b/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm
index 7ce7ce71..661cf88b 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm
+++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm
@@ -29,11 +29,11 @@
 namespace {
 
 // The size of the symbol image.
-NSInteger kSymbolToolbarPointSize = 24;
+const CGFloat kSymbolToolbarPointSize = 24;
 
 // Specific symbols used in the toolbar.
-NSString* kToolbarArrowBackwardSymbol = @"arrow.backward";
-NSString* kToolbarArrowForwardSymbol = @"arrow.forward";
+NSString* const kToolbarArrowBackwardSymbol = @"arrow.backward";
+NSString* const kToolbarArrowForwardSymbol = @"arrow.forward";
 
 }  // namespace
 
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 e205191..f851acee 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
@@ -34,38 +34,38 @@
 
 namespace {
 
-constexpr CGFloat kActionsBottomMargin = 10;
+const CGFloat kActionsBottomMargin = 10;
 // Gradient height.
-constexpr CGFloat kGradientHeight = 40.;
-constexpr CGFloat kScrollViewBottomInsets = 20;
-constexpr CGFloat kStackViewSpacing = 8;
-constexpr CGFloat kStackViewSpacingAfterIllustration = 27;
+const CGFloat kGradientHeight = 40.;
+const CGFloat kScrollViewBottomInsets = 20;
+const CGFloat kStackViewSpacing = 8;
+const CGFloat kStackViewSpacingAfterIllustration = 27;
 // The multiplier used when in regular horizontal size class.
-constexpr CGFloat kSafeAreaMultiplier = 0.65;
-constexpr CGFloat kContentOptimalWidth = 327;
+const CGFloat kSafeAreaMultiplier = 0.65;
+const CGFloat kContentOptimalWidth = 327;
 
 // The size of the symbol image.
-constexpr NSInteger kSymbolBadgeImagePointSize = 13;
+const CGFloat kSymbolBadgeImagePointSize = 13;
 
 // The name of the checkmark symbol in filled circle.
 NSString* const kCheckmarkSymbol = @"checkmark.circle.fill";
 
 // Properties of the favicon.
-constexpr CGFloat kFaviconCornerRadius = 13;
-constexpr CGFloat kFaviconShadowOffsetX = 0;
-constexpr CGFloat kFaviconShadowOffsetY = 0;
-constexpr CGFloat kFaviconShadowRadius = 6;
-constexpr CGFloat kFaviconShadowOpacity = 0.1;
+const CGFloat kFaviconCornerRadius = 13;
+const CGFloat kFaviconShadowOffsetX = 0;
+const CGFloat kFaviconShadowOffsetY = 0;
+const CGFloat kFaviconShadowRadius = 6;
+const CGFloat kFaviconShadowOpacity = 0.1;
 
 // Length of each side of the favicon frame (which contains the favicon and the
 // surrounding whitespace).
-constexpr CGFloat kFaviconFrameSideLength = 60;
+const CGFloat kFaviconFrameSideLength = 60;
 
 // Length of each side of the favicon.
-constexpr CGFloat kFaviconSideLength = 30;
+const CGFloat kFaviconSideLength = 30;
 
 // Length of each side of the favicon badge.
-constexpr CGFloat kFaviconBadgeSideLength = 24;
+const CGFloat kFaviconBadgeSideLength = 24;
 
 }  // namespace
 
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 fcb5d77..41f4747 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 @@
-5a22ae7e156c6d3bbee8f14a9051bd82655aef38
\ No newline at end of file
+e3782fce44e098d2d74a35ba3c3eedf2c6c65035
\ 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 0a2dc443..a58355c5 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 @@
-695bfa5d83ee40f45dd04abcfa772cc13941f17a
\ No newline at end of file
+4a12eb2a39e1c13d596dcc6c8e65ca0c498b641a
\ 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 9a6f005a..b4e6289 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 @@
-069522c9aad31d61dbf0dd5c4d192ee39087e04b
\ No newline at end of file
+ca64430aa7cf21bcb0fb017464ace70ec926ae97
\ 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 b8040a9..0c6f4b4 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 @@
-53dcb38023d5b4e50418da5e9d2c20e496933586
\ No newline at end of file
+b09840ef2f87faaa90ad572ad41bea54e5c22f76
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
index bad25fb..4fa5e0c1 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-46f1347d191bb8805f12f55ad60b9f7d18cb6db1
\ No newline at end of file
+3b1ba1e23a5e66197ebe9f783312e61228af3c41
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
index dac92fca..1b53f5b 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-34b0e6555fbc60dca4a9d05fad9ba9abc08c372a
\ No newline at end of file
+1fe93d98224c4adf2bbbb8bb88e3bbfb5d0f52c0
\ 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 70688f2b..724ee2c 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 @@
-7991932307909cfc1283230ae3ae45b20c92c60f
\ No newline at end of file
+0d79de6a6ae300138122277dab7a99240634bf08
\ 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 4f6242d..f4fb60da 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 @@
-f68d628527e49e768855fe1d065755e6ec8fe444
\ No newline at end of file
+f5269b0071b1007f6cddd8ba296052462ab72f11
\ 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 791b6ab3..1b4ba982 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 @@
-aca876528cd4c3ce0c19987ba213f2e51a38e412
\ No newline at end of file
+4d41f91863212cb5572e00c75e09edd557968667
\ 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 4a44112..a8f3c19c 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 @@
-f4d3130ba4d97003cc162231b569d2d93dcc7aec
\ No newline at end of file
+3120ed39b73023834f47a90838e0bfec2967e030
\ No newline at end of file
diff --git a/ios/web/common/features.h b/ios/web/common/features.h
index eb2f50e..cb00be440 100644
--- a/ios/web/common/features.h
+++ b/ios/web/common/features.h
@@ -56,10 +56,6 @@
 // interaction state.
 extern const base::Feature kSynthesizedRestoreSession;
 
-// Enable support for unrealized WebState upon session restoration.
-// See //docs/ios/unrealized_web_state.md for more information.
-extern const base::Feature kEnableUnrealizedWebStates;
-
 // Enables user control for camera and/or microphone access for a specific site
 // through site settings during its lifespan. When enabled, each web state will
 // keep track of whether camera and/or microphone access is granted by the user
diff --git a/ios/web/common/features.mm b/ios/web/common/features.mm
index cb1ff6e..9de87790 100644
--- a/ios/web/common/features.mm
+++ b/ios/web/common/features.mm
@@ -49,9 +49,6 @@
 const base::Feature kSynthesizedRestoreSession{
     "SynthesizedRestoreSession", base::FEATURE_ENABLED_BY_DEFAULT};
 
-const base::Feature kEnableUnrealizedWebStates{
-    "EnableUnrealizedWebStates", base::FEATURE_ENABLED_BY_DEFAULT};
-
 const base::Feature kMediaPermissionsControl{"MediaPermissionsControl",
                                              base::FEATURE_ENABLED_BY_DEFAULT};
 
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm
index 51b0feb..44b962be 100644
--- a/ios/web/web_state/web_state_impl.mm
+++ b/ios/web/web_state/web_state_impl.mm
@@ -28,10 +28,10 @@
 namespace web {
 namespace {
 
-// With |kEnableUnrealizedWebStates|, detect inefficient usage of WebState
-// realization. Various bugs have triggered the realization of the entire
-// WebStateList. Detect this by checking for the realization of 3 WebStates
-// within one second. Only report this error once per launch.
+// Detect inefficient usage of WebState realization. Various bugs have
+// triggered the realization of the entire WebStateList. Detect this by
+// checking for the realization of 3 WebStates within one second. Only
+// report this error once per launch.
 constexpr size_t kMaxEvents = 3;
 constexpr CFTimeInterval kWindowSizeInSeconds = 1.0f;
 size_t g_last_realized_count = 0;
@@ -82,8 +82,7 @@
 
 WebStateImpl::WebStateImpl(const CreateParams& params,
                            CRWSessionStorage* session_storage) {
-  if (session_storage &&
-      base::FeatureList::IsEnabled(features::kEnableUnrealizedWebStates)) {
+  if (session_storage) {
     saved_ = std::make_unique<SerializedData>(this, params, session_storage);
   } else {
     pimpl_ = std::make_unique<RealizedWebState>(this);
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 05165d6..f14220e 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -3607,7 +3607,7 @@
 
   // Configure against proxy server "myproxy:70".
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   RecordingNetLogObserver net_log_observer;
   NetLogWithSource net_log_with_source =
@@ -3757,7 +3757,7 @@
 
   // Configure against proxy server "myproxy:70".
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   RecordingNetLogObserver net_log_observer;
   session_deps_.net_log = NetLog::Get();
@@ -4132,7 +4132,7 @@
 
   // Configure against proxy server "myproxy:70".
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   RecordingNetLogObserver net_log_observer;
   session_deps_.net_log = NetLog::Get();
@@ -4409,7 +4409,7 @@
 
   // Proxy matches request URL.
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   NetLogWithSource net_log_with_source =
       NetLogWithSource::Make(NetLogSourceType::NONE);
@@ -4566,7 +4566,7 @@
 
   // Proxy matches request URL.
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   NetLogWithSource net_log_with_source =
       NetLogWithSource::Make(NetLogSourceType::NONE);
@@ -4820,7 +4820,7 @@
 
   // Proxy matches request URL.
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   NetLogWithSource net_log_with_source =
       NetLogWithSource::Make(NetLogSourceType::NONE);
@@ -5257,7 +5257,7 @@
 
   // Configure against proxy server "myproxy:70".
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
@@ -5373,7 +5373,7 @@
 
   // Configure against proxy server "myproxy:70".
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
@@ -5494,7 +5494,7 @@
 
   // Configure against proxy server "myproxy:70".
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
@@ -5594,7 +5594,7 @@
 
   // Configure against proxy server "myproxy:70".
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
@@ -5712,7 +5712,7 @@
 
   // Configure against proxy server "myproxy:70".
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
@@ -6320,7 +6320,7 @@
 
   // Configure against proxy server "myproxy:70".
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   NetLogWithSource net_log_with_source =
       NetLogWithSource::Make(NetLogSourceType::NONE);
@@ -9447,7 +9447,7 @@
   // The NTLM test data expects the proxy to be named 'server'. The origin is
   // https://origin/.
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   SSLContextConfig config;
@@ -11319,7 +11319,7 @@
 // Test HTTPS connections to a site, going through an HTTPS proxy
 TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   session_deps_.net_log = net::NetLog::Get();
 
@@ -11383,7 +11383,7 @@
 // Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
 TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   session_deps_.net_log = net::NetLog::Get();
 
@@ -11450,7 +11450,7 @@
        RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
   base::HistogramTester histograms;
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   session_deps_.net_log = net::NetLog::Get();
 
@@ -11496,9 +11496,9 @@
 TEST_F(HttpNetworkTransactionTest,
        RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
   base::HistogramTester histograms;
-  session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
-          "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
+  session_deps_.proxy_resolution_service = ConfiguredProxyResolutionService::
+      CreateFixedFromAutoDetectedPacResultForTest("HTTPS proxy:70",
+                                                  TRAFFIC_ANNOTATION_FOR_TESTS);
   session_deps_.net_log = net::NetLog::Get();
 
   HttpRequestInfo request;
@@ -11725,7 +11725,7 @@
 
   // Configure against https proxy server "myproxy:70".
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   RecordingNetLogObserver net_log_observer;
   session_deps_.net_log = NetLog::Get();
@@ -12366,7 +12366,7 @@
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
 
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
   session_deps_.net_log = net::NetLog::Get();
 
@@ -12422,7 +12422,7 @@
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
 
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
   session_deps_.net_log = net::NetLog::Get();
 
@@ -12538,7 +12538,7 @@
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
 
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
   session_deps_.net_log = net::NetLog::Get();
 
@@ -12606,7 +12606,7 @@
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
 
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
   session_deps_.net_log = net::NetLog::Get();
 
@@ -16394,7 +16394,7 @@
 // Test a basic GET request through a proxy.
 TEST_F(HttpNetworkTransactionTest, ProxyGet) {
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   session_deps_.net_log = NetLog::Get();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -16461,7 +16461,7 @@
 // Test a basic HTTPS GET request through a proxy.
 TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   RecordingNetLogObserver net_log_observer;
   session_deps_.net_log = NetLog::Get();
@@ -16546,7 +16546,7 @@
 // literal host.
 TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   RecordingNetLogObserver net_log_observer;
   session_deps_.net_log = NetLog::Get();
@@ -18290,7 +18290,7 @@
   data1.set_connect_data(connect_data1);
 
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   session_deps_.net_log = net::NetLog::Get();
   SSLSocketDataProvider ssl1(ASYNC, OK);  // to the proxy
@@ -19631,7 +19631,7 @@
 
   // Configure against proxy server "myproxy:70".
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -19738,7 +19738,7 @@
 
   // Configure against proxy server "myproxy:70".
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -19811,7 +19811,7 @@
   for (bool secure : {true, false}) {
     SCOPED_TRACE(secure);
     session_deps_.proxy_resolution_service =
-        ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+        ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
             "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
     session_deps_.enable_quic = true;
 
@@ -20116,7 +20116,7 @@
 
 TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
   session_deps_.enable_quic = false;
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -20399,7 +20399,7 @@
 TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
        DontProcessNelHeaderProxy) {
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   session_deps_.net_log = NetLog::Get();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -21349,7 +21349,7 @@
 
   // Configure against proxy server "myproxy:70".
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
 
@@ -22819,7 +22819,7 @@
     SCOPED_TRACE(use_proxy);
     if (use_proxy) {
       session_deps_.proxy_resolution_service =
-          ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+          ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
               "HTTPS proxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
     } else {
       session_deps_.proxy_resolution_service =
diff --git a/net/http/http_stream_factory_job_controller_unittest.cc b/net/http/http_stream_factory_job_controller_unittest.cc
index 706b74b..d9c3950 100644
--- a/net/http/http_stream_factory_job_controller_unittest.cc
+++ b/net/http/http_stream_factory_job_controller_unittest.cc
@@ -484,7 +484,7 @@
 
 TEST_P(HttpStreamFactoryJobControllerTest, NoSupportedProxies) {
   session_deps_.proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
   session_deps_.enable_quic = false;
   HttpRequestInfo request_info;
@@ -591,7 +591,7 @@
 
       std::unique_ptr<ConfiguredProxyResolutionService>
           proxy_resolution_service =
-              ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+              ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
                   "PROXY badproxy:99; PROXY badfallbackproxy:98; DIRECT",
                   TRAFFIC_ANNOTATION_FOR_TESTS);
       auto test_proxy_delegate = std::make_unique<TestProxyDelegate>();
@@ -777,12 +777,12 @@
 
       std::unique_ptr<ConfiguredProxyResolutionService>
           proxy_resolution_service =
-              ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+              ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
                   "HTTPS badproxy:99; HTTPS badfallbackproxy:98; DIRECT",
                   TRAFFIC_ANNOTATION_FOR_TESTS);
       if (mock_error.triggers_ssl_connect_job_retry_logic) {
         proxy_resolution_service =
-            ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+            ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
                 "HTTPS badproxy:99; DIRECT", TRAFFIC_ANNOTATION_FOR_TESTS);
       }
       auto test_proxy_delegate = std::make_unique<TestProxyDelegate>();
@@ -976,7 +976,7 @@
     CreateSessionDeps();
 
     std::unique_ptr<ConfiguredProxyResolutionService> proxy_resolution_service =
-        ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+        ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
             "SOCKS5 badproxy:99; SOCKS5 badfallbackproxy:98; DIRECT",
             TRAFFIC_ANNOTATION_FOR_TESTS);
     auto test_proxy_delegate = std::make_unique<TestProxyDelegate>();
@@ -1089,7 +1089,7 @@
 // Tests that ERR_MSG_TOO_BIG is retryable for QUIC proxy.
 TEST_F(JobControllerReconsiderProxyAfterErrorTest, ReconsiderErrMsgTooBig) {
   std::unique_ptr<ConfiguredProxyResolutionService> proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC badproxy:99; DIRECT", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   // Before starting the test, verify that there are no proxies marked as bad.
@@ -1136,7 +1136,7 @@
 TEST_F(JobControllerReconsiderProxyAfterErrorTest,
        DoNotReconsiderErrMsgTooBig) {
   std::unique_ptr<ConfiguredProxyResolutionService> proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "HTTPS badproxy:99; DIRECT", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   // Before starting the test, verify that there are no proxies marked as bad.
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc
index 80d406fc..7bcb259 100644
--- a/net/http/http_stream_factory_unittest.cc
+++ b/net/http/http_stream_factory_unittest.cc
@@ -728,7 +728,7 @@
 TEST_F(HttpStreamFactoryTest, JobNotifiesProxy) {
   const char* kProxyString = "PROXY bad:99; PROXY maybe:80; DIRECT";
   SpdySessionDependencies session_deps(
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           kProxyString, TRAFFIC_ANNOTATION_FOR_TESTS));
 
   // First connection attempt fails
@@ -780,7 +780,7 @@
 TEST_F(HttpStreamFactoryTest, NoProxyFallbackOnTunnelFail) {
   const char* kProxyString = "PROXY bad:99; DIRECT";
   SpdySessionDependencies session_deps(
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           kProxyString, TRAFFIC_ANNOTATION_FOR_TESTS));
 
   // A 404 in response to a CONNECT will trigger
@@ -848,7 +848,7 @@
 TEST_F(HttpStreamFactoryTest, QuicProxyMarkedAsBad) {
   for (int quic_proxy_test_mock_error : quic_proxy_test_mock_errors) {
     std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
-        ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+        ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
             "QUIC bad:99; DIRECT", TRAFFIC_ANNOTATION_FOR_TESTS);
 
     HttpNetworkSessionParams session_params;
@@ -1621,10 +1621,10 @@
 TEST_F(HttpStreamFactoryTest, RequestSpdyHttpStreamHttpURL) {
   url::SchemeHostPort scheme_host_port("http", "myproxy.org", 443);
   auto session_deps = std::make_unique<SpdySessionDependencies>(
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS));
   std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
@@ -1691,10 +1691,10 @@
 
   url::SchemeHostPort scheme_host_port("http", "myproxy.org", 443);
   auto session_deps = std::make_unique<SpdySessionDependencies>(
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS));
   std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
diff --git a/net/proxy_resolution/configured_proxy_resolution_service.cc b/net/proxy_resolution/configured_proxy_resolution_service.cc
index 00521eb..e806bc5 100644
--- a/net/proxy_resolution/configured_proxy_resolution_service.cc
+++ b/net/proxy_resolution/configured_proxy_resolution_service.cc
@@ -858,7 +858,7 @@
 
 // static
 std::unique_ptr<ConfiguredProxyResolutionService>
-ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
     const std::string& pac_string,
     const NetworkTrafficAnnotationTag& traffic_annotation) {
   // We need the settings to contain an "automatic" setting, otherwise the
@@ -876,7 +876,7 @@
 
 // static
 std::unique_ptr<ConfiguredProxyResolutionService>
-ConfiguredProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
+ConfiguredProxyResolutionService::CreateFixedFromAutoDetectedPacResultForTest(
     const std::string& pac_string,
     const NetworkTrafficAnnotationTag& traffic_annotation) {
   auto proxy_config_service =
diff --git a/net/proxy_resolution/configured_proxy_resolution_service.h b/net/proxy_resolution/configured_proxy_resolution_service.h
index 7ce9e47..a2fa5a63 100644
--- a/net/proxy_resolution/configured_proxy_resolution_service.h
+++ b/net/proxy_resolution/configured_proxy_resolution_service.h
@@ -216,14 +216,14 @@
   // |pac_string| is a list of proxy servers, in the format that a PAC script
   // would return it. For example, "PROXY foobar:99; SOCKS fml:2; DIRECT"
   static std::unique_ptr<ConfiguredProxyResolutionService>
-  CreateFixedFromPacResult(
+  CreateFixedFromPacResultForTest(
       const std::string& pac_string,
       const NetworkTrafficAnnotationTag& traffic_annotation);
 
-  // Same as CreateFixedFromPacResult(), except the resulting ProxyInfo from
-  // resolutions will be tagged as having been auto-detected.
+  // Same as CreateFixedFromPacResultForTest(), except the resulting ProxyInfo
+  // from resolutions will be tagged as having been auto-detected.
   static std::unique_ptr<ConfiguredProxyResolutionService>
-  CreateFixedFromAutoDetectedPacResult(
+  CreateFixedFromAutoDetectedPacResultForTest(
       const std::string& pac_string,
       const NetworkTrafficAnnotationTag& traffic_annotation);
 
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index 70bf596..2be5e32 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -1668,7 +1668,7 @@
 TEST_P(QuicNetworkTransactionTest, QuicProxy) {
   session_params_.enable_quic = true;
   proxy_resolution_service_ =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC mail.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
@@ -1719,7 +1719,7 @@
 
   session_params_.enable_quic = true;
   proxy_resolution_service_ =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC " + proxy_host + ":70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   client_maker_->set_hostname(origin_host);
@@ -5054,7 +5054,7 @@
     return;
   }
   proxy_resolution_service_ =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   // Since we are using a proxy, the QUIC job will not succeed.
@@ -6123,7 +6123,7 @@
   const HostPortPair host_port_pair("myproxy.org", 443);
 
   proxy_resolution_service_ =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC myproxy.org:443; HTTPS myproxy.org:443",
           TRAFFIC_ANNOTATION_FOR_TESTS);
   proxy_resolution_service_->SetProxyDelegate(&test_proxy_delegate);
@@ -7705,7 +7705,7 @@
   session_params_.enable_quic = true;
   session_params_.enable_quic_proxies_for_https_urls = true;
   proxy_resolution_service_ =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
@@ -7798,7 +7798,7 @@
   session_params_.enable_quic = true;
   session_params_.enable_quic_proxies_for_https_urls = true;
   proxy_resolution_service_ =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
@@ -7892,7 +7892,7 @@
   session_params_.enable_quic = true;
   session_params_.enable_quic_proxies_for_https_urls = true;
   proxy_resolution_service_ =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
@@ -8019,7 +8019,7 @@
   session_params_.enable_quic = true;
   session_params_.enable_quic_proxies_for_https_urls = true;
   proxy_resolution_service_ =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
@@ -8179,7 +8179,7 @@
   session_params_.enable_quic = true;
   session_params_.enable_quic_proxies_for_https_urls = true;
   proxy_resolution_service_ =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
@@ -8230,7 +8230,7 @@
   session_params_.enable_quic = true;
   session_params_.enable_quic_proxies_for_https_urls = true;
   proxy_resolution_service_ =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
@@ -8271,7 +8271,7 @@
   session_params_.enable_quic = true;
   session_params_.enable_quic_proxies_for_https_urls = true;
   proxy_resolution_service_ =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
@@ -8406,7 +8406,7 @@
   session_params_.enable_quic = true;
   session_params_.enable_quic_proxies_for_https_urls = true;
   proxy_resolution_service_ =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
@@ -8458,7 +8458,7 @@
   session_params_.enable_quic = true;
   session_params_.enable_quic_proxies_for_https_urls = true;
   proxy_resolution_service_ =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   const RequestPriority request_priority = MEDIUM;
@@ -8503,7 +8503,7 @@
   session_params_.enable_quic = true;
   session_params_.enable_quic_proxies_for_https_urls = true;
   proxy_resolution_service_ =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   const RequestPriority kRequestPriority = MEDIUM;
@@ -8594,7 +8594,7 @@
     session_params_.enable_quic = true;
     session_params_.enable_quic_proxies_for_https_urls = true;
     proxy_resolution_service_ =
-        ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+        ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
             "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
     MockQuicData mock_quic_data(version_);
@@ -8965,7 +8965,7 @@
 
     if (use_proxy) {
       proxy_resolution_service_ =
-          ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+          ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
               "QUIC mail.example.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
     } else {
       proxy_resolution_service_ =
@@ -9256,7 +9256,7 @@
   session_params_.enable_quic = true;
   session_params_.enable_quic_proxies_for_https_urls = true;
   proxy_resolution_service_ =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   const char kGetRequest[] =
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
index 16c02af..74e0c38 100644
--- a/net/spdy/spdy_network_transaction_unittest.cc
+++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -3797,7 +3797,7 @@
   const char kPacString[] = "PROXY myproxy:443";
 
   auto session_deps = std::make_unique<SpdySessionDependencies>(
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           kPacString, TRAFFIC_ANNOTATION_FOR_TESTS));
   NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
                                      std::move(session_deps));
@@ -5704,7 +5704,7 @@
 TEST_F(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
   request_.method = "GET";
   auto session_deps = std::make_unique<SpdySessionDependencies>(
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
   // Do not force SPDY so that second socket can negotiate HTTP/1.1.
   NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
@@ -5814,7 +5814,7 @@
 
   request_.method = "GET";
   auto session_deps = std::make_unique<SpdySessionDependencies>(
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
   // Do not force SPDY so that second socket can negotiate HTTP/1.1.
   NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
@@ -5928,7 +5928,7 @@
 // Test to make sure we can correctly connect through a proxy.
 TEST_F(SpdyNetworkTransactionTest, ProxyConnect) {
   auto session_deps = std::make_unique<SpdySessionDependencies>(
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
   NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
                                      std::move(session_deps));
@@ -5987,7 +5987,7 @@
   // to simply DIRECT. The reason for appending the second proxy is to verify
   // that the session pool key used does is just "DIRECT".
   auto session_deps = std::make_unique<SpdySessionDependencies>(
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "DIRECT; PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
   // When setting up the first transaction, we store the SpdySessionPool so that
   // we can use the same pool in the second transaction.
@@ -6077,7 +6077,7 @@
   request_.method = "GET";
   request_.url = GURL(kPushedUrl);
   auto session_deps_proxy = std::make_unique<SpdySessionDependencies>(
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
   NormalSpdyTransactionHelper helper_proxy(request_, DEFAULT_PRIORITY, log_,
                                            std::move(session_deps_proxy));
@@ -8578,7 +8578,7 @@
 
   // Need secure proxy so that insecure URL can use HTTP/2.
   auto session_deps = std::make_unique<SpdySessionDependencies>(
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
   NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
                                      std::move(session_deps));
@@ -10754,7 +10754,7 @@
 // streams.
 TEST_F(SpdyNetworkTransactionTest, DoNotGreaseFrameTypeWithConnect) {
   auto session_deps = std::make_unique<SpdySessionDependencies>(
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
 
   const uint8_t type = 0x0b;
diff --git a/net/test/embedded_test_server/default_handlers.cc b/net/test/embedded_test_server/default_handlers.cc
index 31b5545..76150efe 100644
--- a/net/test/embedded_test_server/default_handlers.cc
+++ b/net/test/embedded_test_server/default_handlers.cc
@@ -793,6 +793,7 @@
   http_response->set_content(
       std::string(compressed_body.data(), compressed_size));
   http_response->AddCustomHeader("Content-Encoding", "gzip");
+  http_response->AddCustomHeader("Cache-Control", "max-age=60");
   return http_response;
 }
 
diff --git a/net/url_request/url_request_http_job_unittest.cc b/net/url_request/url_request_http_job_unittest.cc
index 6cfcbd5..9167632d 100644
--- a/net/url_request/url_request_http_job_unittest.cc
+++ b/net/url_request/url_request_http_job_unittest.cc
@@ -260,7 +260,7 @@
       ProxyUriToProxyServer("http://origin.net:80", ProxyServer::SCHEME_HTTP);
 
   std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           ProxyServerToPacResultElement(proxy_server),
           TRAFFIC_ANNOTATION_FOR_TESTS);
 
@@ -302,7 +302,7 @@
   // Connection to |proxy_server| would fail. Request should be fetched over
   // DIRECT.
   std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
-      ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
           ProxyServerToPacResultElement(proxy_server) + "; DIRECT",
           TRAFFIC_ANNOTATION_FOR_TESTS);
 
diff --git a/remoting/host/chromeos/BUILD.gn b/remoting/host/chromeos/BUILD.gn
index bcbda06..c2ea66d 100644
--- a/remoting/host/chromeos/BUILD.gn
+++ b/remoting/host/chromeos/BUILD.gn
@@ -41,7 +41,6 @@
     ":features",
     "//remoting/base:base",
     "//remoting/host:clipboard",
-    "//ui/aura/cursor",
     "//ui/base/cursor/mojom:cursor_type",
     "//ui/display/manager",
     "//ui/wm",
diff --git a/remoting/host/chromeos/mouse_cursor_monitor_aura.cc b/remoting/host/chromeos/mouse_cursor_monitor_aura.cc
index 998166d..70d4760 100644
--- a/remoting/host/chromeos/mouse_cursor_monitor_aura.cc
+++ b/remoting/host/chromeos/mouse_cursor_monitor_aura.cc
@@ -12,11 +12,11 @@
 #include "base/location.h"
 #include "remoting/host/chromeos/skia_bitmap_desktop_frame.h"
 #include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
-#include "ui/aura/cursor/cursor_lookup.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
+#include "ui/wm/core/cursor_lookup.h"
 
 namespace {
 
@@ -73,8 +73,8 @@
   }
 
   std::unique_ptr<SkBitmap> cursor_bitmap =
-      std::make_unique<SkBitmap>(aura::GetCursorBitmap(cursor));
-  gfx::Point cursor_hotspot = aura::GetCursorHotspot(cursor);
+      std::make_unique<SkBitmap>(wm::GetCursorBitmap(cursor));
+  gfx::Point cursor_hotspot = wm::GetCursorHotspot(cursor);
 
   if (cursor_bitmap->isNull()) {
     LOG(ERROR) << "Failed to load bitmap for cursor type:"
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc
index 0929d16..7dd783f2 100644
--- a/services/network/cors/cors_url_loader.cc
+++ b/services/network/cors/cors_url_loader.cc
@@ -856,8 +856,9 @@
   network_loader_start_time_ = base::TimeTicks::Now();
 
   // Check whether a fresh entry exists in the in-memory cache.
+  // TODO(https://crbug.com/1339708): In-memory cache should support DevTools.
   absl::optional<std::string> cache_key;
-  if (memory_cache_) {
+  if (memory_cache_ && !request_.devtools_request_id.has_value()) {
     cache_key = memory_cache_->CanServe(request_,
                                         isolation_info_.network_isolation_key(),
                                         cross_origin_embedder_policy_);
diff --git a/services/network/network_service_memory_cache.cc b/services/network/network_service_memory_cache.cc
index 7f4fe95..e43501bb 100644
--- a/services/network/network_service_memory_cache.cc
+++ b/services/network/network_service_memory_cache.cc
@@ -18,6 +18,7 @@
 #include "net/base/load_flags.h"
 #include "net/base/mime_sniffer.h"
 #include "net/base/network_isolation_key.h"
+#include "net/cert/cert_status_flags.h"
 #include "net/http/http_cache.h"
 #include "net/http/http_request_info.h"
 #include "net/http/http_response_headers.h"
@@ -221,10 +222,12 @@
 struct NetworkServiceMemoryCache::Entry {
   Entry(const net::HttpVaryData& vary_data,
         mojom::URLResponseHeadPtr response_head,
-        scoped_refptr<base::RefCountedBytes> content)
+        scoped_refptr<base::RefCountedBytes> content,
+        int64_t encoded_body_length)
       : vary_data(vary_data),
         response_head(std::move(response_head)),
-        content(std::move(content)) {}
+        content(std::move(content)),
+        encoded_body_length(encoded_body_length) {}
   ~Entry() = default;
 
   // Movable.
@@ -236,6 +239,7 @@
   net::HttpVaryData vary_data;
   mojom::URLResponseHeadPtr response_head;
   scoped_refptr<base::RefCountedBytes> content;
+  int64_t encoded_body_length;
 };
 
 NetworkServiceMemoryCache::NetworkServiceMemoryCache(
@@ -282,16 +286,30 @@
     return nullptr;
   }
 
-  // TODO(https://crbug.com/1339708): Make `this` work for responses from
-  // private network. Currently some tests are failing.
-  if (response->response_address_space == mojom::IPAddressSpace::kPrivate)
-    return nullptr;
-
   DCHECK(url_request->url().is_valid());
   if (!url_request->url().SchemeIsHTTPOrHTTPS())
     return nullptr;
 
-  if (url_request->method() != net::HttpRequestHeaders::kGetMethod)
+  const absl::optional<std::string> cache_key =
+      GenerateCacheKeyForURLRequest(*url_request, request_destination);
+  if (!cache_key.has_value())
+    return nullptr;
+
+  if (url_request->method() != net::HttpRequestHeaders::kGetMethod) {
+    // Invalidate the entry when the method is unsafe, as specified at
+    // https://fetch.spec.whatwg.org/#http-network-or-cache-fetch.
+    // This is a bit overkilling (for example, we don't see the response
+    // status), for the ease of implementation.
+    auto it = entries_.Peek(*cache_key);
+    if (it != entries_.end()) {
+      EraseEntry(it);
+    }
+    return nullptr;
+  }
+
+  // TODO(https://crbug.com/1339708): Make `this` work for responses from
+  // private network. Currently some tests are failing.
+  if (response->response_address_space == mojom::IPAddressSpace::kPrivate)
     return nullptr;
 
   if (!response->headers || response->headers->response_code() != net::HTTP_OK)
@@ -303,6 +321,10 @@
     return nullptr;
   }
 
+  // See comments in net::HttpCache::Transaction::WriteResponseInfoToEntry().
+  if (net::IsCertStatusError(url_request->ssl_info().cert_status))
+    return nullptr;
+
   if (!CheckSpecialRequestHeaders(url_request->extra_request_headers()))
     return nullptr;
 
@@ -314,11 +336,6 @@
   if (validation_type != net::VALIDATION_NONE)
     return nullptr;
 
-  absl::optional<std::string> cache_key =
-      GenerateCacheKeyForURLRequest(*url_request, request_destination);
-  if (!cache_key.has_value())
-    return nullptr;
-
   return std::make_unique<NetworkServiceMemoryCacheWriter>(
       weak_ptr_factory_.GetWeakPtr(), GetNextTraceId(), max_per_entry_bytes_,
       std::move(*cache_key), url_request, request_destination, response);
@@ -376,8 +393,9 @@
 
   scoped_refptr<base::RefCountedBytes> content =
       base::RefCountedBytes::TakeVector(&data);
-  auto entry = std::make_unique<Entry>(vary_data, std::move(response_head),
-                                       std::move(content));
+  auto entry =
+      std::make_unique<Entry>(vary_data, std::move(response_head),
+                              std::move(content), status.encoded_body_length);
   entries_.Put(cache_key, std::move(entry));
 
   ShrinkToTotalBytes();
@@ -469,7 +487,8 @@
 
   auto loader = std::make_unique<NetworkServiceMemoryCacheURLLoader>(
       this, GetNextTraceId(), resource_request.url, net_log,
-      std::move(receiver), std::move(client), it->second->content);
+      std::move(receiver), std::move(client), it->second->content,
+      it->second->encoded_body_length);
   NetworkServiceMemoryCacheURLLoader* raw_loader = loader.get();
   url_loaders_.insert(std::move(loader));
 
diff --git a/services/network/network_service_memory_cache_unittest.cc b/services/network/network_service_memory_cache_unittest.cc
index ef7dfe0..7215c09 100644
--- a/services/network/network_service_memory_cache_unittest.cc
+++ b/services/network/network_service_memory_cache_unittest.cc
@@ -747,6 +747,16 @@
   ASSERT_FALSE(CanServeFromMemoryCache(request));
 }
 
+TEST_F(NetworkServiceMemoryCacheTest, CanServe_DevToolsAttached) {
+  ResourceRequest request = CreateRequest("/cacheable");
+  request.devtools_request_id = "fake-id";
+  StoreResponseToMemoryCache(request);
+
+  // TODO(https://crbug.com/1339708): Change the the expectation when the
+  // in-memory supports DevTools.
+  ASSERT_FALSE(CanServeFromMemoryCache(request));
+}
+
 TEST_F(NetworkServiceMemoryCacheTest, UpdateStoredCache) {
   ResourceRequest request = CreateRequest("/cacheable");
 
@@ -1029,4 +1039,35 @@
   ASSERT_EQ(pair.client->completion_status().error_code, net::ERR_FAILED);
 }
 
+TEST_F(NetworkServiceMemoryCacheTest, ServeFromCache_GzipResponse) {
+  constexpr int64_t kBodySize = 100;
+  const std::string kContent(kBodySize, 'x');
+  ResourceRequest request =
+      CreateRequest(base::StringPrintf("/gzip-body?%s", kContent.c_str()));
+  StoreResponseToMemoryCache(request);
+  ASSERT_TRUE(CanServeFromMemoryCache(request));
+
+  LoaderPair pair = CreateLoaderAndStart(request);
+  pair.client->RunUntilComplete();
+  const URLLoaderCompletionStatus& status = pair.client->completion_status();
+  ASSERT_EQ(status.error_code, net::OK);
+  ASSERT_EQ(status.decoded_body_length, kBodySize);
+  ASSERT_LT(status.encoded_body_length, kBodySize);
+}
+
+TEST_F(NetworkServiceMemoryCacheTest, InvalidateOnNonSafeMethod) {
+  ResourceRequest request = CreateRequest("/cacheable");
+  StoreResponseToMemoryCache(request);
+
+  ASSERT_TRUE(CanServeFromMemoryCache(request));
+
+  ResourceRequest request2 = CreateRequest("/cacheable");
+  request2.method = "PUT";
+
+  LoaderPair pair = CreateLoaderAndStart(request2);
+  pair.client->RunUntilResponseReceived();
+
+  ASSERT_FALSE(CanServeFromMemoryCache(request));
+}
+
 }  // namespace network
diff --git a/services/network/network_service_memory_cache_url_loader.cc b/services/network/network_service_memory_cache_url_loader.cc
index 9197213..f2106204 100644
--- a/services/network/network_service_memory_cache_url_loader.cc
+++ b/services/network/network_service_memory_cache_url_loader.cc
@@ -20,13 +20,15 @@
     const net::NetLogWithSource& net_log,
     mojo::PendingReceiver<mojom::URLLoader> receiver,
     mojo::PendingRemote<mojom::URLLoaderClient> client,
-    scoped_refptr<base::RefCountedBytes> content)
+    scoped_refptr<base::RefCountedBytes> content,
+    int64_t encoded_body_length)
     : memory_cache_(memory_cache),
       trace_id_(trace_id),
       net_log_(net_log),
       receiver_(this, std::move(receiver)),
       client_(std::move(client)),
-      content_(std::move(content)) {
+      content_(std::move(content)),
+      encoded_body_length_(encoded_body_length) {
   DCHECK(memory_cache_);
   TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
       "loading", "NetworkServiceMemoryCacheURLLoader",
@@ -189,7 +191,7 @@
     status.exists_in_cache = true;
     status.exists_in_memory_cache = true;
     status.completion_time = base::TimeTicks::Now();
-    status.encoded_body_length = content_->size();
+    status.encoded_body_length = encoded_body_length_;
     status.decoded_body_length = content_->size();
 
     client_->OnComplete(status);
diff --git a/services/network/network_service_memory_cache_url_loader.h b/services/network/network_service_memory_cache_url_loader.h
index 45befc06..422ef8bc 100644
--- a/services/network/network_service_memory_cache_url_loader.h
+++ b/services/network/network_service_memory_cache_url_loader.h
@@ -40,7 +40,8 @@
       const net::NetLogWithSource& net_log,
       mojo::PendingReceiver<mojom::URLLoader> receiver,
       mojo::PendingRemote<mojom::URLLoaderClient> client,
-      scoped_refptr<base::RefCountedBytes> content);
+      scoped_refptr<base::RefCountedBytes> content,
+      int64_t encoded_body_length);
 
   ~NetworkServiceMemoryCacheURLLoader() override;
 
@@ -91,6 +92,7 @@
 
   // The response body to be served.
   scoped_refptr<base::RefCountedBytes> content_;
+  const int64_t encoded_body_length_;
 
   mojo::ScopedDataPipeProducerHandle producer_handle_;
   std::unique_ptr<mojo::SimpleWatcher> producer_handle_watcher_;
diff --git a/services/network/proxy_resolving_client_socket_unittest.cc b/services/network/proxy_resolving_client_socket_unittest.cc
index 73faab5..ea2531d 100644
--- a/services/network/proxy_resolving_client_socket_unittest.cc
+++ b/services/network/proxy_resolving_client_socket_unittest.cc
@@ -44,7 +44,7 @@
 
 std::unique_ptr<net::ConfiguredProxyResolutionService>
 CreateProxyResolutionService(base::StringPiece pac_result) {
-  return net::ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+  return net::ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
       static_cast<std::string>(pac_result), TRAFFIC_ANNOTATION_FOR_TESTS);
 }
 
diff --git a/services/network/proxy_resolving_socket_mojo_unittest.cc b/services/network/proxy_resolving_socket_mojo_unittest.cc
index 3e80792..5cb0e66 100644
--- a/services/network/proxy_resolving_socket_mojo_unittest.cc
+++ b/services/network/proxy_resolving_socket_mojo_unittest.cc
@@ -61,7 +61,7 @@
     mock_client_socket_factory_->set_enable_read_if_ready(true);
     auto context_builder = net::CreateTestURLRequestContextBuilder();
     context_builder->set_proxy_resolution_service(
-        net::ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+        net::ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
             pac_result, TRAFFIC_ANNOTATION_FOR_TESTS));
     context_builder->set_client_socket_factory_for_testing(
         mock_client_socket_factory_.get());
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index 6805b5f..dc11c70 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -1554,7 +1554,8 @@
     return;
   }
 
-  if (memory_cache_) {
+  // TODO(https://crbug.com/1339708): In-memory cache should support DevTools.
+  if (memory_cache_ && !devtools_request_id().has_value()) {
     memory_cache_writer_ = memory_cache_->MaybeCreateWriter(
         url_request_.get(), request_destination_, response_);
   }
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 39ccc6c..ef06443d 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -8267,15 +8267,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8352,15 +8352,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8777,15 +8777,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8862,15 +8862,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 34c0e84..68be087 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -46513,15 +46513,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -46598,15 +46598,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47023,15 +47023,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47108,15 +47108,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47537,15 +47537,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47622,15 +47622,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48047,15 +48047,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48132,15 +48132,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48629,15 +48629,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48714,15 +48714,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49139,15 +49139,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49224,15 +49224,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49721,15 +49721,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49806,15 +49806,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -50231,15 +50231,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -50316,15 +50316,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 8054c0fa..975f826 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5756,21 +5756,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 105.0.5190.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "dimension_sets": [
@@ -5783,7 +5783,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       },
       {
         "isolate_profile_data": true,
@@ -5921,21 +5921,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 105.0.5190.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "dimension_sets": [
@@ -5947,7 +5947,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       },
       {
         "args": [
@@ -6067,21 +6067,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 105.0.5190.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "dimension_sets": [
@@ -6093,7 +6093,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       },
       {
         "isolate_profile_data": true,
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 5e34090d..76088a4 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -94465,21 +94465,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 105.0.5190.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -94487,7 +94487,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       },
       {
         "isolate_profile_data": true,
@@ -94600,28 +94600,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 105.0.5190.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       },
       {
         "args": [
@@ -94721,28 +94721,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 105.0.5190.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       },
       {
         "isolate_profile_data": true,
@@ -96080,20 +96080,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 105.0.5190.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "dimension_sets": [
@@ -96107,7 +96107,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       },
       {
         "merge": {
@@ -96245,20 +96245,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 105.0.5190.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "dimension_sets": [
@@ -96271,7 +96271,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       },
       {
         "args": [
@@ -96391,20 +96391,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 105.0.5190.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "dimension_sets": [
@@ -96417,7 +96417,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       },
       {
         "merge": {
@@ -97913,20 +97913,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 105.0.5190.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "dimension_sets": [
@@ -97940,7 +97940,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       },
       {
         "merge": {
@@ -98078,20 +98078,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 105.0.5190.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "dimension_sets": [
@@ -98104,7 +98104,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       },
       {
         "args": [
@@ -98224,20 +98224,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 105.0.5190.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "dimension_sets": [
@@ -98250,7 +98250,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       },
       {
         "merge": {
@@ -98985,20 +98985,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 105.0.5190.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "dimension_sets": [
@@ -99011,7 +99011,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       }
     ]
   },
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 8de09f6b..ed10d43 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -20875,21 +20875,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 105.0.5190.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "dimension_sets": [
@@ -20902,7 +20902,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       },
       {
         "isolate_profile_data": true,
@@ -21040,21 +21040,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 105.0.5190.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "dimension_sets": [
@@ -21066,7 +21066,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       },
       {
         "args": [
@@ -21186,21 +21186,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 105.0.5190.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 105.0.5191.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v105.0.5190.0",
-              "revision": "version:105.0.5190.0"
+              "location": "lacros_version_skew_tests_v105.0.5191.0",
+              "revision": "version:105.0.5191.0"
             }
           ],
           "dimension_sets": [
@@ -21212,7 +21212,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 105.0.5190.0"
+        "variant_id": "Lacros version skew testing ash 105.0.5191.0"
       },
       {
         "isolate_profile_data": true,
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 707656a..7a6a06ee1 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -22,15 +22,15 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5190.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v105.0.5191.0/test_ash_chrome',
     ],
-    'identifier': 'Lacros version skew testing ash 105.0.5190.0',
+    'identifier': 'Lacros version skew testing ash 105.0.5191.0',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v105.0.5190.0',
-          'revision': 'version:105.0.5190.0',
+          'location': 'lacros_version_skew_tests_v105.0.5191.0',
+          'revision': 'version:105.0.5191.0',
         },
       ],
     },
@@ -529,16 +529,16 @@
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
-      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--implementation-outdir',
-      '../../weblayer_instrumentation_test_M104/out/Release',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--impl-version=104',
+      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
+      '--implementation-outdir',
+      '../../weblayer_instrumentation_test_M104/out/Release',
+      '--impl-version=104'
     ],
     'identifier': 'with_impl_from_104',
     'swarming': {
@@ -546,23 +546,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.57',
+          'revision': 'version:104.0.5112.57'
         }
-      ],
-    },
+      ]
+    }
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
-      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--implementation-outdir',
-      '../../weblayer_instrumentation_test_M103/out/Release',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--impl-version=103',
+      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
+      '--implementation-outdir',
+      '../../weblayer_instrumentation_test_M103/out/Release',
+      '--impl-version=103'
     ],
     'identifier': 'with_impl_from_103',
     'swarming': {
@@ -570,10 +570,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.139',
+          'revision': 'version:103.0.5060.139'
         }
-      ],
-    },
+      ]
+    }
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -673,16 +673,16 @@
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--implementation-outdir',
-      '../../weblayer_instrumentation_test_M104/out/Release',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--impl-version=104',
+      '--webview-apk-path=apks/SystemWebView.apk',
+      '--implementation-outdir',
+      '../../weblayer_instrumentation_test_M104/out/Release',
+      '--impl-version=104'
     ],
     'identifier': 'with_impl_from_104',
     'swarming': {
@@ -690,23 +690,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.57',
+          'revision': 'version:104.0.5112.57'
         }
-      ],
-    },
+      ]
+    }
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--implementation-outdir',
-      '../../weblayer_instrumentation_test_M103/out/Release',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--impl-version=103',
+      '--webview-apk-path=apks/SystemWebView.apk',
+      '--implementation-outdir',
+      '../../weblayer_instrumentation_test_M103/out/Release',
+      '--impl-version=103'
     ],
     'identifier': 'with_impl_from_103',
     'swarming': {
@@ -714,10 +714,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.139',
+          'revision': 'version:103.0.5060.139'
         }
-      ],
-    },
+      ]
+    }
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -817,16 +817,16 @@
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
-      '--client-outdir',
-      '../../weblayer_instrumentation_test_M104/out/Release',
       '--implementation-outdir',
       '.',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--client-version=104',
+      '--webview-apk-path=apks/SystemWebView.apk',
+      '--client-outdir',
+      '../../weblayer_instrumentation_test_M104/out/Release',
+      '--client-version=104'
     ],
     'identifier': 'with_client_from_104',
     'swarming': {
@@ -834,23 +834,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.57',
+          'revision': 'version:104.0.5112.57'
         }
-      ],
-    },
+      ]
+    }
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
-      '--client-outdir',
-      '../../weblayer_instrumentation_test_M103/out/Release',
       '--implementation-outdir',
       '.',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--client-version=103',
+      '--webview-apk-path=apks/SystemWebView.apk',
+      '--client-outdir',
+      '../../weblayer_instrumentation_test_M103/out/Release',
+      '--client-version=103'
     ],
     'identifier': 'with_client_from_103',
     'swarming': {
@@ -858,10 +858,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.139',
+          'revision': 'version:103.0.5060.139'
         }
-      ],
-    },
+      ]
+    }
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 0a67e0b..2e72d5eb 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -5104,6 +5104,7 @@
                         "Gen": "8",
                         "ReidBlocks": "18009598079355128088,9223784233214641190;10735872651981970214",
                         "ReidBlocksBits": "1,4",
+                        "ReidBlocksNoiseProbabilities": "0.01,0.01",
                         "ReidBlocksSaltsRanges": "1000,1000000"
                     },
                     "enable_features": [
diff --git a/third_party/abseil-cpp/README.chromium b/third_party/abseil-cpp/README.chromium
index b34551a..d220bdc2 100644
--- a/third_party/abseil-cpp/README.chromium
+++ b/third_party/abseil-cpp/README.chromium
@@ -4,7 +4,7 @@
 License: Apache 2.0
 License File: LICENSE
 Version: 0
-Revision: e517aaf499f88383000d4ddf6b84417fbbb48791
+Revision: 0c8bd82e90bac01f8afc6afdd5754d9d9b16cf68
 Security Critical: yes
 
 Description:
diff --git a/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc b/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc
index affade3..8e75e54 100644
--- a/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc
+++ b/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc
@@ -50,7 +50,9 @@
 #ifndef _WIN32
 #define ABSL_HAVE_SIGACTION
 // Apple WatchOS and TVOS don't allow sigaltstack
-#if !(defined(TARGET_OS_WATCH) && TARGET_OS_WATCH) && \
+// Apple macOS has sigaltstack, but using it makes backtrace() unusable.
+#if !(defined(TARGET_OS_OSX) && TARGET_OS_OSX) &&     \
+    !(defined(TARGET_OS_WATCH) && TARGET_OS_WATCH) && \
     !(defined(TARGET_OS_TV) && TARGET_OS_TV) && !defined(__QNX__)
 #define ABSL_HAVE_SIGALTSTACK
 #endif
diff --git a/third_party/abseil-cpp/absl/debugging/internal/demangle.cc b/third_party/abseil-cpp/absl/debugging/internal/demangle.cc
index 93ae3279..9ac644e 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/demangle.cc
+++ b/third_party/abseil-cpp/absl/debugging/internal/demangle.cc
@@ -548,6 +548,7 @@
 static bool ParseCallOffset(State *state);
 static bool ParseNVOffset(State *state);
 static bool ParseVOffset(State *state);
+static bool ParseAbiTags(State *state);
 static bool ParseCtorDtorName(State *state);
 static bool ParseDecltype(State *state);
 static bool ParseType(State *state);
@@ -601,7 +602,7 @@
 //
 // Reference:
 // - Itanium C++ ABI
-//   <https://mentorembedded.github.io/cxx-abi/abi.html#mangling>
+//   <https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling>
 
 // <mangled-name> ::= _Z <encoding>
 static bool ParseMangledName(State *state) {
@@ -741,17 +742,42 @@
   return true;
 }
 
-// <unqualified-name> ::= <operator-name>
-//                    ::= <ctor-dtor-name>
-//                    ::= <source-name>
-//                    ::= <local-source-name> // GCC extension; see below.
-//                    ::= <unnamed-type-name>
+// <unqualified-name> ::= <operator-name> [<abi-tags>]
+//                    ::= <ctor-dtor-name> [<abi-tags>]
+//                    ::= <source-name> [<abi-tags>]
+//                    ::= <local-source-name> [<abi-tags>]
+//                    ::= <unnamed-type-name> [<abi-tags>]
+//
+// <local-source-name> is a GCC extension; see below.
 static bool ParseUnqualifiedName(State *state) {
   ComplexityGuard guard(state);
   if (guard.IsTooComplex()) return false;
-  return (ParseOperatorName(state, nullptr) || ParseCtorDtorName(state) ||
-          ParseSourceName(state) || ParseLocalSourceName(state) ||
-          ParseUnnamedTypeName(state));
+  if (ParseOperatorName(state, nullptr) || ParseCtorDtorName(state) ||
+      ParseSourceName(state) || ParseLocalSourceName(state) ||
+      ParseUnnamedTypeName(state)) {
+    return ParseAbiTags(state);
+  }
+  return false;
+}
+
+// <abi-tags> ::= <abi-tag> [<abi-tags>]
+// <abi-tag>  ::= B <source-name>
+static bool ParseAbiTags(State *state) {
+  ComplexityGuard guard(state);
+  if (guard.IsTooComplex()) return false;
+
+  while (ParseOneCharToken(state, 'B')) {
+    ParseState copy = state->parse_state;
+    MaybeAppend(state, "[abi:");
+
+    if (!ParseSourceName(state)) {
+      state->parse_state = copy;
+      return false;
+    }
+    MaybeAppend(state, "]");
+  }
+
+  return true;
 }
 
 // <source-name> ::= <positive length number> <identifier>
diff --git a/third_party/abseil-cpp/absl/debugging/internal/demangle_test.cc b/third_party/abseil-cpp/absl/debugging/internal/demangle_test.cc
index 6b14290..8463a2b 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/demangle_test.cc
+++ b/third_party/abseil-cpp/absl/debugging/internal/demangle_test.cc
@@ -102,6 +102,30 @@
   EXPECT_FALSE(Demangle("_ZL3Foov.isra.2.constprop.", tmp, sizeof(tmp)));
 }
 
+// Test the GNU abi_tag extension.
+TEST(Demangle, AbiTags) {
+  char tmp[80];
+
+  // Mangled name generated via:
+  // struct [[gnu::abi_tag("abc")]] A{};
+  // A a;
+  EXPECT_TRUE(Demangle("_Z1aB3abc", tmp, sizeof(tmp)));
+  EXPECT_STREQ("a[abi:abc]", tmp);
+
+  // Mangled name generated via:
+  // struct B {
+  //   B [[gnu::abi_tag("xyz")]] (){};
+  // };
+  // B b;
+  EXPECT_TRUE(Demangle("_ZN1BC2B3xyzEv", tmp, sizeof(tmp)));
+  EXPECT_STREQ("B::B[abi:xyz]()", tmp);
+
+  // Mangled name generated via:
+  // [[gnu::abi_tag("foo", "bar")]] void C() {}
+  EXPECT_TRUE(Demangle("_Z1CB3barB3foov", tmp, sizeof(tmp)));
+  EXPECT_STREQ("C[abi:bar][abi:foo]()", tmp);
+}
+
 // Tests that verify that Demangle footprint is within some limit.
 // They are not to be run under sanitizers as the sanitizers increase
 // stack consumption by about 4x.
diff --git a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc
index 7123b71..70b11e5 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc
+++ b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc
@@ -96,7 +96,8 @@
 template <bool STRICT_UNWINDING, bool WITH_CONTEXT>
 ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.
 ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.
-static void ** NextStackFrame(void **old_frame_pointer, const void *uc) {
+static void ** NextStackFrame(void **old_frame_pointer, const void *uc,
+                              const std::pair<size_t, size_t> range) {
   //               .
   //               .
   //               .
@@ -159,7 +160,11 @@
     const uintptr_t max_size = STRICT_UNWINDING ? 100000 : 1000000;
     const uintptr_t frame_size =
         ComputeStackFrameSize(old_frame_pointer, new_frame_pointer);
-    if (frame_size == kUnknownFrameSize || frame_size > max_size)
+    if (frame_size == kUnknownFrameSize &&
+        (reinterpret_cast<uintptr_t>(new_frame_pointer) < range.first ||
+         reinterpret_cast<uintptr_t>(new_frame_pointer) > range.second))
+      return nullptr;
+    if (frame_size > max_size)
       return nullptr;
   }
 
@@ -180,6 +185,12 @@
 #error reading stack pointer not yet supported on this platform
 #endif
 
+  std::pair<size_t, size_t> stack = {
+      // assume that the first page is not the stack.
+      static_cast<size_t>(sysconf(_SC_PAGESIZE)),
+      std::numeric_limits<size_t>::max() - sizeof(void *)
+  };
+
   int n = 0;
   void *return_address = nullptr;
   while (frame_pointer && n < max_depth) {
@@ -190,7 +201,8 @@
     // non-strict unwinding rules to produce a stack trace that is as complete
     // as possible (even if it contains a few bogus entries in some rare cases).
     void **next_frame_pointer =
-        NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp);
+        NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp,
+                                                          stack);
 
     if (skip_count > 0) {
       skip_count--;
@@ -217,7 +229,8 @@
         num_dropped_frames++;
       }
       frame_pointer =
-          NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp);
+          NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp,
+                                                            stack);
     }
     *min_dropped_frames = num_dropped_frames;
   }
diff --git a/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc b/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc
index 9bfdd91..fa401ae 100644
--- a/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc
+++ b/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc
@@ -442,8 +442,8 @@
                               const off_t offset) {
   off_t off = lseek(fd, offset, SEEK_SET);
   if (off == (off_t)-1) {
-    ABSL_RAW_LOG(WARNING, "lseek(%d, %ju, SEEK_SET) failed: errno=%d", fd,
-                 static_cast<uintmax_t>(offset), errno);
+    ABSL_RAW_LOG(WARNING, "lseek(%d, %jd, SEEK_SET) failed: errno=%d", fd,
+                 static_cast<intmax_t>(offset), errno);
     return -1;
   }
   return ReadPersistent(fd, buf, count);
@@ -489,12 +489,19 @@
         (buf_bytes > num_bytes_left) ? num_bytes_left : buf_bytes;
     const off_t offset = sh_offset + i * sizeof(buf[0]);
     const ssize_t len = ReadFromOffset(fd, buf, num_bytes_to_read, offset);
+    if (len < 0) {
+      ABSL_RAW_LOG(
+          WARNING,
+          "Reading %zd bytes from offset %ju returned %zd which is negative.",
+          num_bytes_to_read, static_cast<intmax_t>(offset), len);
+      return false;
+    }
     if (len % sizeof(buf[0]) != 0) {
       ABSL_RAW_LOG(
           WARNING,
-          "Reading %zd bytes from offset %ju returned %zd which is not a "
+          "Reading %zd bytes from offset %jd returned %zd which is not a "
           "multiple of %zu.",
-          num_bytes_to_read, static_cast<uintmax_t>(offset), len,
+          num_bytes_to_read, static_cast<intmax_t>(offset), len,
           sizeof(buf[0]));
       return false;
     }
@@ -693,6 +700,7 @@
     const int entries_in_chunk = std::min(num_remaining_symbols, buf_entries);
     const int bytes_in_chunk = entries_in_chunk * sizeof(buf[0]);
     const ssize_t len = ReadFromOffset(fd, buf, bytes_in_chunk, offset);
+    SAFE_ASSERT(len >= 0);
     SAFE_ASSERT(len % sizeof(buf[0]) == 0);
     const ssize_t num_symbols_in_buf = len / sizeof(buf[0]);
     SAFE_ASSERT(num_symbols_in_buf <= entries_in_chunk);
diff --git a/third_party/abseil-cpp/absl/functional/any_invocable_test.cc b/third_party/abseil-cpp/absl/functional/any_invocable_test.cc
index fb5e7792..dabaae9 100644
--- a/third_party/abseil-cpp/absl/functional/any_invocable_test.cc
+++ b/third_party/abseil-cpp/absl/functional/any_invocable_test.cc
@@ -1246,12 +1246,9 @@
 #else
   using AnyInvType = typename TypeParam::AnyInvType;
 
-// TODO(b/217761454): Fix this and re-enable for MSVC.
-#ifndef _MSC_VER
   EXPECT_FALSE((std::is_constructible<
                 AnyInvType,
                 typename TypeParam::AnyInvocableFunTypeNotNoexcept*>::value));
-#endif
   EXPECT_FALSE((
       std::is_constructible<AnyInvType,
                             typename TypeParam::IncompatibleInvocable>::value));
@@ -1264,12 +1261,9 @@
 #else
   using AnyInvType = typename TypeParam::AnyInvType;
 
-// TODO(b/217761454): Fix this and re-enable for MSVC.
-#ifndef _MSC_VER
   EXPECT_FALSE((std::is_assignable<
                 AnyInvType&,
                 typename TypeParam::AnyInvocableFunTypeNotNoexcept*>::value));
-#endif
   EXPECT_FALSE(
       (std::is_assignable<AnyInvType&,
                           typename TypeParam::IncompatibleInvocable>::value));
diff --git a/third_party/abseil-cpp/absl/hash/internal/low_level_hash.cc b/third_party/abseil-cpp/absl/hash/internal/low_level_hash.cc
index 6f9cb9c..d288f3ec 100644
--- a/third_party/abseil-cpp/absl/hash/internal/low_level_hash.cc
+++ b/third_party/abseil-cpp/absl/hash/internal/low_level_hash.cc
@@ -40,7 +40,7 @@
 }
 
 uint64_t LowLevelHash(const void* data, size_t len, uint64_t seed,
-                      const uint64_t salt[]) {
+                      const uint64_t salt[5]) {
   const uint8_t* ptr = static_cast<const uint8_t*>(data);
   uint64_t starting_length = static_cast<uint64_t>(len);
   uint64_t current_state = seed ^ salt[0];
diff --git a/third_party/abseil-cpp/absl/strings/cord.cc b/third_party/abseil-cpp/absl/strings/cord.cc
index 85a67a08..b34c03a 100644
--- a/third_party/abseil-cpp/absl/strings/cord.cc
+++ b/third_party/abseil-cpp/absl/strings/cord.cc
@@ -537,18 +537,23 @@
   }
 }
 
-static CordBuffer CreateAppendBuffer(InlineData& data, size_t capacity) {
+static CordBuffer CreateAppendBuffer(InlineData& data, size_t block_size,
+                                     size_t capacity) {
   // Watch out for overflow, people can ask for size_t::max().
   const size_t size = data.inline_size();
-  capacity = (std::min)(std::numeric_limits<size_t>::max() - size, capacity);
-  CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(size + capacity);
+  const size_t max_capacity = std::numeric_limits<size_t>::max() - size;
+  capacity = (std::min)(max_capacity, capacity) + size;
+  CordBuffer buffer =
+      block_size ? CordBuffer::CreateWithCustomLimit(block_size, capacity)
+                 : CordBuffer::CreateWithDefaultLimit(capacity);
   cord_internal::SmallMemmove(buffer.data(), data.as_chars(), size);
   buffer.SetLength(size);
   data = {};
   return buffer;
 }
 
-CordBuffer Cord::GetAppendBufferSlowPath(size_t capacity, size_t min_capacity) {
+CordBuffer Cord::GetAppendBufferSlowPath(size_t block_size, size_t capacity,
+                                         size_t min_capacity) {
   auto constexpr method = CordzUpdateTracker::kGetAppendBuffer;
   CordRep* tree = contents_.tree();
   if (tree != nullptr) {
@@ -558,9 +563,10 @@
       contents_.SetTreeOrEmpty(result.tree, scope);
       return CordBuffer(result.extracted->flat());
     }
-    return CordBuffer::CreateWithDefaultLimit(capacity);
+    return block_size ? CordBuffer::CreateWithCustomLimit(block_size, capacity)
+                      : CordBuffer::CreateWithDefaultLimit(capacity);
   }
-  return CreateAppendBuffer(contents_.data_, capacity);
+  return CreateAppendBuffer(contents_.data_, block_size, capacity);
 }
 
 void Cord::Append(const Cord& src) {
diff --git a/third_party/abseil-cpp/absl/strings/cord.h b/third_party/abseil-cpp/absl/strings/cord.h
index 18d6ab852..0332671 100644
--- a/third_party/abseil-cpp/absl/strings/cord.h
+++ b/third_party/abseil-cpp/absl/strings/cord.h
@@ -284,6 +284,19 @@
   //   }
   CordBuffer GetAppendBuffer(size_t capacity, size_t min_capacity = 16);
 
+  // Returns a CordBuffer, re-using potential existing capacity in this cord.
+  //
+  // This function is identical to `GetAppendBuffer`, except that in the case
+  // where a new `CordBuffer` is allocated, it is allocated using the provided
+  // custom limit instead of the default limit. `GetAppendBuffer` will default
+  // to `CordBuffer::CreateWithDefaultLimit(capacity)` whereas this method
+  // will default to `CordBuffer::CreateWithCustomLimit(block_size, capacity)`.
+  // This method is equivalent to `GetAppendBuffer` if `block_size` is zero.
+  // See the documentation for `CreateWithCustomLimit` for more details on the
+  // restrictions and legal values for `block_size`.
+  CordBuffer GetCustomAppendBuffer(size_t block_size, size_t capacity,
+                                   size_t min_capacity = 16);
+
   // Cord::Prepend()
   //
   // Prepends data to the Cord, which may come from another Cord or other string
@@ -861,9 +874,6 @@
     void PrependTreeToTree(CordRep* tree, MethodIdentifier method);
     void PrependTree(CordRep* tree, MethodIdentifier method);
 
-    template <bool has_length>
-    void GetAppendRegion(char** region, size_t* size, size_t length);
-
     bool IsSame(const InlineRep& other) const {
       return memcmp(&data_, &other.data_, sizeof(data_)) == 0;
     }
@@ -980,7 +990,8 @@
   void AppendPrecise(absl::string_view src, MethodIdentifier method);
   void PrependPrecise(absl::string_view src, MethodIdentifier method);
 
-  CordBuffer GetAppendBufferSlowPath(size_t capacity, size_t min_capacity);
+  CordBuffer GetAppendBufferSlowPath(size_t block_size, size_t capacity,
+                                     size_t min_capacity);
 
   // Prepends the provided data to this instance. `method` contains the public
   // API method for this action which is tracked for Cordz sampling purposes.
@@ -1360,7 +1371,17 @@
 
 inline CordBuffer Cord::GetAppendBuffer(size_t capacity, size_t min_capacity) {
   if (empty()) return CordBuffer::CreateWithDefaultLimit(capacity);
-  return GetAppendBufferSlowPath(capacity, min_capacity);
+  return GetAppendBufferSlowPath(0, capacity, min_capacity);
+}
+
+inline CordBuffer Cord::GetCustomAppendBuffer(size_t block_size,
+                                              size_t capacity,
+                                              size_t min_capacity) {
+  if (empty()) {
+    return block_size ? CordBuffer::CreateWithCustomLimit(block_size, capacity)
+                      : CordBuffer::CreateWithDefaultLimit(capacity);
+  }
+  return GetAppendBufferSlowPath(block_size, capacity, min_capacity);
 }
 
 extern template void Cord::Append(std::string&& src);
diff --git a/third_party/abseil-cpp/absl/strings/cord_test.cc b/third_party/abseil-cpp/absl/strings/cord_test.cc
index 0862f69..d28ba113 100644
--- a/third_party/abseil-cpp/absl/strings/cord_test.cc
+++ b/third_party/abseil-cpp/absl/strings/cord_test.cc
@@ -733,18 +733,48 @@
   EXPECT_THAT(cord.Chunks(), ::testing::ElementsAre(s2, s1));
 }
 
-TEST_P(CordTest, GetAppendBufferOnEmptyCord) {
+class CordAppendBufferTest : public testing::TestWithParam<bool> {
+ public:
+  size_t is_default() const { return GetParam(); }
+
+  // Returns human readable string representation of the test parameter.
+  static std::string ToString(testing::TestParamInfo<bool> param) {
+    return param.param ? "DefaultLimit" : "CustomLimit";
+  }
+
+  size_t limit() const {
+    return is_default() ? absl::CordBuffer::kDefaultLimit
+                        : absl::CordBuffer::kCustomLimit;
+  }
+
+  size_t maximum_payload() const {
+    return is_default() ? absl::CordBuffer::MaximumPayload()
+                        : absl::CordBuffer::MaximumPayload(limit());
+  }
+
+  absl::CordBuffer GetAppendBuffer(absl::Cord& cord, size_t capacity,
+                                   size_t min_capacity = 16) {
+    return is_default()
+               ? cord.GetAppendBuffer(capacity, min_capacity)
+               : cord.GetCustomAppendBuffer(limit(), capacity, min_capacity);
+  }
+};
+
+INSTANTIATE_TEST_SUITE_P(WithParam, CordAppendBufferTest, testing::Bool(),
+                         CordAppendBufferTest::ToString);
+
+TEST_P(CordAppendBufferTest, GetAppendBufferOnEmptyCord) {
   absl::Cord cord;
-  absl::CordBuffer buffer = cord.GetAppendBuffer(1000);
+  absl::CordBuffer buffer = GetAppendBuffer(cord, 1000);
   EXPECT_GE(buffer.capacity(), 1000);
   EXPECT_EQ(buffer.length(), 0);
 }
 
-TEST_P(CordTest, GetAppendBufferOnInlinedCord) {
+TEST_P(CordAppendBufferTest, GetAppendBufferOnInlinedCord) {
   static constexpr int kInlinedSize = sizeof(absl::CordBuffer) - 1;
   for (int size : {6, kInlinedSize - 3, kInlinedSize - 2, 1000}) {
     absl::Cord cord("Abc");
-    absl::CordBuffer buffer = cord.GetAppendBuffer(size, 1);
+    absl::CordBuffer buffer = GetAppendBuffer(cord, size, 1);
     EXPECT_GE(buffer.capacity(), 3 + size);
     EXPECT_EQ(buffer.length(), 3);
     EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), "Abc");
@@ -752,7 +782,7 @@
   }
 }
 
-TEST_P(CordTest, GetAppendBufferOnInlinedCordWithCapacityCloseToMax) {
+TEST_P(CordAppendBufferTest, GetAppendBufferOnInlinedCordCapacityCloseToMax) {
   // Cover the use case where we have a non empty inlined cord with some size
   // 'n', and ask for something like 'uint64_max - k', assuming internal logic
   // could overflow on 'uint64_max - k + size', and return a valid, but
@@ -760,30 +790,31 @@
   for (size_t dist_from_max = 0; dist_from_max <= 4; ++dist_from_max) {
     absl::Cord cord("Abc");
     size_t size = std::numeric_limits<size_t>::max() - dist_from_max;
-    absl::CordBuffer buffer = cord.GetAppendBuffer(size, 1);
-    EXPECT_EQ(buffer.capacity(), absl::CordBuffer::kDefaultLimit);
+    absl::CordBuffer buffer = GetAppendBuffer(cord, size, 1);
+    EXPECT_GE(buffer.capacity(), maximum_payload());
     EXPECT_EQ(buffer.length(), 3);
     EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), "Abc");
     EXPECT_TRUE(cord.empty());
   }
 }
 
-TEST_P(CordTest, GetAppendBufferOnFlat) {
+TEST_P(CordAppendBufferTest, GetAppendBufferOnFlat) {
   // Create a cord with a single flat and extra capacity
   absl::Cord cord;
   absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);
+  const size_t expected_capacity = buffer.capacity();
   buffer.SetLength(3);
   memcpy(buffer.data(), "Abc", 3);
   cord.Append(std::move(buffer));
 
-  buffer = cord.GetAppendBuffer(6);
-  EXPECT_GE(buffer.capacity(), 500);
+  buffer = GetAppendBuffer(cord, 6);
+  EXPECT_EQ(buffer.capacity(), expected_capacity);
   EXPECT_EQ(buffer.length(), 3);
   EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), "Abc");
   EXPECT_TRUE(cord.empty());
 }
 
-TEST_P(CordTest, GetAppendBufferOnFlatWithoutMinCapacity) {
+TEST_P(CordAppendBufferTest, GetAppendBufferOnFlatWithoutMinCapacity) {
   // Create a cord with a single flat and extra capacity
   absl::Cord cord;
   absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);
@@ -791,13 +822,13 @@
   memset(buffer.data(), 'x', 30);
   cord.Append(std::move(buffer));
 
-  buffer = cord.GetAppendBuffer(1000, 900);
+  buffer = GetAppendBuffer(cord, 1000, 900);
   EXPECT_GE(buffer.capacity(), 1000);
   EXPECT_EQ(buffer.length(), 0);
   EXPECT_EQ(cord, std::string(30, 'x'));
 }
 
-TEST_P(CordTest, GetAppendBufferOnTree) {
+TEST_P(CordAppendBufferTest, GetAppendBufferOnTree) {
   RandomEngine rng;
   for (int num_flats : {2, 3, 100}) {
     // Create a cord with `num_flats` flats and extra capacity
@@ -812,7 +843,7 @@
       memcpy(buffer.data(), last.data(), 10);
       cord.Append(std::move(buffer));
     }
-    absl::CordBuffer buffer = cord.GetAppendBuffer(6);
+    absl::CordBuffer buffer = GetAppendBuffer(cord, 6);
     EXPECT_GE(buffer.capacity(), 500);
     EXPECT_EQ(buffer.length(), 10);
     EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), last);
@@ -820,7 +851,7 @@
   }
 }
 
-TEST_P(CordTest, GetAppendBufferOnTreeWithoutMinCapacity) {
+TEST_P(CordAppendBufferTest, GetAppendBufferOnTreeWithoutMinCapacity) {
   absl::Cord cord;
   for (int i = 0; i < 2; ++i) {
     absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);
@@ -828,13 +859,13 @@
     memcpy(buffer.data(), i ? "def" : "Abc", 3);
     cord.Append(std::move(buffer));
   }
-  absl::CordBuffer buffer = cord.GetAppendBuffer(1000, 900);
+  absl::CordBuffer buffer = GetAppendBuffer(cord, 1000, 900);
   EXPECT_GE(buffer.capacity(), 1000);
   EXPECT_EQ(buffer.length(), 0);
   EXPECT_EQ(cord, "Abcdef");
 }
 
-TEST_P(CordTest, GetAppendBufferOnSubstring) {
+TEST_P(CordAppendBufferTest, GetAppendBufferOnSubstring) {
   // Create a large cord with a single flat and some extra capacity
   absl::Cord cord;
   absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);
@@ -844,12 +875,12 @@
   cord.RemovePrefix(1);
 
   // Deny on substring
-  buffer = cord.GetAppendBuffer(6);
+  buffer = GetAppendBuffer(cord, 6);
   EXPECT_EQ(buffer.length(), 0);
   EXPECT_EQ(cord, std::string(449, 'x'));
 }
 
-TEST_P(CordTest, GetAppendBufferOnSharedCord) {
+TEST_P(CordAppendBufferTest, GetAppendBufferOnSharedCord) {
   // Create a shared cord with a single flat and extra capacity
   absl::Cord cord;
   absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);
@@ -859,7 +890,7 @@
   absl::Cord shared_cord = cord;
 
   // Deny on flat
-  buffer = cord.GetAppendBuffer(6);
+  buffer = GetAppendBuffer(cord, 6);
   EXPECT_EQ(buffer.length(), 0);
   EXPECT_EQ(cord, "Abc");
 
@@ -870,7 +901,7 @@
   shared_cord = cord;
 
   // Deny on tree
-  buffer = cord.GetAppendBuffer(6);
+  buffer = GetAppendBuffer(cord, 6);
   EXPECT_EQ(buffer.length(), 0);
   EXPECT_EQ(cord, "Abcdef");
 }
diff --git a/third_party/abseil-cpp/absl/strings/escaping.cc b/third_party/abseil-cpp/absl/strings/escaping.cc
index 18b20b83..4dc69702 100644
--- a/third_party/abseil-cpp/absl/strings/escaping.cc
+++ b/third_party/abseil-cpp/absl/strings/escaping.cc
@@ -773,7 +773,8 @@
                             const signed char* unbase64) {
   // Determine the size of the output string.  Base64 encodes every 3 bytes into
   // 4 characters.  any leftover chars are added directly for good measure.
-  // This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548
+  // This is documented in the base64 RFC:
+  // https://datatracker.ietf.org/doc/html/rfc3548
   const size_t dest_len = 3 * (slen / 4) + (slen % 4);
 
   strings_internal::STLStringResizeUninitialized(dest, dest_len);
@@ -876,8 +877,8 @@
 // WebSafeBase64Escape() - Google's variation of base64 encoder
 //
 // Check out
-// http://tools.ietf.org/html/rfc2045 for formal description, but what we
-// care about is that...
+// https://datatracker.ietf.org/doc/html/rfc2045 for formal description, but
+// what we care about is that...
 //   Take the encoded stuff in groups of 4 characters and turn each
 //   character into a code 0 to 63 thus:
 //           A-Z map to 0 to 25
diff --git a/third_party/abseil-cpp/absl/types/internal/span.h b/third_party/abseil-cpp/absl/types/internal/span.h
index 112612f..1920a89e4 100644
--- a/third_party/abseil-cpp/absl/types/internal/span.h
+++ b/third_party/abseil-cpp/absl/types/internal/span.h
@@ -28,6 +28,9 @@
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
+template <typename T>
+class Span;
+
 namespace span_internal {
 // A constexpr min function
 constexpr size_t Min(size_t a, size_t b) noexcept { return a < b ? a : b; }
@@ -121,6 +124,36 @@
 template <typename From, typename To>
 using EnableIfConvertibleTo =
     typename std::enable_if<IsConvertible<From, To>::value>::type;
+
+// IsView is true for types where the return type of .data() is the same for
+// mutable and const instances. This isn't foolproof, but it's only used to
+// enable a compiler warning.
+template <typename T, typename = void, typename = void>
+struct IsView {
+  static constexpr bool value = false;
+};
+
+template <typename T>
+struct IsView<
+    T, absl::void_t<decltype(span_internal::GetData(std::declval<const T&>()))>,
+    absl::void_t<decltype(span_internal::GetData(std::declval<T&>()))>> {
+ private:
+  using Container = std::remove_const_t<T>;
+  using ConstData =
+      decltype(span_internal::GetData(std::declval<const Container&>()));
+  using MutData = decltype(span_internal::GetData(std::declval<Container&>()));
+ public:
+  static constexpr bool value = std::is_same<ConstData, MutData>::value;
+};
+
+// These enablers result in 'int' so they can be used as typenames or defaults
+// in template paramters lists.
+template <typename T>
+using EnableIfIsView = std::enable_if_t<IsView<T>::value, int>;
+
+template <typename T>
+using EnableIfNotIsView = std::enable_if_t<!IsView<T>::value, int>;
+
 }  // namespace span_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/third_party/abseil-cpp/absl/types/span.h b/third_party/abseil-cpp/absl/types/span.h
index fdfbd77..cd863a9 100644
--- a/third_party/abseil-cpp/absl/types/span.h
+++ b/third_party/abseil-cpp/absl/types/span.h
@@ -60,6 +60,7 @@
 #include <type_traits>
 #include <utility>
 
+#include "absl/base/attributes.h"
 #include "absl/base/internal/throw_delegate.h"
 #include "absl/base/macros.h"
 #include "absl/base/optimization.h"
@@ -160,12 +161,12 @@
 
   // Used to SFINAE-enable a function when the slice elements are const.
   template <typename U>
-  using EnableIfConstView =
+  using EnableIfValueIsConst =
       typename std::enable_if<std::is_const<T>::value, U>::type;
 
   // Used to SFINAE-enable a function when the slice elements are mutable.
   template <typename U>
-  using EnableIfMutableView =
+  using EnableIfValueIsMutable =
       typename std::enable_if<!std::is_const<T>::value, U>::type;
 
  public:
@@ -196,13 +197,34 @@
   // Explicit reference constructor for a mutable `Span<T>` type. Can be
   // replaced with MakeSpan() to infer the type parameter.
   template <typename V, typename = EnableIfConvertibleFrom<V>,
-            typename = EnableIfMutableView<V>>
-  explicit Span(V& v) noexcept  // NOLINT(runtime/references)
+            typename = EnableIfValueIsMutable<V>,
+            typename = span_internal::EnableIfNotIsView<V>>
+  explicit Span(
+      V& v
+          ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept  // NOLINT(runtime/references)
       : Span(span_internal::GetData(v), v.size()) {}
 
   // Implicit reference constructor for a read-only `Span<const T>` type
   template <typename V, typename = EnableIfConvertibleFrom<V>,
-            typename = EnableIfConstView<V>>
+            typename = EnableIfValueIsConst<V>,
+            typename = span_internal::EnableIfNotIsView<V>>
+  constexpr Span(
+      const V& v
+          ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept  // NOLINT(runtime/explicit)
+      : Span(span_internal::GetData(v), v.size()) {}
+
+  // Overloads of the above two functions that are only enabled for view types.
+  // This is so we can drop the ABSL_ATTRIBUTE_LIFETIME_BOUND annotation. These
+  // overloads must be made unique by using a different template parameter list
+  // (hence the = 0 for the IsView enabler).
+  template <typename V, typename = EnableIfConvertibleFrom<V>,
+            typename = EnableIfValueIsMutable<V>,
+            span_internal::EnableIfIsView<V> = 0>
+  explicit Span(V& v) noexcept  // NOLINT(runtime/references)
+      : Span(span_internal::GetData(v), v.size()) {}
+  template <typename V, typename = EnableIfConvertibleFrom<V>,
+            typename = EnableIfValueIsConst<V>,
+            span_internal::EnableIfIsView<V> = 0>
   constexpr Span(const V& v) noexcept  // NOLINT(runtime/explicit)
       : Span(span_internal::GetData(v), v.size()) {}
 
@@ -242,7 +264,7 @@
   //   Process(ints);
   //
   template <typename LazyT = T,
-            typename = EnableIfConstView<LazyT>>
+            typename = EnableIfValueIsConst<LazyT>>
   Span(std::initializer_list<value_type> v
            ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept  // NOLINT(runtime/explicit)
       : Span(v.begin(), v.size()) {}
diff --git a/third_party/abseil-cpp/absl/utility/utility_test.cc b/third_party/abseil-cpp/absl/utility/utility_test.cc
index f044ad6..2f0509aa 100644
--- a/third_party/abseil-cpp/absl/utility/utility_test.cc
+++ b/third_party/abseil-cpp/absl/utility/utility_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 The Abseil Authors.
+// Copyright 2022 The Abseil Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -14,10 +14,12 @@
 
 #include "absl/utility/utility.h"
 
+#include <memory>
 #include <sstream>
 #include <string>
 #include <tuple>
 #include <type_traits>
+#include <utility>
 #include <vector>
 
 #include "gmock/gmock.h"
@@ -35,10 +37,10 @@
 // Both the unused variables and the name length warnings are due to calls
 // to absl::make_index_sequence with very large values, creating very long type
 // names. The resulting warnings are so long they make build output unreadable.
-#pragma warning( push )
-#pragma warning( disable : 4503 )  // decorated name length exceeded
-#pragma warning( disable : 4101 )  // unreferenced local variable
-#endif  // _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4503)  // decorated name length exceeded
+#pragma warning(disable : 4101)  // unreferenced local variable
+#endif                           // _MSC_VER
 
 using ::testing::ElementsAre;
 using ::testing::Pointee;
@@ -227,8 +229,7 @@
 }
 
 TEST(ApplyTest, NonCopyableResult) {
-  EXPECT_THAT(absl::apply(Factory, std::make_tuple(42)),
-              ::testing::Pointee(42));
+  EXPECT_THAT(absl::apply(Factory, std::make_tuple(42)), Pointee(42));
 }
 
 TEST(ApplyTest, VoidResult) { absl::apply(NoOp, std::tuple<>()); }
@@ -373,4 +374,3 @@
 }
 
 }  // namespace
-
diff --git a/third_party/abseil-cpp/symbols_arm64_dbg.def b/third_party/abseil-cpp/symbols_arm64_dbg.def
index 86f46aca..dbdf937 100644
--- a/third_party/abseil-cpp/symbols_arm64_dbg.def
+++ b/third_party/abseil-cpp/symbols_arm64_dbg.def
@@ -144,9 +144,9 @@
     ??$?0Uyear_tag@time_internal@absl@@@?$civil_time@Uminute_tag@time_internal@absl@@@detail@cctz@time_internal@absl@@QEAA@AEBV?$civil_time@Uyear_tag@time_internal@absl@@@1234@PEAX@Z
     ??$?0Uyear_tag@time_internal@absl@@@?$civil_time@Umonth_tag@time_internal@absl@@@detail@cctz@time_internal@absl@@QEAA@AEBV?$civil_time@Uyear_tag@time_internal@absl@@@1234@PEAX@Z
     ??$?0Uyear_tag@time_internal@absl@@@?$civil_time@Usecond_tag@time_internal@absl@@@detail@cctz@time_internal@absl@@QEAA@AEBV?$civil_time@Uyear_tag@time_internal@absl@@@1234@PEAX@Z
-    ??$?0V?$Span@I@absl@@XV01@@?$Span@$$CBI@absl@@QEAA@AEBV?$Span@I@1@@Z
-    ??$?0V?$Span@I@absl@@XV01@@?$Span@I@absl@@QEAA@AEAV01@@Z
-    ??$?0V?$Span@VFormatArgImpl@str_format_internal@absl@@@absl@@XV01@@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QEAA@AEBV?$Span@VFormatArgImpl@str_format_internal@absl@@@1@@Z
+    ??$?0V?$Span@I@absl@@XV01@$0A@@?$Span@$$CBI@absl@@QEAA@AEBV?$Span@I@1@@Z
+    ??$?0V?$Span@I@absl@@XV01@$0A@@?$Span@I@absl@@QEAA@AEAV01@@Z
+    ??$?0V?$Span@VFormatArgImpl@str_format_internal@absl@@@absl@@XV01@$0A@@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QEAA@AEBV?$Span@VFormatArgImpl@str_format_internal@absl@@@1@@Z
     ??$?0V?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@@Cr@std@@X@?$__compressed_pair_elem@V?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@@Cr@std@@$00$0A@@Cr@std@@QEAA@$$QEAV?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@@12@@Z
     ??$?0V?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PEAX@Cr@std@@@Cr@std@@AEA_N$0A@@?$pair@V?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PEAX@Cr@std@@@Cr@std@@_N@Cr@std@@QEAA@$$QEAV?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PEAX@Cr@std@@@12@AEA_N@Z
     ??$?0V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PEAX@Cr@std@@@Cr@std@@@Cr@std@@X@?$__compressed_pair_elem@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PEAX@Cr@std@@@Cr@std@@@Cr@std@@$00$0A@@Cr@std@@QEAA@$$QEAV?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PEAX@Cr@std@@@Cr@std@@@12@@Z
@@ -164,7 +164,7 @@
     ??$?0V?$basic_ostream@DU?$char_traits@D@Cr@std@@@Cr@std@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QEAA@PEAV?$basic_ostream@DU?$char_traits@D@Cr@std@@@Cr@std@@@Z
     ??$?0V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@$0A@@Cord@absl@@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@@Z
     ??$?0V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QEAA@PEAV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@@Z
-    ??$?0V?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@Cr@std@@@Cr@std@@XV012@@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QEAA@AEBV?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@Cr@std@@@Cr@std@@@Z
+    ??$?0V?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@Cr@std@@@Cr@std@@XV012@H@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QEAA@AEBV?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@Cr@std@@@Cr@std@@@Z
     ??$?0VBufferRawSink@str_format_internal@absl@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QEAA@PEAVBufferRawSink@12@@Z
     ??$?0VFILERawSink@str_format_internal@absl@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QEAA@PEAVFILERawSink@12@@Z
     ??$?8PEAPEAVCordzHandle@cord_internal@absl@@@Cr@std@@YA_NAEBV?$__wrap_iter@PEAPEAVCordzHandle@cord_internal@absl@@@01@0@Z
@@ -251,6 +251,7 @@
     ??$ConstructElements@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@V?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@PEBUPayload@status_internal@absl@@@inlined_vector_internal@absl@@@inlined_vector_internal@absl@@YAXAEAV?$allocator@UPayload@status_internal@absl@@@Cr@std@@PEAUPayload@status_internal@1@AEAV?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@PEBUPayload@status_internal@absl@@@01@_K@Z
     ??$ConstructElements@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@V?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@V?$move_iterator@PEAUPayload@status_internal@absl@@@23@@inlined_vector_internal@absl@@@inlined_vector_internal@absl@@YAXAEAV?$allocator@UPayload@status_internal@absl@@@Cr@std@@PEAUPayload@status_internal@1@AEAV?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@V?$move_iterator@PEAUPayload@status_internal@absl@@@23@@01@_K@Z
     ??$Convert@VFormatArgImpl@str_format_internal@absl@@@FormatArgImplFriend@str_format_internal@absl@@SA_NVFormatArgImpl@12@VFormatConversionSpecImpl@12@PEAVFormatSinkImpl@12@@Z
+    ??$CreateWithCustomLimitImpl@$$V@CordBuffer@absl@@CA?AV01@_K0@Z
     ??$Dispatch@C@FormatArgImpl@str_format_internal@absl@@CA_NTData@012@VFormatConversionSpecImpl@12@PEAX@Z
     ??$Dispatch@D@FormatArgImpl@str_format_internal@absl@@CA_NTData@012@VFormatConversionSpecImpl@12@PEAX@Z
     ??$Dispatch@E@FormatArgImpl@str_format_internal@absl@@CA_NTData@012@VFormatConversionSpecImpl@12@PEAX@Z
@@ -355,6 +356,7 @@
     ??$Nanoseconds@J$0A@@absl@@YA?AVDuration@0@J@Z
     ??$Nanoseconds@_J$0A@@absl@@YA?AVDuration@0@_J@Z
     ??$NewImpl@$0BAAA@$$V@CordRepFlat@cord_internal@absl@@SAPEAU012@_K@Z
+    ??$NewImpl@$0EAAAA@$$V@CordRepFlat@cord_internal@absl@@SAPEAU012@_K@Z
     ??$NewLeaf@$00@CordRepBtree@cord_internal@absl@@CAPEAV012@Vstring_view@2@_K@Z
     ??$NewLeaf@$0A@@CordRepBtree@cord_internal@absl@@CAPEAV012@Vstring_view@2@_K@Z
     ??$Offset@$00$0A@@?$LayoutImpl@V?$tuple@_KPEAUCordRep@cord_internal@absl@@I@Cr@std@@U?$integer_sequence@_K$0A@$00$01@absl@@U45@@internal_layout@container_internal@absl@@QEBA_KXZ
@@ -661,6 +663,7 @@
     ??$get@$0A@Vstring_view@absl@@V12@@Cr@std@@YAAEBVstring_view@absl@@AEBU?$pair@Vstring_view@absl@@V12@@01@@Z
     ??$get@Vstring_view@absl@@V12@@?$__get_pair@$00@Cr@std@@SAAEBVstring_view@absl@@AEBU?$pair@Vstring_view@absl@@V12@@12@@Z
     ??$get@Vstring_view@absl@@V12@@?$__get_pair@$0A@@Cr@std@@SAAEBVstring_view@absl@@AEBU?$pair@Vstring_view@absl@@V12@@12@@Z
+    ??$has_single_bit@_K@absl@@YA_N_K@Z
     ??$launder@$$CBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@@Cr@std@@YAPEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEBU201@@Z
     ??$launder@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@@Cr@std@@YAPEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEAU201@@Z
     ??$lower_bound@PEBUTransition@cctz@time_internal@absl@@U1234@UByUnixTime@1234@@Cr@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@UByUnixTime@2345@@Z
@@ -1540,6 +1543,7 @@
     ?CreateSlow@CordRepBtree@cord_internal@absl@@CAPEAV123@PEAUCordRep@23@@Z
     ?CreateSlow@CordRepRing@cord_internal@absl@@CAPEAV123@PEAUCordRep@23@_K@Z
     ?CreateThreadIdentity@synchronization_internal@absl@@YAPEAUThreadIdentity@base_internal@2@XZ
+    ?CreateWithCustomLimit@CordBuffer@absl@@SA?AV12@_K0@Z
     ?CreateWithDefaultLimit@CordBuffer@absl@@SA?AV12@_K@Z
     ?Current@CordRepBtreeNavigator@cord_internal@absl@@QEBAPEAUCordRep@23@XZ
     ?CurrentThreadIdentityIfPresent@base_internal@absl@@YAPEAUThreadIdentity@12@XZ
@@ -1774,7 +1778,7 @@
     ?GetAppendBuffer@CordRepBtree@cord_internal@absl@@QEAA?AV?$Span@D@3@_K@Z
     ?GetAppendBuffer@CordRepRing@cord_internal@absl@@QEAA?AV?$Span@D@3@_K@Z
     ?GetAppendBufferSlow@CordRepBtree@cord_internal@absl@@AEAA?AV?$Span@D@3@_K@Z
-    ?GetAppendBufferSlowPath@Cord@absl@@AEAA?AVCordBuffer@2@_K0@Z
+    ?GetAppendBufferSlowPath@Cord@absl@@AEAA?AVCordBuffer@2@_K00@Z
     ?GetCachedTID@base_internal@absl@@YAIXZ
     ?GetCapacity@?$AllocationTransaction@V?$allocator@PEAUCordRep@cord_internal@absl@@@Cr@std@@@inlined_vector_internal@absl@@QEAAAEA_KXZ
     ?GetCapacity@?$AllocationTransaction@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@@inlined_vector_internal@absl@@QEAAAEA_KXZ
@@ -1926,6 +1930,7 @@
     ?IsOne@RefcountAndFlags@cord_internal@absl@@QEAA_NXZ
     ?IsOutOfRange@absl@@YA_NAEBVStatus@1@@Z
     ?IsPermissionDenied@absl@@YA_NAEBVStatus@1@@Z
+    ?IsPow2@CordBuffer@absl@@CA_N_K@Z
     ?IsReachable@GraphCycles@synchronization_internal@absl@@QEBA_NUGraphId@23@0@Z
     ?IsResourceExhausted@absl@@YA_NAEBVStatus@1@@Z
     ?IsRing@CordRep@cord_internal@absl@@QEBA_NXZ
@@ -1961,6 +1966,8 @@
     ?LockWhen@Mutex@absl@@QEAAXAEBVCondition@2@@Z
     ?LockWhenWithDeadline@Mutex@absl@@QEAA_NAEBVCondition@2@VTime@2@@Z
     ?LockWhenWithTimeout@Mutex@absl@@QEAA_NAEBVCondition@2@VDuration@2@@Z
+    ?Log2Ceil@CordBuffer@absl@@CA_K_K@Z
+    ?Log2Floor@CordBuffer@absl@@CA_K_K@Z
     ?LogFatalNodeType@cord_internal@absl@@YAXPEAUCordRep@12@@Z
     ?LogSeverityName@absl@@YAPEBDW4LogSeverity@1@@Z
     ?LossyAdd@CordzUpdateTracker@cord_internal@absl@@QEAAXAEBV123@@Z
@@ -2013,6 +2020,7 @@
     ?New@CordRepBtree@cord_internal@absl@@SAPEAV123@PEAUCordRep@23@@Z
     ?New@CordRepBtree@cord_internal@absl@@SAPEAV123@PEAV123@0@Z
     ?New@CordRepCrc@cord_internal@absl@@SAPEAU123@PEAUCordRep@23@I@Z
+    ?New@CordRepFlat@cord_internal@absl@@SAPEAU123@ULarge@123@_K@Z
     ?New@CordRepFlat@cord_internal@absl@@SAPEAU123@_K@Z
     ?New@CordRepRing@cord_internal@absl@@CAPEAV123@_K0@Z
     ?NewArena@LowLevelAlloc@base_internal@absl@@SAPEAUArena@123@H@Z
diff --git a/third_party/abseil-cpp/symbols_arm64_rel.def b/third_party/abseil-cpp/symbols_arm64_rel.def
index 2c163d54..a820b33 100644
--- a/third_party/abseil-cpp/symbols_arm64_rel.def
+++ b/third_party/abseil-cpp/symbols_arm64_rel.def
@@ -63,6 +63,7 @@
     ??$Merge@$00@CordRepBtree@cord_internal@absl@@CAPEAV012@PEAV012@0@Z
     ??$Merge@$0A@@CordRepBtree@cord_internal@absl@@CAPEAV012@PEAV012@0@Z
     ??$NewImpl@$0BAAA@$$V@CordRepFlat@cord_internal@absl@@SAPEAU012@_K@Z
+    ??$NewImpl@$0EAAAA@$$V@CordRepFlat@cord_internal@absl@@SAPEAU012@_K@Z
     ??$NewLeaf@$00@CordRepBtree@cord_internal@absl@@CAPEAV012@Vstring_view@2@_K@Z
     ??$NewLeaf@$0A@@CordRepBtree@cord_internal@absl@@CAPEAV012@Vstring_view@2@_K@Z
     ??$ParseFloat@$09@strings_internal@absl@@YA?AUParsedFloat@01@PEBD0W4chars_format@1@@Z
@@ -469,7 +470,7 @@
     ?GetAppendBuffer@CordRepBtree@cord_internal@absl@@QEAA?AV?$Span@D@3@_K@Z
     ?GetAppendBuffer@CordRepRing@cord_internal@absl@@QEAA?AV?$Span@D@3@_K@Z
     ?GetAppendBufferSlow@CordRepBtree@cord_internal@absl@@AEAA?AV?$Span@D@3@_K@Z
-    ?GetAppendBufferSlowPath@Cord@absl@@AEAA?AVCordBuffer@2@_K0@Z
+    ?GetAppendBufferSlowPath@Cord@absl@@AEAA?AVCordBuffer@2@_K00@Z
     ?GetCachedTID@base_internal@absl@@YAIXZ
     ?GetCharacter@CordRepBtree@cord_internal@absl@@QEBAD_K@Z
     ?GetCharacter@CordRepRing@cord_internal@absl@@QEBAD_K@Z
diff --git a/third_party/abseil-cpp/symbols_x64_dbg.def b/third_party/abseil-cpp/symbols_x64_dbg.def
index cc25fa4..ceb58cc 100644
--- a/third_party/abseil-cpp/symbols_x64_dbg.def
+++ b/third_party/abseil-cpp/symbols_x64_dbg.def
@@ -144,9 +144,9 @@
     ??$?0Uyear_tag@time_internal@absl@@@?$civil_time@Uminute_tag@time_internal@absl@@@detail@cctz@time_internal@absl@@QEAA@AEBV?$civil_time@Uyear_tag@time_internal@absl@@@1234@PEAX@Z
     ??$?0Uyear_tag@time_internal@absl@@@?$civil_time@Umonth_tag@time_internal@absl@@@detail@cctz@time_internal@absl@@QEAA@AEBV?$civil_time@Uyear_tag@time_internal@absl@@@1234@PEAX@Z
     ??$?0Uyear_tag@time_internal@absl@@@?$civil_time@Usecond_tag@time_internal@absl@@@detail@cctz@time_internal@absl@@QEAA@AEBV?$civil_time@Uyear_tag@time_internal@absl@@@1234@PEAX@Z
-    ??$?0V?$Span@I@absl@@XV01@@?$Span@$$CBI@absl@@QEAA@AEBV?$Span@I@1@@Z
-    ??$?0V?$Span@I@absl@@XV01@@?$Span@I@absl@@QEAA@AEAV01@@Z
-    ??$?0V?$Span@VFormatArgImpl@str_format_internal@absl@@@absl@@XV01@@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QEAA@AEBV?$Span@VFormatArgImpl@str_format_internal@absl@@@1@@Z
+    ??$?0V?$Span@I@absl@@XV01@$0A@@?$Span@$$CBI@absl@@QEAA@AEBV?$Span@I@1@@Z
+    ??$?0V?$Span@I@absl@@XV01@$0A@@?$Span@I@absl@@QEAA@AEAV01@@Z
+    ??$?0V?$Span@VFormatArgImpl@str_format_internal@absl@@@absl@@XV01@$0A@@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QEAA@AEBV?$Span@VFormatArgImpl@str_format_internal@absl@@@1@@Z
     ??$?0V?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@@Cr@std@@X@?$__compressed_pair_elem@V?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@@Cr@std@@$00$0A@@Cr@std@@QEAA@$$QEAV?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@@12@@Z
     ??$?0V?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PEAX@Cr@std@@@Cr@std@@AEA_N$0A@@?$pair@V?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PEAX@Cr@std@@@Cr@std@@_N@Cr@std@@QEAA@$$QEAV?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PEAX@Cr@std@@@12@AEA_N@Z
     ??$?0V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PEAX@Cr@std@@@Cr@std@@@Cr@std@@X@?$__compressed_pair_elem@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PEAX@Cr@std@@@Cr@std@@@Cr@std@@$00$0A@@Cr@std@@QEAA@$$QEAV?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PEAX@Cr@std@@@Cr@std@@@12@@Z
@@ -164,7 +164,7 @@
     ??$?0V?$basic_ostream@DU?$char_traits@D@Cr@std@@@Cr@std@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QEAA@PEAV?$basic_ostream@DU?$char_traits@D@Cr@std@@@Cr@std@@@Z
     ??$?0V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@$0A@@Cord@absl@@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@@Z
     ??$?0V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QEAA@PEAV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@@Z
-    ??$?0V?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@Cr@std@@@Cr@std@@XV012@@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QEAA@AEBV?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@Cr@std@@@Cr@std@@@Z
+    ??$?0V?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@Cr@std@@@Cr@std@@XV012@H@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QEAA@AEBV?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@Cr@std@@@Cr@std@@@Z
     ??$?0VBufferRawSink@str_format_internal@absl@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QEAA@PEAVBufferRawSink@12@@Z
     ??$?0VFILERawSink@str_format_internal@absl@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QEAA@PEAVFILERawSink@12@@Z
     ??$?8PEAPEAVCordzHandle@cord_internal@absl@@@Cr@std@@YA_NAEBV?$__wrap_iter@PEAPEAVCordzHandle@cord_internal@absl@@@01@0@Z
@@ -251,6 +251,7 @@
     ??$ConstructElements@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@V?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@PEBUPayload@status_internal@absl@@@inlined_vector_internal@absl@@@inlined_vector_internal@absl@@YAXAEAV?$allocator@UPayload@status_internal@absl@@@Cr@std@@PEAUPayload@status_internal@1@AEAV?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@PEBUPayload@status_internal@absl@@@01@_K@Z
     ??$ConstructElements@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@V?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@V?$move_iterator@PEAUPayload@status_internal@absl@@@23@@inlined_vector_internal@absl@@@inlined_vector_internal@absl@@YAXAEAV?$allocator@UPayload@status_internal@absl@@@Cr@std@@PEAUPayload@status_internal@1@AEAV?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@V?$move_iterator@PEAUPayload@status_internal@absl@@@23@@01@_K@Z
     ??$Convert@VFormatArgImpl@str_format_internal@absl@@@FormatArgImplFriend@str_format_internal@absl@@SA_NVFormatArgImpl@12@VFormatConversionSpecImpl@12@PEAVFormatSinkImpl@12@@Z
+    ??$CreateWithCustomLimitImpl@$$V@CordBuffer@absl@@CA?AV01@_K0@Z
     ??$Dispatch@C@FormatArgImpl@str_format_internal@absl@@CA_NTData@012@VFormatConversionSpecImpl@12@PEAX@Z
     ??$Dispatch@D@FormatArgImpl@str_format_internal@absl@@CA_NTData@012@VFormatConversionSpecImpl@12@PEAX@Z
     ??$Dispatch@E@FormatArgImpl@str_format_internal@absl@@CA_NTData@012@VFormatConversionSpecImpl@12@PEAX@Z
@@ -355,6 +356,7 @@
     ??$Nanoseconds@J$0A@@absl@@YA?AVDuration@0@J@Z
     ??$Nanoseconds@_J$0A@@absl@@YA?AVDuration@0@_J@Z
     ??$NewImpl@$0BAAA@$$V@CordRepFlat@cord_internal@absl@@SAPEAU012@_K@Z
+    ??$NewImpl@$0EAAAA@$$V@CordRepFlat@cord_internal@absl@@SAPEAU012@_K@Z
     ??$NewLeaf@$00@CordRepBtree@cord_internal@absl@@CAPEAV012@Vstring_view@2@_K@Z
     ??$NewLeaf@$0A@@CordRepBtree@cord_internal@absl@@CAPEAV012@Vstring_view@2@_K@Z
     ??$Offset@$00$0A@@?$LayoutImpl@V?$tuple@_KPEAUCordRep@cord_internal@absl@@I@Cr@std@@U?$integer_sequence@_K$0A@$00$01@absl@@U45@@internal_layout@container_internal@absl@@QEBA_KXZ
@@ -665,6 +667,7 @@
     ??$get@$0A@Vstring_view@absl@@V12@@Cr@std@@YAAEBVstring_view@absl@@AEBU?$pair@Vstring_view@absl@@V12@@01@@Z
     ??$get@Vstring_view@absl@@V12@@?$__get_pair@$00@Cr@std@@SAAEBVstring_view@absl@@AEBU?$pair@Vstring_view@absl@@V12@@12@@Z
     ??$get@Vstring_view@absl@@V12@@?$__get_pair@$0A@@Cr@std@@SAAEBVstring_view@absl@@AEBU?$pair@Vstring_view@absl@@V12@@12@@Z
+    ??$has_single_bit@_K@absl@@YA_N_K@Z
     ??$launder@$$CBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@@Cr@std@@YAPEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEBU201@@Z
     ??$launder@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@@Cr@std@@YAPEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEAU201@@Z
     ??$lower_bound@PEBUTransition@cctz@time_internal@absl@@U1234@UByUnixTime@1234@@Cr@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@UByUnixTime@2345@@Z
@@ -1543,6 +1546,7 @@
     ?CreateSlow@CordRepBtree@cord_internal@absl@@CAPEAV123@PEAUCordRep@23@@Z
     ?CreateSlow@CordRepRing@cord_internal@absl@@CAPEAV123@PEAUCordRep@23@_K@Z
     ?CreateThreadIdentity@synchronization_internal@absl@@YAPEAUThreadIdentity@base_internal@2@XZ
+    ?CreateWithCustomLimit@CordBuffer@absl@@SA?AV12@_K0@Z
     ?CreateWithDefaultLimit@CordBuffer@absl@@SA?AV12@_K@Z
     ?Current@CordRepBtreeNavigator@cord_internal@absl@@QEBAPEAUCordRep@23@XZ
     ?CurrentThreadIdentityIfPresent@base_internal@absl@@YAPEAUThreadIdentity@12@XZ
@@ -1776,7 +1780,7 @@
     ?GetAppendBuffer@CordRepBtree@cord_internal@absl@@QEAA?AV?$Span@D@3@_K@Z
     ?GetAppendBuffer@CordRepRing@cord_internal@absl@@QEAA?AV?$Span@D@3@_K@Z
     ?GetAppendBufferSlow@CordRepBtree@cord_internal@absl@@AEAA?AV?$Span@D@3@_K@Z
-    ?GetAppendBufferSlowPath@Cord@absl@@AEAA?AVCordBuffer@2@_K0@Z
+    ?GetAppendBufferSlowPath@Cord@absl@@AEAA?AVCordBuffer@2@_K00@Z
     ?GetCachedTID@base_internal@absl@@YAIXZ
     ?GetCapacity@?$AllocationTransaction@V?$allocator@PEAUCordRep@cord_internal@absl@@@Cr@std@@@inlined_vector_internal@absl@@QEAAAEA_KXZ
     ?GetCapacity@?$AllocationTransaction@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@@inlined_vector_internal@absl@@QEAAAEA_KXZ
@@ -1928,6 +1932,7 @@
     ?IsOne@RefcountAndFlags@cord_internal@absl@@QEAA_NXZ
     ?IsOutOfRange@absl@@YA_NAEBVStatus@1@@Z
     ?IsPermissionDenied@absl@@YA_NAEBVStatus@1@@Z
+    ?IsPow2@CordBuffer@absl@@CA_N_K@Z
     ?IsReachable@GraphCycles@synchronization_internal@absl@@QEBA_NUGraphId@23@0@Z
     ?IsResourceExhausted@absl@@YA_NAEBVStatus@1@@Z
     ?IsRing@CordRep@cord_internal@absl@@QEBA_NXZ
@@ -1963,6 +1968,8 @@
     ?LockWhen@Mutex@absl@@QEAAXAEBVCondition@2@@Z
     ?LockWhenWithDeadline@Mutex@absl@@QEAA_NAEBVCondition@2@VTime@2@@Z
     ?LockWhenWithTimeout@Mutex@absl@@QEAA_NAEBVCondition@2@VDuration@2@@Z
+    ?Log2Ceil@CordBuffer@absl@@CA_K_K@Z
+    ?Log2Floor@CordBuffer@absl@@CA_K_K@Z
     ?LogFatalNodeType@cord_internal@absl@@YAXPEAUCordRep@12@@Z
     ?LogSeverityName@absl@@YAPEBDW4LogSeverity@1@@Z
     ?LossyAdd@CordzUpdateTracker@cord_internal@absl@@QEAAXAEBV123@@Z
@@ -2015,6 +2022,7 @@
     ?New@CordRepBtree@cord_internal@absl@@SAPEAV123@PEAUCordRep@23@@Z
     ?New@CordRepBtree@cord_internal@absl@@SAPEAV123@PEAV123@0@Z
     ?New@CordRepCrc@cord_internal@absl@@SAPEAU123@PEAUCordRep@23@I@Z
+    ?New@CordRepFlat@cord_internal@absl@@SAPEAU123@ULarge@123@_K@Z
     ?New@CordRepFlat@cord_internal@absl@@SAPEAU123@_K@Z
     ?New@CordRepRing@cord_internal@absl@@CAPEAV123@_K0@Z
     ?NewArena@LowLevelAlloc@base_internal@absl@@SAPEAUArena@123@H@Z
diff --git a/third_party/abseil-cpp/symbols_x64_rel.def b/third_party/abseil-cpp/symbols_x64_rel.def
index 1d86110..a974eaa4 100644
--- a/third_party/abseil-cpp/symbols_x64_rel.def
+++ b/third_party/abseil-cpp/symbols_x64_rel.def
@@ -63,6 +63,7 @@
     ??$Merge@$00@CordRepBtree@cord_internal@absl@@CAPEAV012@PEAV012@0@Z
     ??$Merge@$0A@@CordRepBtree@cord_internal@absl@@CAPEAV012@PEAV012@0@Z
     ??$NewImpl@$0BAAA@$$V@CordRepFlat@cord_internal@absl@@SAPEAU012@_K@Z
+    ??$NewImpl@$0EAAAA@$$V@CordRepFlat@cord_internal@absl@@SAPEAU012@_K@Z
     ??$NewLeaf@$00@CordRepBtree@cord_internal@absl@@CAPEAV012@Vstring_view@2@_K@Z
     ??$NewLeaf@$0A@@CordRepBtree@cord_internal@absl@@CAPEAV012@Vstring_view@2@_K@Z
     ??$ParseFloat@$09@strings_internal@absl@@YA?AUParsedFloat@01@PEBD0W4chars_format@1@@Z
@@ -465,7 +466,7 @@
     ?GetAppendBuffer@CordRepBtree@cord_internal@absl@@QEAA?AV?$Span@D@3@_K@Z
     ?GetAppendBuffer@CordRepRing@cord_internal@absl@@QEAA?AV?$Span@D@3@_K@Z
     ?GetAppendBufferSlow@CordRepBtree@cord_internal@absl@@AEAA?AV?$Span@D@3@_K@Z
-    ?GetAppendBufferSlowPath@Cord@absl@@AEAA?AVCordBuffer@2@_K0@Z
+    ?GetAppendBufferSlowPath@Cord@absl@@AEAA?AVCordBuffer@2@_K00@Z
     ?GetCachedTID@base_internal@absl@@YAIXZ
     ?GetCharacter@CordRepBtree@cord_internal@absl@@QEBAD_K@Z
     ?GetCharacter@CordRepRing@cord_internal@absl@@QEBAD_K@Z
diff --git a/third_party/abseil-cpp/symbols_x64_rel_asan.def b/third_party/abseil-cpp/symbols_x64_rel_asan.def
index 0feb0b2..283f463 100644
--- a/third_party/abseil-cpp/symbols_x64_rel_asan.def
+++ b/third_party/abseil-cpp/symbols_x64_rel_asan.def
@@ -62,6 +62,7 @@
     ??$Merge@$00@CordRepBtree@cord_internal@absl@@CAPEAV012@PEAV012@0@Z
     ??$Merge@$0A@@CordRepBtree@cord_internal@absl@@CAPEAV012@PEAV012@0@Z
     ??$NewImpl@$0BAAA@$$V@CordRepFlat@cord_internal@absl@@SAPEAU012@_K@Z
+    ??$NewImpl@$0EAAAA@$$V@CordRepFlat@cord_internal@absl@@SAPEAU012@_K@Z
     ??$NewLeaf@$00@CordRepBtree@cord_internal@absl@@CAPEAV012@Vstring_view@2@_K@Z
     ??$NewLeaf@$0A@@CordRepBtree@cord_internal@absl@@CAPEAV012@Vstring_view@2@_K@Z
     ??$ParseFloat@$09@strings_internal@absl@@YA?AUParsedFloat@01@PEBD0W4chars_format@1@@Z
@@ -467,7 +468,7 @@
     ?GetAppendBuffer@CordRepBtree@cord_internal@absl@@QEAA?AV?$Span@D@3@_K@Z
     ?GetAppendBuffer@CordRepRing@cord_internal@absl@@QEAA?AV?$Span@D@3@_K@Z
     ?GetAppendBufferSlow@CordRepBtree@cord_internal@absl@@AEAA?AV?$Span@D@3@_K@Z
-    ?GetAppendBufferSlowPath@Cord@absl@@AEAA?AVCordBuffer@2@_K0@Z
+    ?GetAppendBufferSlowPath@Cord@absl@@AEAA?AVCordBuffer@2@_K00@Z
     ?GetCachedTID@base_internal@absl@@YAIXZ
     ?GetCharacter@CordRepBtree@cord_internal@absl@@QEBAD_K@Z
     ?GetCharacter@CordRepRing@cord_internal@absl@@QEBAD_K@Z
diff --git a/third_party/abseil-cpp/symbols_x86_dbg.def b/third_party/abseil-cpp/symbols_x86_dbg.def
index c19bb5e8..c73b9378 100644
--- a/third_party/abseil-cpp/symbols_x86_dbg.def
+++ b/third_party/abseil-cpp/symbols_x86_dbg.def
@@ -144,9 +144,9 @@
     ??$?0Uyear_tag@time_internal@absl@@@?$civil_time@Uminute_tag@time_internal@absl@@@detail@cctz@time_internal@absl@@QAE@ABV?$civil_time@Uyear_tag@time_internal@absl@@@1234@PAX@Z
     ??$?0Uyear_tag@time_internal@absl@@@?$civil_time@Umonth_tag@time_internal@absl@@@detail@cctz@time_internal@absl@@QAE@ABV?$civil_time@Uyear_tag@time_internal@absl@@@1234@PAX@Z
     ??$?0Uyear_tag@time_internal@absl@@@?$civil_time@Usecond_tag@time_internal@absl@@@detail@cctz@time_internal@absl@@QAE@ABV?$civil_time@Uyear_tag@time_internal@absl@@@1234@PAX@Z
-    ??$?0V?$Span@I@absl@@XV01@@?$Span@$$CBI@absl@@QAE@ABV?$Span@I@1@@Z
-    ??$?0V?$Span@I@absl@@XV01@@?$Span@I@absl@@QAE@AAV01@@Z
-    ??$?0V?$Span@VFormatArgImpl@str_format_internal@absl@@@absl@@XV01@@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QAE@ABV?$Span@VFormatArgImpl@str_format_internal@absl@@@1@@Z
+    ??$?0V?$Span@I@absl@@XV01@$0A@@?$Span@$$CBI@absl@@QAE@ABV?$Span@I@1@@Z
+    ??$?0V?$Span@I@absl@@XV01@$0A@@?$Span@I@absl@@QAE@AAV01@@Z
+    ??$?0V?$Span@VFormatArgImpl@str_format_internal@absl@@@absl@@XV01@$0A@@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QAE@ABV?$Span@VFormatArgImpl@str_format_internal@absl@@@1@@Z
     ??$?0V?$__allocator_destructor@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@@Cr@std@@X@?$__compressed_pair_elem@V?$__allocator_destructor@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@@Cr@std@@$00$0A@@Cr@std@@QAE@$$QAV?$__allocator_destructor@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@@12@@Z
     ??$?0V?$__hash_iterator@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PAX@Cr@std@@@Cr@std@@AA_N$0A@@?$pair@V?$__hash_iterator@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PAX@Cr@std@@@Cr@std@@_N@Cr@std@@QAE@$$QAV?$__hash_iterator@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PAX@Cr@std@@@12@AA_N@Z
     ??$?0V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PAX@Cr@std@@@Cr@std@@@Cr@std@@X@?$__compressed_pair_elem@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PAX@Cr@std@@@Cr@std@@@Cr@std@@$00$0A@@Cr@std@@QAE@$$QAV?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@PAX@Cr@std@@@Cr@std@@@12@@Z
@@ -164,7 +164,7 @@
     ??$?0V?$basic_ostream@DU?$char_traits@D@Cr@std@@@Cr@std@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QAE@PAV?$basic_ostream@DU?$char_traits@D@Cr@std@@@Cr@std@@@Z
     ??$?0V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@$0A@@Cord@absl@@QAE@$$QAV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@@Z
     ??$?0V?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QAE@PAV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@@Z
-    ??$?0V?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@Cr@std@@@Cr@std@@XV012@@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QAE@ABV?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@Cr@std@@@Cr@std@@@Z
+    ??$?0V?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@Cr@std@@@Cr@std@@XV012@H@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QAE@ABV?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@Cr@std@@@Cr@std@@@Z
     ??$?0VBufferRawSink@str_format_internal@absl@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QAE@PAVBufferRawSink@12@@Z
     ??$?0VFILERawSink@str_format_internal@absl@@$0A@@FormatRawSinkImpl@str_format_internal@absl@@QAE@PAVFILERawSink@12@@Z
     ??$?8PAPAVCordzHandle@cord_internal@absl@@@Cr@std@@YA_NABV?$__wrap_iter@PAPAVCordzHandle@cord_internal@absl@@@01@0@Z
@@ -251,6 +251,7 @@
     ??$ConstructElements@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@V?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@PBUPayload@status_internal@absl@@@inlined_vector_internal@absl@@@inlined_vector_internal@absl@@YAXAAV?$allocator@UPayload@status_internal@absl@@@Cr@std@@PAUPayload@status_internal@1@AAV?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@PBUPayload@status_internal@absl@@@01@I@Z
     ??$ConstructElements@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@V?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@V?$move_iterator@PAUPayload@status_internal@absl@@@23@@inlined_vector_internal@absl@@@inlined_vector_internal@absl@@YAXAAV?$allocator@UPayload@status_internal@absl@@@Cr@std@@PAUPayload@status_internal@1@AAV?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@V?$move_iterator@PAUPayload@status_internal@absl@@@23@@01@I@Z
     ??$Convert@VFormatArgImpl@str_format_internal@absl@@@FormatArgImplFriend@str_format_internal@absl@@SA_NVFormatArgImpl@12@VFormatConversionSpecImpl@12@PAVFormatSinkImpl@12@@Z
+    ??$CreateWithCustomLimitImpl@$$V@CordBuffer@absl@@CA?AV01@II@Z
     ??$Dispatch@C@FormatArgImpl@str_format_internal@absl@@CA_NTData@012@VFormatConversionSpecImpl@12@PAX@Z
     ??$Dispatch@D@FormatArgImpl@str_format_internal@absl@@CA_NTData@012@VFormatConversionSpecImpl@12@PAX@Z
     ??$Dispatch@E@FormatArgImpl@str_format_internal@absl@@CA_NTData@012@VFormatConversionSpecImpl@12@PAX@Z
@@ -355,6 +356,7 @@
     ??$Nanoseconds@J$0A@@absl@@YA?AVDuration@0@J@Z
     ??$Nanoseconds@_J$0A@@absl@@YA?AVDuration@0@_J@Z
     ??$NewImpl@$0BAAA@$$V@CordRepFlat@cord_internal@absl@@SAPAU012@I@Z
+    ??$NewImpl@$0EAAAA@$$V@CordRepFlat@cord_internal@absl@@SAPAU012@I@Z
     ??$NewLeaf@$00@CordRepBtree@cord_internal@absl@@CAPAV012@Vstring_view@2@I@Z
     ??$NewLeaf@$0A@@CordRepBtree@cord_internal@absl@@CAPAV012@Vstring_view@2@I@Z
     ??$Offset@$00$0A@@?$LayoutImpl@V?$tuple@IPAUCordRep@cord_internal@absl@@I@Cr@std@@U?$integer_sequence@I$0A@$00$01@absl@@U45@@internal_layout@container_internal@absl@@QBEIXZ
@@ -660,6 +662,7 @@
     ??$get@$0A@Vstring_view@absl@@V12@@Cr@std@@YAABVstring_view@absl@@ABU?$pair@Vstring_view@absl@@V12@@01@@Z
     ??$get@Vstring_view@absl@@V12@@?$__get_pair@$00@Cr@std@@SAABVstring_view@absl@@ABU?$pair@Vstring_view@absl@@V12@@12@@Z
     ??$get@Vstring_view@absl@@V12@@?$__get_pair@$0A@@Cr@std@@SAABVstring_view@absl@@ABU?$pair@Vstring_view@absl@@V12@@12@@Z
+    ??$has_single_bit@I@absl@@YA_NI@Z
     ??$launder@$$CBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@@Cr@std@@YAPBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@01@PBU201@@Z
     ??$launder@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@Cr@std@@@Cr@std@@YAPAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@Cr@std@@V?$allocator@D@23@@Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@01@PAU201@@Z
     ??$lower_bound@PBUTransition@cctz@time_internal@absl@@U1234@UByUnixTime@1234@@Cr@std@@YAPBUTransition@cctz@time_internal@absl@@PBU2345@0ABU2345@UByUnixTime@2345@@Z
@@ -1538,6 +1541,7 @@
     ?CreateSlow@CordRepBtree@cord_internal@absl@@CAPAV123@PAUCordRep@23@@Z
     ?CreateSlow@CordRepRing@cord_internal@absl@@CAPAV123@PAUCordRep@23@I@Z
     ?CreateThreadIdentity@synchronization_internal@absl@@YAPAUThreadIdentity@base_internal@2@XZ
+    ?CreateWithCustomLimit@CordBuffer@absl@@SA?AV12@II@Z
     ?CreateWithDefaultLimit@CordBuffer@absl@@SA?AV12@I@Z
     ?Current@CordRepBtreeNavigator@cord_internal@absl@@QBEPAUCordRep@23@XZ
     ?CurrentThreadIdentityIfPresent@base_internal@absl@@YAPAUThreadIdentity@12@XZ
@@ -1771,7 +1775,7 @@
     ?GetAppendBuffer@CordRepBtree@cord_internal@absl@@QAE?AV?$Span@D@3@I@Z
     ?GetAppendBuffer@CordRepRing@cord_internal@absl@@QAE?AV?$Span@D@3@I@Z
     ?GetAppendBufferSlow@CordRepBtree@cord_internal@absl@@AAE?AV?$Span@D@3@I@Z
-    ?GetAppendBufferSlowPath@Cord@absl@@AAE?AVCordBuffer@2@II@Z
+    ?GetAppendBufferSlowPath@Cord@absl@@AAE?AVCordBuffer@2@III@Z
     ?GetCachedTID@base_internal@absl@@YAIXZ
     ?GetCapacity@?$AllocationTransaction@V?$allocator@PAUCordRep@cord_internal@absl@@@Cr@std@@@inlined_vector_internal@absl@@QAEAAIXZ
     ?GetCapacity@?$AllocationTransaction@V?$allocator@UPayload@status_internal@absl@@@Cr@std@@@inlined_vector_internal@absl@@QAEAAIXZ
@@ -1923,6 +1927,7 @@
     ?IsOne@RefcountAndFlags@cord_internal@absl@@QAE_NXZ
     ?IsOutOfRange@absl@@YA_NABVStatus@1@@Z
     ?IsPermissionDenied@absl@@YA_NABVStatus@1@@Z
+    ?IsPow2@CordBuffer@absl@@CA_NI@Z
     ?IsReachable@GraphCycles@synchronization_internal@absl@@QBE_NUGraphId@23@0@Z
     ?IsResourceExhausted@absl@@YA_NABVStatus@1@@Z
     ?IsRing@CordRep@cord_internal@absl@@QBE_NXZ
@@ -1958,6 +1963,8 @@
     ?LockWhen@Mutex@absl@@QAEXABVCondition@2@@Z
     ?LockWhenWithDeadline@Mutex@absl@@QAE_NABVCondition@2@VTime@2@@Z
     ?LockWhenWithTimeout@Mutex@absl@@QAE_NABVCondition@2@VDuration@2@@Z
+    ?Log2Ceil@CordBuffer@absl@@CAII@Z
+    ?Log2Floor@CordBuffer@absl@@CAII@Z
     ?LogFatalNodeType@cord_internal@absl@@YAXPAUCordRep@12@@Z
     ?LogSeverityName@absl@@YAPBDW4LogSeverity@1@@Z
     ?LossyAdd@CordzUpdateTracker@cord_internal@absl@@QAEXABV123@@Z
@@ -2011,6 +2018,7 @@
     ?New@CordRepBtree@cord_internal@absl@@SAPAV123@PAV123@0@Z
     ?New@CordRepCrc@cord_internal@absl@@SAPAU123@PAUCordRep@23@I@Z
     ?New@CordRepFlat@cord_internal@absl@@SAPAU123@I@Z
+    ?New@CordRepFlat@cord_internal@absl@@SAPAU123@ULarge@123@I@Z
     ?New@CordRepRing@cord_internal@absl@@CAPAV123@II@Z
     ?NewArena@LowLevelAlloc@base_internal@absl@@SAPAUArena@123@H@Z
     ?Next@CordRepBtreeNavigator@cord_internal@absl@@QAEPAUCordRep@23@XZ
diff --git a/third_party/abseil-cpp/symbols_x86_rel.def b/third_party/abseil-cpp/symbols_x86_rel.def
index 434e479a..588b493 100644
--- a/third_party/abseil-cpp/symbols_x86_rel.def
+++ b/third_party/abseil-cpp/symbols_x86_rel.def
@@ -63,6 +63,7 @@
     ??$Merge@$00@CordRepBtree@cord_internal@absl@@CAPAV012@PAV012@0@Z
     ??$Merge@$0A@@CordRepBtree@cord_internal@absl@@CAPAV012@PAV012@0@Z
     ??$NewImpl@$0BAAA@$$V@CordRepFlat@cord_internal@absl@@SAPAU012@I@Z
+    ??$NewImpl@$0EAAAA@$$V@CordRepFlat@cord_internal@absl@@SAPAU012@I@Z
     ??$NewLeaf@$00@CordRepBtree@cord_internal@absl@@CAPAV012@Vstring_view@2@I@Z
     ??$NewLeaf@$0A@@CordRepBtree@cord_internal@absl@@CAPAV012@Vstring_view@2@I@Z
     ??$ParseFloat@$09@strings_internal@absl@@YA?AUParsedFloat@01@PBD0W4chars_format@1@@Z
@@ -465,7 +466,7 @@
     ?GetAppendBuffer@CordRepBtree@cord_internal@absl@@QAE?AV?$Span@D@3@I@Z
     ?GetAppendBuffer@CordRepRing@cord_internal@absl@@QAE?AV?$Span@D@3@I@Z
     ?GetAppendBufferSlow@CordRepBtree@cord_internal@absl@@AAE?AV?$Span@D@3@I@Z
-    ?GetAppendBufferSlowPath@Cord@absl@@AAE?AVCordBuffer@2@II@Z
+    ?GetAppendBufferSlowPath@Cord@absl@@AAE?AVCordBuffer@2@III@Z
     ?GetCachedTID@base_internal@absl@@YAIXZ
     ?GetCharacter@CordRepBtree@cord_internal@absl@@QBEDI@Z
     ?GetCharacter@CordRepRing@cord_internal@absl@@QBEDI@Z
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index e59a7ee0..cd037ca 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -1352,7 +1352,7 @@
 
 // Allow use of a named meta tag to set and delegate client hints.
 const base::Feature kClientHintsMetaNameAcceptCH{
-    "ClientHintsMetaNameAcceptCH", base::FEATURE_ENABLED_BY_DEFAULT};
+    "ClientHintsMetaNameAcceptCH", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Allow use of a http-equiv meta tag to set and delegate client hints.
 const base::Feature kClientHintsMetaEquivDelegateCH{
diff --git a/third_party/blink/common/origin_trials/manual_completion_origin_trial_features.cc b/third_party/blink/common/origin_trials/manual_completion_origin_trial_features.cc
index 3b97f78..9e67858d 100644
--- a/third_party/blink/common/origin_trials/manual_completion_origin_trial_features.cc
+++ b/third_party/blink/common/origin_trials/manual_completion_origin_trial_features.cc
@@ -20,6 +20,7 @@
       // as a manual completion features, for tests.
       OriginTrialFeature::kOriginTrialsSampleAPIExpiryGracePeriod,
       OriginTrialFeature::kOriginTrialsSampleAPIExpiryGracePeriodThirdParty,
+      OriginTrialFeature::kOriginTrialsSampleAPIPersistentExpiryGracePeriod,
   };
   return base::Contains(kHasExpiryGracePeriod, feature);
 }
diff --git a/third_party/blink/common/origin_trials/persistent_origin_trials.cc b/third_party/blink/common/origin_trials/persistent_origin_trials.cc
index 3ff2851..b6f859a 100644
--- a/third_party/blink/common/origin_trials/persistent_origin_trials.cc
+++ b/third_party/blink/common/origin_trials/persistent_origin_trials.cc
@@ -15,8 +15,10 @@
 
 bool IsTrialPersistentToNextResponse(base::StringPiece trial_name) {
   static base::StringPiece const kPersistentTrials[] = {
-      // Enable the FrobulatePersistent trial as a persistent trial for tests.
+      // Enable the FrobulatePersistent* trials as a persistent trials for
+      // tests.
       "FrobulatePersistent",
+      "FrobulatePersistentExpiryGracePeriod",
   };
   return base::Contains(kPersistentTrials, trial_name);
 }
diff --git a/third_party/blink/common/origin_trials/trial_token_validator.cc b/third_party/blink/common/origin_trials/trial_token_validator.cc
index 45311f3..ff1276bd 100644
--- a/third_party/blink/common/origin_trials/trial_token_validator.cc
+++ b/third_party/blink/common/origin_trials/trial_token_validator.cc
@@ -57,6 +57,61 @@
   return status;
 }
 
+// Determine if the the |token_expiry_time| should be considered as expired
+// at |current_time| given the |trial_name|.
+// Manual completion trials add an expiry grace period, which has to be taken
+// into account to answer this question.
+bool IsTokenExpired(const base::StringPiece trial_name,
+                    const base::Time token_expiry_time,
+                    const base::Time current_time) {
+  // Check token expiry.
+  bool token_expired = token_expiry_time <= current_time;
+  if (token_expired) {
+    if (origin_trials::IsTrialValid(trial_name)) {
+      // Manual completion trials have an expiry grace period. For these trials
+      // the token expiry time is valid if:
+      // token_expiry_time + kExpiryGracePeriod > current_time
+      for (OriginTrialFeature feature :
+           origin_trials::FeaturesForTrial(trial_name)) {
+        if (origin_trials::FeatureHasExpiryGracePeriod(feature)) {
+          if (token_expiry_time + kExpiryGracePeriod > current_time) {
+            token_expired = false;  // consider the token non-expired
+            break;
+          }
+        }
+      }
+    }
+  }
+  return token_expired;
+}
+
+// Validate that the passed token has not yet expired and that the trial or
+// token has not been disabled.
+OriginTrialTokenStatus ValidateTokenEnabled(
+    const OriginTrialPolicy& policy,
+    const base::StringPiece trial_name,
+    const base::Time token_expiry_time,
+    const TrialToken::UsageRestriction usage_restriction,
+    const base::StringPiece token_signature,
+    const base::Time current_time) {
+  if (IsTokenExpired(trial_name, token_expiry_time, current_time))
+    return OriginTrialTokenStatus::kExpired;
+
+  if (policy.IsFeatureDisabled(trial_name))
+    return OriginTrialTokenStatus::kFeatureDisabled;
+
+  if (policy.IsTokenDisabled(token_signature))
+    return OriginTrialTokenStatus::kTokenDisabled;
+
+  if (usage_restriction == TrialToken::UsageRestriction::kSubset &&
+      policy.IsFeatureDisabledForUser(trial_name)) {
+    return OriginTrialTokenStatus::kFeatureDisabledForUser;
+  }
+
+  // All checks passed, return success
+  return OriginTrialTokenStatus::kSuccess;
+}
+
 }  // namespace
 
 TrialTokenValidator::OriginInfo::OriginInfo(const url::Origin& wrapped_origin)
@@ -222,49 +277,38 @@
   status =
       IsTokenValid(*trial_token, origin, third_party_origins, current_time);
 
-  if (status == OriginTrialTokenStatus::kExpired) {
-    if (origin_trials::IsTrialValid(trial_token->feature_name())) {
-      base::Time validated_time = current_time;
-      // Manual completion trials have an expiry grace period. For these trials
-      // the token expiry time is valid if:
-      // token.expiry_time + kExpiryGracePeriod > current_time
-      for (OriginTrialFeature feature :
-           origin_trials::FeaturesForTrial(trial_token->feature_name())) {
-        if (origin_trials::FeatureHasExpiryGracePeriod(feature)) {
-          validated_time = current_time - kExpiryGracePeriod;
-          status = IsTokenValid(*trial_token, origin, third_party_origins,
-                                validated_time);
-          if (status == OriginTrialTokenStatus::kSuccess) {
-            break;
-          }
-        }
-      }
-    }
+  if (status == OriginTrialTokenStatus::kSuccess ||
+      status == OriginTrialTokenStatus::kExpired) {
+    // Since manual completion trials have a grace period, we need to check
+    // expired tokens in addition to valid tokens.
+    status = ValidateTokenEnabled(*policy, trial_token->feature_name(),
+                                  trial_token->expiry_time(),
+                                  trial_token->usage_restriction(),
+                                  trial_token->signature(), current_time);
   }
-
-  if (status != OriginTrialTokenStatus::kSuccess)
-    return TrialTokenResult(status, std::move(trial_token));
-
-  if (policy->IsFeatureDisabled(trial_token->feature_name())) {
-    return TrialTokenResult(OriginTrialTokenStatus::kFeatureDisabled,
-                            std::move(trial_token));
-  }
-
-  if (policy->IsTokenDisabled(trial_token->signature())) {
-    return TrialTokenResult(OriginTrialTokenStatus::kTokenDisabled,
-                            std::move(trial_token));
-  }
-
-  if (trial_token->usage_restriction() ==
-          TrialToken::UsageRestriction::kSubset &&
-      policy->IsFeatureDisabledForUser(trial_token->feature_name())) {
-    return TrialTokenResult(OriginTrialTokenStatus::kFeatureDisabledForUser,
-                            std::move(trial_token));
-  }
-
   return TrialTokenResult(status, std::move(trial_token));
 }
 
+bool TrialTokenValidator::RevalidateTokenAndTrial(
+    const base::StringPiece trial_name,
+    const base::Time token_expiry_time,
+    const TrialToken::UsageRestriction usage_restriction,
+    const base::StringPiece token_signature,
+    const base::Time current_time) const {
+  OriginTrialPolicy* policy = PolicyGetter().Run();
+
+  if (!policy || !policy->IsOriginTrialsSupported())
+    return false;
+
+  if (!origin_trials::IsTrialValid(trial_name))
+    return false;
+
+  OriginTrialTokenStatus status =
+      ValidateTokenEnabled(*policy, trial_name, token_expiry_time,
+                           usage_restriction, token_signature, current_time);
+  return status == OriginTrialTokenStatus::kSuccess;
+}
+
 bool TrialTokenValidator::RequestEnablesFeature(const net::URLRequest* request,
                                                 base::StringPiece feature_name,
                                                 base::Time current_time) const {
diff --git a/third_party/blink/common/origin_trials/trial_token_validator_unittest.cc b/third_party/blink/common/origin_trials/trial_token_validator_unittest.cc
index 5c886cd..4e74c02 100644
--- a/third_party/blink/common/origin_trials/trial_token_validator_unittest.cc
+++ b/third_party/blink/common/origin_trials/trial_token_validator_unittest.cc
@@ -95,6 +95,7 @@
 const char kAppropriateFeatureName[] = "Frobulate";
 const char kAppropriateThirdPartyFeatureName[] = "FrobulateThirdParty";
 const char kAppropriateDeprecationFeatureName[] = "FrobulateDeprecation";
+const char kAppropriateGracePeriodFeatureName[] = "FrobulateExpiryGracePeriod";
 
 const char kInappropriateFeatureName[] = "Grokalyze";
 const char kInappropriateOrigin[] = "https://invalid.example.com";
@@ -1124,7 +1125,7 @@
   EXPECT_EQ(kSampleTokenExpiryTime, result.ParsedToken()->expiry_time());
 }
 
-// Finally: Tests that only check the behaviour of
+// Tests that only check the behaviour of
 // |ValidateTokenAndTrialWithOriginInfo| - these are the ones
 // that rely on changes in passing in specific OriginInfo
 
@@ -1189,4 +1190,68 @@
   EXPECT_EQ(kSampleTokenExpiryTime, result.ParsedToken()->expiry_time());
 }
 
+//
+// Tests of |RevalidateTokenAndTrial|
+//
+TEST_F(TrialTokenValidatorTest, RevalidateTokenInformation) {
+  EXPECT_TRUE(validator_.RevalidateTokenAndTrial(
+      kAppropriateFeatureName, kSampleTokenExpiryTime,
+      blink::TrialToken::UsageRestriction::kNone, valid_token_signature_,
+      Now()));
+}
+
+TEST_F(TrialTokenValidatorTest, RevalidateExpiredToken) {
+  // Check basic expiration. The expiry must be > the current time
+  base::Time expiry = Now();
+
+  EXPECT_FALSE(validator_.RevalidateTokenAndTrial(
+      kAppropriateFeatureName, expiry,
+      blink::TrialToken::UsageRestriction::kNone, valid_token_signature_,
+      Now()));
+
+  // Check grace period expiration
+  EXPECT_TRUE(validator_.RevalidateTokenAndTrial(
+      kAppropriateGracePeriodFeatureName, expiry,
+      blink::TrialToken::UsageRestriction::kNone, valid_token_signature_,
+      Now()));
+
+  // Check the boundary of the grace period.
+  expiry = Now() - kExpiryGracePeriod;
+  EXPECT_FALSE(validator_.RevalidateTokenAndTrial(
+      kAppropriateGracePeriodFeatureName, expiry,
+      blink::TrialToken::UsageRestriction::kNone, valid_token_signature_,
+      Now()));
+}
+
+TEST_F(TrialTokenValidatorTest, RevalidateDisabledTrial) {
+  policy_.DisableFeature(kAppropriateFeatureName);
+  EXPECT_FALSE(validator_.RevalidateTokenAndTrial(
+      kAppropriateFeatureName, kSampleTokenExpiryTime,
+      blink::TrialToken::UsageRestriction::kNone, valid_token_signature_,
+      Now()));
+}
+
+TEST_F(TrialTokenValidatorTest, RevalidateDisabledToken) {
+  policy_.DisableToken(valid_token_signature_);
+  EXPECT_FALSE(validator_.RevalidateTokenAndTrial(
+      kAppropriateFeatureName, kSampleTokenExpiryTime,
+      blink::TrialToken::UsageRestriction::kNone, valid_token_signature_,
+      Now()));
+}
+
+TEST_F(TrialTokenValidatorTest, RevalidateDisabledTrialForUser) {
+  policy_.DisableFeatureForUser(kAppropriateThirdPartyFeatureName);
+  // Per-user disabled trials should only be disabled if the token is marked as
+  // kSubset
+  EXPECT_TRUE(validator_.RevalidateTokenAndTrial(
+      kAppropriateThirdPartyFeatureName, kSampleTokenExpiryTime,
+      blink::TrialToken::UsageRestriction::kNone, valid_token_signature_,
+      Now()));
+
+  EXPECT_FALSE(validator_.RevalidateTokenAndTrial(
+      kAppropriateThirdPartyFeatureName, kSampleTokenExpiryTime,
+      blink::TrialToken::UsageRestriction::kSubset, valid_token_signature_,
+      Now()));
+}
+
 }  // namespace blink::trial_token_validator_unittest
diff --git a/third_party/blink/common/privacy_budget/BUILD.gn b/third_party/blink/common/privacy_budget/BUILD.gn
index 35d2a792..f17219ea 100644
--- a/third_party/blink/common/privacy_budget/BUILD.gn
+++ b/third_party/blink/common/privacy_budget/BUILD.gn
@@ -14,6 +14,7 @@
   configs += [ "//third_party/blink/common:blink_common_implementation" ]
 
   sources = [
+    "active_sampling.cc",
     "aggregating_sample_collector.cc",
     "aggregating_sample_collector.h",
     "identifiability_metric_builder.cc",
@@ -30,6 +31,7 @@
     "//services/metrics/public/cpp:metrics_cpp",
     "//services/metrics/public/cpp:ukm_builders",
     "//services/metrics/public/mojom",
+    "//skia",
     "//third_party/blink/public/common:common_export",
     "//third_party/blink/public/common/privacy_budget:privacy_budget",
     "//third_party/blink/public/mojom:web_feature_mojo_bindings",
@@ -40,6 +42,7 @@
   testonly = true
 
   sources = [
+    "active_sampling_unittest.cc",
     "aggregating_sample_collector_unittest.cc",
     "identifiability_internal_templates_unittest.cc",
     "identifiability_metric_builder_unittest.cc",
diff --git a/third_party/blink/common/privacy_budget/active_sampling.cc b/third_party/blink/common/privacy_budget/active_sampling.cc
new file mode 100644
index 0000000..4533da6
--- /dev/null
+++ b/third_party/blink/common/privacy_budget/active_sampling.cc
@@ -0,0 +1,75 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/privacy_budget/active_sampling.h"
+
+#include "base/i18n/case_conversion.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_restrictions.h"
+#include "build/build_config.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
+#include "third_party/blink/public/common/privacy_budget/identifiability_sample_collector.h"
+#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
+#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
+#include "third_party/blink/public/common/privacy_budget/identifiable_token.h"
+#include "third_party/skia/include/core/SkFontMgr.h"
+#include "third_party/skia/include/core/SkTypeface.h"
+
+namespace blink {
+
+// static
+bool IdentifiabilityActiveSampler::IsFontFamilyAvailable(const char* family,
+                                                         SkFontMgr* fm) {
+  base::ScopedAllowBaseSyncPrimitives allow;
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+  return !!fm->legacyMakeTypeface(family, SkFontStyle());
+#else
+  sk_sp<SkFontStyleSet> set(fm->matchFamily(family));
+  return set && set->count();
+#endif
+}
+
+// static
+void IdentifiabilityActiveSampler::ReportAvailableFontFamilies(
+    std::vector<std::string> fonts_to_check,
+    ukm::UkmRecorder* ukm_recorder) {
+  sk_sp<SkFontMgr> fontManager(SkFontMgr::RefDefault());
+  ukm::SourceId ukm_source_id = ukm::NoURLSourceId();
+  blink::IdentifiabilityMetricBuilder builder(ukm_source_id);
+  for (const std::string& font : fonts_to_check) {
+    bool is_available = IsFontFamilyAvailable(font.c_str(), fontManager.get());
+
+    // Compute a case-insensitive (in a unicode-compatible way) hash for the
+    // surface key.
+    blink::IdentifiableToken font_family_name_token(
+        base::UTF16ToUTF8(base::i18n::FoldCase(base::UTF8ToUTF16(font))));
+    builder.Add(blink::IdentifiableSurface::FromTypeAndToken(
+                    blink::IdentifiableSurface::Type::kFontFamilyAvailable,
+                    font_family_name_token),
+                is_available);
+  }
+  builder.Record(ukm_recorder);
+  blink::IdentifiabilitySampleCollector::Get()->FlushSource(ukm_recorder,
+                                                            ukm_source_id);
+}
+
+// static
+void IdentifiabilityActiveSampler::ActivelySampleAvailableFonts(
+    ukm::UkmRecorder* recorder) {
+  if (!blink::IdentifiabilityStudySettings::Get()->ShouldActivelySample())
+    return;
+
+  std::vector<std::string> font_families =
+      blink::IdentifiabilityStudySettings::Get()
+          ->FontFamiliesToActivelySample();
+
+  if (font_families.empty())
+    return;
+
+  ReportAvailableFontFamilies(font_families, recorder);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/common/privacy_budget/active_sampling_unittest.cc b/third_party/blink/common/privacy_budget/active_sampling_unittest.cc
new file mode 100644
index 0000000..5a15d22
--- /dev/null
+++ b/third_party/blink/common/privacy_budget/active_sampling_unittest.cc
@@ -0,0 +1,75 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/privacy_budget/active_sampling.h"
+
+#include "base/test/task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/common/privacy_budget/test_ukm_recorder.h"
+#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
+
+namespace blink {
+
+namespace {
+
+class ScopedIdentifiabilityStudySettings {
+ public:
+  class TestProvider : public IdentifiabilityStudySettingsProvider {
+   public:
+    bool IsActive() const override { return true; }
+
+    bool IsAnyTypeOrSurfaceBlocked() const override { return false; }
+
+    bool IsSurfaceAllowed(IdentifiableSurface surface) const override {
+      return true;
+    }
+
+    bool IsTypeAllowed(IdentifiableSurface::Type type) const override {
+      return true;
+    }
+
+    bool ShouldActivelySample() const override { return true; }
+
+    std::vector<std::string> FontFamiliesToActivelySample() const override {
+      return {"Arial", "Helvetica"};
+    }
+  };
+
+  ScopedIdentifiabilityStudySettings() {
+    // Reload the config in the global study settings.
+    blink::IdentifiabilityStudySettings::SetGlobalProvider(
+        std::make_unique<TestProvider>());
+  }
+
+  ~ScopedIdentifiabilityStudySettings() {
+    blink::IdentifiabilityStudySettings::ResetStateForTesting();
+  }
+};
+
+}  // namespace
+
+TEST(PrivacyBudgetActiveSamplingTest, ActivelySampleFonts) {
+  base::test::TaskEnvironment task_environment_;
+  ScopedIdentifiabilityStudySettings scoped_settings;
+
+  base::RunLoop run_loop;
+  test::TestUkmRecorder ukm_recorder;
+  IdentifiabilityActiveSampler::ActivelySampleAvailableFonts(&ukm_recorder);
+
+  const std::vector<ukm::mojom::UkmEntryPtr>& entries = ukm_recorder.entries();
+
+  std::vector<uint64_t> reported_surface_keys;
+  for (const auto& entry : entries) {
+    for (const auto& metric : entry->metrics) {
+      reported_surface_keys.push_back(metric.first);
+    }
+  }
+  EXPECT_EQ(reported_surface_keys,
+            std::vector<uint64_t>({
+                9223784233214641190u,   // Arial
+                10735872651981970214u,  // Helvetica
+            }));
+}
+
+}  // namespace blink
diff --git a/third_party/blink/common/privacy_budget/identifiability_study_settings.cc b/third_party/blink/common/privacy_budget/identifiability_study_settings.cc
index 12ac0fbf..7b493bec 100644
--- a/third_party/blink/common/privacy_budget/identifiability_study_settings.cc
+++ b/third_party/blink/common/privacy_budget/identifiability_study_settings.cc
@@ -151,4 +151,9 @@
   return provider_->ShouldActivelySample();
 }
 
+std::vector<std::string>
+IdentifiabilityStudySettings::FontFamiliesToActivelySample() const {
+  return provider_->FontFamiliesToActivelySample();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/public/common/origin_trials/trial_token_validator.h b/third_party/blink/public/common/origin_trials/trial_token_validator.h
index e713065..54aaea7 100644
--- a/third_party/blink/public/common/origin_trials/trial_token_validator.h
+++ b/third_party/blink/public/common/origin_trials/trial_token_validator.h
@@ -14,6 +14,7 @@
 #include "base/strings/string_piece.h"
 #include "base/time/time.h"
 #include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/common/origin_trials/trial_token.h"
 #include "url/origin.h"
 
 namespace net {
@@ -111,6 +112,18 @@
       base::span<const url::Origin> third_party_origins,
       base::Time current_time) const;
 
+  // Re-validate that |trial_name| is still enabled given the token information.
+  // The token from which the information was obtained should previously have
+  // been validated with either |ValidateToken| or |ValidateTokenAndTrial|, to
+  // ensure that it was a valid token for the origin to which we are applying
+  // it.
+  virtual bool RevalidateTokenAndTrial(
+      const base::StringPiece trial_name,
+      const base::Time token_expiry_time,
+      const TrialToken::UsageRestriction token_usage_restriction,
+      const base::StringPiece token_signature,
+      const base::Time current_time) const;
+
   // |request| must not be nullptr.
   // NOTE: This is not currently used, but remains here for future trials.
   bool RequestEnablesFeature(const net::URLRequest* request,
diff --git a/third_party/blink/public/common/privacy_budget/BUILD.gn b/third_party/blink/public/common/privacy_budget/BUILD.gn
index 1e0d6ea..b6ba497 100644
--- a/third_party/blink/public/common/privacy_budget/BUILD.gn
+++ b/third_party/blink/public/common/privacy_budget/BUILD.gn
@@ -15,6 +15,7 @@
 
 source_set("privacy_budget") {
   sources = [
+    "active_sampling.h",
     "identifiability_metric_builder.h",
     "identifiability_metrics.h",
     "identifiability_sample_collector.h",
diff --git a/third_party/blink/public/common/privacy_budget/active_sampling.h b/third_party/blink/public/common/privacy_budget/active_sampling.h
new file mode 100644
index 0000000..258add9e
--- /dev/null
+++ b/third_party/blink/public/common/privacy_budget/active_sampling.h
@@ -0,0 +1,41 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_ACTIVE_SAMPLING_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_ACTIVE_SAMPLING_H_
+
+#include <string>
+#include <vector>
+
+#include "third_party/blink/public/common/common_export.h"
+
+class SkFontMgr;
+
+namespace ukm {
+class UkmRecorder;
+}  // namespace ukm
+
+namespace blink {
+
+class BLINK_COMMON_EXPORT IdentifiabilityActiveSampler {
+ public:
+  // This class should not be instantiated. It is just a wrapper for a static
+  // method, which needed to be put inside a class in order to become friend of
+  // `base::ScopedAllowBaseSyncPrimitives`.
+  IdentifiabilityActiveSampler() = delete;
+
+  // Check and report availability of a set of fonts.
+  static void ActivelySampleAvailableFonts(ukm::UkmRecorder* recorder);
+
+ private:
+  static bool IsFontFamilyAvailable(const char* family, SkFontMgr* fm);
+
+  static void ReportAvailableFontFamilies(
+      std::vector<std::string> fonts_to_check,
+      ukm::UkmRecorder* ukm_recorder);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_ACTIVE_SAMPLING_H_
diff --git a/third_party/blink/public/common/privacy_budget/identifiability_study_settings.h b/third_party/blink/public/common/privacy_budget/identifiability_study_settings.h
index 7a796b8..7e285268 100644
--- a/third_party/blink/public/common/privacy_budget/identifiability_study_settings.h
+++ b/third_party/blink/public/common/privacy_budget/identifiability_study_settings.h
@@ -85,6 +85,9 @@
   // Returns true if surfaces should be actively sampled.
   bool ShouldActivelySample() const;
 
+  // Returns the font families which should be actively sampled.
+  std::vector<std::string> FontFamiliesToActivelySample() const;
+
   // Only used for testing. Resets internal state and violates API contracts
   // made above about the lifetime of IdentifiabilityStudySettings*.
   static void ResetStateForTesting();
diff --git a/third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h b/third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h
index fd8105f..f226a56 100644
--- a/third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h
+++ b/third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h
@@ -38,6 +38,11 @@
 
   // Returns true if surfaces should be actively sampled.
   virtual bool ShouldActivelySample() const = 0;
+
+  // Returns the list of font families which should be actively sampled.
+  virtual std::vector<std::string> FontFamiliesToActivelySample() const {
+    return std::vector<std::string>();
+  };
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/bindings/IDLExtendedAttributes.md b/third_party/blink/renderer/bindings/IDLExtendedAttributes.md
index 99bfc83..be2da88 100644
--- a/third_party/blink/renderer/bindings/IDLExtendedAttributes.md
+++ b/third_party/blink/renderer/bindings/IDLExtendedAttributes.md
@@ -1650,6 +1650,12 @@
 
 These extended attributes are _discouraged_ - they are not deprecated, but they should be avoided and removed if possible.
 
+### [BufferSourceTypeNoSizeLimit] _(t)_
+
+Summary: The byte length of buffer source types is currently restricted to be under 2 GB (exactly speaking, it must be less than the max size of a direct mapped memory of PartitionAlloc, which is a little less than 2 GB).  This extended attribute removes this limitation.
+
+Consult with the bindings team before you use this extended attribute.
+
 ### [DoNotCheckConstants] _(i)_
 
 Summary: `[DoNotCheckConstants]` indicates that constant values in an IDL file can be different from constant values in Blink implementation.
diff --git a/third_party/blink/renderer/bindings/core/v8/idl_types.h b/third_party/blink/renderer/bindings/core/v8/idl_types.h
index 5114baa3..49fe57df 100644
--- a/third_party/blink/renderer/bindings/core/v8/idl_types.h
+++ b/third_party/blink/renderer/bindings/core/v8/idl_types.h
@@ -236,6 +236,10 @@
     : public IDLBaseHelper<EventListener*> {};
 struct IDLOnErrorEventHandler final : public IDLBaseHelper<EventListener*> {};
 
+// [BufferSourceTypeNoSizeLimit]
+template <typename T>
+struct IDLBufferSourceTypeNoSizeLimit {};
+
 // IDL optional types
 //
 // IDLOptional represents an optional argument and supports a conversion from
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py b/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py
index f6ad5db..d976445a 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py
@@ -420,9 +420,15 @@
             idl_type.type_name_with_extended_attribute_key_values)
 
     if real_type.is_array_buffer:
+        if "BufferSourceTypeNoSizeLimit" in real_type.effective_annotations:
+            return "IDLBufferSourceTypeNoSizeLimit<{}>".format(
+                blink_type_info(real_type).typename)
         return blink_type_info(real_type).typename
 
     if real_type.is_buffer_source_type:
+        if "BufferSourceTypeNoSizeLimit" in real_type.effective_annotations:
+            return "IDLBufferSourceTypeNoSizeLimit<{}>".format(
+                blink_type_info(real_type).value_t)
         return blink_type_info(real_type).value_t
 
     if real_type.is_symbol:
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
index 0a81c617..48eddb4 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -6763,10 +6763,11 @@
     assert function_name == "IsExposed"
     class_like = cg_context.class_like
 
-    is_exposed_decl = CxxFuncDeclNode(name=function_name,
-                                      arg_decls=["ExecutionContext*"],
-                                      return_type="bool",
-                                      static=True)
+    is_exposed_decl = CxxFuncDeclNode(
+        name=function_name,
+        arg_decls=["ExecutionContext* execution_context"],
+        return_type="bool",
+        static=True)
     is_exposed_decl.accumulate(
         CodeGenAccumulator.require_class_decls(["ExecutionContext"]))
 
@@ -6775,12 +6776,20 @@
         arg_decls=["ExecutionContext* execution_context"],
         return_type="bool",
         class_name=cg_context.class_name)
-    is_exposed_def.accumulate(
-        CodeGenAccumulator.require_include_headers([
-            "third_party/blink/renderer/core/execution_context/execution_context.h"
-        ]))
-    is_exposed_def.body.add_template_vars(
-        {"execution_context": "execution_context"})
+
+    def define_execution_context(symbol_node):
+        # execution_context doesn't really need a definition because it's a
+        # function argument, but needs to require ".../execution_context.h".
+        node = SymbolDefinitionNode(symbol_node)
+        node.accumulate(
+            CodeGenAccumulator.require_include_headers([
+                "third_party/blink/renderer/core/execution_context/execution_context.h"
+            ]))
+        return node
+
+    is_exposed_def.body.register_code_symbol(
+        SymbolNode("execution_context",
+                   definition_constructor=define_execution_context))
     bind_installer_local_vars(is_exposed_def.body, cg_context)
     # If [Exposed] exists at all, then this exposure condition should be valid.
     # Otherwise, it is not an exposed interface at all.
diff --git a/third_party/blink/renderer/bindings/scripts/validator/rules/rules_extended_attributes.py b/third_party/blink/renderer/bindings/scripts/validator/rules/rules_extended_attributes.py
index a9b388f..fb5f062c 100644
--- a/third_party/blink/renderer/bindings/scripts/validator/rules/rules_extended_attributes.py
+++ b/third_party/blink/renderer/bindings/scripts/validator/rules/rules_extended_attributes.py
@@ -19,6 +19,7 @@
     "LegacyNullToEmptyString",
 ]
 _blink_specific_extended_attributes_applicable_to_types = [
+    "BufferSourceTypeNoSizeLimit",
     "FlexibleArrayBufferView",
     "StringContext",
     # "TreatNullAs" is the old version of "LegacyNullToEmptyString".
diff --git a/third_party/blink/renderer/core/dom/scripted_animation_controller.cc b/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
index 1d6d131..a9472a4 100644
--- a/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
+++ b/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
@@ -91,7 +91,6 @@
 
 void ScriptedAnimationController::ScheduleVideoFrameCallbacksExecution(
     ExecuteVfcCallback execute_vfc_callback) {
-  DCHECK(RuntimeEnabledFeatures::RequestVideoFrameCallbackEnabled());
   vfc_execution_queue_.push_back(std::move(execute_vfc_callback));
   ScheduleAnimationIfNeeded();
 }
@@ -255,11 +254,9 @@
   // steps for that Document, passing in now as the timestamp.
   RunTasks();
 
-  if (RuntimeEnabledFeatures::RequestVideoFrameCallbackEnabled()) {
-    // Run the fulfilled HTMLVideoELement.requestVideoFrameCallback() callbacks.
-    // See https://wicg.github.io/video-rvfc/.
-    ExecuteVideoFrameCallbacks();
-  }
+  // Run the fulfilled HTMLVideoELement.requestVideoFrameCallback() callbacks.
+  // See https://wicg.github.io/video-rvfc/.
+  ExecuteVideoFrameCallbacks();
 
   // 10.11. For each fully active Document in docs, run the animation
   // frame callbacks for that Document, passing in now as the timestamp.
diff --git a/third_party/blink/renderer/core/fragment_directive/same_block_word_iterator.cc b/third_party/blink/renderer/core/fragment_directive/same_block_word_iterator.cc
index 021fc1c..9f251b2a 100644
--- a/third_party/blink/renderer/core/fragment_directive/same_block_word_iterator.cc
+++ b/third_party/blink/renderer/core/fragment_directive/same_block_word_iterator.cc
@@ -74,6 +74,9 @@
 template <typename Direction>
 Node* SameBlockWordIterator<Direction>::NextVisibleTextNodeWithinBlock(
     Node& start_node) {
+  if (!start_node.GetLayoutObject())
+    return nullptr;
+
   // Move forward/backward until no next/previous node is available within same
   // |block_ancestor|.
   Node* node = &start_node;
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_finder_test.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_finder_test.cc
index f8b5f4c..2ef340f1 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_finder_test.cc
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_finder_test.cc
@@ -6,6 +6,9 @@
 #include "third_party/blink/renderer/core/testing/sim/sim_request.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_test.h"
 
+using testing::_;
+using testing::Mock;
+
 namespace blink {
 
 class MockTextFragmentFinder : public TextFragmentFinder {
@@ -20,21 +23,21 @@
   void GoToStep(SelectorMatchStep step) override { step_ = step; }
 };
 
-class TextFragmentFinderTest : public SimTest,
-                               public TextFragmentFinder::Client {
+class MockTextFragmentFinderClient : public TextFragmentFinder::Client {
+ public:
+  MOCK_METHOD(void,
+              DidFindMatch,
+              (const RangeInFlatTree& match, bool is_unique),
+              (override));
+  MOCK_METHOD(void, NoMatchFound, (), (override));
+};
+
+class TextFragmentFinderTest : public SimTest {
  public:
   void SetUp() override {
     SimTest::SetUp();
     WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600));
   }
-
-  void NoMatchFound() override { no_match_called_ = true; }
-
-  void DidFindMatch(const RangeInFlatTree& match, bool is_unique) override {}
-  bool IsNoMatchFoundCalled() { return no_match_called_; }
-
- private:
-  bool no_match_called_ = false;
 };
 
 // Tests that Find tasks will fail gracefully when DOM mutations invalidate the
@@ -52,23 +55,35 @@
                                 "First paragraph", "", "button text",
                                 "prefix to unique");
 
+  MockTextFragmentFinderClient client;
+
   MockTextFragmentFinder* finder = MakeGarbageCollected<MockTextFragmentFinder>(
-      *this, selector, &GetDocument(),
+      client, selector, &GetDocument(),
       TextFragmentFinder::FindBufferRunnerType::kSynchronous);
-  finder->FindMatch();
+  EXPECT_CALL(client, DidFindMatch(_, _)).Times(0);
 
-  finder->FindPrefix();
-  EXPECT_EQ(false, IsNoMatchFoundCalled());
+  {
+    EXPECT_CALL(client, NoMatchFound()).Times(0);
+    finder->FindMatch();
+    finder->FindPrefix();
+    Mock::VerifyAndClearExpectations(&client);
+  }
 
-  finder->FindTextStart();
-  EXPECT_EQ(false, IsNoMatchFoundCalled());
+  {
+    EXPECT_CALL(client, NoMatchFound()).Times(0);
+    finder->FindTextStart();
+    Mock::VerifyAndClearExpectations(&client);
+  }
 
-  Node* input = GetDocument().getElementById("input");
-  input->remove();
-  GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest);
+  {
+    EXPECT_CALL(client, NoMatchFound()).Times(1);
+    Node* input = GetDocument().getElementById("input");
+    input->remove();
+    GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest);
 
-  finder->FindSuffix();
-  EXPECT_EQ(true, IsNoMatchFoundCalled());
+    finder->FindSuffix();
+    Mock::VerifyAndClearExpectations(&client);
+  }
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.cc
index e1f3749..a2c31af97 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.cc
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.cc
@@ -193,6 +193,9 @@
 
 void TextFragmentSelectorGenerator::DidFindMatch(const RangeInFlatTree& match,
                                                  bool is_unique) {
+  if (did_find_match_callback_for_testing_)
+    std::move(did_find_match_callback_for_testing_).Run(is_unique);
+
   if (is_unique &&
       PlainText(match.ToEphemeralRange()).StripWhiteSpace().length() ==
           PlainText(range_->ToEphemeralRange()).StripWhiteSpace().length()) {
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.h b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.h
index 8bfa937..7873a59 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.h
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.h
@@ -103,17 +103,18 @@
                            GetNextTextStartPosition_NoNextNode);
   FRIEND_TEST_ALL_PREFIXES(TextFragmentSelectorGeneratorTest,
                            ExactTextSelector_Long);
-
   FRIEND_TEST_ALL_PREFIXES(
       TextFragmentSelectorGeneratorTest,
       GetPreviousTextEndPosition_ShouldSkipNodesWithNoLayoutObject);
+  FRIEND_TEST_ALL_PREFIXES(TextFragmentSelectorGeneratorTest,
+                           RemoveLayoutObjectAsync);
 
   // Used for determining the next step of selector generation.
   enum GenerationStep { kExact, kRange, kContext };
 
   // Used for determining the current state of |selector_|.
   enum SelectorState {
-    // Sreach for candidate selector didn't start.
+    // Search for candidate selector didn't start.
     kNotStarted,
 
     // Candidate selector should be generated or extended.
@@ -181,6 +182,10 @@
 
   GenerateCallback pending_generate_selector_callback_;
 
+  // Callback invoked each time DidFindMatch is called; for testing only.
+  // Allows inserting code to run between asynchronous generation steps.
+  base::OnceCallback<void(bool is_unique)> did_find_match_callback_for_testing_;
+
   GenerationStep step_ = kExact;
   SelectorState state_ = kNeedsNewCandidate;
 
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator_test.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator_test.cc
index 40a25b1..0b63df0 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator_test.cc
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator_test.cc
@@ -98,18 +98,17 @@
     };
     auto callback =
         WTF::Bind(lambda, std::ref(callback_called), std::ref(selector));
-    GetTextFragmentSelectorGenerator()->Generate(
-        *MakeGarbageCollected<RangeInFlatTree>(
-            ToPositionInFlatTree(selected_start),
-            ToPositionInFlatTree(selected_end)),
-        std::move(callback));
+    CreateGenerator()->Generate(*MakeGarbageCollected<RangeInFlatTree>(
+                                    ToPositionInFlatTree(selected_start),
+                                    ToPositionInFlatTree(selected_end)),
+                                std::move(callback));
     base::RunLoop().RunUntilIdle();
 
     EXPECT_TRUE(callback_called);
     return selector;
   }
 
-  TextFragmentSelectorGenerator* GetTextFragmentSelectorGenerator() {
+  TextFragmentSelectorGenerator* CreateGenerator() {
     return MakeGarbageCollected<TextFragmentSelectorGenerator>(
         GetDocument().GetFrame());
   }
@@ -1443,9 +1442,8 @@
   Node* first_paragraph = GetDocument().getElementById("first")->firstChild();
   const auto& expected_position =
       ToPositionInFlatTree(Position::LastPositionInNode(*first_paragraph));
-  EXPECT_EQ(
-      expected_position,
-      GetTextFragmentSelectorGenerator()->GetPreviousTextEndPosition(start));
+  EXPECT_EQ(expected_position,
+            CreateGenerator()->GetPreviousTextEndPosition(start));
 }
 
 // Check the case when available prefix is a text node outside of selection
@@ -1466,9 +1464,8 @@
   Node* node = GetDocument().getElementById("first")->previousSibling();
   const auto& expected_position =
       ToPositionInFlatTree(Position::LastPositionInNode(*node));
-  EXPECT_EQ(
-      expected_position,
-      GetTextFragmentSelectorGenerator()->GetPreviousTextEndPosition(start));
+  EXPECT_EQ(expected_position,
+            CreateGenerator()->GetPreviousTextEndPosition(start));
 }
 
 // Check the case when available prefix is a parent node text content outside of
@@ -1489,9 +1486,8 @@
   Node* node = GetDocument().getElementById("div")->firstChild();
   const auto& expected_position =
       ToPositionInFlatTree(Position::LastPositionInNode(*node));
-  EXPECT_EQ(
-      expected_position,
-      GetTextFragmentSelectorGenerator()->GetPreviousTextEndPosition(start));
+  EXPECT_EQ(expected_position,
+            CreateGenerator()->GetPreviousTextEndPosition(start));
 }
 
 // Check the case when previous node is used for available prefix when selection
@@ -1515,9 +1511,8 @@
   Node* node = GetDocument().getElementById("first")->firstChild();
   const auto& expected_position =
       ToPositionInFlatTree(Position::LastPositionInNode(*node));
-  EXPECT_EQ(
-      expected_position,
-      GetTextFragmentSelectorGenerator()->GetPreviousTextEndPosition(start));
+  EXPECT_EQ(expected_position,
+            CreateGenerator()->GetPreviousTextEndPosition(start));
 }
 
 // Check the case when previous node is used for available prefix when selection
@@ -1545,9 +1540,8 @@
   Node* node = GetDocument().getElementById("first")->firstChild();
   const auto& expected_position =
       ToPositionInFlatTree(Position::LastPositionInNode(*node));
-  EXPECT_EQ(
-      expected_position,
-      GetTextFragmentSelectorGenerator()->GetPreviousTextEndPosition(start));
+  EXPECT_EQ(expected_position,
+            CreateGenerator()->GetPreviousTextEndPosition(start));
 }
 
 // Check the case when available prefix complete text content of the previous
@@ -1566,9 +1560,8 @@
   ASSERT_EQ("First", PlainText(EphemeralRangeInFlatTree(start, end)));
 
   PositionInFlatTree expected_position;
-  EXPECT_EQ(
-      expected_position,
-      GetTextFragmentSelectorGenerator()->GetPreviousTextEndPosition(start));
+  EXPECT_EQ(expected_position,
+            CreateGenerator()->GetPreviousTextEndPosition(start));
 }
 
 // Similar test for suffix.
@@ -1593,7 +1586,7 @@
   const auto& expected_position =
       ToPositionInFlatTree(Position::FirstPositionInNode(*node));
   EXPECT_EQ(expected_position,
-            GetTextFragmentSelectorGenerator()->GetNextTextStartPosition(end));
+            CreateGenerator()->GetNextTextStartPosition(end));
 }
 
 // Check the case when there is a commented block between selection and the
@@ -1620,7 +1613,7 @@
   const auto& expected_position =
       ToPositionInFlatTree(Position::FirstPositionInNode(*node));
   EXPECT_EQ(expected_position,
-            GetTextFragmentSelectorGenerator()->GetNextTextStartPosition(end));
+            CreateGenerator()->GetNextTextStartPosition(end));
 }
 
 // Check the case when available suffix is a text node outside of selection
@@ -1643,7 +1636,7 @@
   const auto& expected_position =
       ToPositionInFlatTree(Position::FirstPositionInNode(*node));
   EXPECT_EQ(expected_position,
-            GetTextFragmentSelectorGenerator()->GetNextTextStartPosition(end));
+            CreateGenerator()->GetNextTextStartPosition(end));
 }
 
 // Check the case when available suffix is a parent node text content outside of
@@ -1665,7 +1658,7 @@
   const auto& expected_position =
       ToPositionInFlatTree(Position::FirstPositionInNode(*node));
   EXPECT_EQ(expected_position,
-            GetTextFragmentSelectorGenerator()->GetNextTextStartPosition(end));
+            CreateGenerator()->GetNextTextStartPosition(end));
 }
 
 // Check the case when next node is used for available suffix when selection is
@@ -1690,7 +1683,7 @@
   const auto& expected_position =
       ToPositionInFlatTree(Position::FirstPositionInNode(*node));
   EXPECT_EQ(expected_position,
-            GetTextFragmentSelectorGenerator()->GetNextTextStartPosition(end));
+            CreateGenerator()->GetNextTextStartPosition(end));
 }
 
 // Check the case when next node is used for available suffix when selection is
@@ -1718,7 +1711,7 @@
   const auto& expected_position =
       ToPositionInFlatTree(Position::FirstPositionInNode(*node));
   EXPECT_EQ(expected_position,
-            GetTextFragmentSelectorGenerator()->GetNextTextStartPosition(end));
+            CreateGenerator()->GetNextTextStartPosition(end));
 }
 
 // Check the case when available suffix is a text node outside of selection
@@ -1738,7 +1731,7 @@
 
   PositionInFlatTree expected_position;
   EXPECT_EQ(expected_position,
-            GetTextFragmentSelectorGenerator()->GetNextTextStartPosition(end));
+            CreateGenerator()->GetNextTextStartPosition(end));
 }
 
 TEST_F(TextFragmentSelectorGeneratorTest, BeforeAndAfterAnchor) {
@@ -1785,9 +1778,82 @@
   Node* node = shadow1.getElementById("p")->firstChild();
   const auto& expected_position =
       ToPositionInFlatTree(Position::LastPositionInNode(*node));
-  EXPECT_EQ(
-      expected_position,
-      GetTextFragmentSelectorGenerator()->GetPreviousTextEndPosition(start));
+  EXPECT_EQ(expected_position,
+            CreateGenerator()->GetPreviousTextEndPosition(start));
+}
+
+// Tests that the generator fails gracefully if the layout subtree is removed
+// while we're operating on it. Reproduction for https://crbug.com/1313253.
+TEST_F(TextFragmentSelectorGeneratorTest, RemoveLayoutObjectAsync) {
+  SimRequest request("https://example.com/test.html", "text/html");
+  LoadURL("https://example.com/test.html");
+
+  // This test case relies on the initial try of 'p p p-,Foo,-s s s' being
+  // non-unique. This forces the generator to try expanding the context after
+  // the initial asynchronous search finishes. Before that happens, the current
+  // node's LayoutObject is removed.
+  request.Complete(R"HTML(
+    <!DOCTYPE html>
+    <p>p p p p</p>
+    <p id='target'>Foo s s s p p p Foo s s s</p>
+    <p>More text to so context expansion doesn't abort due to reaching end</p>
+  )HTML");
+
+  // Select the first instance of "Foo"
+  Element* target = GetDocument().getElementById("target");
+
+  Node* text = target->firstChild();
+  const auto& selected_start = Position(text, 0);
+  const auto& selected_end = Position(text, 3);
+  ASSERT_EQ("Foo", PlainText(EphemeralRange(selected_start, selected_end)));
+
+  String selector;
+  bool finished = false;
+  auto lambda = [](bool& callback_called, String& selector,
+                   const TextFragmentSelector& generated_selector,
+                   shared_highlighting::LinkGenerationError error) {
+    selector = generated_selector.ToString();
+    callback_called = true;
+  };
+  auto callback = WTF::Bind(lambda, std::ref(finished), std::ref(selector));
+
+  TextFragmentSelectorGenerator* generator = CreateGenerator();
+  generator->Generate(*MakeGarbageCollected<RangeInFlatTree>(
+                          ToPositionInFlatTree(selected_start),
+                          ToPositionInFlatTree(selected_end)),
+                      std::move(callback));
+
+  // This test intends to test what happens when the layout tree is mutated
+  // while the generator is waiting for the next asynchronous step. Thus, the
+  // generator must still be running at this point for this test to be valid.
+  ASSERT_FALSE(finished);
+
+  // The TestCandidate state is the async break point in the generator, this
+  // will post a task in AsyncFindBuffer to perform the text search on the
+  // document. We'll mutate the layout tree while this task isn't run yet so
+  // that when it run and returns to the generator we ensure neither touches
+  // the removed layout tree.
+  EXPECT_EQ(generator->state_,
+            TextFragmentSelectorGenerator::SelectorState::kTestCandidate);
+
+  generator->did_find_match_callback_for_testing_ = WTF::Bind(
+      [](Element* target, bool is_unique) {
+        EXPECT_FALSE(is_unique);
+
+        // Set display:none should remove the layout object associated with the
+        // range the generator is currently targeting.
+        EXPECT_TRUE(target->GetLayoutObject());
+        target->setAttribute(html_names::kStyleAttr,
+                             AtomicString("display:none"));
+        target->GetDocument().UpdateStyleAndLayoutTree();
+        target->GetDocument().View()->UpdateStyleAndLayout();
+        EXPECT_FALSE(target->GetLayoutObject());
+      },
+      WrapWeakPersistent(target));
+
+  // Pump tasks to continue generator operation now.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(finished);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc
index 72d6dd0c..bf73639 100644
--- a/third_party/blink/renderer/core/html/media/html_video_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -727,17 +727,13 @@
 }
 
 void HTMLVideoElement::OnWebMediaPlayerCreated() {
-  if (RuntimeEnabledFeatures::RequestVideoFrameCallbackEnabled()) {
-    if (auto* vfc_requester = VideoFrameCallbackRequester::From(*this))
-      vfc_requester->OnWebMediaPlayerCreated();
-  }
+  if (auto* vfc_requester = VideoFrameCallbackRequester::From(*this))
+    vfc_requester->OnWebMediaPlayerCreated();
 }
 
 void HTMLVideoElement::OnWebMediaPlayerCleared() {
-  if (RuntimeEnabledFeatures::RequestVideoFrameCallbackEnabled()) {
-    if (auto* vfc_requester = VideoFrameCallbackRequester::From(*this))
-      vfc_requester->OnWebMediaPlayerCleared();
-  }
+  if (auto* vfc_requester = VideoFrameCallbackRequester::From(*this))
+    vfc_requester->OnWebMediaPlayerCleared();
 }
 
 void HTMLVideoElement::AttributeChanged(
@@ -748,7 +744,6 @@
 }
 
 void HTMLVideoElement::OnRequestVideoFrameCallback() {
-  DCHECK(RuntimeEnabledFeatures::RequestVideoFrameCallbackEnabled());
   VideoFrameCallbackRequester::From(*this)->OnRequestVideoFrameCallback();
 }
 
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
index 42468d1..c776f61 100644
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
@@ -1358,7 +1358,6 @@
 }
 
 void WebMediaPlayerMS::RequestVideoFrameCallback() {
-  DCHECK(RuntimeEnabledFeatures::RequestVideoFrameCallbackEnabled());
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   if (!compositor_) {
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc
index 9c9a4a84..be2dcf159 100644
--- a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc
+++ b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc
@@ -395,7 +395,6 @@
                                                const char* trace_event_name) {}
 
 void MockRTCPeerConnectionHandlerPlatform::TrackIceConnectionStateChange(
-    RTCPeerConnectionHandler::IceConnectionStateVersion version,
     webrtc::PeerConnectionInterface::IceConnectionState state) {}
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.h b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.h
index 45a0a07..f0c1e26c 100644
--- a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.h
+++ b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.h
@@ -133,8 +133,8 @@
       base::OnceClosure closure,
       const char* trace_event_name) override;
   void TrackIceConnectionStateChange(
-      RTCPeerConnectionHandler::IceConnectionStateVersion version,
       webrtc::PeerConnectionInterface::IceConnectionState state) override;
+
  private:
   class DummyRTCRtpTransceiverPlatform;
 
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
index 6c5cf70b..b676f1c 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
@@ -1040,18 +1040,6 @@
       webrtc::PeerConnectionInterface::AsString(state).data());
 }
 
-void PeerConnectionTracker::TrackLegacyIceConnectionStateChange(
-    RTCPeerConnectionHandler* pc_handler,
-    webrtc::PeerConnectionInterface::IceConnectionState state) {
-  DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
-  int id = GetLocalIDForHandler(pc_handler);
-  if (id == -1)
-    return;
-  SendPeerConnectionUpdate(
-      id, "iceconnectionstatechange (legacy)",
-      webrtc::PeerConnectionInterface::AsString(state).data());
-}
-
 void PeerConnectionTracker::TrackIceConnectionStateChange(
     RTCPeerConnectionHandler* pc_handler,
     webrtc::PeerConnectionInterface::IceConnectionState state) {
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h
index 3b3c847..6525a9a0 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h
@@ -191,19 +191,7 @@
       webrtc::PeerConnectionInterface::SignalingState state);
 
   // Sends an update when the ICE connection state of a PeerConnection has
-  // changed. There's a legacy and non-legacy version. The non-legacy version
-  // reflects the blink::RTCPeerConnection::iceConnectionState.
-  //
-  // "Legacy" usage: In Unifed Plan, TrackLegacyIceConnectionStateChange() is
-  // used to report the webrtc::PeerConnection layer implementation of the
-  // state, which might not always be the same as the
-  // blink::RTCPeerConnection::iceConnectionState reported with
-  // TrackIceConnectionStateChange(). In Plan B, the webrtc::PeerConnection
-  // layer implementation is the only iceConnectionState version, and
-  // TrackLegacyIceConnectionStateChange() is not applicable.
-  virtual void TrackLegacyIceConnectionStateChange(
-      RTCPeerConnectionHandler* pc_handler,
-      webrtc::PeerConnectionInterface::IceConnectionState state);
+  // changed.
   virtual void TrackIceConnectionStateChange(
       RTCPeerConnectionHandler* pc_handler,
       webrtc::PeerConnectionInterface::IceConnectionState state);
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
index a860da8..3043f76 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
@@ -1191,9 +1191,7 @@
   DCHECK_EQ(webrtc::SdpSemantics::kUnifiedPlan, sdp_semantics_);
   auto new_state = ComputeIceConnectionState();
   if (ice_connection_state_ != new_state) {
-    peer_handler_->TrackIceConnectionStateChange(
-        RTCPeerConnectionHandler::IceConnectionStateVersion::kDefault,
-        new_state);
+    peer_handler_->TrackIceConnectionStateChange(new_state);
   }
   ChangeIceConnectionState(new_state);
 }
@@ -2722,15 +2720,12 @@
   DCHECK(GetExecutionContext()->IsContextThread());
   if (sdp_semantics_ == webrtc::SdpSemantics::kUnifiedPlan) {
     // Unified plan relies on UpdateIceConnectionState() instead.
-    peer_handler_->TrackIceConnectionStateChange(
-        RTCPeerConnectionHandler::IceConnectionStateVersion::kLegacy,
-        new_state);
-  } else {
-    peer_handler_->TrackIceConnectionStateChange(
-        RTCPeerConnectionHandler::IceConnectionStateVersion::kDefault,
-        new_state);
-    ChangeIceConnectionState(new_state);
+    return;
   }
+  // Plan B only.
+  // TODO(https://crbug.com/1302249): Delete this.
+  peer_handler_->TrackIceConnectionStateChange(new_state);
+  ChangeIceConnectionState(new_state);
 }
 
 void RTCPeerConnection::DidChangePeerConnectionState(
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
index c8febca1..21199ba8 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
@@ -2334,20 +2334,11 @@
 }
 
 void RTCPeerConnectionHandler::TrackIceConnectionStateChange(
-    RTCPeerConnectionHandler::IceConnectionStateVersion version,
     webrtc::PeerConnectionInterface::IceConnectionState state) {
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
   if (!peer_connection_tracker_)
     return;
-  switch (version) {
-    case RTCPeerConnectionHandler::IceConnectionStateVersion::kLegacy:
-      peer_connection_tracker_->TrackLegacyIceConnectionStateChange(this,
-                                                                    state);
-      break;
-    case RTCPeerConnectionHandler::IceConnectionStateVersion::kDefault:
-      peer_connection_tracker_->TrackIceConnectionStateChange(this, state);
-      break;
-  }
+  peer_connection_tracker_->TrackIceConnectionStateChange(this, state);
 }
 
 // Called any time the combined peerconnection state changes
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h
index 86879dc..0c0f00c 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h
@@ -153,17 +153,6 @@
 // the main render thread.
 class MODULES_EXPORT RTCPeerConnectionHandler {
  public:
-  enum class IceConnectionStateVersion {
-    // Only applicable in Unified Plan when the JavaScript-exposed
-    // iceConnectionState is calculated in blink. In this case, kLegacy is used
-    // to report the webrtc::PeerConnectionInterface implementation which is not
-    // visible in JavaScript, but still useful to track for debugging purposes.
-    kLegacy,
-    // The JavaScript-visible iceConnectionState. In Plan B, this is the same as
-    // the webrtc::PeerConnectionInterface implementation.
-    kDefault,
-  };
-
   RTCPeerConnectionHandler(
       RTCPeerConnectionHandlerClient* client,
       blink::PeerConnectionDependencyFactory* dependency_factory,
@@ -245,7 +234,6 @@
       const char* trace_event_name);
 
   virtual void TrackIceConnectionStateChange(
-      RTCPeerConnectionHandler::IceConnectionStateVersion version,
       webrtc::PeerConnectionInterface::IceConnectionState state);
 
   // Delegate functions to allow for mocking of WebKit interfaces.
diff --git a/third_party/blink/renderer/modules/video_rvfc/html_video_element_request_video_frame_callback.idl b/third_party/blink/renderer/modules/video_rvfc/html_video_element_request_video_frame_callback.idl
index 65647d8..fa3c3cb 100644
--- a/third_party/blink/renderer/modules/video_rvfc/html_video_element_request_video_frame_callback.idl
+++ b/third_party/blink/renderer/modules/video_rvfc/html_video_element_request_video_frame_callback.idl
@@ -4,7 +4,6 @@
 
 // See https://wicg.github.io/video-rvfc/.
 [
-    RuntimeEnabled=RequestVideoFrameCallback,
     ImplementedAs=VideoFrameCallbackRequesterImpl
 ] partial interface HTMLVideoElement {
     [Measure] long requestVideoFrameCallback(VideoFrameRequestCallback callback);
diff --git a/third_party/blink/renderer/modules/video_rvfc/video_frame_callback_requester_impl.cc b/third_party/blink/renderer/modules/video_rvfc/video_frame_callback_requester_impl.cc
index 388d88d5..afbaaba 100644
--- a/third_party/blink/renderer/modules/video_rvfc/video_frame_callback_requester_impl.cc
+++ b/third_party/blink/renderer/modules/video_rvfc/video_frame_callback_requester_impl.cc
@@ -85,7 +85,6 @@
 }
 
 void VideoFrameCallbackRequesterImpl::OnWebMediaPlayerCreated() {
-  DCHECK(RuntimeEnabledFeatures::RequestVideoFrameCallbackEnabled());
   if (!callback_collection_->IsEmpty())
     GetSupplementable()->GetWebMediaPlayer()->RequestVideoFrameCallback();
 }
@@ -192,7 +191,6 @@
 }
 
 void VideoFrameCallbackRequesterImpl::OnRequestVideoFrameCallback() {
-  DCHECK(RuntimeEnabledFeatures::RequestVideoFrameCallbackEnabled());
   TRACE_EVENT1("blink",
                "VideoFrameCallbackRequesterImpl::OnRequestVideoFrameCallback",
                "has_callbacks", !callback_collection_->IsEmpty());
diff --git a/third_party/blink/renderer/modules/video_rvfc/video_frame_callback_requester_impl_test.cc b/third_party/blink/renderer/modules/video_rvfc/video_frame_callback_requester_impl_test.cc
index 78d7656b..94221bc 100644
--- a/third_party/blink/renderer/modules/video_rvfc/video_frame_callback_requester_impl_test.cc
+++ b/third_party/blink/renderer/modules/video_rvfc/video_frame_callback_requester_impl_test.cc
@@ -16,7 +16,6 @@
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/core/timing/performance.h"
 #include "third_party/blink/renderer/platform/testing/empty_web_media_player.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 
 using testing::_;
@@ -170,13 +169,8 @@
 
 }  // namespace
 
-class VideoFrameCallbackRequesterImplTest
-    : public PageTestBase,
-      private ScopedRequestVideoFrameCallbackForTest {
+class VideoFrameCallbackRequesterImplTest : public PageTestBase {
  public:
-  VideoFrameCallbackRequesterImplTest()
-      : ScopedRequestVideoFrameCallbackForTest(true) {}
-
   virtual void SetUpWebMediaPlayer() {
     auto mock_media_player = std::make_unique<MockWebMediaPlayer>();
     media_player_ = mock_media_player.get();
diff --git a/third_party/blink/renderer/modules/video_rvfc/video_frame_request_callback.idl b/third_party/blink/renderer/modules/video_rvfc/video_frame_request_callback.idl
index 0238764..8bae48c 100644
--- a/third_party/blink/renderer/modules/video_rvfc/video_frame_request_callback.idl
+++ b/third_party/blink/renderer/modules/video_rvfc/video_frame_request_callback.idl
@@ -4,5 +4,4 @@
 
 // See https://wicg.github.io/video-rvfc/.
 
-[RuntimeEnabled=RequestVideoFrameCallback]
 callback VideoFrameRequestCallback = void(DOMHighResTimeStamp time, VideoFrameMetadata metadata);
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 24c16f66..22adc8e9 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -373,7 +373,7 @@
     },
     {
       name: "ClientHintsMetaNameAcceptCH",
-      status: "stable",
+      status: "experimental",
     },
     {
       name: "ClientHintThirdPartyDelegation",
@@ -1339,6 +1339,7 @@
       // crbug.com/1335309
       name: "LayoutNGVTTCue",
       depends_on: ["LayoutNG"],
+      status: "experimental",
     },
     {
       name: "LazyFrameLoading",
@@ -1677,6 +1678,12 @@
     // As above. Do not change this flag to stable, as it exists solely to
     // generate code used by the origin trials sample API implementation.
     {
+      name: "OriginTrialsSampleAPIPersistentExpiryGracePeriod",
+      origin_trial_feature_name: "FrobulatePersistentExpiryGracePeriod",
+    },
+    // As above. Do not change this flag to stable, as it exists solely to
+    // generate code used by the origin trials sample API implementation.
+    {
       name: "OriginTrialsSampleAPIPersistentFeature",
       origin_trial_feature_name: "FrobulatePersistent",
     },
@@ -1943,11 +1950,6 @@
       name: "RenderPriorityAttribute"
     },
     {
-      // See https://crbug.com/1012063
-      name: "RequestVideoFrameCallback",
-      status: "stable",
-    },
-    {
       name: "RestrictBatteryStatusToSecureContexts",
       status: "stable",
     },
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index d9cc169..6559a00d 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -26,11 +26,6 @@
 external/wpt/infrastructure/reftest/reftest_multiple_mismatch-1.html [ Failure ]
 accessibility/slot-poison.html [ Failure ]
 
-# Temporarily disabled for a DevTools roll.
-crbug.com/1313690 http/tests/devtools/elements/iframe-load-event.js [ Failure Pass ]
-
-# Temporarily disabled for DevTools.
-
 # Expected to time out.
 external/wpt/infrastructure/expected-fail/timeout.html [ Timeout ]
 external/wpt/infrastructure/reftest/reftest_ref_timeout.html [ Timeout ]
diff --git a/third_party/blink/web_tests/platform/generic/media/track/track-cue-rendering-no-space-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/media/track/track-cue-rendering-no-space-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/generic/media/track/track-cue-rendering-no-space-expected.txt
rename to third_party/blink/web_tests/flag-specific/disable-layout-ng/media/track/track-cue-rendering-no-space-expected.txt
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/media/track/track-cue-rendering-ruby-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/media/track/track-cue-rendering-ruby-expected.png
new file mode 100644
index 0000000..ff15ffa
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/media/track/track-cue-rendering-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/media/track/track-cue-container-rendering-position.html b/third_party/blink/web_tests/media/track/track-cue-container-rendering-position.html
index d65b713..4af3f24 100644
--- a/third_party/blink/web_tests/media/track/track-cue-container-rendering-position.html
+++ b/third_party/blink/web_tests/media/track/track-cue-container-rendering-position.html
@@ -16,10 +16,13 @@
     var video = document.querySelector("video");
     video.src = "../content/test.ogv";
 
-    video.oncanplaythrough = t.step_func_done(function() {
+    video.oncanplaythrough = t.step_func(function() {
         var cueDisplayElement = textTrackDisplayElement(video);
-        document.body.offsetTop; // Force layout.
-        assert_true(cueDisplayElement.offsetTop > (video.videoHeight * 0.75));
+        requestAnimationFrame(t.step_func(() => {
+            requestAnimationFrame(t.step_func_done(() => {
+                assert_true(cueDisplayElement.offsetTop > (video.videoHeight * 0.75));
+            }));
+        }));
     });
 });
 </script>
diff --git a/third_party/blink/web_tests/media/track/track-cue-rendering-overscan.html b/third_party/blink/web_tests/media/track/track-cue-rendering-overscan.html
index 0b3bbbb..026b60c 100644
--- a/third_party/blink/web_tests/media/track/track-cue-rendering-overscan.html
+++ b/third_party/blink/web_tests/media/track/track-cue-rendering-overscan.html
@@ -29,9 +29,11 @@
         assert_equals(track.track.activeCues.length, 1, "activeCues.length");
         assert_equals(track.track.activeCues[0].text, expectedText, "activeCues[0].text");
         assert_equals(testCueDisplayBox.innerText, expectedText, "testCueDisplayBox.innerText");
-
-        marginAssertFunc(testCueDisplayBox, video);
-        t.done();
+        requestAnimationFrame(t.step_func(() => {
+          requestAnimationFrame(t.step_func_done(() => {
+            marginAssertFunc(testCueDisplayBox, video);
+          }));
+        }));
       });
     });
   };
diff --git a/third_party/blink/web_tests/platform/generic/http/tests/eventsource/eventsource-cors-non-http-expected.txt b/third_party/blink/web_tests/platform/generic/http/tests/eventsource/eventsource-cors-non-http-expected.txt
index c925fa85..07bb316 100644
--- a/third_party/blink/web_tests/platform/generic/http/tests/eventsource/eventsource-cors-non-http-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/http/tests/eventsource/eventsource-cors-non-http-expected.txt
@@ -1,7 +1,7 @@
 CONSOLE ERROR: Not allowed to load local resource: motd
-CONSOLE ERROR: Access to resource at 'ftp://127.0.0.1/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to resource at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to resource at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
+CONSOLE ERROR: Access to resource at 'ftp://127.0.0.1/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to resource at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to resource at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
 Test EventSource with non-HTTP protocol schemes in the URL.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/platform/generic/http/tests/eventsource/workers/eventsource-cors-non-http-expected.txt b/third_party/blink/web_tests/platform/generic/http/tests/eventsource/workers/eventsource-cors-non-http-expected.txt
index ac01e942..33b762a 100644
--- a/third_party/blink/web_tests/platform/generic/http/tests/eventsource/workers/eventsource-cors-non-http-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/http/tests/eventsource/workers/eventsource-cors-non-http-expected.txt
@@ -1,7 +1,7 @@
 CONSOLE ERROR: Not allowed to load local resource: motd
-CONSOLE ERROR: Access to resource at 'ftp://127.0.0.1/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to resource at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to resource at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
+CONSOLE ERROR: Access to resource at 'ftp://127.0.0.1/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to resource at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to resource at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
 [Worker] Test EventSource with non-HTTP protocol schemes in the URL.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/platform/generic/http/tests/xmlhttprequest/cross-origin-unsupported-url-expected.txt b/third_party/blink/web_tests/platform/generic/http/tests/xmlhttprequest/cross-origin-unsupported-url-expected.txt
index f4d7d32..688f10d9 100644
--- a/third_party/blink/web_tests/platform/generic/http/tests/xmlhttprequest/cross-origin-unsupported-url-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/http/tests/xmlhttprequest/cross-origin-unsupported-url-expected.txt
@@ -1,15 +1,15 @@
-CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
+CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
 This is a testharness.js-based test.
 PASS sync test for url=mailto:foo@bar.com, contentType=undefined
 PASS sync test for url=mailto:foo@bar.com, contentType=application/json
diff --git a/third_party/blink/web_tests/platform/generic/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt b/third_party/blink/web_tests/platform/generic/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt
index f4d7d32..688f10d9 100644
--- a/third_party/blink/web_tests/platform/generic/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt
@@ -1,15 +1,15 @@
-CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
-CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
+CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'mailto:foo@bar.com' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'localhost:8080/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
+CONSOLE ERROR: Access to XMLHttpRequest at 'tel:1234' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
 This is a testharness.js-based test.
 PASS sync test for url=mailto:foo@bar.com, contentType=undefined
 PASS sync test for url=mailto:foo@bar.com, contentType=application/json
diff --git a/third_party/blink/web_tests/platform/generic/mhtml/cid_in_html_resource-expected.txt b/third_party/blink/web_tests/platform/generic/mhtml/cid_in_html_resource-expected.txt
index 4813932..9ce2af1 100644
--- a/third_party/blink/web_tests/platform/generic/mhtml/cid_in_html_resource-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/mhtml/cid_in_html_resource-expected.txt
@@ -1,2 +1,2 @@
-CONSOLE ERROR: Access to font at 'cid:xxxxxx' from origin '' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https, isolated-app.
+CONSOLE ERROR: Access to font at 'cid:xxxxxx' from origin '' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.
 No Content-ID url are expected outside of an MHTML document. The document should load without crashing.
diff --git a/third_party/blink/web_tests/platform/linux/media/track/track-cue-rendering-ruby-expected.png b/third_party/blink/web_tests/platform/linux/media/track/track-cue-rendering-ruby-expected.png
index ff15ffa..2f0a1303 100644
--- a/third_party/blink/web_tests/platform/linux/media/track/track-cue-rendering-ruby-expected.png
+++ b/third_party/blink/web_tests/platform/linux/media/track/track-cue-rendering-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/media/track/track-cue-rendering-vertical-expected.png
new file mode 100644
index 0000000..abc2a805
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/media/track/track-cue-rendering-vertical-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/media/track/track-cue-rendering-vertical-expected.png
index 2c512591..abc2a805 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/media/track/track-cue-rendering-vertical-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/media/track/track-cue-rendering-vertical-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac10.15/media/track/track-cue-rendering-vertical-expected.png
new file mode 100644
index 0000000..cd31e60
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.15/media/track/track-cue-rendering-vertical-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/media/track/track-cue-rendering-vertical-expected.png
new file mode 100644
index 0000000..cd31e60
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/media/track/track-cue-rendering-vertical-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac11/media/track/track-cue-rendering-vertical-expected.png
new file mode 100644
index 0000000..cd31e60
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11/media/track/track-cue-rendering-vertical-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/media/track/track-cue-rendering-vertical-expected.png
new file mode 100644
index 0000000..cd31e60
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/media/track/track-cue-rendering-vertical-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/mac/media/track/track-cue-rendering-vertical-expected.png
index 68ca2ad..cd31e60 100644
--- a/third_party/blink/web_tests/platform/mac/media/track/track-cue-rendering-vertical-expected.png
+++ b/third_party/blink/web_tests/platform/mac/media/track/track-cue-rendering-vertical-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-ruby-expected.png b/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-ruby-expected.png
index 903c44f..d64f630 100644
--- a/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-ruby-expected.png
+++ b/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-vertical-expected.png
index 95899c7..5ed9d2b 100644
--- a/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-vertical-expected.png
+++ b/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-vertical-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/media/track/track-cue-rendering-ruby-expected.png b/third_party/blink/web_tests/platform/win10/media/track/track-cue-rendering-ruby-expected.png
new file mode 100644
index 0000000..903c44f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win10/media/track/track-cue-rendering-ruby-expected.png
Binary files differ
diff --git a/third_party/closure_compiler/externs/passwords_private.js b/third_party/closure_compiler/externs/passwords_private.js
index 924a990e..a22753ee 100644
--- a/third_party/closure_compiler/externs/passwords_private.js
+++ b/third_party/closure_compiler/externs/passwords_private.js
@@ -82,6 +82,7 @@
  *   federationText: (string|undefined),
  *   id: number,
  *   storedIn: !chrome.passwordsPrivate.PasswordStoreSet,
+ *   isAndroidCredential: boolean,
  *   passwordNote: string
  * }}
  */
diff --git a/third_party/webgpu-cts/ts_sources.txt b/third_party/webgpu-cts/ts_sources.txt
index 29fb607d..dc065fbc 100644
--- a/third_party/webgpu-cts/ts_sources.txt
+++ b/third_party/webgpu-cts/ts_sources.txt
@@ -240,6 +240,7 @@
 src/webgpu/api/validation/queue/buffer_mapped.spec.ts
 src/webgpu/api/validation/queue/submit.spec.ts
 src/webgpu/api/validation/queue/writeBuffer.spec.ts
+src/webgpu/api/validation/queue/writeTexture.spec.ts
 src/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture.spec.ts
 src/webgpu/api/validation/queue/destroyed/query_set.spec.ts
 src/webgpu/api/validation/render_pass/attachment_compatibility.spec.ts
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 06b157f..db672c33 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -61151,6 +61151,7 @@
   <int value="1541723759" label="ServiceWorkerNavigationPreload:disabled"/>
   <int value="1543027970" label="EnableDisplayZoomSetting:disabled"/>
   <int value="1543349770" label="CastUseBlocklistForRemotingQuery:disabled"/>
+  <int value="1544413751" label="PasswordStrengthIndicator:enabled"/>
   <int value="1546652609" label="SharingHubDesktopOmnibox:disabled"/>
   <int value="1548776701" label="AllBookmarks:disabled"/>
   <int value="1548942246" label="PassiveDocumentEventListeners:disabled"/>
@@ -61334,6 +61335,7 @@
   <int value="1670799163" label="ChromeHomeShowGoogleGWhenUrlCleared:enabled"/>
   <int value="1671021713" label="AutofillImportDynamicForms:disabled"/>
   <int value="1671985641" label="WebViewVulkan:enabled"/>
+  <int value="1672062546" label="PasswordStrengthIndicator:disabled"/>
   <int value="1673185316" label="EarlyCodeCache:enabled"/>
   <int value="1673427566" label="ChromeHomeExpandButton:disabled"/>
   <int value="1673776797"
@@ -92252,6 +92254,7 @@
   <int value="10" label="Duplicate client tag hashes exist"/>
   <int value="11" label="Managed bookmark has sync metadata"/>
   <int value="12" label="Entity missing client tag hash"/>
+  <int value="13" label="Entity missing favicon hash"/>
 </enum>
 
 <enum name="SyncBookmarkModelSyncState">
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index bfa6b37..c6cfa7a 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@
             "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "win": {
-            "hash": "9c7a24c9249a1d939eba719007fca355cd420dde",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/ac8e40ad9eda05b00c491201b9cffbeaad8f566e/trace_processor_shell.exe"
+            "hash": "9a349067848bbbc9c6c02c830de457c4eeaf7247",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/3101cf59da5f63e16cdccfc481064c229c2a4ceb/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893",
@@ -21,8 +21,8 @@
             "full_remote_path": "perfetto-luci-artifacts/v25.0/mac-arm64/trace_processor_shell"
         },
         "linux": {
-            "hash": "a9fae5de51e960b68b2cf86cf50049dd452c4b04",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/ac8e40ad9eda05b00c491201b9cffbeaad8f566e/trace_processor_shell"
+            "hash": "ac75be567c3531560e0b72f4e15081bf587e172d",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/c2235982559f7008e5384d5145e1febe571573cd/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/typescript/definitions/passwords_private.d.ts b/tools/typescript/definitions/passwords_private.d.ts
index 8fe89391..0684852 100644
--- a/tools/typescript/definitions/passwords_private.d.ts
+++ b/tools/typescript/definitions/passwords_private.d.ts
@@ -59,6 +59,7 @@
         federationText?: string;
         id: number;
         storedIn: PasswordStoreSet;
+        isAndroidCredential: boolean;
         passwordNote: string;
       }
 
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
index e2d2588..033dd9b 100644
--- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
@@ -1130,9 +1130,7 @@
 
   const AXNode* anchor = position->GetAnchor();
   DCHECK(anchor);
-  AXTreeID tree_id = anchor->tree()->GetAXTreeID();
-  const AXTreeManager* ax_tree_manager =
-      AXTreeManagerMap::GetInstance().GetManager(tree_id);
+  const AXTreeManager* ax_tree_manager = position->GetManager();
   DCHECK(ax_tree_manager);
 
   const AXPlatformTreeManager* platform_tree_manager =
diff --git a/ui/accessibility/platform/inspect/ax_transform_mac.mm b/ui/accessibility/platform/inspect/ax_transform_mac.mm
index 7cb34e1..0faa991 100644
--- a/ui/accessibility/platform/inspect/ax_transform_mac.mm
+++ b/ui/accessibility/platform/inspect/ax_transform_mac.mm
@@ -115,8 +115,8 @@
   if (position->IsNullPosition())
     return AXNilToBaseValue();
 
-  const AXPlatformTreeManager* manager = static_cast<AXPlatformTreeManager*>(
-      AXTreeManagerMap::GetInstance().GetManager(position->tree_id()));
+  const AXPlatformTreeManager* manager =
+      static_cast<AXPlatformTreeManager*>(position->GetManager());
   if (!manager)
     return AXNilToBaseValue();
 
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index 4349427..c7cf3c8 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -322,7 +322,6 @@
     "//mojo/core/embedder",
     "//skia",
     "//testing/gtest",
-    "//ui/aura/cursor:unittests",
     "//ui/aura_extra",
     "//ui/aura_extra:tests",
     "//ui/base:test_support",
diff --git a/ui/aura/cursor/BUILD.gn b/ui/aura/cursor/BUILD.gn
deleted file mode 100644
index 41b7004c..0000000
--- a/ui/aura/cursor/BUILD.gn
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-component("cursor") {
-  output_name = "ui_aura_cursor"
-  sources = [
-    "cursor_loader.cc",
-    "cursor_loader.h",
-    "cursor_lookup.cc",
-    "cursor_lookup.h",
-    "cursor_util.cc",
-    "cursor_util.h",
-    "cursors_aura.cc",
-    "cursors_aura.h",
-  ]
-  defines = [ "IS_UI_AURA_CURSOR_IMPL" ]
-  public_deps = [
-    "//base",
-    "//ui/base/cursor",
-    "//ui/base/cursor/mojom:cursor_type",
-    "//ui/display",
-  ]
-  deps = [
-    "//skia",
-    "//ui/base",
-    "//ui/gfx",
-    "//ui/gfx/geometry",
-    "//ui/resources:ui_resources_grd",
-  ]
-}
-
-source_set("unittests") {
-  testonly = true
-  sources = [
-    "cursor_loader_unittest.cc",
-    "cursor_util_unittest.cc",
-  ]
-  deps = [
-    ":cursor",
-    "//base",
-    "//skia",
-    "//testing/gtest",
-    "//ui/aura:test_support",
-    "//ui/base",
-    "//ui/base/cursor",
-    "//ui/base/cursor/mojom:cursor_type",
-    "//ui/gfx:gfx_skia",
-    "//ui/gfx/geometry",
-  ]
-  data_deps = [ "//ui/resources:ui_test_pak_data" ]
-}
diff --git a/ui/aura/cursor/DEPS b/ui/aura/cursor/DEPS
deleted file mode 100644
index 5ea09cfd..0000000
--- a/ui/aura/cursor/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+ui/resources",
-]
diff --git a/ui/aura/cursor/DIR_METADATA b/ui/aura/cursor/DIR_METADATA
deleted file mode 100644
index f343444..0000000
--- a/ui/aura/cursor/DIR_METADATA
+++ /dev/null
@@ -1,11 +0,0 @@
-# Metadata information for this directory.
-#
-# For more information on DIR_METADATA files, see:
-#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
-#
-# For the schema of this file, see Metadata message:
-#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
-
-monorail {
-  component: "Internals>Input"
-}
diff --git a/ui/aura/cursor/OWNERS b/ui/aura/cursor/OWNERS
deleted file mode 100644
index 229cc1a..0000000
--- a/ui/aura/cursor/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://ui/base/cursor/OWNERS
diff --git a/ui/base/cocoa/menu_controller.mm b/ui/base/cocoa/menu_controller.mm
index c299e6a..be5ee49d 100644
--- a/ui/base/cocoa/menu_controller.mm
+++ b/ui/base/cocoa/menu_controller.mm
@@ -35,8 +35,8 @@
 // Called when adding a submenu to the menu and checks if the submenu, via its
 // |model|, has visible child items.
 bool MenuHasVisibleItems(const ui::MenuModel* model) {
-  size_t count = model->GetItemCount();
-  for (size_t index = 0; index < count; ++index) {
+  int count = model->GetItemCount();
+  for (int index = 0; index < count; index++) {
     if (model->IsVisibleAt(index))
       return true;
   }
@@ -91,7 +91,7 @@
 // Adds the item at |index| in |model| as an NSMenuItem at |index| of |menu|.
 // Associates a submenu if the MenuModel::ItemType is TYPE_SUBMENU.
 - (void)addItemToMenu:(NSMenu*)menu
-              atIndex:(size_t)index
+              atIndex:(NSInteger)index
             fromModel:(ui::MenuModel*)model
     withColorProvider:(const ui::ColorProvider*)colorProvider;
 
@@ -184,8 +184,8 @@
        withColorProvider:(const ui::ColorProvider*)colorProvider {
   NSMenu* menu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
 
-  const size_t count = model->GetItemCount();
-  for (size_t index = 0; index < count; ++index) {
+  const int count = model->GetItemCount();
+  for (int index = 0; index < count; index++) {
     if (model->GetTypeAt(index) == ui::MenuModel::TYPE_SEPARATOR) {
       [self addSeparatorToMenu:menu atIndex:index];
     } else {
@@ -206,7 +206,7 @@
 }
 
 - (void)addItemToMenu:(NSMenu*)menu
-              atIndex:(size_t)index
+              atIndex:(NSInteger)index
             fromModel:(ui::MenuModel*)model
     withColorProvider:(const ui::ColorProvider*)colorProvider {
   NSString* label = l10n_util::FixUpWindowsStyleLabel(model->GetLabelAt(index));
diff --git a/ui/base/cocoa/menu_controller_unittest.mm b/ui/base/cocoa/menu_controller_unittest.mm
index 98e71a4..0a398630 100644
--- a/ui/base/cocoa/menu_controller_unittest.mm
+++ b/ui/base/cocoa/menu_controller_unittest.mm
@@ -61,14 +61,13 @@
       const TestSimpleMenuModelVisibility&) = delete;
 
   // SimpleMenuModel:
-  bool IsVisibleAt(size_t index) const override {
+  bool IsVisibleAt(int index) const override {
     return items_[ValidateItemIndex(index)].visible;
   }
 
   void SetVisibility(int command_id, bool visible) {
-    absl::optional<size_t> index =
-        SimpleMenuModel::GetIndexOfCommandId(command_id);
-    items_[ValidateItemIndex(index.value())].visible = visible;
+    int index = SimpleMenuModel::GetIndexOfCommandId(command_id);
+    items_[ValidateItemIndex(index)].visible = visible;
   }
 
   void AddItem(int command_id, const std::u16string& label) {
@@ -89,8 +88,9 @@
 
   typedef std::vector<Item> ItemVector;
 
-  int ValidateItemIndex(size_t index) const {
-    CHECK_LT(index, items_.size());
+  int ValidateItemIndex(int index) const {
+    CHECK_GE(index, 0);
+    CHECK_LT(static_cast<size_t>(index), items_.size());
     return index;
   }
 
@@ -215,16 +215,16 @@
  public:
   FontListMenuModel(SimpleMenuModel::Delegate* delegate,
                     const gfx::FontList* font_list,
-                    size_t index)
+                    int index)
       : SimpleMenuModel(delegate), font_list_(font_list), index_(index) {}
   ~FontListMenuModel() override {}
-  const gfx::FontList* GetLabelFontListAt(size_t index) const override {
+  const gfx::FontList* GetLabelFontListAt(int index) const override {
     return (index == index_) ? font_list_.get() : nullptr;
   }
 
  private:
   raw_ptr<const gfx::FontList> font_list_;
-  const size_t index_;
+  const int index_;
 };
 
 TEST_F(MenuControllerTest, EmptyMenu) {
diff --git a/ui/base/interaction/interaction_test_util_mac.mm b/ui/base/interaction/interaction_test_util_mac.mm
index b47f126..1076fec 100644
--- a/ui/base/interaction/interaction_test_util_mac.mm
+++ b/ui/base/interaction/interaction_test_util_mac.mm
@@ -44,7 +44,7 @@
   if (!model)
     return false;
 
-  for (size_t i = 0; i < model->GetItemCount(); ++i) {
+  for (int i = 0; i < model->GetItemCount(); ++i) {
     if (model->GetElementIdentifierAt(i) == element->identifier()) {
       NSMenuItem* item = [menu itemWithTag:i];
       if (item) {
diff --git a/ui/base/models/dialog_model_menu_model_adapter.cc b/ui/base/models/dialog_model_menu_model_adapter.cc
index aca67649..7e6abe62 100644
--- a/ui/base/models/dialog_model_menu_model_adapter.cc
+++ b/ui/base/models/dialog_model_menu_model_adapter.cc
@@ -36,38 +36,38 @@
   return false;
 }
 
-size_t DialogModelMenuModelAdapter::GetItemCount() const {
-  return model_->fields(GetPassKey()).size();
+int DialogModelMenuModelAdapter::GetItemCount() const {
+  return static_cast<int>(model_->fields(GetPassKey()).size());
 }
 
-MenuModel::ItemType DialogModelMenuModelAdapter::GetTypeAt(size_t index) const {
+MenuModel::ItemType DialogModelMenuModelAdapter::GetTypeAt(int index) const {
   return GetField(index)->type(GetPassKey()) == DialogModelField::kSeparator
              ? TYPE_SEPARATOR
              : TYPE_COMMAND;
 }
 
 MenuSeparatorType DialogModelMenuModelAdapter::GetSeparatorTypeAt(
-    size_t index) const {
+    int index) const {
   NOTREACHED();
   return MenuSeparatorType::NORMAL_SEPARATOR;
 }
 
-int DialogModelMenuModelAdapter::GetCommandIdAt(size_t index) const {
+int DialogModelMenuModelAdapter::GetCommandIdAt(int index) const {
   // TODO(pbos): Figure out what this should be. Combobox seems to offset by
   // 1000. Dunno why.
   return index + 1234;
 }
 
-std::u16string DialogModelMenuModelAdapter::GetLabelAt(size_t index) const {
+std::u16string DialogModelMenuModelAdapter::GetLabelAt(int index) const {
   return GetField(index)->AsMenuItem(GetPassKey())->label(GetPassKey());
 }
 
-bool DialogModelMenuModelAdapter::IsItemDynamicAt(size_t index) const {
+bool DialogModelMenuModelAdapter::IsItemDynamicAt(int index) const {
   return false;
 }
 
 bool DialogModelMenuModelAdapter::GetAcceleratorAt(
-    size_t index,
+    int index,
     ui::Accelerator* accelerator) const {
   // TODO(pbos): Add support for accelerators.
   return false;
@@ -78,52 +78,54 @@
   return false;
 }
 
-int DialogModelMenuModelAdapter::GetGroupIdAt(size_t index) const {
+int DialogModelMenuModelAdapter::GetGroupIdAt(int index) const {
   NOTREACHED();
   return -1;
 }
 
-ImageModel DialogModelMenuModelAdapter::GetIconAt(size_t index) const {
+ImageModel DialogModelMenuModelAdapter::GetIconAt(int index) const {
   return GetField(index)->AsMenuItem(GetPassKey())->icon(GetPassKey());
 }
 
 ButtonMenuItemModel* DialogModelMenuModelAdapter::GetButtonMenuItemAt(
-    size_t index) const {
+    int index) const {
   NOTREACHED();
   return nullptr;
 }
 
-bool DialogModelMenuModelAdapter::IsEnabledAt(size_t index) const {
+bool DialogModelMenuModelAdapter::IsEnabledAt(int index) const {
   DCHECK_LT(index, GetItemCount());
 
   const DialogModelField* const field = GetField(index);
-  return field->type(GetPassKey()) != DialogModelField::kSeparator &&
-         field->AsMenuItem(GetPassKey())->is_enabled(GetPassKey());
+  if (field->type(GetPassKey()) == DialogModelField::kSeparator)
+    return false;
+
+  return field->AsMenuItem(GetPassKey())->is_enabled(GetPassKey());
 }
 
-MenuModel* DialogModelMenuModelAdapter::GetSubmenuModelAt(size_t index) const {
+MenuModel* DialogModelMenuModelAdapter::GetSubmenuModelAt(int index) const {
   NOTREACHED();
   return nullptr;
 }
 
-void DialogModelMenuModelAdapter::ActivatedAt(size_t index) {
+void DialogModelMenuModelAdapter::ActivatedAt(int index) {
   // If this flags investigate why the ActivatedAt(index, event_flags) isn't
   // being called.
   NOTREACHED();
 }
 
-void DialogModelMenuModelAdapter::ActivatedAt(size_t index, int event_flags) {
+void DialogModelMenuModelAdapter::ActivatedAt(int index, int event_flags) {
   DialogModelMenuItem* menu_item = GetField(index)->AsMenuItem(GetPassKey());
   menu_item->OnActivated(GetPassKey(), event_flags);
 }
 
-const DialogModelField* DialogModelMenuModelAdapter::GetField(
-    size_t index) const {
+const DialogModelField* DialogModelMenuModelAdapter::GetField(int index) const {
+  DCHECK_GE(index, 0);
   DCHECK_LT(index, GetItemCount());
   return model_->fields(GetPassKey())[index].get();
 }
 
-DialogModelField* DialogModelMenuModelAdapter::GetField(size_t index) {
+DialogModelField* DialogModelMenuModelAdapter::GetField(int index) {
   return const_cast<DialogModelField*>(
       const_cast<const DialogModelMenuModelAdapter*>(this)->GetField(index));
 }
diff --git a/ui/base/models/dialog_model_menu_model_adapter.h b/ui/base/models/dialog_model_menu_model_adapter.h
index 01a663d3..98567cf 100644
--- a/ui/base/models/dialog_model_menu_model_adapter.h
+++ b/ui/base/models/dialog_model_menu_model_adapter.h
@@ -27,26 +27,25 @@
 
   // MenuModel:
   bool HasIcons() const override;
-  size_t GetItemCount() const override;
-  ItemType GetTypeAt(size_t index) const override;
-  ui::MenuSeparatorType GetSeparatorTypeAt(size_t index) const override;
-  int GetCommandIdAt(size_t index) const override;
-  std::u16string GetLabelAt(size_t index) const override;
-  bool IsItemDynamicAt(size_t index) const override;
-  bool GetAcceleratorAt(size_t index,
-                        ui::Accelerator* accelerator) const override;
+  int GetItemCount() const override;
+  ItemType GetTypeAt(int index) const override;
+  ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override;
+  int GetCommandIdAt(int index) const override;
+  std::u16string GetLabelAt(int index) const override;
+  bool IsItemDynamicAt(int index) const override;
+  bool GetAcceleratorAt(int index, ui::Accelerator* accelerator) const override;
   bool IsItemCheckedAt(size_t index) const override;
-  int GetGroupIdAt(size_t index) const override;
-  ImageModel GetIconAt(size_t index) const override;
-  ButtonMenuItemModel* GetButtonMenuItemAt(size_t index) const override;
-  bool IsEnabledAt(size_t index) const override;
-  MenuModel* GetSubmenuModelAt(size_t index) const override;
-  void ActivatedAt(size_t index) override;
-  void ActivatedAt(size_t index, int event_flags) override;
+  int GetGroupIdAt(int index) const override;
+  ImageModel GetIconAt(int index) const override;
+  ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override;
+  bool IsEnabledAt(int index) const override;
+  MenuModel* GetSubmenuModelAt(int index) const override;
+  void ActivatedAt(int index) override;
+  void ActivatedAt(int index, int event_flags) override;
 
  private:
-  const DialogModelField* GetField(size_t index) const;
-  DialogModelField* GetField(size_t index);
+  const DialogModelField* GetField(int index) const;
+  DialogModelField* GetField(int index);
 
   std::unique_ptr<DialogModel> model_;
 };
diff --git a/ui/base/models/menu_model.cc b/ui/base/models/menu_model.cc
index 8ab6327..765db4a0 100644
--- a/ui/base/models/menu_model.cc
+++ b/ui/base/models/menu_model.cc
@@ -15,29 +15,29 @@
     menu_model_delegate_->OnMenuClearingDelegate();
 }
 
-bool MenuModel::IsVisibleAt(size_t index) const {
+bool MenuModel::IsVisibleAt(int index) const {
   return true;
 }
 
-bool MenuModel::IsAlertedAt(size_t index) const {
+bool MenuModel::IsAlertedAt(int index) const {
   return false;
 }
 
-bool MenuModel::IsNewFeatureAt(size_t index) const {
+bool MenuModel::IsNewFeatureAt(int index) const {
   return false;
 }
 
-ElementIdentifier MenuModel::GetElementIdentifierAt(size_t index) const {
+ElementIdentifier MenuModel::GetElementIdentifierAt(int index) const {
   return ElementIdentifier();
 }
 
 // static
 bool MenuModel::GetModelAndIndexForCommandId(int command_id,
                                              MenuModel** model,
-                                             size_t* index) {
-  const size_t item_count = (*model)->GetItemCount();
-  for (size_t i = 0; i < item_count; ++i) {
-    const size_t candidate_index = i;
+                                             int* index) {
+  const int item_count = (*model)->GetItemCount();
+  for (int i = 0; i < item_count; ++i) {
+    const int candidate_index = i;
     // Actionable submenus have commands.
     if ((*model)->GetTypeAt(candidate_index) == TYPE_ACTIONABLE_SUBMENU &&
         (*model)->GetCommandIdAt(candidate_index) == command_id) {
@@ -60,32 +60,32 @@
   return false;
 }
 
-std::u16string MenuModel::GetMinorTextAt(size_t index) const {
+std::u16string MenuModel::GetMinorTextAt(int index) const {
   return std::u16string();
 }
 
-std::u16string MenuModel::GetSecondaryLabelAt(size_t index) const {
+std::u16string MenuModel::GetSecondaryLabelAt(int index) const {
   return std::u16string();
 }
 
-ImageModel MenuModel::GetMinorIconAt(size_t index) const {
+ImageModel MenuModel::GetMinorIconAt(int index) const {
   return ImageModel();
 }
 
-bool MenuModel::MayHaveMnemonicsAt(size_t index) const {
+bool MenuModel::MayHaveMnemonicsAt(int index) const {
   return true;
 }
 
-std::u16string MenuModel::GetAccessibleNameAt(size_t index) const {
+std::u16string MenuModel::GetAccessibleNameAt(int index) const {
   return std::u16string();
 }
 
-const gfx::FontList* MenuModel::GetLabelFontListAt(size_t index) const {
+const gfx::FontList* MenuModel::GetLabelFontListAt(int index) const {
   return nullptr;
 }
 
 // Default implementation ignores the event flags.
-void MenuModel::ActivatedAt(size_t index, int event_flags) {
+void MenuModel::ActivatedAt(int index, int event_flags) {
   ActivatedAt(index);
 }
 
diff --git a/ui/base/models/menu_model.h b/ui/base/models/menu_model.h
index 016a06e..330a631 100644
--- a/ui/base/models/menu_model.h
+++ b/ui/base/models/menu_model.h
@@ -55,52 +55,52 @@
   virtual bool HasIcons() const = 0;
 
   // Returns the number of items in the menu.
-  virtual size_t GetItemCount() const = 0;
+  virtual int GetItemCount() const = 0;
 
   // Returns the type of item at the specified index.
-  virtual ItemType GetTypeAt(size_t index) const = 0;
+  virtual ItemType GetTypeAt(int index) const = 0;
 
   // Returns the separator type at the specified index.
-  virtual ui::MenuSeparatorType GetSeparatorTypeAt(size_t index) const = 0;
+  virtual ui::MenuSeparatorType GetSeparatorTypeAt(int index) const = 0;
 
   // Returns the command id of the item at the specified index.
-  virtual int GetCommandIdAt(size_t index) const = 0;
+  virtual int GetCommandIdAt(int index) const = 0;
 
   // Returns the label of the item at the specified index.
-  virtual std::u16string GetLabelAt(size_t index) const = 0;
+  virtual std::u16string GetLabelAt(int index) const = 0;
 
   // Returns the secondary label of the item at the specified index. Secondary
   // label is shown below the label.
-  virtual std::u16string GetSecondaryLabelAt(size_t index) const;
+  virtual std::u16string GetSecondaryLabelAt(int index) const;
 
   // Returns the minor text of the item at the specified index. The minor text
   // is rendered to the right of the label and using the font GetLabelFontAt().
-  virtual std::u16string GetMinorTextAt(size_t index) const;
+  virtual std::u16string GetMinorTextAt(int index) const;
 
   // Returns the minor icon of the item at the specified index. The minor icon
   // is rendered to the left of the minor text.
-  virtual ImageModel GetMinorIconAt(size_t index) const;
+  virtual ImageModel GetMinorIconAt(int index) const;
 
   // Returns true if the menu item (label/sublabel/icon) at the specified
   // index can change over the course of the menu's lifetime. If this function
   // returns true, the label, sublabel and icon of the menu item will be
   // updated each time the menu is shown.
-  virtual bool IsItemDynamicAt(size_t index) const = 0;
+  virtual bool IsItemDynamicAt(int index) const = 0;
 
   // Returns whether the menu item at the specified index has a user-set title,
   // in which case it should always be treated as plain text.
-  virtual bool MayHaveMnemonicsAt(size_t index) const;
+  virtual bool MayHaveMnemonicsAt(int index) const;
 
   // Returns the accessible name for the menu item at the specified index.
-  virtual std::u16string GetAccessibleNameAt(size_t index) const;
+  virtual std::u16string GetAccessibleNameAt(int index) const;
 
   // Returns the font list used for the label at the specified index.
   // If NULL, then the default font list should be used.
-  virtual const gfx::FontList* GetLabelFontListAt(size_t index) const;
+  virtual const gfx::FontList* GetLabelFontListAt(int index) const;
 
   // Gets the accelerator information for the specified index, returning true if
   // there is a shortcut accelerator for the item, false otherwise.
-  virtual bool GetAcceleratorAt(size_t index,
+  virtual bool GetAcceleratorAt(int index,
                                 ui::Accelerator* accelerator) const = 0;
 
   // Returns the checked state of the item at the specified index.
@@ -108,44 +108,44 @@
 
   // Returns the id of the group of radio items that the item at the specified
   // index belongs to.
-  virtual int GetGroupIdAt(size_t index) const = 0;
+  virtual int GetGroupIdAt(int index) const = 0;
 
   // Gets the icon for the item at the specified index. ImageModel is empty if
   // there is no icon.
-  virtual ImageModel GetIconAt(size_t index) const = 0;
+  virtual ImageModel GetIconAt(int index) const = 0;
 
   // Returns the model for a menu item with a line of buttons at |index|.
-  virtual ButtonMenuItemModel* GetButtonMenuItemAt(size_t index) const = 0;
+  virtual ButtonMenuItemModel* GetButtonMenuItemAt(int index) const = 0;
 
   // Returns the enabled state of the item at the specified index.
-  virtual bool IsEnabledAt(size_t index) const = 0;
+  virtual bool IsEnabledAt(int index) const = 0;
 
   // Returns true if the menu item is visible.
-  virtual bool IsVisibleAt(size_t index) const;
+  virtual bool IsVisibleAt(int index) const;
 
   // Returns true if the item is rendered specially to draw attention
   // for in-product help.
-  virtual bool IsAlertedAt(size_t index) const;
+  virtual bool IsAlertedAt(int index) const;
 
   // Returns true if the menu item grants access to a new feature that we want
   // to show off to users (items marked as new will receive a "New" badge when
   // the appropriate flag is enabled).
-  virtual bool IsNewFeatureAt(size_t index) const;
+  virtual bool IsNewFeatureAt(int index) const;
 
   // Returns an application-window-unique identifier that can be used to track
   // the menu item irrespective of menu-specific command IDs.
-  virtual ElementIdentifier GetElementIdentifierAt(size_t index) const;
+  virtual ElementIdentifier GetElementIdentifierAt(int index) const;
 
   // Returns the model for the submenu at the specified index.
-  virtual MenuModel* GetSubmenuModelAt(size_t index) const = 0;
+  virtual MenuModel* GetSubmenuModelAt(int index) const = 0;
 
   // Called when the item at the specified index has been activated.
-  virtual void ActivatedAt(size_t index) = 0;
+  virtual void ActivatedAt(int index) = 0;
 
   // Called when the item has been activated with given event flags.
   // (for the case where the activation involves a navigation).
   // |event_flags| is a bit mask of ui::EventFlags.
-  virtual void ActivatedAt(size_t index, int event_flags);
+  virtual void ActivatedAt(int index, int event_flags);
 
   // Called when the menu is about to be shown.
   virtual void MenuWillShow() {}
@@ -169,7 +169,7 @@
   // and specifies the model to start searching from.
   static bool GetModelAndIndexForCommandId(int command_id,
                                            MenuModel** model,
-                                           size_t* index);
+                                           int* index);
 
  private:
   // MenuModelDelegate. Weak. Could be null.
diff --git a/ui/base/models/simple_menu_model.cc b/ui/base/models/simple_menu_model.cc
index ce1d8d49..20a3b1e 100644
--- a/ui/base/models/simple_menu_model.cc
+++ b/ui/base/models/simple_menu_model.cc
@@ -225,19 +225,18 @@
   AppendItem(std::move(item));
 }
 
-void SimpleMenuModel::InsertItemAt(size_t index,
+void SimpleMenuModel::InsertItemAt(int index,
                                    int command_id,
                                    const std::u16string& label) {
   InsertItemAtIndex(Item(command_id, TYPE_COMMAND, label), index);
 }
 
-void SimpleMenuModel::InsertItemWithStringIdAt(size_t index,
-                                               int command_id,
-                                               int string_id) {
+void SimpleMenuModel::InsertItemWithStringIdAt(
+    int index, int command_id, int string_id) {
   InsertItemAt(index, command_id, l10n_util::GetStringUTF16(string_id));
 }
 
-void SimpleMenuModel::InsertSeparatorAt(size_t index,
+void SimpleMenuModel::InsertSeparatorAt(int index,
                                         MenuSeparatorType separator_type) {
 #if !defined(USE_AURA)
   if (separator_type != NORMAL_SEPARATOR) {
@@ -249,19 +248,18 @@
   InsertItemAtIndex(std::move(item), index);
 }
 
-void SimpleMenuModel::InsertCheckItemAt(size_t index,
+void SimpleMenuModel::InsertCheckItemAt(int index,
                                         int command_id,
                                         const std::u16string& label) {
   InsertItemAtIndex(Item(command_id, TYPE_CHECK, label), index);
 }
 
-void SimpleMenuModel::InsertCheckItemWithStringIdAt(size_t index,
-                                                    int command_id,
-                                                    int string_id) {
+void SimpleMenuModel::InsertCheckItemWithStringIdAt(
+    int index, int command_id, int string_id) {
   InsertCheckItemAt(index, command_id, l10n_util::GetStringUTF16(string_id));
 }
 
-void SimpleMenuModel::InsertRadioItemAt(size_t index,
+void SimpleMenuModel::InsertRadioItemAt(int index,
                                         int command_id,
                                         const std::u16string& label,
                                         int group_id) {
@@ -270,15 +268,13 @@
   InsertItemAtIndex(std::move(item), index);
 }
 
-void SimpleMenuModel::InsertRadioItemWithStringIdAt(size_t index,
-                                                    int command_id,
-                                                    int string_id,
-                                                    int group_id) {
+void SimpleMenuModel::InsertRadioItemWithStringIdAt(
+    int index, int command_id, int string_id, int group_id) {
   InsertRadioItemAt(
       index, command_id, l10n_util::GetStringUTF16(string_id), group_id);
 }
 
-void SimpleMenuModel::InsertSubMenuAt(size_t index,
+void SimpleMenuModel::InsertSubMenuAt(int index,
                                       int command_id,
                                       const std::u16string& label,
                                       MenuModel* model) {
@@ -287,70 +283,68 @@
   InsertItemAtIndex(std::move(item), index);
 }
 
-void SimpleMenuModel::InsertSubMenuWithStringIdAt(size_t index,
-                                                  int command_id,
-                                                  int string_id,
-                                                  MenuModel* model) {
+void SimpleMenuModel::InsertSubMenuWithStringIdAt(
+    int index, int command_id, int string_id, MenuModel* model) {
   InsertSubMenuAt(index, command_id, l10n_util::GetStringUTF16(string_id),
                   model);
 }
 
-void SimpleMenuModel::RemoveItemAt(size_t index) {
+void SimpleMenuModel::RemoveItemAt(int index) {
   items_.erase(items_.begin() + ValidateItemIndex(index));
   MenuItemsChanged();
 }
 
-void SimpleMenuModel::SetIcon(size_t index, const ui::ImageModel& icon) {
+void SimpleMenuModel::SetIcon(int index, const ui::ImageModel& icon) {
   items_[ValidateItemIndex(index)].icon = icon;
   MenuItemsChanged();
 }
 
-void SimpleMenuModel::SetLabel(size_t index, const std::u16string& label) {
+void SimpleMenuModel::SetLabel(int index, const std::u16string& label) {
   items_[ValidateItemIndex(index)].label = label;
   MenuItemsChanged();
 }
 
-void SimpleMenuModel::SetMinorText(size_t index,
+void SimpleMenuModel::SetMinorText(int index,
                                    const std::u16string& minor_text) {
   items_[ValidateItemIndex(index)].minor_text = minor_text;
 }
 
-void SimpleMenuModel::SetMinorIcon(size_t index,
+void SimpleMenuModel::SetMinorIcon(int index,
                                    const ui::ImageModel& minor_icon) {
   items_[ValidateItemIndex(index)].minor_icon = minor_icon;
 }
 
-void SimpleMenuModel::SetEnabledAt(size_t index, bool enabled) {
+void SimpleMenuModel::SetEnabledAt(int index, bool enabled) {
   if (items_[ValidateItemIndex(index)].enabled == enabled)
     return;
 
-  items_[index].enabled = enabled;
+  items_[ValidateItemIndex(index)].enabled = enabled;
   MenuItemsChanged();
 }
 
-void SimpleMenuModel::SetVisibleAt(size_t index, bool visible) {
+void SimpleMenuModel::SetVisibleAt(int index, bool visible) {
   if (items_[ValidateItemIndex(index)].visible == visible)
     return;
 
-  items_[index].visible = visible;
+  items_[ValidateItemIndex(index)].visible = visible;
   MenuItemsChanged();
 }
 
-void SimpleMenuModel::SetIsNewFeatureAt(size_t index, bool is_new_feature) {
+void SimpleMenuModel::SetIsNewFeatureAt(int index, bool is_new_feature) {
   items_[ValidateItemIndex(index)].is_new_feature = is_new_feature;
 }
 
-void SimpleMenuModel::SetMayHaveMnemonicsAt(size_t index,
+void SimpleMenuModel::SetMayHaveMnemonicsAt(int index,
                                             bool may_have_mnemonics) {
   items_[ValidateItemIndex(index)].may_have_mnemonics = may_have_mnemonics;
 }
 
-void SimpleMenuModel::SetAccessibleNameAt(size_t index,
+void SimpleMenuModel::SetAccessibleNameAt(int index,
                                           std::u16string accessible_name) {
   items_[ValidateItemIndex(index)].accessible_name = std::move(accessible_name);
 }
 
-void SimpleMenuModel::SetElementIdentifierAt(size_t index,
+void SimpleMenuModel::SetElementIdentifierAt(int index,
                                              ElementIdentifier unique_id) {
   items_[ValidateItemIndex(index)].unique_id = unique_id;
 }
@@ -360,20 +354,19 @@
   MenuItemsChanged();
 }
 
-absl::optional<size_t> SimpleMenuModel::GetIndexOfCommandId(
-    int command_id) const {
+int SimpleMenuModel::GetIndexOfCommandId(int command_id) const {
   for (auto i = items_.begin(); i != items_.end(); ++i) {
     if (i->command_id == command_id)
-      return static_cast<size_t>(std::distance(items_.begin(), i));
+      return static_cast<int>(std::distance(items_.begin(), i));
   }
-  return absl::nullopt;
+  return -1;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // SimpleMenuModel, MenuModel implementation:
 
 bool SimpleMenuModel::HasIcons() const {
-  for (size_t i = 0; i < GetItemCount(); ++i) {
+  for (int i = 0; i < GetItemCount(); ++i) {
     if (!GetIconAt(i).IsEmpty())
       return true;
   }
@@ -381,70 +374,76 @@
   return false;
 }
 
-size_t SimpleMenuModel::GetItemCount() const {
-  return items_.size();
+int SimpleMenuModel::GetItemCount() const {
+  return static_cast<int>(items_.size());
 }
 
-MenuModel::ItemType SimpleMenuModel::GetTypeAt(size_t index) const {
+MenuModel::ItemType SimpleMenuModel::GetTypeAt(int index) const {
   return items_[ValidateItemIndex(index)].type;
 }
 
-ui::MenuSeparatorType SimpleMenuModel::GetSeparatorTypeAt(size_t index) const {
+ui::MenuSeparatorType SimpleMenuModel::GetSeparatorTypeAt(int index) const {
   return items_[ValidateItemIndex(index)].separator_type;
 }
 
-int SimpleMenuModel::GetCommandIdAt(size_t index) const {
+int SimpleMenuModel::GetCommandIdAt(int index) const {
   return items_[ValidateItemIndex(index)].command_id;
 }
 
-std::u16string SimpleMenuModel::GetLabelAt(size_t index) const {
+std::u16string SimpleMenuModel::GetLabelAt(int index) const {
   if (IsItemDynamicAt(index))
     return delegate_->GetLabelForCommandId(GetCommandIdAt(index));
   return items_[ValidateItemIndex(index)].label;
 }
 
-std::u16string SimpleMenuModel::GetMinorTextAt(size_t index) const {
+std::u16string SimpleMenuModel::GetMinorTextAt(int index) const {
   return items_[ValidateItemIndex(index)].minor_text;
 }
 
-ImageModel SimpleMenuModel::GetMinorIconAt(size_t index) const {
+ImageModel SimpleMenuModel::GetMinorIconAt(int index) const {
   return items_[ValidateItemIndex(index)].minor_icon;
 }
 
-bool SimpleMenuModel::IsItemDynamicAt(size_t index) const {
-  return delegate_ &&
-         delegate_->IsItemForCommandIdDynamic(GetCommandIdAt(index));
+bool SimpleMenuModel::IsItemDynamicAt(int index) const {
+  if (delegate_)
+    return delegate_->IsItemForCommandIdDynamic(GetCommandIdAt(index));
+  return false;
 }
 
-bool SimpleMenuModel::GetAcceleratorAt(size_t index,
+bool SimpleMenuModel::GetAcceleratorAt(int index,
                                        ui::Accelerator* accelerator) const {
-  return delegate_ && delegate_->GetAcceleratorForCommandId(
-                          GetCommandIdAt(index), accelerator);
+  if (delegate_) {
+    return delegate_->GetAcceleratorForCommandId(GetCommandIdAt(index),
+                                                 accelerator);
+  }
+  return false;
 }
 
 bool SimpleMenuModel::IsItemCheckedAt(size_t index) const {
   if (!delegate_)
     return false;
   MenuModel::ItemType item_type = GetTypeAt(index);
-  return (item_type == TYPE_CHECK || item_type == TYPE_RADIO) &&
-         delegate_->IsCommandIdChecked(GetCommandIdAt(index));
+  return (item_type == TYPE_CHECK || item_type == TYPE_RADIO) ?
+      delegate_->IsCommandIdChecked(GetCommandIdAt(index)) : false;
 }
 
-int SimpleMenuModel::GetGroupIdAt(size_t index) const {
+int SimpleMenuModel::GetGroupIdAt(int index) const {
   return items_[ValidateItemIndex(index)].group_id;
 }
 
-ImageModel SimpleMenuModel::GetIconAt(size_t index) const {
+ImageModel SimpleMenuModel::GetIconAt(int index) const {
   if (IsItemDynamicAt(index))
     return delegate_->GetIconForCommandId(GetCommandIdAt(index));
-  return items_[ValidateItemIndex(index)].icon;
+
+  ValidateItemIndex(index);
+  return items_[index].icon;
 }
 
-ButtonMenuItemModel* SimpleMenuModel::GetButtonMenuItemAt(size_t index) const {
+ButtonMenuItemModel* SimpleMenuModel::GetButtonMenuItemAt(int index) const {
   return items_[ValidateItemIndex(index)].button_model;
 }
 
-bool SimpleMenuModel::IsEnabledAt(size_t index) const {
+bool SimpleMenuModel::IsEnabledAt(int index) const {
   int command_id = GetCommandIdAt(index);
 
   if (!delegate_ || command_id == kSeparatorId || GetButtonMenuItemAt(index))
@@ -454,7 +453,7 @@
          items_[ValidateItemIndex(index)].enabled;
 }
 
-bool SimpleMenuModel::IsVisibleAt(size_t index) const {
+bool SimpleMenuModel::IsVisibleAt(int index) const {
   int command_id = GetCommandIdAt(index);
   if (!delegate_ || command_id == kSeparatorId || command_id == kTitleId ||
       GetButtonMenuItemAt(index)) {
@@ -465,7 +464,7 @@
          items_[ValidateItemIndex(index)].visible;
 }
 
-bool SimpleMenuModel::IsAlertedAt(size_t index) const {
+bool SimpleMenuModel::IsAlertedAt(int index) const {
   const int command_id = GetCommandIdAt(index);
   if (!delegate_ || command_id == kSeparatorId || command_id == kTitleId)
     return false;
@@ -473,7 +472,7 @@
   // This method needs to be recursive, because if the highlighted command is
   // in a submenu then the submenu item should also be highlighted.
   if (auto* const submenu = GetSubmenuModelAt(index)) {
-    for (size_t i = 0; i < submenu->GetItemCount(); ++i) {
+    for (int i = 0; i < submenu->GetItemCount(); ++i) {
       if (submenu->IsAlertedAt(i))
         return true;
     }
@@ -482,32 +481,32 @@
   return delegate_->IsCommandIdAlerted(command_id);
 }
 
-bool SimpleMenuModel::IsNewFeatureAt(size_t index) const {
+bool SimpleMenuModel::IsNewFeatureAt(int index) const {
   return items_[ValidateItemIndex(index)].is_new_feature;
 }
 
-bool SimpleMenuModel::MayHaveMnemonicsAt(size_t index) const {
+bool SimpleMenuModel::MayHaveMnemonicsAt(int index) const {
   return items_[ValidateItemIndex(index)].may_have_mnemonics;
 }
 
-std::u16string SimpleMenuModel::GetAccessibleNameAt(size_t index) const {
+std::u16string SimpleMenuModel::GetAccessibleNameAt(int index) const {
   return items_[ValidateItemIndex(index)].accessible_name;
 }
 
-ElementIdentifier SimpleMenuModel::GetElementIdentifierAt(size_t index) const {
+ElementIdentifier SimpleMenuModel::GetElementIdentifierAt(int index) const {
   return items_[ValidateItemIndex(index)].unique_id;
 }
 
-void SimpleMenuModel::ActivatedAt(size_t index) {
+void SimpleMenuModel::ActivatedAt(int index) {
   ActivatedAt(index, 0);
 }
 
-void SimpleMenuModel::ActivatedAt(size_t index, int event_flags) {
+void SimpleMenuModel::ActivatedAt(int index, int event_flags) {
   if (delegate_)
     delegate_->ExecuteCommand(GetCommandIdAt(index), event_flags);
 }
 
-MenuModel* SimpleMenuModel::GetSubmenuModelAt(size_t index) const {
+MenuModel* SimpleMenuModel::GetSubmenuModelAt(int index) const {
   return items_[ValidateItemIndex(index)].submenu;
 }
 
@@ -545,8 +544,9 @@
 SimpleMenuModel::Item& SimpleMenuModel::Item::operator=(Item&&) = default;
 SimpleMenuModel::Item::~Item() = default;
 
-size_t SimpleMenuModel::ValidateItemIndex(size_t index) const {
-  CHECK_LT(index, items_.size());
+int SimpleMenuModel::ValidateItemIndex(int index) const {
+  CHECK_GE(index, 0);
+  CHECK_LT(static_cast<size_t>(index), items_.size());
   return index;
 }
 
@@ -556,7 +556,7 @@
   MenuItemsChanged();
 }
 
-void SimpleMenuModel::InsertItemAtIndex(Item item, size_t index) {
+void SimpleMenuModel::InsertItemAtIndex(Item item, int index) {
   ValidateItem(item);
   items_.insert(items_.begin() + index, std::move(item));
   MenuItemsChanged();
diff --git a/ui/base/models/simple_menu_model.h b/ui/base/models/simple_menu_model.h
index 7ecb2f6c..eadda34 100644
--- a/ui/base/models/simple_menu_model.h
+++ b/ui/base/models/simple_menu_model.h
@@ -11,7 +11,6 @@
 #include "base/component_export.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/models/image_model.h"
 #include "ui/base/models/menu_model.h"
@@ -132,99 +131,92 @@
                                                const ui::ImageModel& icon);
 
   // Methods for inserting items into the model.
-  void InsertItemAt(size_t index, int command_id, const std::u16string& label);
-  void InsertItemWithStringIdAt(size_t index, int command_id, int string_id);
-  void InsertSeparatorAt(size_t index, MenuSeparatorType separator_type);
-  void InsertCheckItemAt(size_t index,
+  void InsertItemAt(int index, int command_id, const std::u16string& label);
+  void InsertItemWithStringIdAt(int index, int command_id, int string_id);
+  void InsertSeparatorAt(int index, MenuSeparatorType separator_type);
+  void InsertCheckItemAt(int index,
                          int command_id,
                          const std::u16string& label);
-  void InsertCheckItemWithStringIdAt(size_t index,
-                                     int command_id,
-                                     int string_id);
-  void InsertRadioItemAt(size_t index,
+  void InsertCheckItemWithStringIdAt(int index, int command_id, int string_id);
+  void InsertRadioItemAt(int index,
                          int command_id,
                          const std::u16string& label,
                          int group_id);
-  void InsertRadioItemWithStringIdAt(size_t index,
-                                     int command_id,
-                                     int string_id,
-                                     int group_id);
-  void InsertSubMenuAt(size_t index,
+  void InsertRadioItemWithStringIdAt(
+      int index, int command_id, int string_id, int group_id);
+  void InsertSubMenuAt(int index,
                        int command_id,
                        const std::u16string& label,
                        MenuModel* model);
-  void InsertSubMenuWithStringIdAt(size_t index,
-                                   int command_id,
-                                   int string_id,
-                                   MenuModel* model);
+  void InsertSubMenuWithStringIdAt(
+      int index, int command_id, int string_id, MenuModel* model);
 
   // Remove item at specified index from the model.
-  void RemoveItemAt(size_t index);
+  void RemoveItemAt(int index);
 
   // Sets the icon for the item at |index|.
-  void SetIcon(size_t index, const ui::ImageModel& icon);
+  void SetIcon(int index, const ui::ImageModel& icon);
 
   // Sets the label for the item at |index|.
-  void SetLabel(size_t index, const std::u16string& label);
+  void SetLabel(int index, const std::u16string& label);
 
   // Sets the minor text for the item at |index|.
-  void SetMinorText(size_t index, const std::u16string& minor_text);
+  void SetMinorText(int index, const std::u16string& minor_text);
 
   // Sets the minor icon for the item at |index|.
-  void SetMinorIcon(size_t index, const ui::ImageModel& minor_icon);
+  void SetMinorIcon(int index, const ui::ImageModel& minor_icon);
 
   // Sets whether the item at |index| is enabled.
-  void SetEnabledAt(size_t index, bool enabled);
+  void SetEnabledAt(int index, bool enabled);
 
   // Sets whether the item at |index| is visible.
-  void SetVisibleAt(size_t index, bool visible);
+  void SetVisibleAt(int index, bool visible);
 
   // Sets whether the item at |index| is new.
-  void SetIsNewFeatureAt(size_t index, bool is_new_feature);
+  void SetIsNewFeatureAt(int index, bool is_new_feature);
 
   // Sets whether the item at |index| is may have mnemonics.
-  void SetMayHaveMnemonicsAt(size_t index, bool may_have_mnemonics);
+  void SetMayHaveMnemonicsAt(int index, bool may_have_mnemonics);
 
   // Sets the accessible name of item at |index|.
-  void SetAccessibleNameAt(size_t index, std::u16string accessible_name);
+  void SetAccessibleNameAt(int index, std::u16string accessible_name);
 
   // Sets an application-window unique identifier associated with this menu item
   // allowing it to be tracked without knowledge of menu-specific command IDs.
-  void SetElementIdentifierAt(size_t index, ElementIdentifier unique_id);
+  void SetElementIdentifierAt(int index, ElementIdentifier unique_id);
 
   // Clears all items. Note that it does not free MenuModel of submenu.
   void Clear();
 
   // Returns the index of the item that has the given |command_id|. Returns
-  // nullopt if not found.
-  absl::optional<size_t> GetIndexOfCommandId(int command_id) const;
+  // -1 if not found.
+  int GetIndexOfCommandId(int command_id) const;
 
   // Overridden from MenuModel:
   bool HasIcons() const override;
-  size_t GetItemCount() const override;
-  ItemType GetTypeAt(size_t index) const override;
-  ui::MenuSeparatorType GetSeparatorTypeAt(size_t index) const override;
-  int GetCommandIdAt(size_t index) const override;
-  std::u16string GetLabelAt(size_t index) const override;
-  std::u16string GetMinorTextAt(size_t index) const override;
-  ImageModel GetMinorIconAt(size_t index) const override;
-  bool IsItemDynamicAt(size_t index) const override;
-  bool GetAcceleratorAt(size_t index,
-                        ui::Accelerator* accelerator) const override;
+  int GetItemCount() const override;
+  ItemType GetTypeAt(int index) const override;
+  ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override;
+  int GetCommandIdAt(int index) const override;
+  std::u16string GetLabelAt(int index) const override;
+  std::u16string GetMinorTextAt(int index) const override;
+  ImageModel GetMinorIconAt(int index) const override;
+  bool IsItemDynamicAt(int index) const override;
+  bool GetAcceleratorAt(int index, ui::Accelerator* accelerator) const override;
   bool IsItemCheckedAt(size_t index) const override;
-  int GetGroupIdAt(size_t index) const override;
-  ImageModel GetIconAt(size_t index) const override;
-  ui::ButtonMenuItemModel* GetButtonMenuItemAt(size_t index) const override;
-  bool IsEnabledAt(size_t index) const override;
-  bool IsVisibleAt(size_t index) const override;
-  bool IsAlertedAt(size_t index) const override;
-  bool IsNewFeatureAt(size_t index) const override;
-  bool MayHaveMnemonicsAt(size_t index) const override;
-  std::u16string GetAccessibleNameAt(size_t index) const override;
-  ElementIdentifier GetElementIdentifierAt(size_t index) const override;
-  void ActivatedAt(size_t index) override;
-  void ActivatedAt(size_t index, int event_flags) override;
-  MenuModel* GetSubmenuModelAt(size_t index) const override;
+  int GetGroupIdAt(int index) const override;
+  ImageModel GetIconAt(int index) const override;
+  ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override;
+  bool IsEnabledAt(int index) const override;
+  bool IsVisibleAt(int index) const override;
+  bool IsAlertedAt(int index) const override;
+  bool IsNewFeatureAt(int index) const override;
+  bool MayHaveMnemonicsAt(int index) const override;
+  std::u16string GetAccessibleNameAt(int index) const override;
+  ElementIdentifier GetElementIdentifierAt(int index) const override;
+  void ActivatedAt(int index) override;
+  void ActivatedAt(int index, int event_flags) override;
+  MenuModel* GetSubmenuModelAt(int index) const override;
   void MenuWillShow() override;
   void MenuWillClose() override;
 
@@ -261,14 +253,14 @@
     ElementIdentifier unique_id;
   };
 
-  using ItemVector = std::vector<Item>;
+  typedef std::vector<Item> ItemVector;
 
   // Returns |index|.
-  size_t ValidateItemIndex(size_t index) const;
+  int ValidateItemIndex(int index) const;
 
   // Functions for inserting items into |items_|.
   void AppendItem(Item item);
-  void InsertItemAtIndex(Item item, size_t index);
+  void InsertItemAtIndex(Item item, int index);
   void ValidateItem(const Item& item);
 
   // Notify the delegate that the menu is closed.
diff --git a/ui/chromeos/file_manager_strings.grdp b/ui/chromeos/file_manager_strings.grdp
index b423fc6..9b15f4f 100644
--- a/ui/chromeos/file_manager_strings.grdp
+++ b/ui/chromeos/file_manager_strings.grdp
@@ -794,7 +794,7 @@
     Your organization requires more storage to complete the upload.
   </message>
   <message name="IDS_FILE_BROWSER_DRIVE_ORGANIZATION_STORAGE_FULL" desc="File Manager menu storage meter message indicating the user's organization has run out of quota.">
-    Org storage full
+    *Org storage full
   </message>
   <message name="IDS_FILE_BROWSER_SHARE_ERROR" desc="File Manager error message when sharing a file or a directory on Drive fails because of internet connection problems.">
     Sharing failed. Check your connection and try again later.
diff --git a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_DRIVE_ORGANIZATION_STORAGE_FULL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_DRIVE_ORGANIZATION_STORAGE_FULL.png.sha1
index 6d739b95..0944237 100644
--- a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_DRIVE_ORGANIZATION_STORAGE_FULL.png.sha1
+++ b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_DRIVE_ORGANIZATION_STORAGE_FULL.png.sha1
@@ -1 +1 @@
-a041b821d2eb19e78bbf22cfa2ce11eeb5a19685
\ No newline at end of file
+9e8abe0765da5fc3432e20f5316316bd8c64bb70
\ No newline at end of file
diff --git a/ui/compositor/layer_owner.cc b/ui/compositor/layer_owner.cc
index 43dce39..80ae0aa 100644
--- a/ui/compositor/layer_owner.cc
+++ b/ui/compositor/layer_owner.cc
@@ -7,7 +7,7 @@
 // layer_owner.h is a widely included header and its size impacts build
 // time. Try not to raise this limit unless necessary. See
 // https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md
-#pragma clang max_tokens_here 510000
+#pragma clang max_tokens_here 550000
 
 #include <utility>
 
diff --git a/ui/file_manager/file_manager/common/js/api.js b/ui/file_manager/file_manager/common/js/api.js
index ab59ea2a..b946b5c 100644
--- a/ui/file_manager/file_manager/common/js/api.js
+++ b/ui/file_manager/file_manager/common/js/api.js
@@ -6,6 +6,8 @@
  * @fileoverview Helpers for APIs used within Files app.
  */
 
+import {util} from './util.js';
+
 /**
  * Calls the `fn` function which should expect the callback as last argument.
  *
@@ -106,8 +108,9 @@
  */
 export async function getDisallowedTransfers(entries, destinationEntry) {
   return promisify(
-      chrome.fileManagerPrivate.getDisallowedTransfers, entries,
-      destinationEntry);
+      chrome.fileManagerPrivate.getDisallowedTransfers,
+      entries.map(e => util.unwrapEntry(e)),
+      util.unwrapEntry(destinationEntry));
 }
 
 /**
@@ -118,7 +121,9 @@
  *     DlpMetadata
  */
 export async function getDlpMetadata(entries) {
-  return promisify(chrome.fileManagerPrivate.getDlpMetadata, entries);
+  return promisify(
+      chrome.fileManagerPrivate.getDlpMetadata,
+      entries.map(e => util.unwrapEntry(e)));
 }
 
 /**
diff --git a/ui/file_manager/file_manager/common/js/util.js b/ui/file_manager/file_manager/common/js/util.js
index 4664ed4..619c48f 100644
--- a/ui/file_manager/file_manager/common/js/util.js
+++ b/ui/file_manager/file_manager/common/js/util.js
@@ -13,12 +13,12 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {queryRequiredElement} from 'chrome://resources/js/util.m.js';
 
-import {promisify} from '../../common/js/api.js';
 import {EntryLocation} from '../../externs/entry_location.js';
 import {FakeEntry, FilesAppEntry} from '../../externs/files_app_entry_interfaces.js';
 import {VolumeInfo} from '../../externs/volume_info.js';
 import {VolumeManager} from '../../externs/volume_manager.js';
 
+import {promisify} from './api.js';
 import {EntryList} from './files_app_entry_types.js';
 import {VolumeManagerCommon} from './volume_manager_types.js';
 
@@ -1344,7 +1344,6 @@
   return loadTimeData.getBoolean('EXTRACT_ARCHIVE');
 };
 
-
 /**
  * Whether the Files app Experimental flag is enabled.
  * @returns {boolean}
@@ -1355,6 +1354,15 @@
 };
 
 /**
+ * Whether the Files app integration with DLP (Data Loss Prevention) is enabled.
+ * @returns {boolean}
+ */
+util.isDlpEnabled = () => {
+  return loadTimeData.valueExists('DLP_ENABLED') &&
+      loadTimeData.getBoolean('DLP_ENABLED');
+};
+
+/**
  * Returns true if FuseBox flag is enabled.
  * @return {boolean}
  */
diff --git a/ui/file_manager/file_manager/foreground/css/common.css b/ui/file_manager/file_manager/foreground/css/common.css
index 94703b6..915cb7df 100644
--- a/ui/file_manager/file_manager/foreground/css/common.css
+++ b/ui/file_manager/file_manager/foreground/css/common.css
@@ -215,13 +215,6 @@
   min-width: 6px;
 }
 
-.menu-warning {
-  color: var(--cros-textfield-label-color-error);
-  font-size: 11px;
-  line-height: 16px;
-  margin-top: 6px;
-}
-
 /* Entry names (File names, Folder names, Volume names, ...). */
 /* Their base bidi direction should be ltr even in RTL languages. */
 html[dir='rtl'] .entry-name {
diff --git a/ui/file_manager/file_manager/foreground/css/file_types.css b/ui/file_manager/file_manager/foreground/css/file_types.css
index 8604836..43d4789 100644
--- a/ui/file_manager/file_manager/foreground/css/file_types.css
+++ b/ui/file_manager/file_manager/foreground/css/file_types.css
@@ -88,6 +88,8 @@
 
 [file-type-icon='gdoc'] {
   -webkit-mask-image: url(../images/filetype/filetype_gdoc.svg);
+  /* TODO(crbug.com/1345818) Revert the first CL on that bug when it's fixed. */
+  background-color: var(--cros-icon-color-blue);
 }
 
 [file-type-icon='gdraw'] {
@@ -259,7 +261,6 @@
 }
 
 /* File type icon and thumbnail colors. */
-[file-type-icon='gdoc'],
 [file-type-icon='script'],
 [file-type-icon='tini'],
 .no-thumbnail[generic-thumbnail='gdoc'],
diff --git a/ui/file_manager/file_manager/foreground/js/gear_menu_controller.js b/ui/file_manager/file_manager/foreground/js/gear_menu_controller.js
index c608a2f..21456bac 100644
--- a/ui/file_manager/file_manager/foreground/js/gear_menu_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/gear_menu_controller.js
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {getDriveQuotaMetadata, getSizeStats} from '../../common/js/api.js';
-import {str, strf, util} from '../../common/js/util.js';
+import {getSizeStats} from '../../common/js/api.js';
+import {str, util} from '../../common/js/util.js';
 import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
 import {DirectoryChangeEvent} from '../../externs/directory_change_event.js';
 
@@ -126,27 +126,7 @@
       return;
     }
 
-    if (currentVolumeInfo.volumeType == VolumeManagerCommon.VolumeType.DRIVE) {
-      this.gearMenu_.setSpaceInfo(
-          getDriveQuotaMetadata().then(
-              quota /* chrome.fileManagerPrivate.DriveQuotaMetadata */ => ({
-                totalSize: quota.totalUserBytes,
-                usedSize: quota.usedUserBytes,
-                warningMessage: quota.organizationLimitExceeded ?
-                    strf('DRIVE_ORGANIZATION_STORAGE_FULL') :
-                    null,
-              })),
-          true);
-      return;
-    }
-
-    this.gearMenu_.setSpaceInfo(
-        getSizeStats(currentVolumeInfo.volumeId)
-            .then(size /* chrome.fileManagerPrivate.MountPointSizeStats */ => ({
-                    totalSize: size.totalSize,
-                    usedSize: size.totalSize - size.remainingSize,
-                  })),
-        true);
+    this.gearMenu_.setSpaceInfo(getSizeStats(currentVolumeInfo.volumeId), true);
   }
 
   /**
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/dlp_metadata_provider.js b/ui/file_manager/file_manager/foreground/js/metadata/dlp_metadata_provider.js
index f5d61ba..dfb0f5ee 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/dlp_metadata_provider.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/dlp_metadata_provider.js
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import {getDlpMetadata} from '../../../common/js/api.js';
+import {util} from '../../../common/js/util.js';
 
 import {MetadataItem} from './metadata_item.js';
 import {MetadataProvider} from './metadata_provider.js';
@@ -20,14 +21,18 @@
 
   /** @override */
   async get(requests) {
-    if (!requests.length) {
-      return Promise.resolve([]);
+    if (!util.isDlpEnabled()) {
+      return requests.map(() => new MetadataItem());
     }
 
-    // TODO(crbug.com/1297603): Early return if DLP isn't enabled.
+    if (!requests.length) {
+      return [];
+    }
+
     const entries = requests.map(_request => {
       return _request.entry;
     });
+
     try {
       const dlpMetadataList = await getDlpMetadata(entries);
       if (dlpMetadataList.length != entries.length) {
@@ -60,4 +65,4 @@
   // TODO(crbug.com/1329770): Consider using an enum for this property.
   'isDlpRestricted',
   'sourceUrl',
-];
\ No newline at end of file
+];
diff --git a/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js b/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js
index 62697dd..5b50a9d 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js
@@ -8,11 +8,6 @@
 
 import {str, strf, util} from '../../../common/js/util.js';
 
-/**
- * @typedef {{totalSize: number, usedSize: number, warningMessage: string}}
- */
-export let SpaceInfo;
-
 export class GearMenu {
   /**
    * @param {!HTMLElement} element
@@ -68,20 +63,12 @@
      * @const
      * @private
      */
-    this.volumeSpaceWarning_ =
-        queryRequiredElement('#volume-space-info-warning', element);
-
-    /**
-     * @type {!HTMLElement}
-     * @const
-     * @private
-     */
     this.providersMenuItem_ =
         queryRequiredElement('#gear-menu-providers', element);
 
     /**
-     * Promise to be resolved with volume space info.
-     * @type {Promise<SpaceInfo|undefined>}
+     * Volume space info.
+     * @type {Promise<chrome.fileManagerPrivate.MountPointSizeStats|undefined>}
      * @private
      */
     this.spaceInfoPromise_ = null;
@@ -99,20 +86,21 @@
   }
 
   /**
-   * @param {Promise<SpaceInfo|undefined>} spaceInfoPromise Promise to be
-   *     fulfilled with space info.
-   * @param {boolean} showLoadingCaption Whether to show the loading caption or
-   *     not.
+   * @param {Promise<chrome.fileManagerPrivate.MountPointSizeStats|undefined>}
+   * spaceInfoPromise Promise to be fulfilled with space info.
+   * @param {boolean} showLoadingCaption Whether show loading caption or not.
    */
   setSpaceInfo(spaceInfoPromise, showLoadingCaption) {
     this.spaceInfoPromise_ = spaceInfoPromise;
 
     if (!spaceInfoPromise || loadTimeData.getBoolean('HIDE_SPACE_INFO')) {
-      this.hideVolumeSpaceInfo_();
+      this.volumeSpaceInfo.hidden = true;
+      this.volumeSpaceInfoSeparator_.hidden = true;
       return;
     }
 
-    this.showVolumeSpaceInfo_();
+    this.volumeSpaceInfo.hidden = false;
+    this.volumeSpaceInfoSeparator_.hidden = false;
     this.volumeSpaceInnerBar_.setAttribute('pending', '');
     if (showLoadingCaption) {
       this.volumeSpaceInfoLabel_.innerText = str('WAITING_FOR_SPACE_INFO');
@@ -124,51 +112,26 @@
           if (this.spaceInfoPromise_ != spaceInfoPromise) {
             return;
           }
-
           this.volumeSpaceInnerBar_.removeAttribute('pending');
           this.volumeSpaceOuterBar_.hidden = true;
-          this.volumeSpaceWarning_.hidden = true;
-
-          if (!spaceInfo) {
-            this.volumeSpaceInfoLabel_.textContent = str('FAILED_SPACE_INFO');
-            return;
-          }
-
-          if (spaceInfo.totalSize >= 0) {
-            const usedSpace = spaceInfo.usedSize;
-            this.volumeSpaceInnerBar_.style.width =
-                Math.min(100, 100 * usedSpace / spaceInfo.totalSize) + '%';
-
-            this.volumeSpaceOuterBar_.hidden = false;
-
-            this.volumeSpaceInfoLabel_.textContent = strf(
-                'SPACE_AVAILABLE',
-                util.bytesToString(
-                    Math.max(0, spaceInfo.totalSize - spaceInfo.usedSize)));
-          } else {
-            // User has unlimited individual storage.
+          if (spaceInfo) {
+            const sizeStr = util.bytesToString(spaceInfo.remainingSize);
             this.volumeSpaceInfoLabel_.textContent =
-                strf('SPACE_USED', util.bytesToString(spaceInfo.usedSize));
-          }
+                strf('SPACE_AVAILABLE', sizeStr);
 
-          if (spaceInfo.warningMessage) {
-            this.volumeSpaceWarning_.hidden = false;
-            this.volumeSpaceWarning_.textContent =
-                '*' + spaceInfo.warningMessage;
+            if (spaceInfo.totalSize > 0) {
+              const usedSpace = spaceInfo.totalSize - spaceInfo.remainingSize;
+              this.volumeSpaceInnerBar_.style.width =
+                  (100 * usedSpace / spaceInfo.totalSize) + '%';
+
+              this.volumeSpaceOuterBar_.hidden = false;
+            }
+          } else {
+            this.volumeSpaceInfoLabel_.textContent = str('FAILED_SPACE_INFO');
           }
         },
         error => {
           console.warn('Failed get space info', error);
         });
   }
-
-  hideVolumeSpaceInfo_() {
-    this.volumeSpaceInfo.hidden = true;
-    this.volumeSpaceInfoSeparator_.hidden = true;
-  }
-
-  showVolumeSpaceInfo_() {
-    this.volumeSpaceInfo.hidden = false;
-    this.volumeSpaceInfoSeparator_.hidden = false;
-  }
 }
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html
index 685961e..15af0f8 100644
--- a/ui/file_manager/file_manager/main.html
+++ b/ui/file_manager/file_manager/main.html
@@ -300,7 +300,6 @@
             <div class="progress-bar" aria-hidden="true">
               <div class="progress-track" id="volume-space-info-bar"></div>
             </div>
-            <div id="volume-space-info-warning" class="menu-warning"></div>
           </div>
         </cr-menu-item>
       </cr-menu>
diff --git a/ui/file_manager/integration_tests/file_manager/gear_menu.js b/ui/file_manager/integration_tests/file_manager/gear_menu.js
index f8ae65b4..0dc1b67 100644
--- a/ui/file_manager/integration_tests/file_manager/gear_menu.js
+++ b/ui/file_manager/integration_tests/file_manager/gear_menu.js
@@ -575,7 +575,7 @@
 };
 
 /**
- * Tests that the "xGB available" message appears in the gear menu for
+ * Tests that the "xGB available message appears in the gear menu for
  * the "Google Drive" volume.
  */
 testcase.showAvailableStorageDrive = async () => {
@@ -589,19 +589,17 @@
   // Wait for the gear menu to appear.
   await remoteCall.waitForElement(appId, '#gear-menu:not([hidden])');
 
-  // Check #volume-storage is displayed and get a reference to it.
-  const driveMenuEntry = await remoteCall.waitForElement(
+  // Check #volume-storage is shown and disabled (can't manage Drive
+  // storage).
+  await remoteCall.waitForElement(
       appId,
       '#gear-menu:not([hidden]) cr-menu-item' +
           '[command=\'#volume-storage\']' +
           ':not([hidden])');
-
-  // Check that it correctly indicates the available storage.
-  chrome.test.assertTrue(driveMenuEntry.text.trim() === '1 MB available');
 };
 
 /**
- * Tests that the "xGB available" message appears in the gear menu for
+ * Tests that the "xGB available message appears in the gear menu for
  * an SMB volume.
  */
 testcase.showAvailableStorageSmbfs = async () => {
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index a5f5758b..f1cea8485 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -788,7 +788,6 @@
         "widget/desktop_aura/desktop_screen_position_client.cc",
         "widget/desktop_aura/desktop_window_tree_host.cc",
       ]
-      public_deps += [ "//ui/aura/cursor" ]
       if (is_win) {
         public += [ "widget/desktop_aura/desktop_window_tree_host_win.h" ]
         sources += [
diff --git a/ui/views/controls/combobox/combobox_menu_model.cc b/ui/views/controls/combobox/combobox_menu_model.cc
index 156c178..e800e79 100644
--- a/ui/views/controls/combobox/combobox_menu_model.cc
+++ b/ui/views/controls/combobox/combobox_menu_model.cc
@@ -16,35 +16,34 @@
 
 // Overridden from MenuModel:
 bool ComboboxMenuModel::HasIcons() const {
-  for (size_t i = 0; i < GetItemCount(); ++i) {
+  for (int i = 0; i < GetItemCount(); ++i) {
     if (!GetIconAt(i).IsEmpty())
       return true;
   }
   return false;
 }
 
-size_t ComboboxMenuModel::GetItemCount() const {
+int ComboboxMenuModel::GetItemCount() const {
   return model_->GetItemCount();
 }
 
-ui::MenuModel::ItemType ComboboxMenuModel::GetTypeAt(size_t index) const {
+ui::MenuModel::ItemType ComboboxMenuModel::GetTypeAt(int index) const {
   if (model_->IsItemSeparatorAt(index))
     return TYPE_SEPARATOR;
   return UseCheckmarks() ? TYPE_CHECK : TYPE_COMMAND;
 }
 
-ui::MenuSeparatorType ComboboxMenuModel::GetSeparatorTypeAt(
-    size_t index) const {
+ui::MenuSeparatorType ComboboxMenuModel::GetSeparatorTypeAt(int index) const {
   return ui::NORMAL_SEPARATOR;
 }
 
-int ComboboxMenuModel::GetCommandIdAt(size_t index) const {
+int ComboboxMenuModel::GetCommandIdAt(int index) const {
   // Define the id of the first item in the menu (since it needs to be > 0)
   constexpr int kFirstMenuItemId = 1000;
-  return static_cast<int>(index) + kFirstMenuItemId;
+  return index + kFirstMenuItemId;
 }
 
-std::u16string ComboboxMenuModel::GetLabelAt(size_t index) const {
+std::u16string ComboboxMenuModel::GetLabelAt(int index) const {
   // Inserting the Unicode formatting characters if necessary so that the
   // text is displayed correctly in right-to-left UIs.
   std::u16string text = model_->GetDropDownTextAt(index);
@@ -52,21 +51,21 @@
   return text;
 }
 
-std::u16string ComboboxMenuModel::GetSecondaryLabelAt(size_t index) const {
+std::u16string ComboboxMenuModel::GetSecondaryLabelAt(int index) const {
   std::u16string text = model_->GetDropDownSecondaryTextAt(index);
   base::i18n::AdjustStringForLocaleDirection(&text);
   return text;
 }
 
-bool ComboboxMenuModel::IsItemDynamicAt(size_t index) const {
+bool ComboboxMenuModel::IsItemDynamicAt(int index) const {
   return true;
 }
 
-const gfx::FontList* ComboboxMenuModel::GetLabelFontListAt(size_t index) const {
+const gfx::FontList* ComboboxMenuModel::GetLabelFontListAt(int index) const {
   return &owner_->GetFontList();
 }
 
-bool ComboboxMenuModel::GetAcceleratorAt(size_t index,
+bool ComboboxMenuModel::GetAcceleratorAt(int index,
                                          ui::Accelerator* accelerator) const {
   return false;
 }
@@ -75,31 +74,31 @@
   return UseCheckmarks() && index == owner_->GetSelectedIndex();
 }
 
-int ComboboxMenuModel::GetGroupIdAt(size_t index) const {
+int ComboboxMenuModel::GetGroupIdAt(int index) const {
   return -1;
 }
 
-ui::ImageModel ComboboxMenuModel::GetIconAt(size_t index) const {
+ui::ImageModel ComboboxMenuModel::GetIconAt(int index) const {
   return model_->GetDropDownIconAt(index);
 }
 
 ui::ButtonMenuItemModel* ComboboxMenuModel::GetButtonMenuItemAt(
-    size_t index) const {
+    int index) const {
   return nullptr;
 }
 
-bool ComboboxMenuModel::IsEnabledAt(size_t index) const {
+bool ComboboxMenuModel::IsEnabledAt(int index) const {
   return model_->IsItemEnabledAt(index);
 }
 
-void ComboboxMenuModel::ActivatedAt(size_t index) {
+void ComboboxMenuModel::ActivatedAt(int index) {
   owner_->MenuSelectionAt(index);
 }
 
-void ComboboxMenuModel::ActivatedAt(size_t index, int event_flags) {
+void ComboboxMenuModel::ActivatedAt(int index, int event_flags) {
   ActivatedAt(index);
 }
 
-ui::MenuModel* ComboboxMenuModel::GetSubmenuModelAt(size_t index) const {
+ui::MenuModel* ComboboxMenuModel::GetSubmenuModelAt(int index) const {
   return nullptr;
 }
diff --git a/ui/views/controls/combobox/combobox_menu_model.h b/ui/views/controls/combobox/combobox_menu_model.h
index 0656b73..ebce201 100644
--- a/ui/views/controls/combobox/combobox_menu_model.h
+++ b/ui/views/controls/combobox/combobox_menu_model.h
@@ -28,24 +28,23 @@
 
   // Overridden from MenuModel:
   bool HasIcons() const override;
-  size_t GetItemCount() const override;
-  ui::MenuModel::ItemType GetTypeAt(size_t index) const override;
-  ui::MenuSeparatorType GetSeparatorTypeAt(size_t index) const override;
-  int GetCommandIdAt(size_t index) const override;
-  std::u16string GetLabelAt(size_t index) const override;
-  std::u16string GetSecondaryLabelAt(size_t index) const override;
-  bool IsItemDynamicAt(size_t index) const override;
-  const gfx::FontList* GetLabelFontListAt(size_t index) const override;
-  bool GetAcceleratorAt(size_t index,
-                        ui::Accelerator* accelerator) const override;
+  int GetItemCount() const override;
+  ui::MenuModel::ItemType GetTypeAt(int index) const override;
+  ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override;
+  int GetCommandIdAt(int index) const override;
+  std::u16string GetLabelAt(int index) const override;
+  std::u16string GetSecondaryLabelAt(int index) const override;
+  bool IsItemDynamicAt(int index) const override;
+  const gfx::FontList* GetLabelFontListAt(int index) const override;
+  bool GetAcceleratorAt(int index, ui::Accelerator* accelerator) const override;
   bool IsItemCheckedAt(size_t index) const override;
-  int GetGroupIdAt(size_t index) const override;
-  ui::ImageModel GetIconAt(size_t index) const override;
-  ui::ButtonMenuItemModel* GetButtonMenuItemAt(size_t index) const override;
-  bool IsEnabledAt(size_t index) const override;
-  void ActivatedAt(size_t index) override;
-  void ActivatedAt(size_t index, int event_flags) override;
-  ui::MenuModel* GetSubmenuModelAt(size_t index) const override;
+  int GetGroupIdAt(int index) const override;
+  ui::ImageModel GetIconAt(int index) const override;
+  ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override;
+  bool IsEnabledAt(int index) const override;
+  void ActivatedAt(int index) override;
+  void ActivatedAt(int index, int event_flags) override;
+  ui::MenuModel* GetSubmenuModelAt(int index) const override;
 
   raw_ptr<views::Combobox> owner_;    // Weak. Owns this.
   raw_ptr<ui::ComboboxModel> model_;  // Weak.
diff --git a/ui/views/controls/combobox/combobox_unittest.cc b/ui/views/controls/combobox/combobox_unittest.cc
index 00dc0cd..d382986 100644
--- a/ui/views/controls/combobox/combobox_unittest.cc
+++ b/ui/views/controls/combobox/combobox_unittest.cc
@@ -828,7 +828,8 @@
 
   ui::MenuModel* menu_model = test_api_->menu_model();
 
-  EXPECT_EQ(TestComboboxModel::kItemCount, menu_model->GetItemCount());
+  EXPECT_EQ(TestComboboxModel::kItemCount,
+            static_cast<size_t>(menu_model->GetItemCount()));
   EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR,
             menu_model->GetTypeAt(kSeparatorIndex));
 
diff --git a/ui/views/controls/editable_combobox/editable_combobox.cc b/ui/views/controls/editable_combobox/editable_combobox.cc
index e94fafd..f02a2ba 100644
--- a/ui/views/controls/editable_combobox/editable_combobox.cc
+++ b/ui/views/controls/editable_combobox/editable_combobox.cc
@@ -176,8 +176,8 @@
     return MenuConfig::instance().check_selected_combobox_item;
   }
 
-  std::u16string GetItemTextAt(size_t index, bool showing_password_text) const {
-    size_t index_in_model = items_shown_[index].index;
+  std::u16string GetItemTextAt(int index, bool showing_password_text) const {
+    int index_in_model = items_shown_[index].index;
     std::u16string text = combobox_model_->GetItemAt(index_in_model);
     return showing_password_text
                ? text
@@ -185,7 +185,7 @@
                                 gfx::RenderText::kPasswordReplacementChar);
   }
 
-  ui::ImageModel GetIconAt(size_t index) const override {
+  ui::ImageModel GetIconAt(int index) const override {
     return combobox_model_->GetDropDownIconAt(items_shown_[index].index);
   }
 
@@ -198,7 +198,7 @@
     observation_.Reset();
   }
 
-  size_t GetItemCount() const override { return items_shown_.size(); }
+  int GetItemCount() const override { return items_shown_.size(); }
 
  private:
   struct ShownItem {
@@ -206,39 +206,39 @@
     bool enabled;
   };
   bool HasIcons() const override {
-    for (size_t i = 0; i < GetItemCount(); ++i) {
+    for (int i = 0; i < GetItemCount(); ++i) {
       if (!GetIconAt(i).IsEmpty())
         return true;
     }
     return false;
   }
 
-  ItemType GetTypeAt(size_t index) const override {
+  ItemType GetTypeAt(int index) const override {
     return UseCheckmarks() ? TYPE_CHECK : TYPE_COMMAND;
   }
 
-  ui::MenuSeparatorType GetSeparatorTypeAt(size_t index) const override {
+  ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override {
     return ui::NORMAL_SEPARATOR;
   }
 
-  int GetCommandIdAt(size_t index) const override {
+  int GetCommandIdAt(int index) const override {
     constexpr int kFirstMenuItemId = 1000;
-    return static_cast<int>(index) + kFirstMenuItemId;
+    return index + kFirstMenuItemId;
   }
 
-  std::u16string GetLabelAt(size_t index) const override {
+  std::u16string GetLabelAt(int index) const override {
     std::u16string text = GetItemTextAt(index, owner_->showing_password_text_);
     base::i18n::AdjustStringForLocaleDirection(&text);
     return text;
   }
 
-  bool IsItemDynamicAt(size_t index) const override { return false; }
+  bool IsItemDynamicAt(int index) const override { return false; }
 
-  const gfx::FontList* GetLabelFontListAt(size_t index) const override {
+  const gfx::FontList* GetLabelFontListAt(int index) const override {
     return &owner_->GetFontList();
   }
 
-  bool GetAcceleratorAt(size_t index,
+  bool GetAcceleratorAt(int index,
                         ui::Accelerator* accelerator) const override {
     return false;
   }
@@ -249,19 +249,19 @@
                owner_->GetText();
   }
 
-  int GetGroupIdAt(size_t index) const override { return -1; }
+  int GetGroupIdAt(int index) const override { return -1; }
 
-  ui::ButtonMenuItemModel* GetButtonMenuItemAt(size_t index) const override {
+  ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override {
     return nullptr;
   }
 
-  bool IsEnabledAt(size_t index) const override {
+  bool IsEnabledAt(int index) const override {
     return items_shown_[index].enabled;
   }
 
-  void ActivatedAt(size_t index) override { owner_->OnItemSelected(index); }
+  void ActivatedAt(int index) override { owner_->OnItemSelected(index); }
 
-  MenuModel* GetSubmenuModelAt(size_t index) const override { return nullptr; }
+  MenuModel* GetSubmenuModelAt(int index) const override { return nullptr; }
 
   raw_ptr<EditableCombobox> owner_;            // Weak. Owns |this|.
   raw_ptr<ui::ComboboxModel> combobox_model_;  // Weak.
diff --git a/ui/views/controls/menu/menu_model_adapter.cc b/ui/views/controls/menu/menu_model_adapter.cc
index 45b0ba5..fb5d5e6 100644
--- a/ui/views/controls/menu/menu_model_adapter.cc
+++ b/ui/views/controls/menu/menu_model_adapter.cc
@@ -154,7 +154,7 @@
 
 void MenuModelAdapter::ExecuteCommand(int id) {
   ui::MenuModel* model = menu_model_;
-  size_t index = 0;
+  int index = 0;
   if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) {
     model->ActivatedAt(index);
     return;
@@ -165,7 +165,7 @@
 
 void MenuModelAdapter::ExecuteCommand(int id, int mouse_event_flags) {
   ui::MenuModel* model = menu_model_;
-  size_t index = 0;
+  int index = 0;
   if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) {
     model->ActivatedAt(index, mouse_event_flags);
     return;
@@ -184,7 +184,7 @@
 bool MenuModelAdapter::GetAccelerator(int id,
                                       ui::Accelerator* accelerator) const {
   ui::MenuModel* model = menu_model_;
-  size_t index = 0;
+  int index = 0;
   if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index))
     return model->GetAcceleratorAt(index, accelerator);
 
@@ -194,7 +194,7 @@
 
 std::u16string MenuModelAdapter::GetLabel(int id) const {
   ui::MenuModel* model = menu_model_;
-  size_t index = 0;
+  int index = 0;
   if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index))
     return model->GetLabelAt(index);
 
@@ -204,7 +204,7 @@
 
 const gfx::FontList* MenuModelAdapter::GetLabelFontList(int id) const {
   ui::MenuModel* model = menu_model_;
-  size_t index = 0;
+  int index = 0;
   if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) {
     const gfx::FontList* font_list = model->GetLabelFontListAt(index);
     if (font_list)
@@ -217,7 +217,7 @@
 
 bool MenuModelAdapter::IsCommandEnabled(int id) const {
   ui::MenuModel* model = menu_model_;
-  size_t index = 0;
+  int index = 0;
   if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index))
     return model->IsEnabledAt(index);
 
@@ -227,7 +227,7 @@
 
 bool MenuModelAdapter::IsCommandVisible(int id) const {
   ui::MenuModel* model = menu_model_;
-  size_t index = 0;
+  int index = 0;
   if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index))
     return model->IsVisibleAt(index);
 
@@ -237,7 +237,7 @@
 
 bool MenuModelAdapter::IsItemChecked(int id) const {
   ui::MenuModel* model = menu_model_;
-  size_t index = 0;
+  int index = 0;
   if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index))
     return model->IsItemCheckedAt(index);
 
@@ -290,8 +290,8 @@
   DCHECK(menu);
   DCHECK(model);
   bool has_icons = model->HasIcons();
-  const size_t item_count = model->GetItemCount();
-  for (size_t i = 0; i < item_count; ++i) {
+  const int item_count = model->GetItemCount();
+  for (int i = 0; i < item_count; ++i) {
     MenuItemView* item = AppendMenuItem(menu, model, i);
     if (item) {
       // Enabled state should be ignored for titles as they are non-interactive.
diff --git a/ui/views/controls/menu/menu_model_adapter_unittest.cc b/ui/views/controls/menu/menu_model_adapter_unittest.cc
index 5164ca6..2f53921 100644
--- a/ui/views/controls/menu/menu_model_adapter_unittest.cc
+++ b/ui/views/controls/menu/menu_model_adapter_unittest.cc
@@ -27,7 +27,7 @@
 class MenuModelBase : public ui::MenuModel {
  public:
   explicit MenuModelBase(int command_id_base)
-      : command_id_base_(command_id_base) {}
+      : command_id_base_(command_id_base), last_activation_(-1) {}
 
   MenuModelBase(const MenuModelBase&) = delete;
   MenuModelBase& operator=(const MenuModelBase&) = delete;
@@ -38,70 +38,62 @@
 
   bool HasIcons() const override { return false; }
 
-  size_t GetItemCount() const override { return items_.size(); }
+  int GetItemCount() const override { return static_cast<int>(items_.size()); }
 
-  ItemType GetTypeAt(size_t index) const override { return items_[index].type; }
+  ItemType GetTypeAt(int index) const override { return items_[index].type; }
 
-  ui::MenuSeparatorType GetSeparatorTypeAt(size_t index) const override {
+  ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override {
     return ui::NORMAL_SEPARATOR;
   }
 
-  int GetCommandIdAt(size_t index) const override {
-    return static_cast<int>(index) + command_id_base_;
+  int GetCommandIdAt(int index) const override {
+    return index + command_id_base_;
   }
 
-  std::u16string GetLabelAt(size_t index) const override {
+  std::u16string GetLabelAt(int index) const override {
     return items_[index].label;
   }
 
-  bool IsItemDynamicAt(size_t index) const override { return false; }
+  bool IsItemDynamicAt(int index) const override { return false; }
 
-  const gfx::FontList* GetLabelFontListAt(size_t index) const override {
+  const gfx::FontList* GetLabelFontListAt(int index) const override {
     return nullptr;
   }
 
-  bool GetAcceleratorAt(size_t index,
+  bool GetAcceleratorAt(int index,
                         ui::Accelerator* accelerator) const override {
     return false;
   }
 
   bool IsItemCheckedAt(size_t index) const override { return false; }
 
-  int GetGroupIdAt(size_t index) const override { return 0; }
+  int GetGroupIdAt(int index) const override { return 0; }
 
-  ui::ImageModel GetIconAt(size_t index) const override {
+  ui::ImageModel GetIconAt(int index) const override {
     return ui::ImageModel();
   }
 
-  ui::ButtonMenuItemModel* GetButtonMenuItemAt(size_t index) const override {
+  ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override {
     return nullptr;
   }
 
-  bool IsEnabledAt(size_t index) const override {
-    return items_[index].enabled;
-  }
+  bool IsEnabledAt(int index) const override { return items_[index].enabled; }
 
-  bool IsVisibleAt(size_t index) const override {
-    return items_[index].visible;
-  }
+  bool IsVisibleAt(int index) const override { return items_[index].visible; }
 
-  bool IsAlertedAt(size_t index) const override {
-    return items_[index].alerted;
-  }
+  bool IsAlertedAt(int index) const override { return items_[index].alerted; }
 
-  bool IsNewFeatureAt(size_t index) const override {
+  bool IsNewFeatureAt(int index) const override {
     return items_[index].new_feature;
   }
 
-  MenuModel* GetSubmenuModelAt(size_t index) const override {
+  MenuModel* GetSubmenuModelAt(int index) const override {
     return items_[index].submenu;
   }
 
-  void ActivatedAt(size_t index) override { set_last_activation(index); }
+  void ActivatedAt(int index) override { set_last_activation(index); }
 
-  void ActivatedAt(size_t index, int event_flags) override {
-    ActivatedAt(index);
-  }
+  void ActivatedAt(int index, int event_flags) override { ActivatedAt(index); }
 
   void MenuWillShow() override {}
 
@@ -141,8 +133,8 @@
   const Item& GetItemDefinition(size_t index) { return items_[index]; }
 
   // Access index argument to ActivatedAt().
-  absl::optional<size_t> last_activation() const { return last_activation_; }
-  void set_last_activation(absl::optional<size_t> last_activation) {
+  int last_activation() const { return last_activation_; }
+  void set_last_activation(int last_activation) {
     last_activation_ = last_activation;
   }
 
@@ -151,7 +143,7 @@
 
  private:
   int command_id_base_;
-  absl::optional<size_t> last_activation_;
+  int last_activation_;
 };
 
 class SubmenuModel : public MenuModelBase {
@@ -212,7 +204,7 @@
                   views::MenuModelAdapter* delegate,
                   int submenu_id,
                   size_t expected_children,
-                  size_t submenu_model_index,
+                  int submenu_model_index,
                   int id) {
   views::MenuItemView* submenu = menu->GetMenuItemByID(submenu_id);
   views::SubmenuView* subitem_container = submenu->GetSubmenu();
@@ -275,8 +267,8 @@
 
     // Check activation.
     static_cast<views::MenuDelegate*>(delegate)->ExecuteCommand(id);
-    EXPECT_EQ(i, submodel->last_activation());
-    submodel->set_last_activation(absl::nullopt);
+    EXPECT_EQ(i, static_cast<size_t>(submodel->last_activation()));
+    submodel->set_last_activation(-1);
   }
 }
 
@@ -359,8 +351,8 @@
 
     // Check activation.
     static_cast<views::MenuDelegate*>(&delegate)->ExecuteCommand(id);
-    EXPECT_EQ(i, model.last_activation());
-    model.set_last_activation(absl::nullopt);
+    EXPECT_EQ(i, static_cast<size_t>(model.last_activation()));
+    model.set_last_activation(-1);
   }
 
   // Check the submenu.
diff --git a/ui/views/controls/menu/menu_runner_impl_cocoa.mm b/ui/views/controls/menu/menu_runner_impl_cocoa.mm
index 46722c1..6f92eb0 100644
--- a/ui/views/controls/menu/menu_runner_impl_cocoa.mm
+++ b/ui/views/controls/menu/menu_runner_impl_cocoa.mm
@@ -242,12 +242,12 @@
 }
 
 - (void)controllerWillAddMenu:(NSMenu*)menu fromModel:(ui::MenuModel*)model {
-  absl::optional<size_t> alerted_index;
+  int alerted_index = -1;
   IdentifierContainer* const element_ids =
       [[[IdentifierContainer alloc] init] autorelease];
-  for (size_t i = 0; i < model->GetItemCount(); ++i) {
+  for (int i = 0; i < model->GetItemCount(); ++i) {
     if (model->IsAlertedAt(i)) {
-      DCHECK(!alerted_index.has_value());
+      DCHECK_LT(alerted_index, 0);
       alerted_index = i;
     }
     const ui::ElementIdentifier identifier = model->GetElementIdentifierAt(i);
@@ -255,14 +255,14 @@
       [element_ids ids].push_back(identifier);
   }
 
-  if (alerted_index.has_value() || ![element_ids ids].empty()) {
+  if (alerted_index >= 0 || ![element_ids ids].empty()) {
     auto shown_callback = ^(NSNotification* note) {
       NSMenu* const menu_obj = note.object;
-      if (alerted_index.has_value()) {
+      if (alerted_index >= 0) {
         if ([menu respondsToSelector:@selector(_menuImpl)]) {
           NSCarbonMenuImpl* menuImpl = [menu_obj _menuImpl];
           if ([menuImpl respondsToSelector:@selector(highlightItemAtIndex:)]) {
-            [menuImpl highlightItemAtIndex:alerted_index.value()];
+            [menuImpl highlightItemAtIndex:alerted_index];
           }
         }
       }
diff --git a/ui/views/controls/menu/native_menu_win.cc b/ui/views/controls/menu/native_menu_win.cc
index ca62ed3..3a62f75f 100644
--- a/ui/views/controls/menu/native_menu_win.cc
+++ b/ui/views/controls/menu/native_menu_win.cc
@@ -69,9 +69,9 @@
 
   owner_draw_ = model_->HasIcons() || owner_draw_;
   first_item_index_ = delegate ? delegate->GetInsertionIndex(menu_) : 0;
-  for (size_t model_index = 0; model_index < model_->GetItemCount();
+  for (int model_index = 0; model_index < model_->GetItemCount();
        ++model_index) {
-    size_t menu_index = model_index + first_item_index_;
+    int menu_index = model_index + first_item_index_;
     if (model_->GetTypeAt(model_index) == ui::MenuModel::TYPE_SEPARATOR)
       AddSeparatorItemAt(menu_index, model_index);
     else
@@ -83,7 +83,7 @@
   // A depth-first walk of the menu items, updating states.
   int model_index = 0;
   for (const auto& item : items_) {
-    size_t menu_index = model_index + first_item_index_;
+    int menu_index = model_index + first_item_index_;
     SetMenuItemState(menu_index, model_->IsEnabledAt(model_index),
                      model_->IsItemCheckedAt(model_index), false);
     if (model_->IsItemDynamicAt(model_index)) {
diff --git a/ui/views/controls/menu/native_menu_win.h b/ui/views/controls/menu/native_menu_win.h
index bfd6503..c4c8341 100644
--- a/ui/views/controls/menu/native_menu_win.h
+++ b/ui/views/controls/menu/native_menu_win.h
@@ -99,7 +99,7 @@
   HWND system_menu_for_;
 
   // The index of the first item in the model in the menu.
-  size_t first_item_index_;
+  int first_item_index_;
 
   // If we're a submenu, this is our parent.
   raw_ptr<NativeMenuWin> parent_;
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc
index 7d74ba3..3ea9cef 100644
--- a/ui/views/controls/textfield/textfield_unittest.cc
+++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -3879,7 +3879,7 @@
   // A normal empty field may show the Emoji option (if supported).
   ui::MenuModel* context_menu = GetContextMenuModel();
   EXPECT_TRUE(context_menu);
-  EXPECT_GT(context_menu->GetItemCount(), 0u);
+  EXPECT_GT(context_menu->GetItemCount(), 0);
   // Not all OS/versions support the emoji menu.
   EXPECT_EQ(ui::IsEmojiPanelSupported(),
             context_menu->GetLabelAt(0) ==
@@ -3894,7 +3894,7 @@
   // In no case is the emoji option showing on a read-only field.
   ui::MenuModel* context_menu = GetContextMenuModel();
   EXPECT_TRUE(context_menu);
-  EXPECT_GT(context_menu->GetItemCount(), 0u);
+  EXPECT_GT(context_menu->GetItemCount(), 0);
   EXPECT_NE(context_menu->GetLabelAt(0),
             l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_EMOJI));
 }
@@ -3916,7 +3916,7 @@
   textfield_->SelectAll(false);
   ui::MenuModel* context_menu = GetContextMenuModel();
   EXPECT_TRUE(context_menu);
-  EXPECT_GT(context_menu->GetItemCount(), 0u);
+  EXPECT_GT(context_menu->GetItemCount(), 0);
   // Not all OS/versions support the emoji menu.
   EXPECT_EQ(ui::IsEmojiPanelSupported(),
             context_menu->GetLabelAt(kExpectedEmojiIndex) ==
@@ -3967,7 +3967,7 @@
 
   ui::MenuModel* context_menu = GetContextMenuModel();
   EXPECT_TRUE(context_menu);
-  EXPECT_GT(context_menu->GetItemCount(), 0u);
+  EXPECT_GT(context_menu->GetItemCount(), 0);
   EXPECT_NE(context_menu->GetCommandIdAt(0), IDS_CONTENT_CONTEXT_LOOK_UP);
   EXPECT_NE(context_menu->GetLabelAt(0),
             l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_LOOK_UP, kText));
diff --git a/ui/views/interaction/interaction_sequence_views_unittest.cc b/ui/views/interaction/interaction_sequence_views_unittest.cc
index 4ff6c40c..3936e91 100644
--- a/ui/views/interaction/interaction_sequence_views_unittest.cc
+++ b/ui/views/interaction/interaction_sequence_views_unittest.cc
@@ -166,7 +166,7 @@
     menu_model_->AddItem(kMenuID1, kMenuItem1);
     menu_model_->AddItem(kMenuID2, kMenuItem2);
     menu_model_->SetElementIdentifierAt(
-        menu_model_->GetIndexOfCommandId(kMenuID2).value(), id);
+        menu_model_->GetIndexOfCommandId(kMenuID2), id);
 
     menu_runner_ =
         std::make_unique<MenuRunner>(menu_model_.get(), MenuRunner::NO_FLAGS);
diff --git a/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc b/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc
index 235ddf884..79cd1fc 100644
--- a/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc
@@ -7,10 +7,10 @@
 #include <utility>
 
 #include "base/trace_event/trace_event.h"
-#include "ui/aura/cursor/cursor_loader.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
+#include "ui/wm/core/cursor_loader.h"
 
 namespace views {
 
diff --git a/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h b/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h
index 0961f4a..5634eaa 100644
--- a/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h
+++ b/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h
@@ -8,8 +8,8 @@
 #include <memory>
 #include <set>
 
-#include "ui/aura/cursor/cursor_loader.h"
 #include "ui/views/views_export.h"
+#include "ui/wm/core/cursor_loader.h"
 #include "ui/wm/core/native_cursor_manager.h"
 
 namespace aura {
@@ -63,7 +63,7 @@
   using Hosts = std::set<aura::WindowTreeHost*>;
   Hosts hosts_;
 
-  aura::CursorLoader cursor_loader_;
+  wm::CursorLoader cursor_loader_;
 };
 
 }  // namespace views
diff --git a/ui/wm/BUILD.gn b/ui/wm/BUILD.gn
index 5ced3cfb..9aa7bb7 100644
--- a/ui/wm/BUILD.gn
+++ b/ui/wm/BUILD.gn
@@ -22,8 +22,16 @@
     "core/compound_event_filter.h",
     "core/coordinate_conversion.cc",
     "core/coordinate_conversion.h",
+    "core/cursor_loader.cc",
+    "core/cursor_loader.h",
+    "core/cursor_lookup.cc",
+    "core/cursor_lookup.h",
     "core/cursor_manager.cc",
     "core/cursor_manager.h",
+    "core/cursor_util.cc",
+    "core/cursor_util.h",
+    "core/cursors_aura.cc",
+    "core/cursors_aura.h",
     "core/default_activation_client.cc",
     "core/default_activation_client.h",
     "core/default_screen_position_client.cc",
@@ -66,29 +74,30 @@
   configs += [ "//build/config:precompiled_headers" ]
   defines = [ "IS_UI_WM_IMPL" ]
 
-  deps = [
+  public_deps = [
     "//base",
     "//build:chromeos_buildflags",
-    "//skia",
     "//ui/aura",
     "//ui/base",
     "//ui/base/cursor",
     "//ui/base/cursor/mojom:cursor_type",
-    "//ui/base/ime",
     "//ui/compositor",
-    "//ui/compositor_extra",
     "//ui/display",
     "//ui/events",
-    "//ui/events:events_base",
-    "//ui/events/devices",
-    "//ui/events/platform",
     "//ui/gfx",
-    "//ui/gfx/animation",
     "//ui/gfx/geometry",
-    "//ui/resources",
     "//ui/wm/public",
   ]
 
+  deps = [
+    "//skia",
+    "//ui/base/ime",
+    "//ui/compositor_extra",
+    "//ui/events/platform",
+    "//ui/gfx/animation",
+    "//ui/resources",
+  ]
+
   if (is_chromeos_ash) {
     sources += [
       "core/ime_util_chromeos.cc",
@@ -133,7 +142,9 @@
     "core/capture_controller_unittest.cc",
     "core/compound_event_filter_unittest.cc",
     "core/coordinate_conversion_unittest.cc",
+    "core/cursor_loader_unittest.cc",
     "core/cursor_manager_unittest.cc",
+    "core/cursor_util_unittest.cc",
     "core/focus_controller_unittest.cc",
     "core/shadow_controller_unittest.cc",
     "core/transient_window_manager_unittest.cc",
@@ -154,6 +165,7 @@
     "//skia",
     "//testing/gtest",
     "//ui/aura:test_support",
+    "//ui/base",
     "//ui/base:test_support",
     "//ui/base/cursor",
     "//ui/base/cursor/mojom:cursor_type",
@@ -163,6 +175,7 @@
     "//ui/events:test_support",
     "//ui/events/platform",
     "//ui/gfx",
+    "//ui/gfx:gfx_skia",
     "//ui/gfx/animation",
     "//ui/gfx/geometry",
     "//ui/gl:test_support",
diff --git a/ui/wm/core/OWNERS b/ui/wm/core/OWNERS
index 5c9931ca..127c209 100644
--- a/ui/wm/core/OWNERS
+++ b/ui/wm/core/OWNERS
@@ -1 +1,2 @@
+per-file cursor*=file://ui/base/cursor/OWNERS
 per-file shadow*=estade@chromium.org
diff --git a/ui/aura/cursor/cursor_loader.cc b/ui/wm/core/cursor_loader.cc
similarity index 95%
rename from ui/aura/cursor/cursor_loader.cc
rename to ui/wm/core/cursor_loader.cc
index 60426ff7..0ff466a1 100644
--- a/ui/aura/cursor/cursor_loader.cc
+++ b/ui/wm/core/cursor_loader.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/aura/cursor/cursor_loader.h"
+#include "ui/wm/core/cursor_loader.h"
 
 #include <map>
 #include <vector>
@@ -10,16 +10,16 @@
 #include "base/check.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/time/time.h"
-#include "ui/aura/cursor/cursor_util.h"
-#include "ui/aura/cursor/cursors_aura.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/cursor/cursor_factory.h"
 #include "ui/base/cursor/cursor_size.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom.h"
 #include "ui/base/cursor/platform_cursor.h"
 #include "ui/gfx/geometry/point.h"
+#include "ui/wm/core/cursor_util.h"
+#include "ui/wm/core/cursors_aura.h"
 
-namespace aura {
+namespace wm {
 
 namespace {
 
@@ -141,4 +141,4 @@
   return nullptr;
 }
 
-}  // namespace aura
+}  // namespace wm
diff --git a/ui/aura/cursor/cursor_loader.h b/ui/wm/core/cursor_loader.h
similarity index 90%
rename from ui/aura/cursor/cursor_loader.h
rename to ui/wm/core/cursor_loader.h
index 91a7150..8cdb35a8 100644
--- a/ui/aura/cursor/cursor_loader.h
+++ b/ui/wm/core/cursor_loader.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_AURA_CURSOR_CURSOR_LOADER_H_
-#define UI_AURA_CURSOR_CURSOR_LOADER_H_
+#ifndef UI_WM_CORE_CURSOR_LOADER_H_
+#define UI_WM_CORE_CURSOR_LOADER_H_
 
 #include <map>
 #include <memory>
@@ -25,10 +25,9 @@
 class PlatformCursor;
 }
 
-namespace aura {
+namespace wm {
 
-class COMPONENT_EXPORT(UI_AURA_CURSOR) CursorLoader
-    : public ui::CursorFactoryObserver {
+class COMPONENT_EXPORT(UI_WM) CursorLoader : public ui::CursorFactoryObserver {
  public:
   explicit CursorLoader(bool use_platform_cursors = true);
   CursorLoader(const CursorLoader&) = delete;
@@ -84,6 +83,6 @@
   ui::CursorSize size_ = ui::CursorSize::kNormal;
 };
 
-}  // namespace aura
+}  // namespace wm
 
-#endif  // UI_AURA_CURSOR_CURSOR_LOADER_H_
+#endif  // UI_WM_CORE_CURSOR_LOADER_H_
diff --git a/ui/aura/cursor/cursor_loader_unittest.cc b/ui/wm/core/cursor_loader_unittest.cc
similarity index 79%
rename from ui/aura/cursor/cursor_loader_unittest.cc
rename to ui/wm/core/cursor_loader_unittest.cc
index 64529c0..ab833f3 100644
--- a/ui/aura/cursor/cursor_loader_unittest.cc
+++ b/ui/wm/core/cursor_loader_unittest.cc
@@ -2,30 +2,26 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/aura/cursor/cursor_loader.h"
+#include "ui/wm/core/cursor_loader.h"
 
-#include "base/files/file_path.h"
 #include "base/memory/scoped_refptr.h"
-#include "base/path_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/aura/cursor/cursor_lookup.h"
-#include "ui/aura/cursor/cursors_aura.h"
 #include "ui/aura/test/aura_test_base.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/cursor/cursor_factory.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
 #include "ui/base/cursor/platform_cursor.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/base/ui_base_paths.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/skia_util.h"
+#include "ui/wm/core/cursor_lookup.h"
+#include "ui/wm/core/cursors_aura.h"
 
-namespace aura {
+namespace wm {
 
 namespace {
 
-using CursorLoaderTest = test::AuraTestBase;
+using CursorLoaderTest = ::aura::test::AuraTestBase;
 using ::ui::mojom::CursorType;
 
 SkBitmap GetTestBitmap() {
@@ -50,11 +46,6 @@
 // from cursor_lookup.h, that will be replaced by a method of the same name in
 // CursorLoader.
 TEST_F(CursorLoaderTest, GetCursorData) {
-  ui::RegisterPathProvider();
-  base::FilePath ui_test_pak_path =
-      base::PathService::CheckedGet(ui::UI_TEST_PAK);
-  ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path);
-
   const ui::Cursor invisible_cursor = CursorType::kNone;
   EXPECT_TRUE(GetCursorBitmap(invisible_cursor).isNull());
   EXPECT_TRUE(GetCursorHotspot(invisible_cursor).IsOrigin());
@@ -76,4 +67,4 @@
   EXPECT_EQ(GetCursorHotspot(custom_cursor), kHotspot);
 }
 
-}  // namespace aura
+}  // namespace wm
diff --git a/ui/aura/cursor/cursor_lookup.cc b/ui/wm/core/cursor_lookup.cc
similarity index 85%
rename from ui/aura/cursor/cursor_lookup.cc
rename to ui/wm/core/cursor_lookup.cc
index e8db14fd..f7c6646 100644
--- a/ui/aura/cursor/cursor_lookup.cc
+++ b/ui/wm/core/cursor_lookup.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/aura/cursor/cursor_lookup.h"
+#include "ui/wm/core/cursor_lookup.h"
 
 #include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/aura/cursor/cursors_aura.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
 #include "ui/gfx/geometry/point.h"
+#include "ui/wm/core/cursors_aura.h"
 
-namespace aura {
+namespace wm {
 
 SkBitmap GetCursorBitmap(const ui::Cursor& cursor) {
   if (cursor.type() == ui::mojom::CursorType::kCustom)
@@ -24,4 +24,4 @@
   return GetDefaultHotspot(cursor);
 }
 
-}  // namespace aura
+}  // namespace wm
diff --git a/ui/aura/cursor/cursor_lookup.h b/ui/wm/core/cursor_lookup.h
similarity index 63%
rename from ui/aura/cursor/cursor_lookup.h
rename to ui/wm/core/cursor_lookup.h
index 955e598..4fdc9a5 100644
--- a/ui/aura/cursor/cursor_lookup.h
+++ b/ui/wm/core/cursor_lookup.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_AURA_CURSOR_CURSOR_LOOKUP_H_
-#define UI_AURA_CURSOR_CURSOR_LOOKUP_H_
+#ifndef UI_WM_CORE_CURSOR_LOOKUP_H_
+#define UI_WM_CORE_CURSOR_LOOKUP_H_
 
 #include "base/component_export.h"
 
@@ -17,14 +17,14 @@
 class Cursor;
 }
 
-namespace aura {
+namespace wm {
 
-COMPONENT_EXPORT(UI_AURA_CURSOR)
+COMPONENT_EXPORT(UI_WM)
 SkBitmap GetCursorBitmap(const ui::Cursor& cursor);
 
-COMPONENT_EXPORT(UI_AURA_CURSOR)
+COMPONENT_EXPORT(UI_WM)
 gfx::Point GetCursorHotspot(const ui::Cursor& cursor);
 
-}  // namespace aura
+}  // namespace wm
 
-#endif  // UI_AURA_CURSOR_CURSOR_LOOKUP_H_
+#endif  // UI_WM_CORE_CURSOR_LOOKUP_H_
diff --git a/ui/aura/cursor/cursor_util.cc b/ui/wm/core/cursor_util.cc
similarity index 98%
rename from ui/aura/cursor/cursor_util.cc
rename to ui/wm/core/cursor_util.cc
index c3660ee9..5f02a8d 100644
--- a/ui/aura/cursor/cursor_util.cc
+++ b/ui/wm/core/cursor_util.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/aura/cursor/cursor_util.h"
+#include "ui/wm/core/cursor_util.h"
 
 #include "base/check_op.h"
 #include "base/notreached.h"
@@ -17,7 +17,7 @@
 #include "ui/gfx/image/image_skia_rep.h"
 #include "ui/gfx/skbitmap_operations.h"
 
-namespace aura {
+namespace wm {
 
 namespace {
 
@@ -160,4 +160,4 @@
   }
 }
 
-}  // namespace aura
+}  // namespace wm
diff --git a/ui/aura/cursor/cursor_util.h b/ui/wm/core/cursor_util.h
similarity index 86%
rename from ui/aura/cursor/cursor_util.h
rename to ui/wm/core/cursor_util.h
index 6d14a7c..5bf8350 100644
--- a/ui/aura/cursor/cursor_util.h
+++ b/ui/wm/core/cursor_util.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_AURA_CURSOR_CURSOR_UTIL_H_
-#define UI_AURA_CURSOR_CURSOR_UTIL_H_
+#ifndef UI_WM_CORE_CURSOR_UTIL_H_
+#define UI_WM_CORE_CURSOR_UTIL_H_
 
 #include <vector>
 
@@ -16,12 +16,12 @@
 class Point;
 }
 
-namespace aura {
+namespace wm {
 
 // Scale and rotate the cursor's bitmap and hotpoint.
 // |bitmap_in_out| and |hotpoint_in_out| are used as
 // both input and output.
-COMPONENT_EXPORT(UI_AURA_CURSOR)
+COMPONENT_EXPORT(UI_WM)
 void ScaleAndRotateCursorBitmapAndHotpoint(float scale,
                                            display::Display::Rotation rotation,
                                            SkBitmap* bitmap_in_out,
@@ -39,6 +39,6 @@
                               gfx::Point* hotspot,
                               std::vector<SkBitmap>* bitmaps);
 
-}  // namespace aura
+}  // namespace wm
 
-#endif  // UI_AURA_CURSOR_CURSOR_UTIL_H_
+#endif  // UI_WM_CORE_CURSOR_UTIL_H_
diff --git a/ui/aura/cursor/cursor_util_unittest.cc b/ui/wm/core/cursor_util_unittest.cc
similarity index 96%
rename from ui/aura/cursor/cursor_util_unittest.cc
rename to ui/wm/core/cursor_util_unittest.cc
index 26d1165..02f0241 100644
--- a/ui/aura/cursor/cursor_util_unittest.cc
+++ b/ui/wm/core/cursor_util_unittest.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/aura/cursor/cursor_util.h"
+#include "ui/wm/core/cursor_util.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/geometry/point.h"
 
-namespace aura {
+namespace wm {
 namespace {
 
 // Parameterized test for cursor bitmaps with premultiplied and unpremultiplied
@@ -67,4 +67,4 @@
 INSTANTIATE_TEST_SUITE_P(All, CursorUtilTest, testing::Bool());
 
 }  // namespace
-}  // namespace aura
+}  // namespace wm
diff --git a/ui/aura/cursor/cursors_aura.cc b/ui/wm/core/cursors_aura.cc
similarity index 97%
rename from ui/aura/cursor/cursors_aura.cc
rename to ui/wm/core/cursors_aura.cc
index 033fb43..94c9c89 100644
--- a/ui/aura/cursor/cursors_aura.cc
+++ b/ui/wm/core/cursors_aura.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/aura/cursor/cursors_aura.h"
+#include "ui/wm/core/cursors_aura.h"
 
 #include <stddef.h>
 
@@ -18,12 +18,12 @@
 #include "ui/resources/grit/ui_resources.h"
 
 #if BUILDFLAG(IS_WIN)
-#include "ui/aura/cursor/cursor_loader.h"
 #include "ui/base/win/win_cursor.h"
 #include "ui/gfx/icon_util.h"
+#include "ui/wm/core/cursor_loader.h"
 #endif
 
-namespace aura {
+namespace wm {
 
 namespace {
 
@@ -332,7 +332,7 @@
 SkBitmap GetDefaultBitmap(const ui::Cursor& cursor) {
 #if BUILDFLAG(IS_WIN)
   ui::Cursor cursor_copy = cursor;
-  aura::CursorLoader cursor_loader;
+  CursorLoader cursor_loader;
   cursor_loader.SetPlatformCursor(&cursor_copy);
   return IconUtil::CreateSkBitmapFromHICON(
       ui::WinCursor::FromPlatformCursor(cursor_copy.platform())->hcursor());
@@ -353,7 +353,7 @@
 gfx::Point GetDefaultHotspot(const ui::Cursor& cursor) {
 #if BUILDFLAG(IS_WIN)
   ui::Cursor cursor_copy = cursor;
-  aura::CursorLoader cursor_loader;
+  CursorLoader cursor_loader;
   cursor_loader.SetPlatformCursor(&cursor_copy);
   return IconUtil::GetHotSpotFromHICON(
       ui::WinCursor::FromPlatformCursor(cursor_copy.platform())->hcursor());
@@ -368,4 +368,4 @@
 #endif
 }
 
-}  // namespace aura
+}  // namespace wm
diff --git a/ui/aura/cursor/cursors_aura.h b/ui/wm/core/cursors_aura.h
similarity index 79%
rename from ui/aura/cursor/cursors_aura.h
rename to ui/wm/core/cursors_aura.h
index 3a13dcdc..483dad3 100644
--- a/ui/aura/cursor/cursors_aura.h
+++ b/ui/wm/core/cursors_aura.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_AURA_CURSOR_CURSORS_AURA_H_
-#define UI_AURA_CURSOR_CURSORS_AURA_H_
+#ifndef UI_WM_CORE_CURSORS_AURA_H_
+#define UI_WM_CORE_CURSORS_AURA_H_
 
 #include "base/component_export.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
@@ -19,25 +19,25 @@
 enum class CursorSize;
 }  // namespace ui
 
-namespace aura {
+namespace wm {
 
 // Returns data about |id|, where id is a cursor constant like
 // ui::mojom::CursorType::kHelp. The IDR will be placed in |resource_id| and
 // the hotspots for the different DPIs will be placed in |hot_1x| and
 // |hot_2x|.  Returns false if |id| is invalid.
-COMPONENT_EXPORT(UI_AURA_CURSOR)
+COMPONENT_EXPORT(UI_WM)
 bool GetCursorDataFor(ui::CursorSize cursor_size,
                       ui::mojom::CursorType id,
                       float scale_factor,
                       int* resource_id,
                       gfx::Point* point);
 
-COMPONENT_EXPORT(UI_AURA_CURSOR)
+COMPONENT_EXPORT(UI_WM)
 SkBitmap GetDefaultBitmap(const ui::Cursor& cursor);
 
-COMPONENT_EXPORT(UI_AURA_CURSOR)
+COMPONENT_EXPORT(UI_WM)
 gfx::Point GetDefaultHotspot(const ui::Cursor& cursor);
 
-}  // namespace aura
+}  // namespace wm
 
-#endif  // UI_AURA_CURSOR_CURSORS_AURA_H_
+#endif  // UI_WM_CORE_CURSORS_AURA_H_
diff --git a/weblayer/shell/android/BUILD.gn b/weblayer/shell/android/BUILD.gn
index 74a8dbd2..5593b97 100644
--- a/weblayer/shell/android/BUILD.gn
+++ b/weblayer/shell/android/BUILD.gn
@@ -106,6 +106,26 @@
   apk_name = "WebLayerShellSystemWebView"
 }
 
+generate_wrapper("run_browserfragment_shell") {
+  testonly = true
+  wrapper_script = "$root_out_dir/bin/run_browserfragment_shell"
+  executable = "//weblayer/tools/run_weblayer_shell.py"
+  executable_args = [
+    "--shell-apk-path",
+    "@WrappedPath(apks/BFShell.apk)",
+    "--support-apk-path",
+    "@WrappedPath(apks/BFSandbox.apk)",
+    "--support-apk-path",
+    "@WrappedPath(apks/WebLayerSupport.apk)",
+  ]
+
+  deps = [
+    ":browser_sandbox_apk",
+    ":browserfragment_shell_apk",
+    ":weblayer_support_apk",
+  ]
+}
+
 generate_wrapper("run_weblayer_shell") {
   testonly = true
   wrapper_script = "$root_out_dir/bin/run_weblayer_shell"
diff --git a/weblayer/tools/run_weblayer_shell.py b/weblayer/tools/run_weblayer_shell.py
index 41391b2..05fc96a0 100755
--- a/weblayer/tools/run_weblayer_shell.py
+++ b/weblayer/tools/run_weblayer_shell.py
@@ -73,6 +73,12 @@
                     'launch']
       launch_cmd.extend(args.remaining_args)
       subprocess.call(launch_cmd)
+    elif (os.path.basename(args.shell_apk_path) == "BFShell.apk"):
+      launch_cmd = [os.path.join(os.path.dirname(args.shell_apk_path),
+                                 os.pardir, 'bin', 'browserfragment_shell_apk'),
+                    'launch']
+      launch_cmd.extend(args.remaining_args)
+      subprocess.call(launch_cmd)
     else:
       device.adb.Shell('monkey -p org.chromium.weblayer.shell 1')