diff --git a/DEPS b/DEPS
index 9043d4c..53ba33d 100644
--- a/DEPS
+++ b/DEPS
@@ -269,7 +269,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'fa9b8b6bd6a26cbe7ddbe1255205adbce8b3015a',
+  'skia_revision': 'c58e0ba36c7847cd39787b333df347179cb4baa1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -277,7 +277,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'c7a9f0c6c49cc4a9b848ab308bf39b8309347187',
+  'angle_revision': 'e55990e35ddcbd405db9ddc5dfc77828e6090ad2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -344,7 +344,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': 'ea900949c3feced67d12852e064d9f0a6fe72cb5',
+  'devtools_frontend_revision': 'cbb08a0e6a3b952018703bb299cdfdc765e7cd60',
   # 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.
@@ -380,7 +380,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': '73b1d1dafa95ed5c162b3fb24fb7450ea05c8b19',
+  'dawn_revision': '41e4d9a34c1d9dcb2eef3ff39ff9c1f987bfa02a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -447,7 +447,7 @@
   'libcxx_revision':       '79a2e924d96e2fc1e4b937c42efd08898fa472d7',
 
   # GN CIPD package version.
-  'gn_version': 'git_revision:48b013c9d9debc0f5fc1dd71a257b3c38c5acb43',
+  'gn_version': 'git_revision:53ef169800760fdc09f0773bf380fe99eaeab339',
 }
 
 # Only these hosts are allowed for dependencies in this DEPS file.
@@ -831,7 +831,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/linux-amd64',
-          'version': '6jut2oixaAC8Gmz5aIAp6X4icnpdd4EzcuTrO3FLkUMC',
+          'version': 'x9sk15GYbET9EmcG_vOvfgXnouN1otxGy_QXszA9E7gC',
         },
       ],
       'dep_type': 'cipd',
@@ -842,7 +842,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/mac-amd64',
-          'version': 'S5RMHVmo0eSnXXnTjlzUmjo4fXEA1nWSzg82HRQISUoC',
+          'version': 'RTbWMLIh0TpWnJxQkomlNBscU7JtyT6aS9VV_FLuqBsC',
         },
       ],
       'dep_type': 'cipd',
@@ -853,7 +853,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/windows-amd64',
-          'version': 'qtLqT_uMuPHgXzf4FV-qL7lOGmRuZ7RzS_iIjgepFx8C',
+          'version': 'uYZ95J1pszwrxL9fucRN8Fc_BK_9JeAA1df2Q2jppHAC',
         },
       ],
       'dep_type': 'cipd',
@@ -1742,7 +1742,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '547d67bc2212c0d203b9598d8ed3e1589ffb085a',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '3af79d17686a37341fa93570f8d32c7ffad644f1',
+    Var('webrtc_git') + '/src.git' + '@' + '07999d2b6b1fa5e425e9d3fc72cec4ff9cc39050',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1815,7 +1815,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@805ac445bc6a5424dc6c5d7f6c8c57279bc7d935',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0dcce198d82df9c496951f8efc7343e01e0dc739',
     'condition': 'checkout_src_internal',
   },
 
@@ -1845,7 +1845,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'a745TJSOlYX3tV7dR8ZTStXO13Bkw2IerUrOImX7m7YC',
+        'version': '584YI22KFYZTuiDIpftEbNkEu-2D7tHOE5hqBKyxjlgC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1856,7 +1856,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'zgy_rmZ7DYllGasXHYqWeGgZfzwVIXMax-Jabg88YbYC',
+        'version': 'AkDjvwf0lScb2leZYKWvN82D3hWwoBLKHjW020hMNNQC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1867,7 +1867,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': '5MqLZO92lQ5cZ7-t3PkuyU-dkjLwAktcQ61oysMixnEC',
+        'version': 'T0_NfSlEK10hPI63-AtfUv12FMBxD1ei0JYxc8MxcIQC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 973955c9..d6ba185 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -2101,7 +2101,10 @@
     """
     errors = []
     files_to_check = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
-    files_to_skip = [r'^native_client_sdk[\\/]']
+    files_to_skip = [r'^native_client_sdk[\\/]',
+                     r'^services[\\/]test[\\/]',
+                     r'^third_party[\\/]blink[\\/]web_tests[\\/]',
+                    ]
     file_filter = lambda f: input_api.FilterSourceFile(
         f, files_to_check=files_to_check, files_to_skip=files_to_skip)
     for f in input_api.AffectedFiles(include_deletes=False,
diff --git a/ash/components/arc/BUILD.gn b/ash/components/arc/BUILD.gn
index 551e20c..95139567 100644
--- a/ash/components/arc/BUILD.gn
+++ b/ash/components/arc/BUILD.gn
@@ -125,12 +125,12 @@
     "//ash/keyboard/ui",
     "//ash/public/cpp",
     "//ash/public/cpp/external_arc:external_arc",
+    "//chromeos/ash/components/dbus/concierge",
+    "//chromeos/ash/components/dbus/concierge:concierge_proto",
     "//chromeos/ash/components/dbus/patchpanel",
     "//chromeos/ash/components/dbus/patchpanel:patchpanel_proto",
     "//chromeos/components/sensors:sensors",
     "//chromeos/dbus",
-    "//chromeos/dbus:concierge_proto",
-    "//chromeos/dbus/concierge",
     "//chromeos/dbus/cryptohome",
     "//chromeos/dbus/permission_broker",
     "//chromeos/dbus/power",
@@ -202,8 +202,8 @@
     "//ash/constants",
     "//ash/public/cpp",
     "//base",
+    "//chromeos/ash/components/dbus/concierge:concierge_proto",
     "//chromeos/ash/components/dbus/upstart:upstart",
-    "//chromeos/dbus:concierge_proto",
     "//chromeos/dbus:dbus",
     "//chromeos/dbus/session_manager",
     "//components/exo",
diff --git a/ash/components/arc/disk_quota/arc_disk_quota_bridge.cc b/ash/components/arc/disk_quota/arc_disk_quota_bridge.cc
index 2132d00d..cac76a2 100644
--- a/ash/components/arc/disk_quota/arc_disk_quota_bridge.cc
+++ b/ash/components/arc/disk_quota/arc_disk_quota_bridge.cc
@@ -14,7 +14,7 @@
 #include "base/memory/singleton.h"
 #include "base/system/sys_info.h"
 #include "base/task/thread_pool.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/userdataauth/arc_quota_client.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/ash/components/arc/disk_quota/arc_disk_quota_bridge.h b/ash/components/arc/disk_quota/arc_disk_quota_bridge.h
index 8a62333..f24b918 100644
--- a/ash/components/arc/disk_quota/arc_disk_quota_bridge.h
+++ b/ash/components/arc/disk_quota/arc_disk_quota_bridge.h
@@ -8,7 +8,7 @@
 #include "ash/components/arc/mojom/disk_quota.mojom.h"
 #include "base/files/file_path.h"
 #include "base/memory/weak_ptr.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "chromeos/dbus/cryptohome/UserDataAuth.pb.h"
 #include "components/account_id/account_id.h"
 #include "components/keyed_service/core/keyed_service.h"
diff --git a/ash/components/arc/power/arc_power_bridge.h b/ash/components/arc/power/arc_power_bridge.h
index ae11f97..d8bc036 100644
--- a/ash/components/arc/power/arc_power_bridge.h
+++ b/ash/components/arc/power/arc_power_bridge.h
@@ -15,7 +15,7 @@
 #include "base/observer_list.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "mojo/public/cpp/bindings/remote.h"
diff --git a/ash/components/arc/session/BUILD.gn b/ash/components/arc/session/BUILD.gn
index 26d07f7..92b069c 100644
--- a/ash/components/arc/session/BUILD.gn
+++ b/ash/components/arc/session/BUILD.gn
@@ -51,9 +51,9 @@
     "//ash/constants:constants",
     "//ash/public/cpp",
     "//ash/public/cpp/external_arc:external_arc",
+    "//chromeos/ash/components/dbus/concierge",
     "//chromeos/ash/components/dbus/upstart",
     "//chromeos/components/sensors:buildflags",
-    "//chromeos/dbus/concierge",
     "//chromeos/dbus/dlcservice:dlcservice",
     "//chromeos/dbus/dlcservice:dlcservice_proto",
     "//chromeos/dbus/session_manager",
@@ -125,9 +125,9 @@
     "//ash/components/cryptohome",
     "//ash/constants",
     "//base/test:test_support",
+    "//chromeos/ash/components/dbus/concierge",
     "//chromeos/ash/components/dbus/upstart",
     "//chromeos/dbus",
-    "//chromeos/dbus/concierge",
     "//chromeos/dbus/dlcservice",
     "//chromeos/dbus/session_manager",
     "//chromeos/system:system",
diff --git a/ash/components/arc/session/arc_client_adapter_unittest.cc b/ash/components/arc/session/arc_client_adapter_unittest.cc
index 170e5c1..4148489 100644
--- a/ash/components/arc/session/arc_client_adapter_unittest.cc
+++ b/ash/components/arc/session/arc_client_adapter_unittest.cc
@@ -10,8 +10,8 @@
 #include "ash/components/arc/session/arc_service_manager.h"
 #include "base/command_line.h"
 #include "base/scoped_observation.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/upstart/fake_upstart_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ash/components/arc/session/arc_vm_client_adapter.cc b/ash/components/arc/session/arc_vm_client_adapter.cc
index 4f8c4b7..f3c06d8 100644
--- a/ash/components/arc/session/arc_vm_client_adapter.cc
+++ b/ash/components/arc/session/arc_vm_client_adapter.cc
@@ -54,9 +54,9 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/timer/elapsed_timer.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/components/sensors/buildflags.h"
 #include "chromeos/dbus/common/dbus_method_call_status.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
diff --git a/ash/components/arc/session/arc_vm_client_adapter_unittest.cc b/ash/components/arc/session/arc_vm_client_adapter_unittest.cc
index f548cba..abb408bd7 100644
--- a/ash/components/arc/session/arc_vm_client_adapter_unittest.cc
+++ b/ash/components/arc/session/arc_vm_client_adapter_unittest.cc
@@ -48,8 +48,8 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_run_loop_timeout.h"
 #include "base/time/time.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/upstart/fake_upstart_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
diff --git a/ash/login/ui/login_password_view.cc b/ash/login/ui/login_password_view.cc
index b1db4e9d..0d59fdd 100644
--- a/ash/login/ui/login_password_view.cc
+++ b/ash/login/ui/login_password_view.cc
@@ -200,12 +200,18 @@
 // and indicators (easy unlock, display password, caps lock enabled).
 class LoginPasswordView::LoginPasswordRow : public views::View {
  public:
-  explicit LoginPasswordRow(const LoginPalette& palette)
-      : color_(palette.password_row_background_color) {}
+  explicit LoginPasswordRow(const LoginPalette& palette) {
+    UpdatePalette(palette);
+  }
+
   ~LoginPasswordRow() override = default;
   LoginPasswordRow(const LoginPasswordRow&) = delete;
   LoginPasswordRow& operator=(const LoginPasswordRow&) = delete;
 
+  void UpdatePalette(const LoginPalette& palette) {
+    color_ = palette.password_row_background_color;
+  }
+
   // views::View:
   void OnPaint(gfx::Canvas* canvas) override {
     views::View::OnPaint(canvas);
@@ -218,7 +224,7 @@
   }
 
  private:
-  const SkColor color_;
+  SkColor color_;
 };
 
 // A textfield that selects all text on focus and allows to switch between
@@ -949,8 +955,11 @@
 void LoginPasswordView::UpdatePalette(const LoginPalette& palette) {
   palette_ = palette;
   SetCapsLockHighlighted(is_capslock_higlight_);
+  password_row_->UpdatePalette(palette);
   textfield_->UpdatePalette(palette);
   display_password_button_->UpdateIcons(palette);
+  submit_button_->SetBackgroundColor(palette.submit_button_background_color);
+  submit_button_->SetIconColor(palette.submit_button_icon_color);
 }
 
 void LoginPasswordView::SetCapsLockHighlighted(bool highlight) {
diff --git a/ash/services/ime/public/mojom/connection_factory.mojom b/ash/services/ime/public/mojom/connection_factory.mojom
index dfb90114..044c0d5 100644
--- a/ash/services/ime/public/mojom/connection_factory.mojom
+++ b/ash/services/ime/public/mojom/connection_factory.mojom
@@ -2,6 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Updates to this file must be backwards-compatible, as it is used outside of
+// the Chromium repo. This file should be updated first, before syncing in the
+// other repos.
+
+// Next MinVersion: 1
+
 module ash.ime.mojom;
 
 import "ash/services/ime/public/mojom/input_method.mojom";
@@ -9,9 +15,10 @@
 
 // Responsible for instantiating the connection between the shared library
 // and Chromium over an associated Mojo pipe.
+[Stable]
 interface ConnectionFactory {
   // Connects to the given input method specified via ime_spec.
-  ConnectToInputMethod(
+  ConnectToInputMethod@0(
     string ime_spec,
     pending_associated_receiver<InputMethod> input_method,
     pending_associated_remote<InputMethodHost> input_method_host)
diff --git a/ash/services/ime/public/mojom/input_method_host.mojom b/ash/services/ime/public/mojom/input_method_host.mojom
index f54ea6f6..0cf07ca 100644
--- a/ash/services/ime/public/mojom/input_method_host.mojom
+++ b/ash/services/ime/public/mojom/input_method_host.mojom
@@ -151,6 +151,7 @@
 };
 
 // A URL-Keyed Metric (UKM) entry.
+[Stable]
 union UkmEntry {
   NonCompliantApiMetric non_compliant_api;
 };
@@ -238,6 +239,7 @@
 // to communicate back to the browser process.
 //
 // Next ordinal: 14
+[Stable]
 interface InputMethodHost {
   // ========================================================
   // The following methods operate on the focused text field.
diff --git a/ash/shortcut_viewer/strings/shortcut_viewer_strings_hy.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_hy.xtb
index be323db35..035d460 100644
--- a/ash/shortcut_viewer/strings/shortcut_viewer_strings_hy.xtb
+++ b/ash/shortcut_viewer/strings/shortcut_viewer_strings_hy.xtb
@@ -30,7 +30,7 @@
 <translation id="1996162290124031907">Անցնել հաջորդ ներդիր</translation>
 <translation id="2010818616644390445">Բացել պատուհանի վերջին ներդիրը</translation>
 <translation id="2040706009561734834">Բացել/փակել գործարկիչը</translation>
-<translation id="2086334242442703436">Բացել զմայլիկների ընտրիչը</translation>
+<translation id="2086334242442703436">Բացել էմոջիների ընտրիչը</translation>
 <translation id="2088054208777350526">Որոնեք ստեղնային դյուրանցումներ</translation>
 <translation id="2125211348069077981"><ph name="ALT" /><ph name="SEPARATOR" /><ph name="E" /> կամ <ph name="F" /></translation>
 <translation id="2145908266289632567">Տեքստի խմբագրում</translation>
diff --git a/ash/strings/ash_strings_hy.xtb b/ash/strings/ash_strings_hy.xtb
index 4fbf98d..359034a 100644
--- a/ash/strings/ash_strings_hy.xtb
+++ b/ash/strings/ash_strings_hy.xtb
@@ -897,7 +897,7 @@
 <translation id="6520517963145875092">Լուսանկարելու համար ընտրեք պատուհան</translation>
 <translation id="652139407789908527">Թարմացման ընթացքում էկրանը սովորականից ավելի երկար կմնա անջատված (մինչև մեկ րոպե)։ Մի՛ սեղմեք սնուցման կոճակը, մինչև որ թարմացումը չավարտվի։</translation>
 <translation id="6528179044667508675">Չանհանգստացնել</translation>
-<translation id="65320610082834431">Զմայլիկներ</translation>
+<translation id="65320610082834431">Էմոջիներ</translation>
 <translation id="6537924328260219877">Ազդանշանի ուժգնությունը՝ <ph name="SIGNAL_STRENGTH" />, մարտկոցի լիցքը՝ <ph name="BATTERY_STATUS" /></translation>
 <translation id="6539852571005954999">Ներբեռնումը դադարեցված է, <ph name="FILENAME" /> ֆայլը ստուգվում է</translation>
 <translation id="6542521951477560771">Հեռարձակում «<ph name="RECEIVER_NAME" />» սարքին</translation>
diff --git a/base/trace_event/builtin_categories.h b/base/trace_event/builtin_categories.h
index 0736e70..7528d88 100644
--- a/base/trace_event/builtin_categories.h
+++ b/base/trace_event/builtin_categories.h
@@ -338,8 +338,10 @@
   X("shutdown,viz")                                                           \
   X("startup,benchmark,rail")                                                 \
   X("startup,rail")                                                           \
+  X("toplevel,viz")                                                           \
   X("ui,input")                                                               \
   X("ui,latency")                                                             \
+  X("ui,toplevel")                                                            \
   X("v8," TRACE_DISABLED_BY_DEFAULT("v8.compile"))                            \
   X("v8,devtools.timeline")                                                   \
   X("v8,devtools.timeline," TRACE_DISABLED_BY_DEFAULT("v8.compile"))          \
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index 0f01b94..1f884e9893 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-8.20220430.3.1
+8.20220501.3.1
diff --git a/cc/input/threaded_input_handler.cc b/cc/input/threaded_input_handler.cc
index 8046a3a..c0f018c2 100644
--- a/cc/input/threaded_input_handler.cc
+++ b/cc/input/threaded_input_handler.cc
@@ -418,6 +418,8 @@
   bool did_scroll_y = scroll_state->caused_scroll_y();
   did_scroll_x_for_scroll_gesture_ |= did_scroll_x;
   did_scroll_y_for_scroll_gesture_ |= did_scroll_y;
+  delta_consumed_for_scroll_gesture_ |=
+      scroll_state->delta_consumed_for_scroll_sequence();
   bool did_scroll_content = did_scroll_x || did_scroll_y;
   if (did_scroll_content) {
     bool is_animated_scroll = ShouldAnimateScroll(*scroll_state);
@@ -1188,10 +1190,7 @@
   if (!last_scroll_update_state_)
     return ActivelyScrollingType::kNone;
 
-  bool did_scroll_content =
-      did_scroll_x_for_scroll_gesture_ || did_scroll_y_for_scroll_gesture_;
-
-  if (!did_scroll_content)
+  if (!delta_consumed_for_scroll_gesture_)
     return ActivelyScrollingType::kNone;
 
   if (ShouldAnimateScroll(last_scroll_update_state_.value()))
@@ -2163,6 +2162,7 @@
   accumulated_root_overscroll_ = gfx::Vector2dF();
   did_scroll_x_for_scroll_gesture_ = false;
   did_scroll_y_for_scroll_gesture_ = false;
+  delta_consumed_for_scroll_gesture_ = false;
   scroll_animating_snap_target_ids_ = TargetSnapAreaElementIds();
   latched_scroll_type_.reset();
   last_scroll_update_state_.reset();
diff --git a/cc/input/threaded_input_handler.h b/cc/input/threaded_input_handler.h
index 336890dd..32ab23f 100644
--- a/cc/input/threaded_input_handler.h
+++ b/cc/input/threaded_input_handler.h
@@ -427,6 +427,11 @@
   bool did_scroll_x_for_scroll_gesture_ = false;
   bool did_scroll_y_for_scroll_gesture_ = false;
 
+  // did_scroll_x/y_for_scroll_gesture_ is true when contents consume the delta,
+  // but delta_consumed_for_scroll_gesture_ can be true when only browser
+  // controls consume all the delta.
+  bool delta_consumed_for_scroll_gesture_ = false;
+
   // TODO(bokan): Mac doesn't yet have smooth scrolling for wheel; however, to
   // allow consistency in tests we use this bit to override that decision.
   // https://crbug.com/574283.
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index 0995c22..027c2ea0 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -834,6 +834,13 @@
   // Returns a percentage representing average throughput of last X seconds.
   uint32_t GetAverageThroughput() const;
 
+  // TODO(szager): Remove these once threaded compositing is enabled for all
+  // web_tests.
+  bool in_composite_for_test() const { return in_composite_for_test_; }
+  [[nodiscard]] base::AutoReset<bool> ForceSyncCompositeForTest() {
+    return base::AutoReset<bool>(&in_composite_for_test_, true);
+  }
+
  protected:
   LayerTreeHost(InitParams params, CompositorMode mode);
 
@@ -1011,6 +1018,8 @@
   // for histograms.
   mutable bool waited_for_protected_sequence_ = false;
 
+  bool in_composite_for_test_ = false;
+
   // Used to vend weak pointers to LayerTreeHost to ScopedDeferMainFrameUpdate
   // objects.
   base::WeakPtrFactory<LayerTreeHost> defer_main_frame_update_weak_ptr_factory_{
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 6f58ca2..df603e6 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -18340,4 +18340,62 @@
             collected_bounds.bounds().find(kFourthId)->second);
 }
 
+// Check if picturelayer's ScrollInteractionInProgress() return true even when
+// BrowserControl is consuming ScrollUpdate.
+TEST_P(LayerTreeHostImplBrowserControlsTest,
+       BrowserControlsScrollInteractionInProgress) {
+  gfx::Size inner_size = gfx::Size(100, 100);
+  gfx::Size outer_size = gfx::Size(100, 100);
+  gfx::Size content_size = gfx::Size(100, 200);
+  SetupBrowserControlsAndScrollLayerWithVirtualViewport(inner_size, outer_size,
+                                                        content_size);
+
+  LayerTreeImpl* active_tree = host_impl_->active_tree();
+
+  // Create a content layer beneath the outer viewport scroll layer.
+  scoped_refptr<FakeRasterSource> raster_source(
+      FakeRasterSource::CreateFilled(content_size));
+
+  auto* picture_layer =
+      AddLayer<FakePictureLayerImpl>(host_impl_->active_tree(), raster_source);
+  CopyProperties(OuterViewportScrollLayer(), picture_layer);
+  picture_layer->SetBounds(content_size);
+  picture_layer->SetDrawsContent(true);
+  picture_layer->SetNeedsPushProperties();
+  active_tree->PushPageScaleFromMainThread(1.0f, 1.0f, 2.0f);
+  DrawFrame();
+
+  EXPECT_EQ(ScrollThread::SCROLL_ON_IMPL_THREAD,
+            GetInputHandler()
+                .ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 50),
+                                        ui::ScrollInputType::kTouchscreen)
+                                 .get(),
+                             ui::ScrollInputType::kTouchscreen)
+                .thread);
+  // shownratio == 1
+  EXPECT_EQ(1, host_impl_->active_tree()->CurrentTopControlsShownRatio());
+  EXPECT_EQ(picture_layer->ScrollInteractionInProgress(), false);
+
+  // 0 < shownratio <1
+  GetInputHandler().ScrollUpdate(UpdateState(gfx::Point(),
+                                             gfx::Vector2dF(0, 25),
+                                             ui::ScrollInputType::kTouchscreen)
+                                     .get());
+  EXPECT_GT(host_impl_->active_tree()->CurrentTopControlsShownRatio(), 0);
+  EXPECT_LT(host_impl_->active_tree()->CurrentTopControlsShownRatio(), 1);
+  EXPECT_EQ(picture_layer->ScrollInteractionInProgress(), true);
+
+  GetInputHandler().ScrollUpdate(UpdateState(gfx::Point(),
+                                             gfx::Vector2dF(0, 30),
+                                             ui::ScrollInputType::kTouchscreen)
+                                     .get());
+  // now shownratio == 0
+  EXPECT_EQ(0, host_impl_->active_tree()->CurrentTopControlsShownRatio());
+  EXPECT_EQ(picture_layer->ScrollInteractionInProgress(), true);
+
+  GetInputHandler().ScrollEnd();
+  // scroll end, shownratio == 0
+  EXPECT_EQ(0, host_impl_->active_tree()->CurrentTopControlsShownRatio());
+  EXPECT_EQ(picture_layer->ScrollInteractionInProgress(), false);
+}
 }  // namespace cc
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 3bd1669e..fb09ea4 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -714,6 +714,7 @@
   base::AutoReset<bool> inside_composite(&inside_synchronous_composite_, true);
 
   if (layer_tree_frame_sink_lost_) {
+    auto sync = layer_tree_host_->ForceSyncCompositeForTest();  // IN-TEST
     RequestNewLayerTreeFrameSink();
     // RequestNewLayerTreeFrameSink could have synchronously created an output
     // surface, so check again before returning.
@@ -1132,6 +1133,7 @@
     ScheduleRequestNewLayerTreeFrameSink();
   } else {
     DebugScopedSetMainThread main(task_runner_provider_);
+    auto sync = layer_tree_host_->ForceSyncCompositeForTest();  // IN-TEST
     RequestNewLayerTreeFrameSink();
   }
 }
diff --git a/chrome/VERSION b/chrome/VERSION
index 8f242d6..95debc16 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=103
 MINOR=0
-BUILD=5037
+BUILD=5039
 PATCH=0
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index e4eb53f..7319fefb6 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -4742,13 +4742,13 @@
     Configuring Linux
   </message>
   <message name="IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_SUBTEXT" desc="Description for dialog warning user of unavailable Linux container until software configurations are applied.">
-    Linux is being configured by your administrator. Configuration will take a few minutes.
+    Linux is currently being configured. Configuration will take a few minutes.
   </message>
   <message name="IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_ERROR_LABEL" desc="Label for Crostini software config dialog when there is an error in Ansible playbook application or installation.">
     Error configuring Linux
   </message>
   <message name="IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_ERROR_SUBTEXT" desc="Text shown for Crostini software config dialog when there is an error in Ansible playbook application or installation.">
-    There was an error while configuring Linux. Please contact your administrator.
+    There was an error while configuring Linux.
   </message>
   <message name="IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_ERROR_OFFLINE_LABEL" desc="Label for dialog warning user of missing internet connection required for container configuration.">
     <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph> is offline
diff --git a/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_ERROR_SUBTEXT.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_ERROR_SUBTEXT.png.sha1
new file mode 100644
index 0000000..7ac6602
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_ERROR_SUBTEXT.png.sha1
@@ -0,0 +1 @@
+408c601693ee875164b9f7650a56345d4dbe0ed8
diff --git a/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_SUBTEXT.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_SUBTEXT.png.sha1
new file mode 100644
index 0000000..46e722e
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_SUBTEXT.png.sha1
@@ -0,0 +1 @@
+44484daf71bc5b5a651903a2de2fedf550fbfb13
diff --git a/chrome/app/resources/generated_resources_hy.xtb b/chrome/app/resources/generated_resources_hy.xtb
index 0b557b7..0e90a66 100644
--- a/chrome/app/resources/generated_resources_hy.xtb
+++ b/chrome/app/resources/generated_resources_hy.xtb
@@ -1061,7 +1061,7 @@
 <translation id="2005967212456643969">Անհատականացնել թույլտվությունները յուրաքանչյուր ընդլայնման համար</translation>
 <translation id="2006638907958895361">Բացել հղումը <ph name="APP" /> հավելվածում</translation>
 <translation id="2007404777272201486">Report an Issue...</translation>
-<translation id="2009590708342941694">«Զմայլիկներ» գործիք</translation>
+<translation id="2009590708342941694">«Էմոջիներ» գործիք</translation>
 <translation id="2010501376126504057">Համատեղելի սարքեր</translation>
 <translation id="2015232545623037616">Համակարգիչը և Chromecast-ը միևնույն Wi-Fi ցանցում են գտնվում</translation>
 <translation id="2016473077102413275">Գործառույթները, որոնց համար պահանջվում են պատկերներ, չեն աշխատի</translation>
@@ -1842,7 +1842,7 @@
 <translation id="2727712005121231835">Actual Size</translation>
 <translation id="2729314457178420145">Ջնջել նաև այցելությունների պատմությունը (<ph name="URL" />)։ Նկատի ունեցեք, որ արդյունքում հնարավոր է դուրս գրվեք ձեր հաշվից Google.com կայքում։ <ph name="LEARN_MORE" /></translation>
 <translation id="2730029791981212295">Լինուքսի հավելվածների ու ֆայլերի պահուստավորում</translation>
-<translation id="2730901670247399077">Զմայլիկների առաջարկներ</translation>
+<translation id="2730901670247399077">Էմոջիների առաջարկներ</translation>
 <translation id="273093730430620027">Այս էջն օգտագործում է ձեր տեսախցիկը:</translation>
 <translation id="2731392572903530958">Նո&amp;րից բացել փակված պատուհանը</translation>
 <translation id="2731700343119398978">Սպասեք…</translation>
@@ -2456,7 +2456,7 @@
 <translation id="3345886924813989455">Աջակցվող դիտարկիչ չի գտնվել</translation>
 <translation id="3347086966102161372">Պատճենել պատկերի հասցեն</translation>
 <translation id="3348038390189153836">Հայտնաբերվել է արտաքին կրիչ</translation>
-<translation id="3348131053948466246">Առաջարկվում են զմայլիկներ։ Դիտելու համար սեղմեք վեր կամ վար սլաքով ստեղնը, իսկ ընտրելու համար՝ Enter։</translation>
+<translation id="3348131053948466246">Առաջարկվում են էմոջիներ։ Դիտելու համար սեղմեք վեր կամ վար սլաքով ստեղնը, իսկ ընտրելու համար՝ Enter։</translation>
 <translation id="3349933790966648062">Օգտագործված հիշողության ծավալ</translation>
 <translation id="335153035108712532">Այս գաղտնաբառը հիշելու կարիք չկա։ Այն <ph name="EMAIL" /> հաշվի համար կպահվի <ph name="GOOGLE_PASSWORD_MANAGER" /> հավելվածում։</translation>
 <translation id="3354972872297836698">Չհաջողվեց զուգակցվել «<ph name="DEVICE_NAME" />» սարքին։ Ընտրեք սարքը և նորից փորձեք։</translation>
@@ -2974,7 +2974,7 @@
 <translation id="3841964634449506551">Գաղտնաբառը սխալ է</translation>
 <translation id="3842552989725514455">Serif տառատեսակ</translation>
 <translation id="3843464315703645664">Թույլատրված է ներքին օգտագործման համար</translation>
-<translation id="3844888638014364087">Զմայլիկը զետեղվեց</translation>
+<translation id="3844888638014364087">Էմոջին զետեղվեց</translation>
 <translation id="3846116211488856547">Ստացեք գործիքներ, որոնցով կարող եք մշակել կայքեր, Android հավելվածներ և այլն: Linux-ի տեղադրման դեպքում կներբեռնվեն <ph name="DOWNLOAD_SIZE" /> ծավալով տվյալներ:</translation>
 <translation id="3847319713229060696">Օգնեք բարելավել համացանցից օգտվողների անվտանգությունը</translation>
 <translation id="3848547754896969219">Բացել &amp;ինկոգնիտո պատուհանում</translation>
@@ -4802,13 +4802,13 @@
 <translation id="5689516760719285838">Տեղորոշում</translation>
 <translation id="5689531695336322499"><ph name="SUPERVISED_USER_NAME" />-ն արդեն Օգնականի միջոցով կարգավորել է Voice Match-ը այլ սարքում։ Այս նախկին ձայնագրություններն օգտագործվել են՝ ձեր ձայնի նմուշն այս սարքում ստեղծելու համար։</translation>
 <translation id="56907980372820799">Հղման տվյալներ</translation>
-<translation id="5691581861107245578">Ստացեք զմայլիկների առաջարկներ՝ ձեր մուտքագրած տեքստի հիման վրա</translation>
+<translation id="5691581861107245578">Ստացեք էմոջիների առաջարկներ՝ ձեր մուտքագրած տեքստի հիման վրա</translation>
 <translation id="5691772641933328258">Չհաջողվեց ճանաչել մատնահետքը</translation>
 <translation id="5692183275898619210">Տպումն ավարտվեց</translation>
 <translation id="5695184138696833495">Android-ի համար հավելվածների ADB գործիք Լինուքսում</translation>
 <translation id="5696143504434933566">Հաղորդել չարաշահման մասին («<ph name="EXTENSION_NAME" />»)</translation>
 <translation id="5696679855467848181">Ընթացիկ օգտագործվող PPD ֆայլը՝ <ph name="PPD_NAME" /></translation>
-<translation id="5697832193891326782">Զմայլիկների ընտրիչ</translation>
+<translation id="5697832193891326782">Էմոջիների ընտրիչ</translation>
 <translation id="570043786759263127">Google Play հավելվածներ և ծառայություններ</translation>
 <translation id="5700836101007545240">Ձեր ադմինիստրատորն անջատել է կապ ավելացնելու գործառույթը</translation>
 <translation id="5701080607174488915">Քաղաքականությունը չհաջողվեց բեռնել սերվերից։</translation>
diff --git a/chrome/app/resources/generated_resources_kk.xtb b/chrome/app/resources/generated_resources_kk.xtb
index 534bfcb7..33f9271 100644
--- a/chrome/app/resources/generated_resources_kk.xtb
+++ b/chrome/app/resources/generated_resources_kk.xtb
@@ -1914,6 +1914,7 @@
 <translation id="2795716239552913152">Сайттар әдетте қажетті функциялар немесе ақпарат (мысалы, жергілікті жаңалықтар не маңайдағы дүкендер) алу үшін геодерегіңізді пайдаланады.</translation>
 <translation id="2796424461616874739">"<ph name="DEVICE_NAME" />" құрылғысына қосылу кезінде аутентификация кідірісі орын алды.</translation>
 <translation id="2796740370559399562">Cookie файлдарына рұқсат беруді жалғастыру</translation>
+<translation id="2798347533012571708">Жаңартып тұру</translation>
 <translation id="2799223571221894425">Қайта іске қосу</translation>
 <translation id="2800760947029405028">Кескін жүктеп салу</translation>
 <translation id="2801954693771979815">Экран өлшемі</translation>
@@ -3743,6 +3744,7 @@
 <translation id="4619564267100705184">Жеке басыңызды растаңыз</translation>
 <translation id="4619615317237390068">Басқа құрылғылардағы қойындылар</translation>
 <translation id="4620809267248568679">Бұл параметр кеңейтім арқылы іске қосылады.</translation>
+<translation id="4622051949285931942">Автоматты түрде жаңарту өшірілсін бе?</translation>
 <translation id="4623167406982293031">Аккаунтты растау</translation>
 <translation id="4623189117674524348">Жүйе осы құрылғыда API интерфейсіне кіру рұқсатын бере алмады.</translation>
 <translation id="4624054169152573743">Түс тақырыбы</translation>
@@ -4541,6 +4543,7 @@
 <translation id="5436575196282187764">Google Photos естеліктері</translation>
 <translation id="5439680044267106777">Өткізіп жіберу және жаңа профиль жасау</translation>
 <translation id="544083962418256601">Таңбашалар жасау…</translation>
+<translation id="5441133529460183413">Веб-қолданба Chrome браузері арқылы орнатылды.</translation>
 <translation id="5442228125690314719">Диск образын жасау кезінде қате шықты. Қайта жасап көріңіз.</translation>
 <translation id="5442550868130618860">Автоматты түрде жаңарту функциясын қосу</translation>
 <translation id="5445400788035474247">10x</translation>
@@ -4772,6 +4775,7 @@
 <translation id="5658415415603568799">Қауіпсіздікті күшейту үшін Smart Lock функциясы 20 сағаттан кейін құпия сөзді енгізуді сұрауы мүмкін.</translation>
 <translation id="5659593005791499971">Электрондық пошта</translation>
 <translation id="5659833766619490117">Бет аударылмады</translation>
+<translation id="566097169318652001">Құрылғыңыз енді дұрыс жұмыс істемей, өнімділікке және қауіпсіздікке қатысты ақаулар пайда болуы мүмкін. Құрылғыдағы негізгі функциялар ескірген кезде, олар да жұмысын тоқтатуы мүмкін. Осыған байланысты сіздің заң тарапынан шағымдану құқығыңыз да жойылады.</translation>
 <translation id="5662513737565158057">Linux қолданбаларының жұмыс істеу жолын өзгертіңіз.</translation>
 <translation id="5667293444945855280">Зиянды бағдарлама</translation>
 <translation id="5667546120811588575">Google Play орнатылуда...</translation>
@@ -6995,6 +6999,7 @@
 <translation id="7865127013871431856">Аудару опциялары</translation>
 <translation id="7869143217755017858">Қараңғы режимді өшіру</translation>
 <translation id="786957569166715433"><ph name="DEVICE_NAME" /> – жұпталды</translation>
+<translation id="7869655448736341731">Барлығы</translation>
 <translation id="7870730066603611552">Сеанс басталғаннан кейін, синхрондау опцияларын қарап шығу</translation>
 <translation id="7870790288828963061">Киоск қолданбаларының жаңа нұсқалары табылмады. Жаңартатын ештеңе жоқ. USB картасын алып тастаңыз.</translation>
 <translation id="7871109039747854576">Нұсқалар тізімін қарап шығу үшін "<ph name="COMMA" />" және "<ph name="PERIOD" />" пернелерін пайдалану</translation>
@@ -7450,6 +7455,7 @@
 <translation id="8300374739238450534">Қою көк</translation>
 <translation id="8303616404642252802">{COUNT,plural, =1{Мекенжай}other{# мекенжай}}</translation>
 <translation id="8304383784961451596">Бұл құрылғыны пайдалануға рұқсатыңыз жоқ. Кіру рұқсатын алу үшін әкімшіге хабарласыңыз немесе Family Link арқылы қадағаланатын Google аккаунтымен кіріңіз.</translation>
+<translation id="8306885873692337975">Соңғы шыққан функцияларды және қауіпсіздікті жақсарту мүмкіндіктерін пайдаланыңыз.</translation>
 <translation id="8307094075368387939">"Жекелендіру" хабында кестені реттеуге болады, сондай-ақ тұсқағаз, скринсейвер орната және жүйе түстерін бейімдей аласыз.</translation>
 <translation id="8308016398665340540">Бұл желіні осы құрылғының басқа пайдаланушыларымен бөлісіп жатырсыз</translation>
 <translation id="8308179586020895837"><ph name="HOST" /> камераны пайдаланғысы келгенде, рұқсат сұралсын</translation>
diff --git a/chrome/browser/apps/app_discovery_service/app_discovery_service.cc b/chrome/browser/apps/app_discovery_service/app_discovery_service.cc
index 9e0f6c84..b892b8e3 100644
--- a/chrome/browser/apps/app_discovery_service/app_discovery_service.cc
+++ b/chrome/browser/apps/app_discovery_service/app_discovery_service.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "chrome/browser/apps/app_discovery_service/app_discovery_util.h"
 #include "chrome/browser/apps/app_discovery_service/app_fetcher_manager.h"
 
 namespace apps {
@@ -15,11 +16,6 @@
 
 AppDiscoveryService::~AppDiscoveryService() = default;
 
-void AppDiscoveryService::GetApps(ResultType result_type,
-                                  ResultCallback callback) {
-  app_fetcher_manager_->GetApps(result_type, std::move(callback));
-}
-
 base::CallbackListSubscription AppDiscoveryService::RegisterForAppUpdates(
     ResultType result_type,
     RepeatingResultCallback callback) {
@@ -27,4 +23,17 @@
                                                      std::move(callback));
 }
 
+void AppDiscoveryService::GetApps(ResultType result_type,
+                                  ResultCallback callback) {
+  app_fetcher_manager_->GetApps(result_type, std::move(callback));
+}
+
+void AppDiscoveryService::GetIcon(const std::string& app_id,
+                                  int32_t size_hint_in_dip,
+                                  ResultType result_type,
+                                  GetIconCallback callback) {
+  app_fetcher_manager_->GetIcon(app_id, size_hint_in_dip, result_type,
+                                std::move(callback));
+}
+
 }  // namespace apps
diff --git a/chrome/browser/apps/app_discovery_service/app_discovery_service.h b/chrome/browser/apps/app_discovery_service/app_discovery_service.h
index 02dac21..dfc1acb 100644
--- a/chrome/browser/apps/app_discovery_service/app_discovery_service.h
+++ b/chrome/browser/apps/app_discovery_service/app_discovery_service.h
@@ -40,6 +40,13 @@
   // |callback| is called when a response to the request is ready.
   void GetApps(ResultType result_type, ResultCallback callback);
 
+  // Queries for an app's icon, identified by |app_id|.
+  // |callback| is called when a response to the request is ready.
+  void GetIcon(const std::string& app_id,
+               int32_t size_hint_in_dip,
+               ResultType result_type,
+               GetIconCallback callback);
+
  private:
   std::unique_ptr<AppFetcherManager> app_fetcher_manager_;
 };
diff --git a/chrome/browser/apps/app_discovery_service/app_discovery_util.h b/chrome/browser/apps/app_discovery_service/app_discovery_util.h
index c9e212bb..e2171d4 100644
--- a/chrome/browser/apps/app_discovery_service/app_discovery_util.h
+++ b/chrome/browser/apps/app_discovery_service/app_discovery_util.h
@@ -11,6 +11,10 @@
 #include "base/callback_list.h"
 #include "chrome/browser/apps/app_discovery_service/result.h"
 
+namespace gfx {
+class ImageSkia;
+}  // namespace gfx
+
 namespace apps {
 
 enum class ResultType {
@@ -41,6 +45,9 @@
 using ResultCallbackList =
     base::RepeatingCallbackList<void(const std::vector<Result>& results)>;
 
+using GetIconCallback =
+    base::OnceCallback<void(const gfx::ImageSkia& image, DiscoveryError error)>;
+
 }  // namespace apps
 
 #endif  // CHROME_BROWSER_APPS_APP_DISCOVERY_SERVICE_APP_DISCOVERY_UTIL_H_
diff --git a/chrome/browser/apps/app_discovery_service/app_fetcher_manager.cc b/chrome/browser/apps/app_discovery_service/app_fetcher_manager.cc
index 7504e512..1010711b 100644
--- a/chrome/browser/apps/app_discovery_service/app_fetcher_manager.cc
+++ b/chrome/browser/apps/app_discovery_service/app_fetcher_manager.cc
@@ -6,8 +6,10 @@
 
 #include <utility>
 
+#include "base/notreached.h"
 #include "chrome/browser/apps/app_discovery_service/game_fetcher.h"
 #include "chrome/browser/apps/app_discovery_service/recommended_arc_app_fetcher.h"
+#include "ui/gfx/image/image_skia.h"
 
 namespace apps {
 
@@ -17,6 +19,14 @@
   return base::CallbackListSubscription();
 }
 
+void AppFetcher::GetIcon(const std::string& app_id,
+                         int32_t size_hint_in_dip,
+                         GetIconCallback callback) {
+  NOTREACHED();
+  std::move(callback).Run(gfx::ImageSkia(),
+                          DiscoveryError::kErrorRequestFailed);
+}
+
 // static
 AppFetcher* AppFetcherManager::g_test_fetcher_ = nullptr;
 
@@ -64,6 +74,28 @@
   }
 }
 
+void AppFetcherManager::GetIcon(const std::string& app_id,
+                                int32_t size_hint_in_dip,
+                                ResultType result_type,
+                                GetIconCallback callback) {
+  switch (result_type) {
+    case ResultType::kRecommendedArcApps:
+      NOTREACHED();
+      std::move(callback).Run(gfx::ImageSkia(),
+                              DiscoveryError::kErrorRequestFailed);
+      return;
+    case ResultType::kTestType:
+      NOTREACHED();
+      std::move(callback).Run(gfx::ImageSkia(),
+                              DiscoveryError::kErrorRequestFailed);
+      return;
+    case ResultType::kGameSearchCatalog:
+      DCHECK(game_fetcher_);
+      game_fetcher_->GetIcon(app_id, size_hint_in_dip, std::move(callback));
+      return;
+  }
+}
+
 // static
 void AppFetcherManager::SetOverrideFetcherForTesting(AppFetcher* fetcher) {
   g_test_fetcher_ = fetcher;
diff --git a/chrome/browser/apps/app_discovery_service/app_fetcher_manager.h b/chrome/browser/apps/app_discovery_service/app_fetcher_manager.h
index 93dc398..cfacd6e6 100644
--- a/chrome/browser/apps/app_discovery_service/app_fetcher_manager.h
+++ b/chrome/browser/apps/app_discovery_service/app_fetcher_manager.h
@@ -23,6 +23,9 @@
   virtual void GetApps(ResultCallback callback) = 0;
   virtual base::CallbackListSubscription RegisterForAppUpdates(
       RepeatingResultCallback callback);
+  virtual void GetIcon(const std::string& app_id,
+                       int32_t size_hint_in_dip,
+                       GetIconCallback callback);
 };
 
 // Backend for app fetching requests.
@@ -37,6 +40,10 @@
   base::CallbackListSubscription RegisterForAppUpdates(
       ResultType result_type,
       RepeatingResultCallback callback);
+  void GetIcon(const std::string& app_id,
+               int32_t size_hint_in_dip,
+               ResultType result_type,
+               GetIconCallback callback);
 
   static void SetOverrideFetcherForTesting(AppFetcher* fetcher);
 
diff --git a/chrome/browser/apps/app_discovery_service/game_extras.cc b/chrome/browser/apps/app_discovery_service/game_extras.cc
index f929fb0..7c892f7 100644
--- a/chrome/browser/apps/app_discovery_service/game_extras.cc
+++ b/chrome/browser/apps/app_discovery_service/game_extras.cc
@@ -14,11 +14,13 @@
     const absl::optional<std::vector<std::u16string>>& platforms,
     const std::u16string& source,
     const std::u16string& publisher,
-    const base::FilePath& relative_icon_path)
+    const base::FilePath& relative_icon_path,
+    const GURL& deeplink_url)
     : platforms_(platforms),
       source_(source),
       publisher_(publisher),
-      relative_icon_path_(relative_icon_path) {}
+      relative_icon_path_(relative_icon_path),
+      deeplink_url_(deeplink_url) {}
 
 GameExtras::GameExtras(const GameExtras&) = default;
 
@@ -45,6 +47,10 @@
   return relative_icon_path_;
 }
 
+const GURL& GameExtras::GetDeeplinkUrl() const {
+  return deeplink_url_;
+}
+
 GameExtras* GameExtras::AsGameExtras() {
   return this;
 }
diff --git a/chrome/browser/apps/app_discovery_service/game_extras.h b/chrome/browser/apps/app_discovery_service/game_extras.h
index e97e5338..5f415eb 100644
--- a/chrome/browser/apps/app_discovery_service/game_extras.h
+++ b/chrome/browser/apps/app_discovery_service/game_extras.h
@@ -11,6 +11,7 @@
 #include "base/files/file_path.h"
 #include "chrome/browser/apps/app_discovery_service/result.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/gurl.h"
 
 namespace apps {
 
@@ -19,7 +20,8 @@
   GameExtras(const absl::optional<std::vector<std::u16string>>& platforms,
              const std::u16string& source,
              const std::u16string& publisher,
-             const base::FilePath& relative_icon_path);
+             const base::FilePath& relative_icon_path,
+             const GURL& deeplink_url);
   GameExtras(const GameExtras&);
   GameExtras& operator=(const GameExtras&) = delete;
   ~GameExtras() override;
@@ -33,6 +35,7 @@
   // The company that published the game.
   const std::u16string& GetPublisher() const;
   const base::FilePath& GetRelativeIconPath() const;
+  const GURL& GetDeeplinkUrl() const;
 
   // Result::SourceExtras:
   GameExtras* AsGameExtras() override;
@@ -42,6 +45,7 @@
   std::u16string source_;
   std::u16string publisher_;
   base::FilePath relative_icon_path_;
+  GURL deeplink_url_;
 };
 
 }  // namespace apps
diff --git a/chrome/browser/apps/app_discovery_service/game_fetcher.cc b/chrome/browser/apps/app_discovery_service/game_fetcher.cc
index 8f4b365..5762f78 100644
--- a/chrome/browser/apps/app_discovery_service/game_fetcher.cc
+++ b/chrome/browser/apps/app_discovery_service/game_fetcher.cc
@@ -7,17 +7,25 @@
 #include <memory>
 #include <utility>
 
+#include "base/containers/span.h"
 #include "base/files/file_path.h"
+#include "base/files/file_util.h"
 #include "base/i18n/timezone.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
 #include "chrome/browser/apps/app_discovery_service/game_extras.h"
 #include "chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/country_codes/country_codes.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/prefs/pref_service.h"
+#include "content/public/browser/browser_thread.h"
+#include "services/data_decoder/public/cpp/decode_image.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/image/image_skia.h"
+#include "url/gurl.h"
 
 namespace {
 extern const char kDefaultLocale[] = "en-US";
@@ -98,6 +106,45 @@
   return store_names;
 }
 
+std::string ReadFileToString(const base::FilePath& path) {
+  std::string result;
+  if (!base::ReadFileToString(path, &result)) {
+    result.clear();
+  }
+  return result;
+}
+
+void ReplyWithIcon(apps::GetIconCallback callback,
+                   const SkBitmap& decoded_image) {
+  if (decoded_image.empty()) {
+    std::move(callback).Run(gfx::ImageSkia(),
+                            apps::DiscoveryError::kErrorMalformedData);
+    return;
+  }
+
+  std::move(callback).Run(gfx::ImageSkia::CreateFrom1xBitmap(decoded_image),
+                          apps::DiscoveryError::kSuccess);
+}
+
+void DecodeIcon(apps::GetIconCallback callback,
+                int32_t size_hint_in_dip,
+                const std::string& icon_data) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  if (icon_data.empty()) {
+    std::move(callback).Run(gfx::ImageSkia(),
+                            apps::DiscoveryError::kErrorRequestFailed);
+    return;
+  }
+
+  data_decoder::DecodeImageIsolated(
+      base::as_bytes(base::make_span(icon_data)),
+      data_decoder::mojom::ImageCodec::kDefault, true,
+      data_decoder::kDefaultMaxSizeInBytes,
+      gfx::Size(size_hint_in_dip, size_hint_in_dip),
+      base::BindOnce(&ReplyWithIcon, std::move(callback)));
+}
+
 }  // namespace
 
 namespace apps {
@@ -120,6 +167,41 @@
   return result_callback_list_.Add(std::move(callback));
 }
 
+void GameFetcher::GetIcon(const std::string& app_id,
+                          int32_t size_hint_in_dip,
+                          GetIconCallback callback) {
+  if (last_results_.empty()) {
+    std::move(callback).Run(gfx::ImageSkia(),
+                            DiscoveryError::kErrorRequestFailed);
+    return;
+  }
+
+  Result* app = nullptr;
+
+  for (Result& candidate : last_results_) {
+    if (candidate.GetAppId() == app_id) {
+      app = &candidate;
+    }
+  }
+
+  if (!app) {
+    std::move(callback).Run(gfx::ImageSkia(),
+                            DiscoveryError::kErrorRequestFailed);
+    return;
+  }
+
+  base::FilePath icon_path =
+      AppProvisioningDataManager::Get()->GetDataFilePath().Append(
+          app->GetSourceExtras()->AsGameExtras()->GetRelativeIconPath());
+
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+      base::BindOnce(&ReadFileToString, icon_path),
+      base::BindOnce(&DecodeIcon, std::move(callback), size_hint_in_dip));
+}
+
 void GameFetcher::OnAppDataUpdated(const proto::AppWithLocaleList& app_data) {
   last_results_ = GetAppsForCurrentLocale(app_data);
   result_callback_list_.Notify(last_results_);
@@ -136,7 +218,8 @@
         GetPlatforms(app_with_locale.app()),
         base::UTF8ToUTF16(app_with_locale.app().source_name()),
         base::UTF8ToUTF16(app_with_locale.app().publisher_name()),
-        base::FilePath(app_with_locale.app().icon_info().icon_path()));
+        base::FilePath(app_with_locale.app().icon_info().icon_path()),
+        GURL(app_with_locale.app().deeplink()));
     results.push_back(Result(
         AppSource::kGames, app_with_locale.app().app_id_for_platform(),
         GetLocalisedName(app_with_locale.locale_availability(), profile_),
diff --git a/chrome/browser/apps/app_discovery_service/game_fetcher.h b/chrome/browser/apps/app_discovery_service/game_fetcher.h
index afd8fce3..8618100 100644
--- a/chrome/browser/apps/app_discovery_service/game_fetcher.h
+++ b/chrome/browser/apps/app_discovery_service/game_fetcher.h
@@ -28,6 +28,9 @@
   void GetApps(ResultCallback callback) override;
   base::CallbackListSubscription RegisterForAppUpdates(
       RepeatingResultCallback callback) override;
+  void GetIcon(const std::string& app_id,
+               int32_t size_hint_in_dip,
+               GetIconCallback callback) override;
 
   // AppProvisioningDataManager::Observer:
   void OnAppDataUpdated(const proto::AppWithLocaleList& app_data) override;
diff --git a/chrome/browser/apps/app_service/app_service_proxy_ash.cc b/chrome/browser/apps/app_service/app_service_proxy_ash.cc
index 3b9c2625..be2a0575 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_ash.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_ash.cc
@@ -150,7 +150,7 @@
 
 void AppServiceProxyAsh::RegisterCrosApiSubScriber(
     SubscriberCrosapi* subscriber) {
-  if (base::FeatureList::IsEnabled(AppServiceCrosApiOnAppsWithoutMojom)) {
+  if (base::FeatureList::IsEnabled(kAppServiceCrosApiOnAppsWithoutMojom)) {
     crosapi_subscriber_ = subscriber;
     crosapi_subscriber_->OnApps(app_registry_cache_.GetAllApps());
   }
@@ -375,7 +375,7 @@
 }
 
 void AppServiceProxyAsh::InitializePreferredAppsForAllSubscribers() {
-  if (!base::FeatureList::IsEnabled(AppServicePreferredAppsWithoutMojom)) {
+  if (!base::FeatureList::IsEnabled(kAppServicePreferredAppsWithoutMojom)) {
     return;
   }
 
diff --git a/chrome/browser/apps/app_service/app_service_proxy_base.cc b/chrome/browser/apps/app_service/app_service_proxy_base.cc
index 46276a54..9f7f8a2f 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_base.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_base.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "components/services/app_service/app_service_mojom_impl.h"
+#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/intent_filter.h"
 #include "components/services/app_service/public/cpp/intent_filter_util.h"
@@ -140,7 +141,7 @@
       outer_icon_loader_(&icon_coalescer_,
                          apps::IconCache::GarbageCollectionPolicy::kEager),
       profile_(profile) {
-  if (base::FeatureList::IsEnabled(AppServicePreferredAppsWithoutMojom)) {
+  if (base::FeatureList::IsEnabled(kAppServicePreferredAppsWithoutMojom)) {
     preferred_apps_impl_ = std::make_unique<PreferredAppsImpl>(
         this, profile ? profile->GetPath() : base::FilePath());
   }
@@ -239,7 +240,7 @@
 void AppServiceProxyBase::OnSupportedLinksPreferenceChanged(
     const std::string& app_id,
     bool open_in_app) {
-  if (!base::FeatureList::IsEnabled(AppServicePreferredAppsWithoutMojom)) {
+  if (!base::FeatureList::IsEnabled(kAppServicePreferredAppsWithoutMojom)) {
     return;
   }
 
@@ -248,6 +249,17 @@
   }
 }
 
+void AppServiceProxyBase::OnSupportedLinksPreferenceChanged(
+    AppType app_type,
+    const std::string& app_id,
+    bool open_in_app) {
+  publishers_[app_type]->OnSupportedLinksPreferenceChanged(app_id, open_in_app);
+}
+
+bool AppServiceProxyBase::HasPublisher(AppType app_type) {
+  return base::Contains(publishers_, app_type);
+}
+
 absl::optional<IconKey> AppServiceProxyBase::GetIconKey(
     const std::string& app_id) {
   return outer_icon_loader_.GetIconKey(app_id);
diff --git a/chrome/browser/apps/app_service/app_service_proxy_base.h b/chrome/browser/apps/app_service/app_service_proxy_base.h
index e51381a..40c6b6f0 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_base.h
+++ b/chrome/browser/apps/app_service/app_service_proxy_base.h
@@ -97,6 +97,10 @@
   void InitializePreferredAppsForAllSubscribers() override;
   void OnSupportedLinksPreferenceChanged(const std::string& app_id,
                                          bool open_in_app) override;
+  void OnSupportedLinksPreferenceChanged(AppType app_type,
+                                         const std::string& app_id,
+                                         bool open_in_app) override;
+  bool HasPublisher(AppType app_type) override;
 
   // apps::IconLoader overrides.
   absl::optional<IconKey> GetIconKey(const std::string& app_id) override;
diff --git a/chrome/browser/apps/app_service/subscriber_crosapi.cc b/chrome/browser/apps/app_service/subscriber_crosapi.cc
index c57fc7a..9e19b07 100644
--- a/chrome/browser/apps/app_service/subscriber_crosapi.cc
+++ b/chrome/browser/apps/app_service/subscriber_crosapi.cc
@@ -92,7 +92,7 @@
 void SubscriberCrosapi::OnApps(std::vector<apps::mojom::AppPtr> deltas,
                                apps::mojom::AppType mojom_app_type,
                                bool should_notify_initialized) {
-  if (base::FeatureList::IsEnabled(AppServiceCrosApiOnAppsWithoutMojom)) {
+  if (base::FeatureList::IsEnabled(kAppServiceCrosApiOnAppsWithoutMojom)) {
     return;
   }
 
diff --git a/chrome/browser/ash/arc/arc_util_unittest.cc b/chrome/browser/ash/arc/arc_util_unittest.cc
index 492726c..764180d 100644
--- a/chrome/browser/ash/arc/arc_util_unittest.cc
+++ b/chrome/browser/ash/arc/arc_util_unittest.cc
@@ -32,7 +32,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/oobe_config/fake_oobe_configuration_client.h"
 #include "components/account_id/account_id.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
diff --git a/chrome/browser/ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge_unittest.cc b/chrome/browser/ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge_unittest.cc
index e32cd91..944b329 100644
--- a/chrome/browser/ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge_unittest.cc
+++ b/chrome/browser/ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge_unittest.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/ash/arc/test/test_arc_session_manager.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
diff --git a/chrome/browser/ash/arc/enterprise/arc_data_snapshotd_delegate_unittest.cc b/chrome/browser/ash/arc/enterprise/arc_data_snapshotd_delegate_unittest.cc
index 0ea803d..a1f3091 100644
--- a/chrome/browser/ash/arc/enterprise/arc_data_snapshotd_delegate_unittest.cc
+++ b/chrome/browser/ash/arc/enterprise/arc_data_snapshotd_delegate_unittest.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/ash/arc/test/test_arc_session_manager.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/scoped_user_manager.h"
diff --git a/chrome/browser/ash/arc/enterprise/arc_enterprise_reporting_service_unittest.cc b/chrome/browser/ash/arc/enterprise/arc_enterprise_reporting_service_unittest.cc
index 12af69d..08c05ed8 100644
--- a/chrome/browser/ash/arc/enterprise/arc_enterprise_reporting_service_unittest.cc
+++ b/chrome/browser/ash/arc/enterprise/arc_enterprise_reporting_service_unittest.cc
@@ -18,7 +18,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/arc/fileapi/arc_file_system_bridge_unittest.cc b/chrome/browser/ash/arc/fileapi/arc_file_system_bridge_unittest.cc
index b1d03a2..e2d3ef7 100644
--- a/chrome/browser/ash/arc/fileapi/arc_file_system_bridge_unittest.cc
+++ b/chrome/browser/ash/arc/fileapi/arc_file_system_bridge_unittest.cc
@@ -26,7 +26,7 @@
 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/virtual_file_provider/fake_virtual_file_provider_client.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/arc/instance_throttle/arc_boot_phase_throttle_observer_unittest.cc b/chrome/browser/ash/arc/instance_throttle/arc_boot_phase_throttle_observer_unittest.cc
index 56ae368..9ab31bd7 100644
--- a/chrome/browser/ash/arc/instance_throttle/arc_boot_phase_throttle_observer_unittest.cc
+++ b/chrome/browser/ash/arc/instance_throttle/arc_boot_phase_throttle_observer_unittest.cc
@@ -23,7 +23,7 @@
 #include "chrome/browser/ash/arc/test/test_arc_session_manager.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/arc/test/fake_intent_helper_host.h"
 #include "components/arc/test/fake_intent_helper_instance.h"
diff --git a/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle.cc b/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle.cc
index 5c1ad23..5bfb4b6 100644
--- a/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle.cc
+++ b/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle.cc
@@ -21,7 +21,7 @@
 #include "chrome/browser/ash/arc/instance_throttle/arc_power_throttle_observer.h"
 #include "chrome/browser/ash/arc/instance_throttle/arc_provisioning_throttle_observer.h"
 #include "chrome/browser/ash/arc/instance_throttle/arc_switch_throttle_observer.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 
 namespace arc {
diff --git a/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle_unittest.cc b/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle_unittest.cc
index 3c71c66c..3897b3c0e9 100644
--- a/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle_unittest.cc
+++ b/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle_unittest.cc
@@ -29,7 +29,7 @@
 #include "chrome/browser/ash/arc/test/test_arc_session_manager.h"
 #include "chrome/browser/ash/throttle_observer.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "components/arc/test/fake_intent_helper_host.h"
diff --git a/chrome/browser/ash/arc/instance_throttle/arc_power_throttle_observer_unittest.cc b/chrome/browser/ash/arc/instance_throttle/arc_power_throttle_observer_unittest.cc
index e5d17db..0189755 100644
--- a/chrome/browser/ash/arc/instance_throttle/arc_power_throttle_observer_unittest.cc
+++ b/chrome/browser/ash/arc/instance_throttle/arc_power_throttle_observer_unittest.cc
@@ -14,7 +14,7 @@
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chrome/browser/ash/arc/test/test_arc_session_manager.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/arc/instance_throttle/arc_provisioning_throttle_observer_unittest.cc b/chrome/browser/ash/arc/instance_throttle/arc_provisioning_throttle_observer_unittest.cc
index 3aa2dd9..46b2f8b 100644
--- a/chrome/browser/ash/arc/instance_throttle/arc_provisioning_throttle_observer_unittest.cc
+++ b/chrome/browser/ash/arc/instance_throttle/arc_provisioning_throttle_observer_unittest.cc
@@ -18,7 +18,7 @@
 #include "chrome/browser/ash/arc/test/test_arc_session_manager.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/arc/intent_helper/arc_settings_service_unittest.cc b/chrome/browser/ash/arc/intent_helper/arc_settings_service_unittest.cc
index 054ca0d..783939a 100644
--- a/chrome/browser/ash/arc/intent_helper/arc_settings_service_unittest.cc
+++ b/chrome/browser/ash/arc/intent_helper/arc_settings_service_unittest.cc
@@ -29,7 +29,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
diff --git a/chrome/browser/ash/arc/notification/arc_provision_notification_service_unittest.cc b/chrome/browser/ash/arc/notification/arc_provision_notification_service_unittest.cc
index 30d5de69..72c9a14c 100644
--- a/chrome/browser/ash/arc/notification/arc_provision_notification_service_unittest.cc
+++ b/chrome/browser/ash/arc/notification/arc_provision_notification_service_unittest.cc
@@ -26,7 +26,7 @@
 #include "chrome/browser/notifications/notification_display_service_tester.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/session_manager/core/session_manager.h"
diff --git a/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc b/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc
index 59303f9..faa5b9b 100644
--- a/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc
+++ b/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc
@@ -35,8 +35,8 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/upstart/fake_upstart_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/system/fake_statistics_provider.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
diff --git a/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler_unittest.cc b/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler_unittest.cc
index feeceb1a..ee76d291 100644
--- a/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler_unittest.cc
+++ b/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler_unittest.cc
@@ -28,8 +28,8 @@
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/upstart/upstart_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/consent_auditor/fake_consent_auditor.h"
diff --git a/chrome/browser/ash/arc/session/arc_session_manager.h b/chrome/browser/ash/arc/session/arc_session_manager.h
index 96e2596..fea6e23 100644
--- a/chrome/browser/ash/arc/session/arc_session_manager.h
+++ b/chrome/browser/ash/arc/session/arc_session_manager.h
@@ -21,7 +21,7 @@
 #include "chrome/browser/ash/arc/session/arc_app_id_provider_impl.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager_observer.h"
 #include "chrome/browser/ash/policy/arc/android_management_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/policy/core/common/policy_service.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chrome/browser/ash/arc/session/arc_session_manager_unittest.cc b/chrome/browser/ash/arc/session/arc_session_manager_unittest.cc
index 85caa32e..5669097 100644
--- a/chrome/browser/ash/arc/session/arc_session_manager_unittest.cc
+++ b/chrome/browser/ash/arc/session/arc_session_manager_unittest.cc
@@ -54,8 +54,8 @@
 #include "chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/upstart/upstart_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
diff --git a/chrome/browser/ash/borealis/borealis_app_launcher_unittest.cc b/chrome/browser/ash/borealis/borealis_app_launcher_unittest.cc
index 2eadff5c..5197970 100644
--- a/chrome/browser/ash/borealis/borealis_app_launcher_unittest.cc
+++ b/chrome/browser/ash/borealis/borealis_app_launcher_unittest.cc
@@ -16,10 +16,10 @@
 #include "chrome/browser/ash/guest_os/guest_os_registry_service.h"
 #include "chrome/browser/ash/guest_os/guest_os_registry_service_factory.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/vm_applications/apps.pb.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/borealis/borealis_context_manager_impl.cc b/chrome/browser/ash/borealis/borealis_context_manager_impl.cc
index 2c93be7b..89587eb 100644
--- a/chrome/browser/ash/borealis/borealis_context_manager_impl.cc
+++ b/chrome/browser/ash/borealis/borealis_context_manager_impl.cc
@@ -18,7 +18,7 @@
 #include "chrome/browser/ash/borealis/infra/described.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/sessions/exit_type_service.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 
 namespace {
diff --git a/chrome/browser/ash/borealis/borealis_context_manager_impl.h b/chrome/browser/ash/borealis/borealis_context_manager_impl.h
index 025bfd3..0377b754 100644
--- a/chrome/browser/ash/borealis/borealis_context_manager_impl.h
+++ b/chrome/browser/ash/borealis/borealis_context_manager_impl.h
@@ -15,7 +15,7 @@
 #include "chrome/browser/ash/borealis/infra/described.h"
 #include "chrome/browser/ash/borealis/infra/transition.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 
 namespace borealis {
 
diff --git a/chrome/browser/ash/borealis/borealis_context_manager_unittest.cc b/chrome/browser/ash/borealis/borealis_context_manager_unittest.cc
index 1218766..70d62d1 100644
--- a/chrome/browser/ash/borealis/borealis_context_manager_unittest.cc
+++ b/chrome/browser/ash/borealis/borealis_context_manager_unittest.cc
@@ -21,8 +21,8 @@
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/sessions/exit_type_service.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/borealis/borealis_context_unittest.cc b/chrome/browser/ash/borealis/borealis_context_unittest.cc
index 04fae1d..9ada0ef 100644
--- a/chrome/browser/ash/borealis/borealis_context_unittest.cc
+++ b/chrome/browser/ash/borealis/borealis_context_unittest.cc
@@ -22,10 +22,10 @@
 #include "chrome/browser/ash/borealis/testing/dbus.h"
 #include "chrome/browser/ash/guest_os/guest_os_stability_monitor.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/fake_seneschal_client.h"
 #include "chromeos/dbus/chunneld/fake_chunneld_client.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/exo/shell_surface_util.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/borealis/borealis_disk_manager_impl.cc b/chrome/browser/ash/borealis/borealis_disk_manager_impl.cc
index 3dc6a6ec..da1cb852 100644
--- a/chrome/browser/ash/borealis/borealis_disk_manager_impl.cc
+++ b/chrome/browser/ash/borealis/borealis_disk_manager_impl.cc
@@ -22,8 +22,8 @@
 #include "chrome/browser/ash/crostini/crostini_util.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 
 namespace borealis {
 namespace {
diff --git a/chrome/browser/ash/borealis/borealis_disk_manager_unittest.cc b/chrome/browser/ash/borealis/borealis_disk_manager_unittest.cc
index 4c294ad..61e2165 100644
--- a/chrome/browser/ash/borealis/borealis_disk_manager_unittest.cc
+++ b/chrome/browser/ash/borealis/borealis_disk_manager_unittest.cc
@@ -21,10 +21,10 @@
 #include "chrome/browser/ash/borealis/testing/dbus.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/ash/borealis/borealis_installer_impl.cc b/chrome/browser/ash/borealis/borealis_installer_impl.cc
index 40b515f..5d4d031 100644
--- a/chrome/browser/ash/borealis/borealis_installer_impl.cc
+++ b/chrome/browser/ash/borealis/borealis_installer_impl.cc
@@ -20,8 +20,8 @@
 #include "chrome/browser/ash/guest_os/guest_os_registry_service_factory.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "chromeos/dbus/dlcservice/dlcservice.pb.h"
 #include "chromeos/dbus/vm_applications/apps.pb.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ash/borealis/borealis_installer_unittest.cc b/chrome/browser/ash/borealis/borealis_installer_unittest.cc
index e52892e..9a697a0 100644
--- a/chrome/browser/ash/borealis/borealis_installer_unittest.cc
+++ b/chrome/browser/ash/borealis/borealis_installer_unittest.cc
@@ -29,7 +29,7 @@
 #include "chrome/browser/ash/guest_os/guest_os_registry_service_factory.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dlcservice/fake_dlcservice_client.h"
 #include "chromeos/dbus/vm_applications/apps.pb.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ash/borealis/borealis_task.cc b/chrome/browser/ash/borealis/borealis_task.cc
index 35b56551..37cb43ce 100644
--- a/chrome/browser/ash/borealis/borealis_task.cc
+++ b/chrome/browser/ash/borealis/borealis_task.cc
@@ -30,7 +30,7 @@
 #include "chrome/browser/ash/guest_os/public/guest_os_wayland_server.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "chromeos/dbus/dlcservice/dlcservice.pb.h"
 #include "chromeos/dbus/vm_launch/launch.pb.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chrome/browser/ash/borealis/borealis_task.h b/chrome/browser/ash/borealis/borealis_task.h
index 5be09a7c..9f8f0ef 100644
--- a/chrome/browser/ash/borealis/borealis_task.h
+++ b/chrome/browser/ash/borealis/borealis_task.h
@@ -14,7 +14,7 @@
 #include "chrome/browser/ash/borealis/borealis_launch_watcher.h"
 #include "chrome/browser/ash/borealis/borealis_metrics.h"
 #include "chrome/browser/ash/guest_os/public/guest_os_wayland_server.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dlcservice/dlcservice_client.h"
 
 namespace borealis {
diff --git a/chrome/browser/ash/borealis/borealis_task_unittest.cc b/chrome/browser/ash/borealis/borealis_task_unittest.cc
index c60eb2f..cde80e5 100644
--- a/chrome/browser/ash/borealis/borealis_task_unittest.cc
+++ b/chrome/browser/ash/borealis/borealis_task_unittest.cc
@@ -14,9 +14,9 @@
 #include "chrome/browser/ash/borealis/testing/dbus.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/dlcservice/fake_dlcservice_client.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/borealis/testing/dbus.cc b/chrome/browser/ash/borealis/testing/dbus.cc
index 7ba9dc2a..b14ee6b 100644
--- a/chrome/browser/ash/borealis/testing/dbus.cc
+++ b/chrome/browser/ash/borealis/testing/dbus.cc
@@ -4,9 +4,9 @@
 
 #include "chrome/browser/ash/borealis/testing/dbus.h"
 
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/fake_seneschal_client.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/dlcservice/fake_dlcservice_client.h"
 
diff --git a/chrome/browser/ash/concierge_helper_service.cc b/chrome/browser/ash/concierge_helper_service.cc
index 479097e..341ec311 100644
--- a/chrome/browser/ash/concierge_helper_service.cc
+++ b/chrome/browser/ash/concierge_helper_service.cc
@@ -7,8 +7,8 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/no_destructor.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
diff --git a/chrome/browser/ash/concierge_helper_service_unittest.cc b/chrome/browser/ash/concierge_helper_service_unittest.cc
index e67e93e9..70a9e0ba 100644
--- a/chrome/browser/ash/concierge_helper_service_unittest.cc
+++ b/chrome/browser/ash/concierge_helper_service_unittest.cc
@@ -8,8 +8,8 @@
 
 #include "base/run_loop.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "content/public/test/browser_task_environment.h"
 #include "dbus/bus.h"
 #include "dbus/object_proxy.h"
diff --git a/chrome/browser/ash/crostini/ansible/ansible_management_service.cc b/chrome/browser/ash/crostini/ansible/ansible_management_service.cc
index 4ddc2b1..0866b25 100644
--- a/chrome/browser/ash/crostini/ansible/ansible_management_service.cc
+++ b/chrome/browser/ash/crostini/ansible/ansible_management_service.cc
@@ -30,6 +30,18 @@
 
 }  // namespace
 
+AnsibleConfiguration::AnsibleConfiguration(
+    std::string playbook,
+    base::FilePath path,
+    base::OnceCallback<void(bool success)> callback)
+    : playbook(playbook), path(path), callback(std::move(callback)) {}
+AnsibleConfiguration::AnsibleConfiguration(
+    base::FilePath path,
+    base::OnceCallback<void(bool success)> callback)
+    : AnsibleConfiguration("", path, std::move(callback)) {}
+
+AnsibleConfiguration::~AnsibleConfiguration() {}
+
 AnsibleManagementService* AnsibleManagementService::GetForProfile(
     Profile* profile) {
   return AnsibleManagementServiceFactory::GetForProfile(profile);
@@ -39,16 +51,30 @@
     : profile_(profile), weak_ptr_factory_(this) {}
 AnsibleManagementService::~AnsibleManagementService() = default;
 
-void AnsibleManagementService::ConfigureDefaultContainer(
+void AnsibleManagementService::ConfigureContainer(
+    const ContainerId& container_id,
+    base::FilePath playbook_path,
     base::OnceCallback<void(bool success)> callback) {
-  if (!ShouldConfigureDefaultContainer(profile_)) {
+  if (configuration_tasks_.count(container_id) > 0) {
+    LOG(ERROR) << "Attempting to configure a container which is already being "
+                  "configured";
+    std::move(callback).Run(false);
+  }
+  if (container_id == ContainerId::GetDefault() &&
+      !ShouldConfigureDefaultContainer(profile_)) {
     LOG(ERROR) << "Trying to configure default Crostini container when it "
                << "should not be configured";
     std::move(callback).Run(false);
     return;
   }
-  DCHECK(!configuration_finished_callback_);
-  configuration_finished_callback_ = std::move(callback);
+  // Add ourselves as an observer if we aren't already awaiting.
+  if (configuration_tasks_.empty()) {
+    CrostiniManager::GetForProfile(profile_)
+        ->AddLinuxPackageOperationProgressObserver(this);
+  }
+  configuration_tasks_.emplace(
+      std::make_pair(container_id, std::make_unique<AnsibleConfiguration>(
+                                       playbook_path, std::move(callback))));
 
   // Popup dialog is shown in case Crostini has already been installed.
   if (!CrostiniManager::GetForProfile(profile_)->GetCrostiniDialogStatus(
@@ -56,23 +82,20 @@
     ShowCrostiniAnsibleSoftwareConfigView(profile_);
 
   for (auto& observer : observers_) {
-    observer.OnAnsibleSoftwareConfigurationStarted();
+    observer.OnAnsibleSoftwareConfigurationStarted(container_id);
   }
-
-  CrostiniManager::GetForProfile(profile_)
-      ->AddLinuxPackageOperationProgressObserver(this);
   CrostiniManager::GetForProfile(profile_)->InstallLinuxPackageFromApt(
-      ContainerId::GetDefault(), kCrostiniDefaultAnsibleVersion,
-      base::BindOnce(
-          &AnsibleManagementService::OnInstallAnsibleInDefaultContainer,
-          weak_ptr_factory_.GetWeakPtr()));
+      container_id, kCrostiniDefaultAnsibleVersion,
+      base::BindOnce(&AnsibleManagementService::OnInstallAnsibleInContainer,
+                     weak_ptr_factory_.GetWeakPtr(), container_id));
 }
 
-void AnsibleManagementService::OnInstallAnsibleInDefaultContainer(
+void AnsibleManagementService::OnInstallAnsibleInContainer(
+    const ContainerId& container_id,
     CrostiniResult result) {
   if (result == CrostiniResult::INSTALL_LINUX_PACKAGE_FAILED) {
     LOG(ERROR) << "Ansible installation failed";
-    OnConfigurationFinished(false);
+    OnConfigurationFinished(container_id, false);
     return;
   }
 
@@ -81,6 +104,9 @@
   DCHECK_EQ(result, CrostiniResult::SUCCESS);
   VLOG(1) << "Ansible installation has been started successfully";
   // Waiting for Ansible installation progress being reported.
+  for (auto& observer : observers_) {
+    observer.OnAnsibleSoftwareInstall(container_id);
+  }
 }
 
 void AnsibleManagementService::OnInstallLinuxPackageProgress(
@@ -88,17 +114,14 @@
     InstallLinuxPackageProgressStatus status,
     int progress_percent,
     const std::string& error_message) {
-  DCHECK_EQ(container_id.vm_name, kCrostiniDefaultVmName);
-  DCHECK_EQ(container_id.container_name, kCrostiniDefaultContainerName);
-
   switch (status) {
     case InstallLinuxPackageProgressStatus::SUCCEEDED: {
-      GetAnsiblePlaybookToApply();
+      GetAnsiblePlaybookToApply(container_id);
       return;
     }
     case InstallLinuxPackageProgressStatus::FAILED:
       LOG(ERROR) << "Ansible installation failed";
-      OnConfigurationFinished(false);
+      OnConfigurationFinished(container_id, false);
       return;
     // TODO(okalitova): Report Ansible downloading/installation progress.
     case InstallLinuxPackageProgressStatus::DOWNLOADING:
@@ -112,59 +135,65 @@
   }
 }
 
-void AnsibleManagementService::GetAnsiblePlaybookToApply() {
+void AnsibleManagementService::GetAnsiblePlaybookToApply(
+    const ContainerId& container_id) {
+  DCHECK_GT(configuration_tasks_.count(container_id), 0);
   const base::FilePath& ansible_playbook_file_path =
-      profile_->GetPrefs()->GetFilePath(
-          prefs::kCrostiniAnsiblePlaybookFilePath);
+      configuration_tasks_[container_id]->path;
   bool success = base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::BindOnce(base::ReadFileToString, ansible_playbook_file_path,
-                     &playbook_),
+                     &configuration_tasks_[container_id]->playbook),
       base::BindOnce(&AnsibleManagementService::OnAnsiblePlaybookRetrieved,
-                     weak_ptr_factory_.GetWeakPtr()));
+                     weak_ptr_factory_.GetWeakPtr(), container_id));
   if (!success) {
     LOG(ERROR) << "Failed to post task to retrieve Ansible playbook content";
-    OnConfigurationFinished(false);
+    OnConfigurationFinished(container_id, false);
   }
 }
 
-void AnsibleManagementService::OnAnsiblePlaybookRetrieved(bool success) {
+void AnsibleManagementService::OnAnsiblePlaybookRetrieved(
+    const ContainerId& container_id,
+    bool success) {
   if (!success) {
     LOG(ERROR) << "Failed to retrieve Ansible playbook content";
-    OnConfigurationFinished(false);
+    OnConfigurationFinished(container_id, false);
     return;
   }
 
-  ApplyAnsiblePlaybookToDefaultContainer();
+  ApplyAnsiblePlaybook(container_id);
 }
 
-void AnsibleManagementService::ApplyAnsiblePlaybookToDefaultContainer() {
+void AnsibleManagementService::ApplyAnsiblePlaybook(
+    const ContainerId& container_id) {
+  DCHECK_GT(configuration_tasks_.count(container_id), 0);
   if (!GetCiceroneClient()->IsApplyAnsiblePlaybookProgressSignalConnected()) {
     // Technically we could still start the application, but we wouldn't be able
     // to detect when the application completes, successfully or otherwise.
     LOG(ERROR)
         << "Attempted to apply playbook when progress signal not connected.";
-    OnConfigurationFinished(false);
+    OnConfigurationFinished(container_id, false);
     return;
   }
 
   vm_tools::cicerone::ApplyAnsiblePlaybookRequest request;
   request.set_owner_id(CryptohomeIdForProfile(profile_));
-  request.set_vm_name(std::move(kCrostiniDefaultVmName));
-  request.set_container_name(std::move(kCrostiniDefaultContainerName));
-  request.set_playbook(std::move(playbook_));
+  request.set_vm_name(container_id.vm_name);
+  request.set_container_name(container_id.container_name);
+  request.set_playbook(configuration_tasks_[container_id]->playbook);
 
   GetCiceroneClient()->ApplyAnsiblePlaybook(
       std::move(request),
       base::BindOnce(&AnsibleManagementService::OnApplyAnsiblePlaybook,
-                     weak_ptr_factory_.GetWeakPtr()));
+                     weak_ptr_factory_.GetWeakPtr(), container_id));
 }
 
 void AnsibleManagementService::OnApplyAnsiblePlaybook(
+    const ContainerId& container_id,
     absl::optional<vm_tools::cicerone::ApplyAnsiblePlaybookResponse> response) {
   if (!response) {
     LOG(ERROR) << "Failed to apply Ansible playbook. Empty response.";
-    OnConfigurationFinished(false);
+    OnConfigurationFinished(container_id, false);
     return;
   }
 
@@ -172,26 +201,29 @@
       vm_tools::cicerone::ApplyAnsiblePlaybookResponse::FAILED) {
     LOG(ERROR) << "Failed to apply Ansible playbook: "
                << response->failure_reason();
-    OnConfigurationFinished(false);
+    OnConfigurationFinished(container_id, false);
     return;
   }
 
   VLOG(1) << "Ansible playbook application has been started successfully";
   // Waiting for Ansible playbook application progress being reported.
   // TODO(https://crbug.com/1043060): Add a timeout after which we stop waiting.
+  for (auto& observer : observers_) {
+    observer.OnApplyAnsiblePlaybook(container_id);
+  }
 }
 
 void AnsibleManagementService::OnApplyAnsiblePlaybookProgress(
-    vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::Status status,
-    const std::string& failure_details) {
-  switch (status) {
+    const vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal& signal) {
+  ContainerId container_id(signal.vm_name(), signal.container_name());
+  switch (signal.status()) {
     case vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::SUCCEEDED:
-      OnConfigurationFinished(true);
+      OnConfigurationFinished(container_id, true);
       break;
     case vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::FAILED:
       LOG(ERROR) << "Ansible playbook application has failed with reason:\n"
-                 << failure_details;
-      OnConfigurationFinished(false);
+                 << signal.failure_details();
+      OnConfigurationFinished(container_id, false);
       break;
     case vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::IN_PROGRESS:
       // TODO(okalitova): Report Ansible playbook application progress.
@@ -217,18 +249,27 @@
   NOTIMPLEMENTED();
 }
 
-void AnsibleManagementService::OnConfigurationFinished(bool success) {
-  DCHECK(configuration_finished_callback_);
-  if (success) {
+void AnsibleManagementService::OnConfigurationFinished(
+    const ContainerId& container_id,
+    bool success) {
+  DCHECK_GT(configuration_tasks_.count(container_id), 0);
+  if (success && container_id == ContainerId::GetDefault()) {
     profile_->GetPrefs()->SetBoolean(prefs::kCrostiniDefaultContainerConfigured,
                                      true);
   }
-  CrostiniManager::GetForProfile(profile_)
-      ->RemoveLinuxPackageOperationProgressObserver(this);
   for (auto& observer : observers_) {
-    observer.OnAnsibleSoftwareConfigurationFinished(success);
+    observer.OnAnsibleSoftwareConfigurationFinished(container_id, success);
   }
-  std::move(configuration_finished_callback_).Run(success);
+  auto callback = std::move(configuration_tasks_[container_id]->callback);
+  configuration_tasks_.erase(configuration_tasks_.find(container_id));
+
+  // Clean up our observer if no more packages are awaiting this.
+  if (configuration_tasks_.empty()) {
+    CrostiniManager::GetForProfile(profile_)
+        ->RemoveLinuxPackageOperationProgressObserver(this);
+  }
+
+  std::move(callback).Run(success);
 }
 
 }  // namespace crostini
diff --git a/chrome/browser/ash/crostini/ansible/ansible_management_service.h b/chrome/browser/ash/crostini/ansible/ansible_management_service.h
index cba67623..6f2fd274 100644
--- a/chrome/browser/ash/crostini/ansible/ansible_management_service.h
+++ b/chrome/browser/ash/crostini/ansible/ansible_management_service.h
@@ -15,6 +15,19 @@
 
 namespace crostini {
 
+struct AnsibleConfiguration {
+  AnsibleConfiguration(std::string playbook,
+                       base::FilePath path,
+                       base::OnceCallback<void(bool success)> callback);
+  AnsibleConfiguration(base::FilePath path,
+                       base::OnceCallback<void(bool success)> callback);
+  ~AnsibleConfiguration();
+
+  std::string playbook;
+  base::FilePath path;
+  base::OnceCallback<void(bool success)> callback;
+};
+
 // TODO(okalitova): Install Ansible from backports repo once this is feasible.
 extern const char kCrostiniDefaultAnsibleVersion[];
 
@@ -27,8 +40,13 @@
   class Observer : public base::CheckedObserver {
    public:
     ~Observer() override = default;
-    virtual void OnAnsibleSoftwareConfigurationStarted() = 0;
-    virtual void OnAnsibleSoftwareConfigurationFinished(bool success) = 0;
+    virtual void OnAnsibleSoftwareConfigurationStarted(
+        const ContainerId& container_id) = 0;
+    virtual void OnAnsibleSoftwareConfigurationFinished(
+        const ContainerId& container_id,
+        bool success) = 0;
+    virtual void OnAnsibleSoftwareInstall(const ContainerId& container_id) {}
+    virtual void OnApplyAnsiblePlaybook(const ContainerId& container_id) {}
   };
 
   static AnsibleManagementService* GetForProfile(Profile* profile);
@@ -40,10 +58,10 @@
 
   ~AnsibleManagementService() override;
 
-  // |callback| is called once default Crostini container configuration is
-  // finished.
-  void ConfigureDefaultContainer(
-      base::OnceCallback<void(bool success)> callback);
+  // Preconfigures a container with a specified Ansible playbook.
+  void ConfigureContainer(const ContainerId& container_id,
+                          base::FilePath playbook,
+                          base::OnceCallback<void(bool success)> callback);
 
   // LinuxPackageOperationProgressObserver:
   void OnInstallLinuxPackageProgress(const ContainerId& container_id,
@@ -55,29 +73,31 @@
                                   int progress_percent) override;
 
   void OnApplyAnsiblePlaybookProgress(
-      vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::Status status,
-      const std::string& failure_details);
+      const vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal& signal);
 
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
 
  private:
-  void InstallAnsibleInDefaultContainer();
-  void OnInstallAnsibleInDefaultContainer(CrostiniResult result);
-  void GetAnsiblePlaybookToApply();
-  void OnAnsiblePlaybookRetrieved(bool success);
-  void ApplyAnsiblePlaybookToDefaultContainer();
+  void OnInstallAnsibleInContainer(const ContainerId& container_id,
+                                   CrostiniResult result);
+  void GetAnsiblePlaybookToApply(const ContainerId& container_id);
+  void OnAnsiblePlaybookRetrieved(const ContainerId& container_id,
+                                  bool success);
+  void ApplyAnsiblePlaybook(const ContainerId& container_id);
   void OnApplyAnsiblePlaybook(
+      const ContainerId& container_id,
       absl::optional<vm_tools::cicerone::ApplyAnsiblePlaybookResponse>
           response);
 
   // Helper function that runs relevant callback and notifies observers.
-  void OnConfigurationFinished(bool success);
+  void OnConfigurationFinished(const ContainerId& container_id, bool success);
 
   Profile* profile_;
   base::ObserverList<Observer> observers_;
-  base::OnceCallback<void(bool success)> configuration_finished_callback_;
-  std::string playbook_;
+  std::map<ContainerId, std::unique_ptr<AnsibleConfiguration>>
+      configuration_tasks_;
+
   base::WeakPtrFactory<AnsibleManagementService> weak_ptr_factory_;
 };
 
diff --git a/chrome/browser/ash/crostini/ansible/ansible_management_service_unittest.cc b/chrome/browser/ash/crostini/ansible/ansible_management_service_unittest.cc
index 386977e7..dc037b1 100644
--- a/chrome/browser/ash/crostini/ansible/ansible_management_service_unittest.cc
+++ b/chrome/browser/ash/crostini/ansible/ansible_management_service_unittest.cc
@@ -4,21 +4,34 @@
 
 #include "chrome/browser/ash/crostini/ansible/ansible_management_service.h"
 
+#include "base/test/bind.h"
 #include "base/test/mock_callback.h"
 #include "chrome/browser/ash/crostini/ansible/ansible_management_test_helper.h"
+#include "chrome/browser/ash/crostini/crostini_pref_names.h"
 #include "chrome/browser/ash/crostini/crostini_test_util.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "components/prefs/pref_service.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace {
+void ExpectResult(base::OnceClosure closure,
+                  bool expected_result,
+                  bool actual_result) {
+  EXPECT_EQ(expected_result, actual_result);
+  std::move(closure).Run();
+}
+}  // namespace
+
 namespace crostini {
 
-class AnsibleManagementServiceTest : public testing::Test {
+class AnsibleManagementServiceTest : public testing::Test,
+                                     public AnsibleManagementService::Observer {
  public:
   AnsibleManagementServiceTest() {
     chromeos::DBusThreadManager::Initialize();
@@ -58,76 +71,147 @@
     chromeos::DBusThreadManager::Shutdown();
   }
 
+  void SetUp() override {
+    run_loop_ = std::make_unique<base::RunLoop>();
+    is_install_ansible_success_ = true;
+    is_apply_ansible_success_ = true;
+    ansible_management_service_->AddObserver(this);
+  }
+
+  void TearDown() override {
+    run_loop_.reset();
+    ansible_management_service_->RemoveObserver(this);
+  }
+
+  void ExpectTrueResult(bool success) {
+    EXPECT_TRUE(success);
+    run_loop()->Quit();
+  }
+
+  void ExpectFalseResult(bool success) {
+    EXPECT_FALSE(success);
+    run_loop()->Quit();
+  }
+
+  // AnsibleManagementService::Observer
+  void OnAnsibleSoftwareConfigurationStarted(
+      const ContainerId& container_id) override {}
+  void OnAnsibleSoftwareConfigurationFinished(const ContainerId& container_id,
+                                              bool success) override {}
+  void OnAnsibleSoftwareInstall(const ContainerId& container_id) override {
+    if (is_install_ansible_success_) {
+      test_helper_->SendSucceededInstallSignal();
+    } else {
+      test_helper_->SendFailedInstallSignal();
+    }
+  }
+  void OnApplyAnsiblePlaybook(const ContainerId& container_id) override {
+    if (is_apply_ansible_success_) {
+      test_helper_->SendSucceededApplySignal();
+    } else {
+      test_helper_->SendFailedApplySignal();
+    }
+  }
+
+ private:
+  std::unique_ptr<base::RunLoop> run_loop_;
+  CrostiniManager* crostini_manager_;
+  AnsibleManagementService* ansible_management_service_;
+  bool is_install_ansible_success_;
+  bool is_apply_ansible_success_;
+
  protected:
   AnsibleManagementService* ansible_management_service() {
     return ansible_management_service_;
   }
 
-  void ExecuteSuccessfulConfigurationFlow() {
-    ansible_management_service()->ConfigureDefaultContainer(
-        configuration_finished_mock_callback_.Get());
-    // Should wait for Cicerone response for Linux package install request.
-    base::RunLoop().RunUntilIdle();
-    test_helper_->SendSucceededInstallSignal();
-    // AnsibleManagementService should read playbook file content.
-    task_environment_.RunUntilIdle();
-    test_helper_->SendSucceededApplySignal();
+  base::RunLoop* run_loop() { return run_loop_.get(); }
+
+  void SetInstallAnsibleStatus(bool status) {
+    is_install_ansible_success_ = status;
+  }
+  void SetApplyAnsibleStatus(bool status) {
+    is_apply_ansible_success_ = status;
   }
 
   content::BrowserTaskEnvironment task_environment_;
   std::unique_ptr<AnsibleManagementTestHelper> test_helper_;
-  base::MockCallback<base::OnceCallback<void(bool)>>
-      configuration_finished_mock_callback_;
-
- private:
   std::unique_ptr<TestingProfile> profile_;
-  CrostiniManager* crostini_manager_;
-  AnsibleManagementService* ansible_management_service_;
+
+  base::WeakPtrFactory<AnsibleManagementServiceTest> weak_ptr_factory_{this};
 };
 
-TEST_F(AnsibleManagementServiceTest, ConfigureDefaultContainerSuccess) {
+TEST_F(AnsibleManagementServiceTest, ConfigureContainerSuccess) {
   test_helper_->SetUpAnsibleInstallation(
       vm_tools::cicerone::InstallLinuxPackageResponse::STARTED);
   test_helper_->SetUpPlaybookApplication(
       vm_tools::cicerone::ApplyAnsiblePlaybookResponse::STARTED);
 
-  EXPECT_CALL(configuration_finished_mock_callback_, Run(true)).Times(1);
-
-  ansible_management_service()->ConfigureDefaultContainer(
-      configuration_finished_mock_callback_.Get());
-  base::RunLoop().RunUntilIdle();
-
-  test_helper_->SendSucceededInstallSignal();
-  task_environment_.RunUntilIdle();
-
-  test_helper_->SendSucceededApplySignal();
+  ansible_management_service()->ConfigureContainer(
+      ContainerId::GetDefault(),
+      profile_->GetPrefs()->GetFilePath(
+          prefs::kCrostiniAnsiblePlaybookFilePath),
+      base::BindOnce(&AnsibleManagementServiceTest::ExpectTrueResult,
+                     weak_ptr_factory_.GetWeakPtr()));
+  run_loop()->Run();
 }
 
-TEST_F(AnsibleManagementServiceTest, ConfigureDefaultContainerInstallFail) {
+TEST_F(AnsibleManagementServiceTest, ConfigureContainerInstallFail) {
   test_helper_->SetUpAnsibleInstallation(
       vm_tools::cicerone::InstallLinuxPackageResponse::FAILED);
 
-  EXPECT_CALL(configuration_finished_mock_callback_, Run(false)).Times(1);
-
-  ansible_management_service()->ConfigureDefaultContainer(
-      configuration_finished_mock_callback_.Get());
-  base::RunLoop().RunUntilIdle();
+  ansible_management_service()->ConfigureContainer(
+      ContainerId::GetDefault(),
+      profile_->GetPrefs()->GetFilePath(
+          prefs::kCrostiniAnsiblePlaybookFilePath),
+      base::BindOnce(&AnsibleManagementServiceTest::ExpectFalseResult,
+                     weak_ptr_factory_.GetWeakPtr()));
+  run_loop()->Run();
 }
 
-TEST_F(AnsibleManagementServiceTest, ConfigureDefaultContainerApplyFail) {
+TEST_F(AnsibleManagementServiceTest, ConfigureContainerInstallSignalFail) {
+  test_helper_->SetUpAnsibleInstallation(
+      vm_tools::cicerone::InstallLinuxPackageResponse::STARTED);
+  SetInstallAnsibleStatus(false);
+
+  ansible_management_service()->ConfigureContainer(
+      ContainerId::GetDefault(),
+      profile_->GetPrefs()->GetFilePath(
+          prefs::kCrostiniAnsiblePlaybookFilePath),
+      base::BindOnce(&AnsibleManagementServiceTest::ExpectFalseResult,
+                     weak_ptr_factory_.GetWeakPtr()));
+  run_loop()->Run();
+}
+
+TEST_F(AnsibleManagementServiceTest, ConfigureContainerApplyFail) {
   test_helper_->SetUpAnsibleInstallation(
       vm_tools::cicerone::InstallLinuxPackageResponse::STARTED);
   test_helper_->SetUpPlaybookApplication(
       vm_tools::cicerone::ApplyAnsiblePlaybookResponse::FAILED);
 
-  EXPECT_CALL(configuration_finished_mock_callback_, Run(false)).Times(1);
+  ansible_management_service()->ConfigureContainer(
+      ContainerId::GetDefault(),
+      profile_->GetPrefs()->GetFilePath(
+          prefs::kCrostiniAnsiblePlaybookFilePath),
+      base::BindOnce(&AnsibleManagementServiceTest::ExpectFalseResult,
+                     weak_ptr_factory_.GetWeakPtr()));
+  run_loop()->Run();
+}
 
-  ansible_management_service()->ConfigureDefaultContainer(
-      configuration_finished_mock_callback_.Get());
-  base::RunLoop().RunUntilIdle();
+TEST_F(AnsibleManagementServiceTest, ConfigureContainerApplySignalFail) {
+  test_helper_->SetUpAnsibleInstallation(
+      vm_tools::cicerone::InstallLinuxPackageResponse::STARTED);
+  test_helper_->SetUpPlaybookApplication(
+      vm_tools::cicerone::ApplyAnsiblePlaybookResponse::STARTED);
+  SetApplyAnsibleStatus(false);
 
-  test_helper_->SendSucceededInstallSignal();
-  task_environment_.RunUntilIdle();
+  ansible_management_service()->ConfigureContainer(
+      ContainerId::GetDefault(),
+      profile_->GetPrefs()->GetFilePath(
+          prefs::kCrostiniAnsiblePlaybookFilePath),
+      base::BindOnce(&AnsibleManagementServiceTest::ExpectFalseResult,
+                     weak_ptr_factory_.GetWeakPtr()));
+  run_loop()->Run();
 }
 
 TEST_F(AnsibleManagementServiceTest,
@@ -137,14 +221,20 @@
   test_helper_->SetUpPlaybookApplication(
       vm_tools::cicerone::ApplyAnsiblePlaybookResponse::STARTED);
 
-  EXPECT_CALL(configuration_finished_mock_callback_, Run(true)).Times(1);
-  ExecuteSuccessfulConfigurationFlow();
-
-  EXPECT_CALL(configuration_finished_mock_callback_, Run(false)).Times(1);
-
-  ansible_management_service()->ConfigureDefaultContainer(
-      configuration_finished_mock_callback_.Get());
-  base::RunLoop().RunUntilIdle();
+  ansible_management_service()->ConfigureContainer(
+      ContainerId::GetDefault(),
+      profile_->GetPrefs()->GetFilePath(
+          prefs::kCrostiniAnsiblePlaybookFilePath),
+      base::BindOnce(&ExpectResult, base::BindLambdaForTesting([&]() {
+        ansible_management_service()->ConfigureContainer(
+            ContainerId::GetDefault(),
+            profile_->GetPrefs()->GetFilePath(
+                prefs::kCrostiniAnsiblePlaybookFilePath),
+            base::BindOnce(&AnsibleManagementServiceTest::ExpectFalseResult,
+                           weak_ptr_factory_.GetWeakPtr()));
+      }),
+                     true));
+  run_loop()->Run();
 }
 
 TEST_F(AnsibleManagementServiceTest,
@@ -152,22 +242,28 @@
   test_helper_->SetUpAnsibleInstallation(
       vm_tools::cicerone::InstallLinuxPackageResponse::FAILED);
 
-  EXPECT_CALL(configuration_finished_mock_callback_, Run(false)).Times(1);
-
   // Unsuccessful sequence of events.
-  ansible_management_service()->ConfigureDefaultContainer(
-      configuration_finished_mock_callback_.Get());
-  base::RunLoop().RunUntilIdle();
+  ansible_management_service()->ConfigureContainer(
+      ContainerId::GetDefault(),
+      profile_->GetPrefs()->GetFilePath(
+          prefs::kCrostiniAnsiblePlaybookFilePath),
+      base::BindOnce(&ExpectResult, base::BindLambdaForTesting([&]() {
+        // Setup for success.
+        test_helper_->SetUpAnsibleInstallation(
+            vm_tools::cicerone::InstallLinuxPackageResponse::STARTED);
+        test_helper_->SetUpPlaybookApplication(
+            vm_tools::cicerone::ApplyAnsiblePlaybookResponse::STARTED);
+        ansible_management_service()->ConfigureContainer(
+            ContainerId::GetDefault(),
+            profile_->GetPrefs()->GetFilePath(
+                prefs::kCrostiniAnsiblePlaybookFilePath),
+            base::BindOnce(&AnsibleManagementServiceTest::ExpectTrueResult,
+                           weak_ptr_factory_.GetWeakPtr()));
+      }),
+                     false));
   CloseCrostiniAnsibleSoftwareConfigViewForTesting();
 
-  // Setup for success.
-  test_helper_->SetUpAnsibleInstallation(
-      vm_tools::cicerone::InstallLinuxPackageResponse::STARTED);
-  test_helper_->SetUpPlaybookApplication(
-      vm_tools::cicerone::ApplyAnsiblePlaybookResponse::STARTED);
-
-  EXPECT_CALL(configuration_finished_mock_callback_, Run(true)).Times(1);
-  ExecuteSuccessfulConfigurationFlow();
+  run_loop()->Run();
 }
 
 }  // namespace crostini
diff --git a/chrome/browser/ash/crostini/ansible/ansible_management_test_helper.cc b/chrome/browser/ash/crostini/ansible/ansible_management_test_helper.cc
index ccbf573..7628e8a0 100644
--- a/chrome/browser/ash/crostini/ansible/ansible_management_test_helper.cc
+++ b/chrome/browser/ash/crostini/ansible/ansible_management_test_helper.cc
@@ -71,4 +71,27 @@
   fake_cicerone_client_->NotifyApplyAnsiblePlaybookProgress(signal);
 }
 
+void AnsibleManagementTestHelper::SendFailedInstallSignal() {
+  vm_tools::cicerone::InstallLinuxPackageProgressSignal signal;
+  signal.set_owner_id(CryptohomeIdForProfile(profile_));
+  signal.set_vm_name(kCrostiniDefaultVmName);
+  signal.set_container_name(kCrostiniDefaultContainerName);
+  signal.set_status(
+      vm_tools::cicerone::InstallLinuxPackageProgressSignal::FAILED);
+  signal.set_failure_details("banana");
+
+  fake_cicerone_client_->InstallLinuxPackageProgress(signal);
+}
+
+void AnsibleManagementTestHelper::SendFailedApplySignal() {
+  vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal signal;
+  signal.set_owner_id(CryptohomeIdForProfile(profile_));
+  signal.set_vm_name(kCrostiniDefaultVmName);
+  signal.set_container_name(kCrostiniDefaultContainerName);
+  signal.set_status(
+      vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::FAILED);
+  signal.set_failure_details("apple");
+
+  fake_cicerone_client_->NotifyApplyAnsiblePlaybookProgress(signal);
+}
 }  // namespace crostini
diff --git a/chrome/browser/ash/crostini/ansible/ansible_management_test_helper.h b/chrome/browser/ash/crostini/ansible/ansible_management_test_helper.h
index 72fdefa..2d6b830 100644
--- a/chrome/browser/ash/crostini/ansible/ansible_management_test_helper.h
+++ b/chrome/browser/ash/crostini/ansible/ansible_management_test_helper.h
@@ -6,8 +6,10 @@
 #define CHROME_BROWSER_ASH_CROSTINI_ANSIBLE_ANSIBLE_MANAGEMENT_TEST_HELPER_H_
 
 #include "base/test/scoped_feature_list.h"
+#include "chrome/browser/ash/crostini/ansible/ansible_management_service.h"
 #include "chromeos/dbus/cicerone/cicerone_service.pb.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Profile;
 
@@ -29,6 +31,8 @@
       vm_tools::cicerone::ApplyAnsiblePlaybookResponse::Status status);
   void SendSucceededInstallSignal();
   void SendSucceededApplySignal();
+  void SendFailedInstallSignal();
+  void SendFailedApplySignal();
 
  private:
   Profile* profile_;
diff --git a/chrome/browser/ash/crostini/crostini_disk.cc b/chrome/browser/ash/crostini/crostini_disk.cc
index 3c7e56c..541882f 100644
--- a/chrome/browser/ash/crostini/crostini_disk.cc
+++ b/chrome/browser/ash/crostini/crostini_disk.cc
@@ -17,8 +17,8 @@
 #include "chrome/browser/ash/crostini/crostini_manager.h"
 #include "chrome/browser/ash/crostini/crostini_simple_types.h"
 #include "chrome/browser/ash/crostini/crostini_types.mojom.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "ui/base/text/bytes_formatting.h"
 
 using DiskImageStatus = vm_tools::concierge::DiskImageStatus;
diff --git a/chrome/browser/ash/crostini/crostini_disk.h b/chrome/browser/ash/crostini/crostini_disk.h
index eb78e48..77c7064 100644
--- a/chrome/browser/ash/crostini/crostini_disk.h
+++ b/chrome/browser/ash/crostini/crostini_disk.h
@@ -12,7 +12,7 @@
 #include "chrome/browser/ash/crostini/crostini_simple_types.h"
 #include "chrome/browser/ash/crostini/crostini_types.mojom-forward.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace crostini {
diff --git a/chrome/browser/ash/crostini/crostini_disk_unittest.cc b/chrome/browser/ash/crostini/crostini_disk_unittest.cc
index 3dafa69..5dba2b3 100644
--- a/chrome/browser/ash/crostini/crostini_disk_unittest.cc
+++ b/chrome/browser/ash/crostini/crostini_disk_unittest.cc
@@ -13,11 +13,11 @@
 #include "chrome/browser/ash/crostini/crostini_types.mojom.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock-matchers.h"
diff --git a/chrome/browser/ash/crostini/crostini_export_import_unittest.cc b/chrome/browser/ash/crostini/crostini_export_import_unittest.cc
index daecdcd..9816ed1 100644
--- a/chrome/browser/ash/crostini/crostini_export_import_unittest.cc
+++ b/chrome/browser/ash/crostini/crostini_export_import_unittest.cc
@@ -15,12 +15,12 @@
 #include "chrome/browser/notifications/notification_display_service_factory.h"
 #include "chrome/browser/notifications/notification_display_service_tester.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/fake_seneschal_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_service.pb.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/crostini/crostini_installer.cc b/chrome/browser/ash/crostini/crostini_installer.cc
index f807377..29939bb 100644
--- a/chrome/browser/ash/crostini/crostini_installer.cc
+++ b/chrome/browser/ash/crostini/crostini_installer.cc
@@ -400,12 +400,20 @@
   }
 }
 
-void CrostiniInstaller::OnAnsibleSoftwareConfigurationStarted() {
+// TODO(justinhuang): Address the case where Default Container is being booted +
+// getting configured and a new VM is being created. Since Enterprise-based
+// configurations currently work as configure on every startup, we'll have a
+// potential overlap which will cause this to signal too many times.
+void CrostiniInstaller::OnAnsibleSoftwareConfigurationStarted(
+    const ContainerId& container_id) {
   DCHECK_EQ(installing_state_, InstallerState::kStartContainer);
   UpdateInstallingState(InstallerState::kConfigureContainer);
 }
 
-void CrostiniInstaller::OnAnsibleSoftwareConfigurationFinished(bool success) {
+// TODO(justinhuang): Similar to the above.
+void CrostiniInstaller::OnAnsibleSoftwareConfigurationFinished(
+    const ContainerId& container_id,
+    bool success) {
   DCHECK_EQ(installing_state_, InstallerState::kConfigureContainer);
   DCHECK(ansible_management_service_observation_.IsObservingSource(
       AnsibleManagementService::GetForProfile(profile_)));
diff --git a/chrome/browser/ash/crostini/crostini_installer.h b/chrome/browser/ash/crostini/crostini_installer.h
index d5938cb..b26b4ab 100644
--- a/chrome/browser/ash/crostini/crostini_installer.h
+++ b/chrome/browser/ash/crostini/crostini_installer.h
@@ -108,8 +108,10 @@
   void OnContainerStarted(crostini::CrostiniResult result) override;
 
   // AnsibleManagementService::Observer:
-  void OnAnsibleSoftwareConfigurationStarted() override;
-  void OnAnsibleSoftwareConfigurationFinished(bool success) override;
+  void OnAnsibleSoftwareConfigurationStarted(
+      const ContainerId& container_id) override;
+  void OnAnsibleSoftwareConfigurationFinished(const ContainerId& container_id,
+                                              bool success) override;
 
   // Return true if internal state allows starting installation.
   bool CanInstall();
diff --git a/chrome/browser/ash/crostini/crostini_installer_unittest.cc b/chrome/browser/ash/crostini/crostini_installer_unittest.cc
index 699e806..c302672 100644
--- a/chrome/browser/ash/crostini/crostini_installer_unittest.cc
+++ b/chrome/browser/ash/crostini/crostini_installer_unittest.cc
@@ -23,12 +23,12 @@
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/dlcservice/dlcservice_client.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/crostini/crostini_low_disk_notification_unittest.cc b/chrome/browser/ash/crostini/crostini_low_disk_notification_unittest.cc
index c249bfb3..866e2cb1 100644
--- a/chrome/browser/ash/crostini/crostini_low_disk_notification_unittest.cc
+++ b/chrome/browser/ash/crostini/crostini_low_disk_notification_unittest.cc
@@ -19,9 +19,9 @@
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/user_manager/fake_user_manager.h"
 #include "components/user_manager/scoped_user_manager.h"
diff --git a/chrome/browser/ash/crostini/crostini_manager.cc b/chrome/browser/ash/crostini/crostini_manager.cc
index 887f56c7..1c9564c 100644
--- a/chrome/browser/ash/crostini/crostini_manager.cc
+++ b/chrome/browser/ash/crostini/crostini_manager.cc
@@ -60,7 +60,7 @@
 #include "chrome/browser/ui/views/crostini/crostini_expired_container_warning_view.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
 #include "chromeos/dbus/image_loader/image_loader_client.h"
@@ -2578,10 +2578,12 @@
   // pre-determined configuration to the default container.
   if (container_id == ContainerId::GetDefault() &&
       ShouldConfigureDefaultContainer(profile_)) {
-    AnsibleManagementService::GetForProfile(profile_)
-        ->ConfigureDefaultContainer(
-            base::BindOnce(&CrostiniManager::OnDefaultContainerConfigured,
-                           weak_ptr_factory_.GetWeakPtr()));
+    AnsibleManagementService::GetForProfile(profile_)->ConfigureContainer(
+        ContainerId::GetDefault(),
+        profile_->GetPrefs()->GetFilePath(
+            prefs::kCrostiniAnsiblePlaybookFilePath),
+        base::BindOnce(&CrostiniManager::OnDefaultContainerConfigured,
+                       weak_ptr_factory_.GetWeakPtr()));
     return;
   }
 
@@ -2736,8 +2738,7 @@
 
   // TODO(okalitova): Add an observer.
   AnsibleManagementService::GetForProfile(profile_)
-      ->OnApplyAnsiblePlaybookProgress(signal.status(),
-                                       signal.failure_details());
+      ->OnApplyAnsiblePlaybookProgress(signal);
 }
 
 void CrostiniManager::OnUpgradeContainerProgress(
diff --git a/chrome/browser/ash/crostini/crostini_manager.h b/chrome/browser/ash/crostini/crostini_manager.h
index aefe8a3..b7195be 100644
--- a/chrome/browser/ash/crostini/crostini_manager.h
+++ b/chrome/browser/ash/crostini/crostini_manager.h
@@ -25,12 +25,12 @@
 #include "chrome/browser/ash/vm_starting_observer.h"
 #include "chrome/browser/component_updater/cros_component_installer_chromeos.h"
 #include "chrome/browser/ui/browser.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "chromeos/dbus/anomaly_detector/anomaly_detector.pb.h"
 #include "chromeos/dbus/anomaly_detector/anomaly_detector_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
 #include "chromeos/dbus/cicerone/cicerone_service.pb.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
diff --git a/chrome/browser/ash/crostini/crostini_manager_unittest.cc b/chrome/browser/ash/crostini/crostini_manager_unittest.cc
index 2a3d0aec..dd7e614c 100644
--- a/chrome/browser/ash/crostini/crostini_manager_unittest.cc
+++ b/chrome/browser/ash/crostini/crostini_manager_unittest.cc
@@ -37,14 +37,14 @@
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/anomaly_detector/fake_anomaly_detector_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
 #include "chromeos/dbus/cicerone/cicerone_service.pb.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/dlcservice/dlcservice_client.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
@@ -2155,15 +2155,21 @@
   run_loop()->Run();
 }
 
-class CrostiniManagerAnsibleInfraTest : public CrostiniManagerTest {
+class CrostiniManagerAnsibleInfraTest
+    : public CrostiniManagerTest,
+      public AnsibleManagementService::Observer {
  public:
   void SetUp() override {
     CrostiniManagerTest::SetUp();
     ansible_management_test_helper_ =
         std::make_unique<AnsibleManagementTestHelper>(profile_.get());
     ansible_management_test_helper_->SetUpAnsibleInfra();
-
     SetUpViewsEnvironmentForTesting();
+    AnsibleManagementService::GetForProfile(profile_.get())->AddObserver(this);
+
+    // Set sensible default values.
+    is_install_ansible_success_ = true;
+    is_apply_ansible_success_ = true;
   }
 
   void TearDown() override {
@@ -2174,11 +2180,43 @@
     TearDownViewsEnvironmentForTesting();
 
     ansible_management_test_helper_.reset();
+    AnsibleManagementService::GetForProfile(profile_.get())
+        ->RemoveObserver(this);
     CrostiniManagerTest::TearDown();
   }
 
+  // AnsibleManagementService::Observer
+  void OnAnsibleSoftwareConfigurationStarted(
+      const ContainerId& container_id) override {}
+  void OnAnsibleSoftwareConfigurationFinished(const ContainerId& container_id,
+                                              bool success) override {}
+  void OnAnsibleSoftwareInstall(const ContainerId& container_id) override {
+    if (is_install_ansible_success_) {
+      ansible_management_test_helper_->SendSucceededInstallSignal();
+    } else {
+      ansible_management_test_helper_->SendFailedInstallSignal();
+    }
+  }
+  void OnApplyAnsiblePlaybook(const ContainerId& container_id) override {
+    if (is_apply_ansible_success_) {
+      ansible_management_test_helper_->SendSucceededApplySignal();
+    } else {
+      ansible_management_test_helper_->SendFailedApplySignal();
+    }
+  }
+
  protected:
+  void SetInstallAnsibleStatus(bool status) {
+    is_install_ansible_success_ = status;
+  }
+  void SetApplyAnsibleStatus(bool status) {
+    is_apply_ansible_success_ = status;
+  }
+
   std::unique_ptr<AnsibleManagementTestHelper> ansible_management_test_helper_;
+
+  bool is_install_ansible_success_;
+  bool is_apply_ansible_success_;
 };
 
 TEST_F(CrostiniManagerAnsibleInfraTest, StartContainerAnsibleInstallFailure) {
@@ -2193,6 +2231,19 @@
   run_loop()->Run();
 }
 
+TEST_F(CrostiniManagerAnsibleInfraTest, StartContainerInstallSignalFailure) {
+  ansible_management_test_helper_->SetUpAnsibleInstallation(
+      vm_tools::cicerone::InstallLinuxPackageResponse::STARTED);
+  SetInstallAnsibleStatus(false);
+
+  crostini_manager()->StartLxdContainer(
+      ContainerId::GetDefault(),
+      base::BindOnce(&ExpectCrostiniResult, run_loop()->QuitClosure(),
+                     CrostiniResult::CONTAINER_CONFIGURATION_FAILED));
+
+  run_loop()->Run();
+}
+
 TEST_F(CrostiniManagerAnsibleInfraTest, StartContainerApplyFailure) {
   ansible_management_test_helper_->SetUpAnsibleInstallation(
       vm_tools::cicerone::InstallLinuxPackageResponse::STARTED);
@@ -2204,9 +2255,21 @@
       base::BindOnce(&ExpectCrostiniResult, run_loop()->QuitClosure(),
                      CrostiniResult::CONTAINER_CONFIGURATION_FAILED));
 
-  base::RunLoop().RunUntilIdle();
+  run_loop()->Run();
+}
 
-  ansible_management_test_helper_->SendSucceededInstallSignal();
+TEST_F(CrostiniManagerAnsibleInfraTest, StartContainerApplySignalFailure) {
+  ansible_management_test_helper_->SetUpAnsibleInstallation(
+      vm_tools::cicerone::InstallLinuxPackageResponse::STARTED);
+  ansible_management_test_helper_->SetUpPlaybookApplication(
+      vm_tools::cicerone::ApplyAnsiblePlaybookResponse::STARTED);
+
+  SetApplyAnsibleStatus(false);
+
+  crostini_manager()->StartLxdContainer(
+      ContainerId::GetDefault(),
+      base::BindOnce(&ExpectCrostiniResult, run_loop()->QuitClosure(),
+                     CrostiniResult::CONTAINER_CONFIGURATION_FAILED));
 
   run_loop()->Run();
 }
@@ -2221,13 +2284,6 @@
       ContainerId::GetDefault(),
       base::BindOnce(&ExpectCrostiniResult, run_loop()->QuitClosure(),
                      CrostiniResult::SUCCESS));
-  base::RunLoop().RunUntilIdle();
-
-  ansible_management_test_helper_->SendSucceededInstallSignal();
-  base::RunLoop().RunUntilIdle();
-
-  ansible_management_test_helper_->SendSucceededApplySignal();
-
   run_loop()->Run();
 }
 
diff --git a/chrome/browser/ash/crostini/crostini_package_notification_unittest.cc b/chrome/browser/ash/crostini/crostini_package_notification_unittest.cc
index 2049d13..b68544a 100644
--- a/chrome/browser/ash/crostini/crostini_package_notification_unittest.cc
+++ b/chrome/browser/ash/crostini/crostini_package_notification_unittest.cc
@@ -11,9 +11,9 @@
 #include "chrome/browser/ash/crostini/crostini_test_helper.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/ash/crostini/crostini_package_service_unittest.cc b/chrome/browser/ash/crostini/crostini_package_service_unittest.cc
index d6e00a3f..5821169 100644
--- a/chrome/browser/ash/crostini/crostini_package_service_unittest.cc
+++ b/chrome/browser/ash/crostini/crostini_package_service_unittest.cc
@@ -21,12 +21,12 @@
 #include "chrome/browser/notifications/notification_display_service_tester.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/fake_seneschal_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/cros_disks/cros_disks_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/vm_applications/apps.pb.h"
diff --git a/chrome/browser/ash/crostini/crostini_port_forwarder_unittest.cc b/chrome/browser/ash/crostini/crostini_port_forwarder_unittest.cc
index 5f053496..8bc80f7 100644
--- a/chrome/browser/ash/crostini/crostini_port_forwarder_unittest.cc
+++ b/chrome/browser/ash/crostini/crostini_port_forwarder_unittest.cc
@@ -9,9 +9,9 @@
 #include "chrome/browser/ash/crostini/crostini_manager.h"
 #include "chrome/browser/ash/crostini/crostini_test_helper.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/permission_broker/fake_permission_broker_client.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/crostini/crostini_simple_types.h b/chrome/browser/ash/crostini/crostini_simple_types.h
index 778887d1..d086a46 100644
--- a/chrome/browser/ash/crostini/crostini_simple_types.h
+++ b/chrome/browser/ash/crostini/crostini_simple_types.h
@@ -9,8 +9,8 @@
 
 #include "base/callback.h"
 #include "base/files/file_path.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "chromeos/dbus/cicerone/cicerone_service.pb.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
 
 // This file contains simple C++ types. Simple isn't a precise term, but as a
 // guideline enums and PoD structs are simple while structs/classes with methods
diff --git a/chrome/browser/ash/crostini/crostini_sshfs_unittest.cc b/chrome/browser/ash/crostini/crostini_sshfs_unittest.cc
index 72b9cb5..945ce84a 100644
--- a/chrome/browser/ash/crostini/crostini_sshfs_unittest.cc
+++ b/chrome/browser/ash/crostini/crostini_sshfs_unittest.cc
@@ -26,10 +26,10 @@
 #include "chrome/browser/ash/file_manager/volume_manager.h"
 #include "chrome/browser/ash/file_manager/volume_manager_factory.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/cros_disks/cros_disks_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/vm_applications/apps.pb.h"
diff --git a/chrome/browser/ash/crostini/crostini_upgrade_available_notification_unittest.cc b/chrome/browser/ash/crostini/crostini_upgrade_available_notification_unittest.cc
index 5471cf0..6b0aefa 100644
--- a/chrome/browser/ash/crostini/crostini_upgrade_available_notification_unittest.cc
+++ b/chrome/browser/ash/crostini/crostini_upgrade_available_notification_unittest.cc
@@ -22,10 +22,10 @@
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
 #include "chromeos/dbus/cicerone/cicerone_service.pb.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/crostini/crostini_util_unittest.cc b/chrome/browser/ash/crostini/crostini_util_unittest.cc
index 60f7902e..81012c5 100644
--- a/chrome/browser/ash/crostini/crostini_util_unittest.cc
+++ b/chrome/browser/ash/crostini/crostini_util_unittest.cc
@@ -15,10 +15,10 @@
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/dlcservice/dlcservice_client.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/dbus/ash_dbus_helper.cc b/chrome/browser/ash/dbus/ash_dbus_helper.cc
index 7ec5313..8d67de8 100644
--- a/chrome/browser/ash/dbus/ash_dbus_helper.cc
+++ b/chrome/browser/ash/dbus/ash_dbus_helper.cc
@@ -16,6 +16,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chromeos/ash/components/dbus/authpolicy/authpolicy_client.h"
 #include "chromeos/ash/components/dbus/biod/biod_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/cros_healthd/cros_healthd_client.h"
 #include "chromeos/ash/components/dbus/cups_proxy/cups_proxy_client.h"
 #include "chromeos/ash/components/dbus/fusebox/fusebox_reverse_client.h"
@@ -41,7 +42,6 @@
 #include "chromeos/dbus/audio/cras_audio_client.h"
 #include "chromeos/dbus/cdm_factory_daemon/cdm_factory_daemon_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/constants/dbus_paths.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/dlcservice/dlcservice_client.h"
diff --git a/chrome/browser/ash/eol_notification_unittest.cc b/chrome/browser/ash/eol_notification_unittest.cc
index 6417308..0a03afb 100644
--- a/chrome/browser/ash/eol_notification_unittest.cc
+++ b/chrome/browser/ash/eol_notification_unittest.cc
@@ -16,7 +16,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/update_engine/fake_update_engine_client.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ash/exo/chrome_data_exchange_delegate_unittest.cc b/chrome/browser/ash/exo/chrome_data_exchange_delegate_unittest.cc
index 7366d450..04b26de 100644
--- a/chrome/browser/ash/exo/chrome_data_exchange_delegate_unittest.cc
+++ b/chrome/browser/ash/exo/chrome_data_exchange_delegate_unittest.cc
@@ -24,10 +24,10 @@
 #include "chrome/browser/ash/guest_os/guest_os_share_path.h"
 #include "chrome/browser/ash/plugin_vm/plugin_vm_util.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/fake_seneschal_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/exo/shell_surface_util.h"
 #include "content/public/common/drop_data.h"
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
index cc2b538..6e7367f0 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -100,7 +100,7 @@
 #include "chrome/common/extensions/api/file_manager_private.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/test_switches.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "chromeos/dbus/constants/dbus_switches.h"
 #include "chromeos/dbus/cros_disks/fake_cros_disks_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
diff --git a/chrome/browser/ash/file_manager/file_tasks_unittest.cc b/chrome/browser/ash/file_manager/file_tasks_unittest.cc
index a11cf2a..4fcd823 100644
--- a/chrome/browser/ash/file_manager/file_tasks_unittest.cc
+++ b/chrome/browser/ash/file_manager/file_tasks_unittest.cc
@@ -30,7 +30,7 @@
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/testing_pref_service.h"
diff --git a/chrome/browser/ash/file_manager/file_watcher_unittest.cc b/chrome/browser/ash/file_manager/file_watcher_unittest.cc
index 7eaddd04..743fa87 100644
--- a/chrome/browser/ash/file_manager/file_watcher_unittest.cc
+++ b/chrome/browser/ash/file_manager/file_watcher_unittest.cc
@@ -15,11 +15,11 @@
 #include "chrome/browser/ash/crostini/crostini_util.h"
 #include "chrome/browser/ash/file_manager/path_util.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
 #include "chromeos/dbus/cicerone/cicerone_service.pb.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "extensions/common/extension.h"
diff --git a/chrome/browser/ash/file_manager/path_util_unittest.cc b/chrome/browser/ash/file_manager/path_util_unittest.cc
index e1b371b1..5050d2a 100644
--- a/chrome/browser/ash/file_manager/path_util_unittest.cc
+++ b/chrome/browser/ash/file_manager/path_util_unittest.cc
@@ -42,9 +42,9 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/cros_disks/cros_disks_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/account_id/account_id.h"
diff --git a/chrome/browser/ash/guest_os/guest_os_registry_service_icon_browsertest.cc b/chrome/browser/ash/guest_os/guest_os_registry_service_icon_browsertest.cc
index b48fa23b..6855985 100644
--- a/chrome/browser/ash/guest_os/guest_os_registry_service_icon_browsertest.cc
+++ b/chrome/browser/ash/guest_os/guest_os_registry_service_icon_browsertest.cc
@@ -15,10 +15,10 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_service.pb.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "content/public/test/browser_test.h"
 
diff --git a/chrome/browser/ash/guest_os/guest_os_share_path.cc b/chrome/browser/ash/guest_os/guest_os_share_path.cc
index c1b664f..ac41ed8 100644
--- a/chrome/browser/ash/guest_os/guest_os_share_path.cc
+++ b/chrome/browser/ash/guest_os/guest_os_share_path.cc
@@ -24,8 +24,8 @@
 #include "chrome/browser/ash/smb_client/smb_service.h"
 #include "chrome/browser/ash/smb_client/smb_service_factory.h"
 #include "chrome/browser/ash/smb_client/smbfs_share.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "content/public/browser/browser_task_traits.h"
diff --git a/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc b/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc
index 5502e43..5313ec2 100644
--- a/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc
+++ b/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc
@@ -33,12 +33,12 @@
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/fake_seneschal_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_service.pb.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/dlcservice/dlcservice_client.h"
 #include "components/account_id/account_id.h"
diff --git a/chrome/browser/ash/guest_os/guest_os_stability_monitor.h b/chrome/browser/ash/guest_os/guest_os_stability_monitor.h
index 97abf8c..2ba8d00 100644
--- a/chrome/browser/ash/guest_os/guest_os_stability_monitor.h
+++ b/chrome/browser/ash/guest_os/guest_os_stability_monitor.h
@@ -7,10 +7,10 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/chunneld/chunneld_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 
 namespace guest_os {
 
diff --git a/chrome/browser/ash/guest_os/guest_os_stability_monitor_unittest.cc b/chrome/browser/ash/guest_os/guest_os_stability_monitor_unittest.cc
index a82e337..e8a9706 100644
--- a/chrome/browser/ash/guest_os/guest_os_stability_monitor_unittest.cc
+++ b/chrome/browser/ash/guest_os/guest_os_stability_monitor_unittest.cc
@@ -14,13 +14,13 @@
 #include "chrome/browser/ash/crostini/crostini_test_helper.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/fake_seneschal_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/chunneld/fake_chunneld_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/input_method/input_method_settings.cc b/chrome/browser/ash/input_method/input_method_settings.cc
index 41192b3..ac1e7a8 100644
--- a/chrome/browser/ash/input_method/input_method_settings.cc
+++ b/chrome/browser/ash/input_method/input_method_settings.cc
@@ -106,6 +106,8 @@
       input_method_specific_pref
               .FindIntKey("physicalKeyboardAutoCorrectionLevel")
               .value_or(0) > 0;
+  // TODO(crbug.com/1263335): This should only look at the prefs and not the
+  // input field context.
   settings->predictive_writing =
       context.multiword_enabled && context.multiword_allowed &&
       !context.lacros_enabled &&
diff --git a/chrome/browser/ash/input_method/native_input_method_engine.cc b/chrome/browser/ash/input_method/native_input_method_engine.cc
index 57561473..91ff6bd9 100644
--- a/chrome/browser/ash/input_method/native_input_method_engine.cc
+++ b/chrome/browser/ash/input_method/native_input_method_engine.cc
@@ -476,8 +476,14 @@
 }
 
 mojom::TextPredictionMode GetTextPredictionMode(
-    const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions) {
-  return enabled_suggestions.multi_word_suggestions
+    const std::string& engine_id,
+    const InputFieldContext& context,
+    const PrefService& prefs) {
+  // TODO(crbug.com/1263335): Enable text prediction for Lacros.
+  return context.multiword_enabled && context.multiword_allowed &&
+                 !context.lacros_enabled &&
+                 prefs.GetBoolean(prefs::kAssistPredictiveWritingEnabled) &&
+                 IsUsEnglishEngine(engine_id)
              ? mojom::TextPredictionMode::kEnabled
              : mojom::TextPredictionMode::kDisabled;
 }
@@ -494,8 +500,10 @@
 }
 
 mojom::InputFieldInfoPtr CreateInputFieldInfo(
+    const std::string& engine_id,
     const ui::IMEEngineHandlerInterface::InputContext& context,
-    const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions,
+    const InputFieldContext& input_field_context,
+    const PrefService& prefs,
     bool is_normal_screen) {
   // Disable most features on the login screen.
   if (!is_normal_screen) {
@@ -508,12 +516,12 @@
         mojom::TextPredictionMode::kDisabled);
   }
 
-  return mojom::InputFieldInfo::New(TextInputTypeToMojoType(context.type),
-                                    AutocorrectFlagsToMojoType(context.flags),
-                                    context.should_do_learning
-                                        ? mojom::PersonalizationMode::kEnabled
-                                        : mojom::PersonalizationMode::kDisabled,
-                                    GetTextPredictionMode(enabled_suggestions));
+  return mojom::InputFieldInfo::New(
+      TextInputTypeToMojoType(context.type),
+      AutocorrectFlagsToMojoType(context.flags),
+      context.should_do_learning ? mojom::PersonalizationMode::kEnabled
+                                 : mojom::PersonalizationMode::kDisabled,
+      GetTextPredictionMode(engine_id, input_field_context, prefs));
 }
 
 void OverrideXkbLayoutIfNeeded(ImeKeyboard* keyboard,
@@ -816,8 +824,8 @@
   const bool is_normal_screen =
       InputMethodManager::Get()->GetActiveIMEState()->GetUIStyle() ==
       InputMethodManager::UIStyle::kNormal;
-  mojom::InputFieldInfoPtr input_field_info =
-      CreateInputFieldInfo(context, enabled_suggestions, is_normal_screen);
+  mojom::InputFieldInfoPtr input_field_info = CreateInputFieldInfo(
+      engine_id, context, input_field_context, *prefs_, is_normal_screen);
 
   base::OnceCallback<void(bool)> on_focus_callback =
       base::BindOnce(&NativeInputMethodEngine::ImeObserver::ActivateTextClient,
diff --git a/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc b/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc
index 6e41c3cb..f9bd496 100644
--- a/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc
+++ b/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc
@@ -34,7 +34,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "extensions/browser/disable_reason.h"
diff --git a/chrome/browser/ash/lock_screen_apps/lock_screen_profile_creator_impl_unittest.cc b/chrome/browser/ash/lock_screen_apps/lock_screen_profile_creator_impl_unittest.cc
index 74d2d83..c6752411 100644
--- a/chrome/browser/ash/lock_screen_apps/lock_screen_profile_creator_impl_unittest.cc
+++ b/chrome/browser/ash/lock_screen_apps/lock_screen_profile_creator_impl_unittest.cc
@@ -33,7 +33,7 @@
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/crx_file/id_util.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc b/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc
index e5d851f..c681932 100644
--- a/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc
+++ b/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc
@@ -40,7 +40,7 @@
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
diff --git a/chrome/browser/ash/login/demo_mode/demo_mode_test_helper.cc b/chrome/browser/ash/login/demo_mode/demo_mode_test_helper.cc
index 73d7949..1a488630 100644
--- a/chrome/browser/ash/login/demo_mode/demo_mode_test_helper.cc
+++ b/chrome/browser/ash/login/demo_mode/demo_mode_test_helper.cc
@@ -17,7 +17,7 @@
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/component_updater/fake_cros_component_manager.h"
 #include "chrome/test/base/testing_browser_process.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 
 namespace ash {
diff --git a/chrome/browser/ash/login/demo_mode/demo_session_unittest.cc b/chrome/browser/ash/login/demo_mode/demo_session_unittest.cc
index aab1c80e..13a9537 100644
--- a/chrome/browser/ash/login/demo_mode/demo_session_unittest.cc
+++ b/chrome/browser/ash/login/demo_mode/demo_session_unittest.cc
@@ -30,7 +30,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/session_manager/core/session_manager.h"
diff --git a/chrome/browser/ash/login/lock/screen_locker_unittest.cc b/chrome/browser/ash/login/lock/screen_locker_unittest.cc
index fbd4e09..b2a245ff 100644
--- a/chrome/browser/ash/login/lock/screen_locker_unittest.cc
+++ b/chrome/browser/ash/login/lock/screen_locker_unittest.cc
@@ -36,8 +36,8 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "chromeos/ash/components/dbus/biod/biod_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/audio/cras_audio_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
 #include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
diff --git a/chrome/browser/ash/login/session/chrome_session_manager.cc b/chrome/browser/ash/login/session/chrome_session_manager.cc
index 328d7cf..61b876635 100644
--- a/chrome/browser/ash/login/session/chrome_session_manager.cc
+++ b/chrome/browser/ash/login/session/chrome_session_manager.cc
@@ -171,6 +171,9 @@
 }
 
 void LaunchShimlessRma() {
+  if (ash::features::IsShimlessRMAFlowEnabled()) {
+    VLOG(1) << "ChromeSessionManager::LaunchShimlessRma";
+  }
   session_manager::SessionManager::Get()->SetSessionState(
       session_manager::SessionState::RMA);
 
@@ -183,6 +186,9 @@
 
 // The callback invoked when RmadClient determines that RMA is required.
 void OnRmaIsRequiredResponse() {
+  if (ash::features::IsShimlessRMAFlowEnabled()) {
+    VLOG(1) << "ChromeSessionManager::OnRmaIsRequiredResponse";
+  }
   switch (session_manager::SessionManager::Get()->session_state()) {
     case session_manager::SessionState::UNKNOWN:
       LOG(ERROR) << "OnRmaIsRequiredResponse callback triggered unexpectedly";
@@ -253,6 +259,10 @@
     // to append the kLaunchRma switch and restart Chrome in RMA mode.
     RmadClient::Get()->SetRmaRequiredCallbackForSessionManager(
         base::BindOnce(&OnRmaIsRequiredResponse));
+  } else {
+    if (ash::features::IsShimlessRMAFlowEnabled()) {
+      VLOG(1) << "ChromeSessionManager::Initialize Shimless RMA is not allowed";
+    }
   }
 
   // Tests should be able to tune login manager before showing it. Thus only
diff --git a/chrome/browser/ash/login/users/user_manager_unittest.cc b/chrome/browser/ash/login/users/user_manager_unittest.cc
index 34cc66a0..60f3bd0 100644
--- a/chrome/browser/ash/login/users/user_manager_unittest.cc
+++ b/chrome/browser/ash/login/users/user_manager_unittest.cc
@@ -26,7 +26,7 @@
 #include "chrome/test/base/fake_profile_manager.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/known_user.h"
diff --git a/chrome/browser/ash/net/network_portal_detector_impl_unittest.cc b/chrome/browser/ash/net/network_portal_detector_impl_unittest.cc
index 083dc801..2148ad10 100644
--- a/chrome/browser/ash/net/network_portal_detector_impl_unittest.cc
+++ b/chrome/browser/ash/net/network_portal_detector_impl_unittest.cc
@@ -24,7 +24,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/shill/shill_device_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
diff --git a/chrome/browser/ash/notifications/gnubby_notification_unittest.cc b/chrome/browser/ash/notifications/gnubby_notification_unittest.cc
index 1f2ef03..f9df079 100644
--- a/chrome/browser/ash/notifications/gnubby_notification_unittest.cc
+++ b/chrome/browser/ash/notifications/gnubby_notification_unittest.cc
@@ -9,7 +9,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_browser_process.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/gnubby/fake_gnubby_client.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_diagnostics.cc b/chrome/browser/ash/plugin_vm/plugin_vm_diagnostics.cc
index cdc71327..e92c006 100644
--- a/chrome/browser/ash/plugin_vm/plugin_vm_diagnostics.cc
+++ b/chrome/browser/ash/plugin_vm/plugin_vm_diagnostics.cc
@@ -21,8 +21,8 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/grit/generated_resources.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "components/prefs/pref_service.h"
 #include "third_party/protobuf/src/google/protobuf/repeated_field.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_files_unittest.cc b/chrome/browser/ash/plugin_vm/plugin_vm_files_unittest.cc
index bba1757..f97ef95 100644
--- a/chrome/browser/ash/plugin_vm/plugin_vm_files_unittest.cc
+++ b/chrome/browser/ash/plugin_vm/plugin_vm_files_unittest.cc
@@ -22,10 +22,10 @@
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
 #include "chrome/browser/ui/ash/shelf/shelf_controller_helper.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/vm_applications/apps.pb.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_installer.h b/chrome/browser/ash/plugin_vm/plugin_vm_installer.h
index 2bb3509..08e3434 100644
--- a/chrome/browser/ash/plugin_vm/plugin_vm_installer.h
+++ b/chrome/browser/ash/plugin_vm/plugin_vm_installer.h
@@ -11,8 +11,8 @@
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/plugin_vm/plugin_vm_license_checker.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "chromeos/dbus/dlcservice/dlcservice_client.h"
 #include "components/download/public/background_service/download_params.h"
 #include "components/keyed_service/core/keyed_service.h"
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_installer_unittest.cc b/chrome/browser/ash/plugin_vm/plugin_vm_installer_unittest.cc
index 22bbd1f7..7a286d5 100644
--- a/chrome/browser/ash/plugin_vm/plugin_vm_installer_unittest.cc
+++ b/chrome/browser/ash/plugin_vm/plugin_vm_installer_unittest.cc
@@ -26,8 +26,8 @@
 #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/dlcservice/fake_dlcservice_client.h"
 #include "components/account_id/account_id.h"
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl.h b/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl.h
index 9b09e9f..21821d8 100644
--- a/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl.h
+++ b/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl.h
@@ -12,7 +12,7 @@
 #include "chrome/browser/ash/plugin_vm/plugin_vm_metrics_util.h"
 #include "chrome/browser/ash/plugin_vm/plugin_vm_uninstaller_notification.h"
 #include "chrome/browser/ash/vm_starting_observer.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "chromeos/dbus/dlcservice/dlcservice_client.h"
 #include "chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher.pb.h"
 #include "chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.h"
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl_unittest.cc b/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl_unittest.cc
index a02a400..7057c5e 100644
--- a/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl_unittest.cc
+++ b/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl_unittest.cc
@@ -23,11 +23,11 @@
 #include "chrome/browser/ui/ash/shelf/shelf_controller_helper.h"
 #include "chrome/browser/ui/ash/shelf/shelf_spinner_controller.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/fake_seneschal_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/dlcservice/fake_dlcservice_client.h"
 #include "chromeos/dbus/vm_plugin_dispatcher/fake_vm_plugin_dispatcher_client.h"
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_test_helper.h b/chrome/browser/ash/plugin_vm/plugin_vm_test_helper.h
index 1bd947e7..330d02f 100644
--- a/chrome/browser/ash/plugin_vm/plugin_vm_test_helper.h
+++ b/chrome/browser/ash/plugin_vm/plugin_vm_test_helper.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_ASH_PLUGIN_VM_PLUGIN_VM_TEST_HELPER_H_
 
 #include "base/test/scoped_feature_list.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 
 class TestingProfile;
 
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_util_unittest.cc b/chrome/browser/ash/plugin_vm/plugin_vm_util_unittest.cc
index fcb56f8..f481f7cc 100644
--- a/chrome/browser/ash/plugin_vm/plugin_vm_util_unittest.cc
+++ b/chrome/browser/ash/plugin_vm/plugin_vm_util_unittest.cc
@@ -11,7 +11,7 @@
 #include "chrome/browser/ash/settings/cros_settings.h"
 #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
diff --git a/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash_unittest.cc b/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash_unittest.cc
index 6889157..6595a36 100644
--- a/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash_unittest.cc
+++ b/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash_unittest.cc
@@ -37,7 +37,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/enterprise/browser/reporting/common_pref_names.h"
 #include "components/enterprise/browser/reporting/report_scheduler.h"
diff --git a/chrome/browser/ash/policy/core/user_cloud_policy_token_forwarder_unittest.cc b/chrome/browser/ash/policy/core/user_cloud_policy_token_forwarder_unittest.cc
index d8dad14..e8e2283 100644
--- a/chrome/browser/ash/policy/core/user_cloud_policy_token_forwarder_unittest.cc
+++ b/chrome/browser/ash/policy/core/user_cloud_policy_token_forwarder_unittest.cc
@@ -24,7 +24,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/account_id/account_id.h"
 #include "components/policy/core/common/cloud/mock_cloud_external_data_manager.h"
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller_unittest.cc b/chrome/browser/ash/policy/dlp/dlp_files_controller_unittest.cc
index 26ef154..47f0f39 100644
--- a/chrome/browser/ash/policy/dlp/dlp_files_controller_unittest.cc
+++ b/chrome/browser/ash/policy/dlp/dlp_files_controller_unittest.cc
@@ -27,9 +27,9 @@
 #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h"
 #include "chrome/browser/chromeos/policy/dlp/mock_dlp_rules_manager.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/dlp/dlp_client.h"
 #include "chromeos/dbus/dlp/dlp_service.pb.h"
diff --git a/chrome/browser/ash/policy/handlers/lock_to_single_user_manager.h b/chrome/browser/ash/policy/handlers/lock_to_single_user_manager.h
index 4582f0d..65cc244a 100644
--- a/chrome/browser/ash/policy/handlers/lock_to_single_user_manager.h
+++ b/chrome/browser/ash/policy/handlers/lock_to_single_user_manager.h
@@ -9,7 +9,7 @@
 #include "base/scoped_observation.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chrome/browser/ash/vm_starting_observer.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/cryptohome/UserDataAuth.pb.h"
 #include "components/user_manager/user_manager.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc b/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc
index 146d07a..8db22d0 100644
--- a/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc
+++ b/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc
@@ -22,10 +22,10 @@
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_test.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "components/account_id/account_id.h"
diff --git a/chrome/browser/ash/policy/status_collector/child_status_collector_browsertest.cc b/chrome/browser/ash/policy/status_collector/child_status_collector_browsertest.cc
index 0a7b14a4..5e1d334 100644
--- a/chrome/browser/ash/policy/status_collector/child_status_collector_browsertest.cc
+++ b/chrome/browser/ash/policy/status_collector/child_status_collector_browsertest.cc
@@ -43,9 +43,9 @@
 #include "chrome/test/base/chrome_unit_test_suite.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
diff --git a/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc b/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc
index dbef6cee..52aea1a7 100644
--- a/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc
+++ b/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc
@@ -65,10 +65,10 @@
 #include "chrome/test/base/chrome_unit_test_suite.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/attestation/attestation_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/cros_disks/cros_disks_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
diff --git a/chrome/browser/ash/policy/status_collector/legacy_device_status_collector_browsertest.cc b/chrome/browser/ash/policy/status_collector/legacy_device_status_collector_browsertest.cc
index aa13f6d5..f0e4f5b 100644
--- a/chrome/browser/ash/policy/status_collector/legacy_device_status_collector_browsertest.cc
+++ b/chrome/browser/ash/policy/status_collector/legacy_device_status_collector_browsertest.cc
@@ -62,10 +62,10 @@
 #include "chrome/test/base/chrome_unit_test_suite.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/attestation/attestation_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/cros_disks/cros_disks_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
diff --git a/chrome/browser/ash/scanning/OWNERS b/chrome/browser/ash/scanning/OWNERS
index 87fd955..6c37016 100644
--- a/chrome/browser/ash/scanning/OWNERS
+++ b/chrome/browser/ash/scanning/OWNERS
@@ -1,4 +1,4 @@
-file://chromeos/scanning/OWNERS
+file://chromeos/ash/components/scanning/OWNERS
 
 per-file *_type_converter*.*=set noparent
 per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
diff --git a/chrome/browser/ash/scanning/lorgnette_scanner_manager.cc b/chrome/browser/ash/scanning/lorgnette_scanner_manager.cc
index eb6299d..446c34c 100644
--- a/chrome/browser/ash/scanning/lorgnette_scanner_manager.cc
+++ b/chrome/browser/ash/scanning/lorgnette_scanner_manager.cc
@@ -20,10 +20,10 @@
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/ash/scanning/lorgnette_scanner_manager_util.h"
 #include "chrome/browser/ash/scanning/zeroconf_scanner_detector.h"
+#include "chromeos/ash/components/scanning/scanner.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/lorgnette/lorgnette_service.pb.h"
 #include "chromeos/dbus/lorgnette_manager/lorgnette_manager_client.h"
-#include "chromeos/scanning/scanner.h"
 #include "components/device_event_log/device_event_log.h"
 #include "net/base/ip_address.h"
 #include "third_party/re2/src/re2/re2.h"
@@ -82,9 +82,9 @@
 // A prioritized list of scan protocols. Protocols that appear earlier in the
 // list are preferred over those that appear later in the list when
 // communicating with a connected scanner.
-constexpr std::array<chromeos::ScanProtocol, 4> kPrioritizedProtocols = {
-    chromeos::ScanProtocol::kEscls, chromeos::ScanProtocol::kEscl,
-    chromeos::ScanProtocol::kLegacyNetwork, chromeos::ScanProtocol::kLegacyUsb};
+constexpr std::array<ScanProtocol, 4> kPrioritizedProtocols = {
+    ScanProtocol::kEscls, ScanProtocol::kEscl, ScanProtocol::kLegacyNetwork,
+    ScanProtocol::kLegacyUsb};
 
 // Returns a pointer to LorgnetteManagerClient, which is used to detect and
 // interact with scanners via the lorgnette D-Bus service.
@@ -172,7 +172,7 @@
       const std::string& scanner_name,
       GetScannerCapabilitiesCallback callback) override {
     std::string device_name;
-    chromeos::ScanProtocol protocol;
+    ScanProtocol protocol;
     if (!GetUsableDeviceNameAndProtocol(scanner_name, device_name, protocol)) {
       std::move(callback).Run(absl::nullopt);
       return;
@@ -194,7 +194,7 @@
     }
 
     std::string device_name;
-    chromeos::ScanProtocol protocol;
+    ScanProtocol protocol;
     if (!GetUsableDeviceNameAndProtocol(scanner_name, device_name, protocol)) {
       LOG(ERROR) << "Failed to get device name for " << scanner_name;
       return false;
@@ -217,7 +217,7 @@
             PageCallback page_callback,
             CompletionCallback completion_callback) override {
     std::string device_name;
-    chromeos::ScanProtocol protocol;  // Unused.
+    ScanProtocol protocol;  // Unused.
     if (!GetUsableDeviceNameAndProtocol(scanner_name, device_name, protocol)) {
       std::move(completion_callback).Run(lorgnette::SCAN_FAILURE_MODE_UNKNOWN);
       return;
@@ -235,7 +235,7 @@
 
  private:
   // Called when scanners are detected by a ScannerDetector.
-  void OnScannersDetected(std::vector<chromeos::Scanner> scanners) {
+  void OnScannersDetected(std::vector<Scanner> scanners) {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
     zeroconf_scanners_ = scanners;
   }
@@ -314,7 +314,7 @@
       GetScannerCapabilitiesCallback callback,
       const std::string& scanner_name,
       const std::string& device_name,
-      const chromeos::ScanProtocol protocol,
+      const ScanProtocol protocol,
       absl::optional<lorgnette::ScannerCapabilities> capabilities) {
     if (!capabilities) {
       LOG(WARNING) << "Failed to get scanner capabilities using device name: "
@@ -346,7 +346,7 @@
         GetKnownIpAddresses();
     for (const auto& lorgnette_scanner : response->scanners()) {
       std::string ip_address_str;
-      chromeos::ScanProtocol protocol = chromeos::ScanProtocol::kUnknown;
+      ScanProtocol protocol = ScanProtocol::kUnknown;
       ParseScannerName(lorgnette_scanner.name(), ip_address_str, protocol);
       if (!ip_address_str.empty()) {
         net::IPAddress ip_address;
@@ -362,13 +362,12 @@
         }
       }
 
-      const bool is_usb_scanner =
-          protocol == chromeos::ScanProtocol::kLegacyUsb;
+      const bool is_usb_scanner = protocol == ScanProtocol::kLegacyUsb;
       const std::string base_name =
           CreateBaseName(lorgnette_scanner, is_usb_scanner);
       const std::string display_name = CreateUniqueDisplayName(base_name);
 
-      chromeos::Scanner scanner;
+      Scanner scanner;
       scanner.display_name = display_name;
       scanner.device_names[protocol].emplace(lorgnette_scanner.name());
       deduped_scanners_[display_name] = scanner;
@@ -427,7 +426,7 @@
   // success, false on failure.
   bool GetUsableDeviceNameAndProtocol(const std::string& scanner_name,
                                       std::string& device_name_out,
-                                      chromeos::ScanProtocol& protocol_out) {
+                                      ScanProtocol& protocol_out) {
     const auto scanner_it = deduped_scanners_.find(scanner_name);
     if (scanner_it == deduped_scanners_.end()) {
       LOG(ERROR) << "Failed to find scanner with name " << scanner_name;
@@ -440,7 +439,7 @@
       if (device_names_it == scanner_it->second.device_names.end())
         continue;
 
-      for (const chromeos::ScannerDeviceName& name : device_names_it->second) {
+      for (const ScannerDeviceName& name : device_names_it->second) {
         if (name.usable) {
           device_name_out = name.device_name;
           protocol_out = protocol;
@@ -457,7 +456,7 @@
   // calls to GetUsableDeviceNameAndProtocol().
   void MarkDeviceNameUnusable(const std::string& scanner_name,
                               const std::string& device_name,
-                              const chromeos::ScanProtocol protocol) {
+                              const ScanProtocol protocol) {
     auto scanner_it = deduped_scanners_.find(scanner_name);
     if (scanner_it == deduped_scanners_.end())
       return;
@@ -466,7 +465,7 @@
     if (device_names_it == scanner_it->second.device_names.end())
       return;
 
-    for (chromeos::ScannerDeviceName& name : device_names_it->second) {
+    for (ScannerDeviceName& name : device_names_it->second) {
       if (name.device_name == device_name) {
         name.usable = false;
         return;
@@ -479,12 +478,12 @@
 
   // The deduplicated zeroconf scanners reported by the
   // zeroconf_scanner_detector_.
-  std::vector<chromeos::Scanner> zeroconf_scanners_;
+  std::vector<Scanner> zeroconf_scanners_;
 
   // Stores the deduplicated scanners from all sources in a map of display name
   // to Scanner. Clients are given display names and can use them to
   // interact with the corresponding scanners.
-  base::flat_map<std::string, chromeos::Scanner> deduped_scanners_;
+  base::flat_map<std::string, Scanner> deduped_scanners_;
 
   // Stores a list of scanner display names to check while filtering.
   std::vector<std::string> scanners_to_filter_;
diff --git a/chrome/browser/ash/scanning/lorgnette_scanner_manager_unittest.cc b/chrome/browser/ash/scanning/lorgnette_scanner_manager_unittest.cc
index d724d9c8..af275c53 100644
--- a/chrome/browser/ash/scanning/lorgnette_scanner_manager_unittest.cc
+++ b/chrome/browser/ash/scanning/lorgnette_scanner_manager_unittest.cc
@@ -19,10 +19,10 @@
 #include "chrome/browser/ash/scanning/zeroconf_scanner_detector.h"
 #include "chrome/browser/ash/scanning/zeroconf_scanner_detector_utils.h"
 #include "chrome/browser/local_discovery/service_discovery_client.h"
+#include "chromeos/ash/components/scanning/scanner.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/lorgnette/lorgnette_service.pb.h"
 #include "chromeos/dbus/lorgnette_manager/fake_lorgnette_manager_client.h"
-#include "chromeos/scanning/scanner.h"
 #include "net/base/ip_address.h"
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -33,7 +33,6 @@
 namespace {
 
 using ::chromeos::FakeLorgnetteManagerClient;
-using ::chromeos::Scanner;
 using local_discovery::ServiceDescription;
 using ::testing::ElementsAreArray;
 
@@ -359,7 +358,7 @@
 // Test that the name of a detected non-ESCL zeroconf scanner does not generate
 // a scanner if it is not an Epson.
 TEST_F(LorgnetteScannerManagerTest, NonEsclNonEpsonZeroconfScanner) {
-  absl::optional<chromeos::Scanner> scanner = CreateSaneScanner(
+  absl::optional<Scanner> scanner = CreateSaneScanner(
       "Test MX3100", ZeroconfScannerDetector::kGenericScannerServiceType, "",
       net::IPAddress(192, 168, 0, 3), 5, true);
   EXPECT_FALSE(scanner.has_value());
diff --git a/chrome/browser/ash/scanning/lorgnette_scanner_manager_util.cc b/chrome/browser/ash/scanning/lorgnette_scanner_manager_util.cc
index 240b6922..04580950 100644
--- a/chrome/browser/ash/scanning/lorgnette_scanner_manager_util.cc
+++ b/chrome/browser/ash/scanning/lorgnette_scanner_manager_util.cc
@@ -19,14 +19,14 @@
 
 void ParseScannerName(const std::string& scanner_name,
                       std::string& ip_address_out,
-                      chromeos::ScanProtocol& protocol_out) {
+                      ScanProtocol& protocol_out) {
   if (RE2::PartialMatch(scanner_name, kIpv4Pattern, &ip_address_out) ||
       RE2::PartialMatch(scanner_name, kUrlPattern)) {
-    protocol_out = chromeos::ScanProtocol::kLegacyNetwork;
+    protocol_out = ScanProtocol::kLegacyNetwork;
     return;
   }
 
-  protocol_out = chromeos::ScanProtocol::kLegacyUsb;
+  protocol_out = ScanProtocol::kLegacyUsb;
 }
 
 }  // namespace ash
diff --git a/chrome/browser/ash/scanning/lorgnette_scanner_manager_util.h b/chrome/browser/ash/scanning/lorgnette_scanner_manager_util.h
index 42e37a7..c2d8a40 100644
--- a/chrome/browser/ash/scanning/lorgnette_scanner_manager_util.h
+++ b/chrome/browser/ash/scanning/lorgnette_scanner_manager_util.h
@@ -9,7 +9,7 @@
 
 #include <string>
 
-#include "chromeos/scanning/scanner.h"
+#include "chromeos/ash/components/scanning/scanner.h"
 
 namespace ash {
 
@@ -18,7 +18,7 @@
 // |ip_address_out|.
 void ParseScannerName(const std::string& scanner_name,
                       std::string& ip_address_out,
-                      chromeos::ScanProtocol& protocol_out);
+                      ScanProtocol& protocol_out);
 
 }  // namespace ash
 
diff --git a/chrome/browser/ash/scanning/lorgnette_scanner_manager_util_unittest.cc b/chrome/browser/ash/scanning/lorgnette_scanner_manager_util_unittest.cc
index 59404dd7..c464504 100644
--- a/chrome/browser/ash/scanning/lorgnette_scanner_manager_util_unittest.cc
+++ b/chrome/browser/ash/scanning/lorgnette_scanner_manager_util_unittest.cc
@@ -6,13 +6,11 @@
 
 #include <string>
 
-#include "chromeos/scanning/scanner.h"
+#include "chromeos/ash/components/scanning/scanner.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
 
-using ::chromeos::ScanProtocol;
-
 // Test that parsing a scanner name with an IP address successfully extracts the
 // IP address and sets the protocol to kLegacyNetwork.
 TEST(LorgnetteScannerManagerUtilTest, ParseNameWithIPAddress) {
diff --git a/chrome/browser/ash/scanning/scanner_detector.h b/chrome/browser/ash/scanning/scanner_detector.h
index 0009b49..c5fd5ba 100644
--- a/chrome/browser/ash/scanning/scanner_detector.h
+++ b/chrome/browser/ash/scanning/scanner_detector.h
@@ -8,8 +8,8 @@
 #include <vector>
 
 #include "base/callback.h"
+#include "chromeos/ash/components/scanning/scanner.h"
 #include "chromeos/chromeos_export.h"
-#include "chromeos/scanning/scanner.h"
 
 namespace ash {
 
@@ -33,12 +33,12 @@
   // Registers the callback used to provide notifications when scanners are
   // detected.
   using OnScannersDetectedCallback =
-      base::RepeatingCallback<void(std::vector<chromeos::Scanner> scanners)>;
+      base::RepeatingCallback<void(std::vector<Scanner> scanners)>;
   virtual void RegisterScannersDetectedCallback(
       OnScannersDetectedCallback callback) = 0;
 
   // Returns the detected scanners.
-  virtual std::vector<chromeos::Scanner> GetScanners() = 0;
+  virtual std::vector<Scanner> GetScanners() = 0;
 };
 
 }  // namespace ash
diff --git a/chrome/browser/ash/scanning/zeroconf_scanner_detector.cc b/chrome/browser/ash/scanning/zeroconf_scanner_detector.cc
index c239b775..e32ccf4 100644
--- a/chrome/browser/ash/scanning/zeroconf_scanner_detector.cc
+++ b/chrome/browser/ash/scanning/zeroconf_scanner_detector.cc
@@ -20,7 +20,7 @@
 #include "base/strings/string_util.h"
 #include "chrome/browser/ash/scanning/zeroconf_scanner_detector_utils.h"
 #include "chrome/browser/local_discovery/service_discovery_shared_client.h"
-#include "chromeos/scanning/scanner.h"
+#include "chromeos/ash/components/scanning/scanner.h"
 #include "components/device_event_log/device_event_log.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -76,7 +76,7 @@
 
 // Attempts to create a Scanner using the information in |service_description|
 // and |metadata|. Returns the Scanner on success, absl::nullopt on failure.
-absl::optional<chromeos::Scanner> CreateScanner(
+absl::optional<Scanner> CreateScanner(
     const std::string& service_type,
     const ServiceDescription& service_description,
     const ParsedMetadata& metadata) {
@@ -135,7 +135,7 @@
   }
 
   // ScannerDetector:
-  std::vector<chromeos::Scanner> GetScanners() override {
+  std::vector<Scanner> GetScanners() override {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
     return GetDedupedScanners();
   }
@@ -200,31 +200,30 @@
   }
 
   // Returns the detected scanners after merging duplicates.
-  std::vector<chromeos::Scanner> GetDedupedScanners() {
+  std::vector<Scanner> GetDedupedScanners() {
     // Use a map of display name to Scanner to deduplicate the detected
     // scanners. If a Scanner has the same display name as one that's already
     // been added to the map, merge the two by adding the new Scanner's
     // information to the existing Scanner.
-    base::flat_map<std::string, chromeos::Scanner> deduped_scanners;
+    base::flat_map<std::string, Scanner> deduped_scanners;
     for (const auto& entry : scanners_) {
-      const chromeos::Scanner* scanner = &entry.second;
+      const Scanner* scanner = &entry.second;
       auto it = deduped_scanners.find(scanner->display_name);
       if (it == deduped_scanners.end()) {
         deduped_scanners.insert({scanner->display_name, *scanner});
       } else {
         // Each Scanner in scanners_ should have a single device name
         // corresponding to a known protocol.
-        chromeos::ScanProtocol protocol = chromeos::ScanProtocol::kUnknown;
-        if (scanner->device_names.find(chromeos::ScanProtocol::kEscls) !=
+        ScanProtocol protocol = ScanProtocol::kUnknown;
+        if (scanner->device_names.find(ScanProtocol::kEscls) !=
             scanner->device_names.end()) {
-          protocol = chromeos::ScanProtocol::kEscls;
-        } else if (scanner->device_names.find(chromeos::ScanProtocol::kEscl) !=
+          protocol = ScanProtocol::kEscls;
+        } else if (scanner->device_names.find(ScanProtocol::kEscl) !=
                    scanner->device_names.end()) {
-          protocol = chromeos::ScanProtocol::kEscl;
-        } else if (scanner->device_names.find(
-                       chromeos::ScanProtocol::kLegacyNetwork) !=
+          protocol = ScanProtocol::kEscl;
+        } else if (scanner->device_names.find(ScanProtocol::kLegacyNetwork) !=
                    scanner->device_names.end()) {
-          protocol = chromeos::ScanProtocol::kLegacyNetwork;
+          protocol = ScanProtocol::kLegacyNetwork;
         } else {
           NOTREACHED() << "Zeroconf scanner with unknown protocol.";
         }
@@ -237,7 +236,7 @@
       }
     }
 
-    std::vector<chromeos::Scanner> scanners;
+    std::vector<Scanner> scanners;
     scanners.reserve(deduped_scanners.size());
     for (const auto& entry : deduped_scanners)
       scanners.push_back(entry.second);
@@ -248,7 +247,7 @@
   SEQUENCE_CHECKER(sequence_);
 
   // Map from service name to Scanner.
-  base::flat_map<std::string, chromeos::Scanner> scanners_;
+  base::flat_map<std::string, Scanner> scanners_;
 
   // Keep a reference to the shared device client around for the lifetime of
   // this object.
diff --git a/chrome/browser/ash/scanning/zeroconf_scanner_detector_unittest.cc b/chrome/browser/ash/scanning/zeroconf_scanner_detector_unittest.cc
index 1431bf30..f213903 100644
--- a/chrome/browser/ash/scanning/zeroconf_scanner_detector_unittest.cc
+++ b/chrome/browser/ash/scanning/zeroconf_scanner_detector_unittest.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/ash/scanning/zeroconf_scanner_detector_utils.h"
 #include "chrome/browser/local_discovery/fake_service_discovery_device_lister.h"
 #include "chrome/browser/local_discovery/service_discovery_device_lister.h"
-#include "chromeos/scanning/scanner.h"
+#include "chromeos/ash/components/scanning/scanner.h"
 #include "net/base/ip_address.h"
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -28,7 +28,6 @@
 
 namespace {
 
-using ::chromeos::Scanner;
 using local_discovery::FakeServiceDiscoveryDeviceLister;
 using local_discovery::ServiceDescription;
 using local_discovery::ServiceDiscoveryDeviceLister;
diff --git a/chrome/browser/ash/scanning/zeroconf_scanner_detector_utils.cc b/chrome/browser/ash/scanning/zeroconf_scanner_detector_utils.cc
index 348e8ad1..76b61fa 100644
--- a/chrome/browser/ash/scanning/zeroconf_scanner_detector_utils.cc
+++ b/chrome/browser/ash/scanning/zeroconf_scanner_detector_utils.cc
@@ -19,16 +19,16 @@
 // Sets the values of |scheme| and |protocol| based on |service_type|.
 void SetSchemeAndProtocol(const std::string& service_type,
                           std::string& scheme_out,
-                          chromeos::ScanProtocol& protocol_out) {
+                          ScanProtocol& protocol_out) {
   if (service_type == ZeroconfScannerDetector::kEsclsServiceType) {
     scheme_out = "https";
-    protocol_out = chromeos::ScanProtocol::kEscls;
+    protocol_out = ScanProtocol::kEscls;
   } else if (service_type == ZeroconfScannerDetector::kEsclServiceType) {
     scheme_out = "http";
-    protocol_out = chromeos::ScanProtocol::kEscl;
+    protocol_out = ScanProtocol::kEscl;
   } else if (service_type ==
              ZeroconfScannerDetector::kGenericScannerServiceType) {
-    protocol_out = chromeos::ScanProtocol::kLegacyNetwork;
+    protocol_out = ScanProtocol::kLegacyNetwork;
   } else {
     NOTREACHED() << "Zeroconf scanner with unknown service type: "
                  << service_type;
@@ -71,15 +71,14 @@
 
 }  // namespace
 
-absl::optional<chromeos::Scanner> CreateSaneScanner(
-    const std::string& name,
-    const std::string& service_type,
-    const std::string& rs,
-    const net::IPAddress& ip_address,
-    int port,
-    bool usable) {
+absl::optional<Scanner> CreateSaneScanner(const std::string& name,
+                                          const std::string& service_type,
+                                          const std::string& rs,
+                                          const net::IPAddress& ip_address,
+                                          int port,
+                                          bool usable) {
   std::string scheme;
-  chromeos::ScanProtocol protocol = chromeos::ScanProtocol::kUnknown;
+  ScanProtocol protocol = ScanProtocol::kUnknown;
   SetSchemeAndProtocol(service_type, scheme, protocol);
   std::string device_name = "";
   // If the name contains "EPSON" and is a generic service type, use the
@@ -94,10 +93,10 @@
   if (device_name.empty())
     return absl::nullopt;
 
-  chromeos::Scanner scanner;
+  Scanner scanner;
   scanner.display_name = name;
   scanner.device_names[protocol].emplace(
-      chromeos::ScannerDeviceName(device_name, usable));
+      ScannerDeviceName(device_name, usable));
   scanner.ip_addresses.insert(ip_address);
   return scanner;
 }
diff --git a/chrome/browser/ash/scanning/zeroconf_scanner_detector_utils.h b/chrome/browser/ash/scanning/zeroconf_scanner_detector_utils.h
index 281466c..566a49c 100644
--- a/chrome/browser/ash/scanning/zeroconf_scanner_detector_utils.h
+++ b/chrome/browser/ash/scanning/zeroconf_scanner_detector_utils.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "chromeos/scanning/scanner.h"
+#include "chromeos/ash/components/scanning/scanner.h"
 #include "net/base/ip_address.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -22,13 +22,12 @@
 // resolve host names it did not discover itself. See mdns_make_escl_endpoint()
 // at https://github.com/alexpevzner/sane-airscan/blob/master/airscan-mdns.c for
 // more details.
-absl::optional<chromeos::Scanner> CreateSaneScanner(
-    const std::string& name,
-    const std::string& service_type,
-    const std::string& rs,
-    const net::IPAddress& ip_address,
-    int port,
-    bool usable = true);
+absl::optional<Scanner> CreateSaneScanner(const std::string& name,
+                                          const std::string& service_type,
+                                          const std::string& rs,
+                                          const net::IPAddress& ip_address,
+                                          int port,
+                                          bool usable = true);
 
 }  // namespace ash
 
diff --git a/chrome/browser/ash/settings/device_settings_test_helper.cc b/chrome/browser/ash/settings/device_settings_test_helper.cc
index 3115e57..5fd992e 100644
--- a/chrome/browser/ash/settings/device_settings_test_helper.cc
+++ b/chrome/browser/ash/settings/device_settings_test_helper.cc
@@ -14,7 +14,7 @@
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/ash/settings/device_settings_service.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
 #include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
diff --git a/chrome/browser/ash/smb_client/smb_service_unittest.cc b/chrome/browser/ash/smb_client/smb_service_unittest.cc
index 9b04c7c1..29d18585 100644
--- a/chrome/browser/ash/smb_client/smb_service_unittest.cc
+++ b/chrome/browser/ash/smb_client/smb_service_unittest.cc
@@ -43,7 +43,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/smbprovider/fake_smb_provider_client.h"
 #include "components/user_manager/scoped_user_manager.h"
diff --git a/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc b/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc
index 3dfa938..2f28c1d8 100644
--- a/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc
+++ b/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc
@@ -132,7 +132,7 @@
 IN_PROC_BROWSER_TEST_F(CrosWindowBrowserTest, CrosWindowSetOrigin) {
   const char test_code[] = R"(
 async function cros_test() {
-  let [window] = await chromeos.windowManagement.windows();
+  let [window] = await chromeos.windowManagement.getWindows();
 
   const newBounds = DOMRect.fromRect(window.bounds);
   newBounds.x += 10;
@@ -140,7 +140,7 @@
 
   window.setOrigin(newBounds.x, newBounds.y);
   {
-    let [window] = await chromeos.windowManagement.windows();
+    let [window] = await chromeos.windowManagement.getWindows();
     assert_weak_equals(window.bounds, newBounds,
         `SetOrigin should set origin without changing bounds`);
   }
@@ -153,7 +153,7 @@
 IN_PROC_BROWSER_TEST_F(CrosWindowBrowserTest, CrosWindowSetBounds) {
   const char test_code[] = R"(
 async function cros_test() {
-  let [window] = await chromeos.windowManagement.windows();
+  let [window] = await chromeos.windowManagement.getWindows();
 
   const newBounds = DOMRect.fromRect(window.bounds);
   newBounds.x += 10;
@@ -301,13 +301,13 @@
 async function cros_test() {
   await assertWindowState("normal");
   {
-    let [window] = await chromeos.windowManagement.windows();
+    let [window] = await chromeos.windowManagement.getWindows();
     assert_true(window.isFocused);
   }
 
   await minimizeAndTest();
   {
-    let [window] = await chromeos.windowManagement.windows();
+    let [window] = await chromeos.windowManagement.getWindows();
     assert_false(window.isFocused);
   }
 
@@ -329,10 +329,10 @@
 
   {
     let [first_window, second_window] =
-        await chromeos.windowManagement.windows();
+        await chromeos.windowManagement.getWindows();
     getWindows = async function() {
       let [first_returned_window, second_returned_window] =
-          await chromeos.windowManagement.windows();
+          await chromeos.windowManagement.getWindows();
       assert_equals(first_window.id, first_returned_window.id);
       assert_equals(second_window.id, second_returned_window.id);
       return [first_returned_window, second_returned_window];
@@ -442,7 +442,7 @@
 
   std::string test_code = base::StringPrintf(R"(
 async function cros_test() {
-  let windows = await chromeos.windowManagement.windows();
+  let windows = await chromeos.windowManagement.getWindows();
   assert_equals(windows.length, 2);
 
   let window_to_close = windows.find(window => window.id === "%1$s");
@@ -452,7 +452,7 @@
 
   // TODO(b/221123297): Currently test will flake on close under stress.
   // Defer testing until on close event implemented
-  // windows = await chromeos.windowManagement.windows();
+  // windows = await chromeos.windowManagement.getWindows();
   // assert_equals(windows.length, 1);
 }
   )",
@@ -498,7 +498,7 @@
 
   std::string test_code = base::StringPrintf(R"(
 async function cros_test() {
-  let windows = await chromeos.windowManagement.windows();
+  let windows = await chromeos.windowManagement.getWindows();
   assert_equals(windows.length, 2);
 
   let swa_window = windows.find(window => window.id === "%1$s");
diff --git a/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc b/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc
index 4bb9b8ec..dadb224f 100644
--- a/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc
+++ b/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc
@@ -30,10 +30,10 @@
 void WindowManagementImpl::GetAllWindows(GetAllWindowsCallback callback) {
   apps::AppServiceProxy* proxy = apps::AppServiceProxyFactory::GetForProfile(
       Profile::FromBrowserContext(browser_context_));
-  std::vector<blink::mojom::CrosWindowPtr> windows;
+  std::vector<blink::mojom::CrosWindowInfoPtr> windows;
   proxy->InstanceRegistry().ForEachInstance(
       [&windows](const apps::InstanceUpdate& update) {
-        auto window = blink::mojom::CrosWindow::New();
+        auto window = blink::mojom::CrosWindowInfo::New();
         aura::Window* target = update.Window()->GetToplevelWindow();
         views::Widget* widget =
             views::Widget::GetTopLevelWidgetForNativeView(target);
diff --git a/chrome/browser/ash/usb/cros_usb_detector.cc b/chrome/browser/ash/usb/cros_usb_detector.cc
index 8f6495e..ba783a3 100644
--- a/chrome/browser/ash/usb/cros_usb_detector.cc
+++ b/chrome/browser/ash/usb/cros_usb_detector.cc
@@ -33,7 +33,7 @@
 #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/generated_resources.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/vector_icons/vector_icons.h"
diff --git a/chrome/browser/ash/usb/cros_usb_detector.h b/chrome/browser/ash/usb/cros_usb_detector.h
index efae3cf..d35f066f 100644
--- a/chrome/browser/ash/usb/cros_usb_detector.h
+++ b/chrome/browser/ash/usb/cros_usb_detector.h
@@ -13,7 +13,7 @@
 
 #include "ash/components/disks/disk_mount_manager.h"
 #include "base/memory/weak_ptr.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.h"
 #include "mojo/public/cpp/bindings/associated_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chrome/browser/ash/usb/cros_usb_detector_unittest.cc b/chrome/browser/ash/usb/cros_usb_detector_unittest.cc
index 5dcd471..0fee356 100644
--- a/chrome/browser/ash/usb/cros_usb_detector_unittest.cc
+++ b/chrome/browser/ash/usb/cros_usb_detector_unittest.cc
@@ -33,11 +33,11 @@
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/cros_disks/cros_disks_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/vm_plugin_dispatcher/fake_vm_plugin_dispatcher_client.h"
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index d6d0dbb1..497198d 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -37,9 +37,9 @@
     "//chrome/browser/ash/power/ml:user_activity_ukm_logger_helpers",
     "//chrome/browser/ui/webui/chromeos/crostini_installer:mojo_bindings",
     "//chrome/browser/ui/webui/chromeos/emoji:mojo_bindings",
+    "//chromeos/ash/components/dbus/concierge:concierge_proto",
     "//chromeos/ash/components/dbus/seneschal:seneschal_proto",
     "//chromeos/dbus:cicerone_proto",
-    "//chromeos/dbus:concierge_proto",
     "//chromeos/dbus:vm_applications_apps_proto",
     "//chromeos/dbus:vm_disk_management_proto",
     "//chromeos/dbus:vm_launch_proto",
@@ -238,6 +238,7 @@
     "//chromeos/ash/components/dbus/authpolicy",
     "//chromeos/ash/components/dbus/authpolicy:authpolicy_proto",
     "//chromeos/ash/components/dbus/biod",
+    "//chromeos/ash/components/dbus/concierge",
     "//chromeos/ash/components/dbus/cros_healthd",
     "//chromeos/ash/components/dbus/cups_proxy",
     "//chromeos/ash/components/dbus/fusebox",
@@ -262,6 +263,7 @@
     "//chromeos/ash/components/dbus/typecd",
     "//chromeos/ash/components/dbus/upstart",
     "//chromeos/ash/components/hibernate:buildflags",
+    "//chromeos/ash/components/scanning",
     "//chromeos/assistant:buildflags",
     "//chromeos/components/cdm_factory_daemon:cdm_factory_daemon_browser",
     "//chromeos/components/chromebox_for_meetings/buildflags",
@@ -291,7 +293,6 @@
     "//chromeos/dbus/cdm_factory_daemon",
     "//chromeos/dbus/chunneld",
     "//chromeos/dbus/cicerone",
-    "//chromeos/dbus/concierge",
     "//chromeos/dbus/constants",
     "//chromeos/dbus/cros_disks",
     "//chromeos/dbus/cryptohome",
@@ -339,7 +340,6 @@
     "//chromeos/memory",
     "//chromeos/network",
     "//chromeos/printing",
-    "//chromeos/scanning",
     "//chromeos/services/assistant:lib",
     "//chromeos/services/assistant/public/cpp",
     "//chromeos/services/bluetooth_config:in_process_bluetooth_config",
@@ -3973,11 +3973,11 @@
     "//chrome/common:constants",
     "//chrome/test:test_support",
     "//chrome/test:test_support_ui",
+    "//chromeos/ash/components/dbus/concierge",
     "//chromeos/ash/components/dbus/seneschal",
     "//chromeos/dbus:test_support",
     "//chromeos/dbus/chunneld",
     "//chromeos/dbus/cicerone",
-    "//chromeos/dbus/concierge",
     "//chromeos/dbus/cros_disks",
     "//chromeos/dbus/cryptohome",
     "//chromeos/dbus/cryptohome:cryptohome_proto",
@@ -4926,6 +4926,7 @@
     "//chromeos/ash/components/dbus/services:test_support",
     "//chromeos/ash/components/dbus/system_clock",
     "//chromeos/ash/components/dbus/upstart",
+    "//chromeos/ash/components/scanning",
     "//chromeos/components/sensors:test_support",
     "//chromeos/dbus:test_support",
     "//chromeos/dbus/anomaly_detector",
@@ -4951,7 +4952,6 @@
     "//chromeos/login/login_state:test_support",
     "//chromeos/network",
     "//chromeos/network:test_support",
-    "//chromeos/scanning",
     "//chromeos/services/machine_learning/public/cpp:stub",
     "//chromeos/system",
     "//chromeos/ui/frame:test_support",
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc b/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc
index 7e22cff..595a5439 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc
@@ -41,7 +41,7 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/extensions/api/file_system_provider_capabilities/file_system_provider_capabilities_handler.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "chromeos/dbus/cros_disks/cros_disks_client.h"
 #include "chromeos/dbus/dlp/dlp_client.h"
 #include "chromeos/dbus/dlp/dlp_service.pb.h"
diff --git a/chrome/browser/extensions/api/gcm/extension_gcm_app_handler_unittest.cc b/chrome/browser/extensions/api/gcm/extension_gcm_app_handler_unittest.cc
index 6c21ae00..707afb2 100644
--- a/chrome/browser/extensions/api/gcm/extension_gcm_app_handler_unittest.cc
+++ b/chrome/browser/extensions/api/gcm/extension_gcm_app_handler_unittest.cc
@@ -69,7 +69,7 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/ash/login/users/scoped_test_user_manager.h"
 #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #endif
 
 namespace extensions {
diff --git a/chrome/browser/extensions/api/image_writer_private/test_utils.cc b/chrome/browser/extensions/api/image_writer_private/test_utils.cc
index f22a7bd..2e07b6c 100644
--- a/chrome/browser/extensions/api/image_writer_private/test_utils.cc
+++ b/chrome/browser/extensions/api/image_writer_private/test_utils.cc
@@ -20,7 +20,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/components/disks/disk.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"  // nogncheck
 #include "chromeos/dbus/image_burner/fake_image_burner_client.h"
 #endif
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
index 9a0028bc..12e2ed55 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
@@ -219,7 +219,10 @@
                                      std::string* error) {
   extensions::InputImeEventRouter* event_router =
       extensions::GetInputImeEventRouter(profile);
-  DCHECK(event_router) << kErrorRouterNotAvailable;
+  if (!event_router) {
+    *error = kErrorRouterNotAvailable;
+    return nullptr;
+  }
   InputMethodEngine* engine = static_cast<InputMethodEngine*>(
       event_router->GetEngineIfActive(extension_id, error));
   return engine;
diff --git a/chrome/browser/gcm/gcm_profile_service_unittest.cc b/chrome/browser/gcm/gcm_profile_service_unittest.cc
index 2a13932..ebf6261d 100644
--- a/chrome/browser/gcm/gcm_profile_service_unittest.cc
+++ b/chrome/browser/gcm/gcm_profile_service_unittest.cc
@@ -40,7 +40,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #endif
 
 namespace gcm {
diff --git a/chrome/browser/metrics/oom/out_of_memory_reporter.cc b/chrome/browser/metrics/oom/out_of_memory_reporter.cc
index 74164c4..ae751b9 100644
--- a/chrome/browser/metrics/oom/out_of_memory_reporter.cc
+++ b/chrome/browser/metrics/oom/out_of_memory_reporter.cc
@@ -60,22 +60,13 @@
   tick_clock_ = std::move(tick_clock);
 }
 
-void OutOfMemoryReporter::DidFinishNavigation(
-    content::NavigationHandle* handle) {
-  // Ignore navigations to documents not in the primary main frame, as they will
-  // never show up as a visible top document. In particular, prerendered pages
-  // will navigate again in the primary main frame when they are activated.
-  if (!handle->IsInPrimaryMainFrame() || !handle->HasCommitted() ||
-      handle->IsSameDocument()) {
-    return;
-  }
+void OutOfMemoryReporter::PrimaryPageChanged(content::Page& page) {
   last_committed_source_id_.reset();
   last_navigation_timestamp_ = tick_clock_->NowTicks();
   crashed_render_process_id_ = content::ChildProcessHost::kInvalidUniqueID;
-  if (handle->IsErrorPage())
+  if (page.GetMainDocument().IsErrorDocument())
     return;
-  last_committed_source_id_ = ukm::ConvertToSourceId(
-      handle->GetNavigationId(), ukm::SourceIdType::NAVIGATION_ID);
+  last_committed_source_id_ = page.GetMainDocument().GetPageUkmSourceId();
 }
 
 void OutOfMemoryReporter::PrimaryMainFrameRenderProcessGone(
diff --git a/chrome/browser/metrics/oom/out_of_memory_reporter.h b/chrome/browser/metrics/oom/out_of_memory_reporter.h
index 7ab2187..37d63359 100644
--- a/chrome/browser/metrics/oom/out_of_memory_reporter.h
+++ b/chrome/browser/metrics/oom/out_of_memory_reporter.h
@@ -61,7 +61,7 @@
   void SetTickClockForTest(std::unique_ptr<const base::TickClock> tick_clock);
 
   // content::WebContentsObserver:
-  void DidFinishNavigation(content::NavigationHandle* handle) override;
+  void PrimaryPageChanged(content::Page& page) override;
   void PrimaryMainFrameRenderProcessGone(
       base::TerminationStatus termination_status) override;
 
diff --git a/chrome/browser/performance_manager/mechanisms/working_set_trimmer_chromeos_unittest.cc b/chrome/browser/performance_manager/mechanisms/working_set_trimmer_chromeos_unittest.cc
index 059bbd9..a2a8633 100644
--- a/chrome/browser/performance_manager/mechanisms/working_set_trimmer_chromeos_unittest.cc
+++ b/chrome/browser/performance_manager/mechanisms/working_set_trimmer_chromeos_unittest.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chrome/browser/ash/arc/test/test_arc_session_manager.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chrome/browser/performance_manager/policies/working_set_trimmer_policy_arcvm_unittest.cc b/chrome/browser/performance_manager/policies/working_set_trimmer_policy_arcvm_unittest.cc
index 0bee3e2..5f9c2252 100644
--- a/chrome/browser/performance_manager/policies/working_set_trimmer_policy_arcvm_unittest.cc
+++ b/chrome/browser/performance_manager/policies/working_set_trimmer_policy_arcvm_unittest.cc
@@ -22,7 +22,7 @@
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chrome/browser/ash/arc/test/test_arc_session_manager.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "components/arc/test/fake_intent_helper_host.h"
 #include "components/arc/test/fake_intent_helper_instance.h"
 #include "components/prefs/testing_pref_service.h"
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index 62992ec..ca2c6a2c 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -480,14 +480,13 @@
   ProfileThemeUpdateServiceFactory::GetInstance();
 #endif
   ProtocolHandlerRegistryFactory::GetInstance();
-  if (reading_list::switches::IsReadingListEnabled()) {
-    ReadingListModelFactory::GetInstance();
+
+  ReadingListModelFactory::GetInstance();
 
 #if BUILDFLAG(IS_ANDROID)
-    ReadingListManagerFactory::GetInstance();
-    ReadingListNotificationServiceFactory::GetInstance();
+  ReadingListManagerFactory::GetInstance();
+  ReadingListNotificationServiceFactory::GetInstance();
 #endif
-  }
 
   RendererUpdaterFactory::GetInstance();
 
diff --git a/chrome/browser/resources/settings/autofill_page/password_view.html b/chrome/browser/resources/settings/autofill_page/password_view.html
index 6c96d9e..94eb375 100644
--- a/chrome/browser/resources/settings/autofill_page/password_view.html
+++ b/chrome/browser/resources/settings/autofill_page/password_view.html
@@ -61,7 +61,7 @@
       $i18n{editPasswordPasswordLabel}
     </div>
     <div class="row-container">
-      <input id="passwordInput" readonly value="[[password_]]"
+      <input id="passwordInput" readonly value="[[getPassword_(password_)]]"
           type="[[getPasswordInputType_(credential, isPasswordVisible_)]]">
       <template is="dom-if" if="[[!isFederated_(credential)]]" restamp>
         <cr-icon-button id="showPasswordButton" slot="suffix"
diff --git a/chrome/browser/resources/settings/autofill_page/password_view.ts b/chrome/browser/resources/settings/autofill_page/password_view.ts
index d15f7e6..b8d0f18 100644
--- a/chrome/browser/resources/settings/autofill_page/password_view.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_view.ts
@@ -116,7 +116,6 @@
   private isPasswordVisible_: boolean;
   private password_: string;
   // <if expr="chromeos_ash or chromeos_lacros">
-  private isTokenObtained_: boolean = false;
   private showPasswordPromptDialog_: boolean;
   // </if>
   private showEditDialog_: boolean;
@@ -183,6 +182,14 @@
   }
 
   /**
+   * Show the password or a placeholder with 10 characters when password is not
+   * set.
+   */
+  private getPassword_(): string {
+    return this.password_ || ' '.repeat(10);
+  }
+
+  /**
    * Gets the password input's type. Should be 'text' when input content is
    * visible otherwise 'password'. If the entry is a federated credential,
    * the content (federation text) is always visible.
@@ -198,7 +205,10 @@
   /** Handler to copy the password from the password field. */
   private onCopyPasswordButtonClick_() {
     assert(!this.isFederated_());
-    navigator.clipboard.writeText(this.password_);
+    this.requestPlaintextPassword(
+            this.credential!.getAnyId(),
+            chrome.passwordsPrivate.PlaintextReason.COPY)
+        .catch(() => {});
   }
 
   /** Handler to copy the username from the username field. */
@@ -226,7 +236,7 @@
         .then(password => {
           this.credential!.password = password;
           this.showEditDialog_ = true;
-        });
+        }, () => {});
   }
 
   private onEditDialogClosed_() {
@@ -263,35 +273,37 @@
   private onTokenObtained_(
       e: CustomEvent<chrome.quickUnlockPrivate.TokenInfo>) {
     assert(e.detail);
-    this.isTokenObtained_ = true;
     this.tokenRequestManager.resolve();
   }
 
   private onPasswordPromptClose_() {
     this.showPasswordPromptDialog_ = false;
     const toFocus = this.activeDialogAnchorStack_.pop();
-    if (!this.isTokenObtained_ && (!toFocus || toFocus.id !== 'editButton')) {
-      // User dismissed the password prompt by clicking cancel. Reroute back if
-      // prompt was not requested within the page.
-      Router.getInstance().navigateTo(routes.PASSWORDS);
-      return;
-    }
     assert(toFocus);
     focusWithoutInk(toFocus);
-    this.isTokenObtained_ = false;
   }
 
   private openPasswordPromptDialog_() {
     this.activeDialogAnchorStack_.push(getDeepActiveElement() as HTMLElement);
     this.showPasswordPromptDialog_ = true;
-    this.isTokenObtained_ = false;
   }
   // </if>
 
   /** Handler for tapping the show/hide button. */
   private onShowPasswordButtonClick_() {
     assert(!this.isFederated_());
-    this.isPasswordVisible_ = !this.isPasswordVisible_;
+    if (this.isPasswordVisible_) {
+      this.password_ = '';
+      this.isPasswordVisible_ = false;
+      return;
+    }
+    this.requestPlaintextPassword(
+            this.credential!.getAnyId(),
+            chrome.passwordsPrivate.PlaintextReason.VIEW)
+        .then(password => {
+          this.password_ = password;
+          this.isPasswordVisible_ = true;
+        }, () => {});
   }
 
   /** Reroutes to PASSWORDS page and shows the removal notification */
@@ -312,6 +324,7 @@
   private savedPasswordsChanged_() {
     this.credential = null;
     this.password_ = '';
+    this.isPasswordVisible_ = false;
     if (!this.savedPasswords.length || !this.site || !this.username) {
       return;
     }
@@ -330,19 +343,9 @@
       return;
     }
 
+    this.credential = item;
     if (item.federationText) {
-      this.credential = item;
       this.password_ = item.federationText!;
-    } else {
-      this.requestPlaintextPassword(
-              item.getAnyId(), chrome.passwordsPrivate.PlaintextReason.VIEW)
-          .then(password => {
-            this.password_ = password;
-            this.credential = item;
-          })
-          .catch(_error => {
-            Router.getInstance().navigateTo(routes.PASSWORDS);
-          });
     }
     this.showEditDialog_ = false;
   }
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn
index ed426b3..93151ac 100644
--- a/chrome/browser/resources/settings/chromeos/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -555,6 +555,7 @@
     "chromeos/os_files_page/os_files_page.js",
     "chromeos/os_files_page/smb_shares_page.js",
     "chromeos/os_icons.js",
+    "chromeos/os_languages_page/add_items_dialog.js",
     "chromeos/os_languages_page/add_input_methods_dialog.js",
     "chromeos/os_languages_page/add_spellcheck_languages_dialog.js",
     "chromeos/os_languages_page/change_device_language_dialog.js",
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
index 36276da..f8df612 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
@@ -14,6 +14,7 @@
   is_polymer3 = true
   deps = [
     ":add_input_methods_dialog",
+    ":add_items_dialog",
     ":add_spellcheck_languages_dialog",
     ":change_device_language_dialog",
     ":cr_checkbox_with_policy",
@@ -72,26 +73,38 @@
 }
 
 js_library("add_input_methods_dialog") {
-  deps = [ ":cr_checkbox_with_policy" ]
-}
-
-js_library("add_spellcheck_languages_dialog") {
   deps = [
-    ":cr_checkbox_with_policy",
+    ":add_items_dialog",
     ":languages_types",
     "..:metrics_recorder",
-    "..:prefs_behavior",
-    "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout-classes",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+}
+
+js_library("add_items_dialog") {
+  deps = [
+    ":cr_checkbox_with_policy",
     "//third_party/polymer/v3_0/components-chromium/iron-list:iron-list",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/cr_elements:cr_scrollable_behavior.m",
     "//ui/webui/resources/cr_elements:find_shortcut_behavior",
     "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
+    "//ui/webui/resources/cr_elements/cr_checkbox:cr_checkbox.m",
     "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
   ]
   externs_list = [ "//ui/webui/resources/cr_elements/cr_search_field/cr_search_field_externs.js" ]
 }
 
+js_library("add_spellcheck_languages_dialog") {
+  deps = [
+    ":add_items_dialog",
+    ":languages_types",
+    "..:metrics_recorder",
+    "..:prefs_behavior",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+}
+
 js_library("change_device_language_dialog") {
   deps = [
     ":languages",
@@ -160,12 +173,10 @@
 
 js_library("os_add_languages_dialog") {
   deps = [
-    ":languages",
+    ":add_items_dialog",
+    ":languages_types",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-    "//ui/webui/resources/cr_elements:cr_scrollable_behavior.m",
-    "//ui/webui/resources/cr_elements:find_shortcut_behavior",
   ]
-  externs_list = [ "//ui/webui/resources/cr_elements/cr_search_field/cr_search_field_externs.js" ]
 }
 
 js_library("os_edit_dictionary_page") {
@@ -232,6 +243,7 @@
 
 html_to_js("web_components") {
   js_files = [
+    "add_items_dialog.js",
     "add_input_methods_dialog.js",
     "add_spellcheck_languages_dialog.js",
     "change_device_language_dialog.js",
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/add_input_methods_dialog.html b/chrome/browser/resources/settings/chromeos/os_languages_page/add_input_methods_dialog.html
index e8c4d8dd..44f6733 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/add_input_methods_dialog.html
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/add_input_methods_dialog.html
@@ -1,103 +1,13 @@
-<style include="settings-shared iron-flex shared-style">
-  #dialogBody {
-    display: flex;
-    flex-direction: column;
-    height: 336px;
-    overflow: auto;
-  }
-
-  cr-search-field {
-    margin-bottom: 8px;
-  }
-
-  .label {
-    padding-bottom: 4px;
-    padding-top: 8px;
-  }
-
-  .list-item {
-    color: var(--cros-text-color-primary);
-    left: 0;
-    min-height: 36px;
-    right: 0;
-    width: inherit;
-  }
-
-  /* Allows the first focused list-item's (of any iron-list) applied
-   * ink droplet to show entirely. */
-  .list-item:first-of-type {
-    margin-top: 4px;
-  }
-
-  cr-checkbox::part(label-container) {
-    white-space: nowrap;
-  }
-
-  cr-dialog [slot=body] {
-    padding-inline-end: 0;
-    padding-inline-start: 0;
-  }
-
-  /* Adds spacing to elements that have the same width as the dialog.
-   * This is added in lieu of adding padding to the cr-dialog to show
-   * the ink droplets applied on focused checkboxes entirely. */
-   cr-dialog [slot=body] .is-width-of-dialog {
-    margin-inline-end: var(--dialog-horizontal-padding);
-    margin-inline-start: var(--dialog-horizontal-padding);
-  }
-</style>
-
-<cr-dialog id="dialog" close-text="$i18n{close}" show-on-attach>
-  <div slot="title">$i18n{addInputMethodLabel}</div>
-  <div id="dialogBody" slot="body" scrollable>
-    <cr-search-field label="$i18n{searchInputMethodsLabel}" id="search"
-        on-search-changed="onSearchChanged_" on-keydown="onKeydown_"
-        class="is-width-of-dialog"
-        clear-label="$i18n{clearSearch}" autofocus>
-    </cr-search-field>
-    <template is="dom-if" if="[[showSuggestedList_]]">
-      <div id="suggestedInputMethods">
-        <div class="label is-width-of-dialog">
-          $i18n{suggestedInputMethodsLabel}
-        </div>
-        <iron-list items="[[suggestedInputMethods_]]">
-          <template>
-            <cr-checkbox class="list-item no-outline is-width-of-dialog"
-                checked="[[willAdd_(item.id, inputMethodsToAdd_.size)]]"
-                tab-index="[[tabIndex]]" on-change="onCheckboxChange_">
-              [[item.displayName]]
-            </cr-checkbox>
-          </template>
-        </iron-list>
-      </div>
-    </template>
-    <div id="allInputMethods">
-      <div id="allInputMethodsLabel" hidden="[[!showSuggestedList_]]"
-          class="label is-width-of-dialog">
-        $i18n{allInputMethodsLabel}
-      </div>
-      <iron-list items="[[getAllInputMethods_(languages.inputMethods,
-          lowercaseQueryString_)]]">
-        <template>
-          <cr-checkbox-with-policy
-              class="list-item no-outline is-width-of-dialog"
-              checked="[[willAdd_(item.id, inputMethodsToAdd_.size)]]"
-              disabled="[[item.isProhibitedByPolicy]]"
-              policy-tooltip="$i18n{inputMethodNotAllowed}"
-              tab-index="[[tabIndex]]" on-change="onCheckboxChange_">
-            [[item.displayName]]
-          </cr-checkbox-with-policy>
-        </template>
-      </iron-list>
-    </div>
-  </div>
-  <div slot="button-container">
-    <cr-button class="cancel-button" on-click="onCancelButtonTap_">
-      $i18n{cancel}
-    </cr-button>
-    <cr-button class="action-button" on-click="onActionButtonTap_"
-        disabled="[[disableActionButton_]]">
-      $i18n{add}
-    </cr-button>
-  </div>
-</cr-dialog>
+<!-- TODO(crbug.com/1201535): Move everything to the parent element
+     (<os-settings-input-page>), as this element is trivial. -->
+<os-settings-add-items-dialog
+    items="[[getInputMethods_(languages.inputMethods)]]"
+    suggested-item-ids="[[getSuggestedInputMethodIds_(languages,
+        languages.enabled.*, languages.inputMethods.*)]]"
+    header="$i18n{addInputMethodLabel}"
+    search-label="$i18n{searchInputMethodsLabel}"
+    suggested-items-label="$i18n{suggestedInputMethodsLabel}"
+    all-items-label="$i18n{allInputMethodsLabel}"
+    policy-tooltip="$i18n{inputMethodNotAllowed}"
+    on-items-added="onItemsAdded_">
+</os-settings-add-items-dialog>
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/add_input_methods_dialog.js b/chrome/browser/resources/settings/chromeos/os_languages_page/add_input_methods_dialog.js
index dd91d79..becb763 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/add_input_methods_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/add_input_methods_dialog.js
@@ -13,17 +13,9 @@
  */
 import {afterNextRender, Polymer, html, flush, Templatizer, TemplateInstanceBase} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import '//resources/cr_elements/cr_button/cr_button.m.js';
-import '//resources/cr_elements/cr_search_field/cr_search_field.js';
-import '//resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import '//resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
-import '//resources/polymer/v3_0/iron-list/iron-list.js';
-import './cr_checkbox_with_policy.js';
+import {Item} from './add_items_dialog.js';
 import {recordSettingChange} from '../metrics_recorder.js';
-import './shared_style.js';
-import './languages.js';
 import {LanguageHelper, LanguagesModel} from './languages_types.js';
-import '../../settings_shared_css.js';
 
 Polymer({
   _template: html`{__html_template__}`,
@@ -35,51 +27,6 @@
 
     /** @type {!LanguageHelper} */
     languageHelper: Object,
-
-    /** @private {!Set<string>} */
-    inputMethodsToAdd_: {
-      type: Object,
-      value() {
-        return new Set();
-      },
-    },
-
-    /** @private {!Array<!chrome.languageSettingsPrivate.InputMethod>} */
-    suggestedInputMethods_: {
-      type: Array,
-      value: [],
-      computed:
-          'getSuggestedInputMethods_(languages, languages.enabled.*, languages.inputMethods.*)',
-    },
-
-    /** @private */
-    showSuggestedList_: {
-      type: Boolean,
-      value: false,
-      computed:
-          'shouldShowSuggestedList_(suggestedInputMethods_, lowercaseQueryString_)'
-    },
-
-    /** @private */
-    disableActionButton_: {
-      type: Boolean,
-      value: true,
-      computed: 'shouldDisableActionButton_(inputMethodsToAdd_.size)',
-    },
-
-    /** @private */
-    lowercaseQueryString_: {
-      type: String,
-      value: '',
-    },
-  },
-
-  /**
-   * @param {!CustomEvent<string>} e
-   * @private
-   */
-  onSearchChanged_(e) {
-    this.lowercaseQueryString_ = e.detail.toLocaleLowerCase();
   },
 
   /**
@@ -87,113 +34,50 @@
    * @return {!Array<!chrome.languageSettingsPrivate.InputMethod>}
    * @private
    */
-  getSuggestedInputMethods_() {
+  getSuggestedInputMethodIds_() {
     const languageCodes = [
       ...this.languageHelper.getEnabledLanguageCodes(),
       this.languageHelper.getArcImeLanguageCode()
     ];
     return this.languageHelper.getInputMethodsForLanguages(languageCodes)
+        .map(inputMethod => inputMethod.id);
+  },
+
+  /**
+   * @return {!Array<!Item>} A list of possible input methods.
+   * @private
+   */
+  getInputMethods_() {
+    return this.languages.inputMethods.supported
         .filter(inputMethod => {
+          // Don't show input methods which are already enabled.
           if (this.languageHelper.isInputMethodEnabled(inputMethod.id)) {
             return false;
           }
-          return !inputMethod.isProhibitedByPolicy;
-        });
-  },
-
-  /**
-   * @return {!Array<!chrome.languageSettingsPrivate.InputMethod>} A list of
-   *     possible input methods.
-   * @private
-   */
-  getAllInputMethods_() {
-    return this.languages.inputMethods.supported.filter(inputMethod => {
-      // Don't show input methods which are already enabled.
-      if (this.languageHelper.isInputMethodEnabled(inputMethod.id)) {
-        return false;
-      }
-      // Don't show the Dictation (Accessibility Common) extension in this list.
-      if (inputMethod.id === ACCESSIBILITY_COMMON_IME_ID) {
-        return false;
-      }
-      // Show input methods whose tags match the query.
-      return inputMethod.tags.some(
-          tag => tag.toLocaleLowerCase().includes(this.lowercaseQueryString_));
-    });
-  },
-
-  /**
-   * @return {boolean}
-   * @private
-   */
-  shouldShowSuggestedList_() {
-    return this.suggestedInputMethods_.length > 0 &&
-        !this.lowercaseQueryString_;
-  },
-
-  /**
-   * True if the user has chosen to add this input method (checked its
-   * checkbox).
-   * @param {string} id
-   * @return {boolean}
-   * @private
-   */
-  willAdd_(id) {
-    return this.inputMethodsToAdd_.has(id);
-  },
-
-  /**
-   * Handler for an input method checkbox.
-   * @param {!{model: !{item: chrome.languageSettingsPrivate.InputMethod},
-   *           target: !Element}} e
-   * @private
-   */
-  onCheckboxChange_(e) {
-    const inputMethodId = e.model.item.id;
-    if (e.target.checked) {
-      this.inputMethodsToAdd_.add(inputMethodId);
-    } else {
-      this.inputMethodsToAdd_.delete(inputMethodId);
-    }
-    // Polymer doesn't notify changes to set size.
-    this.notifyPath('inputMethodsToAdd_.size');
-  },
-
-  /**
-   * @return {boolean}
-   * @private
-   */
-  shouldDisableActionButton_() {
-    return !this.inputMethodsToAdd_.size;
-  },
-
-  /** @private */
-  onCancelButtonTap_() {
-    this.$.dialog.close();
+          // Don't show the Dictation (Accessibility Common) extension in this
+          // list.
+          if (inputMethod.id === ACCESSIBILITY_COMMON_IME_ID) {
+            return false;
+          }
+          return true;
+        })
+        .map(inputMethod => ({
+               id: inputMethod.id,
+               name: inputMethod.displayName,
+               searchTerms: inputMethod.tags,
+               disabledByPolicy: !!inputMethod.isProhibitedByPolicy
+             }));
   },
 
   /**
    * Add input methods.
+   * @param {!CustomEvent<!Set<string>>} e
    * @private
    */
-  onActionButtonTap_() {
-    this.inputMethodsToAdd_.forEach(id => {
+  onItemsAdded_(e) {
+    e.detail.forEach(id => {
       this.languageHelper.addInputMethod(id);
     });
     recordSettingChange();
-    this.$.dialog.close();
-  },
-
-  /**
-   * @param {!KeyboardEvent} e
-   * @private
-   */
-  onKeydown_(e) {
-    // Close dialog if 'esc' is pressed and the search box is already empty.
-    if (e.key === 'Escape' && !this.$.search.getValue().trim()) {
-      this.$.dialog.close();
-    } else if (e.key !== 'PageDown' && e.key !== 'PageUp') {
-      this.$.search.scrollIntoViewIfNeeded();
-    }
   },
 });
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/add_items_dialog.html b/chrome/browser/resources/settings/chromeos/os_languages_page/add_items_dialog.html
new file mode 100644
index 0000000..29e6399
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/add_items_dialog.html
@@ -0,0 +1,85 @@
+<!-- TODO(crbug.com/1201535): Move this component out of the os_languages_page
+     directory. -->
+<style include="settings-shared shared-style">
+  [slot=body] {
+    display: flex;
+    flex-direction: column;
+    height: 350px;
+    overflow: auto;
+  }
+
+  cr-search-field {
+    margin-bottom: 8px;
+  }
+
+  .label {
+    padding-bottom: 4px;
+    padding-top: 8px;
+  }
+
+  .list-item {
+    color: var(--cros-text-color-primary);
+    min-height: 36px;
+  }
+
+  cr-checkbox::part(label-container) {
+    white-space: nowrap;
+  }
+</style>
+
+<cr-dialog id="dialog" close-text="$i18n{close}" show-on-attach>
+  <div slot="title">[[header]]</div>
+  <div id="dialog-body" slot="body" scrollable>
+    <cr-search-field label="[[searchLabel]]" id="search"
+        clear-label="$i18n{clearSearch}" autofocus
+        on-search-changed="onSearchChanged_" on-keydown="onKeydown_">
+    </cr-search-field>
+    <template is="dom-if" if="[[showSuggestedList_]]">
+      <div id="suggested-items-label" class="label">
+        [[suggestedItemsLabel]]
+      </div>
+      <iron-list id="suggested-items-list" items="[[suggestedItems_]]"
+          scroll-target="dialog-body">
+        <template>
+          <cr-checkbox class="list-item no-outline"
+              checked="[[willAdd_(item.id, itemIdsToAdd_.size)]]"
+              tab-index="[[tabIndex]]" on-change="onCheckboxChange_">
+              [[item.name]]
+          </cr-checkbox>
+        </template>
+      </iron-list>
+    </template>
+    <template is="dom-if" if="[[showFilteredList_]">
+      <div id="filtered-items-label" class="label"
+          hidden="[[!showSuggestedList_]]">
+        [[allItemsLabel]]
+      </div>
+      <iron-list id="filtered-items-list" items="[[filteredItems_]]"
+          scroll-target="dialog-body">
+        <template>
+          <cr-checkbox-with-policy
+              class="list-item no-outline"
+              checked="[[willAdd_(item.id, itemIdsToAdd_.size)]]"
+              disabled="[[item.disabledByPolicy]]"
+              policy-tooltip="[[policyTooltip]]"
+              tab-index="[[tabIndex]]" on-change="onCheckboxChange_">
+            [[item.name]]
+          </cr-checkbox-with-policy>
+        </template>
+      </iron-list>
+    </template>
+    <div id="no-search-results" class="centered-message"
+        hidden="[[showFilteredList_]]">
+      $i18n{noSearchResults}
+    </div>
+  </div>
+  <div slot="button-container">
+    <cr-button class="cancel-button" on-click="onCancelButtonClick_">
+      $i18n{cancel}
+    </cr-button>
+    <cr-button class="action-button" disabled="[[disableActionButton_]]"
+        on-click="onActionButtonClick_">
+      $i18n{add}
+    </cr-button>
+  </div>
+</cr-dialog>
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/add_items_dialog.js b/chrome/browser/resources/settings/chromeos/os_languages_page/add_items_dialog.js
new file mode 100644
index 0000000..46363d1
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/add_items_dialog.js
@@ -0,0 +1,341 @@
+// 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.
+
+/**
+ * @fileoverview 'os-settings-add-items-dialog' is a dialog for adding an
+ * unordered set of items at a time. The component supports suggested items, as
+ * well as items being disabled by policy.
+ */
+import '//resources/cr_elements/cr_button/cr_button.m.js';
+import '//resources/cr_elements/cr_search_field/cr_search_field.js';
+import '//resources/cr_elements/cr_dialog/cr_dialog.m.js';
+import '//resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
+import '//resources/polymer/v3_0/iron-list/iron-list.js';
+import './cr_checkbox_with_policy.js';
+import './shared_style.js';
+import '../../settings_shared_css.js';
+
+import {CrScrollableBehavior, CrScrollableBehaviorInterface} from '//resources/cr_elements/cr_scrollable_behavior.m.js';
+import {FindShortcutBehavior, FindShortcutBehaviorInterface} from '//resources/cr_elements/find_shortcut_behavior.js';
+import {afterNextRender, html, mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+/**
+ * `id` must unique.
+ * `name` is the displayed name to the user.
+ * `searchTerms` are additional strings which will be matched when doing a text
+ * search.
+ * `disabledByPolicy` can be set to show that a given item is disabled by
+ * policy. These items will never appear as a suggestion.
+ * @typedef {!{id: string, name: string, searchTerms: !Array<string>,
+ * disabledByPolicy: boolean}}
+ */
+export let Item;
+
+/**
+ * @constructor
+ * @extends {PolymerElement}
+ * @implements {CrScrollableBehaviorInterface}
+ * @implements {FindShortcutBehaviorInterface}
+ */
+const OsSettingsAddItemsDialogElementBase = mixinBehaviors(
+    [CrScrollableBehavior, FindShortcutBehavior], PolymerElement);
+
+/** @polymer */
+class OsSettingsAddItemsDialogElement extends
+    OsSettingsAddItemsDialogElementBase {
+  static get is() {
+    return 'os-settings-add-items-dialog';
+  }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
+
+  static get properties() {
+    return {
+      /** @type {!Array<!Item>} */
+      items: {
+        type: Array,
+        value: [],
+      },
+
+      /**
+       * Item IDs to show in the "Suggested" section of the dialog.
+       * Any items in this array which are disabled by policy, or IDs which do
+       * not appear in the items array will be filtered out automatically.
+       * @type {!Array<!string>}
+       */
+      suggestedItemIds: {
+        type: Array,
+        value: [],
+      },
+
+      header: String,
+
+      searchLabel: String,
+
+      suggestedItemsLabel: String,
+
+      allItemsLabel: String,
+
+      policyTooltip: String,
+
+      /** @private */
+      lowercaseQueryString_: String,
+
+      /** @private {!Array<!Item>} */
+      filteredItems_: {
+        type: Array,
+        computed: 'getFilteredItems_(items.*, lowercaseQueryString_)',
+        value: [],
+      },
+
+      /** @private {!Set<string>} */
+      itemIdsToAdd_: {
+        type: Object,
+        value() {
+          return new Set();
+        },
+      },
+
+      /**
+       * Mapping from item ID to item for use in computing `suggestedItems_`.
+       * @private {!Map<string, !Item>}
+       */
+      itemIdsToItems_: {
+        type: Object,
+        computed: 'getItemIdsToItems_(items.*)',
+        value() {
+          return new Map();
+        },
+      },
+
+      /**
+       * All items are guaranteed to not be disabled by policy.
+       * @private {!Array<!Item>}
+       */
+      suggestedItems_: {
+        type: Array,
+        computed: 'getSuggestedItems_(suggestedItemIds.*, itemIdsToItems_)',
+        value: []
+      },
+
+      /** @private */
+      showSuggestedList_: {
+        type: Boolean,
+        computed: `shouldShowSuggestedList_(suggestedItems_.length,
+            lowercaseQueryString_)`,
+        value: false,
+      },
+
+      /** @private */
+      showFilteredList_: {
+        type: Boolean,
+        computed: 'shouldShowFilteredList_(filteredItems_.length)',
+        value: true,
+      },
+
+      disableActionButton_: {
+        type: Boolean,
+        computed: 'shouldDisableActionButton_(itemIdsToAdd_.size)',
+        value: true,
+      },
+    };
+  }
+
+  static get observers() {
+    return [
+      // The two observers below have all possible properties that could affect
+      // the scroll offset of the two lists as dependencies.
+      `updateSuggestedListScrollOffset_(showSuggestedList_,
+          suggestedItemsLabel)`,
+      `updateFilteredListScrollOffset_(showSuggestedList_,
+          suggestedItemsLabel, suggestedItems_.length, showFilteredList_)`
+    ];
+  }
+
+  // Override FindShortcutBehavior methods.
+  handleFindShortcut(_modalContextOpen) {
+    // Assumes this is the only open modal.
+    const searchInput = this.$.search.getSearchInput();
+    searchInput.scrollIntoView();
+    if (!this.searchInputHasFocus()) {
+      searchInput.focus();
+    }
+    return true;
+  }
+
+  // Override FindShortcutBehavior methods.
+  searchInputHasFocus() {
+    return this.$.search.getSearchInput() ===
+        this.$.search.shadowRoot.activeElement;
+  }
+
+  /**
+   * @param {!CustomEvent<string>} e
+   * @private
+   */
+  onSearchChanged_(e) {
+    this.lowercaseQueryString_ = e.detail.toLocaleLowerCase();
+  }
+
+  /**
+   * @param {!{model: !{item: !Item}, target: !Element}} e
+   * @private
+   */
+  onCheckboxChange_(e) {
+    const id = e.model.item.id;
+    if (e.target.checked) {
+      this.itemIdsToAdd_.add(id);
+    } else {
+      this.itemIdsToAdd_.delete(id);
+    }
+    // Polymer doesn't notify changes to set size.
+    this.notifyPath('itemIdsToAdd_.size');
+  }
+
+  /** @private */
+  onCancelButtonClick_() {
+    this.$.dialog.close();
+  }
+
+  /**
+   * @private
+   */
+  onActionButtonClick_() {
+    this.dispatchEvent(new CustomEvent('items-added', {
+      bubbles: true,
+      composed: true,
+      detail: this.itemIdsToAdd_,
+    }));
+    this.$.dialog.close();
+  }
+
+  /**
+   * @param {!KeyboardEvent} e
+   * @private
+   */
+  onKeydown_(e) {
+    // Close dialog if 'esc' is pressed and the search box is already empty.
+    if (e.key === 'Escape' && !this.$.search.getValue().trim()) {
+      this.$.dialog.close();
+    } else if (e.key !== 'PageDown' && e.key !== 'PageUp') {
+      this.$.search.scrollIntoView();
+    }
+  }
+
+  /**
+   * True if the user has chosen to add this item (checked its checkbox).
+   * @param {string} id
+   * @return {boolean}
+   * @private
+   */
+  willAdd_(id) {
+    return this.itemIdsToAdd_.has(id);
+  }
+
+  /**
+   * @return {!Map<string, !Item>}
+   * @private
+   */
+  getItemIdsToItems_() {
+    return new Map(this.items.map(item => [item.id, item]));
+  }
+
+  /**
+   * Returns whether a string matches the current search query.
+   * @param {string} string
+   * @return {boolean}
+   * @private
+   */
+  matchesSearchQuery_(string) {
+    return string.toLocaleLowerCase().includes(this.lowercaseQueryString_);
+  }
+
+  /**
+   * @return {!Array<!Item>}
+   * @private
+   */
+  getFilteredItems_() {
+    if (!this.lowercaseQueryString_) {
+      return this.items;
+    }
+
+    return this.items.filter(
+        item => this.matchesSearchQuery_(item.name) ||
+            item.searchTerms.some(term => this.matchesSearchQuery_(term)));
+  }
+
+  /**
+   * @return {!Array<!Item>}
+   * @private
+   */
+  getSuggestedItems_() {
+    return this.suggestedItemIds.map(id => this.itemIdsToItems_.get(id))
+        .filter(item => item !== undefined && !item.disabledByPolicy);
+  }
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  shouldShowSuggestedList_() {
+    return this.suggestedItems_.length > 0 && !this.lowercaseQueryString_;
+  }
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  shouldShowFilteredList_() {
+    return this.filteredItems_.length > 0;
+  }
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  shouldDisableActionButton_() {
+    return !this.itemIdsToAdd_.size;
+  }
+
+  /**
+   * @private
+   */
+  updateSuggestedListScrollOffset_() {
+    afterNextRender(this, () => {
+      if (!this.showSuggestedList_) {
+        return;
+      }
+      // Because #suggestedItemsList is not statically created (as it is
+      // within a <template is="dom-if">), we can't use this.$ here.
+      const list = /** @type {!IronListElement|null} */ (
+          this.shadowRoot.getElementById('suggested-items-list'));
+      if (list === null) {
+        return;
+      }
+      list.scrollOffset = list.offsetTop;
+    });
+  }
+
+  /**
+   * @private
+   */
+  updateFilteredListScrollOffset_() {
+    afterNextRender(this, () => {
+      if (!this.showFilteredList_) {
+        return;
+      }
+      const list = /** @type {!IronListElement|null} */ (
+          this.shadowRoot.getElementById('filtered-items-list'));
+      if (list === null) {
+        return;
+      }
+      list.scrollOffset = list.offsetTop;
+    });
+  }
+}
+
+customElements.define(
+    OsSettingsAddItemsDialogElement.is, OsSettingsAddItemsDialogElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/add_spellcheck_languages_dialog.html b/chrome/browser/resources/settings/chromeos/os_languages_page/add_spellcheck_languages_dialog.html
index b5d8e4ba..79d1374b 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/add_spellcheck_languages_dialog.html
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/add_spellcheck_languages_dialog.html
@@ -1,112 +1,15 @@
-<!-- TODO(crbug.com/1201535): Refactor this and os_add_languages_dialog to share
-     code. -->
+<!-- TODO(crbug.com/1201535): Move everything to the parent element
+     (<os-settings-languages-page>), as this element is trivial. -->
 
-<style include="settings-shared iron-flex shared-style">
-  #dialogBody {
-    display: flex;
-    flex-direction: column;
-    height: 336px;
-    overflow: auto;
-  }
-
-  cr-search-field {
-    margin-bottom: 8px;
-  }
-
-  .label {
-    padding-bottom: 4px;
-    padding-top: 8px;
-  }
-
-  .list-item {
-    color: var(--cros-text-color-primary);
-    left: 0;
-    min-height: 36px;
-    right: 0;
-    width: inherit;
-  }
-
-  /* Allows the first focused list-item's (of any iron-list) applied
-   * ink droplet to show entirely. */
-  .list-item:first-of-type {
-    margin-top: 4px;
-  }
-
-  cr-checkbox::part(label-container) {
-    white-space: nowrap;
-  }
-
-  cr-dialog [slot=body] {
-    padding-inline-end: 0;
-    padding-inline-start: 0;
-  }
-
-  /* Adds spacing to elements that have the same width as the dialog.
-   * This is added in lieu of adding padding to the cr-dialog to show
-   * the ink droplets applied on focused checkboxes entirely. */
-  cr-dialog [slot=body] .is-width-of-dialog {
-    margin-inline-end: var(--dialog-horizontal-padding);
-    margin-inline-start: var(--dialog-horizontal-padding);
-  }
-</style>
-
-<cr-dialog id="dialog" close-text="$i18n{close}" show-on-attach>
-  <div slot="title">$i18n{addSpellCheckLanguagesTitle}</div>
-  <div id="dialogBody" slot="body" scrollable>
-    <cr-search-field label="$i18n{searchSpellCheckLanguagesLabel}" id="search"
-        on-search-changed="onSearchChanged_" on-keydown="onKeydown_"
-        class="is-width-of-dialog"
-        clear-label="$i18n{clearSearch}" autofocus>
-    </cr-search-field>
-    <template is="dom-if" if="[[showSuggestedList_]]">
-      <div id="suggestedLanguages">
-        <div class="label is-width-of-dialog">
-          $i18n{suggestedSpellcheckLanguages}
-        </div>
-        <iron-list items="[[suggestedLanguages_]]">
-          <template>
-            <cr-checkbox class="list-item no-outline is-width-of-dialog"
-                checked="[[willAdd_(item.language.code,
-                    languageCodesToAdd_.size)]]"
-                on-change="onCheckboxChange_" tab-index="[[tabIndex]]">
-              [[getDisplayText_(item.language)]]
-            </cr-checkbox>
-          </template>
-        </iron-list>
-      </div>
-    </template>
-    <div id="allLanguages">
-      <div class="label is-width-of-dialog" hidden="[[!showSuggestedList_]]">
-        $i18n{allSpellcheckLanguages}
-      </div>
-      <template is="dom-if" if="[[languagesExist_]]">
-        <iron-list items="[[allLanguages_]]">
-          <template>
-            <cr-checkbox-with-policy
-                class="list-item no-outline is-width-of-dialog"
-                checked="[[willAdd_(item.language.code,
-                    languageCodesToAdd_.size)]]"
-                disabled="[[item.isManaged]]"
-                policy-tooltip="$i18n{spellCheckLanguageNotAllowed}"
-                on-change="onCheckboxChange_" tab-index="[[tabIndex]]">
-              [[getDisplayText_(item.language)]]
-            </cr-checkbox-with-policy>
-          </template>
-        </iron-list>
-      </template>
-    </div>
-    <div id="no-search-results" class="centered-message"
-        hidden="[[languagesExist_]]">
-      $i18n{noSearchResults}
-    </div>
-  </div>
-  <div slot="button-container">
-    <cr-button class="cancel-button" on-click="onCancelButtonClick_">
-      $i18n{cancel}
-    </cr-button>
-    <cr-button class="action-button" on-click="onActionButtonClick_"
-        disabled="[[disableActionButton_]]">
-      $i18n{add}
-    </cr-button>
-  </div>
-</cr-dialog>
+<os-settings-add-items-dialog
+    items="[[getAllLanguages_(languages.spellCheckOffLanguages.*)]]"
+    suggested-item-ids="[[getSuggestedLanguageCodes_(
+        languages.spellCheckOffLanguages.*, languages.enabled.*,
+        languages.inputMethods.enabled.*)]]"
+    header="$i18n{addSpellCheckLanguagesTitle}"
+    search-label="$i18n{searchSpellCheckLanguagesLabel}"
+    suggested-items-label="$i18n{suggestedSpellcheckLanguages}"
+    all-items-label="$i18n{allSpellcheckLanguages}"
+    policy-tooltip="$i18n{spellCheckLanguageNotAllowed}"
+    on-items-added="onItemsAdded_">
+</os-settings-add-items-dialog>
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/add_spellcheck_languages_dialog.js b/chrome/browser/resources/settings/chromeos/os_languages_page/add_spellcheck_languages_dialog.js
index 6fffe7d..101966da 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/add_spellcheck_languages_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/add_spellcheck_languages_dialog.js
@@ -6,22 +6,12 @@
  * @fileoverview 'os-settings-add-spellcheck-language-dialog' is a dialog for
  * adding spell check languages.
  */
-import '//resources/cr_elements/cr_button/cr_button.m.js';
-import '//resources/cr_elements/cr_search_field/cr_search_field.js';
-import '//resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import '//resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
-import '//resources/polymer/v3_0/iron-list/iron-list.js';
-import './cr_checkbox_with_policy.js';
-import './shared_style.js';
-import '../../settings_shared_css.js';
-
-import {CrScrollableBehavior} from '//resources/cr_elements/cr_scrollable_behavior.m.js';
-import {FindShortcutBehavior} from '//resources/cr_elements/find_shortcut_behavior.js';
 import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {recordSettingChange} from '../metrics_recorder.js';
 import {PrefsBehavior} from '../prefs_behavior.js';
 
+import {Item} from './add_items_dialog.js';
 import {LanguageHelper, LanguagesModel, SpellCheckLanguageState} from './languages_types.js';
 
 Polymer({
@@ -30,9 +20,7 @@
   _template: html`{__html_template__}`,
 
   behaviors: [
-    CrScrollableBehavior,
     PrefsBehavior,
-    FindShortcutBehavior,
   ],
 
   properties: {
@@ -47,153 +35,41 @@
 
     /** @type {!LanguageHelper} */
     languageHelper: Object,
-
-    /** @private {!Set<string>} */
-    languageCodesToAdd_: {
-      type: Object,
-      value() {
-        return new Set();
-      },
-    },
-
-    /** @private {!Array<!SpellCheckLanguageState>} */
-    allLanguages_: {
-      type: Array,
-      value: [],
-      computed: `getAllLanguages_(languages.spellCheckOffLanguages.*,
-          lowercaseQuery_)`,
-    },
-
-    /** @private */
-    languagesExist_: {
-      type: Boolean,
-      value: false,
-      computed: 'computeLanguagesExist_(allLanguages_.length)',
-    },
-
-    /** @private {!Array<!SpellCheckLanguageState>} */
-    suggestedLanguages_: {
-      type: Array,
-      value: [],
-      computed: `getSuggestedLanguages_(languages.spellCheckOffLanguages.*,
-          languages.enabled.*, languages.inputMethods.enabled.*)`,
-    },
-
-    /** @private */
-    showSuggestedList_: {
-      type: Boolean,
-      value: false,
-      computed: `shouldShowSuggestedList_(suggestedLanguages_, lowercaseQuery_,
-          languagesExist_)`,
-    },
-
-    /** @private */
-    disableActionButton_: {
-      type: Boolean,
-      value: true,
-      computed: 'shouldDisableActionButton_(languageCodesToAdd_.size)',
-    },
-
-    /** @private */
-    lowercaseQuery_: {
-      type: String,
-      value: '',
-    },
-  },
-
-  // Override FindShortcutBehavior methods.
-  handleFindShortcut(modalContextOpen) {
-    // Assumes this is the only open modal.
-    const searchInput = this.$.search.getSearchInput();
-    searchInput.scrollIntoViewIfNeeded();
-    if (!this.searchInputHasFocus()) {
-      searchInput.focus();
-    }
-    return true;
-  },
-
-  // Override FindShortcutBehavior methods.
-  searchInputHasFocus() {
-    return this.$.search.getSearchInput() ===
-        this.$.search.shadowRoot.activeElement;
-  },
-
-  /**
-   * @param {!CustomEvent<string>} e
-   * @private
-   */
-  onSearchChanged_(e) {
-    this.lowercaseQuery_ = e.detail.toLocaleLowerCase();
-  },
-
-  /**
-   * True if the user has chosen to add this spell check language (checked its
-   * checkbox).
-   * @param {string} code
-   * @return {boolean}
-   * @private
-   */
-  willAdd_(code) {
-    return this.languageCodesToAdd_.has(code);
-  },
-
-  /**
-   * Handler for an input method checkbox.
-   * @param {!{model: !{item: SpellCheckLanguageState},
-   *           target: !Element}} e
-   * @private
-   */
-  onCheckboxChange_(e) {
-    const languageCode = e.model.item.language.code;
-    if (e.target.checked) {
-      this.languageCodesToAdd_.add(languageCode);
-    } else {
-      this.languageCodesToAdd_.delete(languageCode);
-    }
-    // Polymer doesn't notify changes to set size.
-    this.notifyPath('languageCodesToAdd_.size');
-  },
-
-  /**
-   * @return {boolean}
-   * @private
-   */
-  shouldShowSuggestedList_() {
-    return this.suggestedLanguages_.length > 0 && !this.lowercaseQuery_ &&
-        this.languagesExist_;
   },
 
   /**
    * Get suggested languages based on enabled languages and input methods.
-   * @return {!Array<!SpellCheckLanguageState>}
+   * @return {!Array<string>}
    * @private
    */
-  getSuggestedLanguages_() {
+  getSuggestedLanguageCodes_() {
     const languageCodes = new Set([
       ...this.languages.inputMethods.enabled.flatMap(
           inputMethod => inputMethod.languageCodes),
       ...this.languageHelper.getEnabledLanguageCodes(),
     ]);
-    return this.languages.spellCheckOffLanguages.filter(
-        spellCheckLanguage =>
-            languageCodes.has(spellCheckLanguage.language.code) &&
-            !spellCheckLanguage.isManaged);
+    return this.languages.spellCheckOffLanguages
+        .map(spellCheckLang => spellCheckLang.language.code)
+        .filter(code => languageCodes.has(code));
   },
 
   /**
    * Get the list of languages used for the "all languages" section, filtering
    * based on the current search query.
-   * @return {!Array<!SpellCheckLanguageState>}
+   * @return {!Array<!Item>}
    * @private
    */
   getAllLanguages_() {
-    return this.languages.spellCheckOffLanguages.filter(langState => {
-      const language = langState.language;
-      return language.displayName.toLowerCase().includes(
-                 this.lowercaseQuery_) ||
-          language.nativeDisplayName.toLowerCase().includes(
-              this.lowercaseQuery_);
-    });
+    return this.languages.spellCheckOffLanguages.map(
+        spellCheckLang => ({
+          id: spellCheckLang.language.code,
+          name: this.getDisplayText_(spellCheckLang.language),
+          searchTerms: [
+            spellCheckLang.language.displayName,
+            spellCheckLang.language.nativeDisplayName
+          ],
+          disabledByPolicy: spellCheckLang.isManaged,
+        }));
   },
 
   /**
@@ -211,48 +87,14 @@
   },
 
   /**
-   * @return {boolean}
-   * @private
-   */
-  shouldDisableActionButton_() {
-    return !this.languageCodesToAdd_.size;
-  },
-
-  /** @private */
-  onCancelButtonClick_() {
-    this.$.dialog.close();
-  },
-
-  /**
    * Add spell check languages.
+   * @param {!CustomEvent<!Set<string>>} e
    * @private
    */
-  onActionButtonClick_() {
-    this.languageCodesToAdd_.forEach(code => {
+  onItemsAdded_(e) {
+    e.detail.forEach(code => {
       this.languageHelper.toggleSpellCheck(code, true);
     });
     recordSettingChange();
-    this.$.dialog.close();
-  },
-
-  /**
-   * @param {!KeyboardEvent} e
-   * @private
-   */
-  onKeydown_(e) {
-    // Close dialog if 'esc' is pressed and the search box is already empty.
-    if (e.key === 'Escape' && !this.$.search.getValue().trim()) {
-      this.$.dialog.close();
-    } else if (e.key !== 'PageDown' && e.key !== 'PageUp') {
-      this.$.search.scrollIntoViewIfNeeded();
-    }
-  },
-
-  /**
-   * @return {boolean}
-   * @private
-   */
-  computeLanguagesExist_() {
-    return !!this.allLanguages_.length;
   },
 });
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.html b/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.html
index f425308b..14dcd3f 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.html
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.html
@@ -1,58 +1,10 @@
-<style include="settings-shared shared-style">
-  #dialog-body {
-    display: flex;
-    flex-direction: column;
-    height: 350px;
-    overflow: auto;
-  }
-
-  cr-search-field {
-    margin-bottom: 16px;
-  }
-
-  iron-list {
-    flex: 1;
-  }
-
-  cr-checkbox::part(label-container) {
-    white-space: nowrap;
-  }
-
-  .list-item {
-    min-height: 36px;
-  }
-</style>
-<cr-dialog id="dialog" close-text="$i18n{close}">
-  <div slot="title">$i18n{addLanguagesDialogTitle}</div>
-  <div id="dialog-body" slot="body" scrollable>
-    <cr-search-field label="$i18n{searchLanguages}" id="search"
-        on-search-changed="onSearchChanged_" on-keydown="onKeydown_"
-        clear-label="$i18n{clearSearch}" autofocus>
-    </cr-search-field>
-    <iron-list scroll-target="[[$$('[slot=body]')]]"
-        items="[[displayedLanguages_]]"
-        hidden$="[[displayedLanguagesEmpty_]]">
-      <template>
-        <cr-checkbox class="list-item no-outline"
-            checked="[[willAdd_(item.code)]]" tab-index="[[tabIndex]]"
-            title$="[[item.nativeDisplayName]]"
-            on-change="onLanguageCheckboxChange_">
-          [[getDisplayText_(item)]]
-        </cr-checkbox>
-      </template>
-    </iron-list>
-    <div id="no-search-results" class="centered-message"
-        hidden$="[[!displayedLanguagesEmpty_]]">
-      $i18n{noSearchResults}
-    </div>
-  </div>
-  <div slot="button-container">
-    <cr-button class="cancel-button" on-click="onCancelButtonTap_">
-      $i18n{cancel}
-    </cr-button>
-    <cr-button class="action-button" on-click="onActionButtonTap_"
-        disabled="[[disableActionButton_]]">
-      $i18n{add}
-    </cr-button>
-  </div>
-</cr-dialog>
+<!-- TODO(crbug.com/1201535): Move everything to the parent element
+     (<os-settings-input-page>), as this element is trivial. -->
+<!-- Note: We currently don't display any "suggested items", nor do we
+      show the user languages prohibited by policy. -->
+<os-settings-add-items-dialog
+    items="[[getLanguages_(languages.supported, languages.enabled.*)]]"
+    header="$i18n{addLanguagesDialogTitle}"
+    search-label="$i18n{searchLanguages}"
+    on-items-added="onItemsAdded_">
+</os-settings-add-items-dialog>
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.js b/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.js
index 9ec0958f..ec4c75f 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.js
@@ -6,32 +6,15 @@
  * @fileoverview 'os-settings-add-languages-dialog' is a dialog for enabling
  * languages.
  */
-import '//resources/cr_elements/cr_button/cr_button.m.js';
-import '//resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
-import '//resources/cr_elements/cr_search_field/cr_search_field.js';
-import '//resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import '//resources/cr_elements/shared_vars_css.m.js';
-import '//resources/polymer/v3_0/iron-list/iron-list.js';
-import './shared_style.js';
-import './languages.js';
-import '../../settings_shared_css.js';
-
-import {CrScrollableBehavior} from '//resources/cr_elements/cr_scrollable_behavior.m.js';
-import {FindShortcutBehavior} from '//resources/cr_elements/find_shortcut_behavior.js';
-import {loadTimeData} from '//resources/js/load_time_data.m.js';
 import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {Item} from './add_items_dialog.js';
 import {LanguageHelper, LanguagesModel} from './languages_types.js';
 
 Polymer({
   _template: html`{__html_template__}`,
   is: 'os-settings-add-languages-dialog',
 
-  behaviors: [
-    CrScrollableBehavior,
-    FindShortcutBehavior,
-  ],
-
   properties: {
     /** @type {!LanguagesModel|undefined} */
     languages: {
@@ -39,93 +22,23 @@
       notify: true,
     },
 
-    /** @private {!Array<!chrome.languageSettingsPrivate.Language>} */
-    displayedLanguages_: {
-      type: Array,
-      computed: `getLanguages_(languages.supported, languages.enabled.*,
-          filterValue_)`,
-    },
-
-    /** @private {boolean} */
-    displayedLanguagesEmpty_: {
-      type: Boolean,
-      computed: 'isZero_(displayedLanguages_.length)',
-    },
-
     /** @type {!LanguageHelper} */
     languageHelper: Object,
-
-    /** @private {!Set<string>} */
-    languagesToAdd_: {
-      type: Object,
-      value() {
-        return new Set();
-      },
-    },
-
-    /** @private */
-    disableActionButton_: {
-      type: Boolean,
-      value: true,
-    },
-
-    /** @private */
-    filterValue_: {
-      type: String,
-      value: '',
-    },
-  },
-
-  /** @override */
-  attached() {
-    this.$.dialog.showModal();
-  },
-
-  // Override FindShortcutBehavior methods.
-  handleFindShortcut(modalContextOpen) {
-    // Assumes this is the only open modal.
-    const searchInput = this.$.search.getSearchInput();
-    searchInput.scrollIntoViewIfNeeded();
-    if (!this.searchInputHasFocus()) {
-      searchInput.focus();
-    }
-    return true;
-  },
-
-  // Override FindShortcutBehavior methods.
-  searchInputHasFocus() {
-    return this.$.search.getSearchInput() ===
-        this.$.search.shadowRoot.activeElement;
   },
 
   /**
-   * @param {!CustomEvent<string>} e
-   * @private
-   */
-  onSearchChanged_(e) {
-    this.filterValue_ = e.detail;
-  },
-
-  /**
-   * @return {!Array<!chrome.languageSettingsPrivate.Language>} A list of
-   *     languages to be displayed.
+   * @return {!Array<!Item>} A list of languages to be displayed in the dialog.
    * @private
    */
   getLanguages_() {
-    const filterValue =
-        this.filterValue_ ? this.filterValue_.toLowerCase() : null;
-    return this.languages.supported.filter(language => {
-      if (!this.languageHelper.canEnableLanguage(language)) {
-        return false;
-      }
-
-      if (filterValue === null) {
-        return true;
-      }
-
-      return language.displayName.toLowerCase().includes(filterValue) ||
-          language.nativeDisplayName.toLowerCase().includes(filterValue);
-    });
+    return this.languages.supported
+        .filter(language => this.languageHelper.canEnableLanguage(language))
+        .map(language => ({
+               id: language.code,
+               name: this.getDisplayText_(language),
+               searchTerms: [language.displayName, language.nativeDisplayName],
+               disabledByPolicy: false,
+             }));
   },
 
   /**
@@ -143,71 +56,13 @@
   },
 
   /**
-   * True if the user has chosen to add this language (checked its checkbox).
-   * @param {string} languageCode
-   * @return {boolean}
-   * @private
-   */
-  willAdd_(languageCode) {
-    return this.languagesToAdd_.has(languageCode);
-  },
-
-  /**
-   * Handler for checking or unchecking a language item.
-   * @param {!{model: !{item: !chrome.languageSettingsPrivate.Language},
-   *           target: !Element}} e
-   * @private
-   */
-  onLanguageCheckboxChange_(e) {
-    // Add or remove the item to the Set. No need to worry about data binding:
-    // willAdd_ is called to initialize the checkbox state (in case the
-    // iron-list re-uses a previous checkbox), and the checkbox can only be
-    // changed after that by user action.
-    const language = e.model.item;
-    if (e.target.checked) {
-      this.languagesToAdd_.add(language.code);
-    } else {
-      this.languagesToAdd_.delete(language.code);
-    }
-
-    this.disableActionButton_ = !this.languagesToAdd_.size;
-  },
-
-  /** @private */
-  onCancelButtonTap_() {
-    this.$.dialog.close();
-  },
-
-  /**
    * Enables the checked languages.
+   * @param {!CustomEvent<!Set<string>>} e
    * @private
    */
-  onActionButtonTap_() {
-    this.$.dialog.close();
-    this.languagesToAdd_.forEach(languageCode => {
+  onItemsAdded_(e) {
+    e.detail.forEach(languageCode => {
       this.languageHelper.enableLanguage(languageCode);
     });
   },
-
-  /**
-   * @param {!KeyboardEvent} e
-   * @private
-   */
-  onKeydown_(e) {
-    // Close dialog if 'esc' is pressed and the search box is already empty.
-    if (e.key === 'Escape' && !this.$.search.getValue().trim()) {
-      this.$.dialog.close();
-    } else if (e.key !== 'PageDown' && e.key !== 'PageUp') {
-      this.$.search.scrollIntoViewIfNeeded();
-    }
-  },
-
-  /**
-   * @param {number} num
-   * @return {boolean}
-   * @private
-   */
-  isZero_(num) {
-    return num === 0;
-  },
 });
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_kk.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_kk.xtb
index 9f09c60..83a137a 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_kk.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_kk.xtb
@@ -670,6 +670,7 @@
 <translation id="4758061975920522644">Тек кескін бөлісу</translation>
 <translation id="4759238208242260848">Жүктеп алынғандар</translation>
 <translation id="4763480195061959176">бейне</translation>
+<translation id="4766313118839197559">Құпия сөздер осы құрылғыдағы Құпия сөз менеджеріне сақталады.</translation>
 <translation id="4766678251456904326">Құрылғыға аккаунт енгізу</translation>
 <translation id="4791358705705538979">Интернет арқылы тапсырмаларды орындауға (мысалы, төлем жасау) көмектеседі.</translation>
 <translation id="4794291718671962615">(<ph name="MEGABYTES" />) <ph name="URL" /></translation>
@@ -928,6 +929,7 @@
 <translation id="6162892189396105610">Chrome браузері сіз кіруіңіз мүмкін деп санайтын беттерді алдын ала жүктейді.</translation>
 <translation id="6186394685773237175">Ешқандай құпия сөз ұрланбаған.</translation>
 <translation id="6192907950379606605">Сурет сипаттамаларын алу</translation>
+<translation id="6196315980958524839">Құпия сөздер осы құрылғыдағы Google Құпия сөз менеджеріне сақталады.</translation>
 <translation id="620197886010707372"><ph name="APPNAME" /> қолданбасы Google Play арқылы ашылсын ба?</translation>
 <translation id="6203593061661911168">Жүктеп алу Wi-Fi желісіне қосылғанда басталады.</translation>
 <translation id="6210748933810148297"><ph name="EMAIL" /> емес пе?</translation>
@@ -1258,6 +1260,7 @@
 <translation id="7961015016161918242">Ешқашан</translation>
 <translation id="7961926449547174351">Жадты пайдалану рұқсатын өшірдіңіз, оны қосу үшін параметрлерге өтіңіз.</translation>
 <translation id="7963646190083259054">Жеткізуші:</translation>
+<translation id="7965838025086216108">Сақталған құпия сөздерді кез келген құрылғыда пайдалана аласыз. Олар <ph name="ACCOUNT" /> аккаунтына арналған Google Құпия сөз менеджеріне сақталады.</translation>
 <translation id="7968014550143838305">Оқу тізіміне енгізілді.</translation>
 <translation id="7971136598759319605">1 күн бұрын қосылған.</translation>
 <translation id="7975379999046275268">Бетті алдын ала қарау <ph name="BEGIN_NEW" />Жаңа<ph name="END_NEW" /></translation>
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc b/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc
index 4407d32..03c87ed 100644
--- a/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc
+++ b/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc
@@ -58,9 +58,9 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/services/app_service/public/mojom/types.mojom-shared.h"
diff --git a/chrome/browser/ui/app_list/arc/arc_app_test.cc b/chrome/browser/ui/app_list/arc/arc_app_test.cc
index 9199d5ad..204cccc 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_test.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_test.cc
@@ -28,7 +28,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/arc/test/fake_intent_helper_host.h"
 #include "components/arc/test/fake_intent_helper_instance.h"
diff --git a/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc
index c78c3e7..5ddc9c6 100644
--- a/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc
+++ b/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc
@@ -40,9 +40,9 @@
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/crx_file/id_util.h"
 #include "components/services/app_service/public/cpp/app_types.h"
diff --git a/chrome/browser/ui/app_list/search/games/game_provider_unittest.cc b/chrome/browser/ui/app_list/search/games/game_provider_unittest.cc
index e124546..cbf12999 100644
--- a/chrome/browser/ui/app_list/search/games/game_provider_unittest.cc
+++ b/chrome/browser/ui/app_list/search/games/game_provider_unittest.cc
@@ -18,6 +18,7 @@
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 namespace app_list {
 namespace {
@@ -35,7 +36,7 @@
       std::make_unique<apps::GameExtras>(
           absl::make_optional(std::vector<std::u16string>({u"A", u"B", u"C"})),
           u"SourceName", u"TestGamePublisher",
-          base::FilePath("/icons/test.png")));
+          base::FilePath("/icons/test.png"), GURL("https://game.com/game")));
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/app_list/search/games/game_result.cc b/chrome/browser/ui/app_list/search/games/game_result.cc
index e8c6a9d..7e4deadd 100644
--- a/chrome/browser/ui/app_list/search/games/game_result.cc
+++ b/chrome/browser/ui/app_list/search/games/game_result.cc
@@ -45,13 +45,6 @@
 constexpr char16_t kDetailsDelimiter[] = u" - ";
 constexpr char16_t kA11yDelimiter[] = u", ";
 
-// TODO(crbug.com/1305880): Replace with launch URL once finalized.
-constexpr char kLaunchUrlPrefix[] = "https://todo.com?game=";
-
-GURL LaunchUrlFromId(const std::string& id) {
-  return GURL(base::StrCat({kLaunchUrlPrefix, id}));
-}
-
 bool IsDarkModeEnabled() {
   // TODO(crbug.com/1258415): Simplify this logic once the productivity launcher
   // is launched.
@@ -79,7 +72,7 @@
                        const std::u16string& query)
     : profile_(profile),
       list_controller_(list_controller),
-      launch_url_(LaunchUrlFromId(game.GetAppId())) {
+      launch_url_(game.GetSourceExtras()->AsGameExtras()->GetDeeplinkUrl()) {
   DCHECK(profile);
   DCHECK(list_controller);
   DCHECK(app_discovery_service);
diff --git a/chrome/browser/ui/app_list/search/games/game_result_unittest.cc b/chrome/browser/ui/app_list/search/games/game_result_unittest.cc
index ef93d60..341566f2 100644
--- a/chrome/browser/ui/app_list/search/games/game_result_unittest.cc
+++ b/chrome/browser/ui/app_list/search/games/game_result_unittest.cc
@@ -20,6 +20,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 
 namespace app_list {
 
@@ -43,7 +44,7 @@
       std::make_unique<apps::GameExtras>(
           absl::make_optional(std::vector<std::u16string>({u"A", u"B", u"C"})),
           u"SourceName", u"TestGamePublisher",
-          base::FilePath("/icons/test.png")));
+          base::FilePath("/icons/test.png"), GURL("https://game.com/game")));
 
   GameResult result(profile_.get(), &list_controller_, app_discovery_service,
                     apps_result, 0.6, u"SomeGame");
@@ -71,7 +72,8 @@
       apps::AppSource::kGames, "12345", u"Title",
       std::make_unique<apps::GameExtras>(
           absl::make_optional(std::vector<std::u16string>({})), u"SourceName",
-          u"TestGamePublisher", base::FilePath("/icons/test.png")));
+          u"TestGamePublisher", base::FilePath("/icons/test.png"),
+          GURL("https://game.com/game")));
 
   GameResult result1(profile_.get(), &list_controller_, app_discovery_service,
                      apps_result1, 0.6, u"SomeGame");
@@ -80,9 +82,9 @@
 
   apps::Result apps_result2(
       apps::AppSource::kGames, "12345", u"Title",
-      std::make_unique<apps::GameExtras>(absl::nullopt, u"SourceName",
-                                         u"TestGamePublisher",
-                                         base::FilePath("/icons/test.png")));
+      std::make_unique<apps::GameExtras>(
+          absl::nullopt, u"SourceName", u"TestGamePublisher",
+          base::FilePath("/icons/test.png"), GURL("https://game.com/game")));
 
   GameResult result2(profile_.get(), &list_controller_, app_discovery_service,
                      apps_result1, 0.6, u"SomeGame");
diff --git a/chrome/browser/ui/ash/assistant/assistant_state_client_unittest.cc b/chrome/browser/ui/ash/assistant/assistant_state_client_unittest.cc
index a5e6211..8360b514 100644
--- a/chrome/browser/ui/ash/assistant/assistant_state_client_unittest.cc
+++ b/chrome/browser/ui/ash/assistant/assistant_state_client_unittest.cc
@@ -16,7 +16,7 @@
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
 #include "chrome/test/base/chrome_ash_test_base.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
index 8c92004..97961309 100644
--- a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
+++ b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
@@ -122,7 +122,7 @@
 #include "chrome/test/base/test_browser_window_aura.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/account_id/account_id.h"
 #include "components/app_constants/constants.h"
@@ -533,13 +533,8 @@
   virtual bool StartWebAppProviderForMainProfile() const { return true; }
 
   void StartWebAppProvider(Profile* profile) {
-    auto system_web_app_manager =
-        std::make_unique<web_app::TestSystemWebAppManager>(profile);
-
-    auto* provider = web_app::FakeWebAppProvider::Get(profile);
-    provider->SetSystemWebAppManager(std::move(system_web_app_manager));
-    provider->SetRunSubsystemStartupTasks(true);
-    provider->Start();
+    web_app::FakeWebAppProvider::Get(profile)->SetDefaultFakeSubsystems();
+    web_app::test::AwaitStartWebAppProviderAndSubsystems(profile);
   }
 
   ui::BaseWindow* GetLastActiveWindowForItemController(
@@ -1717,14 +1712,7 @@
   EXPECT_EQ("Chrome, Play Store, Android Settings", GetPinnedAppStatus());
 }
 
-// crbug.com/1312611 Test Failing on linux-cfm-rel
-#if BUILDFLAG(IS_LINUX)
-#define MAYBE_ArcAppPinCrossPlatformWorkflow \
-  DISABLED_ArcAppPinCrossPlatformWorkflow
-#else
-#define MAYBE_ArcAppPinCrossPlatformWorkflow ArcAppPinCrossPlatformWorkflow
-#endif
-TEST_F(ChromeShelfControllerWithArcTest, MAYBE_ArcAppPinCrossPlatformWorkflow) {
+TEST_F(ChromeShelfControllerWithArcTest, ArcAppPinCrossPlatformWorkflow) {
   // Work on ARC disabled platform first.
   const std::string arc_app_id1 =
       ArcAppTest::GetAppId(*arc_test_.fake_apps()[0]);
@@ -1738,6 +1726,7 @@
   extension_service_->AddExtension(extension1_.get());
   extension_service_->AddExtension(extension2_.get());
   AddWebApp(web_app::kGmailAppId);
+  app_service_test().FlushMojoCalls();
   app_service_test().WaitForAppService();
 
   // extension 1, 3 are pinned by user
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 ce0a716e..a812923 100644
--- a/chrome/browser/ui/ash/shelf/shelf_context_menu_unittest.cc
+++ b/chrome/browser/ui/ash/shelf/shelf_context_menu_unittest.cc
@@ -51,9 +51,9 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/chrome_ash_test_base.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/exo/shell_surface_util.h"
 #include "components/prefs/pref_service.h"
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 536c7df..820f44a 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,9 +6,12 @@
 
 #include "base/callback_helpers.h"
 #include "base/logging.h"
+#include "chrome/browser/ash/crostini/crostini_pref_names.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/prefs/pref_service.h"
 #include "content/public/browser/network_service_instance.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
@@ -53,7 +56,9 @@
     state_ = State::CONFIGURING;
     OnStateChanged();
 
-    ansible_management_service_->ConfigureDefaultContainer(base::DoNothing());
+    ansible_management_service_->ConfigureContainer(
+        crostini::ContainerId::GetDefault(),
+        default_container_ansible_filepath_, base::DoNothing());
     return false;
   }
   DCHECK_EQ(state_, State::ERROR);
@@ -74,10 +79,11 @@
   }
 }
 
-void CrostiniAnsibleSoftwareConfigView::
-    OnAnsibleSoftwareConfigurationStarted() {}
+void CrostiniAnsibleSoftwareConfigView::OnAnsibleSoftwareConfigurationStarted(
+    const crostini::ContainerId& container_id) {}
 
 void CrostiniAnsibleSoftwareConfigView::OnAnsibleSoftwareConfigurationFinished(
+    const crostini::ContainerId& container_id,
     bool success) {
   DCHECK_EQ(state_, State::CONFIGURING);
 
@@ -136,6 +142,9 @@
   progress_bar->SetValue(-1);
   progress_bar_ = AddChildView(std::move(progress_bar));
 
+  default_container_ansible_filepath_ = profile->GetPrefs()->GetFilePath(
+      crostini::prefs::kCrostiniAnsiblePlaybookFilePath);
+
   OnStateChanged();
 }
 
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 afbd0c8..3c474c88 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
@@ -32,8 +32,11 @@
   bool Accept() override;
 
   // crostini::AnsibleManagementService::Observer:
-  void OnAnsibleSoftwareConfigurationStarted() override;
-  void OnAnsibleSoftwareConfigurationFinished(bool success) override;
+  void OnAnsibleSoftwareConfigurationStarted(
+      const crostini::ContainerId& container_id) override;
+  void OnAnsibleSoftwareConfigurationFinished(
+      const crostini::ContainerId& container_id,
+      bool success) override;
 
   std::u16string GetSubtextLabelStringForTesting();
 
@@ -58,6 +61,7 @@
 
   views::Label* subtext_label_ = nullptr;
   views::ProgressBar* progress_bar_ = nullptr;
+  base::FilePath default_container_ansible_filepath_;
 
   ~CrostiniAnsibleSoftwareConfigView() override;
 };
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 386ae36..bb8d31b 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
@@ -5,13 +5,17 @@
 #include "chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.h"
 
 #include "base/callback_helpers.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"
+#include "chrome/browser/ash/crostini/crostini_pref_names.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/views/crostini/crostini_dialogue_browser_test_util.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/prefs/pref_service.h"
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/test/browser_test.h"
 #include "services/network/test/test_network_connection_tracker.h"
@@ -19,7 +23,8 @@
 #include "ui/chromeos/devicetype_utils.h"
 
 class CrostiniAnsibleSoftwareConfigViewBrowserTest
-    : public CrostiniDialogBrowserTest {
+    : public CrostiniDialogBrowserTest,
+      public crostini::AnsibleManagementService::Observer {
  public:
   CrostiniAnsibleSoftwareConfigViewBrowserTest()
       : CrostiniDialogBrowserTest(true /*register_termina*/),
@@ -40,6 +45,56 @@
     return CrostiniAnsibleSoftwareConfigView::GetActiveViewForTesting();
   }
 
+  // crostini::AnsibleManagementService::Observer
+  void OnAnsibleSoftwareConfigurationStarted(
+      const crostini::ContainerId& container_id) override {}
+  void OnAnsibleSoftwareConfigurationFinished(
+      const crostini::ContainerId& container_id,
+      bool success) override {}
+
+  void OnApplyAnsiblePlaybook(
+      const crostini::ContainerId& container_id) override {
+    if (is_apply_ansible_success_) {
+      EXPECT_NE(nullptr, ActiveView());
+      vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal signal;
+      signal.set_status(
+          vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::SUCCEEDED);
+      signal.set_vm_name(crostini::ContainerId::GetDefault().vm_name);
+      signal.set_container_name(
+          crostini::ContainerId::GetDefault().container_name);
+      ansible_management_service()->OnApplyAnsiblePlaybookProgress(signal);
+    } else {
+      EXPECT_NE(nullptr, ActiveView());
+
+      vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal signal;
+      signal.set_status(
+          vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::FAILED);
+      signal.set_vm_name(crostini::ContainerId::GetDefault().vm_name);
+      signal.set_container_name(
+          crostini::ContainerId::GetDefault().container_name);
+      signal.set_failure_details("apple");
+      ansible_management_service()->OnApplyAnsiblePlaybookProgress(signal);
+    }
+  }
+  void OnAnsibleSoftwareInstall(
+      const crostini::ContainerId& container_id) override {
+    if (is_install_ansible_success_) {
+      EXPECT_NE(nullptr, ActiveView());
+      EXPECT_TRUE(IsDefaultDialog());
+      ansible_management_service()->OnInstallLinuxPackageProgress(
+          container_id_, crostini::InstallLinuxPackageProgressStatus::SUCCEEDED,
+          100,
+          /*error_message=*/{});
+    } else {
+      EXPECT_NE(nullptr, ActiveView());
+      EXPECT_TRUE(IsDefaultDialog());
+
+      ansible_management_service()->OnInstallLinuxPackageProgress(
+          container_id_, crostini::InstallLinuxPackageProgressStatus::FAILED, 0,
+          /*error_message=*/{});
+    }
+  }
+
  protected:
   void SetUpOnMainThread() override {
     // NetworkConnectionTracker should be reset first.
@@ -50,6 +105,16 @@
     test_helper_ = std::make_unique<crostini::AnsibleManagementTestHelper>(
         browser()->profile());
     test_helper_->SetUpAnsiblePlaybookPreference();
+    run_loop_ = std::make_unique<base::RunLoop>();
+    ansible_management_service()->AddObserver(this);
+
+    // Set sensible defaults.
+    is_install_ansible_success_ = true;
+    is_apply_ansible_success_ = true;
+  }
+
+  void TearDownOnMainThread() override {
+    ansible_management_service()->RemoveObserver(this);
   }
 
   void SetConnectionType(network::mojom::ConnectionType type) {
@@ -77,11 +142,21 @@
     return HasAcceptButton() && HasCancelButton() && HasErrorOfflineStrings();
   }
 
+  base::RunLoop* run_loop() { return run_loop_.get(); }
+
   crostini::AnsibleManagementService* ansible_management_service() {
     return crostini::AnsibleManagementService::GetForProfile(
         browser()->profile());
   }
 
+  void SetApplyAnsibleStatus(bool success) {
+    is_apply_ansible_success_ = success;
+  }
+
+  void SetInstallAnsibleStatus(bool success) {
+    is_install_ansible_success_ = success;
+  }
+
   crostini::ContainerId container_id_;
 
  private:
@@ -116,9 +191,12 @@
                    IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_ERROR_OFFLINE_SUBTEXT);
   }
 
+  bool is_install_ansible_success_;
+  bool is_apply_ansible_success_;
   std::unique_ptr<network::TestNetworkConnectionTracker>
       network_connection_tracker_;
   std::unique_ptr<crostini::AnsibleManagementTestHelper> test_helper_;
+  std::unique_ptr<base::RunLoop> run_loop_;
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
@@ -134,7 +212,7 @@
   EXPECT_TRUE(HasView());
   EXPECT_TRUE(IsDefaultDialog());
 
-  ActiveView()->OnAnsibleSoftwareConfigurationFinished(true);
+  ActiveView()->OnAnsibleSoftwareConfigurationFinished(container_id_, true);
 
   EXPECT_TRUE(HasNoView());
 }
@@ -146,7 +224,7 @@
   EXPECT_TRUE(HasView());
   EXPECT_TRUE(IsDefaultDialog());
 
-  ActiveView()->OnAnsibleSoftwareConfigurationFinished(false);
+  ActiveView()->OnAnsibleSoftwareConfigurationFinished(container_id_, false);
 
   EXPECT_NE(nullptr, ActiveView());
   EXPECT_TRUE(IsErrorDialog());
@@ -161,7 +239,7 @@
   EXPECT_TRUE(HasView());
   EXPECT_TRUE(IsDefaultDialog());
 
-  ActiveView()->OnAnsibleSoftwareConfigurationFinished(false);
+  ActiveView()->OnAnsibleSoftwareConfigurationFinished(container_id_, false);
 
   EXPECT_NE(nullptr, ActiveView());
   EXPECT_TRUE(IsErrorOfflineDialog());
@@ -176,7 +254,7 @@
   EXPECT_TRUE(HasView());
   EXPECT_TRUE(IsDefaultDialog());
 
-  ActiveView()->OnAnsibleSoftwareConfigurationFinished(false);
+  ActiveView()->OnAnsibleSoftwareConfigurationFinished(container_id_, false);
 
   EXPECT_NE(nullptr, ActiveView());
   EXPECT_TRUE(IsErrorOfflineDialog());
@@ -197,7 +275,7 @@
   EXPECT_TRUE(HasView());
   EXPECT_TRUE(IsDefaultDialog());
 
-  ActiveView()->OnAnsibleSoftwareConfigurationFinished(false);
+  ActiveView()->OnAnsibleSoftwareConfigurationFinished(container_id_, false);
 
   EXPECT_NE(nullptr, ActiveView());
   EXPECT_TRUE(IsErrorOfflineDialog());
@@ -210,39 +288,29 @@
 
 IN_PROC_BROWSER_TEST_F(CrostiniAnsibleSoftwareConfigViewBrowserTest,
                        AnsibleConfigFlow_Successful) {
-  ansible_management_service()->ConfigureDefaultContainer(base::DoNothing());
-  base::RunLoop().RunUntilIdle();
+  ansible_management_service()->ConfigureContainer(
+      crostini::ContainerId::GetDefault(),
+      browser()->profile()->GetPrefs()->GetFilePath(
+          crostini::prefs::kCrostiniAnsiblePlaybookFilePath),
+      base::BindLambdaForTesting([&](bool success) { run_loop()->Quit(); }));
 
-  EXPECT_TRUE(HasView());
-  EXPECT_TRUE(IsDefaultDialog());
-
-  ansible_management_service()->OnInstallLinuxPackageProgress(
-      container_id_, crostini::InstallLinuxPackageProgressStatus::SUCCEEDED,
-      100, /*error_message=*/{});
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_NE(nullptr, ActiveView());
-
-  ansible_management_service()->OnApplyAnsiblePlaybookProgress(
-      vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::SUCCEEDED,
-      /*failure_details=*/"");
-  base::RunLoop().RunUntilIdle();
+  run_loop()->Run();
 
   EXPECT_TRUE(HasNoView());
 }
 
 IN_PROC_BROWSER_TEST_F(CrostiniAnsibleSoftwareConfigViewBrowserTest,
                        AnsibleConfigFlow_InstallationFailed) {
-  ansible_management_service()->ConfigureDefaultContainer(base::DoNothing());
-  base::RunLoop().RunUntilIdle();
+  // Set install failure. No need to set apply because it should never reach
+  // there.
+  SetInstallAnsibleStatus(false);
+  ansible_management_service()->ConfigureContainer(
+      crostini::ContainerId::GetDefault(),
+      browser()->profile()->GetPrefs()->GetFilePath(
+          crostini::prefs::kCrostiniAnsiblePlaybookFilePath),
+      base::BindLambdaForTesting([&](bool success) { run_loop()->Quit(); }));
 
-  EXPECT_TRUE(HasView());
-  EXPECT_TRUE(IsDefaultDialog());
-
-  ansible_management_service()->OnInstallLinuxPackageProgress(
-      container_id_, crostini::InstallLinuxPackageProgressStatus::FAILED, 0,
-      /*error_message=*/{});
-  base::RunLoop().RunUntilIdle();
+  run_loop()->Run();
 
   EXPECT_NE(nullptr, ActiveView());
   EXPECT_TRUE(IsErrorDialog());
@@ -250,23 +318,16 @@
 
 IN_PROC_BROWSER_TEST_F(CrostiniAnsibleSoftwareConfigViewBrowserTest,
                        AnsibleConfigFlow_ApplicationFailed) {
-  ansible_management_service()->ConfigureDefaultContainer(base::DoNothing());
-  base::RunLoop().RunUntilIdle();
+  // Set apply failure
+  SetApplyAnsibleStatus(false);
+  ansible_management_service()->ConfigureContainer(
+      crostini::ContainerId::GetDefault(),
+      browser()->profile()->GetPrefs()->GetFilePath(
+          crostini::prefs::kCrostiniAnsiblePlaybookFilePath),
+      base::BindLambdaForTesting(
+          [&](bool success) { std::move(run_loop()->QuitClosure()).Run(); }));
 
-  EXPECT_TRUE(HasView());
-  EXPECT_TRUE(IsDefaultDialog());
-
-  ansible_management_service()->OnInstallLinuxPackageProgress(
-      container_id_, crostini::InstallLinuxPackageProgressStatus::SUCCEEDED,
-      100, /*error_message=*/{});
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_NE(nullptr, ActiveView());
-
-  ansible_management_service()->OnApplyAnsiblePlaybookProgress(
-      vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::FAILED,
-      /*failure_details=*/"");
-  base::RunLoop().RunUntilIdle();
+  run_loop()->Run();
 
   EXPECT_NE(nullptr, ActiveView());
   EXPECT_TRUE(IsErrorDialog());
diff --git a/chrome/browser/ui/views/crostini/crostini_recovery_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_recovery_view_browsertest.cc
index 0507661..4888d83 100644
--- a/chrome/browser/ui/views/crostini/crostini_recovery_view_browsertest.cc
+++ b/chrome/browser/ui/views/crostini/crostini_recovery_view_browsertest.cc
@@ -20,7 +20,7 @@
 #include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_manager.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "content/public/test/browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc
index 28b8681..69d8ec73 100644
--- a/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc
+++ b/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc
@@ -17,8 +17,8 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/views/crostini/crostini_dialogue_browser_test_util.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "components/crx_file/id_util.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/ui/views/crostini/crostini_update_component_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_update_component_view_browsertest.cc
index 0d5c3e32..aa01388 100644
--- a/chrome/browser/ui/views/crostini/crostini_update_component_view_browsertest.cc
+++ b/chrome/browser/ui/views/crostini/crostini_update_component_view_browsertest.cc
@@ -20,7 +20,7 @@
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_manager.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/crx_file/id_util.h"
 #include "content/public/browser/web_contents_observer.h"
diff --git a/chrome/browser/ui/views/crostini/crostini_update_filesystem_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_update_filesystem_view_browsertest.cc
index 7e05754..259fe57 100644
--- a/chrome/browser/ui/views/crostini/crostini_update_filesystem_view_browsertest.cc
+++ b/chrome/browser/ui/views/crostini/crostini_update_filesystem_view_browsertest.cc
@@ -14,8 +14,8 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/views/crostini/crostini_dialogue_browser_test_util.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "components/crx_file/id_util.h"
 #include "content/public/test/browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc
index b84ad0a2..2fb0e29 100644
--- a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc
+++ b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc
@@ -22,7 +22,7 @@
 #include "chrome/browser/ui/test/test_browser_dialog.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/grit/generated_resources.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h"
 #include "chromeos/dbus/vm_plugin_dispatcher/fake_vm_plugin_dispatcher_client.h"
diff --git a/chrome/browser/ui/webui/settings/about_handler_unittest.cc b/chrome/browser/ui/webui/settings/about_handler_unittest.cc
index d45eb8c7..603ebd5 100644
--- a/chrome/browser/ui/webui/settings/about_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/about_handler_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/time/time.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/update_engine/fake_update_engine_client.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc
index e03bc39..6c81d5c 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc
@@ -17,7 +17,7 @@
 #include "chrome/browser/download/download_core_service_impl.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc
index 1b9bd2ac..43500501 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc
@@ -26,8 +26,8 @@
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/spaced/spaced_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index ee741d3..60f1b0aa 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1651340748-989ebe79e81f77a78eb4bea2ce3c0a35f8eba104.profdata
+chrome-linux-main-1651447746-72f7bc28d0cbfb92bceac9e1fd59524b6ff5780e.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 30149b2a..52ad905bfb 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1651361496-1e0ac43163aa06f03c02d705e2d75ea0d12b3f9a.profdata
+chrome-mac-arm-main-1651447746-085ba8d7ad3628ee588c04f09a8b2bb9c14b1244.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 3bcdfaa..baa00f5a 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1651361496-96dba1db278ca82f8f68369ecd4dee372f3d8a8b.profdata
+chrome-mac-main-1651447746-ef16c3a0461cf70341972205f0d20dd47192a008.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 467c7cf3..80e4e23 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1651368376-1960c6f4653222fb12d132978884847319bc7e4c.profdata
+chrome-win32-main-1651447746-a9afb2ed1586bf7b85293185610ee8549bc80b91.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index b1aa13d..ad4138e 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1651368376-6649a5373d25f26b9af58bc183bc763935b6d874.profdata
+chrome-win64-main-1651460328-3a1ada15f6b87d8bd5655d92c5197720396e1bc8.profdata
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index a106f2e..fa61e65 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -549,8 +549,8 @@
       "//ash/constants",
       "//chrome/browser/ash/crosapi",
       "//chrome/browser/chromeos",
+      "//chromeos/ash/components/dbus/concierge",
       "//chromeos/dbus",
-      "//chromeos/dbus/concierge",
       "//chromeos/dbus/power",
       "//chromeos/system",
       "//components/policy/test_support",
@@ -4032,6 +4032,7 @@
         "//chromeos/ash/components/dbus/authpolicy",
         "//chromeos/ash/components/dbus/biod",
         "//chromeos/ash/components/dbus/biod:biod_proto",
+        "//chromeos/ash/components/dbus/concierge",
         "//chromeos/ash/components/dbus/rmad:rmad",
         "//chromeos/ash/components/dbus/seneschal",
         "//chromeos/ash/components/dbus/services:test_support",
@@ -4047,7 +4048,6 @@
         "//chromeos/dbus/attestation",
         "//chromeos/dbus/attestation:attestation_proto",
         "//chromeos/dbus/cicerone",
-        "//chromeos/dbus/concierge",
         "//chromeos/dbus/cros_disks",
         "//chromeos/dbus/cros_disks",
         "//chromeos/dbus/cryptohome",
@@ -7149,6 +7149,7 @@
       "//chrome/services/sharing/nearby/platform:unit_tests",
       "//chrome/services/sharing/public/cpp",
       "//chrome/services/sharing/public/cpp:unit_tests",
+      "//chromeos/ash/components/dbus/concierge",
       "//chromeos/ash/components/dbus/seneschal",
       "//chromeos/assistant:buildflags",
       "//chromeos/components/feature_usage:feature_usage",
@@ -7161,7 +7162,6 @@
       "//chromeos/dbus",
       "//chromeos/dbus/attestation",
       "//chromeos/dbus/cicerone",
-      "//chromeos/dbus/concierge",
       "//chromeos/dbus/cros_disks",
       "//chromeos/dbus/debug_daemon",
       "//chromeos/dbus/hermes",
diff --git a/chrome/test/data/system_extensions/cros_window_test_utils.js b/chrome/test/data/system_extensions/cros_window_test_utils.js
index dae7528..ad7489a 100644
--- a/chrome/test/data/system_extensions/cros_window_test_utils.js
+++ b/chrome/test/data/system_extensions/cros_window_test_utils.js
@@ -4,7 +4,7 @@
 
 // We assume a single window only and apply cros_window API methods at index 0.
 async function assertSingleWindow() {
-  let windows = await chromeos.windowManagement.windows();
+  let windows = await chromeos.windowManagement.getWindows();
   assert_equals(windows.length, 1,
       `util functions restricted to testing with a single window.`);
 }
@@ -15,7 +15,7 @@
 async function setFullscreenAndTest(fullscreen) {
   await assertSingleWindow();
   {
-    let [window] = await chromeos.windowManagement.windows();
+    let [window] = await chromeos.windowManagement.getWindows();
     window.setFullscreen(fullscreen);
   }
 
@@ -25,7 +25,7 @@
   }
 
   {
-    let [window] = await chromeos.windowManagement.windows();
+    let [window] = await chromeos.windowManagement.getWindows();
     assert_false(window.isFullscreen, `setFullscreen() fail`);
   }
 }
@@ -34,13 +34,13 @@
   await assertSingleWindow();
 
   {
-    let [window] = await chromeos.windowManagement.windows();
+    let [window] = await chromeos.windowManagement.getWindows();
     window.setBounds(newBounds.x, newBounds.y,
         newBounds.width, newBounds.height);
   }
 
   {
-    let [window] = await chromeos.windowManagement.windows();
+    let [window] = await chromeos.windowManagement.getWindows();
     const actualBounds = window.bounds;
     assert_weak_equals(actualBounds, newBounds, `set bounds incorrectly`);
   }
@@ -50,7 +50,7 @@
 async function maximizeAndTest() {
   await assertSingleWindow();
 
-  let [window] = await chromeos.windowManagement.windows();
+  let [window] = await chromeos.windowManagement.getWindows();
   window.maximize();
   await assertWindowState("maximized");
 }
@@ -59,7 +59,7 @@
 async function minimizeAndTest() {
   await assertSingleWindow();
 
-  let [window] = await chromeos.windowManagement.windows();
+  let [window] = await chromeos.windowManagement.getWindows();
   window.minimize();
   await assertWindowState("minimized");
 }
@@ -68,12 +68,12 @@
   await assertSingleWindow();
 
   {
-    let [window] = await chromeos.windowManagement.windows();
+    let [window] = await chromeos.windowManagement.getWindows();
     window.focus();
   }
 
   {
-    let [window] = await chromeos.windowManagement.windows();
+    let [window] = await chromeos.windowManagement.getWindows();
     assert_true(window.isFocused, `focus() failed to set focus`);
     assert_equals(
         window.visibilityState, 'shown', `focus() should make window visible`);
@@ -85,7 +85,7 @@
 async function assertWindowState(state) {
   await assertSingleWindow();
 
-  let [window] = await chromeos.windowManagement.windows();
+  let [window] = await chromeos.windowManagement.getWindows();
   assert_equals(window.isMaximized, state === "maximized",
       `window should be in the ${state} state`);
   assert_equals(window.isMinimized, state === "minimized",
diff --git a/chrome/test/data/webui/settings/chromeos/input_page_test.js b/chrome/test/data/webui/settings/chromeos/input_page_test.js
index 2f0be66..c3fb6976 100644
--- a/chrome/test/data/webui/settings/chromeos/input_page_test.js
+++ b/chrome/test/data/webui/settings/chromeos/input_page_test.js
@@ -261,8 +261,8 @@
 
   suite('add input methods dialog', () => {
     let dialog;
-    let suggestedInputMethods;
-    let allInputMethods;
+    let suggestedList;
+    let allImesList;
     let cancelButton;
     let actionButton;
 
@@ -271,7 +271,8 @@
       inputPage.$$('#addInputMethod').click();
       flush();
 
-      dialog = inputPage.$$('os-settings-add-input-methods-dialog');
+      dialog = inputPage.$$('os-settings-add-input-methods-dialog')
+                   .$$('os-settings-add-items-dialog');
       assertTrue(!!dialog);
 
       actionButton = dialog.$$('.action-button');
@@ -279,11 +280,11 @@
       cancelButton = dialog.$$('.cancel-button');
       assertTrue(!!cancelButton);
 
-      suggestedInputMethods = dialog.$$('#suggestedInputMethods');
-      assertTrue(!!suggestedInputMethods);
+      suggestedList = dialog.$$('#suggested-items-list');
+      assertTrue(!!suggestedList);
 
-      allInputMethods = dialog.$$('#allInputMethods');
-      assertTrue(!!allInputMethods);
+      allImesList = dialog.$$('#filtered-items-list');
+      assertTrue(!!allImesList);
 
       // No input methods has been selected, so the action button is disabled.
       assertTrue(actionButton.disabled);
@@ -291,7 +292,7 @@
     });
 
     test('has action button working correctly', () => {
-      const listItems = suggestedInputMethods.querySelectorAll('.list-item');
+      const listItems = suggestedList.querySelectorAll('.list-item');
       // selecting a language enables action button
       listItems[0].click();
       assertFalse(actionButton.disabled);
@@ -302,8 +303,7 @@
     });
 
     test('has correct structure and adds input methods', () => {
-      const suggestedItems =
-          suggestedInputMethods.querySelectorAll('.list-item');
+      const suggestedItems = suggestedList.querySelectorAll('.list-item');
       // input methods are based on and ordered by enabled languages
       // only allowed input methods are shown.
       assertEquals(2, suggestedItems.length);
@@ -312,7 +312,7 @@
       // selecting Swahili keyboard.
       suggestedItems[1].click();
 
-      const allItems = allInputMethods.querySelectorAll('.list-item');
+      const allItems = allImesList.querySelectorAll('.list-item');
       // All input methods should appear and ordered based on fake settings
       // data.
       assertEquals(4, allItems.length);
@@ -384,10 +384,9 @@
       languageHelper.setPrefValue('settings.language.preferred_languages', '');
       flush();
 
-      suggestedInputMethods = dialog.$$('#suggestedInputMethods');
+      suggestedList = dialog.$$('#suggestedInputMethods');
       // suggested input methods is rendered previously.
-      assertTrue(!!suggestedInputMethods);
-      assertEquals('none', getComputedStyle(suggestedInputMethods).display);
+      assertFalse(isVisible(suggestedList));
     });
 
     test('suggested input methods hidden when no input methods left', () => {
@@ -401,29 +400,27 @@
           });
       flush();
 
-      suggestedInputMethods = dialog.$$('#suggestedInputMethods');
-      // suggested input methods is rendered previously.
-      assertTrue(!!suggestedInputMethods);
-      assertEquals('none', getComputedStyle(suggestedInputMethods).display);
+      suggestedList = dialog.$$('#suggestedInputMethods');
+      assertFalse(isVisible(suggestedList));
     });
 
     test('searches input methods correctly', () => {
       const searchInput = dialog.$$('cr-search-field');
       const getItems = function() {
-        return allInputMethods.querySelectorAll('.list-item:not([hidden])');
+        return allImesList.querySelectorAll('.list-item:not([hidden])');
       };
 
-      assertFalse(dialog.$$('#allInputMethodsLabel').hidden);
-      assertEquals('block', getComputedStyle(suggestedInputMethods).display);
+      assertTrue(isVisible(dialog.$$('#filtered-items-label')));
+      assertTrue(isVisible(suggestedList));
 
       // Expecting a few languages to be displayed when no query exists.
       assertGE(getItems().length, 1);
 
-      // Search hides suggestedInputMethods and allInputMethodsLabel.
+      // Search hides the suggested list and the label for all IMEs.
       searchInput.setValue('v');
       flush();
-      assertTrue(dialog.$$('#allInputMethodsLabel').hidden);
-      assertEquals('none', getComputedStyle(suggestedInputMethods).display);
+      assertFalse(isVisible(dialog.$$('#filtered-items-label')));
+      assertFalse(isVisible(suggestedList));
 
       // Search input methods name
       searchInput.setValue('vietnamese');
@@ -1252,8 +1249,8 @@
 
   suite('add spell check languages dialog', () => {
     let dialog;
-    let suggestedLanguages;
-    let allLanguages;
+    let suggestedList;
+    let allLangsList;
     let cancelButton;
     let actionButton;
 
@@ -1270,12 +1267,12 @@
       // This function should return the *visible* items that the user can
       // select, so if the <iron-list> is hidden we should return an empty
       // list instead.
-      const list = allLanguages.querySelector('iron-list');
-      if (!isVisible(list)) {
+      if (!isVisible(allLangsList)) {
         return [];
       }
-      return [...allLanguages.querySelectorAll(
-          'cr-checkbox-with-policy:not([hidden])')];
+      return [
+        ...allLangsList.querySelectorAll('cr-checkbox-with-policy')
+      ].filter(checkbox => isVisible(checkbox));
     }
 
     /**
@@ -1303,14 +1300,15 @@
       inputPage.$$('#addSpellcheckLanguages').click();
       flush();
 
-      dialog = inputPage.$$('os-settings-add-spellcheck-languages-dialog');
+      dialog = inputPage.$$('os-settings-add-spellcheck-languages-dialog')
+                   .$$('os-settings-add-items-dialog');
       assertTrue(!!dialog);
       assertTrue(dialog.$.dialog.open);
 
-      suggestedLanguages = dialog.$$('#suggestedLanguages');
-      assertTrue(!!suggestedLanguages);
-      allLanguages = dialog.$$('#allLanguages');
-      assertTrue(!!allLanguages);
+      suggestedList = dialog.$$('#suggested-items-list');
+      assertTrue(!!suggestedList);
+      allLangsList = dialog.$$('#filtered-items-list');
+      assertTrue(!!allLangsList);
 
       actionButton = dialog.$$('.action-button');
       assertTrue(!!actionButton);
@@ -1343,7 +1341,7 @@
     test('initial expected layout', () => {
       // As Swahili is an enabled language, it should be shown as a suggested
       // language.
-      const suggestedItems = suggestedLanguages.querySelectorAll('cr-checkbox');
+      const suggestedItems = suggestedList.querySelectorAll('cr-checkbox');
       assertEquals(suggestedItems.length, 1);
       assertTrue(suggestedItems[0].textContent.includes('Swahili'));
 
@@ -1363,13 +1361,13 @@
       assertTrue(checkboxes.every(checkbox => !checkbox.checked));
 
       // There should be a label for both sections.
-      const suggestedLabel = suggestedLanguages.querySelector('.label');
+      const suggestedLabel = dialog.$$('#suggested-items-label');
       assertTrue(!!suggestedLabel);
-      assertFalse(suggestedLabel.hidden);
+      assertTrue(isVisible(suggestedLabel));
 
-      const allLanguagesLabel = allLanguages.querySelector('.label');
-      assertTrue(!!allLanguagesLabel);
-      assertFalse(allLanguagesLabel.hidden);
+      const allLangsLabel = dialog.$$('#filtered-items-label');
+      assertTrue(!!allLangsLabel);
+      assertTrue(isVisible(allLangsLabel));
     });
 
     test('can add single language and uncheck language', () => {
@@ -1445,9 +1443,9 @@
       flush();
 
       // Suggested languages should not show up whatsoever.
-      assertFalse(isVisible(suggestedLanguages));
+      assertFalse(isVisible(suggestedList));
       // The label for all languages should not appear either.
-      assertFalse(isVisible(allLanguages.querySelector('.label')));
+      assertFalse(isVisible(allLangsList.querySelector('.label')));
     });
 
     test('input method languages appear as suggested languages', () => {
@@ -1458,15 +1456,14 @@
 
       // Both Swahili (as it is an enabled language) and English (US) (as it is
       // enabled as an input method) should appear in the list.
-      const suggestedListItems =
-          suggestedLanguages.querySelectorAll('.list-item');
+      const suggestedListItems = suggestedList.querySelectorAll('.list-item');
       assertEquals(suggestedListItems.length, 2);
       assertTrue(suggestedListItems[0].textContent.includes(
           'English (United States)'));
       assertTrue(suggestedListItems[1].textContent.includes('Swahili'));
 
       // en-US should also appear in the all languages list now.
-      assertEquals(allLanguages.querySelectorAll('.list-item').length, 4);
+      assertEquals(allLangsList.querySelectorAll('.list-item').length, 4);
     });
 
     test('searches languages on display name', () => {
@@ -1491,7 +1488,7 @@
       searchInput.setValue('egaugnal');
       flush();
       assertEquals(getAllLanguagesCheckboxWithPolicies().length, 0);
-      assertFalse(dialog.$$('#no-search-results').hidden);
+      assertTrue(isVisible(dialog.$$('#no-search-results')));
     });
 
     test('has escape key behavior working correctly', function() {
diff --git a/chrome/test/data/webui/settings/password_view_test.ts b/chrome/test/data/webui/settings/password_view_test.ts
index df0eacf2..89a68f90 100644
--- a/chrome/test/data/webui/settings/password_view_test.ts
+++ b/chrome/test/data/webui/settings/password_view_test.ts
@@ -90,11 +90,6 @@
     });
     Router.getInstance().navigateTo(routes.PASSWORD_VIEW, params);
 
-    const {id, reason} =
-        await passwordManager.whenCalled('requestPlaintextPassword');
-    assertEquals(ID, id);
-    assertEquals(chrome.passwordsPrivate.PlaintextReason.VIEW, reason);
-
     await flushTasks();
     assertVisibilityOfPageElements(page, /*visibility=*/ true);
   });
@@ -116,9 +111,6 @@
         });
         Router.getInstance().navigateTo(routes.PASSWORD_VIEW, params);
 
-        assertEquals(
-            0, passwordManager.getCallCount('requestPlaintextPassword'));
-
         await flushTasks();
         assertVisibilityOfPageElements(page, /*visibility=*/ false);
 
@@ -142,50 +134,15 @@
     });
     Router.getInstance().navigateTo(routes.PASSWORD_VIEW, params);
 
-    assertEquals(0, passwordManager.getCallCount('requestPlaintextPassword'));
-
     await flushTasks();
     assertVisibilityOfFederatedCredentialElements(page);
   });
 
-  // <if expr="not chromeos_ash and not chromeos_lacros">
-  test(
-      'When password request fails view page is empty, ' +
-          'and page is routed to passwords page',
-      async function() {
-        const passwordList = [
-          createPasswordEntry({url: SITE, username: USERNAME, id: ID}),
-        ];
-
-        passwordManager.data.passwords = passwordList;
-        const page = document.createElement('password-view');
-        document.body.appendChild(page);
-        const params = new URLSearchParams({
-          username: USERNAME,
-          site: SITE,
-        });
-        Router.getInstance().navigateTo(routes.PASSWORD_VIEW, params);
-
-        // This will fail because passwordManager.setPlaintextPasswords was not
-        // called.
-        const {id, reason} =
-            await passwordManager.whenCalled('requestPlaintextPassword');
-        assertEquals(ID, id);
-        assertEquals(chrome.passwordsPrivate.PlaintextReason.VIEW, reason);
-
-        await flushTasks();
-        assertVisibilityOfPageElements(page, /*visibility=*/ false);
-
-        assertEquals(routes.PASSWORDS, Router.getInstance().getCurrentRoute());
-      });
-  // </if>
-
   test('Clicking show password button shows / hides it', async function() {
     const passwordList = [
       createPasswordEntry({url: SITE, username: USERNAME, id: ID}),
     ];
 
-    passwordManager.setPlaintextPassword(PASSWORD);
     passwordManager.data.passwords = passwordList;
     const page = document.createElement('password-view');
     document.body.appendChild(page);
@@ -195,41 +152,54 @@
     });
     Router.getInstance().navigateTo(routes.PASSWORD_VIEW, params);
 
-    await passwordManager.whenCalled('requestPlaintextPassword');
     await flushTasks();
-
     const passwordInput =
         page.shadowRoot!.querySelector<HTMLInputElement>('#passwordInput');
     const showButton = page.shadowRoot!.querySelector<HTMLButtonElement>(
         '#showPasswordButton');
     assertTrue(!!passwordInput);
     assertTrue(!!showButton);
-
     assertEquals('password', passwordInput.type);
+    assertEquals(' '.repeat(10), passwordInput.value);
     assertTrue(showButton.classList.contains('icon-visibility'));
 
     showButton.click();
-    flush();
 
+    // this will fail because setPlaintextPassword is not called.
+    await passwordManager.whenCalled('requestPlaintextPassword');
+    await flushTasks();
+    assertEquals('password', passwordInput.type);
+    assertEquals(' '.repeat(10), passwordInput.value);
+    assertTrue(showButton.classList.contains('icon-visibility'));
+
+    passwordManager.setPlaintextPassword(PASSWORD);
+    // show the password
+    showButton.click();
+
+    const {id, reason} =
+        await passwordManager.whenCalled('requestPlaintextPassword');
+    await flushTasks();
+    assertEquals(ID, id);
+    assertEquals(chrome.passwordsPrivate.PlaintextReason.VIEW, reason);
     assertEquals('text', passwordInput.type);
+    assertEquals(PASSWORD, passwordInput.value);
     assertTrue(showButton.classList.contains('icon-visibility-off'));
 
+    // hide the password by re-clicking
     showButton.click();
     flush();
-
     assertEquals('password', passwordInput.type);
+    assertEquals(' '.repeat(10), passwordInput.value);
     assertTrue(showButton.classList.contains('icon-visibility'));
   });
 
   test(
-      'When saved passwords change credential is re-requested',
+      'When saved passwords change credential is still shown',
       async function() {
-        const passwordList = [
-          createPasswordEntry({url: SITE, username: USERNAME, id: ID}),
-        ];
+        const passwordEntry =
+            createPasswordEntry({url: SITE, username: USERNAME, id: ID});
 
-        passwordManager.setPlaintextPassword(PASSWORD);
-        passwordManager.data.passwords = passwordList;
+        passwordManager.data.passwords = [passwordEntry];
         const page = document.createElement('password-view');
         document.body.appendChild(page);
         const params = new URLSearchParams({
@@ -237,22 +207,20 @@
           site: SITE,
         });
         Router.getInstance().navigateTo(routes.PASSWORD_VIEW, params);
-
-        await passwordManager.whenCalled('requestPlaintextPassword');
-        assertEquals(
-            1, passwordManager.getCallCount('requestPlaintextPassword'));
         await flushTasks();
-        passwordManager.resetResolver('requestPlaintextPassword');
+        assertTrue(!!page.credential);
+        assertEquals(SITE, page.credential.urls.shown);
+        assertEquals(USERNAME, page.credential.username);
 
         passwordManager.lastCallback.addSavedPasswordListChangedListener!
-            (passwordList.concat([
+            ([passwordEntry].concat([
               createPasswordEntry({url: 'site2.com', username: 'user2', id: 1}),
             ]));
 
-        await passwordManager.whenCalled('requestPlaintextPassword');
         await flushTasks();
-        assertEquals(
-            1, passwordManager.getCallCount('requestPlaintextPassword'));
+        assertTrue(!!page.credential);
+        assertEquals(SITE, page.credential.urls.shown);
+        assertEquals(USERNAME, page.credential.username);
       });
 
   test(
@@ -272,14 +240,12 @@
         });
         Router.getInstance().navigateTo(routes.PASSWORD_VIEW, params);
 
-        await passwordManager.whenCalled('requestPlaintextPassword');
         await flushTasks();
-        passwordManager.resetResolver('requestPlaintextPassword');
+        assertVisibilityOfPageElements(page, /*visibility=*/ true);
 
         passwordManager.lastCallback.addSavedPasswordListChangedListener!([]);
 
         await flushTasks();
-
         assertVisibilityOfPageElements(page, /*visibility=*/ false);
       });
 
@@ -301,9 +267,7 @@
         });
         Router.getInstance().navigateTo(routes.PASSWORD_VIEW, params);
 
-        await passwordManager.whenCalled('requestPlaintextPassword');
         await flushTasks();
-        passwordManager.resetResolver('requestPlaintextPassword');
 
         page.shadowRoot!.querySelector<HTMLButtonElement>(
                             '#editButton')!.click();
@@ -328,7 +292,6 @@
             ([entry]);
 
         await flushTasks();
-        await passwordManager.whenCalled('requestPlaintextPassword');
         assertFalse(isVisible(editDialog));
 
         assertEquals(NEW_USERNAME, page.credential!.username);
@@ -357,7 +320,6 @@
         });
         Router.getInstance().navigateTo(routes.PASSWORD_VIEW, params);
 
-        await passwordManager.whenCalled('requestPlaintextPassword');
         await flushTasks();
 
         page.shadowRoot!.querySelector<HTMLButtonElement>(
@@ -400,8 +362,6 @@
           site: SITE,
         });
         Router.getInstance().navigateTo(routes.PASSWORD_VIEW, params);
-
-        await passwordManager.whenCalled('requestPlaintextPassword');
         await flushTasks();
 
         page.shadowRoot!.querySelector<HTMLButtonElement>(
diff --git a/chromeos/ash/components/dbus/concierge/BUILD.gn b/chromeos/ash/components/dbus/concierge/BUILD.gn
new file mode 100644
index 0000000..c2297ca90
--- /dev/null
+++ b/chromeos/ash/components/dbus/concierge/BUILD.gn
@@ -0,0 +1,35 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/chromeos/ui_mode.gni")
+import("//third_party/protobuf/proto_library.gni")
+
+assert(is_chromeos_ash, "Non-ChromeOS builds cannot depend on //chromeos/ash")
+
+component("concierge") {
+  defines = [ "IS_CONCIERGE_IMPL" ]
+  deps = [
+    ":concierge_proto",
+    "//base",
+    "//chromeos/dbus:cicerone_proto",
+    "//chromeos/dbus/cicerone",
+    "//chromeos/dbus/common",
+    "//dbus",
+  ]
+
+  sources = [
+    "concierge_client.cc",
+    "concierge_client.h",
+    "fake_concierge_client.cc",
+    "fake_concierge_client.h",
+  ]
+}
+
+proto_library("concierge_proto") {
+  sources = [
+    "//third_party/cros_system_api/dbus/vm_concierge/concierge_service.proto",
+  ]
+
+  proto_out_dir = "chromeos/ash/components/dbus/concierge"
+}
diff --git a/chromeos/dbus/concierge/OWNERS b/chromeos/ash/components/dbus/concierge/OWNERS
similarity index 100%
rename from chromeos/dbus/concierge/OWNERS
rename to chromeos/ash/components/dbus/concierge/OWNERS
diff --git a/chromeos/dbus/concierge/concierge_client.cc b/chromeos/ash/components/dbus/concierge/concierge_client.cc
similarity index 98%
rename from chromeos/dbus/concierge/concierge_client.cc
rename to chromeos/ash/components/dbus/concierge/concierge_client.cc
index 531beef..faa14ff 100644
--- a/chromeos/dbus/concierge/concierge_client.cc
+++ b/chromeos/ash/components/dbus/concierge/concierge_client.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 "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 
 #include <string>
 #include <utility>
@@ -12,8 +12,8 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
-#include "chromeos/dbus/concierge/fake_concierge_client.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/chromeos/dbus/concierge/concierge_client.h b/chromeos/ash/components/dbus/concierge/concierge_client.h
similarity index 97%
rename from chromeos/dbus/concierge/concierge_client.h
rename to chromeos/ash/components/dbus/concierge/concierge_client.h
index 8bd961f..51958239 100644
--- a/chromeos/dbus/concierge/concierge_client.h
+++ b/chromeos/ash/components/dbus/concierge/concierge_client.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_CONCIERGE_CONCIERGE_CLIENT_H_
-#define CHROMEOS_DBUS_CONCIERGE_CONCIERGE_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_CONCIERGE_CONCIERGE_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_CONCIERGE_CONCIERGE_CLIENT_H_
 
 #include "base/component_export.h"
 #include "base/files/scoped_file.h"
 #include "base/observer_list.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
 #include "chromeos/dbus/common/dbus_client.h"
 #include "chromeos/dbus/common/dbus_method_call_status.h"
-#include "chromeos/dbus/concierge/concierge_service.pb.h"
 #include "dbus/object_proxy.h"
 
 namespace chromeos {
@@ -19,7 +19,7 @@
 
 // ConciergeClient is used to communicate with Concierge, which is used to
 // start and stop VMs, as well as for disk image management.
-class COMPONENT_EXPORT(CHROMEOS_DBUS) ConciergeClient : public DBusClient {
+class COMPONENT_EXPORT(CONCIERGE) ConciergeClient : public DBusClient {
  public:
   static constexpr base::ObserverListPolicy kObserverListPolicy =
       base::ObserverListPolicy::EXISTING_ONLY;
@@ -324,4 +324,4 @@
 using ::chromeos::ConciergeClient;
 }
 
-#endif  // CHROMEOS_DBUS_CONCIERGE_CONCIERGE_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_CONCIERGE_CONCIERGE_CLIENT_H_
diff --git a/chromeos/dbus/concierge/fake_concierge_client.cc b/chromeos/ash/components/dbus/concierge/fake_concierge_client.cc
similarity index 99%
rename from chromeos/dbus/concierge/fake_concierge_client.cc
rename to chromeos/ash/components/dbus/concierge/fake_concierge_client.cc
index 5330677..26760fe9 100644
--- a/chromeos/dbus/concierge/fake_concierge_client.cc
+++ b/chromeos/ash/components/dbus/concierge/fake_concierge_client.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 "chromeos/dbus/concierge/fake_concierge_client.h"
+#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 
 #include <utility>
 
diff --git a/chromeos/dbus/concierge/fake_concierge_client.h b/chromeos/ash/components/dbus/concierge/fake_concierge_client.h
similarity index 97%
rename from chromeos/dbus/concierge/fake_concierge_client.h
rename to chromeos/ash/components/dbus/concierge/fake_concierge_client.h
index fd71f55..585978a5 100644
--- a/chromeos/dbus/concierge/fake_concierge_client.h
+++ b/chromeos/ash/components/dbus/concierge/fake_concierge_client.h
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_CONCIERGE_FAKE_CONCIERGE_CLIENT_H_
-#define CHROMEOS_DBUS_CONCIERGE_FAKE_CONCIERGE_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_CONCIERGE_FAKE_CONCIERGE_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_CONCIERGE_FAKE_CONCIERGE_CLIENT_H_
 
 #include <vector>
 
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/time/time.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
-#include "chromeos/dbus/concierge/concierge_client.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromeos {
@@ -19,8 +19,7 @@
 class FakeCiceroneClient;
 
 // FakeConciergeClient is a light mock of ConciergeClient used for testing.
-class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeConciergeClient
-    : public ConciergeClient {
+class COMPONENT_EXPORT(CONCIERGE) FakeConciergeClient : public ConciergeClient {
  public:
   // Returns the fake global instance if initialized. May return null.
   static FakeConciergeClient* Get();
@@ -455,4 +454,4 @@
 using ::chromeos::FakeConciergeClient;
 }
 
-#endif  // CHROMEOS_DBUS_CONCIERGE_FAKE_CONCIERGE_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_CONCIERGE_FAKE_CONCIERGE_CLIENT_H_
diff --git a/chromeos/ash/components/dbus/rmad/rmad_client.cc b/chromeos/ash/components/dbus/rmad/rmad_client.cc
index d9dfaee..e1883d69 100644
--- a/chromeos/ash/components/dbus/rmad/rmad_client.cc
+++ b/chromeos/ash/components/dbus/rmad/rmad_client.cc
@@ -172,8 +172,13 @@
     return;
   }
 
+  // TODO(b/230924565): Remove LOG statements after feature release.
   if (session_manager_callback_) {
+    VLOG(1) << "RmadClientImpl::OnCheckIfRmaIsRequired invoking session "
+               "manager callback";
     std::move(session_manager_callback_).Run();
+  } else {
+    VLOG(1) << "RmadClientImpl::OnCheckIfRmaIsRequired the callback is not set";
   }
 }
 
@@ -514,6 +519,13 @@
                     "WasRmaStateDetected() called.";
   }
 
+  // TODO(b/230924565): Remove LOG statement after feature release.
+  VLOG(1) << "RmadClientImpl::WasRmaStateDetected rma_executable_exists_: "
+          << rma_executable_exists_.value_or(false)
+          << " is_rma_required_: " << is_rma_required_
+          << " rma_state_file_exists_: "
+          << rma_state_file_exists_.value_or(false);
+
   return rma_executable_exists_.value_or(false) &&
          (is_rma_required_ || rma_state_file_exists_.value_or(false));
 }
diff --git a/chromeos/scanning/BUILD.gn b/chromeos/ash/components/scanning/BUILD.gn
similarity index 71%
rename from chromeos/scanning/BUILD.gn
rename to chromeos/ash/components/scanning/BUILD.gn
index 4ab0447..d0bc1ed 100644
--- a/chromeos/scanning/BUILD.gn
+++ b/chromeos/ash/components/scanning/BUILD.gn
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-assert(is_chromeos, "Non-Chrome-OS builds must not depend on //chromeos")
+import("//build/config/chromeos/ui_mode.gni")
+
+assert(is_chromeos_ash, "Non Chrome OS builds cannot depend on //chromeos/ash")
 
 component("scanning") {
   defines = [ "IS_SCANNING_IMPL" ]
diff --git a/chromeos/scanning/OWNERS b/chromeos/ash/components/scanning/OWNERS
similarity index 100%
rename from chromeos/scanning/OWNERS
rename to chromeos/ash/components/scanning/OWNERS
diff --git a/chromeos/scanning/scanner.cc b/chromeos/ash/components/scanning/scanner.cc
similarity index 92%
rename from chromeos/scanning/scanner.cc
rename to chromeos/ash/components/scanning/scanner.cc
index f434f457..7cbff2d 100644
--- a/chromeos/scanning/scanner.cc
+++ b/chromeos/ash/components/scanning/scanner.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/scanning/scanner.h"
+#include "chromeos/ash/components/scanning/scanner.h"
 
-namespace chromeos {
+namespace ash {
 
 ScannerDeviceName::ScannerDeviceName(const std::string& device_name)
     : device_name(device_name) {}
@@ -36,4 +36,4 @@
 
 Scanner& Scanner::operator=(const Scanner& other) = default;
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chromeos/scanning/scanner.h b/chromeos/ash/components/scanning/scanner.h
similarity index 91%
rename from chromeos/scanning/scanner.h
rename to chromeos/ash/components/scanning/scanner.h
index 154fadc..a28779d 100644
--- a/chromeos/scanning/scanner.h
+++ b/chromeos/ash/components/scanning/scanner.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 CHROMEOS_SCANNING_SCANNER_H_
-#define CHROMEOS_SCANNING_SCANNER_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_SCANNING_SCANNER_H_
+#define CHROMEOS_ASH_COMPONENTS_SCANNING_SCANNER_H_
 
 #include <string>
 
@@ -12,7 +12,7 @@
 #include "base/containers/flat_set.h"
 #include "net/base/ip_address.h"
 
-namespace chromeos {
+namespace ash {
 
 // The type of protocol used to communicate with a scanner.
 enum class COMPONENT_EXPORT(SCANNING) ScanProtocol {
@@ -64,6 +64,6 @@
   base::flat_set<net::IPAddress> ip_addresses;
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
-#endif  // CHROMEOS_SCANNING_SCANNER_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_SCANNING_SCANNER_H_
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn
index 9224979..d6431e48 100644
--- a/chromeos/dbus/BUILD.gn
+++ b/chromeos/dbus/BUILD.gn
@@ -142,14 +142,6 @@
   proto_out_dir = "chromeos/dbus/cicerone"
 }
 
-proto_library("concierge_proto") {
-  sources = [
-    "//third_party/cros_system_api/dbus/vm_concierge/concierge_service.proto",
-  ]
-
-  proto_out_dir = "chromeos/dbus/concierge"
-}
-
 proto_library("metrics_event_proto") {
   sources =
       [ "//third_party/cros_system_api/dbus/metrics_event/metrics_event.proto" ]
diff --git a/chromeos/dbus/concierge/BUILD.gn b/chromeos/dbus/concierge/BUILD.gn
deleted file mode 100644
index 9a454a6..0000000
--- a/chromeos/dbus/concierge/BUILD.gn
+++ /dev/null
@@ -1,24 +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.
-
-assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
-
-component("concierge") {
-  defines = [ "IS_CHROMEOS_DBUS_IMPL" ]
-  deps = [
-    "//base",
-    "//chromeos/dbus:cicerone_proto",
-    "//chromeos/dbus:concierge_proto",
-    "//chromeos/dbus/cicerone",
-    "//chromeos/dbus/common",
-    "//dbus",
-  ]
-
-  sources = [
-    "concierge_client.cc",
-    "concierge_client.h",
-    "fake_concierge_client.cc",
-    "fake_concierge_client.h",
-  ]
-}
diff --git a/chromeos/dbus/lorgnette_manager/OWNERS b/chromeos/dbus/lorgnette_manager/OWNERS
index 1a7867b..dda649fc 100644
--- a/chromeos/dbus/lorgnette_manager/OWNERS
+++ b/chromeos/dbus/lorgnette_manager/OWNERS
@@ -1 +1 @@
-file://chromeos/scanning/OWNERS
+file://chromeos/ash/components/scanning/OWNERS
diff --git a/chromeos/language/language_packs/language_pack_manager.cc b/chromeos/language/language_packs/language_pack_manager.cc
index 47a0c17..056a6dc 100644
--- a/chromeos/language/language_packs/language_pack_manager.cc
+++ b/chromeos/language/language_packs/language_pack_manager.cc
@@ -41,7 +41,7 @@
   return result;
 }
 
-const base::flat_map<PackSpecPair, std::string>& GetAllDlcIds() {
+const base::flat_map<PackSpecPair, std::string>& GetAllLanguagePackDlcIds() {
   // Map of all DLCs and corresponding IDs.
   // It's a map from PackSpecPair to DLC ID. The pair is <feature id, locale>.
   // Whenever a new DLC is created, it needs to be added here.
@@ -65,15 +65,41 @@
   return *all_dlc_ids;
 }
 
+const base::flat_map<std::string, std::string>& GetAllBasePayloadDlcIds() {
+  // Map of all features and corresponding Base Payload DLC IDs.
+  static const base::NoDestructor<base::flat_map<std::string, std::string>>
+      all_dlc_ids({
+          {kHandwritingFeatureId, "handwriting"},
+      });
+
+  return *all_dlc_ids;
+}
+
 // Finds the ID of the DLC corresponding to the given spec.
 // Returns the DLC ID if the DLC exists or absl::nullopt otherwise.
-absl::optional<std::string> GetDlcId(const std::string& feature_id,
-                                     const std::string& locale) {
+absl::optional<std::string> GetDlcIdForLanguagePack(
+    const std::string& feature_id,
+    const std::string& locale) {
   // We search in the static list for the given Pack spec.
   const PackSpecPair spec(feature_id, locale);
-  const auto it = GetAllDlcIds().find(spec);
+  const auto it = GetAllLanguagePackDlcIds().find(spec);
 
-  if (it == GetAllDlcIds().end()) {
+  if (it == GetAllLanguagePackDlcIds().end()) {
+    return absl::nullopt;
+  }
+
+  return it->second;
+}
+
+// Finds the ID of the DLC corresponding to the Base Payload for a feature.
+// Returns the DLC ID if the feature has a Base Payload or absl::nullopt
+// otherwise.
+absl::optional<std::string> GetDlcIdForBasePayload(
+    const std::string& feature_id) {
+  // We search in the static list for the given |feature_id|.
+  const auto it = GetAllBasePayloadDlcIds().find(feature_id);
+
+  if (it == GetAllBasePayloadDlcIds().end()) {
     return absl::nullopt;
   }
 
@@ -138,13 +164,14 @@
                                           const std::string& locale) {
   // We search in the static list for the given Pack spec.
   const PackSpecPair spec(feature_id, locale);
-  return base::Contains(GetAllDlcIds(), spec);
+  return base::Contains(GetAllLanguagePackDlcIds(), spec);
 }
 
 void LanguagePackManager::InstallPack(const std::string& feature_id,
                                       const std::string& locale,
                                       OnInstallCompleteCallback callback) {
-  const absl::optional<std::string> dlc_id = GetDlcId(feature_id, locale);
+  const absl::optional<std::string> dlc_id =
+      GetDlcIdForLanguagePack(feature_id, locale);
 
   // If the given Language Pack doesn't exist, run callback and don't reach the
   // DLC Service.
@@ -167,7 +194,8 @@
 void LanguagePackManager::GetPackState(const std::string& feature_id,
                                        const std::string& locale,
                                        GetPackStateCallback callback) {
-  const absl::optional<std::string> dlc_id = GetDlcId(feature_id, locale);
+  const absl::optional<std::string> dlc_id =
+      GetDlcIdForLanguagePack(feature_id, locale);
 
   // If the given Language Pack doesn't exist, run callback and don't reach the
   // DLC Service.
@@ -186,7 +214,8 @@
 void LanguagePackManager::RemovePack(const std::string& feature_id,
                                      const std::string& locale,
                                      OnUninstallCompleteCallback callback) {
-  const absl::optional<std::string> dlc_id = GetDlcId(feature_id, locale);
+  const absl::optional<std::string> dlc_id =
+      GetDlcIdForLanguagePack(feature_id, locale);
 
   // If the given Language Pack doesn't exist, run callback and don't reach the
   // DLC Service.
@@ -202,6 +231,29 @@
       *dlc_id, base::BindOnce(&OnUninstallDlcComplete, std::move(callback)));
 }
 
+void LanguagePackManager::InstallBasePayload(
+    const std::string& feature_id,
+    OnInstallBasePayloadCompleteCallback callback) {
+  const absl::optional<std::string> dlc_id = GetDlcIdForBasePayload(feature_id);
+
+  // If the given |feature_id| doesn't have a Base Payload, run callback and
+  // don't reach the DLC Service.
+  if (!dlc_id) {
+    PackResult result;
+    result.operation_error = dlcservice::kErrorInvalidDlc;
+    result.pack_state = PackResult::WRONG_ID;
+    std::move(callback).Run(result);
+    return;
+  }
+
+  dlcservice::InstallRequest install_request;
+  install_request.set_id(*dlc_id);
+  DlcserviceClient::Get()->Install(
+      install_request,
+      base::BindOnce(&OnInstallDlcComplete, std::move(callback)),
+      base::DoNothing());
+}
+
 void LanguagePackManager::AddObserver(Observer* const observer) {
   observers_.AddObserver(observer);
 }
diff --git a/chromeos/language/language_packs/language_pack_manager.h b/chromeos/language/language_packs/language_pack_manager.h
index bd74063..03e51be7 100644
--- a/chromeos/language/language_packs/language_pack_manager.h
+++ b/chromeos/language/language_packs/language_pack_manager.h
@@ -19,7 +19,7 @@
 constexpr char kHandwritingFeatureId[] = "LP_ID_HANDWRITING";
 constexpr char kTtsFeatureId[] = "LP_ID_TTS";
 
-// Status contains information about the status of an operation.
+// Status contains information about the status of a Language Pack operation.
 struct PackResult {
   // This string contains the error returns by DLC Service.
   std::string operation_error;
@@ -79,8 +79,11 @@
     base::OnceCallback<void(const PackResult& pack_result)>;
 using OnUninstallCompleteCallback =
     base::OnceCallback<void(const PackResult& pack_result)>;
+using OnInstallBasePayloadCompleteCallback =
+    base::OnceCallback<void(const PackResult& pack_result)>;
 
-// This class manages all Language Packs on the device.
+// This class manages all Language Packs and their dependencies (called Base
+// Payloads) on the device.
 // This is a Singleton and needs to be accessed via Get().
 class LanguagePackManager : public DlcserviceClient::Observer {
  public:
@@ -108,6 +111,8 @@
   // Installs the Language Pack.
   // It takes a callback that will be triggered once the operation is done.
   // A state is passed to the callback.
+  // TODO(crbug.com/1320137): If |feature_id| has a corresponding Base Payload,
+  // then the Base Payload should be installed first.
   void InstallPack(const std::string& feature_id,
                    const std::string& locale,
                    OnInstallCompleteCallback callback);
@@ -132,6 +137,10 @@
                   const std::string& locale,
                   OnUninstallCompleteCallback callback);
 
+  // Explicitly installs the base payload for |feature_id|.
+  void InstallBasePayload(const std::string& feature_id,
+                          OnInstallBasePayloadCompleteCallback callback);
+
   // Adds an observer to the observer list.
   void AddObserver(Observer* observer);
 
diff --git a/chromeos/language/language_packs/language_pack_manager_unittest.cc b/chromeos/language/language_packs/language_pack_manager_unittest.cc
index d47807104..fff98f6 100644
--- a/chromeos/language/language_packs/language_pack_manager_unittest.cc
+++ b/chromeos/language/language_packs/language_pack_manager_unittest.cc
@@ -329,5 +329,35 @@
   EXPECT_FALSE(available);
 }
 
+TEST_F(LanguagePackManagerTest, InstallBasePayloadSuccess) {
+  dlcservice_client_->set_install_error(dlcservice::kErrorNone);
+  dlcservice_client_->set_install_root_path("/path");
+
+  // We need to use an existing Pack ID, so that we do get a result back.
+  manager_->InstallBasePayload(
+      kHandwritingFeatureId,
+      base::BindOnce(&LanguagePackManagerTest::InstallTestCallback,
+                     base::Unretained(this)));
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(pack_result_.operation_error, dlcservice::kErrorNone);
+  EXPECT_EQ(pack_result_.pack_state, PackResult::INSTALLED);
+  EXPECT_EQ(pack_result_.path, "/path");
+}
+
+TEST_F(LanguagePackManagerTest, InstallBasePayloadFailureTestFailure) {
+  dlcservice_client_->set_install_error(dlcservice::kErrorInternal);
+
+  // We need to use an existing Pack ID, so that we do get a result back.
+  manager_->InstallBasePayload(
+      kHandwritingFeatureId,
+      base::BindOnce(&LanguagePackManagerTest::InstallTestCallback,
+                     base::Unretained(this)));
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(pack_result_.operation_error, dlcservice::kErrorInternal);
+  EXPECT_NE(pack_result_.pack_state, PackResult::INSTALLED);
+}
+
 }  // namespace language_packs
 }  // namespace chromeos
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt
index a88e16c9..d06a06d 100644
--- a/chromeos/profiles/orderfile.newest.txt
+++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@
-chromeos-chrome-orderfile-field-102-4992.0-1650276262-benchmark-102.0.5005.20-r1.orderfile.xz
+chromeos-chrome-orderfile-field-102-5005.6-1650882860-benchmark-102.0.5005.35-r1.orderfile.xz
diff --git a/chromeos/strings/chromeos_strings_kk.xtb b/chromeos/strings/chromeos_strings_kk.xtb
index 96ba76c..6f23453 100644
--- a/chromeos/strings/chromeos_strings_kk.xtb
+++ b/chromeos/strings/chromeos_strings_kk.xtb
@@ -25,6 +25,7 @@
 <translation id="1204296502688602597">DNS кідірісі</translation>
 <translation id="123124571410524056">Портал болуы мүмкін.</translation>
 <translation id="1238612778414822719">HTTPS кідірісі</translation>
+<translation id="1264116747675686718">Операциялық жүйенің нұсқасы жаңартылып жатыр.</translation>
 <translation id="1264369926465113395">Chromebook құрылғысының авторларға арналған жаңа цифрлық журналын қараңыз.</translation>
 <translation id="1270369111467284986">Адаптивті портал болуы мүмкін.</translation>
 <translation id="1290331692326790741">Әлсіз сигнал</translation>
@@ -121,6 +122,7 @@
 <translation id="2158971754079422508"><ph name="DESC_TEXT" />: Қайталау</translation>
 <translation id="2161394479394250669">Баспа жұмысынан бас тарту</translation>
 <translation id="2163937499206714165">Қараңғы режимді қосу</translation>
+<translation id="2177831236093724629"><ph name="LINK_BEGIN" />Үйлеспейтін құрамдастар<ph name="LINK_END" /> табылды. Барлық сәйкес құрамдастың анықталғанын тексеру үшін Chrome OS жүйесін соңғы нұсқаға жаңартыңыз.</translation>
 <translation id="2180197493692062006">Бірдеңе дұрыс болмады. Қолданбаны қайта ашып көріңіз.</translation>
 <translation id="2209788852729124853">Трафик есептегіштерін нөлдеу</translation>
 <translation id="2212733584906323460">Атаулар ажыратымдылығы</translation>
@@ -203,6 +205,7 @@
 <translation id="3188257591659621405">Файлдарым</translation>
 <translation id="3192947282887913208">Аудио файлдары</translation>
 <translation id="3199982728237701504">Құжат беруші (екі жақты)</translation>
+<translation id="320091191259649613">Жаңартылғаннан кейін қате кетпесе, құрамдас жаңадан бейімделіп, дерекқорға әлі енгізілмеген болуы мүмкін.</translation>
 <translation id="3226405216343213872">Сканерлер ізделуде</translation>
 <translation id="3246869037381808805">1 күннен асқан баспа жұмыстары өшіріледі.</translation>
 <translation id="3268178239013324452">Сәтсіз: есігі ашық</translation>
@@ -377,6 +380,7 @@
 <translation id="4985509611418653372">Іске қосу</translation>
 <translation id="4987769320337599931">Брандмауэр</translation>
 <translation id="4999333166442584738">Есепті жасыру</translation>
+<translation id="5008611843832219958">Жөндеу процесінің артықшылықтарын пайдалану үшін Chrome OS жүйесінің соңғы нұсқасын орнатыңыз.</translation>
 <translation id="500920857929044050">Тексеруді тоқтату</translation>
 <translation id="5017508259293544172">LEAP</translation>
 <translation id="5019310272469539976">Экран пайдаланылмай тұрғанда, фотосуреттерді, уақытты, ауа райын және медиа ақпаратын көрсетеді.</translation>
@@ -430,6 +434,7 @@
 <translation id="5493614766091057239"><ph name="VERDICT" />: <ph name="PROBLEMS" /></translation>
 <translation id="5499114900554609492">Сканерлеу аяқталмады</translation>
 <translation id="5502931783115429516">Android іске қосылмаған.</translation>
+<translation id="5507300744274596613">Chrome OS жүйесінің жаңартылғанын тексеріңіз</translation>
 <translation id="5519195206574732858">LTE</translation>
 <translation id="554517032089923082">GTC</translation>
 <translation id="5578477003638479617">UMTS</translation>
@@ -468,6 +473,7 @@
 <translation id="5939518447894949180">Қалпына келтіру</translation>
 <translation id="594552776027197022">Кездейсоқ кілттер жұбын жасау</translation>
 <translation id="5972388717451707488">Update Engine</translation>
+<translation id="5984145644188835034">Әдепкі тұсқағаз</translation>
 <translation id="6034694447310538551">Ай сайын автоматты түрде бастапқы күйге қайтаруды қосу</translation>
 <translation id="6037291330010597344">Сканердің құжат бергіші бос. Құжаттар қосып, әрекетті қайталаңыз.</translation>
 <translation id="6040143037577758943">Жабу</translation>
@@ -717,6 +723,7 @@
 <translation id="8655295600908251630">Арна</translation>
 <translation id="8660881923941176839">фунт</translation>
 <translation id="8662671328352114214"><ph name="TYPE" /> желісіне қосылу</translation>
+<translation id="8671972493856476349"><ph name="VERSION_NUMBER" /> нұсқасына жаңарту және өшіріп қосу</translation>
 <translation id="8675354002693747642">Алдын ала бөлісілген код</translation>
 <translation id="8677859815076891398">Альбомдар жоқ. <ph name="LINK_BEGIN" />Google Photos<ph name="LINK_END" /> қызметінде альбом жасаңыз.</translation>
 <translation id="8709616837707653427"><ph name="DESC_TEXT" /> Бұл функцияны басқару үшін сол немесе оң жаққа бағыттауыш пернелерді пайдаланыңыз.</translation>
@@ -781,6 +788,7 @@
 <translation id="917720651393141712">Тексеру</translation>
 <translation id="9204237731135241582">Android қолданбаларынан шлюзге қосылу мүмкін емес.</translation>
 <translation id="9211490828691860325">Барлық жұмыс үстелдері</translation>
+<translation id="922179502584117429">Қазіргі <ph name="VERSION_NUMBER" /> нұсқасы ескірген.</translation>
 <translation id="932327136139879170">Негізгі бет</translation>
 <translation id="939519157834106403">SSID</translation>
 <translation id="952992212772159698">Белсендірілмеген</translation>
diff --git a/components/content_capture/browser/content_capture_receiver.cc b/components/content_capture/browser/content_capture_receiver.cc
index 7c82d61..3a31638 100644
--- a/components/content_capture/browser/content_capture_receiver.cc
+++ b/components/content_capture/browser/content_capture_receiver.cc
@@ -222,12 +222,11 @@
 }
 
 void ContentCaptureReceiver::RetrieveFaviconURL() {
-  if (!rfh()->IsActive() || rfh()->GetMainFrame() != rfh() ||
+  if (!rfh()->IsActive() || !rfh()->IsInPrimaryMainFrame() ||
       disable_get_favicon_from_web_contents_for_testing()) {
     frame_content_capture_data_.favicon = std::string();
   } else {
-    frame_content_capture_data_.favicon = ToJSON(
-        content::WebContents::FromRenderFrameHost(rfh())->GetFaviconURLs());
+    frame_content_capture_data_.favicon = ToJSON(rfh()->FaviconURLs());
   }
 }
 
diff --git a/components/content_capture/browser/content_capture_receiver_browsertest.cc b/components/content_capture/browser/content_capture_receiver_browsertest.cc
index c640738d..cdc4a14 100644
--- a/components/content_capture/browser/content_capture_receiver_browsertest.cc
+++ b/components/content_capture/browser/content_capture_receiver_browsertest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/json/json_reader.h"
 #include "components/content_capture/browser/content_capture_test_helper.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/content_browser_test.h"
@@ -109,4 +110,56 @@
             consumer()->captured_data());
 }
 
+IN_PROC_BROWSER_TEST_F(ContentCaptureBrowserTest,
+                       DoNotUpdateFaviconURLsInFencedFrame) {
+  // Simulate to capture the content from main frame.
+  main_frame_sender()->DidCaptureContent(helper()->test_data(),
+                                         true /* first_data */);
+
+  // Simulate to capture the content from fenced frame.
+  fenced_frame_sender()->DidCaptureContent(helper()->test_data2(),
+                                           true /* first_data */);
+
+  // Insert the favicon dynamically to the primary main frame.
+  ASSERT_TRUE(ExecJs(web_contents(),
+                     "let l = document.createElement('link');"
+                     "l.rel='icon'; l.type='image/png'; "
+                     "l.href='https://example.com/favicon.ico';"
+                     "document.head.appendChild(l)"));
+
+  std::string expected_json =
+      R"JSON([{
+          "type":"favicon",
+          "url":"https://example.com/favicon.ico"
+      }])JSON";
+  absl::optional<base::Value> expected = base::JSONReader::Read(expected_json);
+
+  // Verify that the captured data's favicon url from the primary main frame is
+  // valid.
+  auto* main_frame_receiver =
+      provider()->ContentCaptureReceiverForFrameForTesting(main_frame_);
+  absl::optional<base::Value> main_frame_actual = base::JSONReader::Read(
+      main_frame_receiver->GetContentCaptureFrame().favicon);
+  EXPECT_TRUE(main_frame_actual);
+  EXPECT_EQ(expected, main_frame_actual);
+
+  // Verify that the captured data's favicon url from the fenced frame is empty.
+  auto* fenced_frame_receiver =
+      provider()->ContentCaptureReceiverForFrameForTesting(fenced_frame_);
+  EXPECT_FALSE(base::JSONReader::Read(
+      fenced_frame_receiver->GetContentCaptureFrame().favicon));
+
+  // Insert the favicon dynamically to the fenced frame.
+  ASSERT_TRUE(ExecJs(fenced_frame_.get(),
+                     "let l = document.createElement('link');"
+                     "l.rel='icon'; l.type='image/png'; "
+                     "l.href='https://example.com/favicon.ico';"
+                     "document.head.appendChild(l)"));
+
+  // Verify that the captured data's favicon url from the fenced frame is still
+  // empty.
+  EXPECT_FALSE(base::JSONReader::Read(
+      fenced_frame_receiver->GetContentCaptureFrame().favicon));
+}
+
 }  // namespace content_capture
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn
index 76204c9..31994fd 100644
--- a/components/exo/wayland/BUILD.gn
+++ b/components/exo/wayland/BUILD.gn
@@ -208,6 +208,7 @@
     if (enable_color_manager) {
       deps += [
         "//components/exo/wayland/protocol:chrome_color_management_protocol",
+        "//ui/base/wayland:color_manager_util",
       ]
       sources += [
         "zcr_color_manager.cc",
diff --git a/components/exo/wayland/zcr_color_manager.cc b/components/exo/wayland/zcr_color_manager.cc
index cc3d7a9..3ee8b75 100644
--- a/components/exo/wayland/zcr_color_manager.cc
+++ b/components/exo/wayland/zcr_color_manager.cc
@@ -20,6 +20,7 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColorSpace.h"
 #include "third_party/skia/include/third_party/skcms/skcms.h"
+#include "ui/base/wayland/color_manager_util.h"
 #include "ui/gfx/color_space.h"
 #include "ui/gfx/display_color_spaces.h"
 #include "ui/gfx/geometry/triangle_f.h"
@@ -33,42 +34,6 @@
 
 constexpr auto kDefaultColorSpace = gfx::ColorSpace::CreateSRGB();
 
-constexpr auto kChromaticityMap =
-    base::MakeFixedFlatMap<zcr_color_manager_v1_chromaticity_names,
-                           gfx::ColorSpace::PrimaryID>(
-        {{ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_BT601_525_LINE,
-          gfx::ColorSpace::PrimaryID::SMPTE170M},
-         {ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_BT601_625_LINE,
-          gfx::ColorSpace::PrimaryID::BT470BG},
-         {ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_SMPTE170M,
-          gfx::ColorSpace::PrimaryID::SMPTE170M},
-         {ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_BT709,
-          gfx::ColorSpace::PrimaryID::BT709},
-         {ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_BT2020,
-          gfx::ColorSpace::PrimaryID::BT2020},
-         {ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_SRGB,
-          gfx::ColorSpace::PrimaryID::BT709},
-         {ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_DISPLAYP3,
-          gfx::ColorSpace::PrimaryID::P3},
-         {ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_ADOBERGB,
-          gfx::ColorSpace::PrimaryID::ADOBE_RGB}});
-
-constexpr auto kEotfMap =
-    base::MakeFixedFlatMap<zcr_color_manager_v1_eotf_names,
-                           gfx::ColorSpace::TransferID>({
-        {ZCR_COLOR_MANAGER_V1_EOTF_NAMES_LINEAR,
-         gfx::ColorSpace::TransferID::LINEAR},
-        {ZCR_COLOR_MANAGER_V1_EOTF_NAMES_SRGB,
-         gfx::ColorSpace::TransferID::BT709},
-        {ZCR_COLOR_MANAGER_V1_EOTF_NAMES_BT2087,
-         gfx::ColorSpace::TransferID::GAMMA24},
-        {ZCR_COLOR_MANAGER_V1_EOTF_NAMES_ADOBERGB,
-         // This is ever so slightly inaccurate. The number ought to be
-         // 2.19921875f, not 2.2
-         gfx::ColorSpace::TransferID::GAMMA22},
-        {ZCR_COLOR_MANAGER_V1_EOTF_NAMES_PQ, gfx::ColorSpace::TransferID::PQ},
-    });
-
 // Wrapper around a |gfx::ColorSpace| that tracks additional data useful to the
 // protocol. These live as wayland resource data.
 class ColorManagerColorSpace {
@@ -315,8 +280,8 @@
   uint32_t error_flags = 0;
 
   auto chromaticity_id = gfx::ColorSpace::PrimaryID::INVALID;
-  const auto* maybe_primary = kChromaticityMap.find(chromaticity);
-  if (maybe_primary != std::end(kChromaticityMap)) {
+  const auto* maybe_primary = ui::wayland::kChromaticityMap.find(chromaticity);
+  if (maybe_primary != std::end(ui::wayland::kChromaticityMap)) {
     chromaticity_id = maybe_primary->second;
   } else {
     DLOG(ERROR) << "Unable to find named chromaticity for id=" << chromaticity;
@@ -324,8 +289,8 @@
   }
 
   auto eotf_id = gfx::ColorSpace::TransferID::INVALID;
-  const auto* maybe_eotf = kEotfMap.find(eotf);
-  if (maybe_eotf != std::end(kEotfMap)) {
+  const auto* maybe_eotf = ui::wayland::kEotfMap.find(eotf);
+  if (maybe_eotf != std::end(ui::wayland::kEotfMap)) {
     eotf_id = maybe_eotf->second;
   } else {
     DLOG(ERROR) << "Unable to find named eotf for id=" << eotf;
@@ -382,8 +347,8 @@
   }
 
   auto eotf_id = gfx::ColorSpace::TransferID::INVALID;
-  const auto* maybe_eotf = kEotfMap.find(eotf);
-  if (maybe_eotf != std::end(kEotfMap)) {
+  const auto* maybe_eotf = ui::wayland::kEotfMap.find(eotf);
+  if (maybe_eotf != std::end(ui::wayland::kEotfMap)) {
     eotf_id = maybe_eotf->second;
   } else {
     DLOG(ERROR) << "Unable to find named transfer function for id=" << eotf;
diff --git a/components/policy/resources/policy_templates_vi.xtb b/components/policy/resources/policy_templates_vi.xtb
index 231e312..3a1e22a 100644
--- a/components/policy/resources/policy_templates_vi.xtb
+++ b/components/policy/resources/policy_templates_vi.xtb
@@ -2996,7 +2996,7 @@
 <translation id="4192388905594723944">URL để xác thực mã thông báo xác thực ứng dụng truy cập từ xa</translation>
 <translation id="4203055629055264833">Nếu bạn đặt chính sách này thành Bật hoặc không đặt, thì người dùng có thể đưa trang kết quả mới đây nhất của công cụ tìm kiếm mặc định vào một bảng điều khiển bên bằng cách bật/tắt một biểu tượng trong thanh công cụ.
 
-      Thao tác đặt chính sách này thành Tắt sẽ xoá một biểu tượng khỏi thanh công cụ, biểu tượng này mở ra bảng điều khiển bên chứa trang kết quả của công cụ tìm kiếm mặc định.</translation>
+      Nếu bạn đặt chính sách này thành Tắt, biểu tượng bật/tắt sẽ bị xoá khỏi thanh công cụ và người dùng sẽ không thể mở bảng điều khiển bên để xem trang kết quả tìm kiếm của công cụ tìm kiếm mặc định.</translation>
 <translation id="4203643479966921607">Nếu bạn đặt chính sách này thành Bật hoặc không đặt chính sách này, thì <ph name="PRODUCT_NAME" /> sẽ được bật. Người dùng có thể chạy ứng dụng này từ trình đơn ứng dụng, trình đơn ngữ cảnh của trang, các chức năng điều khiển nội dung đa phương tiện trên trang web hỗ trợ Cast và biểu tượng thanh công cụ Cast (nếu hiển thị).
 
       Nếu bạn đặt chính sách này thành Tắt, thì <ph name="PRODUCT_NAME" /> sẽ bị tắt.</translation>
diff --git a/components/services/app_service/BUILD.gn b/components/services/app_service/BUILD.gn
index 264cbc5c..9428e1b 100644
--- a/components/services/app_service/BUILD.gn
+++ b/components/services/app_service/BUILD.gn
@@ -14,6 +14,7 @@
   ]
 
   public_deps = [
+    "//components/services/app_service/public/cpp:app_types",
     "//components/services/app_service/public/cpp:intents",
     "//components/services/app_service/public/cpp:preferred_app",
     "//components/services/app_service/public/cpp:preferred_apps",
diff --git a/components/services/app_service/app_service_mojom_impl.cc b/components/services/app_service/app_service_mojom_impl.cc
index 2a262a708..e1cd651c 100644
--- a/components/services/app_service/app_service_mojom_impl.cc
+++ b/components/services/app_service/app_service_mojom_impl.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/threading/scoped_blocking_call.h"
+#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/cpp/intent_filter_util.h"
 #include "components/services/app_service/public/cpp/preferred_app.h"
 #include "components/services/app_service/public/cpp/preferred_apps_list.h"
@@ -31,11 +32,13 @@
 AppServiceMojomImpl::AppServiceMojomImpl(
     const base::FilePath& profile_dir,
     base::OnceClosure read_completed_for_testing,
-    base::OnceClosure write_completed_for_testing)
-    : preferred_apps_(this,
-                      profile_dir,
-                      std::move(read_completed_for_testing),
-                      std::move(write_completed_for_testing)) {}
+    base::OnceClosure write_completed_for_testing) {
+  if (!base::FeatureList::IsEnabled(kAppServicePreferredAppsWithoutMojom)) {
+    preferred_apps_impl_ = std::make_unique<PreferredAppsImpl>(
+        this, profile_dir, std::move(read_completed_for_testing),
+        std::move(write_completed_for_testing));
+  }
+}
 
 AppServiceMojomImpl::~AppServiceMojomImpl() = default;
 
@@ -82,10 +85,11 @@
   // TODO: store the opts somewhere.
 
   // Initialise the Preferred Apps in the Subscribers on register.
-  if (preferred_apps_.preferred_apps_list_.IsInitialized()) {
+  if (preferred_apps_impl_ &&
+      preferred_apps_impl_->preferred_apps_list_.IsInitialized()) {
     subscriber->InitializePreferredApps(
         ConvertPreferredAppsToMojomPreferredApps(
-            preferred_apps_.preferred_apps_list_.GetValue()));
+            preferred_apps_impl_->preferred_apps_list_.GetValue()));
   }
 
   // Add the new subscriber to the set.
@@ -250,35 +254,46 @@
     apps::mojom::IntentFilterPtr intent_filter,
     apps::mojom::IntentPtr intent,
     bool from_publisher) {
-  preferred_apps_.AddPreferredApp(app_type, app_id, std::move(intent_filter),
-                                  std::move(intent), from_publisher);
+  if (preferred_apps_impl_) {
+    preferred_apps_impl_->AddPreferredApp(app_type, app_id,
+                                          std::move(intent_filter),
+                                          std::move(intent), from_publisher);
+  }
 }
 
 void AppServiceMojomImpl::RemovePreferredApp(apps::mojom::AppType app_type,
                                              const std::string& app_id) {
-  preferred_apps_.RemovePreferredApp(app_type, app_id);
+  if (preferred_apps_impl_) {
+    preferred_apps_impl_->RemovePreferredApp(app_type, app_id);
+  }
 }
 
 void AppServiceMojomImpl::RemovePreferredAppForFilter(
     apps::mojom::AppType app_type,
     const std::string& app_id,
     apps::mojom::IntentFilterPtr intent_filter) {
-  preferred_apps_.RemovePreferredAppForFilter(app_type, app_id,
-                                              std::move(intent_filter));
+  if (preferred_apps_impl_) {
+    preferred_apps_impl_->RemovePreferredAppForFilter(app_type, app_id,
+                                                      std::move(intent_filter));
+  }
 }
 
 void AppServiceMojomImpl::SetSupportedLinksPreference(
     apps::mojom::AppType app_type,
     const std::string& app_id,
     std::vector<apps::mojom::IntentFilterPtr> all_link_filters) {
-  preferred_apps_.SetSupportedLinksPreference(app_type, app_id,
-                                              std::move(all_link_filters));
+  if (preferred_apps_impl_) {
+    preferred_apps_impl_->SetSupportedLinksPreference(
+        app_type, app_id, std::move(all_link_filters));
+  }
 }
 
 void AppServiceMojomImpl::RemoveSupportedLinksPreference(
     apps::mojom::AppType app_type,
     const std::string& app_id) {
-  preferred_apps_.RemoveSupportedLinksPreference(app_type, app_id);
+  if (preferred_apps_impl_) {
+    preferred_apps_impl_->RemoveSupportedLinksPreference(app_type, app_id);
+  }
 }
 
 void AppServiceMojomImpl::SetResizeLocked(apps::mojom::AppType app_type,
@@ -313,10 +328,14 @@
 }
 
 void AppServiceMojomImpl::InitializePreferredAppsForAllSubscribers() {
+  if (!preferred_apps_impl_) {
+    return;
+  }
+
   for (auto& subscriber : subscribers_) {
     subscriber->InitializePreferredApps(
         ConvertPreferredAppsToMojomPreferredApps(
-            preferred_apps_.preferred_apps_list_.GetValue()));
+            preferred_apps_impl_->preferred_apps_list_.GetValue()));
   }
 }
 
@@ -331,11 +350,12 @@
     const std::string& app_id,
     apps::mojom::IntentFilterPtr intent_filter,
     apps::mojom::IntentPtr intent,
-    apps::mojom::ReplacedAppPreferencesPtr replaced_app_preferences) {
+    ReplacedAppPreferences replaced_app_preferences) {
   for (const auto& iter : publishers_) {
-    iter.second->OnPreferredAppSet(app_id, intent_filter->Clone(),
-                                   intent->Clone(),
-                                   replaced_app_preferences->Clone());
+    iter.second->OnPreferredAppSet(
+        app_id, intent_filter->Clone(), intent->Clone(),
+        ConvertReplacedAppPreferencesToMojomReplacedAppPreferences(
+            replaced_app_preferences));
   }
 }
 
@@ -347,17 +367,20 @@
   }
 }
 
-apps::mojom::Publisher* AppServiceMojomImpl::GetMojomPublisher(
-    apps::mojom::AppType app_type) {
-  auto iter = publishers_.find(app_type);
-  if (iter == publishers_.end()) {
-    return nullptr;
-  }
-  return iter->second.get();
+void AppServiceMojomImpl::OnSupportedLinksPreferenceChanged(
+    AppType app_type,
+    const std::string& app_id,
+    bool open_in_app) {
+  publishers_[ConvertAppTypeToMojomAppType(app_type)]
+      ->OnSupportedLinksPreferenceChanged(app_id, open_in_app);
+}
+
+bool AppServiceMojomImpl::HasPublisher(AppType app_type) {
+  return base::Contains(publishers_, ConvertAppTypeToMojomAppType(app_type));
 }
 
 PreferredAppsList& AppServiceMojomImpl::GetPreferredAppsListForTesting() {
-  return preferred_apps_.preferred_apps_list_;
+  return preferred_apps_impl_->preferred_apps_list_;
 }
 
 void AppServiceMojomImpl::OnPublisherDisconnected(
diff --git a/components/services/app_service/app_service_mojom_impl.h b/components/services/app_service/app_service_mojom_impl.h
index abce122..6d2acfbf 100644
--- a/components/services/app_service/app_service_mojom_impl.h
+++ b/components/services/app_service/app_service_mojom_impl.h
@@ -6,8 +6,11 @@
 #define COMPONENTS_SERVICES_APP_SERVICE_APP_SERVICE_MOJOM_IMPL_H_
 
 #include <map>
+#include <memory>
 
 #include "base/files/file_path.h"
+#include "components/services/app_service/public/cpp/app_types.h"
+#include "components/services/app_service/public/cpp/preferred_app.h"
 #include "components/services/app_service/public/cpp/preferred_apps_impl.h"
 #include "components/services/app_service/public/mojom/app_service.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -135,15 +138,18 @@
       const std::string& app_id,
       apps::mojom::IntentFilterPtr intent_filter,
       apps::mojom::IntentPtr intent,
-      apps::mojom::ReplacedAppPreferencesPtr replaced_app_preferences) override;
+      ReplacedAppPreferences replaced_app_preferences) override;
 
   void OnSupportedLinksPreferenceChanged(const std::string& app_id,
                                          bool open_in_app) override;
 
-  // Returns publisher for `app_type`, or nullptr if there is no publisher for
-  // `app_type`.
-  apps::mojom::Publisher* GetMojomPublisher(
-      apps::mojom::AppType app_type) override;
+  void OnSupportedLinksPreferenceChanged(AppType app_type,
+                                         const std::string& app_id,
+                                         bool open_in_app) override;
+
+  // Returns true if there is a publisher for `app_type`. Otherwise, returns
+  // false.
+  bool HasPublisher(AppType app_type) override;
 
   // Retern the preferred_apps_list_ for testing.
   PreferredAppsList& GetPreferredAppsListForTesting();
@@ -161,7 +167,7 @@
   // destroyed first, closing the connection to avoid dangling callbacks.
   mojo::ReceiverSet<apps::mojom::AppService> receivers_;
 
-  PreferredAppsImpl preferred_apps_;
+  std::unique_ptr<PreferredAppsImpl> preferred_apps_impl_;
 };
 
 }  // namespace apps
diff --git a/components/services/app_service/app_service_mojom_impl_unittest.cc b/components/services/app_service/app_service_mojom_impl_unittest.cc
index 55caac01..2756678 100644
--- a/components/services/app_service/app_service_mojom_impl_unittest.cc
+++ b/components/services/app_service/app_service_mojom_impl_unittest.cc
@@ -11,8 +11,10 @@
 #include "base/callback.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
 #include "components/services/app_service/app_service_mojom_impl.h"
 #include "components/services/app_service/public/cpp/app_capability_access_cache.h"
+#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/intent_filter_util.h"
 #include "components/services/app_service/public/cpp/intent_test_util.h"
@@ -246,8 +248,14 @@
 
 class AppServiceMojomImplTest : public testing::Test {
  protected:
+  AppServiceMojomImplTest() {
+    scoped_feature_list_.InitAndDisableFeature(
+        kAppServicePreferredAppsWithoutMojom);
+  }
+
   content::BrowserTaskEnvironment task_environment_;
   base::ScopedTempDir temp_dir_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 TEST_F(AppServiceMojomImplTest, PubSub) {
@@ -517,7 +525,7 @@
   std::vector<std::string> mime_types({"image/png"});
   ASSERT_EQ(kAppId1,
             impl.GetPreferredAppsListForTesting().FindPreferredAppForIntent(
-                std::make_unique<Intent>(filesystem_urls, mime_types)));
+                apps_util::MakeShareIntent(filesystem_urls, mime_types)));
   ASSERT_EQ(
       kAppId2,
       impl.GetPreferredAppsListForTesting().FindPreferredAppForUrl(filter_url));
diff --git a/components/services/app_service/public/cpp/BUILD.gn b/components/services/app_service/public/cpp/BUILD.gn
index 3c9eb445..b510282 100644
--- a/components/services/app_service/public/cpp/BUILD.gn
+++ b/components/services/app_service/public/cpp/BUILD.gn
@@ -49,6 +49,8 @@
   sources = [
     "app_types.cc",
     "app_types.h",
+    "features.cc",
+    "features.h",
     "intent_filter.cc",
     "intent_filter.h",
     "macros.h",
@@ -83,8 +85,6 @@
     "app_update.h",
     "capability_access_update.cc",
     "capability_access_update.h",
-    "features.cc",
-    "features.h",
     "macros.h",
   ]
 
diff --git a/components/services/app_service/public/cpp/app_types.h b/components/services/app_service/public/cpp/app_types.h
index b2e371d..5bd3b34 100644
--- a/components/services/app_service/public/cpp/app_types.h
+++ b/components/services/app_service/public/cpp/app_types.h
@@ -216,7 +216,7 @@
 AppType ConvertMojomAppTypToAppType(apps::mojom::AppType mojom_app_type);
 
 COMPONENT_EXPORT(APP_TYPES)
-mojom::AppType ConvertAppTypeToMojomAppType(AppType mojom_app_type);
+mojom::AppType ConvertAppTypeToMojomAppType(AppType app_type);
 
 COMPONENT_EXPORT(APP_TYPES)
 Readiness ConvertMojomReadinessToReadiness(
diff --git a/components/services/app_service/public/cpp/features.cc b/components/services/app_service/public/cpp/features.cc
index 5f484b9..38788c3 100644
--- a/components/services/app_service/public/cpp/features.cc
+++ b/components/services/app_service/public/cpp/features.cc
@@ -13,10 +13,10 @@
 const base::Feature kAppServiceOnAppUpdateWithoutMojom{
     "AppServiceOnAppUpdateWithoutMojom", base::FEATURE_ENABLED_BY_DEFAULT};
 
-const base::Feature AppServiceCrosApiOnAppsWithoutMojom{
+const base::Feature kAppServiceCrosApiOnAppsWithoutMojom{
     "AppServiceCrosApiOnAppsWithoutMojom", base::FEATURE_ENABLED_BY_DEFAULT};
 
-const base::Feature AppServicePreferredAppsWithoutMojom{
+const base::Feature kAppServicePreferredAppsWithoutMojom{
     "AppServicePreferredAppsWithoutMojom", base::FEATURE_DISABLED_BY_DEFAULT};
 
 }  // namespace apps
diff --git a/components/services/app_service/public/cpp/features.h b/components/services/app_service/public/cpp/features.h
index 7513e26..612d2a8 100644
--- a/components/services/app_service/public/cpp/features.h
+++ b/components/services/app_service/public/cpp/features.h
@@ -10,14 +10,14 @@
 
 namespace apps {
 
-COMPONENT_EXPORT(APP_UPDATE)
+COMPONENT_EXPORT(APP_TYPES)
 extern const base::Feature kAppServiceOnAppTypeInitializedWithoutMojom;
-COMPONENT_EXPORT(APP_UPDATE)
+COMPONENT_EXPORT(APP_TYPES)
 extern const base::Feature kAppServiceOnAppUpdateWithoutMojom;
-COMPONENT_EXPORT(APP_UPDATE)
-extern const base::Feature AppServiceCrosApiOnAppsWithoutMojom;
-COMPONENT_EXPORT(APP_UPDATE)
-extern const base::Feature AppServicePreferredAppsWithoutMojom;
+COMPONENT_EXPORT(APP_TYPES)
+extern const base::Feature kAppServiceCrosApiOnAppsWithoutMojom;
+COMPONENT_EXPORT(APP_TYPES)
+extern const base::Feature kAppServicePreferredAppsWithoutMojom;
 
 }  // namespace apps
 
diff --git a/components/services/app_service/public/cpp/intent.cc b/components/services/app_service/public/cpp/intent.cc
index 5189c2b8..fa811cd 100644
--- a/components/services/app_service/public/cpp/intent.cc
+++ b/components/services/app_service/public/cpp/intent.cc
@@ -51,47 +51,11 @@
 
 Intent::Intent(const std::string& action) : action(action) {}
 
-Intent::Intent(const GURL& url)
-    : action(apps_util::kIntentActionView), url(url) {}
+Intent::Intent(const std::string& action, const GURL& url)
+    : action(action), url(url) {}
 
-Intent::Intent(const std::vector<GURL>& filesystem_urls,
-               const std::vector<std::string>& mime_types)
-    : action(filesystem_urls.size() == 1
-                 ? apps_util::kIntentActionSend
-                 : apps_util::kIntentActionSendMultiple),
-      mime_type(apps_util::CalculateCommonMimeType(mime_types)) {
-  DCHECK_EQ(filesystem_urls.size(), mime_types.size());
-  for (size_t i = 0; i < filesystem_urls.size(); i++) {
-    auto file = std::make_unique<IntentFile>(filesystem_urls[i]);
-    file->mime_type = mime_types.at(i);
-    files.push_back(std::move(file));
-  }
-}
-
-Intent::Intent(std::vector<IntentFilePtr> files)
-    : action(apps_util::kIntentActionView), files(std::move(files)) {}
-
-Intent::Intent(const std::vector<GURL>& filesystem_urls,
-               const std::vector<std::string>& mime_types,
-               const std::string& text,
-               const std::string& title)
-    : Intent(filesystem_urls, mime_types) {
-  if (!text.empty()) {
-    share_text = text;
-  }
-  if (!title.empty()) {
-    share_title = title;
-  }
-}
-
-Intent::Intent(const std::string& text, const std::string& title)
-    : Intent(apps_util::kIntentActionSend) {
-  mime_type = "text/plain";
-  share_text = text;
-  if (!title.empty()) {
-    share_title = title;
-  }
-}
+Intent::Intent(const std::string& action, std::vector<IntentFilePtr> files)
+    : action(action), files(std::move(files)) {}
 
 Intent::~Intent() = default;
 
diff --git a/components/services/app_service/public/cpp/intent.h b/components/services/app_service/public/cpp/intent.h
index a067e0c..b79c955 100644
--- a/components/services/app_service/public/cpp/intent.h
+++ b/components/services/app_service/public/cpp/intent.h
@@ -58,26 +58,11 @@
 // ConvertIntentToValue and ConvertValueToIntent in
 // components/services/app_service/public/cpp/intent_util.*
 struct Intent {
+  // Factory methods for more complicated Intents are available in
+  // intent_util.h.
   explicit Intent(const std::string& action);
-  explicit Intent(const GURL& url);
-
-  // Creates an intent for sharing `filesystem_urls`. `filesystem_urls` must be
-  // co-indexed with `mime_types`.
-  Intent(const std::vector<GURL>& filesystem_urls,
-         const std::vector<std::string>& mime_types);
-
-  // Creates an intent with the list of `files`.
-  explicit Intent(std::vector<IntentFilePtr> files);
-
-  // Creates an intent for sharing `filesystem_urls`, along with `text` content
-  // and `title`. `filesystem_urls` must be co-indexed with  mime_types.
-  Intent(const std::vector<GURL>& filesystem_urls,
-         const std::vector<std::string>& mime_types,
-         const std::string& text,
-         const std::string& title);
-
-  // Creates an intent for sharing `text`, with `title`.
-  Intent(const std::string& text, const std::string& title);
+  explicit Intent(const std::string& action, const GURL& url);
+  explicit Intent(const std::string& action, std::vector<IntentFilePtr> files);
 
   Intent(const Intent&) = delete;
   Intent& operator=(const Intent&) = delete;
diff --git a/components/services/app_service/public/cpp/intent_filter.cc b/components/services/app_service/public/cpp/intent_filter.cc
index 3829423a..96ed7fe5 100644
--- a/components/services/app_service/public/cpp/intent_filter.cc
+++ b/components/services/app_service/public/cpp/intent_filter.cc
@@ -322,10 +322,9 @@
   return ret;
 }
 
-base::flat_map<std::string, apps::IntentFilters> CloneIntentFiltersMap(
-    const base::flat_map<std::string, apps::IntentFilters>&
-        intent_filters_map) {
-  base::flat_map<std::string, apps::IntentFilters> ret;
+base::flat_map<std::string, IntentFilters> CloneIntentFiltersMap(
+    const base::flat_map<std::string, IntentFilters>& intent_filters_map) {
+  base::flat_map<std::string, IntentFilters> ret;
   for (const auto& it : intent_filters_map) {
     ret.insert(std::make_pair(it.first, CloneIntentFilters(it.second)));
   }
diff --git a/components/services/app_service/public/cpp/intent_filter.h b/components/services/app_service/public/cpp/intent_filter.h
index 504e280..7072e80 100644
--- a/components/services/app_service/public/cpp/intent_filter.h
+++ b/components/services/app_service/public/cpp/intent_filter.h
@@ -33,6 +33,8 @@
 
 // The type of a condition in an IntentFilter, which determines what Intent
 // field will be matched against.
+// Values are persisted to disk by preferred_apps_converter.h, so should not be
+// changed or removed without migrating existing data.
 ENUM(ConditionType,
      // Matches the URL scheme (e.g. https, tel).
      kScheme,
@@ -52,6 +54,8 @@
      kFile)
 
 // Describes what pattern matching rules are applied to a ConditionValue.
+// Values are persisted to disk by preferred_apps_converter.h, so should not be
+// changed or removed without migrating existing data.
 enum class PatternMatchType {
   kNone = 0,
   // The ConditionValue is a literal string which must match the value in the
@@ -198,8 +202,8 @@
 
 // Creates a deep copy of `intent_filters` map.
 COMPONENT_EXPORT(APP_TYPES)
-base::flat_map<std::string, apps::IntentFilters> CloneIntentFiltersMap(
-    const base::flat_map<std::string, apps::IntentFilters>& intent_filters_map);
+base::flat_map<std::string, IntentFilters> CloneIntentFiltersMap(
+    const base::flat_map<std::string, IntentFilters>& intent_filters_map);
 
 COMPONENT_EXPORT(APP_TYPES)
 bool IsEqual(const IntentFilters& source, const IntentFilters& target);
diff --git a/components/services/app_service/public/cpp/intent_filter_util.cc b/components/services/app_service/public/cpp/intent_filter_util.cc
index 10f163b..cf5a603 100644
--- a/components/services/app_service/public/cpp/intent_filter_util.cc
+++ b/components/services/app_service/public/cpp/intent_filter_util.cc
@@ -413,7 +413,7 @@
 
 size_t IntentFilterUrlMatchLength(const apps::IntentFilterPtr& intent_filter,
                                   const GURL& url) {
-  apps::Intent intent(url);
+  apps::Intent intent(kIntentActionView, url);
   if (!intent.MatchFilter(intent_filter)) {
     return 0;
   }
diff --git a/components/services/app_service/public/cpp/intent_util.cc b/components/services/app_service/public/cpp/intent_util.cc
index 7cf2694..cf52369 100644
--- a/components/services/app_service/public/cpp/intent_util.cc
+++ b/components/services/app_service/public/cpp/intent_util.cc
@@ -95,6 +95,59 @@
 
 const char kUseBrowserForLink[] = "use_browser";
 
+apps::IntentPtr MakeShareIntent(const std::vector<GURL>& filesystem_urls,
+                                const std::vector<std::string>& mime_types) {
+  auto intent = std::make_unique<apps::Intent>(filesystem_urls.size() == 1
+                                                   ? kIntentActionSend
+                                                   : kIntentActionSendMultiple);
+  intent->mime_type = CalculateCommonMimeType(mime_types);
+
+  DCHECK_EQ(filesystem_urls.size(), mime_types.size());
+  for (size_t i = 0; i < filesystem_urls.size(); i++) {
+    auto file = std::make_unique<apps::IntentFile>(filesystem_urls[i]);
+    file->mime_type = mime_types.at(i);
+    intent->files.push_back(std::move(file));
+  }
+
+  return intent;
+}
+
+apps::IntentPtr MakeShareIntent(const std::vector<GURL>& filesystem_urls,
+                                const std::vector<std::string>& mime_types,
+                                const std::string& text,
+                                const std::string& title) {
+  auto intent = MakeShareIntent(filesystem_urls, mime_types);
+  if (!text.empty()) {
+    intent->share_text = text;
+  }
+  if (!title.empty()) {
+    intent->share_title = title;
+  }
+  return intent;
+}
+
+apps::IntentPtr MakeShareIntent(const std::string& text,
+                                const std::string& title) {
+  auto intent = std::make_unique<apps::Intent>(kIntentActionSend);
+  intent->mime_type = "text/plain";
+  intent->share_text = text;
+  if (!title.empty()) {
+    intent->share_title = title;
+  }
+  return intent;
+}
+
+apps::IntentPtr MakeEditIntent(const GURL& filesystem_url,
+                               const std::string& mime_type) {
+  auto intent = std::make_unique<apps::Intent>(kIntentActionEdit);
+  intent->mime_type = mime_type;
+
+  auto file = std::make_unique<apps::IntentFile>(filesystem_url);
+  file->mime_type = mime_type;
+  intent->files.push_back(std::move(file));
+  return intent;
+}
+
 apps::mojom::IntentPtr CreateIntentFromUrl(const GURL& url) {
   auto intent = apps::mojom::Intent::New();
   intent->action = kIntentActionView;
diff --git a/components/services/app_service/public/cpp/intent_util.h b/components/services/app_service/public/cpp/intent_util.h
index 92adcba..07a8305 100644
--- a/components/services/app_service/public/cpp/intent_util.h
+++ b/components/services/app_service/public/cpp/intent_util.h
@@ -39,6 +39,30 @@
   GURL url;
 };
 
+// Creates an intent for sharing |filesystem_urls|. |filesystem_urls| must be
+// co-indexed with |mime_types|.
+apps::IntentPtr MakeShareIntent(const std::vector<GURL>& filesystem_urls,
+                                const std::vector<std::string>& mime_types);
+
+// Creates an intent for sharing |filesystem_urls|, along with |text| and a
+// |title|. |filesystem_urls| must be co-indexed with |mime_types|.
+apps::IntentPtr MakeShareIntent(const std::vector<GURL>& filesystem_urls,
+                                const std::vector<std::string>& mime_types,
+                                const std::string& text,
+                                const std::string& title);
+
+// Creates an intent for sharing |text|, with |title|.
+apps::IntentPtr MakeShareIntent(const std::string& text,
+                                const std::string& title);
+
+// Create an edit intent for the file with a given |filesystem_url| and
+// |mime_type|.
+apps::IntentPtr MakeEditIntent(const GURL& filesystem_url,
+                               const std::string& mime_type);
+
+// TODO(crbug.com/1253250): Remove below functions after migrating to non-mojo
+// AppService.
+
 // Create an intent struct from URL.
 apps::mojom::IntentPtr CreateIntentFromUrl(const GURL& url);
 
diff --git a/components/services/app_service/public/cpp/intent_util_unittest.cc b/components/services/app_service/public/cpp/intent_util_unittest.cc
index de851453..1dc6035 100644
--- a/components/services/app_service/public/cpp/intent_util_unittest.cc
+++ b/components/services/app_service/public/cpp/intent_util_unittest.cc
@@ -109,7 +109,8 @@
 
 TEST_F(IntentUtilTest, AllConditionMatches) {
   GURL test_url("https://www.google.com/");
-  auto intent = std::make_unique<apps::Intent>(test_url);
+  auto intent =
+      std::make_unique<apps::Intent>(apps_util::kIntentActionView, test_url);
   auto intent_filter = apps_util::MakeIntentFilterForUrlScope(GURL(kFilterUrl));
 
   EXPECT_TRUE(intent->MatchFilter(intent_filter));
@@ -127,7 +128,8 @@
 
 TEST_F(IntentUtilTest, OneConditionDoesNotMatch) {
   GURL test_url("https://www.abc.com/");
-  auto intent = std::make_unique<apps::Intent>(test_url);
+  auto intent =
+      std::make_unique<apps::Intent>(apps_util::kIntentActionView, test_url);
   auto intent_filter = apps_util::MakeIntentFilterForUrlScope(GURL(kFilterUrl));
 
   EXPECT_FALSE(intent->MatchFilter(intent_filter));
@@ -145,7 +147,8 @@
 
 TEST_F(IntentUtilTest, IntentDoesNotHaveValueToMatch) {
   GURL test_url("www.abc.com/");
-  auto intent = std::make_unique<apps::Intent>(test_url);
+  auto intent =
+      std::make_unique<apps::Intent>(apps_util::kIntentActionView, test_url);
   auto intent_filter = apps_util::MakeIntentFilterForUrlScope(GURL(kFilterUrl));
 
   EXPECT_FALSE(intent->MatchFilter(intent_filter));
@@ -164,7 +167,8 @@
 TEST_F(IntentUtilTest, OneConditionValueMatch) {
   auto condition = CreateMultiConditionValuesCondition();
   GURL test_url("https://www.google.com/");
-  auto intent = std::make_unique<apps::Intent>(test_url);
+  auto intent =
+      std::make_unique<apps::Intent>(apps_util::kIntentActionView, test_url);
   EXPECT_TRUE(intent->MatchCondition(condition));
 }
 
@@ -179,7 +183,8 @@
 TEST_F(IntentUtilTest, NoneConditionValueMatch) {
   auto condition = CreateMultiConditionValuesCondition();
   GURL test_url("tel://www.google.com/");
-  auto intent = std::make_unique<apps::Intent>(test_url);
+  auto intent =
+      std::make_unique<apps::Intent>(apps_util::kIntentActionView, test_url);
   EXPECT_FALSE(intent->MatchCondition(condition));
 }
 
@@ -464,11 +469,13 @@
 
 TEST_F(IntentUtilTest, ActionMatch) {
   GURL test_url("https://www.google.com/");
-  auto intent = std::make_unique<apps::Intent>(test_url);
+  auto intent =
+      std::make_unique<apps::Intent>(apps_util::kIntentActionView, test_url);
   auto intent_filter = apps_util::MakeIntentFilterForUrlScope(GURL(kFilterUrl));
   EXPECT_TRUE(intent->MatchFilter(intent_filter));
 
-  auto send_intent = std::make_unique<apps::Intent>(test_url);
+  auto send_intent =
+      std::make_unique<apps::Intent>(apps_util::kIntentActionView, test_url);
   send_intent->action = apps_util::kIntentActionSend;
   EXPECT_FALSE(send_intent->MatchFilter(intent_filter));
 
@@ -750,7 +757,7 @@
 
   // Test match with text/plain type.
   mime_types.push_back(mime_type1);
-  auto intent = std::make_unique<apps::Intent>(urls, mime_types);
+  auto intent = apps_util::MakeShareIntent(urls, mime_types);
   EXPECT_TRUE(intent->MatchFilter(filter1));
   EXPECT_FALSE(intent->MatchFilter(filter2));
   EXPECT_TRUE(intent->MatchFilter(filter1_and_2));
@@ -761,7 +768,7 @@
   // Test match with image/jpeg type.
   mime_types.clear();
   mime_types.push_back(mime_type2);
-  intent = std::make_unique<apps::Intent>(urls, mime_types);
+  intent = apps_util::MakeShareIntent(urls, mime_types);
   EXPECT_FALSE(intent->MatchFilter(filter1));
   EXPECT_TRUE(intent->MatchFilter(filter2));
   EXPECT_TRUE(intent->MatchFilter(filter1_and_2));
@@ -772,7 +779,7 @@
   // Test match with text/html type.
   mime_types.clear();
   mime_types.push_back(mime_type3);
-  intent = std::make_unique<apps::Intent>(urls, mime_types);
+  intent = apps_util::MakeShareIntent(urls, mime_types);
   EXPECT_FALSE(intent->MatchFilter(filter1));
   EXPECT_FALSE(intent->MatchFilter(filter2));
   EXPECT_FALSE(intent->MatchFilter(filter1_and_2));
@@ -783,7 +790,7 @@
   // Test match with text/* types.
   mime_types.clear();
   mime_types.push_back(mime_type_sub_wildcard);
-  intent = std::make_unique<apps::Intent>(urls, mime_types);
+  intent = apps_util::MakeShareIntent(urls, mime_types);
   EXPECT_FALSE(intent->MatchFilter(filter1));
   EXPECT_FALSE(intent->MatchFilter(filter2));
   EXPECT_FALSE(intent->MatchFilter(filter1_and_2));
@@ -794,7 +801,7 @@
   // Test match with */* type.
   mime_types.clear();
   mime_types.push_back(mime_type_all_wildcard);
-  intent = std::make_unique<apps::Intent>(urls, mime_types);
+  intent = apps_util::MakeShareIntent(urls, mime_types);
   EXPECT_FALSE(intent->MatchFilter(filter1));
   EXPECT_FALSE(intent->MatchFilter(filter2));
   EXPECT_FALSE(intent->MatchFilter(filter1_and_2));
@@ -906,7 +913,7 @@
   // Test match with same mime types.
   mime_types.push_back(mime_type1);
   mime_types.push_back(mime_type1);
-  auto intent = std::make_unique<apps::Intent>(urls, mime_types);
+  auto intent = apps_util::MakeShareIntent(urls, mime_types);
   EXPECT_TRUE(intent->MatchFilter(filter1));
   EXPECT_TRUE(intent->MatchFilter(filter1_and_2));
   EXPECT_FALSE(intent->MatchFilter(filter3));
@@ -915,7 +922,7 @@
   mime_types.clear();
   mime_types.push_back(mime_type1);
   mime_types.push_back(mime_type3);
-  intent = std::make_unique<apps::Intent>(urls, mime_types);
+  intent = apps_util::MakeShareIntent(urls, mime_types);
   EXPECT_FALSE(intent->MatchFilter(filter1));
   EXPECT_FALSE(intent->MatchFilter(filter1_and_2));
   EXPECT_FALSE(intent->MatchFilter(filter3));
@@ -925,7 +932,7 @@
   mime_types.clear();
   mime_types.push_back(mime_type1);
   mime_types.push_back(mime_type_sub_wildcard);
-  intent = std::make_unique<apps::Intent>(urls, mime_types);
+  intent = apps_util::MakeShareIntent(urls, mime_types);
   EXPECT_FALSE(intent->MatchFilter(filter1));
   EXPECT_FALSE(intent->MatchFilter(filter1_and_2));
   EXPECT_TRUE(intent->MatchFilter(filter_sub_wildcard));
@@ -934,7 +941,7 @@
   mime_types.clear();
   mime_types.push_back(mime_type1);
   mime_types.push_back(mime_type2);
-  intent = std::make_unique<apps::Intent>(urls, mime_types);
+  intent = apps_util::MakeShareIntent(urls, mime_types);
   EXPECT_FALSE(intent->MatchFilter(filter1));
   EXPECT_FALSE(intent->MatchFilter(filter2));
   EXPECT_FALSE(intent->MatchFilter(filter_sub_wildcard));
@@ -945,7 +952,7 @@
   mime_types.clear();
   mime_types.push_back(mime_type1);
   mime_types.push_back(mime_type_all_wildcard);
-  intent = std::make_unique<apps::Intent>(urls, mime_types);
+  intent = apps_util::MakeShareIntent(urls, mime_types);
   EXPECT_FALSE(intent->MatchFilter(filter1));
   EXPECT_FALSE(intent->MatchFilter(filter1_and_2));
   EXPECT_FALSE(intent->MatchFilter(filter_sub_wildcard));
@@ -1041,21 +1048,25 @@
 
   // Test match with the same mime type and the same file extension.
   auto intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(test_url("abc.mp3"), mime_type_mp3, false));
   EXPECT_TRUE(intent->MatchFilter(file_filter));
 
   // Test match with different mime types and the same file extension.
   intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(test_url("abc.mp3"), mime_type_mp3, false));
   EXPECT_TRUE(intent->MatchFilter(file_filter));
 
   // Test match with the same mime type and a different file extension.
   intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(test_url("abc.png"), mime_type_mp3, false));
   EXPECT_TRUE(intent->MatchFilter(file_filter));
 
   // Test match with different mime types and a different file extension.
   intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(test_url("abc.png"), mime_type_mpeg, false));
   EXPECT_FALSE(intent->MatchFilter(file_filter));
 
@@ -1065,12 +1076,14 @@
 
   // The whole extension must match, not just the end.
   intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(test_url("abc.extramp3"), mime_type_mpeg, false));
   EXPECT_FALSE(intent->MatchFilter(file_filter));
   EXPECT_FALSE(intent->MatchFilter(file_filter_dot));
 
   // Check that the filter behaves the same with and without a leading ".".
   intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(test_url("abc.mp3"), mime_type_mpeg, false));
   EXPECT_TRUE(intent->MatchFilter(file_filter_dot));
 }
@@ -1137,16 +1150,19 @@
 
   // Test match with mp3 file extension.
   auto intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(ext_test_url("abc.mp3"), "", false));
   EXPECT_TRUE(intent->MatchFilter(url_filter));
 
   // Test non-match with mp4 file extension.
   intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(ext_test_url("abc.mp4"), "", false));
   EXPECT_FALSE(intent->MatchFilter(url_filter));
 
   // Test non-match with just the end of a file extension.
   intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(ext_test_url("abc.testmp3"), "", false));
   EXPECT_FALSE(intent->MatchFilter(url_filter));
 
@@ -1156,11 +1172,13 @@
 
   // Test that mp3 matches with *
   intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(ext_test_url("abc.mp3"), "", false));
   EXPECT_TRUE(intent->MatchFilter(wild_filter));
 
   // Test that no file extension matches with *
   intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(ext_test_url("abc"), "", false));
   EXPECT_TRUE(intent->MatchFilter(wild_filter));
 
@@ -1171,11 +1189,13 @@
 
   // Test that mp3 matches with *.*
   intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(ext_test_url("abc.mp3"), "", false));
   EXPECT_TRUE(intent->MatchFilter(ext_wild_filter));
 
   // Test that no file extension does not match with *.*
   intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(ext_test_url("abc"), "", false));
   EXPECT_FALSE(intent->MatchFilter(ext_wild_filter));
 }
@@ -1187,16 +1207,19 @@
 
   // Test match with mp3 file extension.
   auto intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(system_web_app_test_url("abc.mp3"), "", false));
   EXPECT_TRUE(intent->MatchFilter(url_filter));
 
   // Test non-match with mp4 file extension.
   intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(system_web_app_test_url("abc.mp4"), "", false));
   EXPECT_FALSE(intent->MatchFilter(url_filter));
 
   // Test non-match with just the end of a file extension.
   intent = std::make_unique<apps::Intent>(
+      apps_util::kIntentActionView,
       CreateIntentFiles(system_web_app_test_url("abc.testmp3"), "", false));
   EXPECT_FALSE(intent->MatchFilter(url_filter));
 }
@@ -1242,27 +1265,26 @@
   const std::vector<GURL> urls{GURL("abc")};
   const std::vector<std::string> mime_types{mime_type};
 
-  auto intent =
-      std::make_unique<apps::Intent>(urls, mime_types, "text", "title");
+  auto intent = apps_util::MakeShareIntent(urls, mime_types, "text", "title");
   EXPECT_TRUE(intent->share_text.has_value());
   EXPECT_EQ(intent->share_text.value(), "text");
   EXPECT_TRUE(intent->share_title.has_value());
   EXPECT_EQ(intent->share_title.value(), "title");
   EXPECT_TRUE(intent->MatchFilter(filter));
 
-  intent = std::make_unique<apps::Intent>(urls, mime_types, "text", "");
+  intent = apps_util::MakeShareIntent(urls, mime_types, "text", "");
   EXPECT_TRUE(intent->share_text.has_value());
   EXPECT_EQ(intent->share_text.value(), "text");
   EXPECT_FALSE(intent->share_title.has_value());
   EXPECT_TRUE(intent->MatchFilter(filter));
 
-  intent = std::make_unique<apps::Intent>(urls, mime_types, "", "title");
+  intent = apps_util::MakeShareIntent(urls, mime_types, "", "title");
   EXPECT_FALSE(intent->share_text.has_value());
   EXPECT_TRUE(intent->share_title.has_value());
   EXPECT_EQ(intent->share_title.value(), "title");
   EXPECT_TRUE(intent->MatchFilter(filter));
 
-  intent = std::make_unique<apps::Intent>(urls, mime_types, "", "");
+  intent = apps_util::MakeShareIntent(urls, mime_types, "", "");
   EXPECT_FALSE(intent->share_text.has_value());
   EXPECT_FALSE(intent->share_title.has_value());
   EXPECT_TRUE(intent->MatchFilter(filter));
@@ -1294,15 +1316,15 @@
   auto filter1 = apps_util::MakeIntentFilterForMimeType(mime_type1);
   auto filter2 = apps_util::MakeIntentFilterForMimeType(mime_type2);
 
-  auto intent = std::make_unique<apps::Intent>("text", "");
+  auto intent = apps_util::MakeShareIntent("text", "");
   EXPECT_TRUE(intent->MatchFilter(filter1));
   EXPECT_FALSE(intent->MatchFilter(filter2));
 
-  intent = std::make_unique<apps::Intent>("", "title");
+  intent = apps_util::MakeShareIntent("", "title");
   EXPECT_TRUE(intent->MatchFilter(filter1));
   EXPECT_FALSE(intent->MatchFilter(filter2));
 
-  intent = std::make_unique<apps::Intent>("text", "title");
+  intent = apps_util::MakeShareIntent("text", "title");
   EXPECT_TRUE(intent->MatchFilter(filter1));
   EXPECT_FALSE(intent->MatchFilter(filter2));
 }
@@ -1538,9 +1560,12 @@
   foo_dir->is_directory = true;
   intent_files3.push_back(std::move(foo_dir));
 
-  IntentPtr intent = std::make_unique<Intent>(std::move(intent_files));
-  IntentPtr intent2 = std::make_unique<Intent>(std::move(intent_files2));
-  IntentPtr intent3 = std::make_unique<Intent>(std::move(intent_files3));
+  IntentPtr intent = std::make_unique<Intent>(apps_util::kIntentActionView,
+                                              std::move(intent_files));
+  IntentPtr intent2 = std::make_unique<Intent>(apps_util::kIntentActionView,
+                                               std::move(intent_files2));
+  IntentPtr intent3 = std::make_unique<Intent>(apps_util::kIntentActionView,
+                                               std::move(intent_files3));
 
   const std::string kLabel = "";
 
diff --git a/components/services/app_service/public/cpp/preferred_app.cc b/components/services/app_service/public/cpp/preferred_app.cc
index 1360060..c3f22b8 100644
--- a/components/services/app_service/public/cpp/preferred_app.cc
+++ b/components/services/app_service/public/cpp/preferred_app.cc
@@ -172,4 +172,18 @@
   return ret;
 }
 
+apps::mojom::ReplacedAppPreferencesPtr
+ConvertReplacedAppPreferencesToMojomReplacedAppPreferences(
+    const ReplacedAppPreferences& replace_preferences) {
+  auto replaced_app_preferences = apps::mojom::ReplacedAppPreferences::New();
+  auto& replaced_preference_map = replaced_app_preferences->replaced_preference;
+  for (const auto& it : replace_preferences) {
+    for (const auto& filter : it.second) {
+      replaced_preference_map[it.first].push_back(
+          ConvertIntentFilterToMojomIntentFilter(filter));
+    }
+  }
+  return replaced_app_preferences;
+}
+
 }  // namespace apps
diff --git a/components/services/app_service/public/cpp/preferred_app.h b/components/services/app_service/public/cpp/preferred_app.h
index f75622e3..7009f98 100644
--- a/components/services/app_service/public/cpp/preferred_app.h
+++ b/components/services/app_service/public/cpp/preferred_app.h
@@ -47,6 +47,10 @@
 
 using PreferredAppChangesPtr = std::unique_ptr<PreferredAppChanges>;
 
+// Represents a group of `app_ids` that is no longer preferred app of their
+// corresponding `intent_filters`.
+using ReplacedAppPreferences = base::flat_map<std::string, IntentFilters>;
+
 // Creates a deep copy of `preferred_apps`.
 PreferredApps ClonePreferredApps(const PreferredApps& preferred_apps);
 
@@ -73,6 +77,10 @@
 std::vector<apps::mojom::PreferredAppPtr>
 ConvertPreferredAppsToMojomPreferredApps(const PreferredApps& preferred_apps);
 
+apps::mojom::ReplacedAppPreferencesPtr
+ConvertReplacedAppPreferencesToMojomReplacedAppPreferences(
+    const ReplacedAppPreferences& replace_preferences);
+
 }  // namespace apps
 
 #endif  // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_PREFERRED_APP_H_
diff --git a/components/services/app_service/public/cpp/preferred_apps_impl.cc b/components/services/app_service/public/cpp/preferred_apps_impl.cc
index d709f74..44f21c2 100644
--- a/components/services/app_service/public/cpp/preferred_apps_impl.cc
+++ b/components/services/app_service/public/cpp/preferred_apps_impl.cc
@@ -78,11 +78,6 @@
 
 namespace apps {
 
-apps::mojom::Publisher* PreferredAppsImpl::Host::GetMojomPublisher(
-    apps::mojom::AppType app_type) {
-  return nullptr;
-}
-
 PreferredAppsImpl::PreferredAppsImpl(
     Host* host,
     const base::FilePath& profile_dir,
@@ -272,16 +267,18 @@
     return;
   }
 
-  apps::mojom::ReplacedAppPreferencesPtr replaced_apps =
-      preferred_apps_list_.AddPreferredApp(
-          app_id, ConvertMojomIntentFilterToIntentFilter(mojom_intent_filter));
+  auto replaced_apps = preferred_apps_list_.AddPreferredApp(
+      app_id, ConvertMojomIntentFilterToIntentFilter(mojom_intent_filter));
+
+  auto mojom_replaced_apps =
+      ConvertReplacedAppPreferencesToMojomReplacedAppPreferences(replaced_apps);
 
   WriteToJSON(profile_dir_, preferred_apps_list_);
 
   auto changes = apps::mojom::PreferredAppChanges::New();
 
   changes->added_filters[app_id].push_back(mojom_intent_filter->Clone());
-  changes->removed_filters = Clone(replaced_apps->replaced_preference);
+  changes->removed_filters = Clone(mojom_replaced_apps->replaced_preference);
   host_->OnPreferredAppsChanged(std::move(changes));
 
   if (from_publisher || !intent) {
@@ -329,7 +326,7 @@
 }
 
 void PreferredAppsImpl::SetSupportedLinksPreferenceImpl(
-    apps::mojom::AppType app_type,
+    apps::mojom::AppType mojom_app_type,
     const std::string& app_id,
     std::vector<apps::mojom::IntentFilterPtr> all_link_filters) {
   auto changes = apps::mojom::PreferredAppChanges::New();
@@ -337,9 +334,10 @@
   auto& removed = changes->removed_filters;
 
   for (auto& filter : all_link_filters) {
-    apps::mojom::ReplacedAppPreferencesPtr replaced_apps =
-        preferred_apps_list_.AddPreferredApp(
-            app_id, ConvertMojomIntentFilterToIntentFilter(filter));
+    auto replaced_apps =
+        ConvertReplacedAppPreferencesToMojomReplacedAppPreferences(
+            preferred_apps_list_.AddPreferredApp(
+                app_id, ConvertMojomIntentFilterToIntentFilter(filter)));
     added[app_id].push_back(std::move(filter));
 
     // If we removed overlapping supported links when adding the new app, those
@@ -381,10 +379,10 @@
 
   // Notify publishers: The new app has been set to open links, and all removed
   // apps no longer handle links.
-  auto* publisher = host_->GetMojomPublisher(app_type);
-  if (publisher) {
-    publisher->OnSupportedLinksPreferenceChanged(app_id,
-                                                 /*open_in_app=*/true);
+  AppType app_type = ConvertMojomAppTypToAppType(mojom_app_type);
+  if (host_->HasPublisher(app_type)) {
+    host_->OnSupportedLinksPreferenceChanged(app_type, app_id,
+                                             /*open_in_app=*/true);
   }
   for (const auto& removed_app_and_filters : removed) {
     // We don't know what app type the app is, so we have to notify all
@@ -394,10 +392,10 @@
   }
 }
 void PreferredAppsImpl::RemoveSupportedLinksPreferenceImpl(
-    apps::mojom::AppType app_type,
+    apps::mojom::AppType mojom_app_type,
     const std::string& app_id) {
-  auto* publisher = host_->GetMojomPublisher(app_type);
-  if (!publisher) {
+  AppType app_type = ConvertMojomAppTypToAppType(mojom_app_type);
+  if (!host_->HasPublisher(app_type)) {
     return;
   }
 
@@ -413,8 +411,8 @@
         ConvertPreferredAppChangesToMojomPreferredAppChanges(changes));
   }
 
-  publisher->OnSupportedLinksPreferenceChanged(app_id,
-                                               /*open_in_app=*/false);
+  host_->OnSupportedLinksPreferenceChanged(app_type, app_id,
+                                           /*open_in_app=*/false);
 }
 
 }  // namespace apps
diff --git a/components/services/app_service/public/cpp/preferred_apps_impl.h b/components/services/app_service/public/cpp/preferred_apps_impl.h
index bb853e5..8650b6c 100644
--- a/components/services/app_service/public/cpp/preferred_apps_impl.h
+++ b/components/services/app_service/public/cpp/preferred_apps_impl.h
@@ -14,6 +14,8 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/task/sequenced_task_runner.h"
+#include "components/services/app_service/public/cpp/app_types.h"
+#include "components/services/app_service/public/cpp/preferred_app.h"
 #include "components/services/app_service/public/cpp/preferred_apps_list.h"
 #include "components/services/app_service/public/mojom/app_service.mojom.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
@@ -41,15 +43,18 @@
         const std::string& app_id,
         apps::mojom::IntentFilterPtr intent_filter,
         apps::mojom::IntentPtr intent,
-        apps::mojom::ReplacedAppPreferencesPtr replaced_app_preferences) {}
+        ReplacedAppPreferences replaced_app_preferences) {}
 
     virtual void OnSupportedLinksPreferenceChanged(const std::string& app_id,
                                                    bool open_in_app) = 0;
 
-    // Returns publisher for `app_type`, or nullptr if there is no publisher for
-    // `app_type`.
-    virtual apps::mojom::Publisher* GetMojomPublisher(
-        apps::mojom::AppType app_type);
+    virtual void OnSupportedLinksPreferenceChanged(AppType app_type,
+                                                   const std::string& app_id,
+                                                   bool open_in_app) = 0;
+
+    // Returns true if there is a publisher for `app_type`. Otherwise, returns
+    // false.
+    virtual bool HasPublisher(AppType app_type) = 0;
   };
 
   PreferredAppsImpl(
diff --git a/components/services/app_service/public/cpp/preferred_apps_list.cc b/components/services/app_service/public/cpp/preferred_apps_list.cc
index d4fa63e..dac2cc96 100644
--- a/components/services/app_service/public/cpp/preferred_apps_list.cc
+++ b/components/services/app_service/public/cpp/preferred_apps_list.cc
@@ -39,17 +39,16 @@
   initialized_ = true;
 }
 
-apps::mojom::ReplacedAppPreferencesPtr PreferredAppsList::AddPreferredApp(
+ReplacedAppPreferences PreferredAppsList::AddPreferredApp(
     const std::string& app_id,
     const IntentFilterPtr& intent_filter) {
-  auto replaced_app_preferences = apps::mojom::ReplacedAppPreferences::New();
+  ReplacedAppPreferences replaced_app_preferences;
 
   if (EntryExists(app_id, intent_filter)) {
     return replaced_app_preferences;
   }
 
   auto iter = preferred_apps_.begin();
-  auto& replaced_preference_map = replaced_app_preferences->replaced_preference;
 
   // Go through the list and see if there are overlapped intent filters in the
   // list. If there is, add this into the replaced_app_preferences and remove it
@@ -59,8 +58,8 @@
     if ((*iter)->app_id != app_id &&
         apps_util::FiltersHaveOverlap((*iter)->intent_filter, intent_filter)) {
       // Add the to be removed preferred app into a map, key by app_id.
-      replaced_preference_map[(*iter)->app_id].push_back(
-          ConvertIntentFilterToMojomIntentFilter((*iter)->intent_filter));
+      replaced_app_preferences[(*iter)->app_id].push_back(
+          std::move((*iter)->intent_filter));
       iter = preferred_apps_.erase(iter);
     } else {
       iter++;
@@ -72,7 +71,7 @@
   if (apps_util::IsSupportedLinkForApp(app_id, intent_filter)) {
     for (auto& obs : observers_) {
       obs.OnPreferredAppChanged(app_id, true);
-      for (auto& app : replaced_preference_map) {
+      for (auto& app : replaced_app_preferences) {
         obs.OnPreferredAppChanged(app.first, false);
       }
     }
@@ -241,7 +240,8 @@
 
 absl::optional<std::string> PreferredAppsList::FindPreferredAppForUrl(
     const GURL& url) const {
-  return FindPreferredAppForIntent(std::make_unique<Intent>(url));
+  return FindPreferredAppForIntent(
+      std::make_unique<Intent>(apps_util::kIntentActionView, url));
 }
 
 absl::optional<std::string> PreferredAppsList::FindPreferredAppForIntent(
diff --git a/components/services/app_service/public/cpp/preferred_apps_list.h b/components/services/app_service/public/cpp/preferred_apps_list.h
index 3780f7a..614a0d14 100644
--- a/components/services/app_service/public/cpp/preferred_apps_list.h
+++ b/components/services/app_service/public/cpp/preferred_apps_list.h
@@ -14,7 +14,6 @@
 #include "components/services/app_service/public/cpp/intent_filter.h"
 #include "components/services/app_service/public/cpp/preferred_app.h"
 #include "components/services/app_service/public/cpp/preferred_apps_list_handle.h"
-#include "components/services/app_service/public/mojom/types.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class GURL;
@@ -38,9 +37,8 @@
   // Add a preferred app for an |intent_filter|, and returns a group of
   // |app_ids| that is no longer preferred app of their corresponding
   // |intent_filters|.
-  apps::mojom::ReplacedAppPreferencesPtr AddPreferredApp(
-      const std::string& app_id,
-      const IntentFilterPtr& intent_filter);
+  ReplacedAppPreferences AddPreferredApp(const std::string& app_id,
+                                         const IntentFilterPtr& intent_filter);
 
   // Delete a preferred app for an |intent_filter| with the same |app_id|.
   // Returns the deleted filters, if any.
diff --git a/components/services/app_service/public/cpp/preferred_apps_list_unittest.cc b/components/services/app_service/public/cpp/preferred_apps_list_unittest.cc
index 2649a60a..fe8907e45 100644
--- a/components/services/app_service/public/cpp/preferred_apps_list_unittest.cc
+++ b/components/services/app_service/public/cpp/preferred_apps_list_unittest.cc
@@ -9,6 +9,7 @@
 #include "components/services/app_service/public/cpp/intent_filter_util.h"
 #include "components/services/app_service/public/cpp/intent_test_util.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
+#include "components/services/app_service/public/cpp/preferred_app.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -234,7 +235,7 @@
                                apps::PatternMatchType::kNone, intent_filter_1);
   auto replaced_app_preferences =
       preferred_apps_.AddPreferredApp(kAppId1, intent_filter_1);
-  EXPECT_EQ(0u, replaced_app_preferences->replaced_preference.size());
+  EXPECT_EQ(0u, replaced_app_preferences.size());
 
   GURL filter_url_3 = GURL("https://www.abc.com/abc");
   auto intent_filter_2 = apps_util::MakeIntentFilterForUrlScope(filter_url_3);
@@ -245,9 +246,9 @@
                                apps::PatternMatchType::kNone, intent_filter_2);
   replaced_app_preferences =
       preferred_apps_.AddPreferredApp(kAppId2, intent_filter_2);
-  EXPECT_EQ(1u, replaced_app_preferences->replaced_preference.size());
-  EXPECT_TRUE(replaced_app_preferences->replaced_preference.find(kAppId1) !=
-              replaced_app_preferences->replaced_preference.end());
+  EXPECT_EQ(1u, replaced_app_preferences.size());
+  EXPECT_TRUE(replaced_app_preferences.find(kAppId1) !=
+              replaced_app_preferences.end());
 
   GURL filter_url_4 = GURL("http://www.example.com/abc");
   auto intent_filter_3 = apps_util::MakeIntentFilterForUrlScope(filter_url_3);
@@ -259,40 +260,40 @@
   // Test when replacing multiple preferred app entries with same app id.
   replaced_app_preferences =
       preferred_apps_.AddPreferredApp(kAppId1, intent_filter_1);
-  EXPECT_EQ(1u, replaced_app_preferences->replaced_preference.size());
-  EXPECT_TRUE(replaced_app_preferences->replaced_preference.find(kAppId2) !=
-              replaced_app_preferences->replaced_preference.end());
+  EXPECT_EQ(1u, replaced_app_preferences.size());
+  EXPECT_TRUE(replaced_app_preferences.find(kAppId2) !=
+              replaced_app_preferences.end());
 
   replaced_app_preferences =
       preferred_apps_.AddPreferredApp(kAppId1, intent_filter_3);
-  EXPECT_EQ(0u, replaced_app_preferences->replaced_preference.size());
+  EXPECT_EQ(0u, replaced_app_preferences.size());
 
   replaced_app_preferences =
       preferred_apps_.AddPreferredApp(kAppId2, intent_filter_2);
-  EXPECT_EQ(1u, replaced_app_preferences->replaced_preference.size());
-  auto entry = replaced_app_preferences->replaced_preference.find(kAppId1);
-  EXPECT_TRUE(entry != replaced_app_preferences->replaced_preference.end());
+  EXPECT_EQ(1u, replaced_app_preferences.size());
+  auto entry = replaced_app_preferences.find(kAppId1);
+  EXPECT_TRUE(entry != replaced_app_preferences.end());
   EXPECT_EQ(2u, entry->second.size());
 
   // Test when replacing multiple preferred app entries with different app id.
   replaced_app_preferences =
       preferred_apps_.AddPreferredApp(kAppId1, intent_filter_1);
-  EXPECT_EQ(1u, replaced_app_preferences->replaced_preference.size());
-  EXPECT_TRUE(replaced_app_preferences->replaced_preference.find(kAppId2) !=
-              replaced_app_preferences->replaced_preference.end());
+  EXPECT_EQ(1u, replaced_app_preferences.size());
+  EXPECT_TRUE(replaced_app_preferences.find(kAppId2) !=
+              replaced_app_preferences.end());
 
   replaced_app_preferences =
       preferred_apps_.AddPreferredApp(kAppId2, intent_filter_3);
-  EXPECT_EQ(0u, replaced_app_preferences->replaced_preference.size());
+  EXPECT_EQ(0u, replaced_app_preferences.size());
 
   replaced_app_preferences =
       preferred_apps_.AddPreferredApp(kAppId3, intent_filter_2);
-  EXPECT_EQ(2u, replaced_app_preferences->replaced_preference.size());
-  entry = replaced_app_preferences->replaced_preference.find(kAppId1);
-  EXPECT_TRUE(entry != replaced_app_preferences->replaced_preference.end());
+  EXPECT_EQ(2u, replaced_app_preferences.size());
+  entry = replaced_app_preferences.find(kAppId1);
+  EXPECT_TRUE(entry != replaced_app_preferences.end());
   EXPECT_EQ(1u, entry->second.size());
-  entry = replaced_app_preferences->replaced_preference.find(kAppId2);
-  EXPECT_TRUE(entry != replaced_app_preferences->replaced_preference.end());
+  entry = replaced_app_preferences.find(kAppId2);
+  EXPECT_TRUE(entry != replaced_app_preferences.end());
   EXPECT_EQ(1u, entry->second.size());
 }
 
@@ -305,7 +306,7 @@
   auto replaced_app_preferences =
       preferred_apps_.AddPreferredApp(kAppId1, intent_filter);
 
-  EXPECT_EQ(0u, replaced_app_preferences->replaced_preference.size());
+  EXPECT_EQ(0u, replaced_app_preferences.size());
   EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(filter_url));
 }
 
diff --git a/content/app_shim_remote_cocoa/web_contents_occlusion_checker_mac.h b/content/app_shim_remote_cocoa/web_contents_occlusion_checker_mac.h
index 99f642c..f3cb9f7 100644
--- a/content/app_shim_remote_cocoa/web_contents_occlusion_checker_mac.h
+++ b/content/app_shim_remote_cocoa/web_contents_occlusion_checker_mac.h
@@ -7,6 +7,7 @@
 
 #import <AppKit/AppKit.h>
 
+#include "base/feature_list.h"
 #import "content/app_shim_remote_cocoa/web_contents_view_cocoa.h"
 #include "content/common/web_contents_ns_view_bridge.mojom.h"
 
diff --git a/content/app_shim_remote_cocoa/web_contents_occlusion_checker_mac.mm b/content/app_shim_remote_cocoa/web_contents_occlusion_checker_mac.mm
index f3d7ca32..6056a406 100644
--- a/content/app_shim_remote_cocoa/web_contents_occlusion_checker_mac.mm
+++ b/content/app_shim_remote_cocoa/web_contents_occlusion_checker_mac.mm
@@ -9,6 +9,9 @@
 #import "base/mac/scoped_objc_class_swizzler.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/no_destructor.h"
+#include "content/public/common/content_features.h"
+
+using features::kMacWebContentsOcclusion;
 
 namespace {
 
@@ -20,8 +23,6 @@
   return window_class_swizzler.get();
 }
 
-const base::Feature kMacWebContentsOcclusion{"MacWebContentsOcclusion",
-                                             base::FEATURE_DISABLED_BY_DEFAULT};
 const base::FeatureParam<bool> kEnhancedWindowOcclusionDetection{
     &kMacWebContentsOcclusion, "EnhancedWindowOcclusionDetection", false};
 const base::FeatureParam<bool> kDisplaySleepAndAppHideDetection{
@@ -63,6 +64,7 @@
 - (instancetype)init {
   self = [super init];
 
+  DCHECK(base::FeatureList::IsEnabled(kMacWebContentsOcclusion));
   [self setUpNotifications];
 
   return self;
diff --git a/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm b/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm
index d60f89ff..fc67a63f 100644
--- a/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm
+++ b/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm
@@ -11,6 +11,7 @@
 #import "content/app_shim_remote_cocoa/web_contents_occlusion_checker_mac.h"
 #import "content/app_shim_remote_cocoa/web_drag_source_mac.h"
 #import "content/browser/web_contents/web_drag_dest_mac.h"
+#include "content/public/common/content_features.h"
 #import "third_party/mozilla/NSPasteboard+Utils.h"
 #include "ui/base/clipboard/clipboard_constants.h"
 #include "ui/base/clipboard/custom_data_helper.h"
@@ -21,9 +22,10 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 
+using content::DropData;
+using features::kMacWebContentsOcclusion;
 using remote_cocoa::mojom::DraggingInfo;
 using remote_cocoa::mojom::SelectionDirection;
-using content::DropData;
 
 namespace {
 // Time to delay clearing the pasteboard for after a drag ends. This is
@@ -104,11 +106,17 @@
 ////////////////////////////////////////////////////////////////////////////////
 // WebContentsViewCocoa
 
-@implementation WebContentsViewCocoa
+@implementation WebContentsViewCocoa {
+  // TODO(https://crbug.com/883031): Remove this when kMacWebContentsOcclusion
+  // is enabled by default.
+  BOOL _inFullScreenTransition;
+}
 
 + (void)initialize {
-  // Create the WebContentsOcclusionCheckerMac shared instance.
-  [WebContentsOcclusionCheckerMac sharedInstance];
+  if (base::FeatureList::IsEnabled(kMacWebContentsOcclusion)) {
+    // Create the WebContentsOcclusionCheckerMac shared instance.
+    [WebContentsOcclusionCheckerMac sharedInstance];
+  }
 }
 
 - (instancetype)initWithViewsHostableView:(ui::ViewsHostableView*)v {
@@ -367,10 +375,26 @@
 
 - (void)updateWebContentsVisibility:
     (remote_cocoa::mojom::Visibility)visibility {
+  DCHECK(base::FeatureList::IsEnabled(kMacWebContentsOcclusion));
   if (_host)
     _host->OnWindowVisibilityChanged(visibility);
 }
 
+- (void)legacyUpdateWebContentsVisibility {
+  using remote_cocoa::mojom::Visibility;
+  DCHECK(!base::FeatureList::IsEnabled(kMacWebContentsOcclusion));
+  if (!_host || _inFullScreenTransition)
+    return;
+  Visibility visibility = Visibility::kVisible;
+  if ([self isHiddenOrHasHiddenAncestor] || ![self window])
+    visibility = Visibility::kHidden;
+  else if ([[self window] occlusionState] & NSWindowOcclusionStateVisible)
+    visibility = Visibility::kVisible;
+  else
+    visibility = Visibility::kOccluded;
+  _host->OnWindowVisibilityChanged(visibility);
+}
+
 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize {
   // Subviews do not participate in auto layout unless the the size this view
   // changes. This allows RenderWidgetHostViewMac::SetBounds(..) to select a
@@ -387,7 +411,77 @@
     [subview setFrame:[self bounds]];
 }
 
+- (void)viewWillMoveToWindow:(NSWindow*)newWindow {
+  if (base::FeatureList::IsEnabled(kMacWebContentsOcclusion)) {
+    // WebContentsOcclusionCheckerMac will handle notifications.
+    return;
+  }
+
+  NSWindow* oldWindow = [self window];
+  NSNotificationCenter* notificationCenter =
+      [NSNotificationCenter defaultCenter];
+
+  _inFullScreenTransition = NO;
+  if (oldWindow) {
+    NSArray* notificationsToRemove = @[
+      NSWindowDidChangeOcclusionStateNotification,
+      NSWindowWillEnterFullScreenNotification,
+      NSWindowDidEnterFullScreenNotification,
+      NSWindowWillExitFullScreenNotification,
+      NSWindowDidExitFullScreenNotification
+    ];
+    for (NSString* notificationName in notificationsToRemove) {
+      [notificationCenter removeObserver:self
+                                    name:notificationName
+                                  object:oldWindow];
+    }
+  }
+  if (newWindow) {
+    [notificationCenter addObserver:self
+                           selector:@selector(windowChangedOcclusionState:)
+                               name:NSWindowDidChangeOcclusionStateNotification
+                             object:newWindow];
+    // The fullscreen transition causes spurious occlusion notifications.
+    // See https://crbug.com/1081229
+    [notificationCenter addObserver:self
+                           selector:@selector(fullscreenTransitionStarted:)
+                               name:NSWindowWillEnterFullScreenNotification
+                             object:newWindow];
+    [notificationCenter addObserver:self
+                           selector:@selector(fullscreenTransitionComplete:)
+                               name:NSWindowDidEnterFullScreenNotification
+                             object:newWindow];
+    [notificationCenter addObserver:self
+                           selector:@selector(fullscreenTransitionStarted:)
+                               name:NSWindowWillExitFullScreenNotification
+                             object:newWindow];
+    [notificationCenter addObserver:self
+                           selector:@selector(fullscreenTransitionComplete:)
+                               name:NSWindowDidExitFullScreenNotification
+                             object:newWindow];
+  }
+}
+
+- (void)windowChangedOcclusionState:(NSNotification*)notification {
+  DCHECK(!base::FeatureList::IsEnabled(kMacWebContentsOcclusion));
+  [self legacyUpdateWebContentsVisibility];
+}
+
+- (void)fullscreenTransitionStarted:(NSNotification*)notification {
+  DCHECK(!base::FeatureList::IsEnabled(kMacWebContentsOcclusion));
+  _inFullScreenTransition = YES;
+}
+
+- (void)fullscreenTransitionComplete:(NSNotification*)notification {
+  DCHECK(!base::FeatureList::IsEnabled(kMacWebContentsOcclusion));
+  _inFullScreenTransition = NO;
+}
+
 - (void)viewDidMoveToWindow {
+  if (!base::FeatureList::IsEnabled(kMacWebContentsOcclusion)) {
+    [self legacyUpdateWebContentsVisibility];
+    return;
+  }
   if ([self window] == nil) {
     [self updateWebContentsVisibility:remote_cocoa::mojom::Visibility::kHidden];
   } else {
@@ -397,10 +491,18 @@
 }
 
 - (void)viewDidHide {
+  if (!base::FeatureList::IsEnabled(kMacWebContentsOcclusion)) {
+    [self legacyUpdateWebContentsVisibility];
+    return;
+  }
   [self updateWebContentsVisibility:remote_cocoa::mojom::Visibility::kHidden];
 }
 
 - (void)viewDidUnhide {
+  if (!base::FeatureList::IsEnabled(kMacWebContentsOcclusion)) {
+    [self legacyUpdateWebContentsVisibility];
+    return;
+  }
   [[WebContentsOcclusionCheckerMac sharedInstance]
       updateWebContentsVisibility:self];
 }
diff --git a/content/app_shim_remote_cocoa/window_occlusion_browsertest_mac.mm b/content/app_shim_remote_cocoa/window_occlusion_browsertest_mac.mm
index 690427d..2f330f21 100644
--- a/content/app_shim_remote_cocoa/window_occlusion_browsertest_mac.mm
+++ b/content/app_shim_remote_cocoa/window_occlusion_browsertest_mac.mm
@@ -9,6 +9,7 @@
 #include "base/test/test_timeouts.h"
 #import "content/app_shim_remote_cocoa/web_contents_occlusion_checker_mac.h"
 #include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/content_browser_test.h"
 
@@ -18,8 +19,7 @@
 using content::DropData;
 
 namespace {
-const base::Feature kMacWebContentsOcclusion{"MacWebContentsOcclusion",
-                                             base::FEATURE_DISABLED_BY_DEFAULT};
+
 const char kEnhancedWindowOcclusionDetection[] =
     "EnhancedWindowOcclusionDetection";
 const char kDisplaySleepAndAppHideDetection[] =
@@ -504,7 +504,7 @@
  public:
   WindowOcclusionBrowserTestMacWithOcclusionDetectionFeature() {
     _features.InitAndEnableFeatureWithParameters(
-        kMacWebContentsOcclusion,
+        features::kMacWebContentsOcclusion,
         {{kEnhancedWindowOcclusionDetection, "true"}});
     _enhanced_window_occlusion_detection_enabled = true;
   }
@@ -518,7 +518,8 @@
  public:
   WindowOcclusionBrowserTestMacWithDisplaySleepDetectionFeature() {
     _features.InitAndEnableFeatureWithParameters(
-        kMacWebContentsOcclusion, {{kDisplaySleepAndAppHideDetection, "true"}});
+        features::kMacWebContentsOcclusion,
+        {{kDisplaySleepAndAppHideDetection, "true"}});
     _display_sleep_detection_enabled = true;
   }
 
diff --git a/content/browser/renderer_host/frame_tree_node.cc b/content/browser/renderer_host/frame_tree_node.cc
index cb7e1a0..9c3b109 100644
--- a/content/browser/renderer_host/frame_tree_node.cc
+++ b/content/browser/renderer_host/frame_tree_node.cc
@@ -667,10 +667,9 @@
 }
 
 void FrameTreeNode::BeforeUnloadCanceled() {
-  // TODO(clamy): Support BeforeUnload in subframes.
-  // TODO(crbug.com/1314749): With MPArch there may be multiple main frames and
-  // so IsMainFrame should not be used to identify subframes. Follow up to
-  // confirm correctness.
+  // TODO(clamy): Support BeforeUnload in subframes. Fenced Frames don't run
+  // BeforeUnload. Maybe need to check whether other MPArch inner pages cases
+  // need beforeunload(e.g., portals, GuestView if it gets ported to MPArch).
   if (!IsOutermostMainFrame())
     return;
 
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index 92655f4a..d88905f 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -543,7 +543,8 @@
   return NavigationControllerImpl::CreateNavigationEntry(
       url, referrer, std::move(initiator_origin),
       nullptr /* source_site_instance */, transition, is_renderer_initiated,
-      extra_headers, browser_context, std::move(blob_url_loader_factory));
+      extra_headers, browser_context, std::move(blob_url_loader_factory),
+      true /* rewrite_virtual_urls */);
 }
 
 // static
@@ -557,13 +558,15 @@
     bool is_renderer_initiated,
     const std::string& extra_headers,
     BrowserContext* browser_context,
-    scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
-  GURL url_to_load;
-  GURL virtual_url;
+    scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
+    bool rewrite_virtual_urls) {
+  GURL url_to_load = url;
+  GURL virtual_url = url;
   bool reverse_on_redirect = false;
-  RewriteUrlForNavigation(url, browser_context, &url_to_load, &virtual_url,
-                          &reverse_on_redirect);
-
+  if (rewrite_virtual_urls) {
+    RewriteUrlForNavigation(url, browser_context, &url_to_load, &virtual_url,
+                            &reverse_on_redirect);
+  }
   // Let the NTP override the navigation params and pretend that this is a
   // browser-initiated, bookmark-like navigation.
   GetContentClient()->browser()->OverrideNavigationParams(
@@ -2652,7 +2655,8 @@
           GURL(url::kAboutBlankURL), referrer, initiator_origin,
           source_site_instance, page_transition, is_renderer_initiated,
           extra_headers, browser_context_,
-          nullptr /* blob_url_loader_factory */));
+          nullptr /* blob_url_loader_factory */,
+          false /* rewrite_virtual_urls */));
     }
     // TODO(arthursonzogni): What about |is_renderer_initiated|?
     // Renderer-initiated navigation that target a remote frame are currently
@@ -2674,10 +2678,15 @@
         nullptr /* policy_container_policies */);
   } else {
     // Main frame case.
+    // If `node` is the outermost main frame, it rewrites a virtual url in order
+    // to adjust the original input url if needed. For inner frames such as
+    // fenced frames or subframes, they don't rewrite urls as the urls are not
+    // input urls by users.
+    bool rewrite_virtual_urls = node->IsOutermostMainFrame();
     entry = NavigationEntryImpl::FromNavigationEntry(CreateNavigationEntry(
         url, referrer, initiator_origin, source_site_instance, page_transition,
         is_renderer_initiated, extra_headers, browser_context_,
-        blob_url_loader_factory));
+        blob_url_loader_factory, rewrite_virtual_urls));
     entry->root_node()->frame_entry->set_source_site_instance(
         static_cast<SiteInstanceImpl*>(source_site_instance));
     entry->root_node()->frame_entry->set_method(method);
@@ -3531,7 +3540,7 @@
           GURL(url::kAboutBlankURL), params.referrer, params.initiator_origin,
           params.source_site_instance.get(), params.transition_type,
           params.is_renderer_initiated, extra_headers_crlf, browser_context_,
-          blob_url_loader_factory));
+          blob_url_loader_factory, false /* rewrite_virtual_urls */));
     }
     entry->AddOrUpdateFrameEntry(
         node, NavigationEntryImpl::UpdatePolicy::kReplace, -1, -1, "", nullptr,
@@ -3546,11 +3555,16 @@
         nullptr /* policy_container_policies */);
   } else {
     // Otherwise, create a pending entry for the main frame.
+    // If `node` is the outermost main frame, it rewrites a virtual url in order
+    // to adjust the original input url if needed. For inner frames such as
+    // fenced frames or subframes, they don't rewrite urls as the urls are not
+    // input urls by users.
+    bool rewrite_virtual_urls = node->IsOutermostMainFrame();
     entry = NavigationEntryImpl::FromNavigationEntry(CreateNavigationEntry(
         params.url, params.referrer, params.initiator_origin,
         params.source_site_instance.get(), params.transition_type,
         params.is_renderer_initiated, extra_headers_crlf, browser_context_,
-        blob_url_loader_factory));
+        blob_url_loader_factory, rewrite_virtual_urls));
     entry->set_source_site_instance(
         static_cast<SiteInstanceImpl*>(params.source_site_instance.get()));
     entry->SetRedirectChain(params.redirect_chain);
@@ -3614,9 +3628,6 @@
 
   // For main frames, rewrite the URL if necessary and compute the virtual URL
   // that should be shown in the address bar.
-  // TODO(crbug.com/1314749): With MPArch there may be multiple main frames and
-  // so IsMainFrame should not be used to identify subframes. Follow up to
-  // confirm correctness.
   if (node->IsOutermostMainFrame()) {
     bool ignored_reverse_on_redirect = false;
     RewriteUrlForNavigation(params.url, browser_context_, &url_to_load,
diff --git a/content/browser/renderer_host/navigation_controller_impl.h b/content/browser/renderer_host/navigation_controller_impl.h
index d6a4e7c..6a9eb9a 100644
--- a/content/browser/renderer_host/navigation_controller_impl.h
+++ b/content/browser/renderer_host/navigation_controller_impl.h
@@ -389,6 +389,8 @@
 
   // Like NavigationController::CreateNavigationEntry, but takes an extra
   // argument, |source_site_instance|.
+  // `rewrite_virtual_urls` is true when it needs to rewrite virtual urls
+  // (e.g., for outermost frames).
   static std::unique_ptr<NavigationEntryImpl> CreateNavigationEntry(
       const GURL& url,
       Referrer referrer,
@@ -398,7 +400,8 @@
       bool is_renderer_initiated,
       const std::string& extra_headers,
       BrowserContext* browser_context,
-      scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory);
+      scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
+      bool rewrite_virtual_urls);
 
   // Called just before sending the commit to the renderer, or when restoring
   // from back/forward cache. Walks the session history entries for the relevant
diff --git a/content/browser/renderer_host/navigation_controller_impl_unittest.cc b/content/browser/renderer_host/navigation_controller_impl_unittest.cc
index 61845d8..a080d4c 100644
--- a/content/browser/renderer_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/renderer_host/navigation_controller_impl_unittest.cc
@@ -4520,4 +4520,70 @@
   EXPECT_TRUE(controller_impl().GetPendingEntry());
 }
 
+class NavigationControllerFencedFrameTest : public NavigationControllerTest {
+ public:
+  NavigationControllerFencedFrameTest() {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        blink::features::kFencedFrames, {{"implementation_type", "mparch"}});
+  }
+  ~NavigationControllerFencedFrameTest() override = default;
+
+ protected:
+  static constexpr char kTestRewriteURL[] = "http://test.com";
+  static constexpr char kRewrittenURL[] = "http://rewritten.com";
+
+  static bool URLRewriter(GURL* url, BrowserContext* browser_context) {
+    if (*url == GURL(kTestRewriteURL)) {
+      *url = GURL(kRewrittenURL);
+      return true;
+    }
+    return false;
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+// Tests that receiving a request to navigate a fenced frame will not rewrite
+// the fenced frame URL.
+TEST_F(NavigationControllerFencedFrameTest, NoURLRewriteForFencedFrames) {
+  const GURL kUrl1("http://google.com");
+  const GURL kUrl2("http://chromium.org");
+
+  // First, set up a handler that will rewrite urls.
+  BrowserURLHandlerImpl::GetInstance()->AddHandlerPair(
+      &URLRewriter, BrowserURLHandler::null_handler());
+
+  // Simulate navigating to a page that has a fenced frame.
+  NavigationSimulator::NavigateAndCommitFromDocument(kUrl1, main_test_rfh());
+  RenderFrameHostImpl* fenced_frame_root = main_test_rfh()->AppendFencedFrame();
+  // Navigate fenced frame.
+  std::unique_ptr<NavigationSimulator> navigation_simulator =
+      NavigationSimulator::CreateForFencedFrame(kUrl2, fenced_frame_root);
+  navigation_simulator->Commit();
+
+  // Simulate the fenced frame receiving a request from a RenderFrameProxyHost
+  // to navigate to `kTestRewriteURL`.
+  FrameTree* fenced_frame_tree = fenced_frame_root->frame_tree();
+  fenced_frame_tree->controller().NavigateFromFrameProxy(
+      fenced_frame_root, GURL(kTestRewriteURL),
+      nullptr /* initiator_frame_token */,
+      ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
+      url::Origin::Create(kUrl2), true /* is_renderer_initiated */,
+      fenced_frame_root->GetSiteInstance(), Referrer(),
+      ui::PAGE_TRANSITION_LINK, false /* should_replace_current_entry */,
+      blink::NavigationDownloadPolicy(), "GET", nullptr, "",
+      network::mojom::SourceLocation::New(), nullptr, absl::nullopt,
+      base::TimeTicks::Now() /* navigation_start_time */);
+
+  NavigationRequest* request =
+      fenced_frame_root->frame_tree_node()->navigation_request();
+  ASSERT_TRUE(request);
+  // Ensure that the URL is not rewritten.
+  EXPECT_EQ(GURL(kTestRewriteURL), request->GetURL());
+
+  // Clean up the handler.
+  BrowserURLHandlerImpl::GetInstance()->RemoveHandlerForTesting(&URLRewriter);
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/navigator.cc b/content/browser/renderer_host/navigator.cc
index 7aba6be0..6e53e78c 100644
--- a/content/browser/renderer_host/navigator.cc
+++ b/content/browser/renderer_host/navigator.cc
@@ -1377,7 +1377,11 @@
   SiteInstance* current_site_instance =
       frame_tree_node->current_frame_host()->GetSiteInstance();
   SiteInstance* source_site_instance = current_site_instance;
-
+  // If `frame_tree_node` is the outermost main frame, it rewrites a virtual
+  // url in order to adjust the original input url if needed. For inner frames
+  // such as fenced frames or subframes, they don't rewrite urls as the urls
+  // are not input urls by users.
+  bool rewrite_virtual_urls = frame_tree_node->IsOutermostMainFrame();
   std::unique_ptr<NavigationEntryImpl> entry =
       NavigationEntryImpl::FromNavigationEntry(
           NavigationControllerImpl::CreateNavigationEntry(
@@ -1386,7 +1390,7 @@
               ui::PAGE_TRANSITION_LINK, true /* is_renderer_initiated */,
               std::string() /* extra_headers */,
               controller_.GetBrowserContext(),
-              nullptr /* blob_url_loader_factory */));
+              nullptr /* blob_url_loader_factory */, rewrite_virtual_urls));
 
   entry->set_reload_type(NavigationRequest::NavigationTypeToReloadType(
       common_params.navigation_type));
diff --git a/content/browser/service_worker/service_worker_process_browsertest.cc b/content/browser/service_worker/service_worker_process_browsertest.cc
index 10ba9b0..b8f18283 100644
--- a/content/browser/service_worker/service_worker_process_browsertest.cc
+++ b/content/browser/service_worker/service_worker_process_browsertest.cc
@@ -124,8 +124,15 @@
 
 // Tests that a service worker started due to a navigation shares the same
 // process as the navigation.
+// Flaky on Android; see https://crbug.com/1320972.
+#if BUILDFLAG(IS_ANDROID)
+#define MAYBE_ServiceWorkerAndPageShareProcess \
+  DISABLED_ServiceWorkerAndPageShareProcess
+#else
+#define MAYBE_ServiceWorkerAndPageShareProcess ServiceWorkerAndPageShareProcess
+#endif
 IN_PROC_BROWSER_TEST_P(ServiceWorkerProcessBrowserTest,
-                       ServiceWorkerAndPageShareProcess) {
+                       MAYBE_ServiceWorkerAndPageShareProcess) {
   // Register the service worker.
   RegisterServiceWorker();
 
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 60685df0..af6a40b5 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -1243,6 +1243,11 @@
 const base::Feature kMacSyscallSandbox{"MacSyscallSandbox",
                                        base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Feature that controls whether WebContentsOcclusionChecker should handle
+// occlusion notifications.
+const base::Feature kMacWebContentsOcclusion{"MacWebContentsOcclusion",
+                                             base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables retrying to obtain list of available cameras on Macbooks after
 // restarting the video capture service if a previous attempt delivered zero
 // cameras.
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 2a05000..702b946b 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -316,6 +316,7 @@
 CONTENT_EXPORT extern const base::Feature kDeviceMonitorMac;
 CONTENT_EXPORT extern const base::Feature kIOSurfaceCapturer;
 CONTENT_EXPORT extern const base::Feature kMacSyscallSandbox;
+CONTENT_EXPORT extern const base::Feature kMacWebContentsOcclusion;
 CONTENT_EXPORT extern const base::Feature kRetryGetVideoCaptureDeviceInfos;
 #endif  // BUILDFLAG(IS_MAC)
 
diff --git a/ios/chrome/app/strings/resources/ios_strings_kk.xtb b/ios/chrome/app/strings/resources/ios_strings_kk.xtb
index 7afda06..6c23b21 100644
--- a/ios/chrome/app/strings/resources/ios_strings_kk.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_kk.xtb
@@ -345,6 +345,7 @@
 <translation id="3929457972718048006">Мекенжайлар</translation>
 <translation id="3943492037546055397">Құпия сөздер</translation>
 <translation id="3959736869653157332">Мәзір → Жаңа инкогнито қойындысы</translation>
+<translation id="3964173450954943920">Синхрондалатын мазмұнды кез келген уақытта <ph name="BEGIN_LINK" />Параметрлер<ph name="END_LINK" /> бөлімінен таңдай аласыз. Search және басқа да Google қызметтерін жекелендіру үшін әрекеттер тарихы пайдаланылуы мүмкін.</translation>
 <translation id="3967822245660637423">Жүктеп алынды</translation>
 <translation id="3968505803272650567">Қызығушылықтарды басқару</translation>
 <translation id="3989635538409502728">Шығу</translation>
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm
index 4446528f..600a831d 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm
@@ -348,6 +348,7 @@
   DCHECK(IsStartSurfaceEnabled());
   if (self.showMostRecentTabStartSurfaceTile) {
     self.showMostRecentTabStartSurfaceTile = NO;
+    self.returnToRecentTabItem = nil;
     if (IsContentSuggestionsUIViewControllerMigrationEnabled()) {
       [self.consumer hideReturnToRecentTabTile];
     } else {
@@ -470,7 +471,9 @@
   web::WebState* web_state =
       StartSurfaceRecentTabBrowserAgent::FromBrowser(self.browser)
           ->most_recent_tab();
-  DCHECK(web_state);
+  if (!web_state) {
+    return;
+  }
   int index = web_state_list->GetIndexOfWebState(web_state);
   web_state_list->ActivateWebStateAt(index);
 }
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 0492e29..cb3d5e1 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 @@
-b5ab0f917ed92ac6423eba48ba3a41e210a6834d
\ No newline at end of file
+6726b5853504d186ade5acb22ca754f9a095495f
\ 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 e53ca101..60b73c0 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 @@
-649d7bc26b72abb85b397be99205771697dda0c3
\ No newline at end of file
+46e11e1cebd900a72e90867c4490fcc0434dc164
\ 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 2925c6c..5a32b6cb0 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 @@
-0dc2d4896202f2d13c8af7e9ac3f616d15e49001
\ No newline at end of file
+93b4a583588798317d0c02e4c91bb1be219503bd
\ 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 3f811652..e594ba0d 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 @@
-399f99d45a8270fad42a586b16f23ae8e47d69fc
\ No newline at end of file
+ee68dd7f1eeba1df844e41910284d4f1eb6c4814
\ 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 3fdac97..9823ee7 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 @@
-53a503df0ce66ef0819ecec1b475bcc80aad10a7
\ No newline at end of file
+9e4cd2b7c0361b9513a71a47421f5642eb2caba9
\ 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 c5e390b..e77f5486 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 @@
-b92d01c8c68d285024b536c60be99f49a0a2d891
\ No newline at end of file
+0021fa67dce2bbf1648c7d78ce28d47f569ac0b5
\ 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 11983dc..a116403a 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 @@
-ae7203218b6a8509621519928a01d094f7e6c857
\ No newline at end of file
+9daace74e44f9ab176a255ca125d0d74068b858a
\ 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 1e9f4bc..85894898 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 @@
-fcfebf76869cd6e05ee43ed6b39722a689ce9d41
\ No newline at end of file
+49554c2308c6f5181dcb49d48452f9c18f07dceb
\ 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 80248c89..ac3cbc1 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 @@
-3104539fb72e11af3de30c4687951a0414109eeb
\ No newline at end of file
+16b6e57fe7cd8ca380fd8050fd9ba431aad97e47
\ 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 7c11b5c..3ee0157 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 @@
-0db1d38627330bb263a5daed010c56b10dfd90be
\ No newline at end of file
+9e6d0d2b728d8654dec412484c2362ff89af2705
\ No newline at end of file
diff --git a/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.cc b/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.cc
index 211456d..05807b7 100644
--- a/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.cc
+++ b/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.cc
@@ -227,8 +227,6 @@
     }
   }
 
-  native_input_mode_ = ave_config.native_input_mode;
-
   visible_size_ = config.input_visible_size;
   // For 4:2:0, the pixel sizes have to be even.
   if ((visible_size_.width() % 2 != 0) || (visible_size_.height() % 2 != 0)) {
diff --git a/media/gpu/vaapi/h264_vaapi_video_encoder_delegate_unittest.cc b/media/gpu/vaapi/h264_vaapi_video_encoder_delegate_unittest.cc
index f5882a4..4c0df6c 100644
--- a/media/gpu/vaapi/h264_vaapi_video_encoder_delegate_unittest.cc
+++ b/media/gpu/vaapi/h264_vaapi_video_encoder_delegate_unittest.cc
@@ -23,7 +23,6 @@
 
 VaapiVideoEncoderDelegate::Config kDefaultVEADelegateConfig{
     .max_num_ref_frames = 4,
-    .native_input_mode = false,
     .bitrate_control =
         VaapiVideoEncoderDelegate::BitrateControl::kConstantBitrate,
 };
@@ -164,12 +163,6 @@
 
 std::unique_ptr<VaapiVideoEncoderDelegate::EncodeJob>
 H264VaapiVideoEncoderDelegateTest::CreateEncodeJob(bool keyframe) {
-  auto input_frame = VideoFrame::CreateFrame(
-      kDefaultVEAConfig.input_format, kDefaultVEAConfig.input_visible_size,
-      gfx::Rect(kDefaultVEAConfig.input_visible_size),
-      kDefaultVEAConfig.input_visible_size, base::TimeDelta());
-  LOG_ASSERT(input_frame) << " Failed to create VideoFrame";
-
   auto va_surface = base::MakeRefCounted<VASurface>(
       next_surface_id_++, kDefaultVEAConfig.input_visible_size,
       VA_RT_FORMAT_YUV420, base::DoNothing());
@@ -180,9 +173,11 @@
       kDummyVABufferID, VAEncCodedBufferType,
       kDefaultVEAConfig.input_visible_size.GetArea());
 
+  // TODO(b/229358029): Set a valid timestamp and check the timestamp in
+  // metadata.
+  constexpr base::TimeDelta timestamp;
   return std::make_unique<VaapiVideoEncoderDelegate::EncodeJob>(
-      input_frame, keyframe, next_surface_id_++,
-      kDefaultVEAConfig.input_visible_size, picture,
+      keyframe, timestamp, next_surface_id_++, picture,
       std::move(scoped_va_buffer));
 }
 
diff --git a/media/gpu/vaapi/vaapi_video_encode_accelerator.cc b/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
index 603232b..5c0bdbc7 100644
--- a/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
+++ b/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
@@ -358,8 +358,7 @@
       },
       base::Unretained(this));
 
-  VaapiVideoEncoderDelegate::Config ave_config{.native_input_mode =
-                                                   native_input_mode_};
+  VaapiVideoEncoderDelegate::Config ave_config{};
   switch (output_codec_) {
     case VideoCodec::kH264:
       if (!IsConfiguredForTesting()) {
@@ -671,6 +670,12 @@
     return false;
   }
 
+  if (!vaapi_wrapper_->UploadVideoFrameToSurface(frame, (*input_surface)->id(),
+                                                 (*input_surface)->size())) {
+    NOTIFY_ERROR(kPlatformFailureError, "Failed to upload frame");
+    return false;
+  }
+
   *reconstructed_surface = CreateEncodeSurface(encode_size);
   return !!*reconstructed_surface;
 }
@@ -795,12 +800,11 @@
 
 std::unique_ptr<VaapiVideoEncoderDelegate::EncodeJob>
 VaapiVideoEncodeAccelerator::CreateEncodeJob(
-    scoped_refptr<VideoFrame> frame,
     bool force_keyframe,
+    base::TimeDelta frame_timestamp,
     const VASurface& input_surface,
     scoped_refptr<VASurface> reconstructed_surface) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(encoder_sequence_checker_);
-  DCHECK(frame);
   DCHECK_NE(input_surface.id(), VA_INVALID_ID);
   DCHECK(!input_surface.size().IsEmpty());
   DCHECK(reconstructed_surface);
@@ -832,8 +836,8 @@
       return nullptr;
   }
 
-  return std::make_unique<EncodeJob>(frame, force_keyframe, input_surface.id(),
-                                     input_surface.size(), std::move(picture),
+  return std::make_unique<EncodeJob>(force_keyframe, frame_timestamp,
+                                     input_surface.id(), std::move(picture),
                                      std::move(coded_buffer));
 }
 
@@ -892,7 +896,7 @@
       TRACE_EVENT0("media,gpu", "VAVEA::FromCreateEncodeJobToReturn");
       const bool force_key =
           (spatial_idx == 0 ? input_frame->force_keyframe : false);
-      job = CreateEncodeJob(input_frame->frame, force_key,
+      job = CreateEncodeJob(force_key, input_frame->frame->timestamp(),
                             *input_surfaces[spatial_idx],
                             std::move(reconstructed_surfaces[spatial_idx]));
       if (!job)
diff --git a/media/gpu/vaapi/vaapi_video_encode_accelerator.h b/media/gpu/vaapi/vaapi_video_encode_accelerator.h
index 53546191..a00720a 100644
--- a/media/gpu/vaapi/vaapi_video_encode_accelerator.h
+++ b/media/gpu/vaapi/vaapi_video_encode_accelerator.h
@@ -178,8 +178,8 @@
   // are available, and if so, claims them by associating them with
   // a EncodeJob, and returns the newly-created job, nullptr otherwise.
   std::unique_ptr<EncodeJob> CreateEncodeJob(
-      scoped_refptr<VideoFrame> frame,
       bool force_keyframe,
+      base::TimeDelta frame_timestamp,
       const VASurface& input_surface,
       scoped_refptr<VASurface> reconstructed_surface);
 
diff --git a/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc b/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc
index 546fe5a..e7076203 100644
--- a/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc
+++ b/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc
@@ -97,13 +97,11 @@
          config.output_profile == VP9PROFILE_PROFILE0;
 }
 
-MATCHER_P3(MatchesVaapiVideoEncoderDelegateConfig,
+MATCHER_P2(MatchesVaapiVideoEncoderDelegateConfig,
            max_ref_frames,
-           native_input_mode,
            bitrate_control,
            "") {
   return arg.max_num_ref_frames == max_ref_frames &&
-         arg.native_input_mode == native_input_mode &&
          arg.bitrate_control == bitrate_control;
 }
 
@@ -222,9 +220,6 @@
   bool UpdateRates(const VideoBitrateAllocation&, uint32_t) override {
     return false;
   }
-  void set_native_input_mode(bool native_input_mode) {
-    native_input_mode_ = native_input_mode;
-  }
 };
 }  // namespace
 
@@ -311,10 +306,6 @@
     ::testing::InSequence s;
     constexpr auto kBitrateControl = VaapiVideoEncoderDelegate::BitrateControl::
         kConstantQuantizationParameter;
-    const bool native_input_mode =
-        config.storage_type.value_or(
-            VideoEncodeAccelerator::Config::StorageType::kShmem) ==
-        VideoEncodeAccelerator::Config::StorageType::kGpuMemoryBuffer;
     const size_t num_spatial_layers = config.spatial_layers.size();
     // Scaling is needed only for non highest spatial layer, so here the vpp
     // number is |num_spatial_layers - 1|.
@@ -334,14 +325,8 @@
 
     EXPECT_CALL(*mock_encoder_,
                 Initialize(_, MatchesVaapiVideoEncoderDelegateConfig(
-                                  kMaxNumOfRefFrames, native_input_mode,
-                                  kBitrateControl)))
-        .WillOnce(WithArgs<1>(
-            [mock_encoder = mock_encoder_](
-                const VaapiVideoEncoderDelegate::Config& ave_config) {
-              mock_encoder->set_native_input_mode(ave_config.native_input_mode);
-              return true;
-            }));
+                                  kMaxNumOfRefFrames, kBitrateControl)))
+        .WillOnce(Return(true));
     EXPECT_CALL(*mock_vaapi_wrapper_, CreateContext(kDefaultEncodeSize))
         .WillOnce(Return(true));
     EXPECT_CALL(client_, RequireBitstreamBuffers(_, kDefaultEncodeSize, _))
@@ -377,6 +362,11 @@
               return va_surfaces;
             }));
 
+    EXPECT_CALL(
+        *mock_vaapi_wrapper_,
+        UploadVideoFrameToSurface(_, kInputSurfaceId, kDefaultEncodeSize))
+        .WillOnce(Return(true));
+
     constexpr VASurfaceID kEncodeSurfaceId = 1234;
     EXPECT_CALL(*mock_vaapi_wrapper_,
                 CreateScopedVASurfaces(
@@ -420,10 +410,6 @@
           }
           return true;
         }));
-    EXPECT_CALL(
-        *mock_vaapi_wrapper_,
-        UploadVideoFrameToSurface(_, kInputSurfaceId, kDefaultEncodeSize))
-        .WillOnce(Return(true));
     EXPECT_CALL(*mock_vaapi_wrapper_,
                 ExecuteAndDestroyPendingBuffers(kInputSurfaceId))
         .WillOnce(Return(true));
diff --git a/media/gpu/vaapi/vaapi_video_encoder_delegate.cc b/media/gpu/vaapi/vaapi_video_encoder_delegate.cc
index 7826dba..21e8ca9 100644
--- a/media/gpu/vaapi/vaapi_video_encoder_delegate.cc
+++ b/media/gpu/vaapi/vaapi_video_encoder_delegate.cc
@@ -19,28 +19,26 @@
 namespace media {
 
 VaapiVideoEncoderDelegate::EncodeJob::EncodeJob(
-    scoped_refptr<VideoFrame> input_frame,
     bool keyframe,
+    base::TimeDelta timestamp,
     VASurfaceID input_surface_id,
-    const gfx::Size& input_surface_size,
     scoped_refptr<CodecPicture> picture,
     std::unique_ptr<ScopedVABuffer> coded_buffer)
-    : input_frame_(input_frame),
-      keyframe_(keyframe),
+    : keyframe_(keyframe),
+      timestamp_(timestamp),
       input_surface_id_(input_surface_id),
-      input_surface_size_(input_surface_size),
       picture_(std::move(picture)),
       coded_buffer_(std::move(coded_buffer)) {
   DCHECK(picture_);
   DCHECK(coded_buffer_);
 }
 
-VaapiVideoEncoderDelegate::EncodeJob::EncodeJob(
-    scoped_refptr<VideoFrame> input_frame,
-    bool keyframe)
-    : input_frame_(input_frame),
-      keyframe_(keyframe),
-      input_surface_id_(VA_INVALID_ID) {}
+VaapiVideoEncoderDelegate::EncodeJob::EncodeJob(bool keyframe,
+                                                base::TimeDelta timestamp,
+                                                VASurfaceID input_surface_id)
+    : keyframe_(keyframe),
+      timestamp_(timestamp),
+      input_surface_id_(input_surface_id) {}
 
 VaapiVideoEncoderDelegate::EncodeJob::~EncodeJob() = default;
 
@@ -51,12 +49,7 @@
 }
 
 base::TimeDelta VaapiVideoEncoderDelegate::EncodeJob::timestamp() const {
-  return input_frame_->timestamp();
-}
-
-const scoped_refptr<VideoFrame>&
-VaapiVideoEncoderDelegate::EncodeJob::input_frame() const {
-  return input_frame_;
+  return timestamp_;
 }
 
 VABufferID VaapiVideoEncoderDelegate::EncodeJob::coded_buffer_id() const {
@@ -67,11 +60,6 @@
   return input_surface_id_;
 }
 
-const gfx::Size& VaapiVideoEncoderDelegate::EncodeJob::input_surface_size()
-    const {
-  return input_surface_size_;
-}
-
 const scoped_refptr<CodecPicture>&
 VaapiVideoEncoderDelegate::EncodeJob::picture() const {
   return picture_;
@@ -128,15 +116,8 @@
     return false;
   }
 
-  const VASurfaceID va_surface_id = encode_job.input_surface_id();
-  if (!native_input_mode_ && !vaapi_wrapper_->UploadVideoFrameToSurface(
-                                 *encode_job.input_frame(), va_surface_id,
-                                 encode_job.input_surface_size())) {
-    VLOGF(1) << "Failed to upload frame";
-    return false;
-  }
-
-  if (!vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(va_surface_id)) {
+  if (!vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(
+          encode_job.input_surface_id())) {
     VLOGF(1) << "Failed to execute encode";
     return false;
   }
diff --git a/media/gpu/vaapi/vaapi_video_encoder_delegate.h b/media/gpu/vaapi/vaapi_video_encoder_delegate.h
index 5a7975e..eeb15e72 100644
--- a/media/gpu/vaapi/vaapi_video_encoder_delegate.h
+++ b/media/gpu/vaapi/vaapi_video_encoder_delegate.h
@@ -52,14 +52,12 @@
   };
 
   struct Config {
-    // Maxium number of reference frames.
+    // Maximum number of reference frames.
     // For H.264 encoding, the value represents the maximum number of reference
     // frames for both the reference picture list 0 (bottom 16 bits) and the
     // reference picture list 1 (top 16 bits).
     size_t max_num_ref_frames;
 
-    bool native_input_mode = false;
-
     BitrateControl bitrate_control = BitrateControl::kConstantBitrate;
   };
 
@@ -91,12 +89,13 @@
     // Creates an EncodeJob to encode |input_frame|, which will be executed by
     // calling ExecuteSetupCallbacks() in VaapiVideoEncoderDelegate::Encode().
     // If |keyframe| is true, requests this job to produce a keyframe.
-    EncodeJob(scoped_refptr<VideoFrame> input_frame, bool keyframe);
+    EncodeJob(bool keyframe,
+              base::TimeDelta timestamp,
+              VASurfaceID input_surface_id);
     // Constructor for VA-API.
-    EncodeJob(scoped_refptr<VideoFrame> input_frame,
-              bool keyframe,
+    EncodeJob(bool keyframe,
+              base::TimeDelta timestamp,
               VASurfaceID input_surface_id,
-              const gfx::Size& input_surface_size,
               scoped_refptr<CodecPicture> picture,
               std::unique_ptr<ScopedVABuffer> coded_buffer);
 
@@ -121,25 +120,20 @@
 
     base::TimeDelta timestamp() const;
 
-    const scoped_refptr<VideoFrame>& input_frame() const;
-
     // VA-API specific methods.
     VABufferID coded_buffer_id() const;
     VASurfaceID input_surface_id() const;
-    const gfx::Size& input_surface_size() const;
     const scoped_refptr<CodecPicture>& picture() const;
 
    private:
-    // Input VideoFrame to be encoded.
-    const scoped_refptr<VideoFrame> input_frame_;
-
     // True if this job is to produce a keyframe.
     bool keyframe_;
+    // |timestamp_| to be added to the produced encoded chunk.
+    const base::TimeDelta timestamp_;
 
     // VA-API specific members.
     // Input surface ID and size for video frame data or scaled data.
     const VASurfaceID input_surface_id_;
-    const gfx::Size input_surface_size_;
     const scoped_refptr<CodecPicture> picture_;
     // Buffer that will contain the output bitstream data for this frame.
     std::unique_ptr<ScopedVABuffer> coded_buffer_;
@@ -192,8 +186,6 @@
 
   base::RepeatingClosure error_cb_;
 
-  bool native_input_mode_ = false;
-
   SEQUENCE_CHECKER(sequence_checker_);
 
  private:
diff --git a/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.cc b/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.cc
index 8581197..3d9532d 100644
--- a/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.cc
+++ b/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.cc
@@ -310,8 +310,6 @@
     }
   }
 
-  native_input_mode_ = ave_config.native_input_mode;
-
   visible_size_ = config.input_visible_size;
   coded_size_ = gfx::Size(base::bits::AlignUp(visible_size_.width(), 16),
                           base::bits::AlignUp(visible_size_.height(), 16));
diff --git a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc
index 31bdfbc..c914355 100644
--- a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc
+++ b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc
@@ -193,8 +193,6 @@
     return false;
   }
 
-  native_input_mode_ = ave_config.native_input_mode;
-
   visible_size_ = config.input_visible_size;
   coded_size_ = gfx::Size(base::bits::AlignUp(visible_size_.width(), 16),
                           base::bits::AlignUp(visible_size_.height(), 16));
diff --git a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc
index f8665b5b..cbf37a4 100644
--- a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc
+++ b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc
@@ -50,7 +50,6 @@
 
 VaapiVideoEncoderDelegate::Config kDefaultVaapiVideoEncoderDelegateConfig{
     .max_num_ref_frames = kDefaultMaxNumRefFrames,
-    .native_input_mode = false,
     .bitrate_control = VaapiVideoEncoderDelegate::BitrateControl::
         kConstantQuantizationParameter};
 
@@ -324,21 +323,16 @@
     bool keyframe,
     const scoped_refptr<VASurface>& va_surface,
     const scoped_refptr<VP9Picture>& picture) {
-  auto input_frame = VideoFrame::CreateFrame(
-      kDefaultVideoEncodeAcceleratorConfig.input_format,
-      kDefaultVideoEncodeAcceleratorConfig.input_visible_size,
-      gfx::Rect(kDefaultVideoEncodeAcceleratorConfig.input_visible_size),
-      kDefaultVideoEncodeAcceleratorConfig.input_visible_size,
-      base::TimeDelta());
-  LOG_ASSERT(input_frame) << " Failed to create VideoFrame";
-
   constexpr VABufferID kDummyVABufferID = 12;
   auto scoped_va_buffer = ScopedVABuffer::CreateForTesting(
       kDummyVABufferID, VAEncCodedBufferType,
       kDefaultVideoEncodeAcceleratorConfig.input_visible_size.GetArea());
 
+  // TODO(b/229358029): Set a valid timestamp and check the timestamp in
+  // metadata.
+  constexpr base::TimeDelta timestamp;
   return std::make_unique<VaapiVideoEncoderDelegate::EncodeJob>(
-      input_frame, keyframe, va_surface->id(), va_surface->size(), picture,
+      keyframe, timestamp, va_surface->id(), picture,
       std::move(scoped_va_buffer));
 }
 
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 2f66d8a..4b7f092 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -8414,7 +8414,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M101",
-              "revision": "version:101.0.4951.55"
+              "revision": "version:101.0.4951.56"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8498,7 +8498,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.36"
+              "revision": "version:102.0.5005.37"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8918,7 +8918,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M101",
-              "revision": "version:101.0.4951.55"
+              "revision": "version:101.0.4951.56"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -9002,7 +9002,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.36"
+              "revision": "version:102.0.5005.37"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index dcc98025..cd0fdfc 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -46159,7 +46159,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M101",
-              "revision": "version:101.0.4951.55"
+              "revision": "version:101.0.4951.56"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46243,7 +46243,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.36"
+              "revision": "version:102.0.5005.37"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46663,7 +46663,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M101",
-              "revision": "version:101.0.4951.55"
+              "revision": "version:101.0.4951.56"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46747,7 +46747,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.36"
+              "revision": "version:102.0.5005.37"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47171,7 +47171,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M101",
-              "revision": "version:101.0.4951.55"
+              "revision": "version:101.0.4951.56"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47255,7 +47255,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.36"
+              "revision": "version:102.0.5005.37"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47675,7 +47675,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M101",
-              "revision": "version:101.0.4951.55"
+              "revision": "version:101.0.4951.56"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47759,7 +47759,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.36"
+              "revision": "version:102.0.5005.37"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48250,7 +48250,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M101",
-              "revision": "version:101.0.4951.55"
+              "revision": "version:101.0.4951.56"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48334,7 +48334,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.36"
+              "revision": "version:102.0.5005.37"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48754,7 +48754,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M101",
-              "revision": "version:101.0.4951.55"
+              "revision": "version:101.0.4951.56"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48838,7 +48838,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.36"
+              "revision": "version:102.0.5005.37"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49329,7 +49329,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M101",
-              "revision": "version:101.0.4951.55"
+              "revision": "version:101.0.4951.56"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49413,7 +49413,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.36"
+              "revision": "version:102.0.5005.37"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49833,7 +49833,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M101",
-              "revision": "version:101.0.4951.55"
+              "revision": "version:101.0.4951.56"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49917,7 +49917,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.36"
+              "revision": "version:102.0.5005.37"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 577505e..a014c23 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5881,21 +5881,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5035.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5037.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 103.0.5035.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5037.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_v103.0.5035.0",
-              "revision": "version:103.0.5035.0"
+              "location": "lacros_version_skew_tests_v103.0.5037.0",
+              "revision": "version:103.0.5037.0"
             }
           ],
           "dimension_sets": [
@@ -6023,21 +6023,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5035.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5037.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 103.0.5035.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5037.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_v103.0.5035.0",
-              "revision": "version:103.0.5035.0"
+              "location": "lacros_version_skew_tests_v103.0.5037.0",
+              "revision": "version:103.0.5037.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 538b1f9..2320786 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -87726,21 +87726,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5035.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5037.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 103.0.5035.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5037.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_v103.0.5035.0",
-              "revision": "version:103.0.5035.0"
+              "location": "lacros_version_skew_tests_v103.0.5037.0",
+              "revision": "version:103.0.5037.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -87843,21 +87843,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5035.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5037.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 103.0.5035.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5037.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_v103.0.5035.0",
-              "revision": "version:103.0.5035.0"
+              "location": "lacros_version_skew_tests_v103.0.5037.0",
+              "revision": "version:103.0.5037.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -89235,20 +89235,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5035.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5037.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5035.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5037.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_v103.0.5035.0",
-              "revision": "version:103.0.5035.0"
+              "location": "lacros_version_skew_tests_v103.0.5037.0",
+              "revision": "version:103.0.5037.0"
             }
           ],
           "dimension_sets": [
@@ -89377,20 +89377,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5035.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5037.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 103.0.5035.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5037.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_v103.0.5035.0",
-              "revision": "version:103.0.5035.0"
+              "location": "lacros_version_skew_tests_v103.0.5037.0",
+              "revision": "version:103.0.5037.0"
             }
           ],
           "dimension_sets": [
@@ -90932,20 +90932,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5035.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5037.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5035.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5037.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_v103.0.5035.0",
-              "revision": "version:103.0.5035.0"
+              "location": "lacros_version_skew_tests_v103.0.5037.0",
+              "revision": "version:103.0.5037.0"
             }
           ],
           "dimension_sets": [
@@ -91074,20 +91074,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5035.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5037.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 103.0.5035.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5037.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_v103.0.5035.0",
-              "revision": "version:103.0.5035.0"
+              "location": "lacros_version_skew_tests_v103.0.5037.0",
+              "revision": "version:103.0.5037.0"
             }
           ],
           "dimension_sets": [
@@ -91831,20 +91831,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5035.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5037.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 103.0.5035.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 103.0.5037.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_v103.0.5035.0",
-              "revision": "version:103.0.5035.0"
+              "location": "lacros_version_skew_tests_v103.0.5037.0",
+              "revision": "version:103.0.5037.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 183656d25..05531e6 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_v103.0.5035.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5037.0/test_ash_chrome',
     ],
-    'identifier': 'Lacros version skew testing ash 103.0.5035.0',
+    'identifier': 'Lacros version skew testing ash 103.0.5037.0',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v103.0.5035.0',
-          'revision': 'version:103.0.5035.0',
+          'location': 'lacros_version_skew_tests_v103.0.5037.0',
+          'revision': 'version:103.0.5037.0',
         },
       ],
     },
@@ -461,7 +461,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M102',
-          'revision': 'version:102.0.5005.36',
+          'revision': 'version:102.0.5005.37',
         }
       ],
     },
@@ -485,7 +485,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M101',
-          'revision': 'version:101.0.4951.55',
+          'revision': 'version:101.0.4951.56',
         }
       ],
     },
@@ -605,7 +605,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M102',
-          'revision': 'version:102.0.5005.36',
+          'revision': 'version:102.0.5005.37',
         }
       ],
     },
@@ -629,7 +629,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M101',
-          'revision': 'version:101.0.4951.55',
+          'revision': 'version:101.0.4951.56',
         }
       ],
     },
@@ -749,7 +749,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M102',
-          'revision': 'version:102.0.5005.36',
+          'revision': 'version:102.0.5005.37',
         }
       ],
     },
@@ -773,7 +773,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M101',
-          'revision': 'version:101.0.4951.55',
+          'revision': 'version:101.0.4951.56',
         }
       ],
     },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index d7ea038..a08ac99 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1530,8 +1530,8 @@
                         "unload_support": "no"
                     },
                     "enable_features": [
-                        "BFCachePerformanceManagerPolicy",
                         "BackForwardCache",
+                        "FreezeWhileKeepActive",
                         "LoadingTasksUnfreezable"
                     ]
                 }
@@ -3368,6 +3368,7 @@
                 "chromeos",
                 "chromeos_lacros",
                 "linux",
+                "mac",
                 "windows"
             ],
             "experiments": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 42acfa5..f71faee 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -715,9 +715,6 @@
 const base::Feature kCancelFormSubmissionInDefaultHandler{
     "CancelFormSubmissionInDefaultHandler", base::FEATURE_ENABLED_BY_DEFAULT};
 
-const base::Feature kKeepScriptResourceAlive{"KeepScriptResourceAlive",
-                                             base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Enables the JPEG XL Image File Format (JXL).
 const base::Feature kJXL{"JXL", base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 39256985..7fe2933 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -272,8 +272,6 @@
 BLINK_COMMON_EXPORT extern const base::Feature
     kCancelFormSubmissionInDefaultHandler;
 
-BLINK_COMMON_EXPORT extern const base::Feature kKeepScriptResourceAlive;
-
 BLINK_COMMON_EXPORT extern const base::Feature
     kAlignFontDisplayAutoTimeoutWithLCPGoal;
 BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
diff --git a/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom b/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom
index fca00d1..97d955ca 100644
--- a/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom
+++ b/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom
@@ -14,7 +14,7 @@
 
 // Represents a Chrome OS window which can be manipulated by a Window Management
 // System Extension.
-struct CrosWindow {
+struct CrosWindowInfo {
   // A unique identifier for this window.
   mojo_base.mojom.UnguessableToken id;
   // The App ID of the App that this window is an instance of.
@@ -38,7 +38,7 @@
 // Called by System Extensions Renderers and implemented by Ash Chrome.
 interface CrosWindowManagement {
   // Returns all windows visible to a window manager.
-  GetAllWindows() => (array<CrosWindow> result);
+  GetAllWindows() => (array<CrosWindowInfo> result);
 
   // Sets the bounds of a CrosWindow where |hash| is used as the window
   // identifier.
diff --git a/third_party/blink/public/strings/translations/blink_accessibility_strings_hy.xtb b/third_party/blink/public/strings/translations/blink_accessibility_strings_hy.xtb
index 98110469..97ca5909 100644
--- a/third_party/blink/public/strings/translations/blink_accessibility_strings_hy.xtb
+++ b/third_party/blink/public/strings/translations/blink_accessibility_strings_hy.xtb
@@ -64,7 +64,7 @@
 <translation id="6632254525813309835">Շրջանաձև ձախ սլաքի պատկերակ, կարող է նշանակել «Հետարկել»</translation>
 <translation id="6889412865110485830">Գնումների զամբյուղի պատկերակ</translation>
 <translation id="6940482800520966738">Աստղի պատկերակ</translation>
-<translation id="7022838723850801004">Ուրախ և տխուր դեմքով զմայլիկի պատկերակ</translation>
+<translation id="7022838723850801004">Ուրախ և տխուր դեմքով էմոջիի պատկերակ</translation>
 <translation id="7118469954320184356">Նկարագրություն չկա:</translation>
 <translation id="7410239719251593705">Կարծես թե պարունակում է բովանդակություն մեծահասակների համար։ Նկարագրություն չկա:</translation>
 <translation id="7533959249147584474">Չպիտակված գծապատկեր</translation>
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc b/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc
index e59695c..1bdf9229 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc
@@ -16,6 +16,27 @@
 
 namespace blink {
 
+class ScriptPromiseResolver::ExceptionStateScope final : public ExceptionState {
+  STACK_ALLOCATED();
+
+ public:
+  explicit ExceptionStateScope(ScriptPromiseResolver* resolver)
+      : ExceptionState(resolver->script_state_->GetIsolate(),
+                       resolver->exception_context_),
+        resolver_(resolver) {
+    CHECK_NE(resolver->exception_context_.GetContext(),
+             ExceptionContext::Context::kEmpty);
+  }
+  ~ExceptionStateScope() {
+    DCHECK(HadException());
+    resolver_->Reject(GetException());
+    ClearException();
+  }
+
+ private:
+  ScriptPromiseResolver* resolver_;
+};
+
 ScriptPromiseResolver::ScriptPromiseResolver(ScriptState* script_state)
     : ExecutionContextLifecycleObserver(ExecutionContext::From(script_state)),
       state_(kPending),
@@ -27,6 +48,13 @@
   }
 }
 
+ScriptPromiseResolver::ScriptPromiseResolver(
+    ScriptState* script_state,
+    const ExceptionContext& exception_context)
+    : ScriptPromiseResolver(script_state) {
+  exception_context_ = exception_context;
+}
+
 ScriptPromiseResolver::~ScriptPromiseResolver() = default;
 
 void ScriptPromiseResolver::Dispose() {
@@ -61,6 +89,31 @@
   exception_state.ClearException();
 }
 
+void ScriptPromiseResolver::RejectWithDOMException(
+    DOMExceptionCode exception_code,
+    const String& message) {
+  ExceptionStateScope(this).ThrowDOMException(exception_code, message);
+}
+
+void ScriptPromiseResolver::RejectWithSecurityError(
+    const String& sanitized_message,
+    const String& unsanitized_message) {
+  ExceptionStateScope(this).ThrowSecurityError(sanitized_message,
+                                               unsanitized_message);
+}
+
+void ScriptPromiseResolver::RejectWithTypeError(const String& message) {
+  ExceptionStateScope(this).ThrowTypeError(message);
+}
+
+void ScriptPromiseResolver::RejectWithRangeError(const String& message) {
+  ExceptionStateScope(this).ThrowRangeError(message);
+}
+
+void ScriptPromiseResolver::RejectWithWasmCompileError(const String& message) {
+  ExceptionStateScope(this).ThrowWasmCompileError(message);
+}
+
 void ScriptPromiseResolver::Detach() {
   if (state_ == kDetached)
     return;
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h b/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h
index 497aff9..ec07c88 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h
+++ b/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h
@@ -45,6 +45,10 @@
 
  public:
   explicit ScriptPromiseResolver(ScriptState*);
+  // Use this constructor if resolver is intended to be used in a callback
+  // function to reject with exception. ExceptionState will be used for
+  // creating exceptions in functions like RejectWithDOMException method.
+  explicit ScriptPromiseResolver(ScriptState*, const ExceptionContext&);
 
   ScriptPromiseResolver(const ScriptPromiseResolver&) = delete;
   ScriptPromiseResolver& operator=(const ScriptPromiseResolver&) = delete;
@@ -95,6 +99,22 @@
   // Reject with a given exception.
   void Reject(ExceptionState&);
 
+  // Following functions create exceptions using ExceptionState.
+  // They require ScriptPromiseResolver to be created with ExceptionContext.
+
+  // Reject with DOMException with given exception code.
+  void RejectWithDOMException(DOMExceptionCode exception_code,
+                              const String& message);
+  // Reject with DOMException with SECURITY_ERR.
+  void RejectWithSecurityError(const String& sanitized_message,
+                               const String& unsanitized_message);
+  // Reject with ECMAScript Error object.
+  void RejectWithTypeError(const String& message);
+  void RejectWithRangeError(const String& message);
+
+  // Reject with WebAssembly Error object.
+  void RejectWithWasmCompileError(const String& message);
+
   ScriptState* GetScriptState() const { return script_state_; }
 
   // Note that an empty ScriptPromise will be returned after resolve or
@@ -130,6 +150,7 @@
   void Trace(Visitor*) const override;
 
  private:
+  class ExceptionStateScope;
   typedef ScriptPromise::InternalResolver Resolver;
   enum ResolutionState {
     kPending,
@@ -189,6 +210,7 @@
   TaskHandle deferred_resolve_task_;
   Resolver resolver_;
   TraceWrapperV8Reference<v8::Value> value_;
+  ExceptionContext exception_context_;
 
   // To support keepAliveWhilePending(), this object needs to keep itself
   // alive while in that state.
diff --git a/third_party/blink/renderer/core/css/selector_filter.h b/third_party/blink/renderer/core/css/selector_filter.h
index 1c28c155..bc021ecc 100644
--- a/third_party/blink/renderer/core/css/selector_filter.h
+++ b/third_party/blink/renderer/core/css/selector_filter.h
@@ -119,7 +119,7 @@
 
   // With 100 unique strings in the filter, 2^12 slot table has false positive
   // rate of ~0.2%.
-  using IdentifierFilter = BloomFilter<12>;
+  using IdentifierFilter = CountingBloomFilter<12>;
   std::unique_ptr<IdentifierFilter> ancestor_identifier_filter_;
 };
 
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index 416790e..0ee40eb 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -2180,16 +2180,19 @@
           .WithWindow(DomWindow(), nullptr)
           .WithTypeFrom(mime_type)
           .ForPrerendering(GetPage()->IsPrerendering()));
+  DCHECK_EQ(document, GetDocument());
   DocumentParser* parser = document->OpenForNavigation(
       kForceSynchronousParsing, mime_type, AtomicString("UTF-8"));
   for (const auto& segment : *data)
     parser->AppendBytes(segment.data(), segment.size());
   parser->Finish();
 
-  // Upon loading of SVGImages, log PageVisits in UseCounter.
+  // Upon loading of SVGImages, log PageVisits in UseCounter if we did not
+  // replace the document in `parser->Finish()`, which may happen when XSLT
+  // finishes processing.
   // Do not track PageVisits for inspector, web page popups, and validation
   // message overlays (the other callers of this method).
-  if (document->IsSVGDocument())
+  if (document == GetDocument() && document->IsSVGDocument())
     loader_.GetDocumentLoader()->GetUseCounter().DidCommitLoad(this);
 }
 
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index 6bf0085..c2dcb71 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -856,13 +856,16 @@
     } else {
       if (HasOrthogonalWritingModeRoots())
         LayoutOrthogonalWritingModeRoots();
+
+      default_allow_deferred_shaping_ =
+          default_allow_deferred_shaping_ &&
+          RuntimeEnabledFeatures::DeferredShapingEnabled() &&
+          !frame_->PagePopupOwner() &&
+          !FirstMeaningfulPaintDetector::From(*frame_->GetDocument())
+               .SeenFirstMeaningfulPaint();
       base::AutoReset<bool> deferred_shaping(
           &allow_deferred_shaping_,
-          RuntimeEnabledFeatures::DeferredShapingEnabled() &&
-              default_allow_deferred_shaping_ && !frame_->PagePopupOwner() &&
-              !document->Printing() &&
-              !FirstMeaningfulPaintDetector::From(*frame_->GetDocument())
-                   .SeenFirstMeaningfulPaint() &&
+          default_allow_deferred_shaping_ && !document->Printing() &&
               // Locking many shaping-deferred elements is very slow if we have
               // ScopedForcedUpdate instances.
               // Without this check, PerformPostLayoutTasks() takes 200 seconds
diff --git a/third_party/blink/renderer/core/input/widget_event_handler.h b/third_party/blink/renderer/core/input/widget_event_handler.h
index c3d102d5..ccff1956 100644
--- a/third_party/blink/renderer/core/input/widget_event_handler.h
+++ b/third_party/blink/renderer/core/input/widget_event_handler.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_WIDGET_EVENT_HANDLER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_WIDGET_EVENT_HANDLER_H_
 
+#include <memory>
 #include <vector>
 
 #include "third_party/blink/public/platform/web_input_event_result.h"
diff --git a/third_party/blink/renderer/core/layout/scroll_anchor.cc b/third_party/blink/renderer/core/layout/scroll_anchor.cc
index d26c69c9..b07e38fa 100644
--- a/third_party/blink/renderer/core/layout/scroll_anchor.cc
+++ b/third_party/blink/renderer/core/layout/scroll_anchor.cc
@@ -41,7 +41,7 @@
 }  // anonymous namespace
 
 // With 100 unique strings, a 2^12 slot table has a false positive rate of ~2%.
-using ClassnameFilter = BloomFilter<12>;
+using ClassnameFilter = CountingBloomFilter<12>;
 using Corner = ScrollAnchor::Corner;
 
 ScrollAnchor::ScrollAnchor()
diff --git a/third_party/blink/renderer/core/paint/ng/ng_highlight_overlay.cc b/third_party/blink/renderer/core/paint/ng/ng_highlight_overlay.cc
index 58da5c1e..4c91bc51 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_highlight_overlay.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_highlight_overlay.cc
@@ -356,8 +356,7 @@
     wtf_size_t edge_layer_index = layers.Find(edge.layer);
     DCHECK_NE(edge_layer_index, kNotFound)
         << "edge layer should be one of the given layers";
-    // TODO(crbug.com/1147859) this will crash if there are overlapping ranges
-    // for a given highlight layer (see logic in old ComputeMarkersToPaint)
+    // This algorithm malfunctions if the edges represent overlapping ranges.
     DCHECK(active[edge_layer_index] ? edge.type == HighlightEdgeType::kEnd
                                     : edge.type == HighlightEdgeType::kStart)
         << "edge should be kStart iff the layer is active or else kEnd";
diff --git a/third_party/blink/renderer/core/paint/ng/ng_highlight_overlay.h b/third_party/blink/renderer/core/paint/ng/ng_highlight_overlay.h
index ebfbe69..a8be6b6 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_highlight_overlay.h
+++ b/third_party/blink/renderer/core/paint/ng/ng_highlight_overlay.h
@@ -118,6 +118,9 @@
   // Given highlight |layers| and |edges|, returns the ranges that the given
   // |layer| should paint text proper for, suppressing ranges where it’s not the
   // topmost active highlight and splitting for underlying decoration changes.
+  //
+  // The edges must not represent overlapping ranges. If the highlight is active
+  // in overlapping ranges, those ranges must be merged before ComputeEdges.
   static Vector<HighlightPart> ComputeParts(
       const Vector<HighlightLayer>& layers,
       const Vector<HighlightEdge>& edges);
diff --git a/third_party/blink/renderer/core/paint/ng/ng_highlight_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_highlight_painter.cc
index ca889ed5..e6b0d22 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_highlight_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_highlight_painter.cc
@@ -769,8 +769,7 @@
 
 void NGHighlightPainter::PaintDecorationsExceptLineThrough(
     const HighlightPart& part) {
-  GraphicsContextStateSaver state_saver(paint_info_.context);
-  ClipToPartDecorations(part);
+  GraphicsContextStateSaver state_saver(paint_info_.context, false);
 
   for (const HighlightLayer& decoration_layer_id : part.decorations) {
     wtf_size_t decoration_layer_index = layers_.Find(decoration_layer_id);
@@ -780,6 +779,11 @@
     if (!decoration_layer.decoration_info)
       continue;
 
+    if (!state_saver.Saved()) {
+      state_saver.Save();
+      ClipToPartDecorations(part);
+    }
+
     if (decoration_layer_id.type == HighlightLayerType::kOriginating &&
         part.layer.type != HighlightLayerType::kOriginating) {
       wtf_size_t part_layer_index = layers_.Find(part.layer);
@@ -799,8 +803,7 @@
 
 void NGHighlightPainter::PaintDecorationsOnlyLineThrough(
     const HighlightPart& part) {
-  GraphicsContextStateSaver state_saver(paint_info_.context);
-  ClipToPartDecorations(part);
+  GraphicsContextStateSaver state_saver(paint_info_.context, false);
 
   for (const HighlightLayer& decoration_layer_id : part.decorations) {
     wtf_size_t decoration_layer_index = layers_.Find(decoration_layer_id);
@@ -811,6 +814,11 @@
         !decoration_layer.has_line_through_decorations)
       continue;
 
+    if (!state_saver.Saved()) {
+      state_saver.Save();
+      ClipToPartDecorations(part);
+    }
+
     if (decoration_layer_id.type == HighlightLayerType::kOriginating &&
         part.layer.type != HighlightLayerType::kOriginating) {
       wtf_size_t part_layer_index = layers_.Find(part.layer);
diff --git a/third_party/blink/renderer/core/script/script_loader.cc b/third_party/blink/renderer/core/script/script_loader.cc
index 9da1359..7da276c 100644
--- a/third_party/blink/renderer/core/script/script_loader.cc
+++ b/third_party/blink/renderer/core/script/script_loader.cc
@@ -1126,9 +1126,7 @@
   // memory cache. So we keep |resource_keep_alive_| to keep the resource in the
   // memory cache.
   if (resource_keep_alive_ &&
-      !resource_keep_alive_->GetResponse().IsSignedExchangeInnerResponse() &&
-      !base::FeatureList::IsEnabled(
-          blink::features::kKeepScriptResourceAlive)) {
+      !resource_keep_alive_->GetResponse().IsSignedExchangeInnerResponse()) {
     resource_keep_alive_ = nullptr;
   }
 }
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc b/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc
index 5d8573f3..d0ea087 100644
--- a/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc
+++ b/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc
@@ -7,8 +7,10 @@
 #include <memory>
 
 #include "base/memory/ptr_util.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "cc/paint/paint_flags.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/scheme_registry.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
@@ -364,4 +366,41 @@
   EXPECT_FALSE(Compositor().NeedsBeginFrame());
 }
 
+TEST_F(SVGImageSimTest, SVGWithXSLT) {
+  // To make "https" scheme counted as "Blink.UseCounter.Extensions.Features",
+  // we should make it recognized as an extension.
+  CommonSchemeRegistry::RegisterURLSchemeAsExtension("https");
+
+  SimRequest main_resource("https://example.com/", "text/html");
+  SimSubresourceRequest image_resource("https://example.com/image.svg",
+                                       "image/svg+xml");
+
+  base::HistogramTester histograms;
+  LoadURL("https://example.com/");
+  main_resource.Complete(R"HTML(
+    <img src="image.svg">
+  )HTML");
+  image_resource.Complete(R"SVG(<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="#stylesheet"?>
+<!DOCTYPE svg [
+<!ATTLIST xsl:stylesheet
+id ID #REQUIRED>
+]>
+<svg>
+    <xsl:stylesheet id="stylesheet" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:svg="http://www.w3.org/2000/svg"></xsl:stylesheet>
+</svg>)SVG");
+
+  Compositor().BeginFrame();
+  test::RunPendingTasks();
+  // The previous frame should result in a stable state and should not schedule
+  // new visual updates.
+  EXPECT_FALSE(Compositor().NeedsBeginFrame());
+
+  // Ensure |UseCounter.DidCommitLoad| is called once.
+  // Since we cannot use |UseCounter.IsCounted(WebFeature::kPageVisits)|, we
+  // check the histogram updated in |DidCommitLoad|.
+  histograms.ExpectBucketCount("Blink.UseCounter.Extensions.Features",
+                               WebFeature::kPageVisits, 1);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.cc b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.cc
index 8e1d18d..aaaf7e8a 100644
--- a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.cc
+++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.cc
@@ -16,7 +16,7 @@
 static constexpr char kHidden[] = "hidden";
 
 CrosWindow::CrosWindow(CrosWindowManagement* manager,
-                       mojom::blink::CrosWindowPtr window)
+                       mojom::blink::CrosWindowInfoPtr window)
     : window_management_(manager), window_(std::move(window)) {}
 
 void CrosWindow::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.h b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.h
index cf057e31..c94076e 100644
--- a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.h
+++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.h
@@ -18,7 +18,8 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  CrosWindow(CrosWindowManagement* manager, mojom::blink::CrosWindowPtr window);
+  CrosWindow(CrosWindowManagement* manager,
+             mojom::blink::CrosWindowInfoPtr window);
 
   void Trace(Visitor*) const override;
 
@@ -46,7 +47,7 @@
  private:
   Member<CrosWindowManagement> window_management_;
 
-  mojom::blink::CrosWindowPtr window_;
+  mojom::blink::CrosWindowInfoPtr window_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.cc b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.cc
index 812d827a..1cee61e 100644
--- a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.cc
+++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.cc
@@ -38,7 +38,7 @@
   return cros_window_management_.get();
 }
 
-ScriptPromise CrosWindowManagement::windows(ScriptState* script_state) {
+ScriptPromise CrosWindowManagement::getWindows(ScriptState* script_state) {
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
   auto* window_management = GetCrosWindowManagementOrNull();
   if (window_management) {
@@ -51,7 +51,7 @@
 
 void CrosWindowManagement::WindowsCallback(
     ScriptPromiseResolver* resolver,
-    WTF::Vector<mojom::blink::CrosWindowPtr> windows) {
+    WTF::Vector<mojom::blink::CrosWindowInfoPtr> windows) {
   HeapVector<Member<CrosWindow>> results;
   results.ReserveInitialCapacity(windows.size());
   for (auto& w : windows) {
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.h b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.h
index f530e46a..47c5ee7 100644
--- a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.h
+++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.h
@@ -27,9 +27,9 @@
   // implementation. May return null in error cases.
   mojom::blink::CrosWindowManagement* GetCrosWindowManagementOrNull();
 
-  ScriptPromise windows(ScriptState* script_state);
+  ScriptPromise getWindows(ScriptState* script_state);
   void WindowsCallback(ScriptPromiseResolver* resolver,
-                       WTF::Vector<mojom::blink::CrosWindowPtr> windows);
+                       WTF::Vector<mojom::blink::CrosWindowInfoPtr> windows);
 
  private:
   HeapMojoRemote<mojom::blink::CrosWindowManagement> cros_window_management_;
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.idl b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.idl
index c2f0976..075fde0f 100644
--- a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.idl
+++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.idl
@@ -3,5 +3,5 @@
 // found in the LICENSE file.
 
 interface CrosWindowManagement {
-  [CallWith=ScriptState] Promise<sequence<CrosWindow>> windows();
+  [CallWith=ScriptState] Promise<sequence<CrosWindow>> getWindows();
 };
diff --git a/third_party/blink/renderer/modules/eyedropper/eye_dropper.cc b/third_party/blink/renderer/modules/eyedropper/eye_dropper.cc
index 2402045..3115c86 100644
--- a/third_party/blink/renderer/modules/eyedropper/eye_dropper.cc
+++ b/third_party/blink/renderer/modules/eyedropper/eye_dropper.cc
@@ -7,7 +7,6 @@
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_color_selection_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_color_selection_result.h"
@@ -92,7 +91,8 @@
         MakeGarbageCollected<OpenAbortAlgorithm>(this, signal_));
   }
 
-  resolver_ = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  resolver_ = MakeGarbageCollected<ScriptPromiseResolver>(
+      script_state, exception_state.GetContext());
   ScriptPromise promise = resolver_->Promise();
 
   auto* frame = window->GetFrame();
@@ -101,9 +101,8 @@
           frame->GetTaskRunner(TaskType::kUserInteraction)));
   eye_dropper_chooser_.set_disconnect_handler(
       WTF::Bind(&EyeDropper::EndChooser, WrapWeakPersistent(this)));
-  eye_dropper_chooser_->Choose(WTF::Bind(&EyeDropper::EyeDropperResponseHandler,
-                                         WrapPersistent(this),
-                                         WrapPersistent(resolver_.Get())));
+  eye_dropper_chooser_->Choose(resolver_->WrapCallbackInScriptScope(
+      WTF::Bind(&EyeDropper::EyeDropperResponseHandler, WrapPersistent(this))));
 
   return promise;
 }
@@ -143,12 +142,7 @@
   // so by receiving a reply, the eye dropper operation must *not* have
   // been aborted by the abort signal. Thus, the promise is not yet resolved,
   // so resolver_ must be non-null.
-  DCHECK(resolver_);
-  if (!IsInParallelAlgorithmRunnable(resolver_->GetExecutionContext(),
-                                     resolver_->GetScriptState()))
-    return;
-
-  ScriptState::Scope script_state_scope(resolver->GetScriptState());
+  DCHECK_EQ(resolver_, resolver);
 
   if (success) {
     ColorSelectionResult* result = ColorSelectionResult::Create();
@@ -175,11 +169,7 @@
 
 void EyeDropper::RejectPromiseHelper(DOMExceptionCode exception_code,
                                      const WTF::String& message) {
-  v8::Local<v8::Value> v8_value = V8ThrowDOMException::CreateOrEmpty(
-      resolver_->GetScriptState()->GetIsolate(), exception_code, message);
-  if (!v8_value.IsEmpty())
-    resolver_->Reject(v8_value);
-
+  resolver_->RejectWithDOMException(exception_code, message);
   resolver_ = nullptr;
 }
 
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_worklet_thread.cc b/third_party/blink/renderer/modules/webaudio/offline_audio_worklet_thread.cc
index d2c053dd..4340fdb 100644
--- a/third_party/blink/renderer/modules/webaudio/offline_audio_worklet_thread.cc
+++ b/third_party/blink/renderer/modules/webaudio/offline_audio_worklet_thread.cc
@@ -10,9 +10,21 @@
 
 namespace blink {
 
-template class WorkletThreadHolder<OfflineAudioWorkletThread>;
+namespace {
 
-int OfflineAudioWorkletThread::s_ref_count_ = 0;
+// Use for ref-counting of all OfflineAudioWorkletThread instances in a
+// process. Incremented by the constructor and decremented by destructor.
+static int ref_count = 0;
+
+static void EnsureSharedBackingThread(const ThreadCreationParams& params) {
+  DCHECK(IsMainThread());
+  DCHECK_EQ(ref_count, 1);
+  WorkletThreadHolder<OfflineAudioWorkletThread>::EnsureInstance(params);
+}
+
+}  // namespace
+
+template class WorkletThreadHolder<OfflineAudioWorkletThread>;
 
 OfflineAudioWorkletThread::OfflineAudioWorkletThread(
     WorkerReportingProxy& worker_reporting_proxy)
@@ -28,14 +40,15 @@
   // OfflineAudioWorkletThread always uses a NORMAL priority thread.
   params.thread_priority = base::ThreadPriority::NORMAL;
 
-  if (++s_ref_count_ == 1) {
+  if (++ref_count == 1) {
     EnsureSharedBackingThread(params);
   }
 }
 
 OfflineAudioWorkletThread::~OfflineAudioWorkletThread() {
   DCHECK(IsMainThread());
-  if (--s_ref_count_ == 0) {
+  DCHECK_GT(ref_count, 0);
+  if (--ref_count == 0) {
     ClearSharedBackingThread();
   }
 }
@@ -45,15 +58,9 @@
       ->GetThread();
 }
 
-void OfflineAudioWorkletThread::EnsureSharedBackingThread(
-    const ThreadCreationParams& params) {
-  DCHECK(IsMainThread());
-  WorkletThreadHolder<OfflineAudioWorkletThread>::EnsureInstance(params);
-}
-
 void OfflineAudioWorkletThread::ClearSharedBackingThread() {
   DCHECK(IsMainThread());
-  CHECK_EQ(s_ref_count_, 0);
+  CHECK_EQ(ref_count, 0);
   WorkletThreadHolder<OfflineAudioWorkletThread>::ClearInstance();
 }
 
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_worklet_thread.h b/third_party/blink/renderer/modules/webaudio/offline_audio_worklet_thread.h
index 586531e..0dd62fd 100644
--- a/third_party/blink/renderer/modules/webaudio/offline_audio_worklet_thread.h
+++ b/third_party/blink/renderer/modules/webaudio/offline_audio_worklet_thread.h
@@ -12,7 +12,6 @@
 namespace blink {
 
 class WorkerReportingProxy;
-struct ThreadCreationParams;
 
 // OfflineAudioWorkletThread is a per-AudioWorkletGlobalScope object that has a
 // reference count to the backing thread that performs AudioWorklet tasks.
@@ -26,7 +25,6 @@
   WorkerBackingThread& GetWorkerBackingThread() final;
   void ClearWorkerBackingThread() final {}
 
-  static void EnsureSharedBackingThread(const ThreadCreationParams&);
   static void ClearSharedBackingThread();
 
  private:
@@ -36,10 +34,6 @@
   ThreadType GetThreadType() const final {
     return ThreadType::kOfflineAudioWorkletThread;
   }
-
-  // Use for ref-counting of all OfflineAudioWorkletThread instances in a
-  // process. Incremented by the constructor and decremented by destructor.
-  static int s_ref_count_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/realtime_audio_worklet_thread.cc b/third_party/blink/renderer/modules/webaudio/realtime_audio_worklet_thread.cc
index 3372575..5e919929 100644
--- a/third_party/blink/renderer/modules/webaudio/realtime_audio_worklet_thread.cc
+++ b/third_party/blink/renderer/modules/webaudio/realtime_audio_worklet_thread.cc
@@ -12,9 +12,21 @@
 
 namespace blink {
 
-template class WorkletThreadHolder<RealtimeAudioWorkletThread>;
+namespace {
 
-int RealtimeAudioWorkletThread::s_ref_count_ = 0;
+// Use for ref-counting of all RealtimeAudioWorkletThread instances in a
+// process. Incremented by the constructor and decremented by destructor.
+static int ref_count = 0;
+
+static void EnsureSharedBackingThread(const ThreadCreationParams& params) {
+  DCHECK(IsMainThread());
+  DCHECK_EQ(ref_count, 1);
+  WorkletThreadHolder<RealtimeAudioWorkletThread>::EnsureInstance(params);
+}
+
+}  // namespace
+
+template class WorkletThreadHolder<RealtimeAudioWorkletThread>;
 
 RealtimeAudioWorkletThread::RealtimeAudioWorkletThread(
     WorkerReportingProxy& worker_reporting_proxy)
@@ -42,14 +54,15 @@
                  "RealtimeAudioWorkletThread() - NORMAL");
   }
 
-  if (++s_ref_count_ == 1) {
+  if (++ref_count == 1) {
     EnsureSharedBackingThread(params);
   }
 }
 
 RealtimeAudioWorkletThread::~RealtimeAudioWorkletThread() {
   DCHECK(IsMainThread());
-  if (--s_ref_count_ == 0) {
+  DCHECK_GT(ref_count, 0);
+  if (--ref_count == 0) {
     ClearSharedBackingThread();
   }
 }
@@ -59,15 +72,9 @@
       ->GetThread();
 }
 
-void RealtimeAudioWorkletThread::EnsureSharedBackingThread(
-    const ThreadCreationParams& params) {
-  DCHECK(IsMainThread());
-  WorkletThreadHolder<RealtimeAudioWorkletThread>::EnsureInstance(params);
-}
-
 void RealtimeAudioWorkletThread::ClearSharedBackingThread() {
   DCHECK(IsMainThread());
-  CHECK_EQ(s_ref_count_, 0);
+  CHECK_EQ(ref_count, 0);
   WorkletThreadHolder<RealtimeAudioWorkletThread>::ClearInstance();
 }
 
diff --git a/third_party/blink/renderer/modules/webaudio/realtime_audio_worklet_thread.h b/third_party/blink/renderer/modules/webaudio/realtime_audio_worklet_thread.h
index 5bd324c..9fbe4f8 100644
--- a/third_party/blink/renderer/modules/webaudio/realtime_audio_worklet_thread.h
+++ b/third_party/blink/renderer/modules/webaudio/realtime_audio_worklet_thread.h
@@ -12,7 +12,6 @@
 namespace blink {
 
 class WorkerReportingProxy;
-struct ThreadCreationParams;
 
 // RealtimeAudioWorkletThread is a per-AudioWorkletGlobalScope object that has
 // a reference count to the backing thread that performs AudioWorklet tasks.
@@ -26,7 +25,6 @@
   WorkerBackingThread& GetWorkerBackingThread() final;
   void ClearWorkerBackingThread() final {}
 
-  static void EnsureSharedBackingThread(const ThreadCreationParams&);
   static void ClearSharedBackingThread();
 
  private:
@@ -36,10 +34,6 @@
   ThreadType GetThreadType() const final {
     return ThreadType::kRealtimeAudioWorkletThread;
   }
-
-  // Use for ref-counting of all RealtimeAudioWorkletThread instances in a
-  // process. Incremented by the constructor and decremented by destructor.
-  static int s_ref_count_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/semi_realtime_audio_worklet_thread.cc b/third_party/blink/renderer/modules/webaudio/semi_realtime_audio_worklet_thread.cc
index 9f9fb8e7..3210de3 100644
--- a/third_party/blink/renderer/modules/webaudio/semi_realtime_audio_worklet_thread.cc
+++ b/third_party/blink/renderer/modules/webaudio/semi_realtime_audio_worklet_thread.cc
@@ -12,9 +12,21 @@
 
 namespace blink {
 
-template class WorkletThreadHolder<SemiRealtimeAudioWorkletThread>;
+namespace {
 
-int SemiRealtimeAudioWorkletThread::s_ref_count_ = 0;
+// Use for ref-counting of all SemiRealtimeAudioWorkletThread instances in a
+// process. Incremented by the constructor and decremented by destructor.
+static int ref_count = 0;
+
+static void EnsureSharedBackingThread(const ThreadCreationParams& params) {
+  DCHECK(IsMainThread());
+  DCHECK_EQ(ref_count, 1);
+  WorkletThreadHolder<SemiRealtimeAudioWorkletThread>::EnsureInstance(params);
+}
+
+}  // namespace
+
+template class WorkletThreadHolder<SemiRealtimeAudioWorkletThread>;
 
 SemiRealtimeAudioWorkletThread::SemiRealtimeAudioWorkletThread(
     WorkerReportingProxy& worker_reporting_proxy)
@@ -37,14 +49,15 @@
     params.thread_priority = base::ThreadPriority::NORMAL;
   }
 
-  if (++s_ref_count_ == 1) {
+  if (++ref_count == 1) {
     EnsureSharedBackingThread(params);
   }
 }
 
 SemiRealtimeAudioWorkletThread::~SemiRealtimeAudioWorkletThread() {
   DCHECK(IsMainThread());
-  if (--s_ref_count_ == 0) {
+  DCHECK_GT(ref_count, 0);
+  if (--ref_count == 0) {
     ClearSharedBackingThread();
   }
 }
@@ -54,15 +67,9 @@
       ->GetThread();
 }
 
-void SemiRealtimeAudioWorkletThread::EnsureSharedBackingThread(
-    const ThreadCreationParams& params) {
-  DCHECK(IsMainThread());
-  WorkletThreadHolder<SemiRealtimeAudioWorkletThread>::EnsureInstance(params);
-}
-
 void SemiRealtimeAudioWorkletThread::ClearSharedBackingThread() {
   DCHECK(IsMainThread());
-  CHECK_EQ(s_ref_count_, 0);
+  CHECK_EQ(ref_count, 0);
   WorkletThreadHolder<SemiRealtimeAudioWorkletThread>::ClearInstance();
 }
 
diff --git a/third_party/blink/renderer/modules/webaudio/semi_realtime_audio_worklet_thread.h b/third_party/blink/renderer/modules/webaudio/semi_realtime_audio_worklet_thread.h
index 937529c0..e58c941 100644
--- a/third_party/blink/renderer/modules/webaudio/semi_realtime_audio_worklet_thread.h
+++ b/third_party/blink/renderer/modules/webaudio/semi_realtime_audio_worklet_thread.h
@@ -12,7 +12,6 @@
 namespace blink {
 
 class WorkerReportingProxy;
-struct ThreadCreationParams;
 
 // SemiRealtimeAudioWorkletThread is a per-AudioWorkletGlobalScope object that
 // has a reference count to the backing thread that performs AudioWorklet tasks.
@@ -26,7 +25,6 @@
   WorkerBackingThread& GetWorkerBackingThread() final;
   void ClearWorkerBackingThread() final {}
 
-  static void EnsureSharedBackingThread(const ThreadCreationParams&);
   static void ClearSharedBackingThread();
 
  private:
@@ -36,10 +34,6 @@
   ThreadType GetThreadType() const final {
     return ThreadType::kSemiRealtimeAudioWorkletThread;
   }
-
-  // Use for ref-counting of all SemiRealtimeAudioWorkletThread instances in a
-  // process. Incremented by the constructor and decremented by destructor.
-  static int s_ref_count_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index ec63c3a..6cf77786 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -2387,11 +2387,17 @@
 
   sources = [ "testing/run_all_tests.cc" ]
 
-  if (is_linux || is_chromeos) {
+  if (is_linux || is_chromeos || is_fuchsia) {
     deps += [
       "//third_party/blink/renderer/platform/scheduler:scheduler_fuzzer_tests",
     ]
   }
+
+  if (is_fuchsia) {
+    use_cfv2 = false
+    additional_manifest_fragments =
+        [ "//build/config/fuchsia/test/jit_capabilities.test-cmx" ]
+  }
 }
 
 # This source set is used for fuzzers that need an environment similar to unit
diff --git a/third_party/blink/renderer/platform/scheduler/BUILD.gn b/third_party/blink/renderer/platform/scheduler/BUILD.gn
index f0d2cb9..b7bab09 100644
--- a/third_party/blink/renderer/platform/scheduler/BUILD.gn
+++ b/third_party/blink/renderer/platform/scheduler/BUILD.gn
@@ -277,7 +277,7 @@
     "//third_party/blink/renderer/platform/scheduler:test_support",
   ]
 
-  if (is_linux || is_chromeos) {
+  if (is_linux || is_chromeos || is_fuchsia) {
     sources += [
       "test/fuzzer/sequence_manager_fuzzer_processor.cc",
       "test/fuzzer/sequence_manager_fuzzer_processor.h",
diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc
index 43c83f8e..ddaf980b 100644
--- a/third_party/blink/renderer/platform/widget/widget_base.cc
+++ b/third_party/blink/renderer/platform/widget/widget_base.cc
@@ -629,7 +629,10 @@
                      std::move(render_frame_metadata_observer_remote),
                      std::move(render_frame_metadata_observer),
                      std::move(params), std::move(callback));
-  if (base::FeatureList::IsEnabled(features::kEstablishGpuChannelAsync)) {
+  bool needs_sync_composite_for_test =
+      layer_tree_view_ && LayerTreeHost()->in_composite_for_test();
+  if (base::FeatureList::IsEnabled(features::kEstablishGpuChannelAsync) &&
+      !needs_sync_composite_for_test) {
     Platform::Current()->EstablishGpuChannel(std::move(finish_callback));
   } else {
     scoped_refptr<gpu::GpuChannelHost> gpu_channel_host =
diff --git a/third_party/blink/renderer/platform/wtf/BUILD.gn b/third_party/blink/renderer/platform/wtf/BUILD.gn
index 850ee670..af1069c 100644
--- a/third_party/blink/renderer/platform/wtf/BUILD.gn
+++ b/third_party/blink/renderer/platform/wtf/BUILD.gn
@@ -290,6 +290,7 @@
     "assertions_test.cc",
     "atomic_operations_test.cc",
     "bit_field_test.cc",
+    "bloom_filter_test.cc",
     "cross_thread_functional_test.cc",
     "decimal_test.cc",
     "deque_test.cc",
diff --git a/third_party/blink/renderer/platform/wtf/bloom_filter.h b/third_party/blink/renderer/platform/wtf/bloom_filter.h
index 9ca5cc63..65af9f7c 100644
--- a/third_party/blink/renderer/platform/wtf/bloom_filter.h
+++ b/third_party/blink/renderer/platform/wtf/bloom_filter.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,12 +31,95 @@
 
 namespace WTF {
 
+// Bloom filter with k=2. Uses 2^keyBits/8 bytes of memory.
+// False positive rate is approximately (1-e^(-2n/m))^2, where n is the number
+// of unique  keys and m is the table size (==2^keyBits).
+template <unsigned keyBits>
+class BloomFilter {
+  USING_FAST_MALLOC(BloomFilter);
+
+ public:
+  BloomFilter() { Clear(); }
+
+  void Add(unsigned hash);
+
+  // The filter may give false positives (claim it may contain a key it doesn't)
+  // but never false negatives (claim it doesn't contain a key it does).
+  bool MayContain(unsigned hash) const;
+
+  // The filter must be cleared before reuse.
+  void Clear();
+
+ private:
+  using BitArrayUnit = unsigned;
+  static constexpr size_t kMaxKeyBits = 16;
+  static constexpr size_t kTableSize = 1 << keyBits;
+  static constexpr size_t kBitsPerPosition = 8 * sizeof(BitArrayUnit);
+  static constexpr size_t kBitArraySize = kTableSize / kBitsPerPosition;
+  static constexpr size_t kBitArrayMemorySize =
+      kBitArraySize * sizeof(BitArrayUnit);
+  static constexpr unsigned kKeyMask = (1 << keyBits) - 1;
+
+  static size_t BitArrayIndex(unsigned key);
+  static unsigned BitMask(unsigned key);
+
+  bool IsBitSet(unsigned key) const;
+  void SetBit(unsigned key);
+
+  BitArrayUnit bit_array_[kBitArraySize];
+
+  static_assert(keyBits <= kMaxKeyBits, "bloom filter key size check");
+
+  friend class BloomFilterTest;
+};
+
+template <unsigned keyBits>
+inline bool BloomFilter<keyBits>::MayContain(unsigned hash) const {
+  // The top and bottom bits of the incoming hash are treated as independent
+  // bloom filter hash functions. This works well as long as the filter size
+  // is not much above 2^kMaxKeyBits
+  return IsBitSet(hash) && IsBitSet(hash >> kMaxKeyBits);
+}
+
+template <unsigned keyBits>
+inline void BloomFilter<keyBits>::Add(unsigned hash) {
+  SetBit(hash);
+  SetBit(hash >> kMaxKeyBits);
+}
+
+template <unsigned keyBits>
+inline void BloomFilter<keyBits>::Clear() {
+  memset(bit_array_, 0, kBitArrayMemorySize);
+}
+
+template <unsigned keyBits>
+inline size_t BloomFilter<keyBits>::BitArrayIndex(unsigned key) {
+  return (key & kKeyMask) / kBitsPerPosition;
+}
+
+template <unsigned keyBits>
+inline unsigned BloomFilter<keyBits>::BitMask(unsigned key) {
+  return 1 << (key % kBitsPerPosition);
+}
+
+template <unsigned keyBits>
+bool BloomFilter<keyBits>::IsBitSet(unsigned key) const {
+  DCHECK_LT(BitArrayIndex(key), kBitArraySize);
+  return bit_array_[BitArrayIndex(key)] & BitMask(key);
+}
+
+template <unsigned keyBits>
+void BloomFilter<keyBits>::SetBit(unsigned key) {
+  DCHECK_LT(BitArrayIndex(key), kBitArraySize);
+  bit_array_[BitArrayIndex(key)] |= BitMask(key);
+}
+
 // Counting bloom filter with k=2 and 8 bit counters. Uses 2^keyBits bytes of
 // memory.  False positive rate is approximately (1-e^(-2n/m))^2, where n is
 // the number of unique keys and m is the table size (==2^keyBits).
 template <unsigned keyBits>
-class BloomFilter {
-  USING_FAST_MALLOC(BloomFilter);
+class CountingBloomFilter {
+  USING_FAST_MALLOC(CountingBloomFilter);
 
  public:
   static_assert(keyBits <= 16, "bloom filter key size check");
@@ -45,7 +128,7 @@
   static const unsigned kKeyMask = (1 << keyBits) - 1;
   static uint8_t MaximumCount() { return std::numeric_limits<uint8_t>::max(); }
 
-  BloomFilter() { Clear(); }
+  CountingBloomFilter() { Clear(); }
 
   void Add(unsigned hash);
   void Remove(unsigned hash);
@@ -80,7 +163,7 @@
 };
 
 template <unsigned keyBits>
-inline void BloomFilter<keyBits>::Add(unsigned hash) {
+inline void CountingBloomFilter<keyBits>::Add(unsigned hash) {
   uint8_t& first = FirstSlot(hash);
   uint8_t& second = SecondSlot(hash);
   if (LIKELY(first < MaximumCount()))
@@ -90,7 +173,7 @@
 }
 
 template <unsigned keyBits>
-inline void BloomFilter<keyBits>::Remove(unsigned hash) {
+inline void CountingBloomFilter<keyBits>::Remove(unsigned hash) {
   uint8_t& first = FirstSlot(hash);
   uint8_t& second = SecondSlot(hash);
   DCHECK(first);
@@ -103,13 +186,13 @@
 }
 
 template <unsigned keyBits>
-inline void BloomFilter<keyBits>::Clear() {
+inline void CountingBloomFilter<keyBits>::Clear() {
   memset(table_, 0, kTableSize);
 }
 
 #if DCHECK_IS_ON()
 template <unsigned keyBits>
-bool BloomFilter<keyBits>::LikelyEmpty() const {
+bool CountingBloomFilter<keyBits>::LikelyEmpty() const {
   for (size_t n = 0; n < kTableSize; ++n) {
     if (table_[n] && table_[n] != MaximumCount())
       return false;
@@ -118,7 +201,7 @@
 }
 
 template <unsigned keyBits>
-bool BloomFilter<keyBits>::IsClear() const {
+bool CountingBloomFilter<keyBits>::IsClear() const {
   for (size_t n = 0; n < kTableSize; ++n) {
     if (table_[n])
       return false;
@@ -129,6 +212,6 @@
 
 }  // namespace WTF
 
-using WTF::BloomFilter;
+using WTF::CountingBloomFilter;
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BLOOM_FILTER_H_
diff --git a/third_party/blink/renderer/platform/wtf/bloom_filter_test.cc b/third_party/blink/renderer/platform/wtf/bloom_filter_test.cc
new file mode 100644
index 0000000..24905288
--- /dev/null
+++ b/third_party/blink/renderer/platform/wtf/bloom_filter_test.cc
@@ -0,0 +1,111 @@
+// 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/renderer/platform/wtf/bloom_filter.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace WTF {
+
+class BloomFilterTest : public ::testing::Test {
+ protected:
+  template <unsigned keyBits>
+  size_t BloomFilterBitArrayIndex(unsigned key) {
+    return BloomFilter<keyBits>::BitArrayIndex(key);
+  }
+
+  template <unsigned keyBits>
+  unsigned BloomFilterBitMask(unsigned key) {
+    return BloomFilter<keyBits>::BitMask(key);
+  }
+
+  template <unsigned keyBits>
+  void TestBloomFilterKeyBoundary() {
+    BloomFilter<keyBits> filter;
+
+    filter.Add(0);
+    EXPECT_TRUE(filter.MayContain(0));
+    const unsigned max_key_bits = BloomFilter<keyBits>::kMaxKeyBits;
+    static_assert(max_key_bits + keyBits <= sizeof(unsigned) * 8);
+    for (unsigned i = max_key_bits; i < max_key_bits + keyBits; i++) {
+      unsigned hash = 1u << i;
+      EXPECT_FALSE(filter.MayContain(hash)) << String::Format(
+          "BloomFilter<%d>.Add(0) Must not contain 0x%08x", keyBits, hash);
+    }
+  }
+};
+
+TEST_F(BloomFilterTest, NonCountingBloomFilterBitArrayIndexTest) {
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0x00000000), 0u);
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0x0000001f), 0u);
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0xfffff000), 0u);
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0xfffff01f), 0u);
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0x00000020), 1u);
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0x0000003f), 1u);
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0xfffff020), 1u);
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0xfffff03f), 1u);
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0x00000800), 64u);
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0x0000081f), 64u);
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0xfffff800), 64u);
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0xfffff81f), 64u);
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0x00000ff8), 127u);
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0x00000fff), 127u);
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0xfffffff8), 127u);
+  EXPECT_EQ(BloomFilterBitArrayIndex<12>(0xffffffff), 127u);
+}
+
+TEST_F(BloomFilterTest, NonCountingBloomFilterBitMaskTest) {
+  EXPECT_EQ(BloomFilterBitMask<12>(0x00000000), 0x00000001u);
+  EXPECT_EQ(BloomFilterBitMask<12>(0xffffffc0), 0x00000001u);
+  EXPECT_EQ(BloomFilterBitMask<12>(0x00000001), 0x00000002u);
+  EXPECT_EQ(BloomFilterBitMask<12>(0xffffffc1), 0x00000002u);
+  EXPECT_EQ(BloomFilterBitMask<12>(0x0000000f), 0x00008000u);
+  EXPECT_EQ(BloomFilterBitMask<12>(0xffffff0f), 0x00008000u);
+  EXPECT_EQ(BloomFilterBitMask<12>(0x0000003e), 0x40000000u);
+  EXPECT_EQ(BloomFilterBitMask<12>(0xfffffffe), 0x40000000u);
+  EXPECT_EQ(BloomFilterBitMask<12>(0x0000003f), 0x80000000u);
+  EXPECT_EQ(BloomFilterBitMask<12>(0xffffffff), 0x80000000u);
+}
+
+TEST_F(BloomFilterTest, NonCountingBloomFilterKeyBoundary) {
+  TestBloomFilterKeyBoundary<12>();
+  TestBloomFilterKeyBoundary<13>();
+  TestBloomFilterKeyBoundary<14>();
+  TestBloomFilterKeyBoundary<15>();
+  TestBloomFilterKeyBoundary<16>();
+}
+
+TEST_F(BloomFilterTest, NonCountingBloomFilterBasic) {
+  unsigned alfa = AtomicString("Alfa").Impl()->ExistingHash();
+  unsigned bravo = AtomicString("Bravo").Impl()->ExistingHash();
+  unsigned charlie = AtomicString("Charlie").Impl()->ExistingHash();
+
+  BloomFilter<12> filter;
+  EXPECT_FALSE(filter.MayContain(alfa));
+  EXPECT_FALSE(filter.MayContain(bravo));
+  EXPECT_FALSE(filter.MayContain(charlie));
+
+  filter.Add(alfa);
+  EXPECT_TRUE(filter.MayContain(alfa));
+  EXPECT_FALSE(filter.MayContain(bravo));
+  EXPECT_FALSE(filter.MayContain(charlie));
+
+  filter.Add(bravo);
+  EXPECT_TRUE(filter.MayContain(alfa));
+  EXPECT_TRUE(filter.MayContain(bravo));
+  EXPECT_FALSE(filter.MayContain(charlie));
+
+  filter.Add(charlie);
+  EXPECT_TRUE(filter.MayContain(alfa));
+  EXPECT_TRUE(filter.MayContain(bravo));
+  EXPECT_TRUE(filter.MayContain(charlie));
+
+  filter.Clear();
+  EXPECT_FALSE(filter.MayContain(alfa));
+  EXPECT_FALSE(filter.MayContain(bravo));
+  EXPECT_FALSE(filter.MayContain(charlie));
+}
+
+}  // namespace WTF
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index ec37388..9071b779 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -7731,7 +7731,6 @@
 
 # Sheriff 2022-04-26
 crbug.com/1320120 [ Mac10.13 ] fast/harness/perftests/runs-per-second-log.html [ Failure Pass Timeout ]
-crbug.com/1320121 [ Mac10.13 ] http/tests/inspector-protocol/network/blocked-setcookie-same-party-cross-party.js [ Failure Pass Timeout ]
 crbug.com/1320140 [ Win ] virtual/fenced-frame-mparch/wpt_internal/fenced_frame/disallowed-navigations.https.html [ Pass Timeout ]
 crbug.com/1320140 [ Win ] virtual/fenced-frame-mparch/wpt_internal/fenced_frame/opaque-ad-sizes.https.html [ Pass Timeout ]
 crbug.com/1320140 [ Win ] virtual/fenced-frame-shadow-dom/wpt_internal/fenced_frame/disallowed-navigations.https.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 775a9294..ff597d9 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -1191,7 +1191,8 @@
       "external/wpt/css/css-highlight-api",
       "paint/markers/inline_spelling_markers.html",
       "paint/markers/inline-spelling-markers-hidpi.html",
-      "paint/markers/inline-spelling-markers-hidpi-composited.html"
+      "paint/markers/inline-spelling-markers-hidpi-composited.html",
+      "paint/invalidation/selection/selection-after-remove.html"
     ],
     "args": ["--enable-blink-features=HighlightOverlayPainting"]
   },
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/resources/battery-status.https.html b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/resources/battery-status.https.html
similarity index 100%
rename from third_party/blink/web_tests/wpt_internal/prerender/resources/battery-status.https.html
rename to third_party/blink/web_tests/external/wpt/speculation-rules/prerender/resources/battery-status.https.html
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/restriction-battery-status.https.html b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-battery-status.https.html
similarity index 96%
rename from third_party/blink/web_tests/wpt_internal/prerender/restriction-battery-status.https.html
rename to third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-battery-status.https.html
index ac69fd91..80e25b0 100644
--- a/third_party/blink/web_tests/wpt_internal/prerender/restriction-battery-status.https.html
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-battery-status.https.html
@@ -8,6 +8,8 @@
 <body>
 <script>
 
+setup(() => assertSpeculationRulesIsSupported());
+
 promise_test(async t => {
   const uid = token();
   const bc = new PrerenderChannel('test-channel', uid);
diff --git a/third_party/blink/web_tests/loader/document-updated-by-xslt-expected.txt b/third_party/blink/web_tests/loader/document-updated-by-xslt-expected.txt
new file mode 100644
index 0000000..a0772fd
--- /dev/null
+++ b/third_party/blink/web_tests/loader/document-updated-by-xslt-expected.txt
@@ -0,0 +1 @@
+PASS if it does not crash in debug.
diff --git a/third_party/blink/web_tests/loader/document-updated-by-xslt.html b/third_party/blink/web_tests/loader/document-updated-by-xslt.html
new file mode 100644
index 0000000..977ac146
--- /dev/null
+++ b/third_party/blink/web_tests/loader/document-updated-by-xslt.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<meta charset="utf-8">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<p>PASS if it does not crash in debug.</p>
+<img src="resources/document-updated-by-xslt.svg">
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+</script>
diff --git a/third_party/blink/web_tests/loader/resources/document-updated-by-xslt.svg b/third_party/blink/web_tests/loader/resources/document-updated-by-xslt.svg
new file mode 100644
index 0000000..af48358
--- /dev/null
+++ b/third_party/blink/web_tests/loader/resources/document-updated-by-xslt.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="#stylesheet"?>
+<!DOCTYPE svg [
+<!ATTLIST xsl:stylesheet
+id ID #REQUIRED>
+]>
+<svg>
+    <xsl:stylesheet id="stylesheet" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:svg="http://www.w3.org/2000/svg"></xsl:stylesheet>
+</svg>
\ No newline at end of file
diff --git a/third_party/zlib/slide_hash_simd.h b/third_party/zlib/slide_hash_simd.h
index 3b2e463..6f715bc 100644
--- a/third_party/zlib/slide_hash_simd.h
+++ b/third_party/zlib/slide_hash_simd.h
@@ -78,7 +78,8 @@
     Assert(sizeof(Pos) == 2, "Pos type size error: should be 2 bytes");
     Assert(sizeof(ush) == 2, "ush type size error: should be 2 bytes");
 
-    Assert(hash_size == (ush)hash_size, "Hash table size error");
+    Assert(hash_size <= (1 << 16), "Hash table maximum size error");
+    Assert(hash_size >= (1 << 8), "Hash table minimum size error");
     Assert(w_size == (ush)w_size, "Prev table size error");
 
     /*
diff --git a/ui/base/wayland/BUILD.gn b/ui/base/wayland/BUILD.gn
index b2d3f8c..c7763d1 100644
--- a/ui/base/wayland/BUILD.gn
+++ b/ui/base/wayland/BUILD.gn
@@ -25,9 +25,9 @@
   ]
 
   public_deps = [
+    "//third_party/wayland:wayland_client",
     "//third_party/wayland-protocols:text_input_extension_protocol",
     "//third_party/wayland-protocols:text_input_protocol",
-    "//third_party/wayland:wayland_client",
     "//ui/base/ime:text_input_types",
   ]
 
@@ -45,14 +45,25 @@
 
   public_deps = [
     "//third_party/abseil-cpp:absl",
+    "//third_party/wayland:wayland_server",
     "//third_party/wayland-protocols:text_input_extension_protocol",
     "//third_party/wayland-protocols:text_input_protocol",
-    "//third_party/wayland:wayland_server",
     "//ui/base/ime:text_input_types",
   ]
 
-  deps = [
-    ":wayland_input_types_impl",
+  deps = [ ":wayland_input_types_impl" ]
+}
+
+source_set("color_manager_util") {
+  sources = [
+    "color_manager_util.cc",
+    "color_manager_util.h",
+  ]
+  public_deps = [
+    "//base",
+    "//components/exo/wayland/protocol:chrome_color_management_protocol",
+    "//third_party/wayland:wayland_server",
+    "//ui/gfx:color_space",
   ]
 }
 
diff --git a/ui/base/wayland/color_manager_util.cc b/ui/base/wayland/color_manager_util.cc
new file mode 100644
index 0000000..ad9ac98
--- /dev/null
+++ b/ui/base/wayland/color_manager_util.cc
@@ -0,0 +1,27 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/wayland/color_manager_util.h"
+
+namespace ui::wayland {
+
+zcr_color_manager_v1_chromaticity_names ToColorManagerChromaticity(
+    gfx::ColorSpace::PrimaryID primaryID) {
+  for (const auto& it : kChromaticityMap) {
+    if (it.second == primaryID)
+      return it.first;
+  }
+  return ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_UNKNOWN;
+}
+
+zcr_color_manager_v1_eotf_names ToColorManagerEOTF(
+    gfx::ColorSpace::TransferID transferID) {
+  for (const auto& it : kEotfMap) {
+    if (it.second == transferID)
+      return it.first;
+  }
+  return ZCR_COLOR_MANAGER_V1_EOTF_NAMES_UNKNOWN;
+}
+
+}  // namespace ui::wayland
diff --git a/ui/base/wayland/color_manager_util.h b/ui/base/wayland/color_manager_util.h
new file mode 100644
index 0000000..79c9839
--- /dev/null
+++ b/ui/base/wayland/color_manager_util.h
@@ -0,0 +1,66 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_WAYLAND_COLOR_MANAGER_UTIL_H_
+#define UI_BASE_WAYLAND_COLOR_MANAGER_UTIL_H_
+
+#include <chrome-color-management-server-protocol.h>
+
+#include "base/containers/fixed_flat_map.h"
+#include "ui/gfx/color_space.h"
+#include "ui/gfx/display_color_spaces.h"
+
+namespace ui::wayland {
+
+// A map from the zcr_color_manager_v1 chromaticity_names enum values
+// representing well-known chromaticities, to their equivalent PrimaryIDs.
+// See components/exo/wayland/protocol/chrome-color-management.xml
+constexpr auto kChromaticityMap =
+    base::MakeFixedFlatMap<zcr_color_manager_v1_chromaticity_names,
+                           gfx::ColorSpace::PrimaryID>(
+        {{ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_BT601_525_LINE,
+          gfx::ColorSpace::PrimaryID::SMPTE170M},
+         {ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_BT601_625_LINE,
+          gfx::ColorSpace::PrimaryID::BT470BG},
+         {ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_SMPTE170M,
+          gfx::ColorSpace::PrimaryID::SMPTE170M},
+         {ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_BT709,
+          gfx::ColorSpace::PrimaryID::BT709},
+         {ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_BT2020,
+          gfx::ColorSpace::PrimaryID::BT2020},
+         {ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_SRGB,
+          gfx::ColorSpace::PrimaryID::BT709},
+         {ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_DISPLAYP3,
+          gfx::ColorSpace::PrimaryID::P3},
+         {ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_ADOBERGB,
+          gfx::ColorSpace::PrimaryID::ADOBE_RGB}});
+
+// A map from the zcr_color_manager_v1 eotf_names enum values
+// representing well-known EOTFs, to their equivalent TransferIDs.
+// See components/exo/wayland/protocol/chrome-color-management.xml
+constexpr auto kEotfMap =
+    base::MakeFixedFlatMap<zcr_color_manager_v1_eotf_names,
+                           gfx::ColorSpace::TransferID>({
+        {ZCR_COLOR_MANAGER_V1_EOTF_NAMES_LINEAR,
+         gfx::ColorSpace::TransferID::LINEAR},
+        {ZCR_COLOR_MANAGER_V1_EOTF_NAMES_SRGB,
+         gfx::ColorSpace::TransferID::BT709},
+        {ZCR_COLOR_MANAGER_V1_EOTF_NAMES_BT2087,
+         gfx::ColorSpace::TransferID::GAMMA24},
+        {ZCR_COLOR_MANAGER_V1_EOTF_NAMES_ADOBERGB,
+         // This is ever so slightly inaccurate. The number ought to be
+         // 2.19921875f, not 2.2
+         gfx::ColorSpace::TransferID::GAMMA22},
+        {ZCR_COLOR_MANAGER_V1_EOTF_NAMES_PQ, gfx::ColorSpace::TransferID::PQ},
+    });
+
+zcr_color_manager_v1_chromaticity_names ToColorManagerChromaticity(
+    gfx::ColorSpace::PrimaryID primaryID);
+
+zcr_color_manager_v1_eotf_names ToColorManagerEOTF(
+    gfx::ColorSpace::TransferID transferID);
+
+}  // namespace ui::wayland
+
+#endif  // UI_BASE_WAYLAND_COLOR_MANAGER_UTIL_H_
\ No newline at end of file
diff --git a/ui/chromeos/translations/ui_chromeos_strings_gl.xtb b/ui/chromeos/translations/ui_chromeos_strings_gl.xtb
index 7f03b21..626cf61 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_gl.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_gl.xtb
@@ -562,7 +562,7 @@
 <translation id="5776325638577448643">Borrar e formatar</translation>
 <translation id="57838592816432529">Silenciar</translation>
 <translation id="5788127256798019331">Ficheiros de Play</translation>
-<translation id="5790193330357274855">Casaco</translation>
+<translation id="5790193330357274855">Kazako</translation>
 <translation id="5804245609861364054">Kannará (transliteración)</translation>
 <translation id="5814126672212206791">Tipo de conexión</translation>
 <translation id="5817397429773072584">Chinés tradicional</translation>
diff --git a/ui/strings/translations/ui_strings_hy.xtb b/ui/strings/translations/ui_strings_hy.xtb
index 6fef820a..da0ccfe 100644
--- a/ui/strings/translations/ui_strings_hy.xtb
+++ b/ui/strings/translations/ui_strings_hy.xtb
@@ -118,7 +118,7 @@
 <translation id="5278860589123563674">Չհաջողվեց ուղարկել</translation>
 <translation id="528468243742722775">Վերջ</translation>
 <translation id="5329858601952122676">&amp;Ջնջել</translation>
-<translation id="5463830097259460683">Զմայլիկներ և նշաններ</translation>
+<translation id="5463830097259460683">Էմոջիներ և նշաններ</translation>
 <translation id="5528053674512161860">Չհաջողվեց բեռնել էջը, քանի որ ծրագրավորողի միջերեսի մոդուլը (dev_ui) տեղադրված չէ</translation>
 <translation id="5574202486608032840"><ph name="IDS_SHORT_PRODUCT_OS_NAME" /> համակարգ</translation>
 <translation id="5583640892426849032">Backspace</translation>
@@ -172,7 +172,7 @@
 <translation id="7410957453383678442">{MINUTES,plural, =1{Մնացել է 1 րոպե}one{Մնացել է # րոպե}other{Մնացել է # րոպե}}</translation>
 <translation id="7437971918971306061">«<ph name="COLUMN_NAME" />» սյունակի արժեքները դասավորված չեն։</translation>
 <translation id="7460907917090416791"><ph name="QUANTITY" /> ՏԲ</translation>
-<translation id="7507604095951736240">Զմայլիկներ</translation>
+<translation id="7507604095951736240">Էմոջիներ</translation>
 <translation id="7620655452534002301">Հեռացվեց։</translation>
 <translation id="7658239707568436148">Չեղարկել</translation>
 <translation id="7781829728241885113">Երեկ</translation>
diff --git a/ui/views/controls/webview/webview_unittest.cc b/ui/views/controls/webview/webview_unittest.cc
index 60b4ee89..8779f4e 100644
--- a/ui/views/controls/webview/webview_unittest.cc
+++ b/ui/views/controls/webview/webview_unittest.cc
@@ -16,6 +16,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/content_client.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/mock_render_process_host.h"
@@ -271,14 +272,16 @@
   web_view()->SetWebContents(web_contents1.get());
   // Layout() is normally async, call it now to ensure visibility is updated.
   web_view()->Layout();
-#if defined(USE_AURA)
-  EXPECT_EQ(1, observer1.shown_count());
-#else
+  int expected_shown_count = 1;
+#if defined(USE_MAC)
   // On Mac, setting the web contents adds a WebContentsViewCocoa
-  // to the view hierarchy. The window change (from nil to non-nil)
-  // generates one more web contents visibility update that Aura.
-  EXPECT_EQ(2, observer1.shown_count());
+  // to the view hierarchy. When enhanced occlusion checking is enabled, the
+  // window change (from nil to non-nil) generates one more web contents
+  // visibility update that Aura.
+  if (base::FeatureList::IsEnabled(features::kMacWebContentsOcclusion))
+    expected_shown_count++;
 #endif
+  EXPECT_EQ(expected_shown_count, observer1.shown_count());
 
   // Nothing else should change.
   EXPECT_EQ(1, observer1.hidden_count());