diff --git a/AUTHORS b/AUTHORS
index fdd5171..b81d16f 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -22,6 +22,7 @@
 Abhishek Agarwal <abhishek.a21@samsung.com>
 Abhishek Kanike <abhishek.ka@samsung.com>
 Abhishek Singh <abhi.rathore@samsung.com>
+Abin K Paul <abin.paul1@gmail.com>
 Abul Hasan Md Osama <ahm.osama@samsung.com>
 Adam Bonner <abonner-chromium@solscope.com>
 Adam Bujalski <abujalski@gmail.com>
diff --git a/DEPS b/DEPS
index a29d440..3e07427 100644
--- a/DEPS
+++ b/DEPS
@@ -280,7 +280,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': '022cad13a17ab6186c74a7f2bc4c8ada1393a38a',
+  'skia_revision': '83c4cebc1e8fb4e138eb51745351349ca7cf0b07',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -288,7 +288,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': '86c735bfe65063bd5fc319809ea3ddb939d65319',
+  'angle_revision': '4a5c1e1f2df58b4274f727b4db4fdac69be59ffa',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -331,7 +331,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': 'bec4ef415ef07ad1fa9542978136d9863dd7a6d0',
+  'freetype_revision': '31b14fd4dce4b017090f5ba7c15a178fa0ce6d7d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
@@ -359,7 +359,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': 'ce905398178adc4abec56263ae656cf78d0f57f3',
+  'devtools_frontend_revision': 'c5f659d6b6a8e6bc81362b3f7bc9bd3ba641b53e',
   # 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.
@@ -395,7 +395,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': 'bd512acad8c9d29e942ff5df0c13024458b09249',
+  'dawn_revision': 'b9ab0240030d48ec8ec407128b587bb08b39ea49',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -929,7 +929,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'LQ9vdgkVWAv1399Rmm15OrPsglaFUcAF8fkDjzH06o4C',
+          'version': 'g9HIhocBsCFlSh1b6fzvSBJB8WIKPqyWsauldtRS4DIC',
       },
     ],
     'condition': 'checkout_android',
@@ -1734,7 +1734,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '1f5f875f89f8af99653b8e5fae1007115747397e',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'f82e8fa911ab3547885f8070b9a951197967c94d',
+    Var('webrtc_git') + '/src.git' + '@' + '63299a3124dd6cd37e887ee274fec3716bb0d27b',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1807,7 +1807,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@96b1e592ed122b4c44eaa581d0a412f8a7968cba',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@7415ea2aeaa5f22e77641dc56ae27970ece20a03',
     'condition': 'checkout_src_internal',
   },
 
@@ -1859,7 +1859,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'C_W-d-5MCa4aXPlaRI94F399ZFFKha1JNPSQOh3p-IAC',
+        'version': 'ibaUZbDASq1aAbCwXLDC2A8PA8eUzHmxBaItUFBLKLoC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/WATCHLISTS b/WATCHLISTS
index 3c953c6..36e6b43 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1781,8 +1781,7 @@
     'smb': {
       'filepath': 'chrome/browser/ash/file_system_provider' \
                   '|chrome/browser/ash/smb_client'\
-                  '|chromeos/dbus/fake_smb_provider_client'\
-                  '|chromeos/dbus/smb_provider_client',
+                  '|chromeos/ash/components/dbus/smb_provider_client',
     },
     'source_idls': {
       'filepath': 'third_party/blink/renderer/(core|modules|platform)/.*\.idl',
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index c9e8e5f..248489a 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -2229,6 +2229,8 @@
     "//chromeos/ash/components/assistant:buildflags",
     "//chromeos/ash/components/dbus/audio",
     "//chromeos/ash/components/dbus/hammerd",
+    "//chromeos/ash/components/dbus/human_presence",
+    "//chromeos/ash/components/dbus/human_presence:hps_proto",
     "//chromeos/ash/components/dbus/rgbkbd",
     "//chromeos/ash/components/dbus/rmad",
     "//chromeos/ash/components/dbus/rmad:rmad_proto",
@@ -2248,8 +2250,6 @@
     "//chromeos/dbus",
     "//chromeos/dbus/constants",
     "//chromeos/dbus/hermes",
-    "//chromeos/dbus/human_presence",
-    "//chromeos/dbus/human_presence:hps_proto",
     "//chromeos/dbus/init",
     "//chromeos/dbus/power",
     "//chromeos/dbus/power:power_manager_proto",
@@ -3033,6 +3033,8 @@
     "//chromeos/ash/components/assistant:buildflags",
     "//chromeos/ash/components/dbus/audio",
     "//chromeos/ash/components/dbus/hammerd",
+    "//chromeos/ash/components/dbus/human_presence",
+    "//chromeos/ash/components/dbus/human_presence:hps_proto",
     "//chromeos/ash/components/dbus/rgbkbd",
     "//chromeos/ash/components/dbus/services:test_support",
     "//chromeos/ash/components/dbus/userdataauth",
@@ -3049,8 +3051,6 @@
     "//chromeos/crosapi/cpp",
     "//chromeos/dbus:test_support",
     "//chromeos/dbus/hermes",
-    "//chromeos/dbus/human_presence",
-    "//chromeos/dbus/human_presence:hps_proto",
     "//chromeos/dbus/power",
     "//chromeos/dbus/power:power_manager_proto",
     "//chromeos/services/bluetooth_config:test_support",
diff --git a/ash/components/login/auth/BUILD.gn b/ash/components/login/auth/BUILD.gn
index 73b5f17c..1b9a9b7 100644
--- a/ash/components/login/auth/BUILD.gn
+++ b/ash/components/login/auth/BUILD.gn
@@ -151,8 +151,10 @@
     "//chromeos/ash/components/dbus/userdataauth:test_support",
     "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
     "//chromeos/dbus/cryptohome",
+    "//components/account_id",
     "//components/prefs",
     "//components/prefs:test_support",
+    "//components/user_manager",
     "//net",
     "//net:test_support",
     "//testing/gmock",
diff --git a/ash/components/login/auth/auth_performer.cc b/ash/components/login/auth/auth_performer.cc
index 5415fc88..036b456 100644
--- a/ash/components/login/auth/auth_performer.cc
+++ b/ash/components/login/auth/auth_performer.cc
@@ -15,9 +15,20 @@
 #include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/cryptohome/key.pb.h"
 #include "components/device_event_log/device_event_log.h"
+#include "components/user_manager/user_type.h"
 
 namespace ash {
 
+namespace {
+
+bool IsKioskUserType(user_manager::UserType type) {
+  return type == user_manager::USER_TYPE_KIOSK_APP ||
+         type == user_manager::USER_TYPE_ARC_KIOSK_APP ||
+         type == user_manager::USER_TYPE_WEB_KIOSK_APP;
+}
+
+}  // namespace
+
 AuthPerformer::AuthPerformer(base::raw_ptr<UserDataAuthClient> client)
     : client_(client) {}
 
@@ -249,12 +260,17 @@
   // Remember key metadata
   std::vector<cryptohome::KeyDefinition> key_definitions;
   for (const auto& [label, key_data] : reply->key_label_data()) {
-    // Backfill kiosk key type
+    // Backfill key type
     // TODO(crbug.com/1310312): Find if there is any better way.
     cryptohome::KeyData data(key_data);
     if (!data.has_type()) {
-      LOGIN_LOG(DEBUG) << "Backfilling Kiosk key type for key " << label;
-      data.set_type(cryptohome::KeyData::KEY_TYPE_KIOSK);
+      if (IsKioskUserType(context->GetUserType())) {
+        LOGIN_LOG(DEBUG) << "Backfilling Kiosk key type for key " << label;
+        data.set_type(cryptohome::KeyData::KEY_TYPE_KIOSK);
+      } else {
+        LOGIN_LOG(DEBUG) << "Backfilling Password key type for key " << label;
+        data.set_type(cryptohome::KeyData::KEY_TYPE_PASSWORD);
+      }
     }
     // "legacy-0" keys exist as label in map, but might not exist as labels
     // in KeyData.
diff --git a/ash/components/login/auth/auth_performer_unittest.cc b/ash/components/login/auth/auth_performer_unittest.cc
index 70c9b91..54a2a43 100644
--- a/ash/components/login/auth/auth_performer_unittest.cc
+++ b/ash/components/login/auth/auth_performer_unittest.cc
@@ -19,6 +19,8 @@
 #include "chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h"
 #include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/cryptohome/UserDataAuth.pb.h"
+#include "components/account_id/account_id.h"
+#include "components/user_manager/user_type.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -66,7 +68,6 @@
     CryptohomeMiscClient::InitializeFake();
     chromeos::SystemSaltGetter::Initialize();
     context_ = std::make_unique<UserContext>();
-    context_->SetAuthSessionId("123");
   }
 
   ~AuthPerformerTest() override {
@@ -80,6 +81,69 @@
   std::unique_ptr<UserContext> context_;
 };
 
+// Checks that a key that has no type is recognized during StartAuthSession() as
+// a password knowledge key.
+TEST_F(AuthPerformerTest, StartWithUntypedPasswordKey) {
+  // Arrange: cryptohome replies with a key that has no |type| set.
+  EXPECT_CALL(mock_client_, StartAuthSession(_, _))
+      .WillOnce([](const ::user_data_auth::StartAuthSessionRequest& request,
+                   UserDataAuthClient::StartAuthSessionCallback callback) {
+        ::user_data_auth::StartAuthSessionReply reply;
+        reply.set_auth_session_id("123");
+        reply.set_user_exists(true);
+        (*reply.mutable_key_label_data())["legacy-0"] = cryptohome::KeyData();
+        std::move(callback).Run(reply);
+      });
+  AuthPerformer performer(&mock_client_);
+
+  // Act.
+  base::test::TestFuture<bool, std::unique_ptr<UserContext>,
+                         absl::optional<CryptohomeError>>
+      result;
+  performer.StartAuthSession(std::move(context_), /*ephemeral=*/false,
+                             result.GetCallback());
+  auto [user_exists, user_context, cryptohome_error] = result.Take();
+
+  // Assert: no error, user context has AuthSession ID and the password factor.
+  EXPECT_TRUE(user_exists);
+  ASSERT_TRUE(user_context);
+  EXPECT_EQ(user_context->GetAuthSessionId(), "123");
+  EXPECT_TRUE(user_context->GetAuthFactorsData().FindOnlinePasswordKey());
+}
+
+// Checks that a key that has no type is recognized during StartAuthSession() as
+// a kiosk key for a kiosk user.
+TEST_F(AuthPerformerTest, StartWithUntypedKioskKey) {
+  // Arrange: user is kiosk, and cryptohome replies with a key that has no
+  // |type| set.
+  context_ = std::make_unique<UserContext>(user_manager::USER_TYPE_KIOSK_APP,
+                                           AccountId());
+  EXPECT_CALL(mock_client_, StartAuthSession(_, _))
+      .WillOnce([](const ::user_data_auth::StartAuthSessionRequest& request,
+                   UserDataAuthClient::StartAuthSessionCallback callback) {
+        ::user_data_auth::StartAuthSessionReply reply;
+        reply.set_auth_session_id("123");
+        reply.set_user_exists(true);
+        (*reply.mutable_key_label_data())["legacy-0"] = cryptohome::KeyData();
+        std::move(callback).Run(reply);
+      });
+  AuthPerformer performer(&mock_client_);
+
+  // Act.
+  base::test::TestFuture<bool, std::unique_ptr<UserContext>,
+                         absl::optional<CryptohomeError>>
+      result;
+  performer.StartAuthSession(std::move(context_), /*ephemeral=*/false,
+                             result.GetCallback());
+  auto [user_exists, user_context, cryptohome_error] = result.Take();
+
+  // Assert: no error, user context has AuthSession ID and the kiosk factor.
+  EXPECT_TRUE(user_exists);
+  ASSERT_TRUE(user_context);
+  EXPECT_EQ(user_context->GetAuthSessionId(), "123");
+  EXPECT_TRUE(user_context->GetAuthFactorsData().FindKioskKey());
+}
+
 // Checks that AuthenticateUsingKnowledgeKey (which will be called with "gaia"
 // label after online authentication) correctly falls back to "legacy-0" label.
 TEST_F(AuthPerformerTest, KnowledgeKeyCorrectLabelFallback) {
@@ -87,6 +151,8 @@
   // Password knowledge key in user context.
   *context_->GetKey() = Key("secret");
   context_->GetKey()->SetLabel("gaia");
+  // Simulate the already started auth session.
+  context_->SetAuthSessionId("123");
 
   AuthPerformer performer(&mock_client_);
 
@@ -111,6 +177,8 @@
 // fallback to "legacy-0" label.
 TEST_F(AuthPerformerTest, KnowledgeKeyNoFallbackOnPin) {
   SetupUserWithLegacyPassword(context_.get());
+  // Simulate the already started auth session.
+  context_->SetAuthSessionId("123");
 
   // PIN knowledge key in user context.
   *context_->GetKey() =
@@ -140,6 +208,8 @@
 
 TEST_F(AuthPerformerTest, AuthenticateWithPasswordCorrectLabel) {
   SetupUserWithLegacyPassword(context_.get());
+  // Simulate the already started auth session.
+  context_->SetAuthSessionId("123");
 
   AuthPerformer performer(&mock_client_);
 
@@ -163,6 +233,8 @@
 
 TEST_F(AuthPerformerTest, AuthenticateWithPasswordBadLabel) {
   SetupUserWithLegacyPassword(context_.get());
+  // Simulate the already started auth session.
+  context_->SetAuthSessionId("123");
 
   AuthPerformer performer(&mock_client_);
 
diff --git a/ash/system/human_presence/lock_on_leave_controller.cc b/ash/system/human_presence/lock_on_leave_controller.cc
index abe90d6..1f00f81 100644
--- a/ash/system/human_presence/lock_on_leave_controller.cc
+++ b/ash/system/human_presence/lock_on_leave_controller.cc
@@ -6,8 +6,8 @@
 
 #include "ash/shell.h"
 #include "base/bind.h"
+#include "chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h"
 #include "chromeos/ash/components/human_presence/human_presence_configuration.h"
-#include "chromeos/dbus/human_presence/human_presence_dbus_client.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace ash {
@@ -17,21 +17,21 @@
 void EnableLockOnLeaveViaDBus() {
   const auto config = hps::GetEnableLockOnLeaveConfig();
   if (config.has_value()) {
-    chromeos::HumanPresenceDBusClient::Get()->EnableHpsSense(config.value());
+    HumanPresenceDBusClient::Get()->EnableHpsSense(config.value());
   }
 }
 
 // Helper for DisableHpsSense.
 void DisableLockOnLeaveViaDBus() {
-  chromeos::HumanPresenceDBusClient::Get()->DisableHpsSense();
+  HumanPresenceDBusClient::Get()->DisableHpsSense();
 }
 
 }  // namespace
 
 LockOnLeaveController::LockOnLeaveController() {
-  human_presence_observation_.Observe(chromeos::HumanPresenceDBusClient::Get());
+  human_presence_observation_.Observe(HumanPresenceDBusClient::Get());
 
-  chromeos::HumanPresenceDBusClient::Get()->WaitForServiceToBeAvailable(
+  HumanPresenceDBusClient::Get()->WaitForServiceToBeAvailable(
       base::BindOnce(&LockOnLeaveController::OnServiceAvailable,
                      weak_ptr_factory_.GetWeakPtr()));
 
diff --git a/ash/system/human_presence/lock_on_leave_controller.h b/ash/system/human_presence/lock_on_leave_controller.h
index 9515679d..3d26e362 100644
--- a/ash/system/human_presence/lock_on_leave_controller.h
+++ b/ash/system/human_presence/lock_on_leave_controller.h
@@ -9,17 +9,17 @@
 #include "ash/system/human_presence/human_presence_orientation_controller.h"
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
-#include "chromeos/dbus/hps/hps_service.pb.h"
-#include "chromeos/dbus/human_presence/human_presence_dbus_client.h"
+#include "chromeos/ash/components/dbus/hps/hps_service.pb.h"
+#include "chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h"
 
 namespace ash {
 
-// Helper class for chromeos::HumanPresenceDBusClient, responsible for
+// Helper class for HumanPresenceDBusClient, responsible for
 // enabling/disabling the DBus service via the client and is responsible for
 // maintaining state between restarts.
 class ASH_EXPORT LockOnLeaveController
     : public HumanPresenceOrientationController::Observer,
-      chromeos::HumanPresenceDBusClient::Observer {
+      HumanPresenceDBusClient::Observer {
  public:
   // The state of lock on leave inside DBus service that is configured. It is
   // set as kUnknown in this class on initialization. And is set to either
@@ -47,7 +47,7 @@
   // HumanPresenceOrientationObserver:
   void OnOrientationChanged(bool suitable_for_human_presence) override;
 
-  // chromeos::HumanPresenceDBusClient::Observer:
+  // HumanPresenceDBusClient::Observer:
   void OnHpsSenseChanged(const hps::HpsResultProto&) override;
   void OnHpsNotifyChanged(const hps::HpsResultProto&) override;
   // Re-enables LockOnLeave on human presence service restart if it was enabled
@@ -77,8 +77,8 @@
   ConfiguredLockOnLeaveState configured_state_ =
       ConfiguredLockOnLeaveState::kUnknown;
 
-  base::ScopedObservation<chromeos::HumanPresenceDBusClient,
-                          chromeos::HumanPresenceDBusClient::Observer>
+  base::ScopedObservation<HumanPresenceDBusClient,
+                          HumanPresenceDBusClient::Observer>
       human_presence_observation_{this};
   base::ScopedObservation<HumanPresenceOrientationController,
                           HumanPresenceOrientationController::Observer>
diff --git a/ash/system/human_presence/lock_on_leave_controller_unittest.cc b/ash/system/human_presence/lock_on_leave_controller_unittest.cc
index c8b14a0..3f51c7d 100644
--- a/ash/system/human_presence/lock_on_leave_controller_unittest.cc
+++ b/ash/system/human_presence/lock_on_leave_controller_unittest.cc
@@ -13,8 +13,8 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_command_line.h"
 #include "base/test/scoped_feature_list.h"
-#include "chromeos/dbus/human_presence/fake_human_presence_dbus_client.h"
-#include "chromeos/dbus/human_presence/human_presence_dbus_client.h"
+#include "chromeos/ash/components/dbus/human_presence/fake_human_presence_dbus_client.h"
+#include "chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
@@ -28,15 +28,15 @@
     base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kHasHps);
 
     // Initialize FakeHumanPresenceDBusClient.
-    chromeos::HumanPresenceDBusClient::InitializeFake();
-    human_presence_client_ = chromeos::FakeHumanPresenceDBusClient::Get();
+    HumanPresenceDBusClient::InitializeFake();
+    human_presence_client_ = FakeHumanPresenceDBusClient::Get();
     human_presence_client_->Reset();
 
     AshTestBase::SetUp();
   }
 
  protected:
-  chromeos::FakeHumanPresenceDBusClient* human_presence_client_ = nullptr;
+  FakeHumanPresenceDBusClient* human_presence_client_ = nullptr;
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
diff --git a/ash/system/human_presence/snooping_protection_controller.cc b/ash/system/human_presence/snooping_protection_controller.cc
index 0dd08d24..6021d15 100644
--- a/ash/system/human_presence/snooping_protection_controller.cc
+++ b/ash/system/human_presence/snooping_protection_controller.cc
@@ -17,8 +17,8 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
+#include "chromeos/ash/components/dbus/hps/hps_service.pb.h"
 #include "chromeos/ash/components/human_presence/human_presence_configuration.h"
-#include "chromeos/dbus/hps/hps_service.pb.h"
 #include "components/account_id/account_id.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_change_registrar.h"
@@ -66,8 +66,8 @@
   // error.
   //
   // Might not exist in unit tests.
-  if (chromeos::HumanPresenceDBusClient::Get()) {
-    chromeos::HumanPresenceDBusClient::Get()->WaitForServiceToBeAvailable(
+  if (HumanPresenceDBusClient::Get()) {
+    HumanPresenceDBusClient::Get()->WaitForServiceToBeAvailable(
         base::BindOnce(&SnoopingProtectionController::StartServiceObservation,
                        weak_ptr_factory_.GetWeakPtr()));
   }
@@ -84,8 +84,8 @@
   // TODO(crbug.com/1241704): only disable if the service is enabled.
   //
   // Might not exist in unit tests.
-  if (chromeos::HumanPresenceDBusClient::Get())
-    chromeos::HumanPresenceDBusClient::Get()->DisableHpsNotify();
+  if (HumanPresenceDBusClient::Get())
+    HumanPresenceDBusClient::Get()->DisableHpsNotify();
 
   for (auto& observer : observers_)
     observer.OnSnoopingProtectionControllerDestroyed();
@@ -266,10 +266,10 @@
       return;
     }
 
-    chromeos::HumanPresenceDBusClient::Get()->EnableHpsNotify(*config);
+    HumanPresenceDBusClient::Get()->EnableHpsNotify(*config);
 
     // Populate our initial HPS state for consistency with the service.
-    chromeos::HumanPresenceDBusClient::Get()->GetResultHpsNotify(
+    HumanPresenceDBusClient::Get()->GetResultHpsNotify(
         base::BindOnce(&SnoopingProtectionController::UpdateServiceState,
                        weak_ptr_factory_.GetWeakPtr()));
     new_state->service_configured = true;
@@ -278,7 +278,7 @@
   }
 
   // No longer need signals to be emitted.
-  chromeos::HumanPresenceDBusClient::Get()->DisableHpsNotify();
+  HumanPresenceDBusClient::Get()->DisableHpsNotify();
   new_state->service_configured = false;
 }
 
@@ -295,11 +295,10 @@
   // Special case: at this point, the service could have been left in an enabled
   // state by a previous session that crashed (and hence didn't clean up
   // properly). Disable it here, which is a no-op if it is already disabled.
-  chromeos::HumanPresenceDBusClient::Get()->DisableHpsNotify();
+  HumanPresenceDBusClient::Get()->DisableHpsNotify();
 
   // Start listening for state updates and restarts/shutdowns.
-  human_presence_dbus_observation_.Observe(
-      chromeos::HumanPresenceDBusClient::Get());
+  human_presence_dbus_observation_.Observe(HumanPresenceDBusClient::Get());
 
   // Configure the service and poll its initial value if necessary.
   ReconfigureService(&state_);
diff --git a/ash/system/human_presence/snooping_protection_controller.h b/ash/system/human_presence/snooping_protection_controller.h
index 19de746..d2dc81e 100644
--- a/ash/system/human_presence/snooping_protection_controller.h
+++ b/ash/system/human_presence/snooping_protection_controller.h
@@ -16,8 +16,8 @@
 #include "base/scoped_observation.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-#include "chromeos/dbus/hps/hps_service.pb.h"
-#include "chromeos/dbus/human_presence/human_presence_dbus_client.h"
+#include "chromeos/ash/components/dbus/hps/hps_service.pb.h"
+#include "chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h"
 #include "components/session_manager/session_manager_types.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -33,7 +33,7 @@
 class ASH_EXPORT SnoopingProtectionController
     : public SessionObserver,
       public HumanPresenceOrientationController::Observer,
-      public chromeos::HumanPresenceDBusClient::Observer {
+      public HumanPresenceDBusClient::Observer {
  public:
   class Observer : public base::CheckedObserver {
    public:
@@ -62,7 +62,7 @@
   // HumanPresenceOrientationObserver:
   void OnOrientationChanged(bool suitable_for_human_presence) override;
 
-  // chromeos::HumanPresenceDBusClient::Observer:
+  // HumanPresenceDBusClient::Observer:
   void OnHpsSenseChanged(const hps::HpsResultProto&) override;
   void OnHpsNotifyChanged(const hps::HpsResultProto&) override;
   void OnRestart() override;
@@ -143,8 +143,8 @@
   base::ScopedObservation<HumanPresenceOrientationController,
                           HumanPresenceOrientationController::Observer>
       orientation_observation_{this};
-  base::ScopedObservation<chromeos::HumanPresenceDBusClient,
-                          chromeos::HumanPresenceDBusClient::Observer>
+  base::ScopedObservation<HumanPresenceDBusClient,
+                          HumanPresenceDBusClient::Observer>
       human_presence_dbus_observation_{this};
 
   // Used to notify ourselves of changes to the pref that enables / disables
diff --git a/ash/system/human_presence/snooping_protection_controller_unittest.cc b/ash/system/human_presence/snooping_protection_controller_unittest.cc
index a8719ee..a6885a8 100644
--- a/ash/system/human_presence/snooping_protection_controller_unittest.cc
+++ b/ash/system/human_presence/snooping_protection_controller_unittest.cc
@@ -18,9 +18,9 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/hps/hps_service.pb.h"
-#include "chromeos/dbus/human_presence/fake_human_presence_dbus_client.h"
-#include "chromeos/dbus/human_presence/human_presence_dbus_client.h"
+#include "chromeos/ash/components/dbus/hps/hps_service.pb.h"
+#include "chromeos/ash/components/dbus/human_presence/fake_human_presence_dbus_client.h"
+#include "chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h"
 #include "components/account_id/account_id.h"
 #include "components/user_manager/user_type.h"
 
@@ -71,8 +71,8 @@
   ~SnoopingProtectionControllerTestBase() override = default;
 
   void SetUp() override {
-    chromeos::HumanPresenceDBusClient::InitializeFake();
-    dbus_client_ = chromeos::FakeHumanPresenceDBusClient::Get();
+    HumanPresenceDBusClient::InitializeFake();
+    dbus_client_ = FakeHumanPresenceDBusClient::Get();
     dbus_client_->set_hps_service_is_available(service_available_);
     hps::HpsResultProto state;
     state.set_value(service_state_ ? hps::HpsResult::POSITIVE
@@ -91,7 +91,7 @@
 
   void TearDown() override {
     AshTestBase::TearDown();
-    chromeos::HumanPresenceDBusClient::Shutdown();
+    HumanPresenceDBusClient::Shutdown();
   }
 
  protected:
@@ -102,7 +102,7 @@
   const bool service_state_;
   const std::map<std::string, std::string> params_;
 
-  chromeos::FakeHumanPresenceDBusClient* dbus_client_ = nullptr;
+  FakeHumanPresenceDBusClient* dbus_client_ = nullptr;
   SnoopingProtectionController* controller_ = nullptr;
 
   // Simulates a login. This will trigger a DBus call if and only if logging in
diff --git a/ash/system/human_presence/snooping_protection_notification_blocker.cc b/ash/system/human_presence/snooping_protection_notification_blocker.cc
index fd0236c..0743a1bc8 100644
--- a/ash/system/human_presence/snooping_protection_notification_blocker.cc
+++ b/ash/system/human_presence/snooping_protection_notification_blocker.cc
@@ -28,7 +28,7 @@
 #include "base/no_destructor.h"
 #include "base/notreached.h"
 #include "base/strings/string_util.h"
-#include "chromeos/dbus/hps/hps_service.pb.h"
+#include "chromeos/ash/components/dbus/hps/hps_service.pb.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_service.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/ash/system/human_presence/snooping_protection_notification_blocker_unittest.cc b/ash/system/human_presence/snooping_protection_notification_blocker_unittest.cc
index c29b1de9..745ff4ad 100644
--- a/ash/system/human_presence/snooping_protection_notification_blocker_unittest.cc
+++ b/ash/system/human_presence/snooping_protection_notification_blocker_unittest.cc
@@ -29,9 +29,9 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_command_line.h"
 #include "base/test/scoped_feature_list.h"
-#include "chromeos/dbus/hps/hps_service.pb.h"
-#include "chromeos/dbus/human_presence/fake_human_presence_dbus_client.h"
-#include "chromeos/dbus/human_presence/human_presence_dbus_client.h"
+#include "chromeos/ash/components/dbus/hps/hps_service.pb.h"
+#include "chromeos/ash/components/dbus/human_presence/fake_human_presence_dbus_client.h"
+#include "chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h"
 #include "components/account_id/account_id.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/app_update.h"
@@ -198,8 +198,8 @@
   // AshTestBase overrides:
   void SetUp() override {
     // Simulate a working DBus client.
-    chromeos::HumanPresenceDBusClient::InitializeFake();
-    auto* dbus_client = chromeos::FakeHumanPresenceDBusClient::Get();
+    HumanPresenceDBusClient::InitializeFake();
+    auto* dbus_client = FakeHumanPresenceDBusClient::Get();
     dbus_client->set_hps_service_is_available(true);
     hps::HpsResultProto state;
     state.set_value(hps::HpsResult::NEGATIVE);
diff --git a/ash/system/power/power_prefs_unittest.cc b/ash/system/power/power_prefs_unittest.cc
index baab688a..5daed95 100644
--- a/ash/system/power/power_prefs_unittest.cc
+++ b/ash/system/power/power_prefs_unittest.cc
@@ -23,8 +23,8 @@
 #include "base/test/scoped_command_line.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_tick_clock.h"
+#include "chromeos/ash/components/dbus/human_presence/fake_human_presence_dbus_client.h"
 #include "chromeos/ash/components/human_presence/human_presence_configuration.h"
-#include "chromeos/dbus/human_presence/fake_human_presence_dbus_client.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
@@ -218,10 +218,9 @@
     feature_list_.InitWithFeatures(
         {features::kQuickDim, features::kAdaptiveCharging}, {});
     base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kHasHps);
-    chromeos::HumanPresenceDBusClient::InitializeFake();
-    chromeos::FakeHumanPresenceDBusClient::Get()->Reset();
-    chromeos::FakeHumanPresenceDBusClient::Get()->set_hps_service_is_available(
-        true);
+    HumanPresenceDBusClient::InitializeFake();
+    FakeHumanPresenceDBusClient::Get()->Reset();
+    FakeHumanPresenceDBusClient::Get()->set_hps_service_is_available(true);
     NoSessionAshTestBase::SetUp();
 
     power_policy_controller_ = chromeos::PowerPolicyController::Get();
@@ -576,12 +575,8 @@
 TEST_F(PowerPrefsTest, SetQuickDimParams) {
   // Check that DisableHpsSense is called on initialization.
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(
-      chromeos::FakeHumanPresenceDBusClient::Get()->disable_hps_sense_count(),
-      1);
-  EXPECT_EQ(
-      chromeos::FakeHumanPresenceDBusClient::Get()->enable_hps_sense_count(),
-      0);
+  EXPECT_EQ(FakeHumanPresenceDBusClient::Get()->disable_hps_sense_count(), 1);
+  EXPECT_EQ(FakeHumanPresenceDBusClient::Get()->enable_hps_sense_count(), 0);
 
   // This will trigger UpdatePowerPolicyFromPrefs and set correct parameters.
   SetQuickDimPreference(true);
@@ -602,16 +597,12 @@
 
   // EnableHpsSense should be called when kPowerQuickDimEnabled becomes true.
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(
-      chromeos::FakeHumanPresenceDBusClient::Get()->enable_hps_sense_count(),
-      1);
+  EXPECT_EQ(FakeHumanPresenceDBusClient::Get()->enable_hps_sense_count(), 1);
 
   // DisableHpsSense should be called when kPowerQuickDimEnabled becomes false.
   SetQuickDimPreference(false);
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(
-      chromeos::FakeHumanPresenceDBusClient::Get()->disable_hps_sense_count(),
-      2);
+  EXPECT_EQ(FakeHumanPresenceDBusClient::Get()->disable_hps_sense_count(), 2);
 }
 
 TEST_F(PowerPrefsTest, QuickDimMetrics) {
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py
index fde49c8..cf7987c 100644
--- a/build/android/pylib/instrumentation/instrumentation_test_instance.py
+++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -699,6 +699,10 @@
     self._test_launcher_batch_limit = None
     self._initializeTestLauncherAttributes(args)
 
+    self._approve_app_links_domain = None
+    self._approve_app_links_package = None
+    self._initializeApproveAppLinksAttributes(args)
+
     self._wpr_enable_record = args.wpr_enable_record
 
     self._external_shard_index = args.test_launcher_shard_index
@@ -933,6 +937,20 @@
     if hasattr(args, 'test_launcher_batch_limit'):
       self._test_launcher_batch_limit = args.test_launcher_batch_limit
 
+  def _initializeApproveAppLinksAttributes(self, args):
+    if (not hasattr(args, 'approve_app_links') or not args.approve_app_links):
+      return
+
+    # The argument will be formatted as com.android.thing:www.example.com .
+    app_links = args.approve_app_links.split(':')
+
+    if (len(app_links) != 2 or not app_links[0] or not app_links[1]):
+      logging.warning('--approve_app_links option provided, but malformed.')
+      return
+
+    self._approve_app_links_package = app_links[0]
+    self._approve_app_links_domain = app_links[1]
+
   @property
   def additional_apks(self):
     return self._additional_apks
@@ -946,6 +964,14 @@
     return self._apk_under_test_incremental_install_json
 
   @property
+  def approve_app_links_package(self):
+    return self._approve_app_links_package
+
+  @property
+  def approve_app_links_domain(self):
+    return self._approve_app_links_domain
+
+  @property
   def modules(self):
     return self._modules
 
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index 510684c..d28f6fa5 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -26,6 +26,7 @@
 from devil.android import device_temp_file
 from devil.android import flag_changer
 from devil.android.sdk import shared_prefs
+from devil.android.sdk import version_codes
 from devil.android import logcat_monitor
 from devil.android.tools import system_app
 from devil.android.tools import webview_app
@@ -383,6 +384,10 @@
               shared_pref, setting)
 
       @trace_event.traced
+      def approve_app_links(dev):
+        self._ToggleAppLinks(dev, 'STATE_APPROVED')
+
+      @trace_event.traced
       def set_vega_permissions(dev):
         # Normally, installation of VrCore automatically grants storage
         # permissions. However, since VrCore is part of the system image on
@@ -424,8 +429,8 @@
             dev, self._test_instance.timeout_scale)
 
       steps += [
-          set_debug_app, edit_shared_prefs, push_test_data, create_flag_changer,
-          set_vega_permissions, DismissCrashDialogs
+          set_debug_app, edit_shared_prefs, approve_app_links, push_test_data,
+          create_flag_changer, set_vega_permissions, DismissCrashDialogs
       ]
 
       def bind_crash_handler(step, dev):
@@ -507,6 +512,9 @@
       for pref_to_restore in self._shared_prefs_to_restore:
         pref_to_restore.Commit(force_commit=True)
 
+      # If we've force approved app links for a package, undo that now.
+      self._ToggleAppLinks(dev, 'STATE_NO_RESPONSE')
+
       # Context manager exit handlers are applied in reverse order
       # of the enter handlers.
       for context in reversed(self._context_managers[str(dev)]):
@@ -517,6 +525,24 @@
 
     self._env.parallel_devices.pMap(individual_device_tear_down)
 
+  def _ToggleAppLinks(self, dev, state):
+    # The set-app-links command was added in Android 12 (sdk = 31). The
+    # restrictions that require us to set the app links were also added in
+    # Android 12, so doing nothing on earlier Android versions is fine.
+    if dev.build_version_sdk < version_codes.S:
+      return
+
+    package = self._test_instance.approve_app_links_package
+    domain = self._test_instance.approve_app_links_domain
+
+    if not package or not domain:
+      return
+
+    cmd = [
+        'pm', 'set-app-links', '--package', package, state, domain
+    ]
+    dev.RunShellCommand(cmd, check_return=True)
+
   def _CreateFlagChangerIfNeeded(self, device):
     if str(device) not in self._flag_changers:
       cmdline_file = 'test-cmdline-file'
diff --git a/build/android/test/incremental_javac_gn/incremental_javac_test_android_library.py b/build/android/test/incremental_javac_gn/incremental_javac_test_android_library.py
index c84cff0d..e0f7e1f 100755
--- a/build/android/test/incremental_javac_gn/incremental_javac_test_android_library.py
+++ b/build/android/test/incremental_javac_gn/incremental_javac_test_android_library.py
@@ -116,8 +116,9 @@
       # GOMA does not work with non-standard output directories.
       'use_goma = false',
   ]
-  _copy_and_append_gn_args(options.gn_args_path, out_gn_args_path,
-                           extra_gn_args)
+  _copy_and_append_gn_args(
+      options.gn_args_path, out_gn_args_path,
+      extra_gn_args + ['incremental_javac_test_toggle_gn = false'])
 
   _run_gn([
       '--root-target=' + options.target_name, 'gen',
@@ -132,19 +133,19 @@
   ninja_args = [_NINJA_PATH, '-C', options.out_dir, gn_path]
   ninja_output = _run_command(ninja_args, env=ninja_env)
   if _USING_PARTIAL_JAVAC_MSG in ninja_output:
-    raise Exception("Incorrectly using partial javac for clean compile.")
+    raise Exception('Incorrectly using partial javac for clean compile.')
 
   _copy_and_append_gn_args(
       options.gn_args_path, out_gn_args_path,
       extra_gn_args + ['incremental_javac_test_toggle_gn = true'])
   ninja_output = _run_command(ninja_args, env=ninja_env)
   if _USING_PARTIAL_JAVAC_MSG not in ninja_output:
-    raise Exception("Not using partial javac for incremental compile.")
+    raise Exception('Not using partial javac for incremental compile.')
 
-  expected_output_path = "{}/lib.java/{}.jar".format(options.out_dir,
-                                                     gn_path.replace(':', '/'))
+  expected_output_path = '{}/obj/{}.javac.jar'.format(options.out_dir,
+                                                      gn_path.replace(':', '/'))
   if not os.path.exists(expected_output_path):
-    raise Exception("{} not created.".format(expected_output_path))
+    raise Exception('{} not created.'.format(expected_output_path))
 
   shutil.copyfile(expected_output_path, options.out_jar)
 
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 8245ef72..3e909fb8 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -595,6 +595,12 @@
                       help='If true, WPR server runs in record mode.'
                       'otherwise, runs in replay mode.')
 
+  parser.add_argument(
+      '--approve-app-links',
+      help='Force enables Digital Asset Link verification for the provided '
+      'package and domain, example usage: --approve-app-links '
+      'com.android.package:www.example.com')
+
   # These arguments are suppressed from the help text because they should
   # only ever be specified by an intermediate script.
   parser.add_argument(
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 59e101a6..1710355 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -20,6 +20,9 @@
 }
 assert(is_android)
 
+default_android_sdk_dep = "//third_party/android_sdk:android_sdk_java"
+_jacoco_dep = "//third_party/jacoco:jacocoagent_java"
+
 # The following _java_*_types variables capture all the existing target types.
 # If a new type is introduced, please add it to one of these categories,
 # preferring the more specific resource/library types.
@@ -115,9 +118,8 @@
   _target_label =
       get_label_info(":${_parent_invoker.target_name}", "label_no_toolchain")
 
-  # Ensure targets match naming patterns so that __assetres, __header, __impl
-  # targets work properly. Those generated targets allow for effective deps
-  # filtering.
+  # Ensure targets match naming patterns so that __assetres, __header, __host,
+  # and __validate targets work properly.
   if (filter_exclude([ _type ], _java_resource_types) == []) {
     if (filter_exclude([ _target_label ], java_resource_patterns) != []) {
       assert(false, "Invalid java resource target name: $_target_label")
@@ -162,8 +164,6 @@
       foreach(_possible_dep, invoker.possible_config_deps) {
         _dep_label = get_label_info(_possible_dep, "label_no_toolchain")
         if (filter_exclude([ _dep_label ], java_target_patterns) == []) {
-          # Put the bug number in the target name so that false-positives
-          # have a hint in the error message about non-existent dependencies.
           deps += [ "$_dep_label$build_config_target_suffix" ]
           _dep_gen_dir = get_label_info(_possible_dep, "target_gen_dir")
           _dep_name = get_label_info(_possible_dep, "name")
@@ -1151,12 +1151,7 @@
   }
 
   template("proguard") {
-    forward_variables_from(invoker,
-                           TESTONLY_AND_VISIBILITY + [
-                                 "data",
-                                 "data_deps",
-                                 "public_deps",
-                               ])
+    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
     _script = "//build/android/gyp/proguard.py"
     _deps = invoker.deps
 
@@ -1358,6 +1353,12 @@
       _deps += [ ":$_expectations_target" ]
     }
     action_with_pydeps(target_name) {
+      forward_variables_from(invoker,
+                             [
+                               "data",
+                               "data_deps",
+                               "public_deps",
+                             ])
       script = _script
       deps = _deps
       inputs = _inputs
@@ -1586,6 +1587,9 @@
           _r8_path,
           _custom_d8_path,
         ]
+        if (defined(invoker.inputs)) {
+          inputs += invoker.inputs
+        }
 
         if (!_is_library) {
           # http://crbug.com/725224. Fix for bots running out of memory.
@@ -1878,7 +1882,7 @@
 
   template("bytecode_processor") {
     action_with_pydeps(target_name) {
-      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
+      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "data_deps" ])
       _bytecode_checker_script = "$root_build_dir/bin/helper/bytecode_processor"
       script = "//build/android/gyp/bytecode_processor.py"
       inputs = [
@@ -2974,7 +2978,7 @@
 
       if (target_name == "chrome_java__header") {
         # Regression test for: https://crbug.com/1154302
-        assert_no_deps = [ "//base:base_java__impl" ]
+        assert_no_deps = [ "//base:base_java__compile_java" ]
       }
 
       depfile = "$target_gen_dir/$target_name.d"
@@ -3115,28 +3119,6 @@
     }
   }
 
-  template("java_lib_group") {
-    forward_variables_from(invoker, [ "testonly" ])
-    _group_name = invoker.group_name
-    not_needed([ "_group_name" ])
-    group(target_name) {
-      if (defined(invoker.deps)) {
-        deps = []
-        foreach(_dep, invoker.deps) {
-          _target_label = get_label_info(_dep, "label_no_toolchain")
-          if (filter_exclude([ _target_label ], java_library_patterns) == [] &&
-              filter_exclude([ _target_label ], java_resource_patterns) != []) {
-            # This is a java library dep, so replace it.
-            deps += [ "${_target_label}__${_group_name}" ]
-          } else {
-            # Transitive java group targets should also include direct deps.
-            deps += [ _dep ]
-          }
-        }
-      }
-    }
-  }
-
   # Create an interface jar from a normal jar.
   #
   # Variables
@@ -3308,10 +3290,16 @@
     _type = invoker.type
     _is_annotation_processor = _type == "java_annotation_processor"
     _is_java_binary = _type == "java_binary" || _type == "robolectric_binary"
+    _is_library = _type == "java_library"
     _supports_android =
         defined(invoker.supports_android) && invoker.supports_android
     _requires_android =
         defined(invoker.requires_android) && invoker.requires_android
+    _supports_host = !_requires_android
+    if (_is_java_binary || _is_annotation_processor) {
+      assert(!_requires_android && !_supports_android)
+    }
+
     _bypass_platform_checks = defined(invoker.bypass_platform_checks) &&
                               invoker.bypass_platform_checks
     _is_robolectric = defined(invoker.is_robolectric) && invoker.is_robolectric
@@ -3400,6 +3388,9 @@
         _jacoco_instrument =
             !invoker.jacoco_never_instrument && _jacoco_instrument
       }
+      if (_jacoco_instrument) {
+        _invoker_deps += [ _jacoco_dep ]
+      }
 
       if (_build_host_jar) {
         # Jar files can be needed at runtime (by Robolectric tests or java binaries),
@@ -3457,77 +3448,83 @@
       }
     }
 
+    _java_assetres_deps = filter_include(_invoker_deps, java_resource_patterns)
+
+    # Cannot use minus operator because it does not work when the operand has
+    # repeated entries.
+    _invoker_deps_minus_assetres =
+        filter_exclude(_invoker_deps, _java_assetres_deps)
+    _lib_deps =
+        filter_include(_invoker_deps_minus_assetres, java_library_patterns)
+    _non_java_deps = filter_exclude(_invoker_deps_minus_assetres, _lib_deps)
+
+    _java_header_deps = []  # Turbine / ijar
+
+    # It would be more ideal to split this into __host and __javac, but we
+    # combine the two concepts to save on a group() target.
+    _java_host_deps = []  # Processed host .jar + javac .jar.
+    _java_validate_deps = []  # Bytecode checker & errorprone.
+
+    foreach(_lib_dep, _lib_deps) {
+      # Expand //foo/java -> //foo/java:java
+      _lib_dep = get_label_info(_lib_dep, "label_no_toolchain")
+      _java_assetres_deps += [ "${_lib_dep}__assetres" ]
+      _java_header_deps += [ "${_lib_dep}__header" ]
+      _java_host_deps += [ "${_lib_dep}__host" ]
+      _java_validate_deps += [ "${_lib_dep}__validate" ]
+    }
+
+    # APK and base module targets are special because:
+    # 1) They do not follow java target naming scheme (since they are not
+    #    generally deps, there is no need for them to).
+    # 2) They do not bother to define a __host target.
+    # Since __host is used as an indirect dep for the compile_java artifacts,
+    # add the __compile_java target directly for them.
+    if (defined(invoker.apk_under_test)) {
+      _java_assetres_deps += [ "${invoker.apk_under_test}__java__assetres" ]
+      _java_header_deps += [ "${invoker.apk_under_test}__java__header" ]
+      _java_validate_deps += [ "${invoker.apk_under_test}__java__validate" ]
+      _java_host_deps += [ "${invoker.apk_under_test}__compile_java" ]
+    }
+    if (defined(invoker.base_module_target)) {
+      _java_assetres_deps += [ "${invoker.base_module_target}__java__assetres" ]
+      _java_header_deps += [ "${invoker.base_module_target}__java__header" ]
+      _java_validate_deps += [ "${invoker.base_module_target}__java__validate" ]
+      _java_host_deps += [ "${invoker.base_module_target}__compile_java" ]
+    }
+
+    not_needed([ "_non_java_deps" ])
+
     if (_is_prebuilt || _has_sources) {
-      _java_assetres_deps =
-          filter_include(_invoker_deps, java_resource_patterns)
+      # Classpath deps are used for header and dex targets, they do not need
+      # __assetres deps.
+      # _non_java_deps are needed for input_jars_paths that are generated.
+      _header_classpath_deps =
+          _java_header_deps + _non_java_deps + [ ":$_build_config_target_name" ]
 
-      # Cannot use minus operator because it does not work when the operand has
-      # repeated entries.
-      _invoker_deps_minus_assetres =
-          filter_exclude(_invoker_deps, _java_assetres_deps)
-      _lib_deps =
-          filter_include(_invoker_deps_minus_assetres, java_library_patterns)
-      _non_java_deps = filter_exclude(_invoker_deps_minus_assetres, _lib_deps)
-
-      _java_header_deps = []
-      _java_impl_deps = []
-      foreach(_lib_dep, _lib_deps) {
-        # Expand //foo/java -> //foo/java:java
-        _lib_dep = get_label_info(_lib_dep, "label_no_toolchain")
-
-        # This is a java library dep, so it has header and impl targets.
-        _java_header_deps += [ "${_lib_dep}__header" ]
-        _java_impl_deps += [ "${_lib_dep}__impl" ]
-        _java_assetres_deps += [ "${_lib_dep}__assetres" ]
-      }
-
-      # Don't need to depend on the apk-under-test to be packaged.
-      if (defined(invoker.apk_under_test)) {
-        _java_header_deps += [ "${invoker.apk_under_test}__java__header" ]
-        _java_impl_deps += [ "${invoker.apk_under_test}__java__impl" ]
-      }
-
-      # These deps cannot be passed via invoker.deps since bundle_module targets
-      # have bundle_module.build_config without the __java suffix, so they are
-      # special and cannot be passed as regular deps to write_build_config.
-      if (defined(invoker.base_module_target)) {
-        _java_header_deps += [ "${invoker.base_module_target}__java__header" ]
-        _java_impl_deps += [ "${invoker.base_module_target}__java__impl" ]
-      }
-
-      _extra_java_deps = []
-      if (_jacoco_instrument) {
-        _extra_java_deps += [ "//third_party/jacoco:jacocoagent_java" ]
-      }
+      _javac_classpath_deps =
+          _java_host_deps + _non_java_deps + [ ":$_build_config_target_name" ]
 
       _include_android_sdk = _build_device_jar
       if (defined(invoker.include_android_sdk)) {
         _include_android_sdk = invoker.include_android_sdk
       }
       if (_include_android_sdk) {
-        _sdk_java_dep = "//third_party/android_sdk:android_sdk_java"
         if (defined(invoker.alternative_android_sdk_dep)) {
-          _sdk_java_dep = invoker.alternative_android_sdk_dep
+          _android_sdk_dep = invoker.alternative_android_sdk_dep
+        } else {
+          _android_sdk_dep = default_android_sdk_dep
         }
 
-        # This is an android_system_java_prebuilt target, so no headers.
-        _extra_java_deps += [ _sdk_java_dep ]
+        _header_classpath_deps += [ "${_android_sdk_dep}__header" ]
+        _javac_classpath_deps += [ "${_android_sdk_dep}" ]
       }
-
-      # Classpath deps is used for header and dex targets, they do not need
-      # resource deps.
-      _classpath_deps = _java_header_deps + _non_java_deps + _extra_java_deps +
-                        [ ":$_build_config_target_name" ]
-
-      _full_classpath_deps =
-          _java_impl_deps + _java_assetres_deps + _non_java_deps +
-          _extra_java_deps + [ ":$_build_config_target_name" ]
     }
 
     # Often needed, but too hard to figure out when ahead of time.
     not_needed([
-                 "_classpath_deps",
-                 "_full_classpath_deps",
+                 "_header_classpath_deps",
+                 "_javac_classpath_deps",
                ])
 
     if (_java_files != []) {
@@ -3611,12 +3608,15 @@
       if (defined(invoker.public_deps)) {
         possible_config_public_deps = invoker.public_deps
       }
-      if (defined(_extra_java_deps)) {
-        possible_config_deps += _extra_java_deps
-      }
       if (defined(apk_under_test)) {
         possible_config_deps += [ apk_under_test ]
       }
+      if (defined(_jacoco_instrument) && _jacoco_instrument) {
+        possible_config_deps += [ _jacoco_dep ]
+      }
+      if (defined(_android_sdk_dep)) {
+        possible_config_deps += [ _android_sdk_dep ]
+      }
 
       supports_android = _supports_android
       requires_android = _requires_android
@@ -3663,9 +3663,6 @@
       _header_target_name = "${target_name}__header"
     }
 
-    _public_deps = []
-    _analysis_public_deps = []
-
     if (_has_sources) {
       if (defined(invoker.enable_errorprone)) {
         _enable_errorprone = invoker.enable_errorprone
@@ -3682,10 +3679,9 @@
                    "android_library(), or robolectric_library(). " +
                    "Target=$target_name")
 
-        # has _resources at the end so it looks like a resources pattern, since
-        # it does act like one (and other resources patterns need to depend on
-        # this before they can read its output R.txt).
-        _fake_rjava_target = "${target_name}__rjava_resources"
+        # Serves double purpose: Generating R.java, as well as being the
+        #__assetres target (instead of using a separate group).
+        _fake_rjava_target = "${target_name}__assetres"
         generate_r_java(_fake_rjava_target) {
           deps = [ ":$_build_config_target_name" ] + _java_assetres_deps +
                  _non_java_deps
@@ -3712,10 +3708,17 @@
           # Filtering out generated files resulted in no files left.
           group(target_name) {
             not_needed(invoker, "*")
+            deps = _header_classpath_deps
           }
         } else {
           compile_java(target_name) {
-            forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
+            forward_variables_from(invoker,
+                                   "*",
+                                   TESTONLY_AND_VISIBILITY + [ "deps" ])
+            deps = _header_classpath_deps
+            if (defined(invoker.deps)) {
+              deps += invoker.deps
+            }
             output_jar_path = invoker.output_jar_path
             enable_errorprone = _enable_errorprone
             use_turbine = defined(invoker.use_turbine) && invoker.use_turbine
@@ -3736,10 +3739,6 @@
             chromium_code = _chromium_code
             supports_android = _supports_android
             include_android_sdk = _is_robolectric || _requires_android
-            if (!defined(deps)) {
-              deps = []
-            }
-            deps += _classpath_deps
           }
         }
       }
@@ -3763,7 +3762,6 @@
         generated_jar_path = _generated_jar_path
         deps = _annotation_processor_deps
       }
-      _public_deps += [ ":$_header_target_name" ]
 
       _compile_java_target = "${_main_target_name}__compile_java"
       compile_java_helper(_compile_java_target) {
@@ -3789,14 +3787,16 @@
           generated_jar_path = _generated_jar_path
           output_jar_path = "$target_out_dir/$target_name.errorprone.stamp"
         }
-        _analysis_public_deps += [ ":$_compile_java_errorprone_target" ]
+        _java_validate_deps += [ ":$_compile_java_errorprone_target" ]
       }
     }  # _has_sources
 
     if (_is_prebuilt || _build_device_jar || _build_host_jar) {
-      _unprocessed_jar_deps = []
       if (_has_sources) {
-        _unprocessed_jar_deps += [ ":$_compile_java_target" ]
+        _unprocessed_jar_deps = [ ":$_compile_java_target" ]
+      } else {
+        # jars might be generated by a dep.
+        _unprocessed_jar_deps = _non_java_deps
       }
     }
 
@@ -3832,7 +3832,7 @@
           "--output-jar",
           rebase_path(_rewritten_jar, root_build_dir),
         ]
-        deps = _unprocessed_jar_deps + _full_classpath_deps +
+        deps = _unprocessed_jar_deps + _javac_classpath_deps +
                [ invoker.bytecode_rewriter_target ]
       }
 
@@ -3849,14 +3849,10 @@
         input_jar = _unprocessed_jar_path
         output_jar = _final_ijar_path
 
-        # Normally ijar does not require any deps, but:
-        # 1 - Some jars are bytecode rewritten by _unprocessed_jar_deps.
-        # 2 - Other jars need to be unzipped by _non_java_deps.
-        # 3 - It is expected that depending on a header target implies depending
-        #     on its transitive header target deps via _java_header_deps.
-        deps = _unprocessed_jar_deps + _non_java_deps + _java_header_deps
+        # ijar needs only _unprocessed_jar_deps, but this also needs to export
+        # __header target from deps.
+        deps = _unprocessed_jar_deps + _java_header_deps
       }
-      _public_deps += [ ":$_header_target_name" ]
     }
 
     if (_build_host_jar || _build_device_jar) {
@@ -3864,11 +3860,15 @@
           (!defined(invoker.enable_bytecode_checks) ||
            invoker.enable_bytecode_checks) && android_static_analysis != "off"
       if (_enable_bytecode_checks) {
-        _bytecode_checks_target = "${target_name}__validate_classpath"
-        bytecode_processor(_bytecode_checks_target) {
+        _validate_target_name = "${target_name}__validate"
+        bytecode_processor(_validate_target_name) {
           forward_variables_from(invoker, [ "missing_classes_allowlist" ])
-          deps = _unprocessed_jar_deps + _full_classpath_deps +
+          deps = _unprocessed_jar_deps + _javac_classpath_deps +
                  [ ":$_build_config_target_name" ]
+          data_deps = _java_validate_deps
+          if (defined(_compile_java_errorprone_target)) {
+            data_deps += [ ":$_compile_java_errorprone_target" ]
+          }
 
           include_android_sdk = _requires_android || _is_robolectric
           target_label =
@@ -3877,13 +3877,12 @@
           build_config = _build_config
           is_prebuilt = _is_prebuilt
         }
-        _analysis_public_deps += [ ":$_bytecode_checks_target" ]
       } else {
         not_needed(invoker, [ "missing_classes_allowlist" ])
       }
 
       if (_build_host_jar) {
-        _process_host_jar_target_name = "${target_name}__process_host"
+        _process_host_jar_target_name = "${target_name}__host"
         process_java_library(_process_host_jar_target_name) {
           forward_variables_from(invoker,
                                  [
@@ -3894,15 +3893,20 @@
           # Robolectric tests require these to be on swarming.
           data = [ _host_processed_jar_path ]
           input_jar_path = _unprocessed_jar_path
-          deps = _unprocessed_jar_deps + _full_classpath_deps
+          deps = _unprocessed_jar_deps + _javac_classpath_deps
           output_jar_path = _host_processed_jar_path
           jacoco_instrument = _jacoco_instrument
           if (_jacoco_instrument) {
             java_files = _java_files
             java_sources_file = _java_sources_file
           }
+
+          # _java_host_deps isn't necessary for process_java_library(), but is
+          # necessary so that this target can be used to depend on transitive
+          # __device targets without the need to create a separate group()
+          # target. This trade-off works because process_java_library is fast.
+          deps += _java_host_deps
         }
-        _public_deps += [ ":${_process_host_jar_target_name}" ]
       }
 
       if (_build_device_jar) {
@@ -3915,7 +3919,8 @@
                                      "jar_included_patterns",
                                    ])
             input_jar_path = _unprocessed_jar_path
-            deps = _unprocessed_jar_deps + _full_classpath_deps
+
+            deps = _unprocessed_jar_deps + _javac_classpath_deps
             output_jar_path = _device_processed_jar_path
             jacoco_instrument = _jacoco_instrument
             if (_jacoco_instrument) {
@@ -3924,14 +3929,13 @@
             }
           }
           _process_device_jar_deps = [ ":${_process_device_jar_target_name}" ]
-          _public_deps += _process_device_jar_deps
         } else {
           assert(_unprocessed_jar_path == _device_processed_jar_path)
-          _process_device_jar_deps =
-              _unprocessed_jar_deps + _full_classpath_deps
+          _process_device_jar_deps = _unprocessed_jar_deps
         }
 
-        dex("${target_name}__dex") {
+        _dex_target_name = "${target_name}__dex"
+        dex(_dex_target_name) {
           forward_variables_from(invoker,
                                  [
                                    "desugar_jars_paths",
@@ -3951,16 +3955,24 @@
             # Desugaring with D8 requires full classpath.
             build_config = _build_config
             final_ijar_path = _final_ijar_path
-            deps += _classpath_deps + [
-                      ":$_build_config_target_name",
-                      ":$_header_target_name",
-                    ]
+            deps += _header_classpath_deps + [ ":$_header_target_name" ]
           }
 
           enable_multidex = false
           is_library = true
+
+          # proguard_configs listed on java_library targets need to be marked
+          # as inputs to at least one target so that "gn analyze" will know
+          # about them. Although this target doesn't use them, it's a convenient spot
+          # to list them.
+          # https://crbug.com/827197
+          if (compute_inputs_for_analyze && defined(invoker.proguard_configs)) {
+            inputs = invoker.proguard_configs
+
+            # For the aapt-generated proguard rules.
+            deps += _non_java_deps + _srcjar_deps
+          }
         }
-        _public_deps += [ ":${target_name}__dex" ]
       }
     }
 
@@ -3985,57 +3997,100 @@
           extra_classpath_jars = [ _robolectric_jar_path ]
         }
       }
-      _public_deps += [ ":$_java_binary_script_target_name" ]
     }
 
-    # The __impl target contains all non-analysis steps for this template.
-    # Having this separated out from the main target (which contains analysis
-    # steps) allows analysis steps for this target to be run concurrently with
-    # the non-analysis steps of other targets that depend on this one.
-    group("${target_name}__impl") {
-      public_deps = _public_deps
+    if (!defined(_validate_target_name)) {
+      _validate_target_name = "${target_name}__validate"
 
-      # proguard_configs listed on java_library targets need to be marked
-      # as inputs to at least one target so that "gn analyze" will know
-      # about them. Although this target doesn't use them, it's a convenient spot
-      # to list them.
-      # https://crbug.com/827197
-      if (compute_inputs_for_analyze && defined(invoker.proguard_configs)) {
-        assert(_build_host_jar || _build_device_jar)
-        data = invoker.proguard_configs
-
-        # For the aapt-generated proguard rules.
-        deps = _non_java_deps + _srcjar_deps
+      # Allow other targets to depend on this __validate one.
+      group(_validate_target_name) {
+        deps = _java_validate_deps
       }
     }
 
-    java_lib_group("${target_name}__assetres") {
-      deps = _invoker_deps
-      group_name = "assetres"
-
-      if (defined(_fake_rjava_target)) {
-        deps += [ ":$_fake_rjava_target" ]
+    if (_supports_host && !defined(_process_host_jar_target_name)) {
+      group("${target_name}__host") {
+        deps = _java_host_deps
       }
     }
 
+    # robolectric_library can depend on java_library, so java_library must
+    # define __assetres.
+    if ((_is_library || _supports_android || _is_robolectric) &&
+        !defined(_fake_rjava_target)) {
+      group("${target_name}__assetres") {
+        if (_supports_android || _is_robolectric) {
+          deps = _java_assetres_deps
+        }
+      }
+    }
+
+    # The top-level group is used:
+    # 1) To allow building the target explicitly via ninja,
+    # 2) To trigger all analysis deps,
+    # 3) By custom action() targets that want to use artifacts as inputs.
     group(target_name) {
       forward_variables_from(invoker,
                              [
                                "assert_no_deps",
                                "data",
                                "data_deps",
-                               "deps",
-                               "public_deps",
                                "visibility",
                              ])
-      if (!defined(public_deps)) {
+      if (_requires_android || (_supports_android && _is_library)) {
+        # For non-robolectric targets, depend on other java target's top-level
+        # groups so that the __dex step gets depended on.
+        forward_variables_from(invoker,
+                               [
+                                 "deps",
+                                 "public_deps",
+                               ])
+        if (!defined(deps)) {
+          deps = []
+        }
+        if (!defined(public_deps)) {
+          public_deps = []
+        }
+      } else {
+        # For robolectric targets, depend only on non-java deps and the specific
+        # subtargets below, which will not include __dex.
+        deps = _non_java_deps
         public_deps = []
+        if (defined(invoker.public_deps)) {
+          public_deps +=
+              filter_exclude(invoker.public_deps, java_target_patterns)
+        }
       }
-      public_deps += [ ":${target_name}__impl" ]
+      if (defined(_jacoco_instrument) && _jacoco_instrument) {
+        deps += [ _jacoco_dep ]
+      }
+      if (defined(_process_device_jar_target_name)) {
+        public_deps += [ ":$_process_device_jar_target_name" ]
+      }
+      if (defined(_dex_target_name)) {
+        public_deps += [ ":$_dex_target_name" ]
+      }
+      if (_supports_android && _is_library) {
+        # Robolectric targets define __assetres, but there's no need to build it
+        # by default.
+        public_deps += [ ":${target_name}__assetres" ]
+      }
+      if (_supports_host) {
+        # android_* targets define __host, but there's no need to build it by
+        # default.
+        public_deps += [ ":${target_name}__host" ]
+      }
+      if (_is_java_binary) {
+        public_deps += [ ":$_java_binary_script_target_name" ]
+      }
       if (!defined(data_deps)) {
         data_deps = []
       }
-      data_deps += _analysis_public_deps
+      if (defined(_validate_target_name)) {
+        data_deps += [ ":$_validate_target_name" ]
+      } else {
+        data_deps += _java_validate_deps
+      }
     }
   }
 }
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index cf372d1..a327061 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -1031,9 +1031,9 @@
     }
 
     if (defined(invoker.alternative_android_sdk_dep)) {
-      _deps += [ invoker.alternative_android_sdk_dep ]
+      _android_sdk_dep = invoker.alternative_android_sdk_dep
     } else {
-      _deps += [ "//third_party/android_sdk:android_sdk_java" ]
+      _android_sdk_dep = default_android_sdk_dep
     }
 
     _resource_files = []
@@ -1072,7 +1072,7 @@
                              ])
 
       r_text = _r_text_out_path
-      possible_config_deps = _deps
+      possible_config_deps = _deps + [ _android_sdk_dep ]
 
       # Always merge manifests from resources.
       # * Might want to change this at some point for consistency and clarity,
@@ -1103,7 +1103,7 @@
       }
 
       # Depend on non-library deps and on __assetres subtargets of library deps.
-      deps = filter_exclude(_deps, _lib_deps)
+      deps = filter_exclude(_deps, _lib_deps) + [ _android_sdk_dep ]
       foreach(_lib_dep, _lib_deps) {
         # Expand //foo/java -> //foo/java:java
         _lib_dep = get_label_info(_lib_dep, "label_no_toolchain")
@@ -1237,17 +1237,34 @@
       supports_android = true
       possible_config_deps = _invoker_deps
     }
+
+    _assetres_deps = filter_include(_invoker_deps, java_resource_patterns)
+    _invoker_deps_minus_assetres = filter_exclude(_invoker_deps, _assetres_deps)
+    _lib_deps =
+        filter_include(_invoker_deps_minus_assetres, java_library_patterns)
+
+    _expanded_lib_deps = []
+    foreach(_lib_dep, _lib_deps) {
+      _expanded_lib_deps += [ get_label_info(_lib_dep, "label_no_toolchain") ]
+    }
     foreach(_group_name,
             [
-              "header",
-              "impl",
               "assetres",
+              "header",
+              "host",
+              "validate",
             ]) {
-      java_lib_group("${target_name}__${_group_name}") {
-        deps = _invoker_deps
-        group_name = _group_name
+      group("${target_name}__$_group_name") {
+        deps = []
+        foreach(_lib_dep, _expanded_lib_deps) {
+          deps += [ "${_lib_dep}__${_group_name}" ]
+        }
+        if (_group_name == "assetres") {
+          deps += _assetres_deps
+        }
       }
     }
+
     group(target_name) {
       forward_variables_from(invoker,
                              "*",
@@ -1363,7 +1380,7 @@
     if (defined(invoker.alternative_android_sdk_dep)) {
       _android_sdk_dep = invoker.alternative_android_sdk_dep
     } else {
-      _android_sdk_dep = "//third_party/android_sdk:android_sdk_java"
+      _android_sdk_dep = default_android_sdk_dep
     }
 
     # A package name or a manifest is required to have resources. This is
@@ -1500,8 +1517,13 @@
       deps = [
         ":$_apkbuilder_target_name",
         ":$_build_config_target_name",
-        ":$_java_binary_target_name",
+        ":${_java_binary_target_name}__host",
+        ":${_java_binary_target_name}__java_binary_script",
+        ":${_java_binary_target_name}__validate",
       ]
+
+      # Add non-libary deps, since the __host target does not depend on them.
+      deps += filter_exclude(_invoker_deps, java_library_patterns)
     }
   }
 
@@ -1745,7 +1767,7 @@
   #     output = "$root_build_dir/MyLibrary.jar"
   #   }
   template("dist_dex") {
-    _deps = [ "//third_party/android_sdk:android_sdk_java" ]
+    _deps = [ default_android_sdk_dep ]
     if (defined(invoker.deps)) {
       _deps += invoker.deps
     }
@@ -1766,8 +1788,6 @@
       build_config = _build_config
     }
 
-    _deps += [ ":$_build_config_target_name" ]
-
     dex(target_name) {
       forward_variables_from(invoker,
                              TESTONLY_AND_VISIBILITY + [
@@ -1778,7 +1798,7 @@
                                    "proguard_enable_obfuscation",
                                    "min_sdk_version",
                                  ])
-      deps = _deps
+      deps = [ ":$_build_config_target_name" ] + _deps
       build_config = _build_config
       enable_multidex = false
       output = invoker.output
@@ -2598,7 +2618,7 @@
       }
     }
 
-    _final_deps = []
+    _final_deps = [ ":$_java_target_name" ]
 
     _enable_main_dex_list = _enable_multidex && _min_sdk_version < 21
     if (_enable_main_dex_list) {
@@ -2610,7 +2630,7 @@
     if (defined(invoker.alternative_android_sdk_dep)) {
       _android_sdk_dep = invoker.alternative_android_sdk_dep
     } else {
-      _android_sdk_dep = "//third_party/android_sdk:android_sdk_java"
+      _android_sdk_dep = default_android_sdk_dep
     }
 
     if (defined(_shared_resources_allowlist_target)) {
@@ -3071,6 +3091,8 @@
         output = _dist_ijar_path
         data = [ _dist_ijar_path ]
         use_interface_jars = true
+
+        # This will use __header under-the-hood.
         deps = [ ":$_java_target_name" ]
       }
     }
@@ -3078,7 +3100,7 @@
     if (_uses_static_library_synchronized_proguard) {
       _final_dex_target_dep = "${invoker.static_library_provider}__dexsplitter"
     } else if ((_is_bundle_module && _proguard_enabled) || _omit_dex) {
-      _final_deps += [ ":$_java_target_name" ]
+      # No library dep needed.
     } else if (_incremental_apk) {
       if (defined(invoker.enable_proguard_checks)) {
         not_needed(invoker, [ "enable_proguard_checks" ])
@@ -3101,18 +3123,24 @@
           ":$_java_target_name",
         ]
         if (_proguard_enabled) {
-          deps += _invoker_deps + [ ":$_compile_resources_target" ]
+          # Generates proguard configs
+          deps += [ ":$_compile_resources_target" ]
           proguard_mapping_path = _proguard_mapping_path
           proguard_sourcefile_suffix = "$android_channel-$_version_code"
           has_apk_under_test = defined(invoker.apk_under_test)
-        } else if (_min_sdk_version >= default_min_sdk_version) {
-          # Enable dex merging only when min_sdk_version is >= what the library
-          # .dex files were created with.
-          input_dex_filearg =
-              "@FileArg(${_rebased_build_config}:final_dex:all_dex_files)"
         } else {
-          input_classes_filearg =
-              "@FileArg($_rebased_build_config:deps_info:device_classpath)"
+          if (_min_sdk_version >= default_min_sdk_version) {
+            # Enable dex merging only when min_sdk_version is >= what the library
+            # .dex files were created with.
+            input_dex_filearg =
+                "@FileArg(${_rebased_build_config}:final_dex:all_dex_files)"
+
+            # Pure dex-merge.
+            enable_desugar = false
+          } else {
+            input_classes_filearg =
+                "@FileArg($_rebased_build_config:deps_info:device_classpath)"
+          }
         }
 
         if (_is_static_library_provider) {
@@ -3134,11 +3162,14 @@
         # their respective dex steps. False positives that were suppressed at
         # per-target dex steps are emitted here since this may use jar files
         # rather than dex files.
-        ignore_desugar_missing_deps = true
+        if (!defined(enable_desugar)) {
+          ignore_desugar_missing_deps = true
+        }
 
         if (_enable_main_dex_list) {
-          extra_main_dex_proguard_config = _generated_proguard_main_dex_config
+          # Generates main-dex config.
           deps += [ ":$_compile_resources_target" ]
+          extra_main_dex_proguard_config = _generated_proguard_main_dex_config
         }
       }
 
@@ -3275,11 +3306,11 @@
             name = "${invoker.name}.apk"
             build_config = _build_config
             res_size_info_path = _res_size_info_path
-            deps = _invoker_deps + [
-                     ":$_build_config_target",
-                     ":$_compile_resources_target",
-                     ":$_java_target_name",
-                   ]
+            deps = [
+              ":$_build_config_target",
+              ":$_compile_resources_target",
+              ":$_java_target_name",
+            ]
           }
           _final_deps += [ ":$_size_info_target" ]
         } else {
@@ -3437,10 +3468,7 @@
           args += [ "--native-libs=$_rebased_loadable_modules" ]
         }
       }
-      _final_deps += [
-        ":$_java_target_name",
-        ":$_write_installer_json_rule_name",
-      ]
+      _final_deps += [ ":$_write_installer_json_rule_name" ]
     }
 
     # Generate apk operation related script.
@@ -3527,6 +3555,8 @@
                                ])
         build_config = _build_config
         build_config_dep = ":$_build_config_target"
+
+        # This will use library subtargets under-the-hood
         deps = [ ":$_java_target_name" ]
         if (defined(invoker.lint_suppressions_dep)) {
           deps += [ invoker.lint_suppressions_dep ]
@@ -3562,8 +3592,7 @@
       }
 
       # Include unstripped native libraries so tests can symbolize stacks.
-      data_deps += _all_native_libs_deps
-
+      data_deps += _all_native_libs_deps + [ ":${_java_target_name}__validate" ]
       if (_enable_lint) {
         data_deps += [ ":${target_name}__lint" ]
       }
@@ -4015,6 +4044,7 @@
                                    "data",
                                    "data_deps",
                                    "deps",
+                                   "extra_args",
                                    "proguard_configs",
                                  ])
     }
@@ -4947,9 +4977,9 @@
     _rebased_build_config = rebase_path(_build_config, root_build_dir)
     _build_config_target = "$_target_name$build_config_target_suffix"
     if (defined(invoker.proguard_android_sdk_dep)) {
-      proguard_android_sdk_dep_ = invoker.proguard_android_sdk_dep
+      _android_sdk_dep = invoker.proguard_android_sdk_dep
     } else {
-      proguard_android_sdk_dep_ = "//third_party/android_sdk:android_sdk_java"
+      _android_sdk_dep = default_android_sdk_dep
     }
 
     if (_proguard_enabled) {
@@ -4963,7 +4993,7 @@
 
     write_build_config(_build_config_target) {
       type = "android_app_bundle"
-      possible_config_deps = _module_targets + [ proguard_android_sdk_dep_ ]
+      possible_config_deps = _module_targets + [ _android_sdk_dep ]
       build_config = _build_config
       proguard_enabled = _proguard_enabled
       module_build_configs = _module_build_configs
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index e14c3cc2..85ccedd 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-8.20220704.3.1
+8.20220705.1.1
diff --git a/build/toolchain/rbe.gni b/build/toolchain/rbe.gni
index 793b6ae6..0750c040 100644
--- a/build/toolchain/rbe.gni
+++ b/build/toolchain/rbe.gni
@@ -13,9 +13,6 @@
   # Set to true to enable remote compilation using reclient.
   use_remoteexec = false
 
-  # Set to true to enable remote compilation using reclient (deprecated).
-  use_rbe = false
-
   # The directory where the re-client configuration files are.
   rbe_cfg_dir = rebase_path("//buildtools/reclient_cfgs", root_build_dir)
 
@@ -26,12 +23,6 @@
   rbe_cros_cc_wrapper = "${rbe_bin_dir}/rewrapper"
 }
 
-# Set use_remoteexec if use_rbe is set.  Remove this once use_rbe is no longer
-# used to configure builds.
-if (!use_remoteexec && use_rbe) {
-  use_remoteexec = true
-}
-
 # Configuration file selection based on operating system.
 if (is_linux || is_android || is_chromeos || is_fuchsia) {
   rbe_cc_cfg_file = "${rbe_cfg_dir}/chromium-browser-clang/rewrapper_linux.cfg"
diff --git a/cc/raster/gpu_raster_buffer_provider.cc b/cc/raster/gpu_raster_buffer_provider.cc
index 7c18384..f77c3ae2 100644
--- a/cc/raster/gpu_raster_buffer_provider.cc
+++ b/cc/raster/gpu_raster_buffer_provider.cc
@@ -150,8 +150,7 @@
       tile_format_(tile_format),
       max_tile_size_(max_tile_size),
       pending_raster_queries_(pending_raster_queries),
-      random_generator_(static_cast<uint32_t>(base::RandUint64())),
-      bernoulli_distribution_(raster_metric_probability),
+      raster_metric_probability_(raster_metric_probability),
       is_using_raw_draw_(features::IsUsingRawDraw()) {
   DCHECK(pending_raster_queries);
   DCHECK(compositor_context_provider);
@@ -288,8 +287,8 @@
       client_->worker_context_provider_->RasterInterface();
   DCHECK(ri);
 
-  const bool measure_raster_metric =
-      client_->bernoulli_distribution_(client_->random_generator_);
+  const bool measure_raster_metric = client_->metrics_subsampler_.ShouldSample(
+      client_->raster_metric_probability_);
 
   gfx::Rect playback_rect = raster_full_rect;
   if (resource_has_previous_content_) {
diff --git a/cc/raster/gpu_raster_buffer_provider.h b/cc/raster/gpu_raster_buffer_provider.h
index f8ca6f9..30eb7a0 100644
--- a/cc/raster/gpu_raster_buffer_provider.h
+++ b/cc/raster/gpu_raster_buffer_provider.h
@@ -7,10 +7,10 @@
 
 #include <stdint.h>
 #include <memory>
-#include <random>
 #include <vector>
 
 #include "base/memory/raw_ptr.h"
+#include "base/rand_util.h"
 #include "base/time/time.h"
 #include "cc/raster/raster_buffer_provider.h"
 #include "cc/raster/raster_query_queue.h"
@@ -145,9 +145,9 @@
 
   const raw_ptr<RasterQueryQueue> pending_raster_queries_;
 
+  const double raster_metric_probability_;
   // Accessed with the worker context lock acquired.
-  std::mt19937 random_generator_;
-  std::bernoulli_distribution bernoulli_distribution_;
+  base::MetricsSubSampler metrics_subsampler_;
   const bool is_using_raw_draw_;
 };
 
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index c4e6223..15f0982 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -3106,6 +3106,7 @@
                              "data_deps",
                              "enable_lint",
                              "enforce_resource_overlays_in_tests",
+                             "extra_args",
                              "shared_libraries",
                            ])
 
@@ -3289,6 +3290,15 @@
     "//chrome/test/android/chrome_public_test_support:chrome_public_test_support_apk",
     "//components/media_router/test/android/media_router_test_support:media_router_test_support_apk",
   ]
+
+  # TrustedWebActivityClientTest relies on sending a browsable Intent to an
+  # ActivityWithDeepLink. On Android S+, for an app to receive a browsable
+  # Intent it must have Digital Asset Link verification set up. This command
+  # will associate the given package with the given website.
+  extra_args = [
+    "--approve-app-links",
+    "org.chromium.chrome.tests.support:www.example.com",
+  ]
 }
 
 if (enable_vr) {
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java
index f731031..74e8fb2c 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java
@@ -40,9 +40,7 @@
 import org.chromium.components.autofill_assistant.infobox.AssistantInfoBoxModel;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
-/**
- * Tests for the Autofill Assistant infobox.
- */
+/** Tests for the Autofill Assistant infobox. */
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RunWith(ChromeJUnit4ClassRunner.class)
 public class AutofillAssistantInfoBoxUiTest {
@@ -135,10 +133,26 @@
 
     @Test
     @MediumTest
-    public void testVisibility() throws Exception {
+    public void hideIfEmpty() throws Exception {
         AssistantInfoBoxModel model = createModel();
         AssistantInfoBoxCoordinator coordinator = createCoordinator(model);
-        AssistantInfoBox infoBox = new AssistantInfoBox("", "");
+
+        TestThreadUtils.runOnUiThreadBlocking(()
+                                                      -> model.set(AssistantInfoBoxModel.INFO_BOX,
+                                                              new AssistantInfoBox("", "Message")));
+        onView(is(coordinator.getView())).check(matches(isDisplayed()));
+
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> model.set(AssistantInfoBoxModel.INFO_BOX, new AssistantInfoBox("", "")));
+        onView(is(coordinator.getView())).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    @MediumTest
+    public void hideIfNull() throws Exception {
+        AssistantInfoBoxModel model = createModel();
+        AssistantInfoBoxCoordinator coordinator = createCoordinator(model);
+        AssistantInfoBox infoBox = new AssistantInfoBox("Message", "");
 
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantInfoBoxModel.INFO_BOX, infoBox));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherImpl.java
index f3387f5..5935d6d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherImpl.java
@@ -8,6 +8,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
+import android.os.SystemClock;
 import android.provider.Browser;
 import android.text.TextUtils;
 
@@ -15,6 +16,7 @@
 
 import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.AppHooks;
@@ -88,10 +90,8 @@
     public void show(final Activity activity, final String helpContext, Profile profile,
             @Nullable String url) {
         RecordUserAction.record("MobileHelpAndFeedback");
-        new ChromeFeedbackCollector(activity, null /* categoryTag */, null /* description */,
-                new ScreenshotTask(activity),
-                new ChromeFeedbackCollector.InitParams(profile, url, helpContext),
-                collector -> show(activity, helpContext, collector), profile);
+        showFeedback(activity, profile, url, /* categoryTag= */ null, ScreenshotMode.DEFAULT,
+                helpContext);
     }
 
     /**
@@ -109,10 +109,17 @@
     public void showFeedback(final Activity activity, Profile profile, @Nullable String url,
             @Nullable final String categoryTag, @ScreenshotMode int screenshotMode,
             @Nullable final String feedbackContext) {
+        long startTime = SystemClock.elapsedRealtime();
         new ChromeFeedbackCollector(activity, categoryTag, null /* description */,
                 new ScreenshotTask(activity, screenshotMode),
                 new ChromeFeedbackCollector.InitParams(profile, url, feedbackContext),
-                collector -> showFeedback(activity, collector), profile);
+                (collector)
+                        -> {
+                    RecordHistogram.recordLongTimesHistogram("Feedback.Duration.FormOpenToSubmit",
+                            SystemClock.elapsedRealtime() - startTime);
+                    showFeedback(activity, collector);
+                },
+                profile);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
index ffde7c2..b81e01c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
@@ -99,7 +99,7 @@
 import org.chromium.chrome.browser.ui.appmenu.AppMenuHandler;
 import org.chromium.chrome.browser.ui.default_browser_promo.DefaultBrowserPromoUtils;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
-import org.chromium.chrome.browser.ui.signin.SigninPromoUtil;
+import org.chromium.chrome.browser.ui.signin.FullScreenSyncPromoUtil;
 import org.chromium.chrome.browser.ui.system.StatusBarColorController.StatusBarColorProvider;
 import org.chromium.chrome.browser.ui.tablet.emptybackground.EmptyBackgroundViewWrapper;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
@@ -848,7 +848,7 @@
 
     private boolean maybeShowPromo() {
         // Only one promo can be shown in one run to avoid nagging users too much.
-        if (SigninPromoUtil.launchSigninPromoIfNeeded(mActivity,
+        if (FullScreenSyncPromoUtil.launchPromoIfNeeded(mActivity,
                     SyncConsentActivityLauncherImpl.get(), VersionInfo.getProductMajorVersion())) {
             return true;
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/RunningInChromeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/RunningInChromeTest.java
index 4f9f83b4..0befabe 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/RunningInChromeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/RunningInChromeTest.java
@@ -34,7 +34,6 @@
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.CriteriaHelper;
-import org.chromium.base.test.util.FlakyTest;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
@@ -131,7 +130,6 @@
 
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/1164424")
     public void showsNewRunningInChrome() throws TimeoutException {
         launch(createTrustedWebActivityIntent(mTestPage));
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
index 0762567..bdaf7d18 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
@@ -58,6 +58,10 @@
  * 2. This calls through to TestTrustedWebActivityService.
  * 3. This calls a method on MessengerService.
  * 4. This sends a Message to ResponseHandler in this class.
+ *
+ * In order for this test to work on Android S+, Digital Asset Link verification must pass for
+ * org.chromium.chrome.tests.support and www.example.com. This is accomplished with the
+ * `--approve-app-links` command passed to the test target.
  */
 @RunWith(BaseJUnit4ClassRunner.class)
 public class TrustedWebActivityClientTest {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollectorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollectorTest.java
index 0466731..b309539 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollectorTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollectorTest.java
@@ -41,6 +41,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.CollectionUtil;
+import org.chromium.base.metrics.test.ShadowRecordHistogram;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -58,7 +59,7 @@
  * Test for {@link ChromeFeedbackCollector}.
  */
 @RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
+@Config(manifest = Config.NONE, shadows = {ShadowRecordHistogram.class})
 @LooperMode(LooperMode.Mode.LEGACY)
 public class ChromeFeedbackCollectorTest {
     @Rule
@@ -273,6 +274,7 @@
 
     @Before
     public void setUp() {
+        ShadowRecordHistogram.reset();
         when(mAccountInfo.getEmail()).thenReturn(ACCOUNT_IN_USE);
         IdentityServicesProvider.setInstanceForTests(mock(IdentityServicesProvider.class));
         when(IdentityServicesProvider.get().getIdentityManager(any()))
@@ -289,6 +291,23 @@
 
     @Test
     @Feature({"Feedback"})
+    public void testRecordLatencyHistogram() {
+        @SuppressWarnings("unchecked")
+        Callback<FeedbackCollector> callback = mock(Callback.class);
+
+        ChromeFeedbackCollector collector = new EmptyChromeFeedbackCollector(mActivity, mProfile,
+                null, null, null, null, null, (result) -> callback.onResult(result));
+
+        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
+        verify(callback, times(1)).onResult(any());
+
+        assertEquals(1,
+                ShadowRecordHistogram.getHistogramTotalCountForTesting(
+                        "Feedback.Duration.FetchSystemInformation"));
+    }
+
+    @Test
+    @Feature({"Feedback"})
     public void testNoMetaData() {
         @SuppressWarnings("unchecked")
         Callback<FeedbackCollector> callback = mock(Callback.class);
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 090f84e9..fe3190a 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -5434,8 +5434,6 @@
       "lacros/lacros_url_handling.h",
       "lacros/launcher_search/search_controller_lacros.cc",
       "lacros/launcher_search/search_controller_lacros.h",
-      "lacros/launcher_search/search_util.cc",
-      "lacros/launcher_search/search_util.h",
       "lacros/metrics_reporting_observer.cc",
       "lacros/metrics_reporting_observer.h",
       "lacros/net/lacros_extension_proxy_tracker.cc",
@@ -5506,6 +5504,7 @@
     deps += [
       ":dlp_policy_event_proto",
       "//chrome/browser/chromeos/extensions/vpn_provider",
+      "//chrome/browser/chromeos/launcher_search:search_util",
       "//chrome/common/chromeos/extensions",
       "//chromeos/crosapi/cpp",
       "//chromeos/crosapi/cpp:crosapi_constants",
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.cc b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.cc
index 790c1ee..0bc3e53 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.cc
+++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.cc
@@ -49,6 +49,7 @@
   registry->RegisterDictionaryPref(kAppActivatedCount);
   registry->RegisterDictionaryPref(kAppUsageTime);
   registry->RegisterDictionaryPref(kAppInputEventsKey);
+  registry->RegisterDictionaryPref(kWebsiteUsageTime);
 }
 
 // static
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics.cc b/chrome/browser/apps/app_service/metrics/website_metrics.cc
index e99282c..71a361a 100644
--- a/chrome/browser/apps/app_service/metrics/website_metrics.cc
+++ b/chrome/browser/apps/app_service/metrics/website_metrics.cc
@@ -5,9 +5,9 @@
 #include "chrome/browser/apps/app_service/metrics/website_metrics.h"
 
 #include "base/containers/contains.h"
+#include "base/json/values_util.h"
 #include "chrome/browser/apps/app_service/web_contents_app_id_utils.h"
 #include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -63,6 +63,11 @@
 
 namespace apps {
 
+constexpr char kWebsiteUsageTime[] = "app_platform_metrics.website_usage_time";
+constexpr char kRunningTimeKey[] = "time";
+constexpr char kUrlContentKey[] = "url_content";
+constexpr char kPromotableKey[] = "promotable";
+
 WebsiteMetrics::ActiveTabWebContentsObserver::ActiveTabWebContentsObserver(
     content::WebContents* contents,
     WebsiteMetrics* owner)
@@ -96,8 +101,17 @@
   owner_->OnInstallableWebAppStatusUpdated(web_contents());
 }
 
+base::Value WebsiteMetrics::UrlInfo::ConvertToValue() const {
+  base::Value usage_time_dict(base::Value::Type::DICTIONARY);
+  usage_time_dict.SetPath(kRunningTimeKey,
+                          base::TimeDeltaToValue(running_time));
+  usage_time_dict.SetIntKey(kUrlContentKey, static_cast<int>(url_content));
+  usage_time_dict.SetBoolKey(kPromotableKey, promotable);
+  return usage_time_dict;
+}
+
 WebsiteMetrics::WebsiteMetrics(Profile* profile)
-    : browser_tab_strip_tracker_(this, nullptr) {
+    : profile_(profile), browser_tab_strip_tracker_(this, nullptr) {
   BrowserList::GetInstance()->AddObserver(this);
   browser_tab_strip_tracker_.Init();
   history::HistoryService* history_service =
@@ -177,8 +191,7 @@
 }
 
 void WebsiteMetrics::OnFiveMinutes() {
-  // TODO(crbug.com/1334173): Save the usage time records to the local user
-  // perf.
+  SaveUsageTime();
 }
 
 void WebsiteMetrics::OnTwoHours() {
@@ -412,4 +425,14 @@
   it->second.is_activated = false;
 }
 
+void WebsiteMetrics::SaveUsageTime() {
+  DictionaryPrefUpdate usage_time_update(profile_->GetPrefs(),
+                                         kWebsiteUsageTime);
+  auto& dict = usage_time_update->GetDict();
+  dict.clear();
+  for (auto it : url_infos_) {
+    dict.Set(it.first.spec(), it.second.ConvertToValue());
+  }
+}
+
 }  // namespace apps
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics.h b/chrome/browser/apps/app_service/metrics/website_metrics.h
index 90fbd06..3af9b217e 100644
--- a/chrome/browser/apps/app_service/metrics/website_metrics.h
+++ b/chrome/browser/apps/app_service/metrics/website_metrics.h
@@ -12,6 +12,7 @@
 #include "base/scoped_multi_source_observation.h"
 #include "base/scoped_observation.h"
 #include "base/time/time.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/browser/ui/browser_tab_strip_tracker.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
@@ -44,6 +45,11 @@
   kMaxValue = kScope,
 };
 
+extern const char kWebsiteUsageTime[];
+extern const char kRunningTimeKey[];
+extern const char kUrlContentKey[];
+extern const char kPromotableKey[];
+
 // WebsiteMetrics monitors creation/deletion of Browser and its
 // TabStripModel to record the website usage time metrics.
 class WebsiteMetrics : public BrowserListObserver,
@@ -123,6 +129,14 @@
     UrlContent url_content = UrlContent::kUnknown;
     bool is_activated = false;
     bool promotable = false;
+
+    // Converts the struct UsageTime to base::Value, e.g.:
+    // {
+    //    "time": "3600",
+    //    "url_content": "scope",
+    //    "promotable": "false",
+    // }
+    base::Value ConvertToValue() const;
   };
 
   void OnTabStripModelChangeInsert(TabStripModel* tab_strip_model,
@@ -167,6 +181,12 @@
 
   void SetTabInActivated(content::WebContents* web_contents);
 
+  // Saves the website usage time in `url_infos_` to the user pref each 5
+  // minutes.
+  void SaveUsageTime();
+
+  const raw_ptr<Profile> profile_;
+
   BrowserTabStripTracker browser_tab_strip_tracker_;
 
   // The map from the window to the active tab contents.
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics_browsertest.cc b/chrome/browser/apps/app_service/metrics/website_metrics_browsertest.cc
index eba951d51..cf57b60 100644
--- a/chrome/browser/apps/app_service/metrics/website_metrics_browsertest.cc
+++ b/chrome/browser/apps/app_service/metrics/website_metrics_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/containers/contains.h"
+#include "base/json/values_util.h"
 #include "base/run_loop.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
@@ -25,6 +26,7 @@
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
+#include "services/preferences/public/cpp/dictionary_value_update.h"
 
 namespace apps {
 
@@ -170,6 +172,24 @@
     EXPECT_EQ(promotable, url_infos()[url].promotable);
   }
 
+  void VerifyUrlInfoInPref(const GURL& url,
+                           UrlContent url_content,
+                           bool promotable) {
+    DictionaryPrefUpdate update(
+        ProfileManager::GetPrimaryUserProfile()->GetPrefs(), kWebsiteUsageTime);
+    auto& dict = update->GetDict();
+
+    const auto* url_info = dict.FindDict(url.spec());
+    ASSERT_TRUE(url_info);
+    auto url_content_value = url_info->FindInt(kUrlContentKey);
+    ASSERT_TRUE(url_content_value.has_value());
+    EXPECT_EQ(static_cast<int>(url_content), url_content_value.value());
+
+    auto promotable_value = url_info->FindBool(kPromotableKey);
+    ASSERT_TRUE(promotable_value.has_value());
+    EXPECT_EQ(promotable, promotable_value.value());
+  }
+
   WebsiteMetrics* website_metrics() {
     DCHECK(app_platform_metrics_service_);
     return app_platform_metrics_service_->website_metrics_.get();
@@ -274,6 +294,13 @@
   EXPECT_EQ(3u, url_infos().size());
   VerifyUrlInfo(GURL("https://b.example.org"), UrlContent::kFullUrl,
                 /*is_activated=*/false, /*promotable=*/false);
+  website_metrics()->OnFiveMinutes();
+  VerifyUrlInfoInPref(GURL("https://b.example.org"), UrlContent::kFullUrl,
+                      /*promotable=*/false);
+  VerifyUrlInfoInPref(GURL("https://c.example.org"), UrlContent::kFullUrl,
+                      /*promotable=*/false);
+  VerifyUrlInfoInPref(GURL("https://d.example.org"), UrlContent::kFullUrl,
+                      /*promotable=*/false);
 
   // Simulate recording the UKMs to clear the local usage time records.
   website_metrics()->OnTwoHours();
@@ -321,6 +348,11 @@
                 /*is_activated=*/false, /*promotable=*/false);
   VerifyUrlInfo(GURL("https://b.example.org"), UrlContent::kFullUrl,
                 /*is_activated=*/false, /*promotable=*/false);
+  website_metrics()->OnFiveMinutes();
+  VerifyUrlInfoInPref(GURL("https://a.example.org"), UrlContent::kFullUrl,
+                      /*promotable=*/false);
+  VerifyUrlInfoInPref(GURL("https://b.example.org"), UrlContent::kFullUrl,
+                      /*promotable=*/false);
 
   // Simulate recording the UKMs to clear the local usage time records.
   website_metrics()->OnTwoHours();
@@ -377,6 +409,11 @@
                 /*is_activated=*/false, /*promotable=*/false);
   VerifyUrlInfo(ukm_key, UrlContent::kScope,
                 /*is_activated=*/false, /*promotable=*/true);
+  website_metrics()->OnFiveMinutes();
+  VerifyUrlInfoInPref(url1, UrlContent::kFullUrl,
+                      /*promotable=*/false);
+  VerifyUrlInfoInPref(ukm_key, UrlContent::kScope,
+                      /*promotable=*/true);
 
   // Simulate recording the UKMs to clear the local usage time records.
   website_metrics()->OnTwoHours();
@@ -483,6 +520,16 @@
   EXPECT_TRUE(webcontents_to_observer_map().empty());
   EXPECT_TRUE(webcontents_to_ukm_key().empty());
 
+  website_metrics()->OnFiveMinutes();
+  VerifyUrlInfoInPref(GURL("https://a.example.org"), UrlContent::kFullUrl,
+                      /*promotable=*/false);
+  VerifyUrlInfoInPref(GURL("https://b.example.org"), UrlContent::kFullUrl,
+                      /*promotable=*/false);
+  VerifyUrlInfoInPref(GURL("https://c.example.org"), UrlContent::kFullUrl,
+                      /*promotable=*/false);
+  VerifyUrlInfoInPref(GURL("https://d.example.org"), UrlContent::kFullUrl,
+                      /*promotable=*/false);
+
   // Simulate recording the UKMs to clear the local usage time records.
   website_metrics()->OnTwoHours();
   EXPECT_TRUE(url_infos().empty());
@@ -536,6 +583,11 @@
                 /*is_activated=*/false, /*promotable=*/false);
   VerifyUrlInfo(GURL("https://b.example.org"), UrlContent::kFullUrl,
                 /*is_activated=*/true, /*promotable=*/false);
+  website_metrics()->OnFiveMinutes();
+  VerifyUrlInfoInPref(GURL("https://a.example.org"), UrlContent::kFullUrl,
+                      /*promotable=*/false);
+  VerifyUrlInfoInPref(GURL("https://b.example.org"), UrlContent::kFullUrl,
+                      /*promotable=*/false);
 
   // Simulate OnURLsDeleted is called.
   website_metrics()->OnURLsDeleted(nullptr,
@@ -562,6 +614,11 @@
                 /*is_activated=*/false, /*promotable=*/false);
   VerifyUrlInfo(GURL("https://d.example.org"), UrlContent::kFullUrl,
                 /*is_activated=*/true, /*promotable=*/false);
+  website_metrics()->OnFiveMinutes();
+  VerifyUrlInfoInPref(GURL("https://c.example.org"), UrlContent::kFullUrl,
+                      /*promotable=*/false);
+  VerifyUrlInfoInPref(GURL("https://d.example.org"), UrlContent::kFullUrl,
+                      /*promotable=*/false);
 
   // Close the browsers.
   browser1->tab_strip_model()->CloseAllTabs();
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index ec2a7c4..73eea19 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -2264,6 +2264,7 @@
     "//chromeos/ash/components/dbus/cups_proxy",
     "//chromeos/ash/components/dbus/federated",
     "//chromeos/ash/components/dbus/fusebox",
+    "//chromeos/ash/components/dbus/human_presence",
     "//chromeos/ash/components/dbus/ip_peripheral",
     "//chromeos/ash/components/dbus/kerberos",
     "//chromeos/ash/components/dbus/lorgnette_manager",
@@ -2272,6 +2273,7 @@
     "//chromeos/ash/components/dbus/pciguard",
     "//chromeos/ash/components/dbus/rgbkbd",
     "//chromeos/ash/components/dbus/rmad",
+    "//chromeos/ash/components/dbus/smbprovider",
     "//chromeos/ash/components/dbus/spaced",
     "//chromeos/ash/components/dbus/system_proxy",
     "//chromeos/ash/components/dbus/typecd",
@@ -2302,14 +2304,12 @@
     "//chromeos/dbus/dlp:dlp_proto",
     "//chromeos/dbus/easy_unlock",
     "//chromeos/dbus/hermes",
-    "//chromeos/dbus/human_presence",
     "//chromeos/dbus/image_loader",
     "//chromeos/dbus/init",
     "//chromeos/dbus/machine_learning",
     "//chromeos/dbus/oobe_config",
     "//chromeos/dbus/permission_broker",
     "//chromeos/dbus/shill",
-    "//chromeos/dbus/smbprovider",
     "//chromeos/dbus/u2f",
     "//chromeos/dbus/util",
     "//chromeos/ime:gencode",
diff --git a/chrome/browser/ash/borealis/borealis_game_mode_controller.cc b/chrome/browser/ash/borealis/borealis_game_mode_controller.cc
index b569af6..39934d997 100644
--- a/chrome/browser/ash/borealis/borealis_game_mode_controller.cc
+++ b/chrome/browser/ash/borealis/borealis_game_mode_controller.cc
@@ -94,7 +94,7 @@
   RecordBorealisGameModeResultHistogram(BorealisGameModeResult::kAttempted);
   if (chromeos::ResourcedClient::Get()) {
     chromeos::ResourcedClient::Get()->SetGameModeWithTimeout(
-        true, kTimeoutSec,
+        chromeos::ResourcedClient::GameMode::BOREALIS, kTimeoutSec,
         base::BindOnce(&GameModeEnabler::OnSetGameMode, false));
   }
   timer_.Start(FROM_HERE, base::Seconds(kRefreshSec), this,
@@ -105,14 +105,15 @@
   timer_.Stop();
   if (chromeos::ResourcedClient::Get()) {
     chromeos::ResourcedClient::Get()->SetGameModeWithTimeout(
-        false, 0, base::BindOnce(&GameModeEnabler::OnSetGameMode, true));
+        chromeos::ResourcedClient::GameMode::OFF, 0,
+        base::BindOnce(&GameModeEnabler::OnSetGameMode, true));
   }
 }
 
 void BorealisGameModeController::GameModeEnabler::RefreshGameMode() {
   if (chromeos::ResourcedClient::Get()) {
     chromeos::ResourcedClient::Get()->SetGameModeWithTimeout(
-        true, kTimeoutSec,
+        chromeos::ResourcedClient::GameMode::BOREALIS, kTimeoutSec,
         base::BindOnce(&GameModeEnabler::OnSetGameMode, true));
   }
 }
@@ -120,11 +121,12 @@
 // Previous is whether game mode was enabled previous to this call.
 void BorealisGameModeController::GameModeEnabler::OnSetGameMode(
     bool was_refresh,
-    absl::optional<bool> previous) {
+    absl::optional<chromeos::ResourcedClient::GameMode> previous) {
   if (!previous.has_value()) {
     LOG(ERROR) << "Failed to set Game Mode";
   } else if (GameModeEnabler::should_record_failure && was_refresh &&
-             !previous.value()) {
+             previous.value() !=
+                 chromeos::ResourcedClient::GameMode::BOREALIS) {
     // If game mode was not on and it was not the initial call,
     // it means the previous call failed/timed out.
     RecordBorealisGameModeResultHistogram(BorealisGameModeResult::kFailed);
diff --git a/chrome/browser/ash/borealis/borealis_game_mode_controller.h b/chrome/browser/ash/borealis/borealis_game_mode_controller.h
index 93ed6a63..015a097 100644
--- a/chrome/browser/ash/borealis/borealis_game_mode_controller.h
+++ b/chrome/browser/ash/borealis/borealis_game_mode_controller.h
@@ -47,7 +47,9 @@
     ~GameModeEnabler();
 
    private:
-    static void OnSetGameMode(bool was_refresh, absl::optional<bool> previous);
+    static void OnSetGameMode(
+        bool was_refresh,
+        absl::optional<chromeos::ResourcedClient::GameMode> previous);
     void RefreshGameMode();
 
     // Used to determine if it's the first instance of game mode failing.
diff --git a/chrome/browser/ash/borealis/borealis_game_mode_controller_unittest.cc b/chrome/browser/ash/borealis/borealis_game_mode_controller_unittest.cc
index 1cbfa10..046cf28 100644
--- a/chrome/browser/ash/borealis/borealis_game_mode_controller_unittest.cc
+++ b/chrome/browser/ash/borealis/borealis_game_mode_controller_unittest.cc
@@ -128,7 +128,7 @@
 
 TEST_F(BorealisGameModeControllerTest, SetGameModeFailureDoesNotCrash) {
   fake_resourced_client_->set_set_game_mode_with_timeout_response(
-      absl::optional<bool>(absl::nullopt));
+      absl::nullopt);
   std::unique_ptr<views::Widget> test_widget =
       CreateFakeWidget("org.chromium.borealis.foo", true);
   aura::Window* window = test_widget->GetNativeWindow();
@@ -166,7 +166,8 @@
                                        BorealisGameModeResult::kFailed, 0);
 
   // Previous game mode timed out/failed followed by refresh.
-  fake_resourced_client_->set_set_game_mode_with_timeout_response(false);
+  fake_resourced_client_->set_set_game_mode_with_timeout_response(
+      chromeos::ResourcedClient::GameMode::OFF);
   task_environment()->FastForwardBy(base::Seconds(61));
   EXPECT_EQ(3, fake_resourced_client_->get_enter_game_mode_count());
   histogram_tester_->ExpectBucketCount(kBorealisGameModeResultHistogram,
@@ -176,7 +177,8 @@
 
   // Previous game mode timed out/failed followed by exit.
   // Should not record to histogram as it was already recorded above.
-  fake_resourced_client_->set_set_game_mode_with_timeout_response(false);
+  fake_resourced_client_->set_set_game_mode_with_timeout_response(
+      chromeos::ResourcedClient::GameMode::OFF);
   test_widget->SetFullscreen(false);
   EXPECT_FALSE(ash::WindowState::Get(window)->IsFullscreen());
   EXPECT_EQ(1, fake_resourced_client_->get_exit_game_mode_count());
diff --git a/chrome/browser/ash/crosapi/test_controller_ash.cc b/chrome/browser/ash/crosapi/test_controller_ash.cc
index 366fe177..f3f48b0 100644
--- a/chrome/browser/ash/crosapi/test_controller_ash.cc
+++ b/chrome/browser/ash/crosapi/test_controller_ash.cc
@@ -32,6 +32,8 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/views/tabs/tab_scrubber_chromeos.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_profile_client.h"
 #include "chromeos/dbus/shill/shill_third_party_vpn_driver_client.h"
 #include "components/version_info/version_info.h"
@@ -514,6 +516,38 @@
 #endif  // defined(USE_CUPS)
 }
 
+void TestControllerAsh::BindShillClientTestInterface(
+    mojo::PendingReceiver<crosapi::mojom::ShillClientTestInterface> receiver,
+    BindShillClientTestInterfaceCallback callback) {
+  mojo::MakeSelfOwnedReceiver<crosapi::mojom::ShillClientTestInterface>(
+      std::make_unique<crosapi::ShillClientTestInterfaceAsh>(),
+      std::move(receiver));
+  std::move(callback).Run();
+}
+
+void TestControllerAsh::GetSanitizedActiveUsername(
+    GetSanitizedActiveUsernameCallback callback) {
+  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
+  user_manager::User* user = user_manager->GetActiveUser();
+  CHECK(user);
+
+  ::user_data_auth::GetSanitizedUsernameRequest request;
+
+  request.set_username(
+      cryptohome::CreateAccountIdentifierFromAccountId(user->GetAccountId())
+          .account_id());
+  ash::CryptohomeMiscClient::Get()->GetSanitizedUsername(
+      request,
+      base::BindOnce(
+          [](GetSanitizedActiveUsernameCallback callback,
+             absl::optional<::user_data_auth::GetSanitizedUsernameReply>
+                 result) {
+            CHECK(result.has_value());
+            std::move(callback).Run(result->sanitized_username());
+          },
+          std::move(callback)));
+}
+
 // This class waits for overview mode to either enter or exit and fires a
 // callback. This class will fire the callback at most once.
 class TestControllerAsh::OverviewWaiter : public ash::OverviewObserver {
@@ -605,4 +639,100 @@
   client->OnPlatformMessage(shill_key, message);
 }
 
+////////////
+// ShillClientTestInterfaceAsh
+
+ShillClientTestInterfaceAsh::ShillClientTestInterfaceAsh() = default;
+ShillClientTestInterfaceAsh::~ShillClientTestInterfaceAsh() = default;
+
+void ShillClientTestInterfaceAsh::AddDevice(const std::string& device_path,
+                                            const std::string& type,
+                                            const std::string& name,
+                                            AddDeviceCallback callback) {
+  auto* device_test = chromeos::ShillDeviceClient::Get()->GetTestInterface();
+  device_test->AddDevice(device_path, type, name);
+  std::move(callback).Run();
+}
+
+void ShillClientTestInterfaceAsh::ClearDevices(ClearDevicesCallback callback) {
+  auto* device_test = chromeos::ShillDeviceClient::Get()->GetTestInterface();
+  device_test->ClearDevices();
+  std::move(callback).Run();
+}
+
+void ShillClientTestInterfaceAsh::SetDeviceProperty(
+    const std::string& device_path,
+    const std::string& name,
+    ::base::Value value,
+    bool notify_changed,
+    SetDevicePropertyCallback callback) {
+  auto* device_test = chromeos::ShillDeviceClient::Get()->GetTestInterface();
+  device_test->SetDeviceProperty(device_path, name, value, notify_changed);
+  std::move(callback).Run();
+}
+
+void ShillClientTestInterfaceAsh::SetSimLocked(const std::string& device_path,
+                                               bool enabled,
+                                               SetSimLockedCallback callback) {
+  auto* device_test = chromeos::ShillDeviceClient::Get()->GetTestInterface();
+  device_test->SetSimLocked(device_path, enabled);
+  std::move(callback).Run();
+}
+
+void ShillClientTestInterfaceAsh::AddService(
+    const std::string& service_path,
+    const std::string& guid,
+    const std::string& name,
+    const std::string& type,
+    const std::string& state,
+    bool visible,
+    SetDevicePropertyCallback callback) {
+  auto* service_test = chromeos::ShillServiceClient::Get()->GetTestInterface();
+  service_test->AddService(service_path, guid, name, type, state, visible);
+  std::move(callback).Run();
+}
+
+void ShillClientTestInterfaceAsh::ClearServices(
+    ClearServicesCallback callback) {
+  auto* service_test = chromeos::ShillServiceClient::Get()->GetTestInterface();
+  service_test->ClearServices();
+  std::move(callback).Run();
+}
+
+void ShillClientTestInterfaceAsh::SetServiceProperty(
+    const std::string& service_path,
+    const std::string& property,
+    base::Value value,
+    SetServicePropertyCallback callback) {
+  auto* service_test = chromeos::ShillServiceClient::Get()->GetTestInterface();
+  service_test->SetServiceProperty(service_path, property, value);
+  std::move(callback).Run();
+}
+
+void ShillClientTestInterfaceAsh::AddProfile(const std::string& profile_path,
+                                             const std::string& userhash,
+                                             AddProfileCallback callback) {
+  auto* profile_test = chromeos::ShillProfileClient::Get()->GetTestInterface();
+  profile_test->AddProfile(profile_path, userhash);
+  std::move(callback).Run();
+}
+
+void ShillClientTestInterfaceAsh::AddServiceToProfile(
+    const std::string& profile_path,
+    const std::string& service_path,
+    AddServiceToProfileCallback callback) {
+  auto* profile_test = chromeos::ShillProfileClient::Get()->GetTestInterface();
+  profile_test->AddService(profile_path, service_path);
+  std::move(callback).Run();
+}
+
+void ShillClientTestInterfaceAsh::AddIPConfig(const std::string& ip_config_path,
+                                              ::base::Value properties,
+                                              AddIPConfigCallback callback) {
+  auto* ip_config_test =
+      chromeos::ShillIPConfigClient::Get()->GetTestInterface();
+  ip_config_test->AddIPConfig(ip_config_path, properties);
+  std::move(callback).Run();
+}
+
 }  // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/test_controller_ash.h b/chrome/browser/ash/crosapi/test_controller_ash.h
index 9c36a59..3faae57 100644
--- a/chrome/browser/ash/crosapi/test_controller_ash.h
+++ b/chrome/browser/ash/crosapi/test_controller_ash.h
@@ -85,6 +85,13 @@
       const std::string& job_title,
       CreateAndCancelPrintJobCallback callback) override;
 
+  void BindShillClientTestInterface(
+      mojo::PendingReceiver<crosapi::mojom::ShillClientTestInterface> receiver,
+      BindShillClientTestInterfaceCallback callback) override;
+
+  void GetSanitizedActiveUsername(
+      GetSanitizedActiveUsernameCallback callback) override;
+
   mojo::Remote<mojom::StandaloneBrowserTestController>&
   GetStandaloneBrowserTestController() {
     DCHECK(standalone_browser_test_controller_.is_bound());
@@ -141,6 +148,51 @@
                          uint32_t message) override;
 };
 
+class ShillClientTestInterfaceAsh
+    : public crosapi::mojom::ShillClientTestInterface {
+ public:
+  ShillClientTestInterfaceAsh();
+  ~ShillClientTestInterfaceAsh() override;
+
+  void AddDevice(const std::string& device_path,
+                 const std::string& type,
+                 const std::string& name,
+                 AddDeviceCallback callback) override;
+  void ClearDevices(ClearDevicesCallback callback) override;
+  void SetDeviceProperty(const std::string& device_path,
+                         const std::string& name,
+                         ::base::Value value,
+                         bool notify_changed,
+                         SetDevicePropertyCallback callback) override;
+  void SetSimLocked(const std::string& device_path,
+                    bool enabled,
+                    SetSimLockedCallback callback) override;
+
+  void AddService(const std::string& service_path,
+                  const std::string& guid,
+                  const std::string& name,
+                  const std::string& type,
+                  const std::string& state,
+                  bool visible,
+                  AddServiceCallback callback) override;
+  void ClearServices(ClearServicesCallback callback) override;
+  void SetServiceProperty(const std::string& service_path,
+                          const std::string& property,
+                          base::Value value,
+                          SetServicePropertyCallback callback) override;
+
+  void AddProfile(const std::string& profile_path,
+                  const std::string& userhash,
+                  AddProfileCallback callback) override;
+  void AddServiceToProfile(const std::string& profile_path,
+                           const std::string& service_path,
+                           AddServiceToProfileCallback callback) override;
+
+  void AddIPConfig(const std::string& ip_config_path,
+                   ::base::Value properties,
+                   AddIPConfigCallback callback) override;
+};
+
 }  // namespace crosapi
 
 #endif  // CHROME_BROWSER_ASH_CROSAPI_TEST_CONTROLLER_ASH_H_
diff --git a/chrome/browser/ash/dbus/ash_dbus_helper.cc b/chrome/browser/ash/dbus/ash_dbus_helper.cc
index d476a6b7..036f099 100644
--- a/chrome/browser/ash/dbus/ash_dbus_helper.cc
+++ b/chrome/browser/ash/dbus/ash_dbus_helper.cc
@@ -27,6 +27,7 @@
 #include "chromeos/ash/components/dbus/cups_proxy/cups_proxy_client.h"
 #include "chromeos/ash/components/dbus/federated/federated_client.h"
 #include "chromeos/ash/components/dbus/fusebox/fusebox_reverse_client.h"
+#include "chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h"
 #include "chromeos/ash/components/dbus/ip_peripheral/ip_peripheral_service_client.h"
 #include "chromeos/ash/components/dbus/kerberos/kerberos_client.h"
 #include "chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client.h"
@@ -38,6 +39,7 @@
 #include "chromeos/ash/components/dbus/rmad/rmad_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
+#include "chromeos/ash/components/dbus/smbprovider/smb_provider_client.h"
 #include "chromeos/ash/components/dbus/spaced/spaced_client.h"
 #include "chromeos/ash/components/dbus/system_clock/system_clock_client.h"
 #include "chromeos/ash/components/dbus/system_proxy/system_proxy_client.h"
@@ -62,7 +64,6 @@
 #include "chromeos/dbus/dlcservice/dlcservice_client.h"
 #include "chromeos/dbus/dlp/dlp_client.h"
 #include "chromeos/dbus/hermes/hermes_clients.h"
-#include "chromeos/dbus/human_presence/human_presence_dbus_client.h"
 #include "chromeos/dbus/image_loader/image_loader_client.h"
 #include "chromeos/dbus/init/initialize_dbus_client.h"
 #include "chromeos/dbus/machine_learning/machine_learning_client.h"
@@ -72,7 +73,6 @@
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/resourced/resourced_client.h"
 #include "chromeos/dbus/runtime_probe/runtime_probe_client.h"
-#include "chromeos/dbus/smbprovider/smb_provider_client.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
 #include "chromeos/dbus/u2f/u2f_client.h"
 #include "device/bluetooth/dbus/bluez_dbus_manager.h"
@@ -208,7 +208,7 @@
 
   if (ash::features::IsSnoopingProtectionEnabled() ||
       ash::features::IsQuickDimEnabled()) {
-    InitializeDBusClient<chromeos::HumanPresenceDBusClient>(bus);
+    InitializeDBusClient<HumanPresenceDBusClient>(bus);
   }
 }
 
@@ -217,7 +217,7 @@
   // shut down in reverse order of initialization (in case of dependencies).
   if (ash::features::IsSnoopingProtectionEnabled() ||
       ash::features::IsQuickDimEnabled()) {
-    chromeos::HumanPresenceDBusClient::Shutdown();
+    HumanPresenceDBusClient::Shutdown();
   }
   chromeos::WilcoDtcSupportdClient::Shutdown();
 #if BUILDFLAG(PLATFORM_CFM)
diff --git a/chrome/browser/ash/login/oobe_browsertest.cc b/chrome/browser/ash/login/oobe_browsertest.cc
index cd7deb68..4c49ebf 100644
--- a/chrome/browser/ash/login/oobe_browsertest.cc
+++ b/chrome/browser/ash/login/oobe_browsertest.cc
@@ -17,6 +17,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/ash/login/login_pref_names.h"
 #include "chrome/browser/ash/login/test/fake_gaia_mixin.h"
+#include "chrome/browser/ash/login/test/feature_parameter_interface.h"
 #include "chrome/browser/ash/login/test/local_state_mixin.h"
 #include "chrome/browser/ash/login/test/oobe_base_test.h"
 #include "chrome/browser/ash/login/test/oobe_screen_waiter.h"
@@ -55,17 +56,9 @@
 
 namespace ash {
 
-class OobeTest : public OobeBaseTest, public testing::WithParamInterface<bool> {
+class OobeTest : public OobeBaseTest, public FeatureAsParameterInterface<1> {
  public:
-  OobeTest() : is_auth_session_enabled_(GetParam()) {
-    if (is_auth_session_enabled_) {
-      scoped_feature_list_.InitAndEnableFeature(
-          features::kUseAuthsessionAuthentication);
-    } else {
-      scoped_feature_list_.InitAndDisableFeature(
-          features::kUseAuthsessionAuthentication);
-    }
-  }
+  OobeTest() = default;
 
   OobeTest(const OobeTest&) = delete;
   OobeTest& operator=(const OobeTest&) = delete;
@@ -98,12 +91,8 @@
         ->login_window_for_test();
   }
 
- protected:
-  bool is_auth_session_enabled_;
-
  private:
   FakeGaiaMixin fake_gaia_{&mixin_host_};
-  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 IN_PROC_BROWSER_TEST_P(OobeTest, NewUser) {
@@ -129,7 +118,8 @@
   // Create does not make sense in the context of AuthSession,
   // so we only check passed params when AuthSession feature
   // is disabled.
-  if (!is_auth_session_enabled_) {
+  if (!IsFeatureEnabledInThisTestCase(
+          features::kUseAuthsessionAuthentication)) {
     // Key that was passed as mount authentication does not actually matter,
     // but checking it for the sake of completeness.
     const cryptohome::AuthorizationRequest& cryptohome_auth =
@@ -172,6 +162,14 @@
   OobeScreenWaiter(EnrollmentScreenView::kScreenId).Wait();
 }
 
+const auto kAllFeatureVariations = FeatureAsParameterInterface<1>::Generator(
+    {&features::kUseAuthsessionAuthentication});
+
+INSTANTIATE_TEST_SUITE_P(All,
+                         OobeTest,
+                         testing::ValuesIn(kAllFeatureVariations),
+                         FeatureAsParameterInterface<1>::ParamInfoToString);
+
 // Checks that update screen is shown with both legacy and actual name stored
 // in the local state.
 class PendingUpdateScreenTest
@@ -272,6 +270,4 @@
   EXPECT_EQ(display.height(), 1440);
 }
 
-INSTANTIATE_TEST_SUITE_P(All, OobeTest, testing::Bool());
-
 }  // namespace ash
diff --git a/chrome/browser/ash/login/saml/in_session_password_sync_manager.cc b/chrome/browser/ash/login/saml/in_session_password_sync_manager.cc
index f61f5a9..a517dac 100644
--- a/chrome/browser/ash/login/saml/in_session_password_sync_manager.cc
+++ b/chrome/browser/ash/login/saml/in_session_password_sync_manager.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/ash/login/profile_auth_data.h"
 #include "chrome/browser/ash/login/saml/in_session_password_change_manager.h"
 #include "chrome/browser/ash/login/saml/password_sync_token_fetcher.h"
+#include "chrome/browser/ash/login/screens/network_error.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/ash/settings/cros_settings.h"
 #include "chrome/browser/browser_process.h"
@@ -306,4 +307,11 @@
   }
 }
 
+void InSessionPasswordSyncManager::OnWebviewLoadAborted() {
+  if (lock_screen_start_reauth_dialog_) {
+    lock_screen_start_reauth_dialog_->UpdateState(
+        NetworkError::ERROR_REASON_FRAME_ERROR);
+  }
+}
+
 }  // namespace ash
diff --git a/chrome/browser/ash/login/saml/in_session_password_sync_manager.h b/chrome/browser/ash/login/saml/in_session_password_sync_manager.h
index 8f516ba0..3561aff 100644
--- a/chrome/browser/ash/login/saml/in_session_password_sync_manager.h
+++ b/chrome/browser/ash/login/saml/in_session_password_sync_manager.h
@@ -123,6 +123,9 @@
   // Notify test that the reauth dialog is ready for testing.
   void OnReauthDialogReadyForTesting();
 
+  // Forces network state update because webview reported frame loading error.
+  void OnWebviewLoadAborted();
+
   LockScreenStartReauthDialog* get_reauth_dialog_for_testing() {
     return lock_screen_start_reauth_dialog_.get();
   }
diff --git a/chrome/browser/ash/login/saml/saml_lockscreen_browsertest.cc b/chrome/browser/ash/login/saml/saml_lockscreen_browsertest.cc
index 381bee26..b730cf6f 100644
--- a/chrome/browser/ash/login/saml/saml_lockscreen_browsertest.cc
+++ b/chrome/browser/ash/login/saml/saml_lockscreen_browsertest.cc
@@ -31,6 +31,7 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_utils.h"
+#include "google_apis/gaia/gaia_urls.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -365,6 +366,30 @@
   reauth_dialog_helper->ExpectVerifyAccountScreenHidden();
 }
 
+IN_PROC_BROWSER_TEST_F(LockscreenWebUiTest, LoadAbort) {
+  Login();
+
+  // Make gaia landing page unreachable
+  fake_gaia_mixin()->fake_gaia()->SetErrorResponse(
+      GaiaUrls::GetInstance()->embedded_setup_chromeos_url(2),
+      net::HTTP_NOT_FOUND);
+
+  // Lock the screen and trigger the lock screen SAML reauth dialog.
+  ScreenLockerTester().Lock();
+
+  absl::optional<LockScreenReauthDialogTestHelper> reauth_dialog_helper =
+      LockScreenReauthDialogTestHelper::ShowDialogAndWait();
+  ASSERT_TRUE(reauth_dialog_helper);
+
+  // Unreachable gaia page should have resulted in load abort error which should
+  // trigger the network dialog
+  reauth_dialog_helper->WaitForNetworkDialogAndSetHandlers();
+  reauth_dialog_helper->ExpectNetworkDialogVisible();
+
+  // Close dialog at the end of the test - otherwise test will crash on exit
+  reauth_dialog_helper->ClickCloseNetworkButton();
+}
+
 // Sets up proxy server which requires authentication.
 class ProxyAuthLockscreenWebUiTest : public LockscreenWebUiTest {
  public:
diff --git a/chrome/browser/ash/smb_client/discovery/netbios_host_locator.h b/chrome/browser/ash/smb_client/discovery/netbios_host_locator.h
index 61068d0..bbafb6b 100644
--- a/chrome/browser/ash/smb_client/discovery/netbios_host_locator.h
+++ b/chrome/browser/ash/smb_client/discovery/netbios_host_locator.h
@@ -13,7 +13,7 @@
 #include "base/timer/timer.h"
 #include "chrome/browser/ash/smb_client/discovery/host_locator.h"
 #include "chrome/browser/ash/smb_client/discovery/netbios_client_interface.h"
-#include "chromeos/dbus/smbprovider/smb_provider_client.h"
+#include "chromeos/ash/components/dbus/smbprovider/smb_provider_client.h"
 #include "net/base/network_interfaces.h"
 
 namespace ash {
diff --git a/chrome/browser/ash/smb_client/discovery/netbios_host_locator_unittest.cc b/chrome/browser/ash/smb_client/discovery/netbios_host_locator_unittest.cc
index f40b07f..af9e0f7 100644
--- a/chrome/browser/ash/smb_client/discovery/netbios_host_locator_unittest.cc
+++ b/chrome/browser/ash/smb_client/discovery/netbios_host_locator_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/timer/timer.h"
 #include "chrome/browser/ash/smb_client/discovery/fake_netbios_client.h"
 #include "chrome/browser/ash/smb_client/smb_constants.h"
-#include "chromeos/dbus/smbprovider/fake_smb_provider_client.h"
+#include "chromeos/ash/components/dbus/smbprovider/fake_smb_provider_client.h"
 #include "net/base/ip_endpoint.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ash/smb_client/smb_errors.h b/chrome/browser/ash/smb_client/smb_errors.h
index c2d1b0b..16dc89f4 100644
--- a/chrome/browser/ash/smb_client/smb_errors.h
+++ b/chrome/browser/ash/smb_client/smb_errors.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_ASH_SMB_CLIENT_SMB_ERRORS_H_
 
 #include "base/files/file.h"
-#include "chromeos/dbus/smbprovider/smb_provider_client.h"
+#include "chromeos/ash/components/dbus/smbprovider/smb_provider_client.h"
 
 namespace ash {
 namespace smb_client {
diff --git a/chrome/browser/ash/smb_client/smb_errors_unittest.cc b/chrome/browser/ash/smb_client/smb_errors_unittest.cc
index 22f40099..38e1225 100644
--- a/chrome/browser/ash/smb_client/smb_errors_unittest.cc
+++ b/chrome/browser/ash/smb_client/smb_errors_unittest.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/ash/smb_client/smb_errors.h"
 
 #include "base/files/file.h"
-#include "chromeos/dbus/smbprovider/directory_entry.pb.h"
+#include "chromeos/ash/components/dbus/smbprovider/directory_entry.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
diff --git a/chrome/browser/ash/smb_client/smb_file_system.h b/chrome/browser/ash/smb_client/smb_file_system.h
index ad96541..22ecd89 100644
--- a/chrome/browser/ash/smb_client/smb_file_system.h
+++ b/chrome/browser/ash/smb_client/smb_file_system.h
@@ -19,7 +19,7 @@
 #include "chrome/browser/ash/file_system_provider/provided_file_system_interface.h"
 #include "chrome/browser/ash/file_system_provider/watcher.h"
 #include "chrome/browser/ash/smb_client/smb_service.h"
-#include "chromeos/dbus/smbprovider/smb_provider_client.h"
+#include "chromeos/ash/components/dbus/smbprovider/smb_provider_client.h"
 #include "storage/browser/file_system/async_file_util.h"
 #include "storage/browser/file_system/watcher_manager.h"
 #include "url/gurl.h"
diff --git a/chrome/browser/ash/smb_client/smb_service.cc b/chrome/browser/ash/smb_client/smb_service.cc
index 97d6776..a14cf2b 100644
--- a/chrome/browser/ash/smb_client/smb_service.cc
+++ b/chrome/browser/ash/smb_client/smb_service.cc
@@ -426,7 +426,7 @@
 }
 
 SmbProviderClient* SmbService::GetSmbProviderClient() const {
-  return chromeos::SmbProviderClient::Get();
+  return SmbProviderClient::Get();
 }
 
 void SmbService::RestoreMounts() {
diff --git a/chrome/browser/ash/smb_client/smb_service.h b/chrome/browser/ash/smb_client/smb_service.h
index ee34c87..1ea7330a 100644
--- a/chrome/browser/ash/smb_client/smb_service.h
+++ b/chrome/browser/ash/smb_client/smb_service.h
@@ -23,7 +23,7 @@
 #include "chrome/browser/ash/smb_client/smb_share_finder.h"
 #include "chrome/browser/ash/smb_client/smbfs_share.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chromeos/dbus/smbprovider/smb_provider_client.h"
+#include "chromeos/ash/components/dbus/smbprovider/smb_provider_client.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "net/base/network_change_notifier.h"
 
diff --git a/chrome/browser/ash/smb_client/smb_service_unittest.cc b/chrome/browser/ash/smb_client/smb_service_unittest.cc
index 56eaee2..a44b609 100644
--- a/chrome/browser/ash/smb_client/smb_service_unittest.cc
+++ b/chrome/browser/ash/smb_client/smb_service_unittest.cc
@@ -44,8 +44,8 @@
 #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/dbus/smbprovider/fake_smb_provider_client.h"
-#include "chromeos/dbus/smbprovider/smb_provider_client.h"
+#include "chromeos/ash/components/dbus/smbprovider/fake_smb_provider_client.h"
+#include "chromeos/ash/components/dbus/smbprovider/smb_provider_client.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "storage/browser/file_system/external_mount_points.h"
diff --git a/chrome/browser/ash/smb_client/smb_share_finder.h b/chrome/browser/ash/smb_client/smb_share_finder.h
index 1631342..3c78f1149 100644
--- a/chrome/browser/ash/smb_client/smb_share_finder.h
+++ b/chrome/browser/ash/smb_client/smb_share_finder.h
@@ -13,7 +13,7 @@
 #include "chrome/browser/ash/smb_client/discovery/host_locator.h"
 #include "chrome/browser/ash/smb_client/discovery/network_scanner.h"
 #include "chrome/browser/ash/smb_client/smb_url.h"
-#include "chromeos/dbus/smbprovider/smb_provider_client.h"
+#include "chromeos/ash/components/dbus/smbprovider/smb_provider_client.h"
 
 namespace ash {
 namespace smb_client {
diff --git a/chrome/browser/ash/smb_client/smb_share_finder_unittest.cc b/chrome/browser/ash/smb_client/smb_share_finder_unittest.cc
index 63580e12..7d51bdd2 100644
--- a/chrome/browser/ash/smb_client/smb_share_finder_unittest.cc
+++ b/chrome/browser/ash/smb_client/smb_share_finder_unittest.cc
@@ -14,7 +14,7 @@
 #include "chrome/browser/ash/smb_client/discovery/in_memory_host_locator.h"
 #include "chrome/browser/ash/smb_client/smb_constants.h"
 #include "chrome/browser/ash/smb_client/smb_url.h"
-#include "chromeos/dbus/smbprovider/fake_smb_provider_client.h"
+#include "chromeos/ash/components/dbus/smbprovider/fake_smb_provider_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
diff --git a/chrome/browser/autofill/autofill_context_menu_manager.cc b/chrome/browser/autofill/autofill_context_menu_manager.cc
index 25f541a..73dd000a 100644
--- a/chrome/browser/autofill/autofill_context_menu_manager.cc
+++ b/chrome/browser/autofill/autofill_context_menu_manager.cc
@@ -7,6 +7,8 @@
 #include <string>
 
 #include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/chrome_pages.h"
 #include "components/autofill/content/browser/content_autofill_driver.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
@@ -60,10 +62,12 @@
 AutofillContextMenuManager::AutofillContextMenuManager(
     PersonalDataManager* personal_data_manager,
     ui::SimpleMenuModel::Delegate* delegate,
-    ui::SimpleMenuModel* menu_model)
+    ui::SimpleMenuModel* menu_model,
+    Browser* browser)
     : personal_data_manager_(personal_data_manager),
       menu_model_(menu_model),
-      delegate_(delegate) {}
+      delegate_(delegate),
+      browser_(browser) {}
 
 AutofillContextMenuManager::~AutofillContextMenuManager() {
   cached_menu_models_.clear();
@@ -128,6 +132,26 @@
   if (!params.field_renderer_id)
     return;
 
+  if (it->second.is_manage_item) {
+    DCHECK(browser_);
+    switch (it->second.sub_menu_type) {
+      case SubMenuType::SUB_MENU_TYPE_ADDRESS:
+        chrome::ShowAddresses(browser_);
+        break;
+      case SubMenuType::SUB_MENU_TYPE_CREDIT_CARD:
+        chrome::ShowPaymentMethods(browser_);
+        break;
+      case SubMenuType::SUB_MENU_TYPE_PASSWORD:
+        chrome::ShowPasswordManager(browser_);
+        break;
+      case SubMenuType::NUM_SUBMENU_TYPES:
+        [[fallthrough]];
+      default:
+        NOTREACHED();
+    }
+    return;
+  }
+
   driver->RendererShouldFillFieldWithValue(
       {LocalFrameToken(render_frame_host->GetFrameToken().value()),
        FieldRendererId(params.field_renderer_id.value())},
@@ -187,6 +211,16 @@
   if (!address_added)
     return;
 
+  profile_menu->AddSeparator(ui::NORMAL_SEPARATOR);
+  absl::optional<CommandId> manage_item_command_id =
+      GetNextAvailableAutofillCommandId();
+  DCHECK(manage_item_command_id);
+  // TODO(crbug.com/1325811): Use i18n string.
+  profile_menu->AddItem(manage_item_command_id->value(), u"Manage addresses");
+  detail_items_added_to_context_menu.emplace_back(
+      *manage_item_command_id,
+      ContextMenuItem{u"", SubMenuType::SUB_MENU_TYPE_ADDRESS, true});
+
   // Add a menu option to suggest filling address in the context menu.
   // Hovering over it opens a submenu suggesting all the address profiles
   // stored in the profile.
@@ -244,6 +278,17 @@
   if (!card_added)
     return;
 
+  card_submenu->AddSeparator(ui::NORMAL_SEPARATOR);
+  absl::optional<CommandId> manage_item_command_id =
+      GetNextAvailableAutofillCommandId();
+  DCHECK(manage_item_command_id);
+  // TODO(crbug.com/1325811): Use i18n string.
+  card_submenu->AddItem(manage_item_command_id->value(),
+                        u"Manage payment methods");
+  detail_items_added_to_context_menu.emplace_back(
+      *manage_item_command_id,
+      ContextMenuItem{u"", SubMenuType::SUB_MENU_TYPE_CREDIT_CARD, true});
+
   // Add a menu option to suggest filling a credit card in the context menu.
   // Hovering over it opens a submenu suggesting all the credit cards
   // stored in the profile.
@@ -277,10 +322,12 @@
   // Check if there are enough command ids for adding all the items to the
   // context menu.
   // 1 is added to count for the address/credit card description.
-  if (!IsAutofillCustomCommandId(CommandId(kAutofillContextCustomFirst +
-                                           SubMenuType::NUM_SUBMENU_TYPES +
-                                           count_of_items_added_to_menu_model_ +
-                                           count_of_items_to_be_added + 1))) {
+  // Another 1 is added to account for the manage addresses/payment methods
+  // option.
+  if (!IsAutofillCustomCommandId(CommandId(
+          kAutofillContextCustomFirst + SubMenuType::NUM_SUBMENU_TYPES +
+          count_of_items_added_to_menu_model_ + count_of_items_to_be_added + 1 +
+          1))) {
     return false;
   }
 
diff --git a/chrome/browser/autofill/autofill_context_menu_manager.h b/chrome/browser/autofill/autofill_context_menu_manager.h
index 35266fba..f5790a90 100644
--- a/chrome/browser/autofill/autofill_context_menu_manager.h
+++ b/chrome/browser/autofill/autofill_context_menu_manager.h
@@ -14,6 +14,8 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/models/simple_menu_model.h"
 
+class Browser;
+
 namespace content {
 class RenderFrameHost;
 }  // namespace content
@@ -44,6 +46,10 @@
   // Represents the type that this item belongs to out of address, credit cards
   // and passwords.
   SubMenuType sub_menu_type;
+
+  // The context menu item represents a manage option. Example: Manage
+  // addresses/ Manage payment methods options.
+  bool is_manage_item = false;
 };
 
 // `AutofillContextMenuManager` is responsible for adding/executing Autofill
@@ -68,7 +74,8 @@
 
   AutofillContextMenuManager(PersonalDataManager* personal_data_manager,
                              ui::SimpleMenuModel::Delegate* delegate,
-                             ui::SimpleMenuModel* menu_model);
+                             ui::SimpleMenuModel* menu_model,
+                             Browser* browser);
   ~AutofillContextMenuManager();
   AutofillContextMenuManager(const AutofillContextMenuManager&) = delete;
   AutofillContextMenuManager& operator=(const AutofillContextMenuManager&) =
@@ -82,6 +89,7 @@
   bool IsCommandIdChecked(CommandId command_id) const;
   bool IsCommandIdVisible(CommandId command_id) const;
   bool IsCommandIdEnabled(CommandId command_id) const;
+  // TODO(crbug.com/1325811): Add tests for the method.
   void ExecuteCommand(CommandId command_id,
                       content::RenderFrameHost* render_frame_host,
                       const content::ContextMenuParams& params);
@@ -125,6 +133,7 @@
   raw_ptr<PersonalDataManager> personal_data_manager_;
   raw_ptr<ui::SimpleMenuModel> menu_model_;
   raw_ptr<ui::SimpleMenuModel::Delegate> delegate_;
+  raw_ptr<Browser> browser_;
 
   // Stores the count of items added to the context menu from Autofill.
   int count_of_items_added_to_menu_model_ = 0;
diff --git a/chrome/browser/autofill/autofill_context_menu_manager_unittest.cc b/chrome/browser/autofill/autofill_context_menu_manager_unittest.cc
index ae36118c..e20d2c4 100644
--- a/chrome/browser/autofill/autofill_context_menu_manager_unittest.cc
+++ b/chrome/browser/autofill/autofill_context_menu_manager_unittest.cc
@@ -41,7 +41,7 @@
 
     autofill_context_menu_manager_ =
         std::make_unique<AutofillContextMenuManager>(
-            personal_data_manager_.get(), nullptr, menu_model_.get());
+            personal_data_manager_.get(), nullptr, menu_model_.get(), nullptr);
   }
 
   void TearDown() override {
@@ -78,10 +78,13 @@
 
   // Check for submenu with address descriptions.
   auto* address_menu_model = menu_model()->GetSubmenuModelAt(0);
-  ASSERT_EQ(address_menu_model->GetItemCount(), 1);
+  ASSERT_EQ(address_menu_model->GetItemCount(), 3);
   ASSERT_EQ(u"John H. Doe, 666 Erebus St.", address_menu_model->GetLabelAt(0));
   ASSERT_EQ(address_menu_model->GetTypeAt(0),
             ui::MenuModel::ItemType::TYPE_SUBMENU);
+  ASSERT_EQ(address_menu_model->GetTypeAt(1),
+            ui::MenuModel::ItemType::TYPE_SEPARATOR);
+  ASSERT_EQ(u"Manage addresses", address_menu_model->GetLabelAt(2));
 
   // Check for submenu with address details.
   auto* address_details_submenu = address_menu_model->GetSubmenuModelAt(0);
@@ -97,7 +100,7 @@
 
   // Check for submenu with credit card descriptions.
   auto* card_menu_model = menu_model()->GetSubmenuModelAt(1);
-  ASSERT_EQ(card_menu_model->GetItemCount(), 1);
+  ASSERT_EQ(card_menu_model->GetItemCount(), 3);
   ASSERT_EQ(
       u"Visa  "
       u"\x202A\x2022\x2060\x2006\x2060\x2022\x2060\x2006\x2060\x2022\x2060"
@@ -106,6 +109,9 @@
       card_menu_model->GetLabelAt(0));
   ASSERT_EQ(card_menu_model->GetTypeAt(0),
             ui::MenuModel::ItemType::TYPE_SUBMENU);
+  ASSERT_EQ(card_menu_model->GetTypeAt(1),
+            ui::MenuModel::ItemType::TYPE_SEPARATOR);
+  ASSERT_EQ(u"Manage payment methods", card_menu_model->GetLabelAt(2));
 
   // Check for submenu with credit card details.
   auto* card_details_submenu = card_menu_model->GetSubmenuModelAt(0);
diff --git a/chrome/browser/autofill/autofill_server_browsertest.cc b/chrome/browser/autofill/autofill_server_browsertest.cc
index 211587b..cecbbe6b 100644
--- a/chrome/browser/autofill/autofill_server_browsertest.cc
+++ b/chrome/browser/autofill/autofill_server_browsertest.cc
@@ -280,7 +280,7 @@
   } else if (structured_names && honorific_prefix && structured_address) {
     upload->set_data_present("1f7e0003780000080004000001c404");
   } else if (!structured_names && !honorific_prefix && structured_address) {
-    upload->set_data_present("1f7e0003780000080004000001c");
+    upload->set_data_present("1f7e0003780000080004000001c0");
   } else {
     upload->set_data_present("1f7e0003780000080004");
   }
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 079713cf..84aebc0 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -215,6 +215,7 @@
     "//chrome/browser/ash/system_web_apps/types:types",
     "//chrome/browser/ash/wilco_dtc_supportd:mojo_utils",
     "//chrome/browser/browsing_data:constants",
+    "//chrome/browser/chromeos/launcher_search:search_util",
     "//chrome/browser/devtools",
     "//chrome/browser/extensions",
     "//chrome/browser/favicon",
@@ -259,6 +260,7 @@
     "//chromeos/ash/components/dbus/federated",
     "//chromeos/ash/components/dbus/fusebox",
     "//chromeos/ash/components/dbus/fusebox:proto",
+    "//chromeos/ash/components/dbus/human_presence",
     "//chromeos/ash/components/dbus/ip_peripheral",
     "//chromeos/ash/components/dbus/kerberos",
     "//chromeos/ash/components/dbus/kerberos:kerberos_proto",
@@ -276,6 +278,7 @@
     "//chromeos/ash/components/dbus/services",
     "//chromeos/ash/components/dbus/session_manager",
     "//chromeos/ash/components/dbus/session_manager:login_manager_proto",
+    "//chromeos/ash/components/dbus/smbprovider",
     "//chromeos/ash/components/dbus/spaced",
     "//chromeos/ash/components/dbus/system_clock",
     "//chromeos/ash/components/dbus/system_proxy",
@@ -336,7 +339,6 @@
     "//chromeos/dbus/fwupd",
     "//chromeos/dbus/gnubby",
     "//chromeos/dbus/hermes",
-    "//chromeos/dbus/human_presence",
     "//chromeos/dbus/image_loader",
     "//chromeos/dbus/machine_learning",
     "//chromeos/dbus/missive",
@@ -345,7 +347,6 @@
     "//chromeos/dbus/permission_broker",
     "//chromeos/dbus/power",
     "//chromeos/dbus/resourced",
-    "//chromeos/dbus/smbprovider",
     "//chromeos/dbus/tpm_manager",
     "//chromeos/dbus/tpm_manager:tpm_manager_proto",
     "//chromeos/dbus/u2f",
@@ -3158,6 +3159,7 @@
     "//chrome/browser/ash:arc_test_support",
     "//chrome/browser/ash/crosapi:unit_tests",
     "//chrome/browser/ash/system_web_apps",
+    "//chrome/browser/chromeos/launcher_search:unit_tests",
     "//chrome/browser/ui",
     "//chrome/browser/ui:ash_test_support",
     "//chrome/browser/web_applications",
@@ -3172,6 +3174,8 @@
     "//chromeos/ash/components/dbus/lorgnette_manager:lorgnette_proto",
     "//chromeos/ash/components/dbus/services:test_support",
     "//chromeos/ash/components/dbus/session_manager",
+    "//chromeos/ash/components/dbus/smbprovider",
+    "//chromeos/ash/components/dbus/smbprovider:proto",
     "//chromeos/ash/components/dbus/system_clock",
     "//chromeos/ash/components/dbus/update_engine",
     "//chromeos/ash/components/dbus/upstart",
@@ -3194,8 +3198,6 @@
     "//chromeos/dbus/missive",
     "//chromeos/dbus/oobe_config",
     "//chromeos/dbus/power",
-    "//chromeos/dbus/smbprovider",
-    "//chromeos/dbus/smbprovider:proto",
     "//chromeos/ime:gencode",
     "//chromeos/login/login_state",
     "//chromeos/login/login_state:test_support",
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/BUILD.gn b/chrome/browser/chromeos/extensions/telemetry/api/BUILD.gn
index b3f9644..75202463 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/BUILD.gn
+++ b/chrome/browser/chromeos/extensions/telemetry/api/BUILD.gn
@@ -37,6 +37,8 @@
     "//chrome/browser/ui",
     "//chrome/common/chromeos/extensions",
     "//chrome/common/chromeos/extensions/api",
+    "//components/security_state/content",
+    "//components/security_state/core",
     "//components/user_manager",
     "//content/public/browser",
     "//extensions/browser",
@@ -87,10 +89,13 @@
     "//chromeos/dbus",
     "//chromeos/dbus/debug_daemon",
     "//components/user_manager",
+    "//content/test:test_support",
     "//extensions:test_support",
     "//extensions/browser",
     "//extensions/browser:test_support",
     "//extensions/common",
+    "//net",
+    "//net:test_support",
     "//url",
   ]
 }
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/api_guard_delegate.cc b/chrome/browser/chromeos/extensions/telemetry/api/api_guard_delegate.cc
index af387f2..41e0ff24 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/api_guard_delegate.cc
+++ b/chrome/browser/chromeos/extensions/telemetry/api/api_guard_delegate.cc
@@ -17,6 +17,8 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chromeos/extensions/chromeos_system_extension_info.h"
+#include "components/security_state/content/content_utils.h"
+#include "components/security_state/core/security_state.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/web_contents.h"
@@ -70,8 +72,8 @@
       return;
     }
 
-    if (!IsPwaUiOpen(context, extension)) {
-      std::move(callback).Run("Companion PWA UI is not open");
+    if (!IsPwaUiOpenAndSecure(context, extension)) {
+      std::move(callback).Run("Companion PWA UI is not open or not secure");
       return;
     }
 
@@ -97,8 +99,8 @@
     return user_manager::UserManager::Get()->IsCurrentUserOwner();
   }
 
-  bool IsPwaUiOpen(content::BrowserContext* context,
-                   const extensions::Extension* extension) {
+  bool IsPwaUiOpenAndSecure(content::BrowserContext* context,
+                            const extensions::Extension* extension) {
     Profile* profile = Profile::FromBrowserContext(context);
 
     const auto* externally_connectable_info =
@@ -116,7 +118,13 @@
             target_tab_strip->GetWebContentsAt(i);
         if (externally_connectable_info->matches.MatchesURL(
                 target_contents->GetLastCommittedURL())) {
-          return true;
+          // Ensure the PWA URL connection is secure (e.g. valid certificate).
+          const auto visible_security_state =
+              security_state::GetVisibleSecurityState(target_contents);
+          return security_state::GetSecurityLevel(
+                     *visible_security_state,
+                     /*used_policy_installed_certificate=*/false) ==
+                 security_state::SecurityLevel::SECURE;
         }
       }
     }
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/api_guard_delegate_unittest.cc b/chrome/browser/chromeos/extensions/telemetry/api/api_guard_delegate_unittest.cc
index e817cd7..153d0aa1 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/api_guard_delegate_unittest.cc
+++ b/chrome/browser/chromeos/extensions/telemetry/api/api_guard_delegate_unittest.cc
@@ -16,9 +16,16 @@
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "components/user_manager/user.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/ssl_status.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_builder.h"
 #include "extensions/common/extension_urls.h"
+#include "net/base/net_errors.h"
+#include "net/cert/cert_status_flags.h"
+#include "net/cert/x509_certificate.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
@@ -44,7 +51,7 @@
 const std::vector<ExtensionInfoTestParams> kAllExtensionInfoTestParams{
     ExtensionInfoTestParams(
         /*extension_id=*/"gogonhoemckpdpadfnjnpgbjpbjnodgc",
-        /*pwa_page_url=*/"http://www.google.com",
+        /*pwa_page_url=*/"https://www.google.com",
         /*matches_origin=*/"*://www.google.com/*",
         /*manufacturer=*/"HP"),  // TODO(http://b/237059912): Refactor this as
                                  // soon as it becomes a set.
@@ -136,6 +143,24 @@
         hardware_info_delegate_factory_.get());
   }
 
+  void OpenPwaUrlAndSetCertificateWithStatus(net::CertStatus cert_status) {
+    const base::FilePath certs_dir = net::GetTestCertsDirectory();
+    scoped_refptr<net::X509Certificate> test_cert(
+        net::ImportCertFromFile(certs_dir, "ok_cert.pem"));
+    ASSERT_TRUE(test_cert);
+
+    // Open the PWA page url and set valid certificate to bypass the
+    // IsPwaUiOpenAndSecure() check.
+    AddTab(browser(), GURL(pwa_page_url()));
+
+    // AddTab() adds a new tab at index 0.
+    auto* web_contents = browser()->tab_strip_model()->GetWebContentsAt(0);
+    auto* entry = web_contents->GetController().GetVisibleEntry();
+    content::SSLStatus& ssl = entry->GetSSL();
+    ssl.certificate = test_cert;
+    ssl.cert_status = cert_status;
+  }
+
  private:
   void CreateExtension() {
     extension_ =
@@ -182,12 +207,24 @@
                                    future.GetCallback());
 
   ASSERT_TRUE(future.Wait());
-  EXPECT_EQ("Companion PWA UI is not open", future.Get());
+  EXPECT_EQ("Companion PWA UI is not open or not secure", future.Get());
+}
+
+TEST_P(ApiGuardDelegateTest, PwaIsOpenButNotSecure) {
+  OpenPwaUrlAndSetCertificateWithStatus(
+      /*cert_status=*/net::CERT_STATUS_INVALID);
+
+  auto api_guard_delegate = ApiGuardDelegate::Factory::Create();
+  base::test::TestFuture<std::string> future;
+  api_guard_delegate->CanAccessApi(profile(), extension(),
+                                   future.GetCallback());
+
+  ASSERT_TRUE(future.Wait());
+  EXPECT_EQ("Companion PWA UI is not open or not secure", future.Get());
 }
 
 TEST_P(ApiGuardDelegateTest, ManufacturerNotAllowed) {
-  // Open the PWA page url to bypass IsPwaUiOpen() check.
-  AddTab(browser(), GURL(pwa_page_url()));
+  OpenPwaUrlAndSetCertificateWithStatus(/*cert_status=*/net::OK);
 
   // Make sure device manufacturer is not allowed.
   SetDeviceManufacturer("GOOGLE");
@@ -203,8 +240,7 @@
 }
 
 TEST_P(ApiGuardDelegateTest, NoError) {
-  // Open the PWA page url to bypass IsPwaUiOpen() check.
-  AddTab(browser(), GURL(pwa_page_url()));
+  OpenPwaUrlAndSetCertificateWithStatus(/*cert_status=*/net::OK);
 
   auto api_guard_delegate = ApiGuardDelegate::Factory::Create();
   base::test::TestFuture<std::string> future;
@@ -262,7 +298,30 @@
                                    future.GetCallback());
 
   ASSERT_TRUE(future.Wait());
-  EXPECT_EQ("Companion PWA UI is not open", future.Get());
+  EXPECT_EQ("Companion PWA UI is not open or not secure", future.Get());
+}
+
+TEST_P(ApiGuardDelegateAffiliatedUserTest, PwaIsOpenButNotSecure) {
+  {
+    extensions::ExtensionManagementPrefUpdater<
+        sync_preferences::TestingPrefServiceSyncable>
+        updater(profile()->GetTestingPrefService());
+    // Make sure the extension is marked as force-installed.
+    updater.SetIndividualExtensionAutoInstalled(
+        extension_id(), extension_urls::kChromeWebstoreUpdateURL,
+        /*forced=*/true);
+  }
+
+  OpenPwaUrlAndSetCertificateWithStatus(
+      /*cert_status=*/net::CERT_STATUS_INVALID);
+
+  auto api_guard_delegate = ApiGuardDelegate::Factory::Create();
+  base::test::TestFuture<std::string> future;
+  api_guard_delegate->CanAccessApi(profile(), extension(),
+                                   future.GetCallback());
+
+  ASSERT_TRUE(future.Wait());
+  EXPECT_EQ("Companion PWA UI is not open or not secure", future.Get());
 }
 
 TEST_P(ApiGuardDelegateAffiliatedUserTest, ManufacturerNotAllowed) {
@@ -276,8 +335,7 @@
         /*forced=*/true);
   }
 
-  // Open the PWA page url to bypass IsPwaUiOpen() check.
-  AddTab(browser(), GURL(pwa_page_url()));
+  OpenPwaUrlAndSetCertificateWithStatus(/*cert_status=*/net::OK);
 
   // Make sure device manufacturer is not allowed.
   SetDeviceManufacturer("GOOGLE");
@@ -303,8 +361,7 @@
         /*forced=*/true);
   }
 
-  // Open the PWA page url to bypass IsPwaUiOpen() check.
-  AddTab(browser(), GURL(pwa_page_url()));
+  OpenPwaUrlAndSetCertificateWithStatus(/*cert_status=*/net::OK);
 
   auto api_guard_delegate = ApiGuardDelegate::Factory::Create();
   base::test::TestFuture<std::string> future;
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_api_guard_function_browsertest.cc b/chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_api_guard_function_browsertest.cc
index c21750bf..1141c08 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_api_guard_function_browsertest.cc
+++ b/chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_api_guard_function_browsertest.cc
@@ -17,7 +17,11 @@
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/test/browser_test.h"
+#include "content/public/test/content_mock_cert_verifier.h"
+#include "net/base/net_errors.h"
+#include "net/cert/x509_certificate.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
@@ -326,7 +330,9 @@
     : public BaseTelemetryExtensionBrowserTest {
  public:
   TelemetryExtensionApiGuardRealDelegateBrowserTest()
-      : fake_hardware_info_delegate_factory_("HP") {
+      : fake_hardware_info_delegate_factory_("HP"),
+        https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
+    https_server_.ServeFilesFromSourceDirectory(GetChromeTestDataDir());
     // Make sure device manufacturer is allowlisted.
     HardwareInfoDelegate::Factory::SetForTesting(
         &fake_hardware_info_delegate_factory_);
@@ -339,15 +345,34 @@
       const TelemetryExtensionApiGuardRealDelegateBrowserTest&) = delete;
 
   // BaseTelemetryExtensionBrowserTest:
+  void SetUp() override {
+    ASSERT_TRUE(https_server_.InitializeAndListen());
+
+    BaseTelemetryExtensionBrowserTest::SetUp();
+  }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    BaseTelemetryExtensionBrowserTest::SetUpCommandLine(command_line);
+
+    command_line->AppendSwitchASCII(
+        chromeos::switches::kTelemetryExtensionPwaOriginOverrideForTesting,
+        pwa_page_url());
+    mock_cert_verifier_.SetUpCommandLine(command_line);
+  }
+
   void SetUpOnMainThread() override {
     // Skip BaseTelemetryExtensionBrowserTest::SetUpOnMainThread() as it sets up
     // a FakeApiGuardDelegate instance.
     extensions::ExtensionBrowserTest::SetUpOnMainThread();
 
+    mock_cert_verifier()->set_default_result(net::OK);
+
     // Must be initialized before dealing with UserManager.
     user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>(
         std::make_unique<ash::FakeChromeUserManager>());
 
+    https_server_.StartAcceptingConnections();
+
     // This is needed when navigating to a network URL (e.g.
     // ui_test_utils::NavigateToURL). Rules can only be added before
     // BrowserTestBase::InitializeNetworkProcess() is called because host
@@ -363,17 +388,43 @@
         GetFakeUserManager()->GetActiveUser()->GetAccountId());
     user_manager_enabler_.reset();
 
+    ASSERT_TRUE(https_server_.ShutdownAndWaitUntilComplete());
+
     BaseTelemetryExtensionBrowserTest::TearDownOnMainThread();
   }
 
+  void SetUpInProcessBrowserTestFixture() override {
+    BaseTelemetryExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
+
+    mock_cert_verifier_.SetUpInProcessBrowserTestFixture();
+  }
+
+  void TearDownInProcessBrowserTestFixture() override {
+    mock_cert_verifier_.TearDownInProcessBrowserTestFixture();
+
+    BaseTelemetryExtensionBrowserTest::TearDownInProcessBrowserTestFixture();
+  }
+
+  content::ContentMockCertVerifier::CertVerifier* mock_cert_verifier() {
+    return mock_cert_verifier_.mock_cert_verifier();
+  }
+
  protected:
   ash::FakeChromeUserManager* GetFakeUserManager() const {
     return static_cast<ash::FakeChromeUserManager*>(
         user_manager::UserManager::Get());
   }
 
+  GURL GetPwaGURL() const { return https_server_.GetURL("/ssl/google.html"); }
+
+  // BaseTelemetryExtensionBrowserTest:
+  std::string pwa_page_url() const override { return GetPwaGURL().spec(); }
+  std::string matches_origin() const override { return GetPwaGURL().spec(); }
+
   FakeHardwareInfoDelegate::Factory fake_hardware_info_delegate_factory_;
   std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
+  net::EmbeddedTestServer https_server_;
+  content::ContentMockCertVerifier mock_cert_verifier_;
 };
 
 // Smoke test to verify that real ApiGuardDelegate works in prod.
@@ -387,7 +438,7 @@
   user_manager->SwitchActiveUser(account_id);
   user_manager->SetOwnerId(account_id);
 
-  // Make sure PWA UI is open.
+  // Make sure PWA UI is open and secure.
   auto* pwa_page_rfh =
       ui_test_utils::NavigateToURL(browser(), GURL(pwa_page_url()));
   ASSERT_TRUE(pwa_page_rfh);
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_browser_test.h b/chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_browser_test.h
index cd98568..395a81c 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_browser_test.h
+++ b/chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_browser_test.h
@@ -30,8 +30,8 @@
  protected:
   std::string extension_id() const;
   std::string public_key() const;
-  std::string pwa_page_url() const;
-  std::string matches_origin() const;
+  virtual std::string pwa_page_url() const;
+  virtual std::string matches_origin() const;
   void CreateExtensionAndRunServiceWorker(
       const std::string& service_worker_content);
   virtual std::string GetManifestFile(const std::string& matches_origin);
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_extension_capabilities_browser_test.cc b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_extension_capabilities_browser_test.cc
index a238761..a1ace85 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_extension_capabilities_browser_test.cc
+++ b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_extension_capabilities_browser_test.cc
@@ -174,7 +174,7 @@
   const auto extension_info = GetChromeOSExtensionInfoForId(extension_id());
   EXPECT_EQ(kPwaOriginOverride, extension_info.pwa_origin);
 
-  // Open the PWA page url to bypass IsPwaUiOpen() check.
+  // Open the PWA page url to bypass IsPwaUiOpenAndSecure() check.
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kPwaPageUrl)));
 
   // Start listening on the extension.
diff --git a/chrome/browser/chromeos/launcher_search/BUILD.gn b/chrome/browser/chromeos/launcher_search/BUILD.gn
new file mode 100644
index 0000000..bc6820e9
--- /dev/null
+++ b/chrome/browser/chromeos/launcher_search/BUILD.gn
@@ -0,0 +1,35 @@
+# Copyright 2022 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/chromeos/ui_mode.gni")
+import("//extensions/buildflags/buildflags.gni")
+
+assert(is_chromeos)
+
+source_set("search_util") {
+  sources = [
+    "search_util.cc",
+    "search_util.h",
+  ]
+
+  deps = [
+    "//base",
+    "//chromeos/crosapi/mojom",
+    "//components/bookmarks/browser",
+    "//components/omnibox/browser",
+    "//ui/base",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [ "search_util_unittest.cc" ]
+
+  deps = [
+    ":search_util",
+    "//base",
+    "//chrome/test:test_support",
+    "//components/omnibox/browser",
+  ]
+}
diff --git a/chrome/browser/lacros/launcher_search/OWNERS b/chrome/browser/chromeos/launcher_search/OWNERS
similarity index 100%
rename from chrome/browser/lacros/launcher_search/OWNERS
rename to chrome/browser/chromeos/launcher_search/OWNERS
diff --git a/chrome/browser/lacros/launcher_search/search_util.cc b/chrome/browser/chromeos/launcher_search/search_util.cc
similarity index 99%
rename from chrome/browser/lacros/launcher_search/search_util.cc
rename to chrome/browser/chromeos/launcher_search/search_util.cc
index a09416e..4fe1ac29 100644
--- a/chrome/browser/lacros/launcher_search/search_util.cc
+++ b/chrome/browser/chromeos/launcher_search/search_util.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/lacros/launcher_search/search_util.h"
+#include "chrome/browser/chromeos/launcher_search/search_util.h"
 
 #include "base/callback_helpers.h"
 #include "components/bookmarks/browser/bookmark_model.h"
diff --git a/chrome/browser/lacros/launcher_search/search_util.h b/chrome/browser/chromeos/launcher_search/search_util.h
similarity index 82%
rename from chrome/browser/lacros/launcher_search/search_util.h
rename to chrome/browser/chromeos/launcher_search/search_util.h
index 91cddc3..db3c6cd 100644
--- a/chrome/browser/lacros/launcher_search/search_util.h
+++ b/chrome/browser/chromeos/launcher_search/search_util.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_LACROS_LAUNCHER_SEARCH_SEARCH_UTIL_H_
-#define CHROME_BROWSER_LACROS_LAUNCHER_SEARCH_SEARCH_UTIL_H_
+#ifndef CHROME_BROWSER_CHROMEOS_LAUNCHER_SEARCH_SEARCH_UTIL_H_
+#define CHROME_BROWSER_CHROMEOS_LAUNCHER_SEARCH_SEARCH_UTIL_H_
 
 #include "chromeos/crosapi/mojom/launcher_search.mojom.h"
 #include "components/omnibox/browser/autocomplete_input.h"
@@ -20,9 +20,6 @@
 
 namespace crosapi {
 
-// TODO(crbug.com/1228587): This code will be shared with ash. Move this file
-// into an appropriate location.
-
 // Returns a bitmask of the AutocompleteProvider types to be used by Launcher
 // search.
 int ProviderTypes();
@@ -42,4 +39,4 @@
 
 }  // namespace crosapi
 
-#endif  // CHROME_BROWSER_LACROS_LAUNCHER_SEARCH_SEARCH_UTIL_H_
+#endif  // CHROME_BROWSER_CHROMEOS_LAUNCHER_SEARCH_SEARCH_UTIL_H_
diff --git a/chrome/browser/lacros/launcher_search/search_util_unittest.cc b/chrome/browser/chromeos/launcher_search/search_util_unittest.cc
similarity index 98%
rename from chrome/browser/lacros/launcher_search/search_util_unittest.cc
rename to chrome/browser/chromeos/launcher_search/search_util_unittest.cc
index df1886d3..06520c43 100644
--- a/chrome/browser/lacros/launcher_search/search_util_unittest.cc
+++ b/chrome/browser/chromeos/launcher_search/search_util_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/lacros/launcher_search/search_util.h"
+#include "chrome/browser/chromeos/launcher_search/search_util.h"
 
 #include <string>
 
diff --git a/chrome/browser/device_api/managed_configuration_api.cc b/chrome/browser/device_api/managed_configuration_api.cc
index 0272ac0d..6d0e1c4 100644
--- a/chrome/browser/device_api/managed_configuration_api.cc
+++ b/chrome/browser/device_api/managed_configuration_api.cc
@@ -4,11 +4,15 @@
 
 #include "chrome/browser/device_api/managed_configuration_api.h"
 
+#include <memory>
+#include <tuple>
+
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/containers/contains.h"
 #include "base/json/json_string_value_serializer.h"
 #include "base/task/thread_pool.h"
+#include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/device_api/managed_configuration_store.h"
 #include "chrome/browser/net/system_network_context_manager.h"
@@ -115,9 +119,7 @@
 ManagedConfigurationAPI::ManagedConfigurationAPI(Profile* profile)
     : profile_(profile),
       stores_path_(
-          profile->GetPath().AppendASCII(kManagedConfigurationDirectoryName)),
-      backend_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
-          {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {
+          profile->GetPath().AppendASCII(kManagedConfigurationDirectoryName)) {
   pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
   pref_change_registrar_->Init(profile_->GetPrefs());
   pref_change_registrar_->Add(
@@ -145,16 +147,21 @@
   if (!CanHaveManagedStore(origin)) {
     return std::move(callback).Run(nullptr);
   }
-  backend_task_runner_->PostTaskAndReplyWithResult(
-      FROM_HERE,
-      base::BindOnce(&ManagedConfigurationAPI::GetConfigurationOnBackend,
-                     base::Unretained(this), origin, keys),
-      std::move(callback));
+
+  if (!base::Contains(store_map_, origin))
+    return std::move(callback).Run(nullptr);
+
+  store_map_[origin]
+      .AsyncCall(&ManagedConfigurationStore::Get)
+      .WithArgs(std::move(keys))
+      .Then(std::move(callback));
 }
 
 void ManagedConfigurationAPI::AddObserver(Observer* observer) {
-  if (CanHaveManagedStore(observer->GetOrigin())) {
-    GetOrLoadStoreForOrigin(observer->GetOrigin())->AddObserver(observer);
+  url::Origin origin = observer->GetOrigin();
+  if (CanHaveManagedStore(origin)) {
+    MaybeCreateStoreForOrigin(origin);
+    observers_[origin].AddObserver(observer);
   } else {
     unmanaged_observers_.insert(observer);
   }
@@ -167,7 +174,7 @@
     return;
   }
 
-  GetOrLoadStoreForOrigin(observer->GetOrigin())->RemoveObserver(observer);
+  observers_[observer->GetOrigin()].RemoveObserver(observer);
 }
 
 bool ManagedConfigurationAPI::CanHaveManagedStore(const url::Origin& origin) {
@@ -216,37 +223,17 @@
   PromoteObservers();
 }
 
-ManagedConfigurationStore* ManagedConfigurationAPI::GetOrLoadStoreForOrigin(
+void ManagedConfigurationAPI::MaybeCreateStoreForOrigin(
     const url::Origin& origin) {
-  auto it = store_map_.find(origin);
-  if (it != store_map_.end())
-    return it->second.get();
+  if (base::Contains(store_map_, origin))
+    return;
+
   // Create the store now, and serve the cached policy until the PolicyService
   // sends updated values.
-  auto store = std::make_unique<ManagedConfigurationStore>(
-      backend_task_runner_, origin, GetStoreLocation(origin));
-  ManagedConfigurationStore* store_ptr = store.get();
-  store_map_[origin] = std::move(store);
-  return store_ptr;
-}
-
-std::unique_ptr<base::DictionaryValue>
-ManagedConfigurationAPI::GetConfigurationOnBackend(
-    const url::Origin& origin,
-    const std::vector<std::string>& keys) {
-  // If there was no policy set for this origin, there is no reason to create
-  // or load a store.
-  if (!base::Contains(store_map_, origin))
-    return nullptr;
-
-  value_store::LeveldbValueStore::ReadResult result =
-      store_map_[origin]->Get(keys);
-  if (!result.status().ok())
-    return nullptr;
-
-  auto dict = std::make_unique<base::DictionaryValue>();
-  dict->Swap(&result.settings());
-  return dict;
+  store_map_[origin] = base::SequenceBound<ManagedConfigurationStore>(
+      base::ThreadPool::CreateSequencedTaskRunner(
+          {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}),
+      origin, GetStoreLocation(origin));
 }
 
 base::FilePath ManagedConfigurationAPI::GetStoreLocation(
@@ -333,17 +320,24 @@
 void ManagedConfigurationAPI::PostStoreConfiguration(
     const url::Origin& origin,
     base::DictionaryValue configuration) {
-  // Safe to use unretained here, since we own the task runner.
-  backend_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&ManagedConfigurationAPI::StoreConfigurationOnBackend,
-                     base::Unretained(this), origin, std::move(configuration)));
+  MaybeCreateStoreForOrigin(origin);
+  store_map_[origin]
+      .AsyncCall(&ManagedConfigurationStore::SetCurrentPolicy)
+      .WithArgs(std::move(configuration))
+      .Then(base::BindOnce(
+          &ManagedConfigurationAPI::InformObserversIfConfigurationChanged,
+          weak_ptr_factory_.GetWeakPtr(), origin));
 }
 
-void ManagedConfigurationAPI::StoreConfigurationOnBackend(
+void ManagedConfigurationAPI::InformObserversIfConfigurationChanged(
     const url::Origin& origin,
-    base::DictionaryValue configuration) {
-  GetOrLoadStoreForOrigin(origin)->SetCurrentPolicy(configuration);
+    bool has_changed) {
+  if (!has_changed || !base::Contains(observers_, origin))
+    return;
+
+  for (auto& observer : observers_[origin]) {
+    observer.OnManagedConfigurationChanged();
+  }
 }
 
 void ManagedConfigurationAPI::PromoteObservers() {
diff --git a/chrome/browser/device_api/managed_configuration_api.h b/chrome/browser/device_api/managed_configuration_api.h
index 9469754..06445aa 100644
--- a/chrome/browser/device_api/managed_configuration_api.h
+++ b/chrome/browser/device_api/managed_configuration_api.h
@@ -8,7 +8,8 @@
 #include "base/files/file_path.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/observer_list_types.h"
+#include "base/observer_list.h"
+#include "base/threading/sequence_bound.h"
 #include "base/values.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/prefs/pref_change_registrar.h"
@@ -83,14 +84,10 @@
   // Sends an operation to set the configured value on FILE thread.
   void PostStoreConfiguration(const url::Origin& origin,
                               base::DictionaryValue configuration);
+  void InformObserversIfConfigurationChanged(const url::Origin& origin,
+                                             bool changed);
 
-  std::unique_ptr<base::DictionaryValue> GetConfigurationOnBackend(
-      const url::Origin& origin,
-      const std::vector<std::string>& keys);
-  void StoreConfigurationOnBackend(const url::Origin& origin,
-                                   base::DictionaryValue configuration);
-
-  ManagedConfigurationStore* GetOrLoadStoreForOrigin(const url::Origin& origin);
+  void MaybeCreateStoreForOrigin(const url::Origin& origin);
   base::FilePath GetStoreLocation(const url::Origin& origin);
 
   // Assigns observers from |unmanaged_observers_| to a particular store if
@@ -103,10 +100,12 @@
   const raw_ptr<Profile> profile_;
 
   const base::FilePath stores_path_;
-  std::map<url::Origin, std::unique_ptr<ManagedConfigurationStore>> store_map_;
+  std::map<url::Origin, base::SequenceBound<ManagedConfigurationStore>>
+      store_map_;
   // Stores current configuration downloading managers.
   std::map<url::Origin, std::unique_ptr<ManagedConfigurationDownloader>>
       downloaders_;
+  std::map<url::Origin, base::ObserverList<Observer>> observers_;
 
   // Stores the list of orrigins which have a managed configuration(may not yet
   // loaded).
@@ -114,9 +113,6 @@
 
   std::set<Observer*> unmanaged_observers_;
 
-  // Blocking task runner for IO related tasks.
-  scoped_refptr<base::SequencedTaskRunner> backend_task_runner_;
-
   // Observes changes to WebAppInstallForceList.
   std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
   base::WeakPtrFactory<ManagedConfigurationAPI> weak_ptr_factory_{this};
diff --git a/chrome/browser/device_api/managed_configuration_store.cc b/chrome/browser/device_api/managed_configuration_store.cc
index beba1d4..6ff2a310 100644
--- a/chrome/browser/device_api/managed_configuration_store.cc
+++ b/chrome/browser/device_api/managed_configuration_store.cc
@@ -4,44 +4,24 @@
 
 #include "chrome/browser/device_api/managed_configuration_store.h"
 
-ManagedConfigurationStore::ManagedConfigurationStore(
-    scoped_refptr<base::SequencedTaskRunner> backend_sequence,
-    const url::Origin& origin,
-    const base::FilePath& path)
-    : backend_sequence_(backend_sequence),
-      origin_(origin),
-      path_(path),
-      observers_(new base::ObserverListThreadSafe<
-                 ManagedConfigurationAPI::Observer>()) {}
+#include "base/logging.h"
 
-void ManagedConfigurationStore::InitializeOnBackend() {
+ManagedConfigurationStore::ManagedConfigurationStore(const url::Origin& origin,
+                                                     const base::FilePath& path)
+    : origin_(origin), path_(path) {}
+
+ManagedConfigurationStore::~ManagedConfigurationStore() = default;
+
+void ManagedConfigurationStore::Initialize() {
   // LeveldbValueStore can only be initialized on a blocking sequnece.
-  DCHECK(backend_sequence_->RunsTasksInCurrentSequence());
   store_ = std::make_unique<value_store::LeveldbValueStore>(
       "OriginManagedConfiguration", path_);
 }
 
-ManagedConfigurationStore::~ManagedConfigurationStore() {
-  // Delete ValueStore on the FILE thread, since it can only operate on that
-  // thread.
-  backend_sequence_->DeleteSoon(FROM_HERE, std::move(store_));
-}
-
-void ManagedConfigurationStore::AddObserver(
-    ManagedConfigurationAPI::Observer* observer) {
-  observers_->AddObserver(observer);
-}
-
-void ManagedConfigurationStore::RemoveObserver(
-    ManagedConfigurationAPI::Observer* observer) {
-  observers_->RemoveObserver(observer);
-}
-
-void ManagedConfigurationStore::SetCurrentPolicy(
+bool ManagedConfigurationStore::SetCurrentPolicy(
     const base::DictionaryValue& current_configuration) {
-  DCHECK(backend_sequence_->RunsTasksInCurrentSequence());
   if (!store_)
-    InitializeOnBackend();
+    Initialize();
   // Get the previous policies stored in the database.
   base::DictionaryValue previous_policy;
   value_store::ValueStore::ReadResult read_result = store_->Get();
@@ -78,17 +58,18 @@
     store_updated |= !result.changes().empty();
   }
 
-  if (!store_updated)
-    return;
-  observers_->Notify(
-      FROM_HERE,
-      &ManagedConfigurationAPI::Observer::OnManagedConfigurationChanged);
+  return store_updated;
 }
 
-value_store::ValueStore::ReadResult ManagedConfigurationStore::Get(
+std::unique_ptr<base::DictionaryValue> ManagedConfigurationStore::Get(
     const std::vector<std::string>& keys) {
-  DCHECK(backend_sequence_->RunsTasksInCurrentSequence());
   if (!store_)
-    InitializeOnBackend();
-  return store_->Get(keys);
+    Initialize();
+
+  auto result = store_->Get(keys);
+
+  if (!result.status().ok())
+    return nullptr;
+
+  return result.PassSettings();
 }
diff --git a/chrome/browser/device_api/managed_configuration_store.h b/chrome/browser/device_api/managed_configuration_store.h
index a95646d..c156c8756 100644
--- a/chrome/browser/device_api/managed_configuration_store.h
+++ b/chrome/browser/device_api/managed_configuration_store.h
@@ -6,47 +6,35 @@
 #define CHROME_BROWSER_DEVICE_API_MANAGED_CONFIGURATION_STORE_H_
 
 #include "base/files/file_path.h"
-#include "base/observer_list_threadsafe.h"
-#include "chrome/browser/device_api/managed_configuration_api.h"
+#include "base/values.h"
 #include "components/value_store/leveldb_value_store.h"
 #include "url/origin.h"
 
-namespace base {
-class SequencedTaskRunner;
-}
-
-// Class responsible for internal storage of the managed configuration. Adding
-// and removing observers is allowed on any thread, while setting/getting the
-// data is only allowed on the FILE thread.
+// Class responsible for internal storage of the managed configuration.
+// Setting/getting the data is a blocking operation and need to be run on a
+// thread that supports this.
 //
 // By itself, this class can be percieved as a handle to access levelDB database
 // stored at |path|.
 class ManagedConfigurationStore {
  public:
-  ManagedConfigurationStore(
-      scoped_refptr<base::SequencedTaskRunner> backend_sequence,
-      const url::Origin& origin,
-      const base::FilePath& path);
+  ManagedConfigurationStore(const url::Origin& origin,
+                            const base::FilePath& path);
   ~ManagedConfigurationStore();
 
-  // Initializes connection to the database. Must be called on
-  // |backend_sequence_|.
-  void InitializeOnBackend();
-
-  void AddObserver(ManagedConfigurationAPI::Observer* observer);
-  void RemoveObserver(ManagedConfigurationAPI::Observer* observer);
-
-  // Read/Write operations must be called on |backend_sequence_|.
-  void SetCurrentPolicy(const base::DictionaryValue& current_configuration);
-  value_store::ValueStore::ReadResult Get(const std::vector<std::string>& keys);
+  // Returns |true| if the new policy is different from the previously set
+  // policy.
+  bool SetCurrentPolicy(const base::DictionaryValue& current_configuration);
+  std::unique_ptr<base::DictionaryValue> Get(
+      const std::vector<std::string>& keys);
 
  private:
-  scoped_refptr<base::SequencedTaskRunner> backend_sequence_;
+  // Initializes connection to the database.
+  void Initialize();
+
   const url::Origin origin_;
   const base::FilePath path_;
   std::unique_ptr<value_store::ValueStore> store_;
-  scoped_refptr<base::ObserverListThreadSafe<ManagedConfigurationAPI::Observer>>
-      observers_;
 };
 
 #endif  // CHROME_BROWSER_DEVICE_API_MANAGED_CONFIGURATION_STORE_H_
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
index bae6384..ac2aabb 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
@@ -5,8 +5,6 @@
 #include <memory>
 #include <utility>
 
-#include "ash/components/cryptohome/cryptohome_parameters.h"
-#include "ash/constants/ash_switches.h"
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/callback_helpers.h"
@@ -20,23 +18,6 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/networking_private/networking_private_ui_delegate_chromeos.h"
 #include "chrome/browser/extensions/extension_apitest.h"
-#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
-#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
-#include "chromeos/ash/components/network/cellular_metrics_logger.h"
-#include "chromeos/ash/components/network/managed_network_configuration_handler.h"
-#include "chromeos/ash/components/network/network_certificate_handler.h"
-#include "chromeos/ash/components/network/network_handler_test_helper.h"
-#include "chromeos/ash/components/network/onc/network_onc_utils.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill/shill_device_client.h"
-#include "chromeos/dbus/shill/shill_ipconfig_client.h"
-#include "chromeos/dbus/shill/shill_manager_client.h"
-#include "chromeos/dbus/shill/shill_profile_client.h"
-#include "chromeos/dbus/shill/shill_service_client.h"
-#include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_state.h"
-#include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_type_pattern.h"
 #include "components/onc/onc_constants.h"
 #include "components/onc/onc_pref_names.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
@@ -55,16 +36,44 @@
 #include "components/user_manager/user_names.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_utils.h"
-#include "dbus/object_path.h"
 #include "extensions/browser/api/networking_private/networking_private_chromeos.h"
 #include "extensions/browser/api/networking_private/networking_private_delegate_factory.h"
 #include "extensions/common/switches.h"
 #include "extensions/common/value_builder.h"
 #include "extensions/test/extension_test_message_listener.h"
 #include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ash/components/cryptohome/cryptohome_parameters.h"
+#include "ash/constants/ash_switches.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/network/cellular_metrics_logger.h"
+#include "chromeos/ash/components/network/managed_network_configuration_handler.h"
+#include "chromeos/ash/components/network/network_certificate_handler.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
+#include "chromeos/ash/components/network/onc/network_onc_utils.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
+#include "chromeos/network/network_type_pattern.h"
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#include "chromeos/crosapi/mojom/test_controller.mojom-test-utils.h"
+#include "chromeos/crosapi/mojom/test_controller.mojom.h"
+#include "chromeos/lacros/lacros_service.h"
+
+using crosapi::mojom::ShillClientTestInterfaceAsyncWaiter;
+#endif
+
 // This tests the Chrome OS implementation of the networkingPrivate API
 // (NetworkingPrivateChromeOS). Note: The test expectations for chromeos, and
 // win/mac (NetworkingPrivateServiceClient) are different to reflect the
@@ -73,6 +82,7 @@
 using testing::Return;
 using testing::_;
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 using ash::UserDataAuthClient;
 using chromeos::ShillDeviceClient;
 using chromeos::ShillIPConfigClient;
@@ -83,41 +93,30 @@
 using extensions::NetworkingPrivateDelegate;
 using extensions::NetworkingPrivateDelegateFactory;
 using extensions::NetworkingPrivateChromeOS;
+#endif
 
 namespace {
 
-const char kUser1ProfilePath[] = "/profile/user1/shill";
-const char kEthernetDevicePath[] = "/device/stub_ethernet_device";
-const char kWifiDevicePath[] = "/device/stub_wifi_device1";
+const char kCellular1ServicePath[] = "stub_cellular1";
 const char kCellularDevicePath[] = "/device/stub_cellular_device1";
+const char kEthernetDevicePath[] = "/device/stub_ethernet_device";
 const char kIPConfigPath[] = "/ipconfig/ipconfig1";
-
+const char kUser1ProfilePath[] = "/profile/user1/shill";
 const char kWifi1ServicePath[] = "stub_wifi1";
 const char kWifi2ServicePath[] = "stub_wifi2";
-const char kCellular1ServicePath[] = "stub_cellular1";
+const char kWifiDevicePath[] = "/device/stub_wifi_device1";
 
-class UIDelegateStub : public NetworkingPrivateDelegate::UIDelegate {
+class NetworkingPrivateChromeOSApiTestBase
+    : public extensions::ExtensionApiTest {
  public:
-  static int s_show_account_details_called_;
-
- private:
-  // UIDelegate
-  void ShowAccountDetails(const std::string& guid) const override {
-    ++s_show_account_details_called_;
+  // From extensions::ExtensionApiTest
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    extensions::ExtensionApiTest::SetUpCommandLine(command_line);
+    // Allowlist the extension ID of the test extension.
+    command_line->AppendSwitchASCII(
+        extensions::switches::kAllowlistedExtensionID,
+        "epcifkihnkjgphfkloaaleeakhpmgdmn");
   }
-};
-
-// static
-int UIDelegateStub::s_show_account_details_called_ = 0;
-
-class NetworkingPrivateChromeOSApiTest : public extensions::ExtensionApiTest {
- public:
-  NetworkingPrivateChromeOSApiTest() {}
-
-  NetworkingPrivateChromeOSApiTest(const NetworkingPrivateChromeOSApiTest&) =
-      delete;
-  NetworkingPrivateChromeOSApiTest& operator=(
-      const NetworkingPrivateChromeOSApiTest&) = delete;
 
   bool RunNetworkingSubtest(const std::string& test) {
     const std::string arg =
@@ -127,62 +126,107 @@
         {.custom_arg = arg.c_str(), .launch_as_platform_app = true});
   }
 
-  void SetUpInProcessBrowserTestFixture() override {
-    provider_.SetDefaultReturns(
-        /*is_initialization_complete_return=*/true,
-        /*is_first_policy_load_complete_return=*/true);
-    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
+  void ConfigFakeNetwork() {
+    ClearDevices();
+    ClearServices();
 
-    extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture();
+    std::string userhash = GetSanitizedActiveUsername();
+
+    // Sends a notification about the added profile.
+    AddProfile(kUser1ProfilePath, userhash);
+
+    // Add IPConfigs
+    base::DictionaryValue ipconfig;
+    ipconfig.SetKey(shill::kAddressProperty, base::Value("0.0.0.0"));
+    ipconfig.SetKey(shill::kGatewayProperty, base::Value("0.0.0.1"));
+    ipconfig.SetKey(shill::kPrefixlenProperty, base::Value(0));
+    ipconfig.SetKey(shill::kMethodProperty, base::Value(shill::kTypeIPv4));
+    AddIPConfig(kIPConfigPath, ipconfig);
+
+    // Add Devices
+    AddDevice(kEthernetDevicePath, shill::kTypeEthernet,
+              "stub_ethernet_device1");
+
+    AddDevice(kWifiDevicePath, shill::kTypeWifi, "stub_wifi_device1");
+    base::ListValue wifi_ip_configs;
+    wifi_ip_configs.Append(kIPConfigPath);
+    SetDeviceProperty(kWifiDevicePath, shill::kIPConfigsProperty,
+                      wifi_ip_configs);
+    SetDeviceProperty(kWifiDevicePath, shill::kAddressProperty,
+                      base::Value("001122aabbcc"));
+
+    // Add Services
+    AddService("stub_ethernet", "eth0", shill::kTypeEthernet,
+               shill::kStateOnline);
+    SetServiceProperty("stub_ethernet", shill::kProfileProperty,
+                       base::Value(GetSharedProfilePath()));
+    AddServiceToProfile(GetSharedProfilePath(), "stub_ethernet");
+
+    AddService(kWifi1ServicePath, "wifi1", shill::kTypeWifi,
+               shill::kStateOnline);
+    SetServiceProperty(kWifi1ServicePath, shill::kSecurityClassProperty,
+                       base::Value(shill::kSecurityWep));
+    SetServiceProperty(kWifi1ServicePath, shill::kWifiBSsid,
+                       base::Value("00:01:02:03:04:05"));
+    SetServiceProperty(kWifi1ServicePath, shill::kSignalStrengthProperty,
+                       base::Value(40));
+    SetServiceProperty(kWifi1ServicePath, shill::kProfileProperty,
+                       base::Value(kUser1ProfilePath));
+    SetServiceProperty(kWifi1ServicePath, shill::kConnectableProperty,
+                       base::Value(true));
+    SetServiceProperty(kWifi1ServicePath, shill::kDeviceProperty,
+                       base::Value(kWifiDevicePath));
+    base::DictionaryValue static_ipconfig;
+    static_ipconfig.SetKey(shill::kAddressProperty, base::Value("1.2.3.4"));
+    static_ipconfig.SetKey(shill::kGatewayProperty, base::Value("0.0.0.0"));
+    static_ipconfig.SetKey(shill::kPrefixlenProperty, base::Value(1));
+    SetServiceProperty(kWifi1ServicePath, shill::kStaticIPConfigProperty,
+                       static_ipconfig);
+    base::ListValue frequencies1;
+    frequencies1.Append(2400);
+    SetServiceProperty(kWifi1ServicePath, shill::kWifiFrequencyListProperty,
+                       frequencies1);
+    SetServiceProperty(kWifi1ServicePath, shill::kWifiFrequency,
+                       base::Value(2400));
+    AddServiceToProfile(kUser1ProfilePath, kWifi1ServicePath);
+
+    AddService(kWifi2ServicePath, "wifi2_PSK", shill::kTypeWifi,
+               shill::kStateIdle);
+    SetServiceProperty(kWifi2ServicePath, shill::kSecurityClassProperty,
+                       base::Value(shill::kSecurityPsk));
+    SetServiceProperty(kWifi2ServicePath, shill::kSignalStrengthProperty,
+                       base::Value(80));
+    SetServiceProperty(kWifi2ServicePath, shill::kConnectableProperty,
+                       base::Value(true));
+
+    base::ListValue frequencies2;
+    frequencies2.Append(2400);
+    frequencies2.Append(5000);
+    SetServiceProperty(kWifi2ServicePath, shill::kWifiFrequencyListProperty,
+                       frequencies2);
+    SetServiceProperty(kWifi2ServicePath, shill::kWifiFrequency,
+                       base::Value(5000));
+    SetServiceProperty(kWifi2ServicePath, shill::kProfileProperty,
+                       base::Value(kUser1ProfilePath));
+    AddServiceToProfile(kUser1ProfilePath, kWifi2ServicePath);
+
+    AddService("stub_vpn1", "vpn1", shill::kTypeVPN, shill::kStateOnline);
+    SetServiceProperty("stub_vpn1", shill::kProviderTypeProperty,
+                       base::Value(shill::kProviderOpenVpn));
+    AddServiceToProfile(kUser1ProfilePath, "stub_vpn1");
+
+    AddService("stub_vpn2", "vpn2", shill::kTypeVPN, shill::kStateOffline);
+    SetServiceProperty("stub_vpn2", shill::kProviderTypeProperty,
+                       base::Value(shill::kProviderThirdPartyVpn));
+    SetServiceProperty("stub_vpn2", shill::kProviderHostProperty,
+                       base::Value("third_party_provider_extension_id"));
+    AddServiceToProfile(kUser1ProfilePath, "stub_vpn2");
   }
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    extensions::ExtensionApiTest::SetUpCommandLine(command_line);
-    // Allowlist the extension ID of the test extension.
-    command_line->AppendSwitchASCII(
-        extensions::switches::kAllowlistedExtensionID,
-        "epcifkihnkjgphfkloaaleeakhpmgdmn");
-
-    // TODO(pneubeck): Remove the following hack, once the NetworkingPrivateAPI
-    // uses the ProfileHelper to obtain the userhash crbug/238623.
-    cryptohome::AccountIdentifier login_user;
-    login_user.set_account_id(user_manager::CanonicalizeUserID(
-        command_line->GetSwitchValueNative(ash::switches::kLoginUser)));
-    const std::string sanitized_user =
-        UserDataAuthClient::GetStubSanitizedUsername(login_user);
-    command_line->AppendSwitchASCII(ash::switches::kLoginProfile,
-                                    sanitized_user);
-  }
-
-  void InitializeSanitizedUsername() {
-    user_manager::UserManager* user_manager = user_manager::UserManager::Get();
-    user_manager::User* user = user_manager->GetActiveUser();
-    CHECK(user);
-    std::string userhash;
-    ::user_data_auth::GetSanitizedUsernameRequest request;
-    request.set_username(
-        cryptohome::CreateAccountIdentifierFromAccountId(user->GetAccountId())
-            .account_id());
-    ash::CryptohomeMiscClient::Get()->GetSanitizedUsername(
-        request,
-        base::BindOnce(
-            [](std::string* out,
-               absl::optional<::user_data_auth::GetSanitizedUsernameReply>
-                   result) {
-              CHECK(result.has_value());
-              *out = result->sanitized_username();
-            },
-            &userhash_));
-    content::RunAllPendingInMessageLoop();
-    CHECK(!userhash_.empty());
-  }
-
-  void SetupCellular() {
-    UIDelegateStub::s_show_account_details_called_ = 0;
-
+  virtual void SetupCellular() {
     // Add a Cellular GSM Device.
-    device_test()->AddDevice(kCellularDevicePath, shill::kTypeCellular,
-                             "stub_cellular_device1");
+    AddDevice(kCellularDevicePath, shill::kTypeCellular,
+              "stub_cellular_device1");
     base::DictionaryValue home_provider;
     home_provider.SetStringKey("name", "Cellular1_Provider");
     home_provider.SetStringKey("code", "000000");
@@ -205,31 +249,89 @@
                       base::Value("test_min"));
     SetDeviceProperty(kCellularDevicePath, shill::kModelIdProperty,
                       base::Value("test_model_id"));
-    device_test()->SetSimLocked(kCellularDevicePath, false);
+    SetSimLocked(kCellularDevicePath, false);
 
     // Add the Cellular Service.
     AddService(kCellular1ServicePath, "cellular1", shill::kTypeCellular,
                shill::kStateIdle);
-    service_test()->SetServiceProperty(kCellular1ServicePath,
-                                       shill::kCellularAllowRoamingProperty,
-                                       base::Value(false));
-    service_test()->SetServiceProperty(
-        kCellular1ServicePath, shill::kAutoConnectProperty, base::Value(true));
-    service_test()->SetServiceProperty(kCellular1ServicePath,
-                                       shill::kIccidProperty,
-                                       base::Value("test_iccid"));
-    service_test()->SetServiceProperty(
-        kCellular1ServicePath, shill::kNetworkTechnologyProperty,
-        base::Value(shill::kNetworkTechnologyGsm));
-    service_test()->SetServiceProperty(
-        kCellular1ServicePath, shill::kActivationStateProperty,
-        base::Value(shill::kActivationStateNotActivated));
-    service_test()->SetServiceProperty(kCellular1ServicePath,
-                                       shill::kRoamingStateProperty,
-                                       base::Value(shill::kRoamingStateHome));
+    SetServiceProperty(kCellular1ServicePath,
+                       shill::kCellularAllowRoamingProperty,
+                       base::Value(false));
+    SetServiceProperty(kCellular1ServicePath, shill::kAutoConnectProperty,
+                       base::Value(true));
+    SetServiceProperty(kCellular1ServicePath, shill::kIccidProperty,
+                       base::Value("test_iccid"));
+    SetServiceProperty(kCellular1ServicePath, shill::kNetworkTechnologyProperty,
+                       base::Value(shill::kNetworkTechnologyGsm));
+    SetServiceProperty(kCellular1ServicePath, shill::kActivationStateProperty,
+                       base::Value(shill::kActivationStateNotActivated));
+    SetServiceProperty(kCellular1ServicePath, shill::kRoamingStateProperty,
+                       base::Value(shill::kRoamingStateHome));
 
-    profile_test()->AddService(kUser1ProfilePath, kCellular1ServicePath);
-    content::RunAllPendingInMessageLoop();
+    AddServiceToProfile(kUser1ProfilePath, kCellular1ServicePath);
+  }
+
+  virtual std::string GetSanitizedActiveUsername() = 0;
+
+  virtual void AddDevice(const std::string& device_path,
+                         const std::string& type,
+                         const std::string& name) = 0;
+  virtual void SetDeviceProperty(const std::string& device_path,
+                                 const std::string& name,
+                                 const base::Value& value) = 0;
+  virtual void SetSimLocked(const std::string& device_path, bool enabled) = 0;
+  virtual void ClearDevices() = 0;
+  virtual void AddService(const std::string& service_path,
+                          const std::string& name,
+                          const std::string& type,
+                          const std::string& state) = 0;
+  virtual void ClearServices() = 0;
+  virtual void SetServiceProperty(const std::string& service_path,
+                                  const std::string& property,
+                                  const base::Value& value) = 0;
+  virtual void AddProfile(const std::string& profile_path,
+                          const std::string& userhash) = 0;
+
+  virtual void AddServiceToProfile(const std::string& profile_path,
+                                   const std::string& service_path) = 0;
+  virtual std::string GetSharedProfilePath() = 0;
+  virtual void AddIPConfig(const std::string& ip_config_path,
+                           const base::Value& properties) = 0;
+};
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+class UIDelegateStub : public NetworkingPrivateDelegate::UIDelegate {
+ public:
+  static int s_show_account_details_called_;
+
+ private:
+  // UIDelegate
+  void ShowAccountDetails(const std::string& guid) const override {
+    ++s_show_account_details_called_;
+  }
+};
+
+// static
+int UIDelegateStub::s_show_account_details_called_ = 0;
+
+class NetworkingPrivateChromeOSApiTestAsh
+    : public NetworkingPrivateChromeOSApiTestBase {
+ public:
+  NetworkingPrivateChromeOSApiTestAsh() = default;
+
+  NetworkingPrivateChromeOSApiTestAsh(
+      const NetworkingPrivateChromeOSApiTestAsh&) = delete;
+  NetworkingPrivateChromeOSApiTestAsh& operator=(
+      const NetworkingPrivateChromeOSApiTestAsh&) = delete;
+
+  static std::unique_ptr<KeyedService> CreateNetworkingPrivateDelegate(
+      content::BrowserContext* context) {
+    std::unique_ptr<NetworkingPrivateDelegate> result(
+        new NetworkingPrivateChromeOS(context));
+    std::unique_ptr<NetworkingPrivateDelegate::UIDelegate> ui_delegate(
+        new UIDelegateStub);
+    result->set_ui_delegate(std::move(ui_delegate));
+    return result;
   }
 
   void SetupTether() {
@@ -247,159 +349,6 @@
         false /* has_connected_to_host */);
   }
 
-  void AddService(const std::string& service_path,
-                  const std::string& name,
-                  const std::string& type,
-                  const std::string& state) {
-    service_test()->AddService(service_path, service_path + "_guid", name, type,
-                               state, true /* add_to_visible */);
-  }
-
-  void SetDeviceProperty(const std::string& device_path,
-                         const std::string& name,
-                         const base::Value& value) {
-    device_test()->SetDeviceProperty(device_path, name, value,
-                                     /*notify_changed=*/true);
-  }
-
-  static std::unique_ptr<KeyedService> CreateNetworkingPrivateDelegate(
-      content::BrowserContext* context) {
-    std::unique_ptr<NetworkingPrivateDelegate> result(
-        new NetworkingPrivateChromeOS(context));
-    std::unique_ptr<NetworkingPrivateDelegate::UIDelegate> ui_delegate(
-        new UIDelegateStub);
-    result->set_ui_delegate(std::move(ui_delegate));
-    return result;
-  }
-
-  void SetUpOnMainThread() override {
-    extensions::ExtensionApiTest::SetUpOnMainThread();
-    content::RunAllPendingInMessageLoop();
-
-    NetworkingPrivateDelegateFactory::GetInstance()->SetTestingFactory(
-        profile(), base::BindRepeating(&CreateNetworkingPrivateDelegate));
-
-    InitializeSanitizedUsername();
-
-    network_handler_test_helper_ =
-        std::make_unique<chromeos::NetworkHandlerTestHelper>();
-    device_test()->ClearDevices();
-    service_test()->ClearServices();
-
-    // Sends a notification about the added profile.
-    profile_test()->AddProfile(kUser1ProfilePath, userhash_);
-
-    // Add IPConfigs
-    base::DictionaryValue ipconfig;
-    ipconfig.SetKey(shill::kAddressProperty, base::Value("0.0.0.0"));
-    ipconfig.SetKey(shill::kGatewayProperty, base::Value("0.0.0.1"));
-    ipconfig.SetKey(shill::kPrefixlenProperty, base::Value(0));
-    ipconfig.SetKey(shill::kMethodProperty, base::Value(shill::kTypeIPv4));
-    network_handler_test_helper_->ip_config_test()->AddIPConfig(kIPConfigPath,
-                                                                ipconfig);
-
-    // Add Devices
-    device_test()->AddDevice(kEthernetDevicePath, shill::kTypeEthernet,
-                             "stub_ethernet_device1");
-
-    device_test()->AddDevice(kWifiDevicePath, shill::kTypeWifi,
-                             "stub_wifi_device1");
-    base::ListValue wifi_ip_configs;
-    wifi_ip_configs.Append(kIPConfigPath);
-    SetDeviceProperty(kWifiDevicePath, shill::kIPConfigsProperty,
-                      wifi_ip_configs);
-    SetDeviceProperty(kWifiDevicePath, shill::kAddressProperty,
-                      base::Value("001122aabbcc"));
-
-    // Add Services
-    AddService("stub_ethernet", "eth0", shill::kTypeEthernet,
-               shill::kStateOnline);
-    service_test()->SetServiceProperty(
-        "stub_ethernet", shill::kProfileProperty,
-        base::Value(ShillProfileClient::GetSharedProfilePath()));
-    profile_test()->AddService(ShillProfileClient::GetSharedProfilePath(),
-                               "stub_ethernet");
-
-    AddService(kWifi1ServicePath, "wifi1", shill::kTypeWifi,
-               shill::kStateOnline);
-    service_test()->SetServiceProperty(kWifi1ServicePath,
-                                       shill::kSecurityClassProperty,
-                                       base::Value(shill::kSecurityWep));
-    service_test()->SetServiceProperty(kWifi1ServicePath, shill::kWifiBSsid,
-                                       base::Value("00:01:02:03:04:05"));
-    service_test()->SetServiceProperty(
-        kWifi1ServicePath, shill::kSignalStrengthProperty, base::Value(40));
-    service_test()->SetServiceProperty(kWifi1ServicePath,
-                                       shill::kProfileProperty,
-                                       base::Value(kUser1ProfilePath));
-    service_test()->SetServiceProperty(
-        kWifi1ServicePath, shill::kConnectableProperty, base::Value(true));
-    service_test()->SetServiceProperty(kWifi1ServicePath,
-                                       shill::kDeviceProperty,
-                                       base::Value(kWifiDevicePath));
-    base::DictionaryValue static_ipconfig;
-    static_ipconfig.SetKey(shill::kAddressProperty, base::Value("1.2.3.4"));
-    static_ipconfig.SetKey(shill::kGatewayProperty, base::Value("0.0.0.0"));
-    static_ipconfig.SetKey(shill::kPrefixlenProperty, base::Value(1));
-    service_test()->SetServiceProperty(
-        kWifi1ServicePath, shill::kStaticIPConfigProperty, static_ipconfig);
-    base::ListValue frequencies1;
-    frequencies1.Append(2400);
-    service_test()->SetServiceProperty(
-        kWifi1ServicePath, shill::kWifiFrequencyListProperty, frequencies1);
-    service_test()->SetServiceProperty(kWifi1ServicePath, shill::kWifiFrequency,
-                                       base::Value(2400));
-    profile_test()->AddService(kUser1ProfilePath, kWifi1ServicePath);
-
-    AddService(kWifi2ServicePath, "wifi2_PSK", shill::kTypeWifi,
-               shill::kStateIdle);
-    service_test()->SetServiceProperty(kWifi2ServicePath,
-                                       shill::kSecurityClassProperty,
-                                       base::Value(shill::kSecurityPsk));
-    service_test()->SetServiceProperty(
-        kWifi2ServicePath, shill::kSignalStrengthProperty, base::Value(80));
-    service_test()->SetServiceProperty(
-        kWifi2ServicePath, shill::kConnectableProperty, base::Value(true));
-
-    base::ListValue frequencies2;
-    frequencies2.Append(2400);
-    frequencies2.Append(5000);
-    service_test()->SetServiceProperty(
-        kWifi2ServicePath, shill::kWifiFrequencyListProperty, frequencies2);
-    service_test()->SetServiceProperty(kWifi2ServicePath, shill::kWifiFrequency,
-                                       base::Value(5000));
-    service_test()->SetServiceProperty(kWifi2ServicePath,
-                                       shill::kProfileProperty,
-                                       base::Value(kUser1ProfilePath));
-    profile_test()->AddService(kUser1ProfilePath, kWifi2ServicePath);
-
-    AddService("stub_vpn1", "vpn1", shill::kTypeVPN, shill::kStateOnline);
-    service_test()->SetServiceProperty("stub_vpn1",
-                                       shill::kProviderTypeProperty,
-                                       base::Value(shill::kProviderOpenVpn));
-    profile_test()->AddService(kUser1ProfilePath, "stub_vpn1");
-
-    AddService("stub_vpn2", "vpn2", shill::kTypeVPN, shill::kStateOffline);
-    service_test()->SetServiceProperty(
-        "stub_vpn2", shill::kProviderTypeProperty,
-        base::Value(shill::kProviderThirdPartyVpn));
-    service_test()->SetServiceProperty(
-        "stub_vpn2", shill::kProviderHostProperty,
-        base::Value("third_party_provider_extension_id"));
-    profile_test()->AddService(kUser1ProfilePath, "stub_vpn2");
-
-    PrefProxyConfigTrackerImpl::RegisterProfilePrefs(user_prefs_.registry());
-    PrefProxyConfigTrackerImpl::RegisterPrefs(local_state_.registry());
-    network_handler_test_helper_->RegisterPrefs(user_prefs_.registry(),
-                                                local_state_.registry());
-
-    network_handler_test_helper_->InitializePrefs(&user_prefs_, &local_state_);
-
-    content::RunAllPendingInMessageLoop();
-  }
-
-  void TearDownOnMainThread() { network_handler_test_helper_.reset(); }
-
   ShillServiceClient::TestInterface* service_test() {
     return network_handler_test_helper_->service_test();
   }
@@ -413,74 +362,384 @@
     return network_handler_test_helper_->manager_test();
   }
 
+  // extensions::ExtensionApiTest overrides:
+
+  void SetUpInProcessBrowserTestFixture() override {
+    provider_.SetDefaultReturns(
+        /*is_initialization_complete_return=*/true,
+        /*is_first_policy_load_complete_return=*/true);
+    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
+
+    extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture();
+  }
+
+  void SetUpOnMainThread() override {
+    extensions::ExtensionApiTest::SetUpOnMainThread();
+    content::RunAllPendingInMessageLoop();
+
+    NetworkingPrivateDelegateFactory::GetInstance()->SetTestingFactory(
+        profile(), base::BindRepeating(&CreateNetworkingPrivateDelegate));
+
+    network_handler_test_helper_ =
+        std::make_unique<chromeos::NetworkHandlerTestHelper>();
+
+    ConfigFakeNetwork();
+
+    PrefProxyConfigTrackerImpl::RegisterProfilePrefs(user_prefs_.registry());
+    PrefProxyConfigTrackerImpl::RegisterPrefs(local_state_.registry());
+    network_handler_test_helper_->RegisterPrefs(user_prefs_.registry(),
+                                                local_state_.registry());
+
+    network_handler_test_helper_->InitializePrefs(&user_prefs_, &local_state_);
+
+    base::RunLoop().RunUntilIdle();
+  }
+
+  void TearDownOnMainThread() override { network_handler_test_helper_.reset(); }
+
+  // NetworkingPrivateChromeOSApiTestBase overrides:
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    NetworkingPrivateChromeOSApiTestBase::SetUpCommandLine(command_line);
+
+    // TODO(pneubeck): Remove the following hack, once the NetworkingPrivateAPI
+    // uses the ProfileHelper to obtain the userhash crbug/238623.
+    cryptohome::AccountIdentifier login_user;
+    login_user.set_account_id(user_manager::CanonicalizeUserID(
+        command_line->GetSwitchValueNative(ash::switches::kLoginUser)));
+    const std::string sanitized_user =
+        UserDataAuthClient::GetStubSanitizedUsername(login_user);
+    command_line->AppendSwitchASCII(ash::switches::kLoginProfile,
+                                    sanitized_user);
+  }
+
+  std::string GetSanitizedActiveUsername() override {
+    user_manager::UserManager* user_manager = user_manager::UserManager::Get();
+    user_manager::User* user = user_manager->GetActiveUser();
+    CHECK(user);
+    std::string userhash;
+    ::user_data_auth::GetSanitizedUsernameRequest request;
+    request.set_username(
+        cryptohome::CreateAccountIdentifierFromAccountId(user->GetAccountId())
+            .account_id());
+    ash::CryptohomeMiscClient::Get()->GetSanitizedUsername(
+        request,
+        base::BindOnce(
+            [](std::string* out,
+               absl::optional<::user_data_auth::GetSanitizedUsernameReply>
+                   result) {
+              CHECK(result.has_value());
+              *out = result->sanitized_username();
+            },
+            &userhash));
+    base::RunLoop().RunUntilIdle();
+    CHECK(!userhash.empty());
+    return userhash;
+  }
+
+  void SetupCellular() override {
+    UIDelegateStub::s_show_account_details_called_ = 0;
+    NetworkingPrivateChromeOSApiTestBase::SetupCellular();
+    base::RunLoop().RunUntilIdle();
+  }
+
+  void AddDevice(const std::string& device_path,
+                 const std::string& type,
+                 const std::string& name) override {
+    device_test()->AddDevice(device_path, type, name);
+  }
+
+  void ClearDevices() override { device_test()->ClearDevices(); }
+
+  void SetDeviceProperty(const std::string& device_path,
+                         const std::string& name,
+                         const base::Value& value) override {
+    device_test()->SetDeviceProperty(device_path, name, value,
+                                     /*notify_changed=*/true);
+  }
+
+  void SetSimLocked(const std::string& device_path, bool enabled) override {
+    device_test()->SetSimLocked(device_path, enabled);
+  }
+
+  void AddService(const std::string& service_path,
+                  const std::string& name,
+                  const std::string& type,
+                  const std::string& state) override {
+    service_test()->AddService(service_path, service_path + "_guid", name, type,
+                               state, true /* add_to_visible */);
+  }
+
+  void ClearServices() override { service_test()->ClearServices(); }
+
+  void SetServiceProperty(const std::string& service_path,
+                          const std::string& property,
+                          const base::Value& value) override {
+    service_test()->SetServiceProperty(service_path, property, value);
+  }
+
+  void AddIPConfig(const std::string& ip_config_path,
+                   const base::Value& properties) override {
+    network_handler_test_helper_->ip_config_test()->AddIPConfig(ip_config_path,
+                                                                properties);
+  }
+
+  void AddProfile(const std::string& profile_path,
+                  const std::string& userhash) override {
+    profile_test()->AddProfile(profile_path, userhash);
+  }
+
+  void AddServiceToProfile(const std::string& profile_path,
+                           const std::string& service_path) override {
+    profile_test()->AddService(profile_path, service_path);
+  }
+
+  std::string GetSharedProfilePath() override {
+    return ShillProfileClient::GetSharedProfilePath();
+  }
+
  protected:
   std::unique_ptr<chromeos::NetworkHandlerTestHelper>
       network_handler_test_helper_;
   testing::NiceMock<policy::MockConfigurationPolicyProvider> provider_;
   sync_preferences::TestingPrefServiceSyncable user_prefs_;
   TestingPrefServiceSimple local_state_;
-  std::string userhash_;
 };
+#else
+class NetworkingPrivateChromeOSApiTestLacros
+    : public NetworkingPrivateChromeOSApiTestBase {
+ public:
+  NetworkingPrivateChromeOSApiTestLacros() {}
+
+  NetworkingPrivateChromeOSApiTestLacros(
+      const NetworkingPrivateChromeOSApiTestLacros&) = delete;
+  NetworkingPrivateChromeOSApiTestLacros& operator=(
+      const NetworkingPrivateChromeOSApiTestLacros&) = delete;
+
+  bool SetUpAsh() {
+    auto* service = chromeos::LacrosService::Get();
+    if (!service->IsAvailable<crosapi::mojom::TestController>() ||
+        service->GetInterfaceVersion(crosapi::mojom::TestController::Uuid_) <
+            static_cast<int>(crosapi::mojom::TestController::MethodMinVersions::
+                                 kBindShillClientTestInterfaceMinVersion)) {
+      LOG(ERROR) << "Unsupported ash version.";
+      return false;
+    }
+    crosapi::mojom::TestControllerAsyncWaiter test_controller_waiter{
+        service->GetRemote<crosapi::mojom::TestController>().get()};
+
+    test_controller_waiter.BindShillClientTestInterface(
+        shill_test_.BindNewPipeAndPassReceiver());
+
+    ConfigFakeNetwork();
+
+    return true;
+  }
+
+  // NetworkingPrivateChromeOSApiTestBase overrides
+
+  std::string GetSanitizedActiveUsername() override {
+    auto* service = chromeos::LacrosService::Get();
+    if (!service->IsAvailable<crosapi::mojom::TestController>() ||
+        service->GetInterfaceVersion(crosapi::mojom::TestController::Uuid_) <
+            static_cast<int>(crosapi::mojom::TestController::MethodMinVersions::
+                                 kGetSanitizedActiveUsernameMinVersion)) {
+      LOG(ERROR) << "Unsupported ash version.";
+      return "";
+    }
+
+    crosapi::mojom::TestControllerAsyncWaiter test_controller_waiter{
+        service->GetRemote<crosapi::mojom::TestController>().get()};
+
+    std::string userhash;
+    test_controller_waiter.GetSanitizedActiveUsername(&userhash);
+    return userhash;
+  }
+
+  void AddDevice(const std::string& device_path,
+                 const std::string& type,
+                 const std::string& name) override {
+    ShillClientTestInterfaceAsyncWaiter(shill_test_.get())
+        .AddDevice(device_path, type, name);
+  }
+
+  void SetDeviceProperty(const std::string& device_path,
+                         const std::string& name,
+                         const base::Value& value) override {
+    ShillClientTestInterfaceAsyncWaiter(shill_test_.get())
+        .SetDeviceProperty(device_path, name, value.Clone(),
+                           /*notify_changed=*/true);
+  }
+
+  void SetSimLocked(const std::string& device_path, bool enabled) override {
+    ShillClientTestInterfaceAsyncWaiter(shill_test_.get())
+        .SetSimLocked(device_path, enabled);
+  }
+
+  void ClearDevices() override {
+    ShillClientTestInterfaceAsyncWaiter(shill_test_.get()).ClearDevices();
+  }
+
+  void AddService(const std::string& service_path,
+                  const std::string& name,
+                  const std::string& type,
+                  const std::string& state) override {
+    ShillClientTestInterfaceAsyncWaiter(shill_test_.get())
+        .AddService(service_path, service_path + "_guid", name, type, state,
+                    true /* add_to_visible */);
+  }
+
+  void ClearServices() override {
+    ShillClientTestInterfaceAsyncWaiter(shill_test_.get()).ClearServices();
+  }
+
+  void SetServiceProperty(const std::string& service_path,
+                          const std::string& property,
+                          const base::Value& value) override {
+    ShillClientTestInterfaceAsyncWaiter(shill_test_.get())
+        .SetServiceProperty(service_path, property, value.Clone());
+  }
+
+  void AddIPConfig(const std::string& ip_config_path,
+                   const base::Value& properties) override {
+    ShillClientTestInterfaceAsyncWaiter(shill_test_.get())
+        .AddIPConfig(ip_config_path, properties.Clone());
+  }
+
+  void AddProfile(const std::string& profile_path,
+                  const std::string& userhash) override {
+    ShillClientTestInterfaceAsyncWaiter(shill_test_.get())
+        .AddProfile(profile_path, userhash);
+  }
+
+  void AddServiceToProfile(const std::string& profile_path,
+                           const std::string& service_path) override {
+    ShillClientTestInterfaceAsyncWaiter(shill_test_.get())
+        .AddServiceToProfile(profile_path, service_path);
+  }
+
+  std::string GetSharedProfilePath() override {
+    // TODO(crbug.com/): get this information from Ash
+    const char kSharedProfilePath[] = "/profile/default";
+    return kSharedProfilePath;
+  }
+
+ protected:
+  mojo::Remote<crosapi::mojom::ShillClientTestInterface> shill_test_;
+};
+#endif
+
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+using NetworkingPrivateChromeOSApiTest = NetworkingPrivateChromeOSApiTestLacros;
+#else
+using NetworkingPrivateChromeOSApiTest = NetworkingPrivateChromeOSApiTestAsh;
+#endif
 
 // Place each subtest into a separate browser test so that the stub networking
 // library state is reset for each subtest run. This way they won't affect each
 // other.
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, StartConnect) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("startConnect")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, StartDisconnect) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("startDisconnect")) << message_;
 }
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, StartActivate) {
   SetupCellular();
   EXPECT_TRUE(RunNetworkingSubtest("startActivate")) << message_;
   EXPECT_EQ(1, UIDelegateStub::s_show_account_details_called_);
 }
+#endif
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                        StartConnectNonexistent) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("startConnectNonexistent")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                        StartDisconnectNonexistent) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("startDisconnectNonexistent")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                        StartGetPropertiesNonexistent) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("startGetPropertiesNonexistent"))
       << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetNetworks) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   // Hide stub_wifi2.
-  service_test()->SetServiceProperty(kWifi2ServicePath, shill::kVisibleProperty,
-                                     base::Value(false));
+  SetServiceProperty(kWifi2ServicePath, shill::kVisibleProperty,
+                     base::Value(false));
   // Add a couple of additional networks that are not configured (saved).
   AddService("stub_wifi3", "wifi3", shill::kTypeWifi, shill::kStateIdle);
   AddService("stub_wifi4", "wifi4", shill::kTypeWifi, shill::kStateIdle);
   content::RunAllPendingInMessageLoop();
+
   EXPECT_TRUE(RunNetworkingSubtest("getNetworks")) << message_;
 }
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetVisibleNetworks) {
   EXPECT_TRUE(RunNetworkingSubtest("getVisibleNetworks")) << message_;
 }
+#endif
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                        GetVisibleNetworksWifi) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("getVisibleNetworksWifi")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, EnabledNetworkTypes) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("enabledNetworkTypesDisable")) << message_;
   EXPECT_TRUE(RunNetworkingSubtest("enabledNetworkTypesEnable")) << message_;
 }
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetDeviceStates) {
   SetupCellular();
   manager_test()->RemoveTechnology("cellular");
@@ -488,13 +747,24 @@
   manager_test()->SetTechnologyInitializing("cellular", true);
   EXPECT_TRUE(RunNetworkingSubtest("getDeviceStates")) << message_;
 }
+#endif
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, RequestNetworkScan) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("requestNetworkScan")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                        RequestNetworkScanCellular) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   SetupCellular();
   EXPECT_TRUE(RunNetworkingSubtest("requestNetworkScanCellular")) << message_;
 }
@@ -502,23 +772,41 @@
 // Properties are filtered and translated through
 // ShillToONCTranslator::TranslateWiFiWithState
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetProperties) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("getProperties")) << message_;
 }
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                        GetCellularProperties) {
   SetupCellular();
   EXPECT_TRUE(RunNetworkingSubtest("getPropertiesCellular")) << message_;
 }
+#endif
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetState) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("getState")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetStateNonExistent) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("getStateNonExistent")) << message_;
 }
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                        SetCellularProperties) {
   SetupCellular();
@@ -567,11 +855,18 @@
 
   EXPECT_TRUE(RunNetworkingSubtest("createNetworkForPolicyControlledNetwork"));
 }
+#endif
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, ForgetNetwork) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("forgetNetwork")) << message_;
 }
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                        ForgetPolicyControlledNetwork) {
   constexpr char kUserPolicyBlob[] =
@@ -657,36 +952,63 @@
       kWifi1ServicePath, "TestErrorState");
   EXPECT_TRUE(RunNetworkingSubtest("getErrorState")) << message_;
 }
+#endif
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                        OnNetworksChangedEventConnect) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("onNetworksChangedEventConnect"))
       << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                        OnNetworksChangedEventDisconnect) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("onNetworksChangedEventDisconnect"))
       << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                        OnNetworkListChangedEvent) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("onNetworkListChangedEvent")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                        OnDeviceStateListChangedEvent) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   EXPECT_TRUE(RunNetworkingSubtest("onDeviceStateListChangedEvent"))
       << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                        OnDeviceScanningChangedEvent) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   SetupCellular();
   EXPECT_TRUE(RunNetworkingSubtest("onDeviceScanningChangedEvent")) << message_;
 }
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                        OnCertificateListsChangedEvent) {
   ExtensionTestMessageListener listener("eventListenerReady");
@@ -703,10 +1025,10 @@
                        GetCaptivePortalStatus) {
   // Ethernet defaults to online. Set wifi1 to idle -> 'Offline', and wifi2 to
   // redirect-found -> 'Portal'.
-  service_test()->SetServiceProperty(kWifi1ServicePath, shill::kStateProperty,
-                                     base::Value(shill::kStateIdle));
-  service_test()->SetServiceProperty(kWifi2ServicePath, shill::kStateProperty,
-                                     base::Value(shill::kStateRedirectFound));
+  SetServiceProperty(kWifi1ServicePath, shill::kStateProperty,
+                     base::Value(shill::kStateIdle));
+  SetServiceProperty(kWifi2ServicePath, shill::kStateProperty,
+                     base::Value(shill::kStateRedirectFound));
   base::RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(RunNetworkingSubtest("getCaptivePortalStatus")) << message_;
@@ -722,28 +1044,43 @@
   ExtensionTestMessageListener listener("notifyPortalDetectorObservers");
   listener.SetOnSatisfied(
       base::BindLambdaForTesting([&](const std::string& message) {
-        service_test()->SetServiceProperty(
-            kWifi1ServicePath, shill::kStateProperty,
-            base::Value(shill::kStateRedirectFound));
+        SetServiceProperty(kWifi1ServicePath, shill::kStateProperty,
+                           base::Value(shill::kStateRedirectFound));
       }));
 
   EXPECT_TRUE(RunNetworkingSubtest("captivePortalNotification")) << message_;
 }
+#endif
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, UnlockCellularSim) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   SetupCellular();
   // Lock the SIM
-  device_test()->SetSimLocked(kCellularDevicePath, true);
+  SetSimLocked(kCellularDevicePath, true);
   EXPECT_TRUE(RunNetworkingSubtest("unlockCellularSim")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, SetCellularSimState) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   SetupCellular();
   EXPECT_TRUE(RunNetworkingSubtest("setCellularSimState")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                        SelectCellularMobileNetwork) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   SetupCellular();
   // Create fake list of found networks.
   std::unique_ptr<base::ListValue> found_networks =
@@ -765,12 +1102,18 @@
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, CellularSimPuk) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (!SetUpAsh()) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+#endif
   SetupCellular();
   // Lock the SIM
-  device_test()->SetSimLocked(kCellularDevicePath, true);
+  SetSimLocked(kCellularDevicePath, true);
   EXPECT_TRUE(RunNetworkingSubtest("cellularSimPuk")) << message_;
 }
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetGlobalPolicy) {
   base::DictionaryValue global_config;
   global_config.SetKey(
@@ -831,5 +1174,6 @@
                                {.launch_as_platform_app = true}))
       << message_;
 }
+#endif
 
 }  // namespace
diff --git a/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java b/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java
index 88de5abd..1d8a79bf 100644
--- a/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java
+++ b/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java
@@ -17,6 +17,7 @@
 import org.chromium.base.Callback;
 import org.chromium.base.CollectionUtil;
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.task.PostTask;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
@@ -203,6 +204,8 @@
             }
         }
 
+        RecordHistogram.recordMediumTimesHistogram("Feedback.Duration.FetchSystemInformation",
+                SystemClock.elapsedRealtime() - mStartTime);
         final Callback<FeedbackCollector> callback = mCallback;
         mCallback = null;
 
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index c6871aab..75566e4f 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -604,8 +604,8 @@
   },
   {
     "name": "biometric-reauth-password-filling",
-    "owners": [ "ioanap" ],
-    "expiry_milestone": 104
+    "owners": [ "ioanap", "vsemeniuk@google.com" ],
+    "expiry_milestone": 108
   },
   {
     "name": "block-insecure-private-network-requests",
diff --git a/chrome/browser/lacros/browser_service_lacros.cc b/chrome/browser/lacros/browser_service_lacros.cc
index 8451b454..8b69149 100644
--- a/chrome/browser/lacros/browser_service_lacros.cc
+++ b/chrome/browser/lacros/browser_service_lacros.cc
@@ -211,7 +211,8 @@
 void BrowserServiceLacros::NewWindow(bool incognito,
                                      bool should_trigger_session_restore,
                                      NewWindowCallback callback) {
-  if (ProfilePicker::ShouldShowAtLaunch() && !incognito) {
+  if (ProfilePicker::ShouldShowAtLaunch() &&
+      chrome::GetTotalBrowserCount() == 0 && !incognito) {
     // Profile picker does not support passing through the incognito param. It
     // also does not support passing through the
     // `should_trigger_session_restore` param but that's very common (left
diff --git a/chrome/browser/lacros/browser_service_lacros_browsertest.cc b/chrome/browser/lacros/browser_service_lacros_browsertest.cc
index a384023..c28faaa 100644
--- a/chrome/browser/lacros/browser_service_lacros_browsertest.cc
+++ b/chrome/browser/lacros/browser_service_lacros_browsertest.cc
@@ -163,29 +163,59 @@
 }
 
 IN_PROC_BROWSER_TEST_F(BrowserServiceLacrosBrowserTest,
-                       ProfilePickerOpensOnStartup) {
-  Profile* main_profile = browser()->profile();
+                       NewWindow_OpensProfilePicker) {
+  // Keep the browser process running during the test while the browser is
+  // closed.
+  ScopedKeepAlive keep_alive(KeepAliveOrigin::BROWSER,
+                             KeepAliveRestartOption::DISABLED);
+  ProfileManager* profile_manager = g_browser_process->profile_manager();
+
+  // Start in a state with no browser windows opened.
+  CloseBrowserSynchronously(browser());
+  EXPECT_EQ(0u, chrome::GetTotalBrowserCount());
+
+  // `NewWindow()` should create a new window if the system has only one
+  // profile.
+  NewWindowSync(/*incognito=*/false, /*should_trigger_session_restore=*/false);
+  EXPECT_FALSE(ProfilePicker::IsOpen());
+  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
 
   // Create an additional profile.
-  ProfileManager* profile_manager = g_browser_process->profile_manager();
   base::FilePath path_profile2 =
       profile_manager->user_data_dir().Append(FILE_PATH_LITERAL("Profile 2"));
-
   Profile* profile2 =
       profiles::testing::CreateProfileSync(profile_manager, path_profile2);
   // Open a browser window to make it the last used profile.
   chrome::NewEmptyWindow(profile2);
-  ui_test_utils::WaitForBrowserToOpen();
+  Browser* browser2 = ui_test_utils::WaitForBrowserToOpen();
+  EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
 
   // Profile picker does _not_ open for incognito windows. Instead, the
-  // incognito window for the last used profile is directly opened.
+  // incognito window for the main profile is directly opened.
   NewWindowSync(/*incognito=*/true, /*should_trigger_session_restore=*/false);
   EXPECT_FALSE(ProfilePicker::IsOpen());
+  EXPECT_EQ(3u, chrome::GetTotalBrowserCount());
   Profile* profile = BrowserList::GetInstance()->GetLastActive()->profile();
   // Main profile should be always used.
-  EXPECT_EQ(profile->GetPath(), main_profile->GetPath());
+  EXPECT_EQ(profile->GetPath(), profile_manager->GetPrimaryUserProfilePath());
   EXPECT_TRUE(profile->IsOffTheRecord());
 
+  BrowserList::SetLastActive(browser2);
+  // Profile picker does _not_ open if Chrome already has opened windows.
+  // Instead, a new browser window for the main profile is directly opened.
+  NewWindowSync(/*incognito=*/false, /*should_trigger_session_restore=*/false);
+  EXPECT_FALSE(ProfilePicker::IsOpen());
+  // A new browser is created for the main profile.
+  EXPECT_EQ(BrowserList::GetInstance()->GetLastActive()->profile()->GetPath(),
+            profile_manager->GetPrimaryUserProfilePath());
+  EXPECT_EQ(4u, chrome::GetTotalBrowserCount());
+
+  size_t browser_count = chrome::GetTotalBrowserCount();
+  chrome::CloseAllBrowsers();
+  for (size_t i = 0; i < browser_count; ++i)
+    ui_test_utils::WaitForBrowserToClose();
+
+  // `NewWindow()` should open the profile picker.
   NewWindowSync(/*incognito=*/false, /*should_trigger_session_restore=*/false);
   EXPECT_TRUE(ProfilePicker::IsOpen());
 }
diff --git a/chrome/browser/lacros/launcher_search/search_controller_lacros.cc b/chrome/browser/lacros/launcher_search/search_controller_lacros.cc
index 395d3148..06994e61 100644
--- a/chrome/browser/lacros/launcher_search/search_controller_lacros.cc
+++ b/chrome/browser/lacros/launcher_search/search_controller_lacros.cc
@@ -10,9 +10,9 @@
 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/launcher_search/search_util.h"
 #include "chrome/browser/favicon/favicon_service_factory.h"
 #include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/lacros/launcher_search/search_util.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chromeos/lacros/lacros_service.h"
 #include "components/bookmarks/browser/bookmark_model.h"
diff --git a/chrome/browser/metrics/perf/metric_provider.cc b/chrome/browser/metrics/perf/metric_provider.cc
index f778c81..eca2804 100644
--- a/chrome/browser/metrics/perf/metric_provider.cc
+++ b/chrome/browser/metrics/perf/metric_provider.cc
@@ -193,25 +193,12 @@
     return RecordAttemptStatus::kSyncServiceUnavailable;
   syncer::SyncUserSettings* sync_settings = sync_service->GetUserSettings();
 
-  // IsSyncFeatureEnabled should be checked regardless of
-  // SyncSettingsCategorization status.
   if (!sync_service->IsSyncFeatureEnabled())
     return RecordAttemptStatus::kChromeSyncFeatureDisabled;
 
-  // SyncSettingsCategorization splits the sync settings between Chrome and
-  // ChromeOS. The App Sync toggle is moved under the ChromeOS settings.
-  // If SyncSettingsCategorization is enabled, we will directly read from
-  // the OS settings.
-  if (chromeos::features::IsSyncSettingsCategorizationEnabled()) {
-    if (!sync_settings->GetSelectedOsTypes().Has(
-            syncer::UserSelectableOsType::kOsApps))
-      return RecordAttemptStatus::kOSAppSyncDisabled;
-    return RecordAttemptStatus::kAppSyncEnabled;
-  }
-
-  // Read chrome settings if SyncSettingsCategorization is disabled.
-  if (!sync_settings->GetSelectedTypes().Has(syncer::UserSelectableType::kApps))
-    return RecordAttemptStatus::kChromeAppSyncDisabled;
+  if (!sync_settings->GetSelectedOsTypes().Has(
+          syncer::UserSelectableOsType::kOsApps))
+    return RecordAttemptStatus::kOSAppSyncDisabled;
   return RecordAttemptStatus::kAppSyncEnabled;
 }
 
diff --git a/chrome/browser/metrics/perf/metric_provider.h b/chrome/browser/metrics/perf/metric_provider.h
index 0b239d91..1c92ab4 100644
--- a/chrome/browser/metrics/perf/metric_provider.h
+++ b/chrome/browser/metrics/perf/metric_provider.h
@@ -80,7 +80,7 @@
     kAppSyncEnabled = 4,
     kSyncServiceUnavailable = 5,
     kChromeSyncFeatureDisabled = 6,
-    kChromeAppSyncDisabled = 7,
+    // Deprecated: kChromeAppSyncDisabled = 7,
     // Deprecated: kOSSyncFeatureDisabled = 8,
     kOSAppSyncDisabled = 9,
     kMaxValue = kOSAppSyncDisabled,
diff --git a/chrome/browser/metrics/perf/metric_provider_unittest.cc b/chrome/browser/metrics/perf/metric_provider_unittest.cc
index 4a318b3f..e56b65e 100644
--- a/chrome/browser/metrics/perf/metric_provider_unittest.cc
+++ b/chrome/browser/metrics/perf/metric_provider_unittest.cc
@@ -11,7 +11,6 @@
 #include <utility>
 #include <vector>
 
-#include "ash/constants/ash_features.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
@@ -376,8 +375,6 @@
 
   std::unique_ptr<TestMetricProvider> metric_provider_;
 
-  base::test::ScopedFeatureList feature_list_;
-
   PerfDataProto perf_data_unchanged_;
 
   PerfDataProto perf_data_redacted_;
@@ -405,13 +402,10 @@
       TestMetricProvider::RecordAttemptStatus::kNoLoadedProfile, 1);
 }
 
-TEST_F(MetricProviderSyncSettingsTest,
-       SettingsCategorizationSyncFeatureDisabled) {
+TEST_F(MetricProviderSyncSettingsTest, SyncFeatureDisabled) {
   base::HistogramTester histogram_tester;
   std::vector<SampledProfile> stored_profiles;
   metric_provider_->OnUserLoggedIn();
-  feature_list_.InitAndEnableFeature(
-      chromeos::features::kSyncSettingsCategorization);
 
   // The first testing profile has both sync-the-feature and App sync enabled.
   TestSyncService* sync_service1 =
@@ -439,12 +433,10 @@
       TestMetricProvider::RecordAttemptStatus::kChromeSyncFeatureDisabled, 1);
 }
 
-TEST_F(MetricProviderSyncSettingsTest, SettingsCategorizationAppSyncEnabled) {
+TEST_F(MetricProviderSyncSettingsTest, AppSyncEnabled) {
   base::HistogramTester histogram_tester;
   std::vector<SampledProfile> stored_profiles;
   metric_provider_->OnUserLoggedIn();
-  feature_list_.InitAndEnableFeature(
-      chromeos::features::kSyncSettingsCategorization);
 
   // Set up two testing profiles, both with OS App Sync enabled. The Default
   // profile has OS App Sync disabled but is skipped.
@@ -469,12 +461,10 @@
       TestMetricProvider::RecordAttemptStatus::kAppSyncEnabled, 1);
 }
 
-TEST_F(MetricProviderSyncSettingsTest, SettingsCategorizationAppSyncDisabled) {
+TEST_F(MetricProviderSyncSettingsTest, AppSyncDisabled) {
   base::HistogramTester histogram_tester;
   std::vector<SampledProfile> stored_profiles;
   metric_provider_->OnUserLoggedIn();
-  feature_list_.InitAndEnableFeature(
-      chromeos::features::kSyncSettingsCategorization);
 
   // Set up two testing profiles, one with OS App Sync enabled and the other
   // disabled.
@@ -499,64 +489,4 @@
       TestMetricProvider::RecordAttemptStatus::kOSAppSyncDisabled, 1);
 }
 
-TEST_F(MetricProviderSyncSettingsTest, UnifiedSettingsAppSyncEnabled) {
-  base::HistogramTester histogram_tester;
-  std::vector<SampledProfile> stored_profiles;
-  metric_provider_->OnUserLoggedIn();
-  feature_list_.InitAndDisableFeature(
-      chromeos::features::kSyncSettingsCategorization);
-
-  // Set up two testing profiles, both with App Sync enabled. The Default
-  // profile has App Sync disabled but is skipped.
-  TestSyncService* sync_service1 =
-      GetSyncService(testing_profile_manager_->CreateTestingProfile("user1"));
-  TestSyncService* sync_service2 =
-      GetSyncService(testing_profile_manager_->CreateTestingProfile("user2"));
-  EnableAppSync(sync_service1);
-  EnableAppSync(sync_service2);
-
-  task_environment_.FastForwardBy(kPeriodicCollectionInterval);
-
-  EXPECT_TRUE(metric_provider_->GetSampledProfiles(&stored_profiles));
-  EXPECT_EQ(stored_profiles.size(), 1u);
-
-  const SampledProfile& profile = stored_profiles[0];
-  EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event());
-  EXPECT_EQ(SerializeMessageToVector(perf_data_unchanged_),
-            SerializeMessageToVector(profile.perf_data()));
-  histogram_tester.ExpectUniqueSample(
-      "ChromeOS.CWP.RecordTest",
-      TestMetricProvider::RecordAttemptStatus::kAppSyncEnabled, 1);
-}
-
-TEST_F(MetricProviderSyncSettingsTest, UnifiedSettingsAppSyncDisabled) {
-  base::HistogramTester histogram_tester;
-  std::vector<SampledProfile> stored_profiles;
-  metric_provider_->OnUserLoggedIn();
-  feature_list_.InitAndDisableFeature(
-      chromeos::features::kSyncSettingsCategorization);
-
-  // Set up two testing profiles, one with App Sync enabled and the other
-  // disabled.
-  TestSyncService* sync_service1 =
-      GetSyncService(testing_profile_manager_->CreateTestingProfile("user1"));
-  TestSyncService* sync_service2 =
-      GetSyncService(testing_profile_manager_->CreateTestingProfile("user2"));
-  EnableAppSync(sync_service1);
-  DisableAppSync(sync_service2);
-
-  task_environment_.FastForwardBy(kPeriodicCollectionInterval);
-
-  EXPECT_TRUE(metric_provider_->GetSampledProfiles(&stored_profiles));
-  EXPECT_EQ(stored_profiles.size(), 1u);
-
-  const SampledProfile& profile = stored_profiles[0];
-  EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event());
-  EXPECT_EQ(SerializeMessageToVector(perf_data_redacted_),
-            SerializeMessageToVector(profile.perf_data()));
-  histogram_tester.ExpectUniqueSample(
-      "ChromeOS.CWP.RecordTest",
-      TestMetricProvider::RecordAttemptStatus::kChromeAppSyncDisabled, 1);
-}
-
 }  // namespace metrics
diff --git a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc
index 894b7458..db36fd5 100644
--- a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc
@@ -258,6 +258,15 @@
 }
 
 page_load_metrics::PageLoadMetricsObserver::ObservePolicy
+UkmPageLoadMetricsObserver::OnPrerenderStart(
+    content::NavigationHandle* navigation_handle,
+    const GURL& currently_committed_url) {
+  // PrerenderPageLoadMetricsObserver records prerendering version of metrics
+  // and this PLMO can stop on prerendering.
+  return STOP_OBSERVING;
+}
+
+page_load_metrics::PageLoadMetricsObserver::ObservePolicy
 UkmPageLoadMetricsObserver::OnRedirect(
     content::NavigationHandle* navigation_handle) {
   main_frame_request_redirect_count_++;
diff --git a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.h
index 3b49da78..351da4c6 100644
--- a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.h
@@ -57,6 +57,8 @@
   ObservePolicy OnFencedFramesStart(
       content::NavigationHandle* navigation_handle,
       const GURL& currently_committed_url) override;
+  ObservePolicy OnPrerenderStart(content::NavigationHandle* navigation_handle,
+                                 const GURL& currently_committed_url) override;
 
   ObservePolicy OnRedirect(
       content::NavigationHandle* navigation_handle) override;
diff --git a/chrome/browser/password_manager/android/password_store_android_backend.cc b/chrome/browser/password_manager/android/password_store_android_backend.cc
index 387ef91d..9a0712e 100644
--- a/chrome/browser/password_manager/android/password_store_android_backend.cc
+++ b/chrome/browser/password_manager/android/password_store_android_backend.cc
@@ -361,11 +361,11 @@
 PasswordStoreAndroidBackend::~PasswordStoreAndroidBackend() = default;
 
 void PasswordStoreAndroidBackend::InitBackend(
-    RemoteChangesReceived stored_passwords_changed,
+    RemoteChangesReceived remote_form_changes_received,
     base::RepeatingClosure sync_enabled_or_disabled_cb,
     base::OnceCallback<void(bool)> completion) {
   main_task_runner_ = base::SequencedTaskRunnerHandle::Get();
-  stored_passwords_changed_ = std::move(stored_passwords_changed);
+  stored_passwords_changed_ = std::move(remote_form_changes_received);
   lifecycle_helper_->RegisterObserver(base::BindRepeating(
       &PasswordStoreAndroidBackend::OnForegroundSessionStart,
       base::Unretained(this)));
@@ -436,9 +436,8 @@
 void PasswordStoreAndroidBackend::AddLoginAsync(
     const PasswordForm& form,
     PasswordChangesOrErrorReply callback) {
-  // TODO(crbug.com/1324588): remove this check
-  CHECK(!form.blocked_by_user ||
-        (form.username_value.empty() && form.password_value.empty()));
+  DCHECK(!form.blocked_by_user ||
+         (form.username_value.empty() && form.password_value.empty()));
   JobId job_id =
       bridge_->AddLogin(form, GetAccount(GetSyncingAccount(sync_service_)));
   QueueNewJob(job_id, std::move(callback), MetricInfix("AddLoginAsync"));
@@ -447,9 +446,8 @@
 void PasswordStoreAndroidBackend::UpdateLoginAsync(
     const PasswordForm& form,
     PasswordChangesOrErrorReply callback) {
-  // TODO(crbug.com/1324588): remove this check
-  CHECK(!form.blocked_by_user ||
-        (form.username_value.empty() && form.password_value.empty()));
+  DCHECK(!form.blocked_by_user ||
+         (form.username_value.empty() && form.password_value.empty()));
   JobId job_id =
       bridge_->UpdateLogin(form, GetAccount(GetSyncingAccount(sync_service_)));
   QueueNewJob(job_id, std::move(callback), MetricInfix("UpdateLoginAsync"));
diff --git a/chrome/browser/password_manager/android/password_store_android_backend.h b/chrome/browser/password_manager/android/password_store_android_backend.h
index a2f351d..7fe1020 100644
--- a/chrome/browser/password_manager/android/password_store_android_backend.h
+++ b/chrome/browser/password_manager/android/password_store_android_backend.h
@@ -111,7 +111,7 @@
       std::unordered_map<JobId, JobReturnHandler, JobId::Hasher>>;
 
   // Implements PasswordStoreBackend interface.
-  void InitBackend(RemoteChangesReceived stored_passwords_changed,
+  void InitBackend(RemoteChangesReceived remote_form_changes_received,
                    base::RepeatingClosure sync_enabled_or_disabled_cb,
                    base::OnceCallback<void(bool)> completion) override;
   void Shutdown(base::OnceClosure shutdown_completed) override;
diff --git a/chrome/browser/password_manager/android/password_store_android_backend_unittest.cc b/chrome/browser/password_manager/android/password_store_android_backend_unittest.cc
index fb187b3e..fc62687 100644
--- a/chrome/browser/password_manager/android/password_store_android_backend_unittest.cc
+++ b/chrome/browser/password_manager/android/password_store_android_backend_unittest.cc
@@ -969,7 +969,7 @@
   base::MockCallback<PasswordStoreBackend::RemoteChangesReceived>
       store_notification_trigger;
   backend().InitBackend(
-      /*stored_passwords_changed=*/store_notification_trigger.Get(),
+      /*remote_form_changes_received=*/store_notification_trigger.Get(),
       /*sync_enabled_or_disabled_cb=*/base::DoNothing(),
       /*completion=*/base::DoNothing());
 
@@ -989,6 +989,8 @@
 
 TEST_F(PasswordStoreAndroidBackendTest, RecordClearedZombieTaskWithoutLatency) {
   constexpr JobId kJobId{1337};
+  const char kStartedMetric[] =
+      "PasswordManager.PasswordStoreAndroidBackend.AddLoginAsync";
   const char kDurationMetric[] =
       "PasswordManager.PasswordStoreAndroidBackend.AddLoginAsync.Latency";
   const char kSuccessMetric[] =
@@ -996,7 +998,7 @@
   const char kErrorCodeMetric[] =
       "PasswordManager.PasswordStoreAndroidBackend.ErrorCode";
   base::HistogramTester histogram_tester;
-  backend().InitBackend(/*stored_passwords_changed=*/base::DoNothing(),
+  backend().InitBackend(/*remote_form_changes_received=*/base::DoNothing(),
                         /*sync_enabled_or_disabled_cb=*/base::DoNothing(),
                         /*completion=*/base::DoNothing());
 
@@ -1033,6 +1035,39 @@
               ElementsAre(base::Bucket(false, 1)));
   EXPECT_THAT(histogram_tester.GetAllSamples(kErrorCodeMetric),
               ElementsAre(base::Bucket(8, 1)));  // Record only once.
+  EXPECT_THAT(histogram_tester.GetAllSamples(kStartedMetric),
+              ElementsAre(base::Bucket(/* Requested */ 0, 1),
+                          base::Bucket(/* Timeout */ 1, 1)));
+}
+TEST_F(PasswordStoreAndroidBackendTest, RecordsRequestStartAndEndMetric) {
+  constexpr JobId kJobId{1337};
+  const char kStartedMetric[] =
+      "PasswordManager.PasswordStoreAndroidBackend.AddLoginAsync";
+  base::HistogramTester histogram_tester;
+  backend().InitBackend(/*remote_form_changes_received=*/base::DoNothing(),
+                        /*sync_enabled_or_disabled_cb=*/base::DoNothing(),
+                        /*completion=*/base::DoNothing());
+
+  base::MockCallback<PasswordChangesOrErrorReply> mock_reply;
+  EXPECT_CALL(*bridge(), AddLogin).WillOnce(Return(kJobId));
+  // Since tasks are never run, the reply should never be called.
+  EXPECT_CALL(mock_reply, Run).Times(0);
+
+  backend().AddLoginAsync(
+      CreateTestLogin(kTestUsername, kTestPassword, kTestUrl, kTestDateCreated),
+      mock_reply.Get());
+
+  // Don't wait for execution, check that request start is already logged.
+  EXPECT_THAT(histogram_tester.GetAllSamples(kStartedMetric),
+              ElementsAre(base::Bucket(/* Requested */ 0, 1)));
+
+  task_environment_.FastForwardUntilNoTasksRemain();
+  consumer().OnLoginsChanged(kJobId, absl::nullopt);
+
+  // After execution, check that request is logged again.
+  EXPECT_THAT(histogram_tester.GetAllSamples(kStartedMetric),
+              ElementsAre(base::Bucket(/* Requested */ 0, 1),
+                          base::Bucket(/* Completed */ 2, 1)));
 }
 
 TEST_F(PasswordStoreAndroidBackendTest,
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index 11f54d1..ab8e034 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -716,7 +716,8 @@
           autofill::PersonalDataManagerFactory::GetForProfile(
               GetProfile()->GetOriginalProfile()),
           this,
-          &menu_model_) {
+          &menu_model_,
+          GetBrowser()) {
   if (!g_custom_id_ranges_initialized) {
     g_custom_id_ranges_initialized = true;
     SetContentCustomCommandIdRange(IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
diff --git a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js
index 16a666b..a46c82e 100644
--- a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js
+++ b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js
@@ -147,12 +147,4 @@
   sendNumberOfSelectedApps();
 }
 
-/**
- * Calculate height of the recommend-apps-container.
- * @return {number}
- */
-function getHeight() {
-  return document.querySelector('#recommend-apps-container').clientHeight;
-}
-
 window.addEventListener('message', onMessage_);
diff --git a/chrome/browser/resources/chromeos/arc_support/recommend_app_old_list_view.html b/chrome/browser/resources/chromeos/arc_support/recommend_app_old_list_view.html
deleted file mode 100644
index 0dbf8bb..0000000
--- a/chrome/browser/resources/chromeos/arc_support/recommend_app_old_list_view.html
+++ /dev/null
@@ -1,134 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <style>
-    :root {
-      color: #333;
-      font-family: 'Google Sans', Roboto, sans-serif;
-      font-size: 13px;
-      font-weight: 400; /* roboto-regular */
-    }
-
-    body {
-      margin: 0;
-    }
-
-    #recommend-apps-container {
-      box-sizing: border-box;
-      display: flex;
-      flex-flow: row wrap;
-      gap: 16px;
-      overflow: hidden;
-      padding: 2px;
-    }
-
-    #recommend-apps-container .item {
-      display: flex;
-      flex: 0 0 calc((100% - 32px) / 3); /* This size allows <= 3 items in a row */
-      flex-flow: row nowrap;
-      float: left;
-      max-width: 280px;
-      min-width: 156px;
-      position: relative;
-      user-select: none;
-    }
-
-    #recommend-apps-container .item .image-picker {
-      background: url(images/ic_checkmark.svg) no-repeat;
-      display: none;
-      flex-shrink: 0;
-      transform: translate(-32px, 8px);
-      width: 24px;
-    }
-
-    #recommend-apps-container .item.checked .image-picker {
-      display: block;
-    }
-
-    #recommend-apps-container .item .chip {
-      border-radius: 8px;
-      box-shadow:
-          1px 1px 4px rgba(60, 64, 67, 0.30),
-          1px 2px 4px 1px rgba(60, 64, 67, 0.15);
-      flex-shrink: 0;
-      height: 160px;
-      position: relative;
-      width: 100%;
-      --x: 0;
-      --y: 0;
-    }
-
-    #recommend-apps-container .item .chip .chip-content-container {
-      display: flex;
-      flex-direction: column;
-      height: 100%;
-      overflow: hidden;
-      position: relative;
-      text-align: center;
-    }
-
-    #recommend-apps-container .item .chip:focus,
-    #recommend-apps-container .item .chip .chip-content-container:focus {
-      outline: none;
-    }
-
-    #recommend-apps-container .item .chip:focus > .chip-content-container {
-      outline: 2px solid rgba(26, 115, 232, 0.5);
-    }
-
-    @keyframes ripple {
-      30% {
-        transform: scale(7);
-      }
-      100% {
-        opacity: 0;
-      }
-    }
-
-    #recommend-apps-container .item .chip .chip-content-container .ripple {
-      animation: ripple 1s forwards;
-      background: rgba(32, 33, 36, 0.14);
-      border-radius: 50%;
-      height: 100px;
-      margin-inline-start: calc(var(--x) * 1px);
-      margin-top: calc(var(--y) * 1px);
-      position: absolute;
-      transform: translate(-50%, -50%);
-      width: 100px;
-    }
-
-    #recommend-apps-container .item .chip:active {
-      box-shadow:
-          0 1px 2px 0 rgba(60, 64, 67, 0.30),
-          0 3px 6px 2px rgba(60, 64, 67, 0.15);
-    }
-
-    img.app-icon {
-      height: 48px;
-      margin-bottom: 20px;
-      margin-inline: auto;
-      margin-top: 32px;
-      vertical-align: middle;
-      width: 48px;
-    }
-
-    span.app-title {
-      color: rgb(32, 33, 36);
-      display: inline-block;
-      font-size: 13px;
-      line-height: 20px;
-      margin-bottom: 20px;
-      margin-inline: 8px;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      vertical-align: middle;
-      white-space: nowrap;
-    }
-  </style>
-</head>
-<body>
-  <div id="scroll-top"></div>
-  <div id="recommend-apps-container"></div>
-  <div id="scroll-bottom"></div>
-</body>
-</html>
diff --git a/chrome/browser/resources/chromeos/arc_support/recommend_app_old_list_view.js b/chrome/browser/resources/chromeos/arc_support/recommend_app_old_list_view.js
deleted file mode 100644
index 3fbd0aaf..0000000
--- a/chrome/browser/resources/chromeos/arc_support/recommend_app_old_list_view.js
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-let appWindow;
-let appOrigin;
-
-function generateContents(appIcon, appTitle, appPackageName) {
-  const doc = document;
-  const recommendAppsContainer = doc.getElementById('recommend-apps-container');
-  const item = doc.createElement('div');
-  item.classList.add('item');
-  item.setAttribute('data-packagename', appPackageName);
-
-  const chip = doc.createElement('div');
-  chip.classList.add('chip');
-  chip.tabIndex = 0;
-  chip.addEventListener('mousedown', addRippleCircle_);
-  chip.addEventListener('mouseup', toggleCheckStatus_);
-  chip.addEventListener('animationend', removeRippleCircle_);
-
-  // Add keyboard events
-  let keyEventFired = false;
-  chip.addEventListener('keydown', function(e) {
-    if (!keyEventFired && isConfirmKey_(e)) {
-      addRippleCircle_(e);
-    }
-    keyEventFired = true;
-  });
-  chip.addEventListener('keyup', function(e) {
-    if (isConfirmKey_(e)) {
-      toggleCheckStatus_(e);
-      keyEventFired = false;
-    }
-  });
-
-  const chipContent = doc.createElement('div');
-  chipContent.classList.add('chip-content-container');
-  chipContent.tabIndex = -1;
-  chip.appendChild(chipContent);
-
-  item.appendChild(chip);
-
-  const img = doc.createElement('img');
-  img.classList.add('app-icon');
-  img.setAttribute('src', decodeURIComponent(appIcon));
-
-  const title = doc.createElement('span');
-  title.classList.add('app-title');
-  title.innerHTML = appTitle;
-
-  chipContent.appendChild(img);
-  chipContent.appendChild(title);
-
-  const imagePicker = doc.createElement('div');
-  imagePicker.classList.add('image-picker');
-  imagePicker.addEventListener('click', toggleCheckStatus_);
-  item.appendChild(imagePicker);
-
-  recommendAppsContainer.appendChild(item);
-}
-
-/**
- * Add a layer on top of the chip to create the ripple effect.
- * @param {!Event} e
- * @private
- */
-function addRippleCircle_(e) {
-  const chip = e.currentTarget;
-  const item = chip.parentNode;
-  const offsetX = e.pageX - item.offsetLeft;
-  const offsetY = e.pageY - item.offsetTop;
-  chip.style.setProperty('--x', offsetX);
-  chip.style.setProperty('--y', offsetY);
-  const chipContent = chip.querySelector('.chip-content-container');
-  chipContent.innerHTML += '<div class="ripple"></div>';
-}
-
-/**
- * After the animation ends, remove the ripple layer.
- * @param {!Event} e
- * @private
- */
-function removeRippleCircle_(e) {
-  const chip = e.currentTarget;
-  const rippleLayers = chip.querySelectorAll('.ripple');
-  for (const rippleLayer of rippleLayers) {
-    if (rippleLayer.className === 'ripple') {
-      rippleLayer.remove();
-    }
-  }
-}
-
-/**
- * Toggle the check status of an app. If an app is selected, add the "checked"
- * lass so that the checkmark is visible. Otherwise, remove the checked class.
- * @param {!Event} e
- * @private
- */
-function toggleCheckStatus_(e) {
-  const item = e.currentTarget.parentNode;
-  item.classList.toggle('checked');
-
-  sendNumberOfSelectedApps();
-}
-
-function getSelectedPackages() {
-  const selectedPackages = [];
-  const checkedItems = document.getElementsByClassName('checked');
-  for (const checkedItem of checkedItems) {
-    selectedPackages.push(checkedItem.dataset.packagename);
-  }
-  return selectedPackages;
-}
-
-function isConfirmKey_(e) {
-  return e.keyCode === 13   // Enter
-      || e.keyCode === 32;  // Space
-}
-
-/**
- * Send the number of selected apps back to the embedding page.
- */
-function sendNumberOfSelectedApps() {
-  if (appWindow && appOrigin) {
-    const checkedItems = document.querySelectorAll('.checked');
-    appWindow.postMessage(
-        {type: 'NUM_OF_SELECTED_APPS', numOfSelected: checkedItems.length},
-        appOrigin);
-  }
-}
-
-function onMessage_(e) {
-  appWindow = e.source;
-  appOrigin = e.origin;
-}
-
-/**
- * Mark all recommended apps as checked.
- */
-function selectAll() {
-  const allItems = document.getElementsByClassName('item');
-  for (const item of allItems) {
-    item.classList.add('checked');
-  }
-
-  sendNumberOfSelectedApps();
-}
-
-window.addEventListener('message', onMessage_);
diff --git a/chrome/browser/resources/chromeos/login/components/common_styles/common_styles.html b/chrome/browser/resources/chromeos/login/components/common_styles/common_styles.html
index 91006b34..4c26ff34 100644
--- a/chrome/browser/resources/chromeos/login/components/common_styles/common_styles.html
+++ b/chrome/browser/resources/chromeos/login/components/common_styles/common_styles.html
@@ -72,7 +72,7 @@
       }
 
       .oobe-local-link:focus {
-        outline-color: var(--cros-button-active-shadow-color-ambient-primary);
+        outline-color: var(--cros-focus-ring-color);
         transition: outline-color 200ms;
       }
 
diff --git a/chrome/browser/resources/chromeos/login/debug/debug.js b/chrome/browser/resources/chromeos/login/debug/debug.js
index d1396e866..d28106b 100644
--- a/chrome/browser/resources/chromeos/login/debug/debug.js
+++ b/chrome/browser/resources/chromeos/login/debug/debug.js
@@ -1274,6 +1274,7 @@
       ],
     },
     {
+      // TODO(https://crbug.com/1261902): update debug overlay
       id: 'recommend-apps',
       kind: ScreenKind.NORMAL,
       handledSteps: 'list',
@@ -1284,7 +1285,7 @@
           id: '2-apps',
           trigger: (screen) => {
             screen.reset();
-            screen.setWebview(RECOMMENDED_APPS_OLD_CONTENT);
+            screen.setWebview(RECOMMENDED_APPS_CONTENT);
             screen.loadAppList([
               {
                 name: 'Test app 1',
@@ -1302,7 +1303,7 @@
           trigger: (screen) => {
             // There can be up to 21 apps: see recommend_apps_fetcher_impl
             screen.reset();
-            screen.setWebview(RECOMMENDED_APPS_OLD_CONTENT);
+            screen.setWebview(RECOMMENDED_APPS_CONTENT);
             const apps = [];
             for (let i = 1; i <= 21; i++) {
               apps.push({
diff --git a/chrome/browser/resources/chromeos/login/debug/debug_util.js b/chrome/browser/resources/chromeos/login/debug/debug_util.js
index 1ffea53..b88b0ae 100644
--- a/chrome/browser/resources/chromeos/login/debug/debug_util.js
+++ b/chrome/browser/resources/chromeos/login/debug/debug_util.js
@@ -4,11 +4,6 @@
 
 // TODO(crbug.com/1229130) - Remove this global namespace pollution.
 // TODO(crbug.com/1261902): Remove once crbug.com/1229130 is tackled.
-window.RECOMMENDED_APPS_OLD_CONTENT = `
-  // <include src="../../arc_support/recommend_app_old_list_view.html">
-  `;
-
-// TODO(crbug.com/1229130) - Remove this global namespace pollution.
 window.RECOMMENDED_APPS_CONTENT = `
 // <include src="../../arc_support/recommend_app_list_view.html">
   `;
diff --git a/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.js b/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.js
index 65db83a..5ca00c5 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.js
+++ b/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.js
@@ -612,27 +612,22 @@
 
   onGoogleEulaLinkClick_() {
     this.setUIStep(ConsolidatedConsentScreenState.GOOGLE_EULA);
-    this.$.googleEulaOkButton.focus();
   }
 
   onCrosEulaLinkClick_() {
     this.setUIStep(ConsolidatedConsentScreenState.CROS_EULA);
-    this.$.crosEulaOkButton.focus();
   }
 
   onArcTosLinkClick_() {
     this.setUIStep(ConsolidatedConsentScreenState.ARC);
-    this.$.ArcTosOkButton.focus();
   }
 
   onPrivacyPolicyLinkClick_() {
     this.setUIStep(ConsolidatedConsentScreenState.PRIVACY);
-    this.$.privacyOkButton.focus();
   }
 
   onTermsStepOkClick_() {
     this.setUIStep(ConsolidatedConsentScreenState.LOADED);
-    this.$.acceptButton.focus();
   }
 
   onUsageLearnMoreClick_() {
diff --git a/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js b/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js
index b6d7cb4..1da2d71 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js
+++ b/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js
@@ -140,12 +140,10 @@
 
   onGoogleEulaLinkClick_() {
     this.setUIStep(GuestTosScreenState.GOOGLE_EULA);
-    this.$.googleEulaOkButton.focus();
   }
 
   onCrosEulaLinkClick_() {
     this.setUIStep(GuestTosScreenState.CROS_EULA);
-    this.$.crosEulaOkButton.focus();
   }
 
   onGoogleEulaContentLoad_() {
@@ -160,7 +158,6 @@
 
   onTermsStepOkClick_() {
     this.setUIStep(GuestTosScreenState.LOADED);
-    this.$.acceptButton.focus();
   }
 
   onAcceptClick_() {
diff --git a/chrome/browser/resources/chromeos/login/screens/common/recommend_apps.js b/chrome/browser/resources/chromeos/login/screens/common/recommend_apps.js
index e2618ed..17430e80 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/recommend_apps.js
+++ b/chrome/browser/resources/chromeos/login/screens/common/recommend_apps.js
@@ -18,6 +18,8 @@
   LIST: 'list',
 };
 
+const BLANK_PAGE_URL = 'about:blank';
+
 /**
  * @constructor
  * @extends {PolymerElement}
@@ -129,6 +131,15 @@
     return OOBE_UI_STATE.ONBOARDING;
   }
 
+  onBeforeHide() {
+    if (this.isOobeNewRecommendAppsEnabled_) {
+      this.appList_ = [];
+      return;
+    }
+    const appListView = this.shadowRoot.querySelector('#appView');
+    appListView.src = BLANK_PAGE_URL;
+  }
+
   setWebview(contents) {
     cr.ui.login.invokePolymerMethod(this.$.appsDialog, 'onBeforeShow');
     // Can't use this.$.appView here as the element is in a <dom-if>.
@@ -179,7 +190,7 @@
     const appListView = this.shadowRoot.querySelector('#appView');
     appListView.addEventListener('contentload', () => {
       appListView.executeScript(
-          {file: 'recommend_app_old_list_view.js'}, () => {
+          {file: 'recommend_app_list_view.js'}, () => {
             appListView.contentWindow.postMessage('initialMessage', '*');
 
             appList.forEach(function(app_data, index) {
diff --git a/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.js b/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.js
index 3724754..8450d11 100644
--- a/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.js
+++ b/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.js
@@ -119,6 +119,8 @@
         'authDomainChange', () => void this.onAuthDomainChange_());
     this.authenticator_.addEventListener(
         'authCompleted', (e) => void this.onAuthCompletedMessage_(e));
+    this.authenticator_.addEventListener(
+        'loadAbort', (e) => void this.onLoadAbortMessage_(e));
     chrome.send('initialize');
   },
 
@@ -233,6 +235,29 @@
   },
 
   /**
+   * Invoked when onLoadAbort message received.
+   * @param {!CustomEvent<!Object>} e Event with the payload containing
+   *     additional information about error event like:
+   *     {number} error_code Error code such as net::ERR_INTERNET_DISCONNECTED.
+   *     {string} src The URL that failed to load.
+   * @private
+   */
+  onLoadAbortMessage_(e) {
+    this.onWebviewError_(e.detail);
+  },
+
+  /**
+   * Handler for webview error handling.
+   * @param {!Object} data Additional information about error event like:
+   *     {number} error_code Error code such as net::ERR_INTERNET_DISCONNECTED.
+   *     {string} src The URL that failed to load.
+   * @private
+   */
+  onWebviewError_(data) {
+    chrome.send('webviewLoadAborted', [data.error_code]);
+  },
+
+  /**
    * Invoked when the user has successfully authenticated via SAML,
    * the Chrome Credentials Passing API was not used and the authenticator needs
    * the user to confirm the scraped password.
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd
index 077c2c1f4..209b602 100644
--- a/chrome/browser/resources/component_extension_resources.grd
+++ b/chrome/browser/resources/component_extension_resources.grd
@@ -74,10 +74,8 @@
         <include name="IDR_ARC_SUPPORT_ICON_ERROER_IMAGE" file="chromeos/arc_support/images/error_image.png" type="BINDATA" />
         <include name="IDR_ARC_SUPPORT_ICON_HEADER" file="chromeos/arc_support/images/header.png" type="BINDATA" />
         <!-- TODO(crbug.com/1261902): Remove. -->
-        <include name="IDR_ARC_SUPPORT_RECOMMEND_APP_OLD_LIST_VIEW_JS" file="chromeos/arc_support/recommend_app_old_list_view.js" type="BINDATA" />
         <include name="IDR_ARC_SUPPORT_RECOMMEND_APP_LIST_VIEW_JS" file="chromeos/arc_support/recommend_app_list_view.js" type="BINDATA" />
         <!-- TODO(crbug.com/1261902): Remove. -->
-        <include name="IDR_ARC_SUPPORT_RECOMMEND_APP_OLD_LIST_VIEW_HTML" file="chromeos/arc_support/recommend_app_old_list_view.html" type="chrome_html" flattenhtml="true" />
         <include name="IDR_ARC_SUPPORT_RECOMMEND_APP_LIST_VIEW_HTML" file="chromeos/arc_support/recommend_app_list_view.html" type="chrome_html" flattenhtml="true" />
         <include name="IDS_ARC_INPUT_OVERLAY_ONBOARDING_ILLUSTRATION" file="chromeos/arc_input_overlay/onboarding_illustration.png" type="BINDATA" />
         <include name="IDS_ARC_INPUT_OVERLAY_ONBOARDING_ILLUSTRATION_DARK" file="chromeos/arc_input_overlay/onboarding_illustration_dark.png" type="BINDATA" />
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 659351f..e7a8624 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3136,6 +3136,7 @@
       "//chrome/services/file_util/public/cpp",
       "//chromeos/ash/components/assistant:buildflags",
       "//chromeos/ash/components/dbus/audio",
+      "//chromeos/ash/components/dbus/human_presence",
       "//chromeos/ash/components/dbus/kerberos:kerberos_proto",
       "//chromeos/ash/components/dbus/os_install",
       "//chromeos/ash/components/dbus/pciguard:pciguard",
@@ -3169,7 +3170,6 @@
       "//chromeos/dbus/cryptohome",
       "//chromeos/dbus/cryptohome:cryptohome_proto",
       "//chromeos/dbus/hermes",
-      "//chromeos/dbus/human_presence",
       "//chromeos/dbus/power",
       "//chromeos/dbus/tpm_manager",
       "//chromeos/dbus/tpm_manager:tpm_manager_proto",
diff --git a/chrome/browser/ui/android/signin/BUILD.gn b/chrome/browser/ui/android/signin/BUILD.gn
index dacce58..bc5fe21a 100644
--- a/chrome/browser/ui/android/signin/BUILD.gn
+++ b/chrome/browser/ui/android/signin/BUILD.gn
@@ -47,11 +47,11 @@
     "java/src/org/chromium/chrome/browser/ui/signin/ConfirmSyncDataStateMachine.java",
     "java/src/org/chromium/chrome/browser/ui/signin/ConfirmSyncDataStateMachineDelegate.java",
     "java/src/org/chromium/chrome/browser/ui/signin/ConsentTextTracker.java",
+    "java/src/org/chromium/chrome/browser/ui/signin/FullScreenSyncPromoUtil.java",
     "java/src/org/chromium/chrome/browser/ui/signin/GoogleActivityController.java",
     "java/src/org/chromium/chrome/browser/ui/signin/PersonalizedSigninPromoView.java",
     "java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogCoordinator.java",
     "java/src/org/chromium/chrome/browser/ui/signin/SigninPromoController.java",
-    "java/src/org/chromium/chrome/browser/ui/signin/SigninPromoUtil.java",
     "java/src/org/chromium/chrome/browser/ui/signin/SigninScrollView.java",
     "java/src/org/chromium/chrome/browser/ui/signin/SigninUtils.java",
     "java/src/org/chromium/chrome/browser/ui/signin/SigninView.java",
@@ -134,8 +134,8 @@
 robolectric_library("junit") {
   sources = [
     "junit/src/org/chromium/chrome/browser/ui/signin/ConfirmSyncDataStateMachineTest.java",
+    "junit/src/org/chromium/chrome/browser/ui/signin/FullScreenSyncPromoTest.java",
     "junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoControllerTest.java",
-    "junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoUtilLaunchSigninPromoTest.java",
     "junit/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerMediatorTest.java",
     "junit/src/org/chromium/chrome/browser/ui/signin/account_picker/WebSigninAccountPickerDelegateTest.java",
   ]
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SigninPromoUtil.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/FullScreenSyncPromoUtil.java
similarity index 93%
rename from chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SigninPromoUtil.java
rename to chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/FullScreenSyncPromoUtil.java
index c971c716..998491e 100644
--- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SigninPromoUtil.java
+++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/FullScreenSyncPromoUtil.java
@@ -30,11 +30,10 @@
 import java.util.Set;
 
 /**
- * Helper functions for promoting sign in.
+ * Helper class responsible of launching the full screen sync promo, i.e.
+ * {@link SyncConsentActivity}.
  */
-public final class SigninPromoUtil {
-    private SigninPromoUtil() {}
-
+public final class FullScreenSyncPromoUtil {
     /**
      * Launches the {@link SyncConsentActivity} if it needs to be displayed.
      * @param context The {@link Context} to launch the {@link SyncConsentActivity}.
@@ -42,11 +41,11 @@
      * @param currentMajorVersion The current major version of Chrome.
      * @return Whether the signin promo is shown.
      */
-    public static boolean launchSigninPromoIfNeeded(Context context,
+    public static boolean launchPromoIfNeeded(Context context,
             SyncConsentActivityLauncher syncConsentActivityLauncher,
             final int currentMajorVersion) {
         final SigninPreferencesManager prefManager = SigninPreferencesManager.getInstance();
-        if (shouldLaunchSigninPromo(prefManager, currentMajorVersion)) {
+        if (shouldLaunchPromo(prefManager, currentMajorVersion)) {
             syncConsentActivityLauncher.launchActivityIfAllowed(
                     context, SigninAccessPoint.SIGNIN_PROMO);
             prefManager.setSigninPromoLastShownVersion(currentMajorVersion);
@@ -59,7 +58,7 @@
         return false;
     }
 
-    private static boolean shouldLaunchSigninPromo(
+    private static boolean shouldLaunchPromo(
             SigninPreferencesManager prefManager, final int currentMajorVersion) {
         if (ChromeFeatureList.isEnabled(ChromeFeatureList.FORCE_STARTUP_SIGNIN_PROMO)) {
             return true;
@@ -117,4 +116,6 @@
         return previousAccountNames == null
                 || !previousAccountNames.containsAll(currentAccountNames);
     }
+
+    private FullScreenSyncPromoUtil() {}
 }
diff --git a/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoUtilLaunchSigninPromoTest.java b/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/FullScreenSyncPromoTest.java
similarity index 91%
rename from chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoUtilLaunchSigninPromoTest.java
rename to chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/FullScreenSyncPromoTest.java
index ef52fa9..5dc01dd0 100644
--- a/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoUtilLaunchSigninPromoTest.java
+++ b/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/FullScreenSyncPromoTest.java
@@ -49,13 +49,11 @@
 
 import java.util.Set;
 
-/**
- * Tests for {@link SigninPromoUtil#launchSigninPromoIfNeeded}.
- */
+/** Tests for {@link FullScreenSyncPromoUtil}. */
 @RunWith(BaseRobolectricTestRunner.class)
 @Features.DisableFeatures({ChromeFeatureList.FORCE_DISABLE_EXTENDED_SYNC_PROMOS,
         ChromeFeatureList.FORCE_STARTUP_SIGNIN_PROMO})
-public class SigninPromoUtilLaunchSigninPromoTest {
+public class FullScreenSyncPromoTest {
     private static final int CURRENT_MAJOR_VERSION = 42;
     @Rule
     public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -112,7 +110,7 @@
         mAccountManagerTestRule.addAccount(AccountManagerTestRule.TEST_ACCOUNT_EMAIL);
         mPrefManager.setSigninPromoLastShownVersion(38);
         when(mFakeAccountManagerFacade.getAccounts()).thenReturn(new Promise<>());
-        Assert.assertFalse(SigninPromoUtil.launchSigninPromoIfNeeded(
+        Assert.assertFalse(FullScreenSyncPromoUtil.launchPromoIfNeeded(
                 mContext, mLauncherMock, CURRENT_MAJOR_VERSION));
         Assert.assertEquals(38, mPrefManager.getSigninPromoLastShownVersion());
         verify(mLauncherMock, never()).launchActivityIfAllowed(any(), anyInt());
@@ -121,7 +119,7 @@
     @Test
     public void whenNoLastShownVersionShouldReturnFalseAndSaveVersion() {
         mAccountManagerTestRule.addAccount(AccountManagerTestRule.TEST_ACCOUNT_EMAIL);
-        Assert.assertFalse(SigninPromoUtil.launchSigninPromoIfNeeded(
+        Assert.assertFalse(FullScreenSyncPromoUtil.launchPromoIfNeeded(
                 mContext, mLauncherMock, CURRENT_MAJOR_VERSION));
         Assert.assertEquals(42, mPrefManager.getSigninPromoLastShownVersion());
         verify(mFakeAccountManagerFacade, never()).getAccounts();
@@ -131,7 +129,7 @@
     @Test
     public void promoVisibleWhenForcingSigninPromoAtStartup() {
         mAccountManagerTestRule.addAccount(AccountManagerTestRule.TEST_ACCOUNT_EMAIL);
-        Assert.assertTrue(SigninPromoUtil.launchSigninPromoIfNeeded(
+        Assert.assertTrue(FullScreenSyncPromoUtil.launchPromoIfNeeded(
                 mContext, mLauncherMock, CURRENT_MAJOR_VERSION));
         verify(mLauncherMock).launchActivityIfAllowed(mContext, SigninAccessPoint.SIGNIN_PROMO);
     }
@@ -143,7 +141,7 @@
         when(mIdentityManagerMock.getPrimaryAccountInfo(ConsentLevel.SYNC))
                 .thenReturn(coreAccountInfo);
         mPrefManager.setSigninPromoLastShownVersion(38);
-        Assert.assertFalse(SigninPromoUtil.launchSigninPromoIfNeeded(
+        Assert.assertFalse(FullScreenSyncPromoUtil.launchPromoIfNeeded(
                 mContext, mLauncherMock, CURRENT_MAJOR_VERSION));
         verify(mFakeAccountManagerFacade, never()).getAccounts();
         verify(mLauncherMock, never()).launchActivityIfAllowed(any(), anyInt());
@@ -155,7 +153,7 @@
         when(mPrefServiceMock.getString(Pref.GOOGLE_SERVICES_LAST_USERNAME))
                 .thenReturn(AccountManagerTestRule.TEST_ACCOUNT_EMAIL);
         mPrefManager.setSigninPromoLastShownVersion(38);
-        Assert.assertFalse(SigninPromoUtil.launchSigninPromoIfNeeded(
+        Assert.assertFalse(FullScreenSyncPromoUtil.launchPromoIfNeeded(
                 mContext, mLauncherMock, CURRENT_MAJOR_VERSION));
         verify(mFakeAccountManagerFacade, never()).getAccounts();
         verify(mLauncherMock, never()).launchActivityIfAllowed(any(), anyInt());
@@ -165,7 +163,7 @@
     public void whenVersionDifferenceTooSmallShouldReturnFalse() {
         mAccountManagerTestRule.addAccount(AccountManagerTestRule.TEST_ACCOUNT_EMAIL);
         mPrefManager.setSigninPromoLastShownVersion(41);
-        Assert.assertFalse(SigninPromoUtil.launchSigninPromoIfNeeded(
+        Assert.assertFalse(FullScreenSyncPromoUtil.launchPromoIfNeeded(
                 mContext, mLauncherMock, CURRENT_MAJOR_VERSION));
         verify(mFakeAccountManagerFacade, never()).getAccounts();
         verify(mLauncherMock, never()).launchActivityIfAllowed(any(), anyInt());
@@ -174,7 +172,7 @@
     @Test
     public void whenNoAccountsShouldReturnFalse() {
         mPrefManager.setSigninPromoLastShownVersion(38);
-        Assert.assertFalse(SigninPromoUtil.launchSigninPromoIfNeeded(
+        Assert.assertFalse(FullScreenSyncPromoUtil.launchPromoIfNeeded(
                 mContext, mLauncherMock, CURRENT_MAJOR_VERSION));
         verify(mFakeAccountManagerFacade).getAccounts();
         verify(mLauncherMock, never()).launchActivityIfAllowed(any(), anyInt());
@@ -188,7 +186,7 @@
                 .thenReturn(accountInfo);
         mPrefManager.setSigninPromoLastShownVersion(40);
         // Old implementation hasn't been storing account list
-        Assert.assertTrue(SigninPromoUtil.launchSigninPromoIfNeeded(
+        Assert.assertTrue(FullScreenSyncPromoUtil.launchPromoIfNeeded(
                 mContext, mLauncherMock, CURRENT_MAJOR_VERSION));
         verify(mLauncherMock).launchActivityIfAllowed(mContext, SigninAccessPoint.SIGNIN_PROMO);
         Assert.assertEquals(CURRENT_MAJOR_VERSION, mPrefManager.getSigninPromoLastShownVersion());
@@ -200,7 +198,7 @@
     public void whenCapabilityIsNotAvailable() {
         mAccountManagerTestRule.addAccount(AccountManagerTestRule.TEST_ACCOUNT_EMAIL);
         mPrefManager.setSigninPromoLastShownVersion(40);
-        Assert.assertFalse(SigninPromoUtil.launchSigninPromoIfNeeded(
+        Assert.assertFalse(FullScreenSyncPromoUtil.launchPromoIfNeeded(
                 mContext, mLauncherMock, CURRENT_MAJOR_VERSION));
         verify(mLauncherMock, never())
                 .launchActivityIfAllowed(mContext, SigninAccessPoint.SIGNIN_PROMO);
@@ -216,7 +214,7 @@
         mPrefManager.setSigninPromoLastShownVersion(40);
         mPrefManager.setSigninPromoLastAccountNames(
                 Set.of(AccountManagerTestRule.TEST_ACCOUNT_EMAIL));
-        Assert.assertTrue(SigninPromoUtil.launchSigninPromoIfNeeded(
+        Assert.assertTrue(FullScreenSyncPromoUtil.launchPromoIfNeeded(
                 mContext, mLauncherMock, CURRENT_MAJOR_VERSION));
         verify(mLauncherMock).launchActivityIfAllowed(mContext, SigninAccessPoint.SIGNIN_PROMO);
         Assert.assertEquals(CURRENT_MAJOR_VERSION, mPrefManager.getSigninPromoLastShownVersion());
@@ -229,7 +227,7 @@
         mPrefManager.setSigninPromoLastShownVersion(40);
         mPrefManager.setSigninPromoLastAccountNames(
                 Set.of(AccountManagerTestRule.TEST_ACCOUNT_EMAIL));
-        Assert.assertFalse(SigninPromoUtil.launchSigninPromoIfNeeded(
+        Assert.assertFalse(FullScreenSyncPromoUtil.launchPromoIfNeeded(
                 mContext, mLauncherMock, CURRENT_MAJOR_VERSION));
         verify(mFakeAccountManagerFacade).getAccounts();
         verify(mLauncherMock, never()).launchActivityIfAllowed(any(), anyInt());
@@ -244,7 +242,7 @@
         mPrefManager.setSigninPromoLastShownVersion(40);
         mPrefManager.setSigninPromoLastAccountNames(
                 Set.of(AccountManagerTestRule.TEST_ACCOUNT_EMAIL, "test2@gmail.com"));
-        Assert.assertFalse(SigninPromoUtil.launchSigninPromoIfNeeded(
+        Assert.assertFalse(FullScreenSyncPromoUtil.launchPromoIfNeeded(
                 mContext, mLauncherMock, CURRENT_MAJOR_VERSION));
         verify(mFakeAccountManagerFacade).getAccounts();
         verify(mLauncherMock, never()).launchActivityIfAllowed(any(), anyInt());
@@ -259,7 +257,7 @@
         mAccountManagerTestRule.addAccount("test2@gmail.com");
         mPrefManager.setSigninPromoLastShownVersion(38);
 
-        Assert.assertFalse(SigninPromoUtil.launchSigninPromoIfNeeded(
+        Assert.assertFalse(FullScreenSyncPromoUtil.launchPromoIfNeeded(
                 mContext, mLauncherMock, CURRENT_MAJOR_VERSION));
 
         verify(mLauncherMock, never()).launchActivityIfAllowed(any(), anyInt());
@@ -276,7 +274,7 @@
         when(mIdentityManagerMock.findExtendedAccountInfoByEmailAddress(eq(account2.getEmail())))
                 .thenReturn(account2);
         mPrefManager.setSigninPromoLastShownVersion(38);
-        Assert.assertTrue(SigninPromoUtil.launchSigninPromoIfNeeded(
+        Assert.assertTrue(FullScreenSyncPromoUtil.launchPromoIfNeeded(
                 mContext, mLauncherMock, CURRENT_MAJOR_VERSION));
 
         verify(mLauncherMock).launchActivityIfAllowed(mContext, SigninAccessPoint.SIGNIN_PROMO);
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc
index 6c4bb9a..a7751690 100644
--- a/chrome/browser/ui/chrome_pages.cc
+++ b/chrome/browser/ui/chrome_pages.cc
@@ -466,6 +466,16 @@
   ShowSettingsSubPage(browser, kPrivacySandboxLearnMoreSubPage);
 }
 
+void ShowAddresses(Browser* browser) {
+  base::RecordAction(UserMetricsAction("Options_ShowAddresses"));
+  ShowSettingsSubPage(browser, kAddressesSubPage);
+}
+
+void ShowPaymentMethods(Browser* browser) {
+  base::RecordAction(UserMetricsAction("Options_ShowPaymentMethods"));
+  ShowSettingsSubPage(browser, kPaymentsSubPage);
+}
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 void ShowEnterpriseManagementPageInTabbedBrowser(Browser* browser) {
   // Management shows in a tab because it has a "back" arrow that takes the
diff --git a/chrome/browser/ui/chrome_pages.h b/chrome/browser/ui/chrome_pages.h
index c41cdad..77b03371 100644
--- a/chrome/browser/ui/chrome_pages.h
+++ b/chrome/browser/ui/chrome_pages.h
@@ -167,6 +167,8 @@
 void ShowPrivacySandboxSettings(Browser* browser);
 void ShowPrivacySandboxAdPersonalization(Browser* browser);
 void ShowPrivacySandboxLearnMore(Browser* browser);
+void ShowAddresses(Browser* browser);
+void ShowPaymentMethods(Browser* browser);
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 // Shows the enterprise management info page in a browser tab.
diff --git a/chrome/browser/ui/webui/chromeos/human_presence_internals_ui.cc b/chrome/browser/ui/webui/chromeos/human_presence_internals_ui.cc
index 6af5197..dd23422 100644
--- a/chrome/browser/ui/webui/chromeos/human_presence_internals_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/human_presence_internals_ui.cc
@@ -15,11 +15,11 @@
 #include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/url_constants.h"
+#include "chromeos/ash/components/dbus/hps/hps_service.pb.h"
+#include "chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h"
 #include "chromeos/ash/components/human_presence/human_presence_configuration.h"
 #include "chromeos/ash/components/human_presence/human_presence_internals.h"
 #include "chromeos/ash/grit/ash_resources.h"
-#include "chromeos/dbus/hps/hps_service.pb.h"
-#include "chromeos/dbus/human_presence/human_presence_dbus_client.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_controller.h"
 #include "content/public/browser/web_ui_data_source.h"
@@ -30,7 +30,7 @@
 // Class acting as a controller of the chrome://hps-internals WebUI.
 class HumanPresenceInternalsUIMessageHandler
     : public content::WebUIMessageHandler,
-      public chromeos::HumanPresenceDBusClient::Observer {
+      public ash::HumanPresenceDBusClient::Observer {
  public:
   HumanPresenceInternalsUIMessageHandler();
 
@@ -46,7 +46,7 @@
   void OnJavascriptAllowed() override;
   void OnJavascriptDisallowed() override;
 
-  // chromeos::HumanPresenceDBusClient::Observer implementation.
+  // ash::HumanPresenceDBusClient::Observer implementation.
   void OnHpsSenseChanged(const hps::HpsResultProto&) override;
   void OnHpsNotifyChanged(const hps::HpsResultProto&) override;
   void OnRestart() override;
@@ -67,8 +67,8 @@
   static absl::optional<std::string> ReadManifest();
   void UpdateManifest(absl::optional<std::string> manifest);
 
-  base::ScopedObservation<chromeos::HumanPresenceDBusClient,
-                          chromeos::HumanPresenceDBusClient::Observer>
+  base::ScopedObservation<ash::HumanPresenceDBusClient,
+                          ash::HumanPresenceDBusClient::Observer>
       human_presence_observation_{this};
   base::WeakPtrFactory<HumanPresenceInternalsUIMessageHandler>
       msg_weak_ptr_factory_{this};
@@ -129,12 +129,12 @@
 
 void HumanPresenceInternalsUIMessageHandler::Connect(
     const base::Value::List& args) {
-  if (!chromeos::HumanPresenceDBusClient::Get()) {
+  if (!ash::HumanPresenceDBusClient::Get()) {
     LOG(ERROR) << "HPS dbus client not available";
     return;
   }
   AllowJavascript();
-  chromeos::HumanPresenceDBusClient::Get()->WaitForServiceToBeAvailable(
+  ash::HumanPresenceDBusClient::Get()->WaitForServiceToBeAvailable(
       base::BindOnce(&HumanPresenceInternalsUIMessageHandler::OnConnected,
                      weak_ptr_factory_.GetWeakPtr()));
 }
@@ -177,54 +177,54 @@
 
 void HumanPresenceInternalsUIMessageHandler::EnableLockOnLeave(
     const base::Value::List& args) {
-  if (!chromeos::HumanPresenceDBusClient::Get() ||
+  if (!ash::HumanPresenceDBusClient::Get() ||
       !hps::GetEnableLockOnLeaveConfig().has_value()) {
     FireWebUIListener(hps::kHumanPresenceInternalsEnableErrorEvent);
     return;
   }
   hps::FeatureConfig config(*hps::GetEnableLockOnLeaveConfig());
   config.set_report_raw_results(true);
-  chromeos::HumanPresenceDBusClient::Get()->EnableHpsSense(config);
+  ash::HumanPresenceDBusClient::Get()->EnableHpsSense(config);
 }
 
 void HumanPresenceInternalsUIMessageHandler::DisableLockOnLeave(
     const base::Value::List& args) {
-  if (chromeos::HumanPresenceDBusClient::Get())
-    chromeos::HumanPresenceDBusClient::Get()->DisableHpsSense();
+  if (ash::HumanPresenceDBusClient::Get())
+    ash::HumanPresenceDBusClient::Get()->DisableHpsSense();
 }
 
 void HumanPresenceInternalsUIMessageHandler::QueryLockOnLeave(
     const base::Value::List& args) {
-  if (!chromeos::HumanPresenceDBusClient::Get())
+  if (!ash::HumanPresenceDBusClient::Get())
     return;
-  chromeos::HumanPresenceDBusClient::Get()->GetResultHpsSense(base::BindOnce(
+  ash::HumanPresenceDBusClient::Get()->GetResultHpsSense(base::BindOnce(
       &HumanPresenceInternalsUIMessageHandler::OnLockOnLeaveResult,
       weak_ptr_factory_.GetWeakPtr()));
 }
 
 void HumanPresenceInternalsUIMessageHandler::EnableSnoopingProtection(
     const base::Value::List& args) {
-  if (!chromeos::HumanPresenceDBusClient::Get() ||
+  if (!ash::HumanPresenceDBusClient::Get() ||
       !hps::GetEnableSnoopingProtectionConfig().has_value()) {
     FireWebUIListener(hps::kHumanPresenceInternalsEnableErrorEvent);
     return;
   }
   hps::FeatureConfig config(*hps::GetEnableSnoopingProtectionConfig());
   config.set_report_raw_results(true);
-  chromeos::HumanPresenceDBusClient::Get()->EnableHpsNotify(config);
+  ash::HumanPresenceDBusClient::Get()->EnableHpsNotify(config);
 }
 
 void HumanPresenceInternalsUIMessageHandler::DisableSnoopingProtection(
     const base::Value::List& args) {
-  if (chromeos::HumanPresenceDBusClient::Get())
-    chromeos::HumanPresenceDBusClient::Get()->DisableHpsNotify();
+  if (ash::HumanPresenceDBusClient::Get())
+    ash::HumanPresenceDBusClient::Get()->DisableHpsNotify();
 }
 
 void HumanPresenceInternalsUIMessageHandler::QuerySnoopingProtection(
     const base::Value::List& args) {
-  if (!chromeos::HumanPresenceDBusClient::Get())
+  if (!ash::HumanPresenceDBusClient::Get())
     return;
-  chromeos::HumanPresenceDBusClient::Get()->GetResultHpsNotify(base::BindOnce(
+  ash::HumanPresenceDBusClient::Get()->GetResultHpsNotify(base::BindOnce(
       &HumanPresenceInternalsUIMessageHandler::OnSnoopingProtectionResult,
       weak_ptr_factory_.GetWeakPtr()));
 }
@@ -267,9 +267,8 @@
 }
 
 void HumanPresenceInternalsUIMessageHandler::OnJavascriptAllowed() {
-  if (chromeos::HumanPresenceDBusClient::Get())
-    human_presence_observation_.Observe(
-        chromeos::HumanPresenceDBusClient::Get());
+  if (ash::HumanPresenceDBusClient::Get())
+    human_presence_observation_.Observe(ash::HumanPresenceDBusClient::Get());
 }
 
 void HumanPresenceInternalsUIMessageHandler::OnJavascriptDisallowed() {
diff --git a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.cc b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.cc
index 01bba02..9121d298 100644
--- a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.cc
+++ b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.cc
@@ -282,6 +282,14 @@
 
   const NetworkStateInformer::State state = network_state_informer_->state();
 
+  // If frame didn't load but we believe that we are online then we want to show
+  // the network screen (mimicking behaviour of `ErrorScreen` on signin screen).
+  if (reason == NetworkError::ERROR_REASON_FRAME_ERROR &&
+      state == NetworkStateInformer::ONLINE) {
+    ShowLockScreenNetworkDialog();
+    return;
+  }
+
   if (state == NetworkStateInformer::OFFLINE) {
     ShowLockScreenNetworkDialog();
   } else if (state == NetworkStateInformer::CAPTIVE_PORTAL) {
diff --git a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.h b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.h
index dd0f612c..ba91f09 100644
--- a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.h
+++ b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.h
@@ -53,6 +53,9 @@
   bool IsCaptivePortalDialogLoadedForTesting(base::OnceClosure callback);
   void OnNetworkDialogReadyForTesting();
 
+  // NetworkStateInformer::NetworkStateInformerObserver:
+  void UpdateState(NetworkError::ErrorReason reason) override;
+
   LockScreenNetworkDialog* get_network_dialog_for_testing() {
     return lock_screen_network_dialog_.get();
   }
@@ -75,9 +78,6 @@
   void OnDialogShown(content::WebUI* webui) override;
   void OnDialogClosed(const std::string& json_retval) override;
 
-  // NetworkStateInformer::NetworkStateInformerObserver:
-  void UpdateState(NetworkError::ErrorReason reason) override;
-
   // ChromeWebModalDialogManagerDelegate:
   web_modal::WebContentsModalDialogHost* GetWebContentsModalDialogHost()
       override;
diff --git a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.cc b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.cc
index 2028ad2..84453bc 100644
--- a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.cc
@@ -30,6 +30,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/gaia_urls.h"
+#include "net/base/net_errors.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
@@ -383,6 +384,24 @@
                          weak_factory_.GetWeakPtr()));
 }
 
+void LockScreenReauthHandler::HandleWebviewLoadAborted(int error_code) {
+  if (error_code == net::ERR_INVALID_AUTH_CREDENTIALS) {
+    // Silently ignore this error - it is used as an intermediate state for
+    // committed interstitials (see https://crbug.com/1049349 for details).
+    return;
+  }
+
+  if (error_code == net::ERR_ABORTED) {
+    LOG(WARNING) << "Ignoring Gaia webview error: "
+                 << net::ErrorToShortString(error_code);
+    return;
+  }
+
+  LOG(ERROR) << "Gaia webview error: " << net::ErrorToShortString(error_code);
+  auto* password_sync_manager = GetInSessionPasswordSyncManager();
+  password_sync_manager->OnWebviewLoadAborted();
+}
+
 void LockScreenReauthHandler::ReloadGaia() {
   CallJavascriptFunction(std::string(kMainElement) + "reloadAuthenticator");
 }
@@ -410,6 +429,10 @@
       "onPasswordTyped",
       base::BindRepeating(&LockScreenReauthHandler::HandleOnPasswordTyped,
                           weak_factory_.GetWeakPtr()));
+  web_ui()->RegisterHandlerCallback(
+      "webviewLoadAborted",
+      base::BindRepeating(&LockScreenReauthHandler::HandleWebviewLoadAborted,
+                          weak_factory_.GetWeakPtr()));
 }
 
 bool LockScreenReauthHandler::IsAuthenticatorLoaded(
diff --git a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.h b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.h
index bdef4dc..a32bc7861 100644
--- a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.h
+++ b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.h
@@ -34,6 +34,7 @@
   void HandleAuthenticatorLoaded(const base::Value::List&);
   void HandleUpdateUserPassword(const base::Value::List&);
   void HandleOnPasswordTyped(const base::Value::List& value);
+  void HandleWebviewLoadAborted(int error_code);
 
   bool IsAuthenticatorLoaded(base::OnceClosure callback);
 
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index 5a8ee3f..15b13c8a 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -173,8 +173,6 @@
 constexpr char kProductLogoPath[] = "product-logo.png";
 // TODO(crbug.com/1261902): Clean-up old implementation once feature is
 // launched.
-constexpr char kRecommendAppOldListViewJSPath[] =
-    "recommend_app_old_list_view.js";
 constexpr char kRecommendAppListViewJSPath[] = "recommend_app_list_view.js";
 constexpr char kTestAPIJSPath[] = "test_api.js";
 constexpr char kTestAPIJsMPath[] = "test_api/test_api.m.js";
@@ -229,12 +227,9 @@
 
   // TODO(crbug.com/1261902): Clean-up old implementation once feature is
   // launched.
-  if (features::IsOobeNewRecommendAppsEnabled()) {
+  if (!features::IsOobeNewRecommendAppsEnabled()) {
     source->AddResourcePath(kRecommendAppListViewJSPath,
                             IDR_ARC_SUPPORT_RECOMMEND_APP_LIST_VIEW_JS);
-  } else {
-    source->AddResourcePath(kRecommendAppOldListViewJSPath,
-                            IDR_ARC_SUPPORT_RECOMMEND_APP_OLD_LIST_VIEW_JS);
   }
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
   source->AddResourcePath(kArcAppDownloadingVideoPath,
diff --git a/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.cc
index 0393d11..38bd2c5 100644
--- a/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.cc
@@ -103,7 +103,7 @@
     const ui::ResourceBundle& resource_bundle =
         ui::ResourceBundle::GetSharedInstance();
     std::string app_list_webview = resource_bundle.LoadDataResourceString(
-        IDR_ARC_SUPPORT_RECOMMEND_APP_OLD_LIST_VIEW_HTML);
+        IDR_ARC_SUPPORT_RECOMMEND_APP_LIST_VIEW_HTML);
     CallExternalAPI("setWebview", app_list_webview);
   }
   CallExternalAPI("loadAppList", std::move(app_list));
diff --git a/chrome/browser/ui/webui/signin/signin_helper_chromeos.cc b/chrome/browser/ui/webui/signin/signin_helper_chromeos.cc
index 9834dc5..3cd2f9f 100644
--- a/chrome/browser/ui/webui/signin/signin_helper_chromeos.cc
+++ b/chrome/browser/ui/webui/signin/signin_helper_chromeos.cc
@@ -11,6 +11,7 @@
 #include "components/account_manager_core/account_addition_result.h"
 #include "components/account_manager_core/chromeos/account_manager.h"
 #include "components/account_manager_core/chromeos/account_manager_mojo_service.h"
+#include "components/user_manager/user_manager.h"
 #include "google_apis/gaia/gaia_auth_fetcher.h"
 
 namespace chromeos {
@@ -68,8 +69,7 @@
 
   if (ash::AccountAppsAvailability::IsArcAccountRestrictionsEnabled())
     DCHECK(arc_helper_);
-
-  if (IsSecondaryGoogleAccountUsageEnabled()) {
+  if (!IsInitialPrimaryAccount() && IsSecondaryGoogleAccountUsageEnabled()) {
     DCHECK(show_signin_blocked_error_);
     restriction_fetcher_ =
         std::make_unique<ash::UserCloudSigninRestrictionPolicyFetcherChromeOS>(
@@ -84,7 +84,7 @@
 
 void SigninHelper::OnClientOAuthSuccess(const ClientOAuthResult& result) {
   refresh_token_ = result.refresh_token;
-  if (IsSecondaryGoogleAccountUsageEnabled()) {
+  if (!IsInitialPrimaryAccount() && IsSecondaryGoogleAccountUsageEnabled()) {
     restriction_fetcher_->GetSecondaryGoogleAccountUsage(
         /*access_token_fetcher=*/GaiaAccessTokenFetcher::
             CreateExchangeRefreshTokenForAccessTokenInstance(
@@ -95,7 +95,6 @@
             weak_factory_.GetWeakPtr()));
     return;
   }
-
   UpsertAccount(refresh_token_);
   CloseDialogAndExit();
 }
@@ -210,6 +209,13 @@
   Exit();
 }
 
+bool SigninHelper::IsInitialPrimaryAccount() {
+  return user_manager::UserManager::Get()
+             ->GetPrimaryUser()
+             ->GetAccountId()
+             .GetGaiaId() == account_key_.id();
+}
+
 account_manager::AccountManager* SigninHelper::GetAccountManager() {
   return account_manager_;
 }
diff --git a/chrome/browser/ui/webui/signin/signin_helper_chromeos.h b/chrome/browser/ui/webui/signin/signin_helper_chromeos.h
index 598121f..70e0751 100644
--- a/chrome/browser/ui/webui/signin/signin_helper_chromeos.h
+++ b/chrome/browser/ui/webui/signin/signin_helper_chromeos.h
@@ -110,6 +110,12 @@
   scoped_refptr<network::SharedURLLoaderFactory> GetUrlLoaderFactory();
 
  private:
+  // Returns the account that must be auto-signed-in to the Main Profile in
+  // Lacros. This is, when available, the account used to sign into the Chrome
+  // OS session. This may be a Gaia account or a Microsoft Active Directory
+  // account. This field will be null for Guest sessions, Managed Guest
+  // sessions, Demo mode, and Kiosks.
+  bool IsInitialPrimaryAccount();
   // Fetcher to get SecondaryGoogleAccountUsage policy value.
   std::unique_ptr<ash::UserCloudSigninRestrictionPolicyFetcherChromeOS>
       restriction_fetcher_;
diff --git a/chrome/browser/ui/webui/signin/signin_helper_chromeos_browsertest.cc b/chrome/browser/ui/webui/signin/signin_helper_chromeos_browsertest.cc
index 7ab78ad..31344ad 100644
--- a/chrome/browser/ui/webui/signin/signin_helper_chromeos_browsertest.cc
+++ b/chrome/browser/ui/webui/signin/signin_helper_chromeos_browsertest.cc
@@ -7,6 +7,7 @@
 #include "ash/components/account_manager/account_manager_factory.h"
 #include "ash/constants/ash_features.h"
 #include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
 #include "base/test/bind.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/ash/account_manager/account_apps_availability.h"
@@ -19,9 +20,13 @@
 #include "components/account_manager_core/account.h"
 #include "components/account_manager_core/chromeos/account_manager.h"
 #include "components/account_manager_core/chromeos/account_manager_mojo_service.h"
+#include "components/user_manager/user_manager.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/test/browser_test.h"
+#include "google_apis/gaia/gaia_urls.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
 
 namespace chromeos {
 
@@ -29,14 +34,35 @@
 
 namespace {
 
+const char kFakePrimaryGaiaId[] = "primary_account_gaia";
+const char kFakePrimaryEmail[] = "primary@example.com";
 const char kFakeGaiaId[] = "fake_gaia_id";
 const char kFakeEmail[] = "fake_email@gmail.com";
 const char kFakeAuthCode[] = "fake_auth_code";
 const char kFakeDeviceId[] = "fake_device_id";
 const char kFakeRefreshToken[] = "fake_refresh_token";
+const char kFakeEnterpriseGaiaId[] = "fake_enterprise_gaia_id";
 const char kFakeEnterpriseEmail[] = "fake_enterprise@example.com";
 const char kFakeEnterpriseDomain[] = "example.com";
 
+const char kSecureConnectApiGetSecondaryGoogleAccountUsageURL[] =
+    "https://secureconnect-pa.clients6.google.com/"
+    "v1:getManagedAccountsSigninRestriction?policy_name="
+    "SecondaryGoogleAccountUsage";
+;
+
+// Fake responses for the URL requests that are part of the sign-in flow.
+const char kOnClientOAuthSuccessBody[] =
+    R"({
+            "refresh_token": "refresh_token",
+            "access_token": "access_token",
+            "expires_in": 99999
+       })";
+const char kUserInfoURLBodyWithHostedDomain[] = R"({"hd": "%s"})";
+const char kUserInfoURLBodyWithoutHostedDomain[] = R"({})";
+const char kSecureConnectApiGetSecondaryGoogleAccountUsageURLBody[] =
+    R"({"policyValue": "%s"})";
+
 // Convenience helper to allow a `closure` to be used in a context which is
 // expecting a callback with arguments.
 template <typename... T>
@@ -77,27 +103,6 @@
 
   ~TestSigninHelper() override;
 
-  void OnClientOAuthSuccess(const ClientOAuthResult& result) override {
-    SigninHelper::OnClientOAuthSuccess(result);
-  }
-
-  void OnClientOAuthFailure(const GoogleServiceAuthError& error) override {
-    SigninHelper::OnClientOAuthFailure(error);
-  }
-
-  void OnGetSecondaryGoogleAccountUsage(
-      ash::UserCloudSigninRestrictionPolicyFetcherChromeOS::Status status,
-      absl::optional<std::string> policy_result,
-      const std::string& hosted_domain) override {
-    SigninHelper::OnGetSecondaryGoogleAccountUsage(status, policy_result,
-                                                   hosted_domain);
-  }
-
-  void RevokeGaiaTokenOnServer() override {
-    SigninHelper::OnOAuth2RevokeTokenCompleted(
-        GaiaAuthConsumer::TokenRevocationStatus::kSuccess);
-  }
-
  private:
   SigninHelperChromeOSTest* test_fixture_;
 };
@@ -108,7 +113,10 @@
     : public InProcessBrowserTest,
       public account_manager::AccountManager::Observer {
  public:
-  SigninHelperChromeOSTest() = default;
+  SigninHelperChromeOSTest()
+      : test_shared_loader_factory_(
+            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+                &test_url_loader_factory_)) {}
 
   ~SigninHelperChromeOSTest() override {
     DCHECK_EQ(signin_helper_created_count_, signin_helper_deleted_count_);
@@ -126,8 +134,8 @@
 
     // Setup the main account:
     account_manager::AccountKey kPrimaryAccountKey{
-        "primary_account_gaia", account_manager::AccountType::kGaia};
-    account_manager()->UpsertAccount(kPrimaryAccountKey, "primary@gmai.com",
+        kFakePrimaryGaiaId, account_manager::AccountType::kGaia};
+    account_manager()->UpsertAccount(kPrimaryAccountKey, kFakePrimaryEmail,
                                      "access_token");
     base::RunLoop().RunUntilIdle();
     on_token_upserted_call_count_ = 0;
@@ -140,10 +148,9 @@
     on_token_upserted_account_ = absl::nullopt;
   }
 
-  TestSigninHelper* CreateSigninHelper(
-      const base::RepeatingClosure& close_dialog_closure) {
+  void CreateSigninHelper(const base::RepeatingClosure& close_dialog_closure) {
     OnSigninHelperCreated();
-    return new TestSigninHelper(
+    new TestSigninHelper(
         this, account_manager(), account_manager_mojo_service(),
         close_dialog_closure,
         /*show_signin_blocked_by_policy_page=*/base::DoNothing(),
@@ -167,10 +174,7 @@
   }
 
   scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory() {
-    return browser()
-        ->profile()
-        ->GetDefaultStoragePartition()
-        ->GetURLLoaderFactoryForBrowserProcess();
+    return test_shared_loader_factory_;
   }
 
   account_manager::AccountManager* account_manager() {
@@ -181,6 +185,56 @@
     return account_manager_mojo_service_;
   }
 
+ protected:
+  void AddResponseClientOAuthSuccess() {
+    loader_factory().AddResponse(
+        GaiaUrls::GetInstance()->oauth2_token_url().spec(),
+        /*content=*/kOnClientOAuthSuccessBody, net::HTTP_OK);
+  }
+
+  void AddResponseClientOAuthFailure() {
+    loader_factory().AddResponse(
+        GaiaUrls::GetInstance()->oauth2_token_url().spec(),
+        /*content=*/R"({})", net::HTTP_BAD_REQUEST);
+  }
+
+  void AddResponseGetSecondaryGoogleAccountUsage(
+      const std::string& policy_value) {
+    loader_factory().AddResponse(
+        kSecureConnectApiGetSecondaryGoogleAccountUsageURL,
+        /*content=*/
+        base::StringPrintf(
+            kSecureConnectApiGetSecondaryGoogleAccountUsageURLBody,
+            policy_value.c_str()),
+        net::HTTP_OK);
+  }
+
+  void AddResponseGetUserInfoWithHostedDomain(
+      const std::string& hosted_domain) {
+    loader_factory().AddResponse(
+        GaiaUrls::GetInstance()->oauth_user_info_url().spec(),
+        /*content=*/
+        base::StringPrintf(kUserInfoURLBodyWithHostedDomain,
+                           hosted_domain.c_str()),
+        net::HTTP_OK);
+  }
+
+  void AddResponseGetUserInfoWithoutHostedDomain() {
+    loader_factory().AddResponse(
+        GaiaUrls::GetInstance()->oauth_user_info_url().spec(),
+        /*content=*/kUserInfoURLBodyWithoutHostedDomain, net::HTTP_OK);
+  }
+
+  void AddResponseRevokeGaiaTokenOnServer() {
+    loader_factory().AddResponse(
+        GaiaUrls::GetInstance()->oauth2_revoke_url().spec(),
+        /*content=*/std::string(), net::HTTP_OK);
+  }
+
+  network::TestURLLoaderFactory& loader_factory() {
+    return test_url_loader_factory_;
+  }
+
  private:
   // account_manager::AccountManager::Observer overrides:
   void OnTokenUpserted(const account_manager::Account& account) override {
@@ -196,6 +250,8 @@
   int signin_helper_deleted_count_ = 0;
   int on_token_upserted_call_count_ = 0;
   absl::optional<account_manager::Account> on_token_upserted_account_;
+  network::TestURLLoaderFactory test_url_loader_factory_;
+  scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
 };
 
 TestSigninHelper::~TestSigninHelper() {
@@ -205,13 +261,12 @@
 IN_PROC_BROWSER_TEST_F(SigninHelperChromeOSTest,
                        NoAccountAddedWhenAuthTokenFetchFails) {
   base::RunLoop close_dialog_closure_run_loop;
-  auto* helper = CreateSigninHelper(
+  // Set auth token fetch to fail.
+  AddResponseClientOAuthFailure();
+  CreateSigninHelper(
       base::BindLambdaForTesting([&close_dialog_closure_run_loop]() {
         close_dialog_closure_run_loop.Quit();
       }));
-  // Auth token fetch fails.
-  helper->OnClientOAuthFailure(
-      GoogleServiceAuthError(GoogleServiceAuthError::State::CONNECTION_FAILED));
   // Make sure the close_dialog_closure was called.
   close_dialog_closure_run_loop.Run();
   // Wait until SigninHelper finishes and deletes itself.
@@ -223,10 +278,9 @@
 IN_PROC_BROWSER_TEST_F(SigninHelperChromeOSTest,
                        AccountAddedWhenAuthTokenFetchSucceeds) {
   base::RunLoop close_dialog_closure_run_loop;
-  auto* helper =
-      CreateSigninHelper(close_dialog_closure_run_loop.QuitClosure());
-  // Auth token fetch succeeds.
-  helper->OnClientOAuthSuccess(GetFakeOAuthResult());
+  CreateSigninHelper(close_dialog_closure_run_loop.QuitClosure());
+  // Set auth token fetch to succeed.
+  AddResponseClientOAuthSuccess();
   // Make sure the close_dialog_closure was called.
   close_dialog_closure_run_loop.Run();
   // Wait until SigninHelper finishes and deletes itself.
@@ -271,11 +325,10 @@
     SigninHelperChromeOSTest::TearDownOnMainThread();
   }
 
-  TestSigninHelper* CreateSigninHelper(
-      std::unique_ptr<SigninHelper::ArcHelper> arc_helper,
-      const base::RepeatingClosure& close_dialog_closure) {
+  void CreateSigninHelper(std::unique_ptr<SigninHelper::ArcHelper> arc_helper,
+                          const base::RepeatingClosure& close_dialog_closure) {
     OnSigninHelperCreated();
-    return new TestSigninHelper(
+    new TestSigninHelper(
         this, account_manager(), account_manager_mojo_service(),
         close_dialog_closure,
         /*show_signin_blocked_by_policy_page=*/base::DoNothing(),
@@ -353,10 +406,10 @@
           /*is_available_in_arc=*/true, /*is_account_addition=*/true,
           account_apps_availability());
   base::RunLoop close_dialog_closure_run_loop;
-  auto* helper = CreateSigninHelper(
-      std::move(arc_helper), close_dialog_closure_run_loop.QuitClosure());
-  // Auth token fetch succeeds.
-  helper->OnClientOAuthSuccess(GetFakeOAuthResult());
+  // Set auth token fetch to succeed.
+  AddResponseClientOAuthSuccess();
+  CreateSigninHelper(std::move(arc_helper),
+                     close_dialog_closure_run_loop.QuitClosure());
   // Make sure the close_dialog_closure was called.
   close_dialog_closure_run_loop.Run();
   // Wait until SigninHelper finishes and deletes itself.
@@ -388,13 +441,13 @@
           /*is_available_in_arc=*/false, /*is_account_addition=*/true,
           account_apps_availability());
   base::RunLoop close_dialog_closure_run_loop;
-  auto* helper = CreateSigninHelper(
+  // Set auth token fetch to succeed.
+  AddResponseClientOAuthSuccess();
+  CreateSigninHelper(
       std::move(arc_helper),
       base::BindLambdaForTesting([&close_dialog_closure_run_loop]() {
         close_dialog_closure_run_loop.Quit();
       }));
-  // Auth token fetch succeeds.
-  helper->OnClientOAuthSuccess(GetFakeOAuthResult());
   // Make sure the close_dialog_closure was called.
   close_dialog_closure_run_loop.Run();
   // Wait until SigninHelper finishes and deletes itself.
@@ -430,13 +483,13 @@
           /*is_available_in_arc=*/true, /*is_account_addition=*/false,
           account_apps_availability());
   base::RunLoop close_dialog_closure_run_loop;
-  auto* helper = CreateSigninHelper(
+  // Set auth token fetch to succeed.
+  AddResponseClientOAuthSuccess();
+  CreateSigninHelper(
       std::move(arc_helper),
       base::BindLambdaForTesting([&close_dialog_closure_run_loop]() {
         close_dialog_closure_run_loop.Quit();
       }));
-  // Auth token fetch succeeds.
-  helper->OnClientOAuthSuccess(GetFakeOAuthResult());
   // Make sure the close_dialog_closure was called.
   close_dialog_closure_run_loop.Run();
   // Wait until SigninHelper finishes and deletes itself.
@@ -466,20 +519,22 @@
 
   ~SigninHelperChromeOSTestSecondaryGoogleAccountUsage() override = default;
 
-  TestSigninHelper* CreateSigninHelper(
+  void CreateSigninHelper(
       const base::RepeatingClosure& close_dialog_closure,
       const base::RepeatingClosure& show_signin_blocked_by_policy_page,
+      const std::string& gaia_id,
       const std::string& email) {
     OnSigninHelperCreated();
     // The `TestSigninHelper` deletes itself after its work is complete.
-    return new TestSigninHelper(
-        this, account_manager(), account_manager_mojo_service(),
-        /*close_dialog_closure=*/close_dialog_closure,
-        /*show_signin_blocked_by_policy_page=*/
-        IgnoreArgs<const std::string&, const std::string&>(
-            show_signin_blocked_by_policy_page),
-        shared_url_loader_factory(), /*arc_helper=*/nullptr, kFakeGaiaId, email,
-        kFakeAuthCode, kFakeDeviceId);
+
+    new TestSigninHelper(this, account_manager(),
+                         account_manager_mojo_service(),
+                         /*close_dialog_closure=*/close_dialog_closure,
+                         /*show_signin_blocked_by_policy_page=*/
+                         IgnoreArgs<const std::string&, const std::string&>(
+                             show_signin_blocked_by_policy_page),
+                         shared_url_loader_factory(), /*arc_helper=*/nullptr,
+                         gaia_id, email, kFakeAuthCode, kFakeDeviceId);
   }
 
  private:
@@ -489,14 +544,17 @@
 IN_PROC_BROWSER_TEST_F(SigninHelperChromeOSTestSecondaryGoogleAccountUsage,
                        AccountAddedForNonEnterpriseAccount) {
   base::RunLoop close_dialog_closure_run_loop;
+
+  // Set auth token fetch to succeed.
+  AddResponseClientOAuthSuccess();
+  // Set no hosted domain for user info request.
+  AddResponseGetUserInfoWithoutHostedDomain();
   // Non Enterprise account tries to sign in.
-  auto* helper = CreateSigninHelper(
+  CreateSigninHelper(
       /*close_dialog_closure=*/close_dialog_closure_run_loop.QuitClosure(),
       /*show_signin_blocked_by_policy_page=*/
-      base::RepeatingClosure(), kFakeEmail);
+      base::RepeatingClosure(), kFakeGaiaId, kFakeEmail);
 
-  // Auth token fetch succeeds.
-  helper->OnClientOAuthSuccess(GetFakeOAuthResult());
   // Make sure the close_dialog_closure was called.
   close_dialog_closure_run_loop.Run();
   // Wait until SigninHelper finishes and deletes itself.
@@ -513,15 +571,18 @@
 IN_PROC_BROWSER_TEST_F(SigninHelperChromeOSTestSecondaryGoogleAccountUsage,
                        AccountAddedForEnterpriseAccountWithNoPolicySet) {
   base::RunLoop close_dialog_closure_run_loop;
+
+  // Set auth token fetch to succeed.
+  AddResponseClientOAuthSuccess();
+  // Set user info response with hosted domain (hd) value.
+  AddResponseGetUserInfoWithHostedDomain(kFakeEnterpriseDomain);
+  // Set SecondaryGoogleAccountUsage policy fetch to unset.
+  AddResponseGetSecondaryGoogleAccountUsage("unset");
   // Enterprise account tries to sign in.
-  auto* helper = CreateSigninHelper(
+  CreateSigninHelper(
       /*close_dialog_closure=*/close_dialog_closure_run_loop.QuitClosure(),
       /*show_signin_blocked_by_policy_page=*/
-      base::RepeatingClosure(), kFakeEnterpriseEmail);
-  // `GetSecondaryGoogleAccountUsage` succeeds.
-  helper->OnGetSecondaryGoogleAccountUsage(
-      ash::UserCloudSigninRestrictionPolicyFetcherChromeOS::Status::kSuccess,
-      /*policy_value=*/absl::nullopt, kFakeEnterpriseEmail);
+      base::RepeatingClosure(), kFakeEnterpriseGaiaId, kFakeEnterpriseEmail);
   // Make sure the close_dialog_closure was called.
   close_dialog_closure_run_loop.Run();
   // Wait until SigninHelper finishes and deletes itself.
@@ -539,15 +600,18 @@
     SigninHelperChromeOSTestSecondaryGoogleAccountUsage,
     AccountAddedForEnterpriseAccountWithPolicyValueAllUsages) {
   base::RunLoop close_dialog_closure_run_loop;
+
+  // Set auth token fetch to succeed.
+  AddResponseClientOAuthSuccess();
+  // Set user info response with hosted domain (hd) value.
+  AddResponseGetUserInfoWithHostedDomain(kFakeEnterpriseDomain);
+  // Set SecondaryGoogleAccountUsage policy fetch to all.
+  AddResponseGetSecondaryGoogleAccountUsage("all");
   // Enterprise account tries to sign in.
-  auto* helper = CreateSigninHelper(
+  CreateSigninHelper(
       /*close_dialog_closure=*/close_dialog_closure_run_loop.QuitClosure(),
       /*show_signin_blocked_by_policy_page=*/
-      base::RepeatingClosure(), kFakeEnterpriseEmail);
-  // `GetSecondaryGoogleAccountUsage` succeeds.
-  helper->OnGetSecondaryGoogleAccountUsage(
-      ash::UserCloudSigninRestrictionPolicyFetcherChromeOS::Status::kSuccess,
-      /*policy_value=*/"all", kFakeEnterpriseDomain);
+      base::RepeatingClosure(), kFakeEnterpriseGaiaId, kFakeEnterpriseEmail);
   // Make sure the close_dialog_closure was called.
   close_dialog_closure_run_loop.Run();
   // Wait until SigninHelper finishes and deletes itself.
@@ -565,16 +629,21 @@
     SigninHelperChromeOSTestSecondaryGoogleAccountUsage,
     NoAccountAddedForEnterpriseAccountWithPolicyValuePrimaryAccountSignin) {
   base::RunLoop show_signin_blocked_error_closure_run_loop;
+
+  // Set auth token fetch to succeed.
+  AddResponseClientOAuthSuccess();
+  // Set user info response with hosted domain (hd) value.
+  AddResponseGetUserInfoWithHostedDomain(kFakeEnterpriseDomain);
+  // Set SecondaryGoogleAccountUsage policy fetch to primary_account_signin.
+  AddResponseGetSecondaryGoogleAccountUsage("primary_account_signin");
+  // Set response for token revokation.
+  AddResponseRevokeGaiaTokenOnServer();
   // Enterprise account tries to sign in.
-  auto* helper = CreateSigninHelper(
+  CreateSigninHelper(
       /*close_dialog_closure=*/base::RepeatingClosure(),
       /*show_signin_blocked_by_policy_page=*/
       show_signin_blocked_error_closure_run_loop.QuitClosure(),
-      kFakeEnterpriseEmail);
-  // `GetSecondaryGoogleAccountUsage` succeeds.
-  helper->OnGetSecondaryGoogleAccountUsage(
-      ash::UserCloudSigninRestrictionPolicyFetcherChromeOS::Status::kSuccess,
-      /*policy_value=*/"primary_account_signin", kFakeEnterpriseEmail);
+      kFakeEnterpriseGaiaId, kFakeEnterpriseEmail);
   // Make sure the show_signin_blocked_error_closure_run_loop was called.
   show_signin_blocked_error_closure_run_loop.Run();
   // Wait until SigninHelper finishes and deletes itself.
@@ -584,4 +653,28 @@
   EXPECT_EQ(on_token_upserted_call_count(), 0);
 }
 
+IN_PROC_BROWSER_TEST_F(SigninHelperChromeOSTestSecondaryGoogleAccountUsage,
+                       ReauthForInitialPrimaryEnterpriseAccount) {
+  base::RunLoop close_dialog_closure_run_loop;
+  // Set auth token fetch to succeed.
+  AddResponseClientOAuthSuccess();
+  CreateSigninHelper(
+      /*close_dialog_closure=*/close_dialog_closure_run_loop.QuitClosure(),
+      /*show_signin_blocked_by_policy_page=*/
+      base::RepeatingClosure(),
+      user_manager::UserManager::Get()
+          ->GetPrimaryUser()
+          ->GetAccountId()
+          .GetGaiaId(),
+      kFakePrimaryEmail);
+
+  // Make sure the close_dialog_closure was called.
+  close_dialog_closure_run_loop.Run();
+  // Wait until SigninHelper finishes and deletes itself.
+  base::RunLoop().RunUntilIdle();
+
+  // 1 account should be upserted.
+  EXPECT_EQ(on_token_upserted_call_count(), 1);
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
index 7117cee..92e36cc 100644
--- a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
+++ b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
@@ -4376,9 +4376,15 @@
   return "\n    [\n" + icon_list + "    ]\n  ";
 }
 
+// Disabled due to test flakiness: https://crbug.com/1341954
+#if BUILDFLAG(IS_WIN)
+#define MAYBE_CheckCombinations DISABLED_CheckCombinations
+#else
+#define MAYBE_CheckCombinations CheckCombinations
+#endif
 IN_PROC_BROWSER_TEST_P(
     ManifestUpdateManagerBrowserTest_AppIdentityParameterized,
-    CheckCombinations) {
+    MAYBE_CheckCombinations) {
   constexpr char kManifestTemplate[] = R"(
     {
       "name": "$1",
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 9c5c6b4..6606d65 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1656978378-52d63b1ea90adacdd3fad89c66d5a0bb99535e1f.profdata
+chrome-linux-main-1657022349-bffae36425e502a761df100ce16ea8e8b34be36b.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index a807722..a41d57fd 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1656956749-2cc23747b7471debb5a097933912b2a814829eed.profdata
+chrome-mac-arm-main-1657000683-bf710ea6591ccb8f5976caeb3e71912937482abc.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 2cf73dd1..597fb36 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1656978378-e5487b3bdfa923bdb0112e79c9fb2a484253a9d2.profdata
+chrome-mac-main-1657000683-751d125c77f9e3de0691664fec9f3b07aea236c8.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 924f38aa..53f11d5 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1656978378-7598a1d5e1abb7b31a9885474b09777419743a9c.profdata
+chrome-win32-main-1657000683-f2a4e8fb8dc3d187dddb7926031fb1315f1d3b13.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index a2e74e48..2503c33 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1656989798-ff1ea13aec751aa8903a31d640534c9047fc9103.profdata
+chrome-win64-main-1657011560-380fadbba0240cedb557fab3969305e2a8a5cba0.profdata
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 6765afa..4d485a85 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -4621,6 +4621,7 @@
       "../browser/chromeos/extensions/login_screen/login_screen_storage/login_screen_storage_apitest.cc",
       "../browser/chromeos/extensions/wallpaper_apitest.cc",
       "../browser/chromeos/tablet_mode/tablet_mode_page_behavior_browsertest.cc",
+      "../browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc",
       "../browser/extensions/api/preference/preference_api_lacros_browsertest.cc",
       "../browser/extensions/api/vpn_provider/vpn_provider_apitest.cc",
       "../browser/lacros/browser_service_lacros_browsertest.cc",
@@ -4687,9 +4688,11 @@
       "//components/infobars/content:content",
       "//components/metrics/structured",
       "//components/metrics/structured:structured_events",
+      "//components/onc:onc",
       "//components/proxy_config:proxy_config",
       "//components/services/app_service/public/cpp:intents",
       "//components/services/app_service/public/cpp:preferred_apps",
+      "//components/user_manager:user_manager",
       "//ui/gfx/codec",
       "//ui/platform_window",
     ]
@@ -7355,7 +7358,6 @@
       "../browser/lacros/force_installed_tracker_lacros_unittest.cc",
       "../browser/lacros/lacros_memory_pressure_evaluator_unittest.cc",
       "../browser/lacros/lacros_url_handling_unittest.cc",
-      "../browser/lacros/launcher_search/search_util_unittest.cc",
       "../browser/lacros/metrics_reporting_observer_unittest.cc",
       "../browser/lacros/net/network_settings_translation_unittest.cc",
       "../browser/lacros/prefs_ash_observer_unittest.cc",
@@ -7371,6 +7373,7 @@
 
     deps += [
       "//chrome/browser:dlp_policy_event_proto",
+      "//chrome/browser/chromeos/launcher_search:unit_tests",
       "//chrome/browser/policy:onc",
       "//chrome/browser/policy:unit_tests",
       "//chromeos/components/onc:onc",
@@ -7903,6 +7906,9 @@
         "//chrome/browser/chromeos/extensions/telemetry/api:unit_tests",
         "//chrome/common/chromeos/extensions",
         "//chromeos/dbus/image_burner",
+        "//content/public/browser",
+        "//net",
+        "//net:test_support",
       ]
     } else {
       sources += [
diff --git a/chrome/utility/BUILD.gn b/chrome/utility/BUILD.gn
index 7b82bdc..90d20c63 100644
--- a/chrome/utility/BUILD.gn
+++ b/chrome/utility/BUILD.gn
@@ -43,6 +43,7 @@
     "//components/metrics:child_call_stack_profile_builder",
     "//components/mirroring/service:mirroring_service",
     "//components/paint_preview/buildflags",
+    "//components/password_manager/services/csv_password:lib",
     "//components/safe_browsing:buildflags",
     "//components/search_engines",
     "//components/services/language_detection",
diff --git a/chrome/utility/DEPS b/chrome/utility/DEPS
index b7ae692..77673e7c 100644
--- a/chrome/utility/DEPS
+++ b/chrome/utility/DEPS
@@ -43,6 +43,8 @@
   "+components/mirroring/mojom",
   "+components/mirroring/service",
   "+components/paint_preview/buildflags",
+  "+components/password_manager/services/csv_password",
+  "+components/password_manager/core/common",
   "+components/payments/content/utility",
   "+components/safe_browsing/buildflags.h",
   "+components/services/language_detection",
diff --git a/chrome/utility/services.cc b/chrome/utility/services.cc
index 3e8313f5..8ba02bc 100644
--- a/chrome/utility/services.cc
+++ b/chrome/utility/services.cc
@@ -13,6 +13,9 @@
 #include "chrome/services/qrcode_generator/qrcode_generator_service_impl.h"
 #include "chrome/services/speech/buildflags/buildflags.h"
 #include "components/paint_preview/buildflags/buildflags.h"
+#include "components/password_manager/core/common/password_manager_features.h"
+#include "components/password_manager/services/csv_password/csv_password_parser_impl.h"
+#include "components/password_manager/services/csv_password/public/mojom/csv_password_parser.mojom.h"
 #include "components/safe_browsing/buildflags.h"
 #include "components/services/language_detection/language_detection_service_impl.h"
 #include "components/services/language_detection/public/mojom/language_detection.mojom.h"
@@ -162,6 +165,13 @@
       std::move(receiver));
 }
 
+auto RunCSVPasswordParser(
+    mojo::PendingReceiver<password_manager::mojom::CSVPasswordParser>
+        receiver) {
+  return std::make_unique<password_manager::CSVPasswordParserImpl>(
+      std::move(receiver));
+}
+
 #if BUILDFLAG(IS_WIN)
 auto RunProcessorMetrics(
     mojo::PendingReceiver<chrome::mojom::ProcessorMetrics> receiver) {
@@ -398,6 +408,9 @@
   services.Add(RunQRCodeGeneratorService);
   services.Add(RunWebAppOriginAssociationParser);
 
+  if (base::FeatureList::IsEnabled(password_manager::features::kPasswordImport))
+    services.Add(RunCSVPasswordParser);
+
 #if !BUILDFLAG(IS_ANDROID)
   services.Add(RunProfileImporter);
   services.Add(RunMirroringService);
diff --git a/chromeos/dbus/human_presence/BUILD.gn b/chromeos/ash/components/dbus/human_presence/BUILD.gn
similarity index 78%
rename from chromeos/dbus/human_presence/BUILD.gn
rename to chromeos/ash/components/dbus/human_presence/BUILD.gn
index 80d26132..49f4639 100644
--- a/chromeos/dbus/human_presence/BUILD.gn
+++ b/chromeos/ash/components/dbus/human_presence/BUILD.gn
@@ -2,9 +2,10 @@
 # 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, "Non-ChromeOS builds cannot depend on //chromeos")
+assert(is_chromeos_ash, "Non-ChromeOS builds cannot depend on //chromeos/ash")
 
 component("human_presence") {
   defines = [ "IS_HPS_IMPL" ]
@@ -24,5 +25,5 @@
 
 proto_library("hps_proto") {
   sources = [ "//third_party/cros_system_api/dbus/hps/hps_service.proto" ]
-  proto_out_dir = "chromeos/dbus/hps"
+  proto_out_dir = "chromeos/ash/components/dbus/hps"
 }
diff --git a/chromeos/dbus/human_presence/fake_human_presence_dbus_client.cc b/chromeos/ash/components/dbus/human_presence/fake_human_presence_dbus_client.cc
similarity index 95%
rename from chromeos/dbus/human_presence/fake_human_presence_dbus_client.cc
rename to chromeos/ash/components/dbus/human_presence/fake_human_presence_dbus_client.cc
index 2ace00d7..fc0b80c 100644
--- a/chromeos/dbus/human_presence/fake_human_presence_dbus_client.cc
+++ b/chromeos/ash/components/dbus/human_presence/fake_human_presence_dbus_client.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/human_presence/fake_human_presence_dbus_client.h"
+#include "chromeos/ash/components/dbus/human_presence/fake_human_presence_dbus_client.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -102,4 +102,4 @@
   observers_.Clear();
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chromeos/dbus/human_presence/fake_human_presence_dbus_client.h b/chromeos/ash/components/dbus/human_presence/fake_human_presence_dbus_client.h
similarity index 88%
rename from chromeos/dbus/human_presence/fake_human_presence_dbus_client.h
rename to chromeos/ash/components/dbus/human_presence/fake_human_presence_dbus_client.h
index 17bcb058..1fc42ae 100644
--- a/chromeos/dbus/human_presence/fake_human_presence_dbus_client.h
+++ b/chromeos/ash/components/dbus/human_presence/fake_human_presence_dbus_client.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_HUMAN_PRESENCE_FAKE_HUMAN_PRESENCE_DBUS_CLIENT_H_
-#define CHROMEOS_DBUS_HUMAN_PRESENCE_FAKE_HUMAN_PRESENCE_DBUS_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_HUMAN_PRESENCE_FAKE_HUMAN_PRESENCE_DBUS_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_HUMAN_PRESENCE_FAKE_HUMAN_PRESENCE_DBUS_CLIENT_H_
 
 #include "base/observer_list.h"
-#include "chromeos/dbus/human_presence/human_presence_dbus_client.h"
+#include "chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
-namespace chromeos {
+namespace ash {
 
 // Fake implementation of HumanPresenceDBusClient. Allows callers to set a
 // response value and count the number of calls to GetResultHpsNotify.
@@ -86,6 +86,6 @@
   base::ObserverList<Observer> observers_;
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
-#endif  // CHROMEOS_DBUS_HUMAN_PRESENCE_FAKE_HUMAN_PRESENCE_DBUS_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_HUMAN_PRESENCE_FAKE_HUMAN_PRESENCE_DBUS_CLIENT_H_
diff --git a/chromeos/dbus/human_presence/human_presence_dbus_client.cc b/chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.cc
similarity index 97%
rename from chromeos/dbus/human_presence/human_presence_dbus_client.cc
rename to chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.cc
index 3f895134..cb06960 100644
--- a/chromeos/dbus/human_presence/human_presence_dbus_client.cc
+++ b/chromeos/ash/components/dbus/human_presence/human_presence_dbus_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/human_presence/human_presence_dbus_client.h"
+#include "chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h"
 
 #include <memory>
 
@@ -11,14 +11,14 @@
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "chromeos/dbus/human_presence/fake_human_presence_dbus_client.h"
+#include "chromeos/ash/components/dbus/human_presence/fake_human_presence_dbus_client.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_proxy.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cros_system_api/dbus/hps/dbus-constants.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -253,4 +253,4 @@
   return g_instance;
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chromeos/dbus/human_presence/human_presence_dbus_client.h b/chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h
similarity index 90%
rename from chromeos/dbus/human_presence/human_presence_dbus_client.h
rename to chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h
index 912ccecb8..a782abcc 100644
--- a/chromeos/dbus/human_presence/human_presence_dbus_client.h
+++ b/chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_HUMAN_PRESENCE_HUMAN_PRESENCE_DBUS_CLIENT_H_
-#define CHROMEOS_DBUS_HUMAN_PRESENCE_HUMAN_PRESENCE_DBUS_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_HUMAN_PRESENCE_HUMAN_PRESENCE_DBUS_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_HUMAN_PRESENCE_HUMAN_PRESENCE_DBUS_CLIENT_H_
 
 #include "base/callback.h"
 #include "base/component_export.h"
 #include "base/observer_list_types.h"
-#include "chromeos/dbus/hps/hps_service.pb.h"
+#include "chromeos/ash/components/dbus/hps/hps_service.pb.h"
 #include "dbus/object_proxy.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -16,7 +16,7 @@
 class Bus;
 }
 
-namespace chromeos {
+namespace ash {
 
 // D-Bus client for human presence sensing. Communicates with the Chrome OS
 // presence daemon to allow for features that depend on user presence.
@@ -91,6 +91,6 @@
   virtual ~HumanPresenceDBusClient();
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
-#endif  // CHROMEOS_DBUS_HUMAN_PRESENCE_HUMAN_PRESENCE_DBUS_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_HUMAN_PRESENCE_HUMAN_PRESENCE_DBUS_CLIENT_H_
diff --git a/chromeos/dbus/smbprovider/BUILD.gn b/chromeos/ash/components/dbus/smbprovider/BUILD.gn
similarity index 83%
rename from chromeos/dbus/smbprovider/BUILD.gn
rename to chromeos/ash/components/dbus/smbprovider/BUILD.gn
index 18d45028..95b6529 100644
--- a/chromeos/dbus/smbprovider/BUILD.gn
+++ b/chromeos/ash/components/dbus/smbprovider/BUILD.gn
@@ -8,8 +8,8 @@
 assert(is_chromeos_ash, "Non-Chrome-OS builds must not depend on //chromeos")
 
 component("smbprovider") {
-  output_name = "chromeos_smbprovider"
-  defines = [ "IS_CHROMEOS_DBUS_SMBPROVIDER_IMPL" ]
+  output_name = "ash_smbprovider"
+  defines = [ "IS_ASH_DBUS_SMBPROVIDER_IMPL" ]
   deps = [
     ":proto",
     "//base",
@@ -28,5 +28,5 @@
   sources =
       [ "//third_party/cros_system_api/dbus/smbprovider/directory_entry.proto" ]
 
-  proto_out_dir = "chromeos/dbus/smbprovider"
+  proto_out_dir = "chromeos/ash/components/dbus/smbprovider"
 }
diff --git a/chromeos/dbus/smbprovider/DIR_METADATA b/chromeos/ash/components/dbus/smbprovider/DIR_METADATA
similarity index 100%
rename from chromeos/dbus/smbprovider/DIR_METADATA
rename to chromeos/ash/components/dbus/smbprovider/DIR_METADATA
diff --git a/chromeos/dbus/smbprovider/OWNERS b/chromeos/ash/components/dbus/smbprovider/OWNERS
similarity index 100%
rename from chromeos/dbus/smbprovider/OWNERS
rename to chromeos/ash/components/dbus/smbprovider/OWNERS
diff --git a/chromeos/dbus/smbprovider/fake_smb_provider_client.cc b/chromeos/ash/components/dbus/smbprovider/fake_smb_provider_client.cc
similarity index 96%
rename from chromeos/dbus/smbprovider/fake_smb_provider_client.cc
rename to chromeos/ash/components/dbus/smbprovider/fake_smb_provider_client.cc
index 7b2d218..e9f9277 100644
--- a/chromeos/dbus/smbprovider/fake_smb_provider_client.cc
+++ b/chromeos/ash/components/dbus/smbprovider/fake_smb_provider_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/smbprovider/fake_smb_provider_client.h"
+#include "chromeos/ash/components/dbus/smbprovider/fake_smb_provider_client.h"
 
 #include <utility>
 
@@ -10,7 +10,7 @@
 #include "base/callback.h"
 #include "base/threading/thread_task_runner_handle.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -107,4 +107,4 @@
   std::move(stored_readdir_callback_).Run();
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chromeos/dbus/smbprovider/fake_smb_provider_client.h b/chromeos/ash/components/dbus/smbprovider/fake_smb_provider_client.h
similarity index 83%
rename from chromeos/dbus/smbprovider/fake_smb_provider_client.h
rename to chromeos/ash/components/dbus/smbprovider/fake_smb_provider_client.h
index 59885f7b..a266980 100644
--- a/chromeos/dbus/smbprovider/fake_smb_provider_client.h
+++ b/chromeos/ash/components/dbus/smbprovider/fake_smb_provider_client.h
@@ -2,20 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_SMBPROVIDER_FAKE_SMB_PROVIDER_CLIENT_H_
-#define CHROMEOS_DBUS_SMBPROVIDER_FAKE_SMB_PROVIDER_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_SMBPROVIDER_FAKE_SMB_PROVIDER_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_SMBPROVIDER_FAKE_SMB_PROVIDER_CLIENT_H_
 
 #include <map>
 #include <string>
 #include <vector>
 
 #include "base/component_export.h"
-#include "chromeos/dbus/smbprovider/smb_provider_client.h"
+#include "chromeos/ash/components/dbus/smbprovider/smb_provider_client.h"
 
-namespace chromeos {
+namespace ash {
 
 // A fake implementation of SmbProviderClient.
-class COMPONENT_EXPORT(CHROMEOS_DBUS_SMBPROVIDER) FakeSmbProviderClient
+class COMPONENT_EXPORT(ASH_DBUS_SMBPROVIDER) FakeSmbProviderClient
     : public SmbProviderClient {
  public:
   FakeSmbProviderClient();
@@ -79,11 +79,6 @@
   std::map<std::string, ShareResult> shares_;
 };
 
-}  // namespace chromeos
-
-// TODO(https://crbug.com/1164001): remove when moved to ash.
-namespace ash {
-using ::chromeos::FakeSmbProviderClient;
 }  // namespace ash
 
-#endif  // CHROMEOS_DBUS_SMBPROVIDER_FAKE_SMB_PROVIDER_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_SMBPROVIDER_FAKE_SMB_PROVIDER_CLIENT_H_
diff --git a/chromeos/dbus/smbprovider/smb_provider_client.cc b/chromeos/ash/components/dbus/smbprovider/smb_provider_client.cc
similarity index 97%
rename from chromeos/dbus/smbprovider/smb_provider_client.cc
rename to chromeos/ash/components/dbus/smbprovider/smb_provider_client.cc
index 3f4655e..91d8716 100644
--- a/chromeos/dbus/smbprovider/smb_provider_client.cc
+++ b/chromeos/ash/components/dbus/smbprovider/smb_provider_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/smbprovider/smb_provider_client.h"
+#include "chromeos/ash/components/dbus/smbprovider/smb_provider_client.h"
 
 #include <memory>
 
@@ -11,12 +11,12 @@
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
-#include "chromeos/dbus/smbprovider/fake_smb_provider_client.h"
+#include "chromeos/ash/components/dbus/smbprovider/fake_smb_provider_client.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_proxy.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -259,4 +259,4 @@
   g_instance = nullptr;
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chromeos/dbus/smbprovider/smb_provider_client.h b/chromeos/ash/components/dbus/smbprovider/smb_provider_client.h
similarity index 87%
rename from chromeos/dbus/smbprovider/smb_provider_client.h
rename to chromeos/ash/components/dbus/smbprovider/smb_provider_client.h
index 77c1b41..4862103a5 100644
--- a/chromeos/dbus/smbprovider/smb_provider_client.h
+++ b/chromeos/ash/components/dbus/smbprovider/smb_provider_client.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_DBUS_SMBPROVIDER_SMB_PROVIDER_CLIENT_H_
-#define CHROMEOS_DBUS_SMBPROVIDER_SMB_PROVIDER_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_SMBPROVIDER_SMB_PROVIDER_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_SMBPROVIDER_SMB_PROVIDER_CLIENT_H_
 
 #include <memory>
 #include <string>
@@ -13,17 +13,17 @@
 #include "base/files/file_path.h"
 #include "base/files/scoped_file.h"
 #include "base/memory/weak_ptr.h"
+#include "chromeos/ash/components/dbus/smbprovider/directory_entry.pb.h"
 #include "chromeos/dbus/common/dbus_client.h"
-#include "chromeos/dbus/smbprovider/directory_entry.pb.h"
 #include "dbus/object_proxy.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace ash {
 
 // SmbProviderClient is used to communicate with the org.chromium.SmbProvider
 // service. All methods should be called from the origin thread (UI thread)
 // which initializes the DBusThreadManager instance.
-class COMPONENT_EXPORT(CHROMEOS_DBUS_SMBPROVIDER) SmbProviderClient
+class COMPONENT_EXPORT(ASH_DBUS_SMBPROVIDER) SmbProviderClient
     : public DBusClient,
       public base::SupportsWeakPtr<SmbProviderClient> {
  public:
@@ -77,11 +77,6 @@
   ~SmbProviderClient() override;
 };
 
-}  // namespace chromeos
-
-// TODO(https://crbug.com/1164001): remove when move to ash
-namespace ash {
-using ::chromeos::SmbProviderClient;
 }  // namespace ash
 
-#endif  // CHROMEOS_DBUS_SMBPROVIDER_SMB_PROVIDER_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_SMBPROVIDER_SMB_PROVIDER_CLIENT_H_
diff --git a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc
index db8809a..c8d80970 100644
--- a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc
+++ b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc
@@ -90,6 +90,33 @@
   return OverloadedFunctor<Ts...>{std::forward<Ts>(ts)...};
 }
 
+absl::optional<cryptohome::KeyData> AuthFactorToKeyData(
+    std::string label,
+    const FakeAuthFactor& factor) {
+  absl::optional<cryptohome::KeyData> data;
+  absl::visit(Overload(
+                  [&](const PasswordFactor& password) {
+                    data = cryptohome::KeyData();
+                    data->set_type(cryptohome::KeyData::KEY_TYPE_PASSWORD);
+                    data->set_label(std::move(label));
+                  },
+                  [&](const PinFactor& pin) {
+                    data = cryptohome::KeyData();
+                    data->set_type(cryptohome::KeyData::KEY_TYPE_PASSWORD);
+                    data->set_label(std::move(label));
+                    data->mutable_policy()->set_low_entropy_credential(true);
+                    data->mutable_policy()->set_auth_locked(pin.locked);
+                  },
+                  [&](const RecoveryFactor& recovery) { data = absl::nullopt; },
+                  [&](const KioskFactor& kiosk) {
+                    data = cryptohome::KeyData();
+                    data->set_type(cryptohome::KeyData::KEY_TYPE_KIOSK);
+                    data->set_label(std::move(label));
+                  }),
+              factor);
+  return data;
+}
+
 // Helper that automatically sends a reply struct to a supplied callback when
 // it goes out of scope. Basically a specialized `absl::Cleanup` or
 // `std::scope_exit`.
@@ -330,30 +357,14 @@
     const std::string& label = factors_it->first;
     const FakeAuthFactor& factor = factors_it->second;
 
-    absl::visit(Overload(
-                    [&](const PasswordFactor& password) {
-                      cryptohome::KeyData* data = reply.add_key_data();
-                      data->set_type(cryptohome::KeyData::KEY_TYPE_PASSWORD);
-                      data->set_label(label);
-                    },
-                    [&](const PinFactor& pin) {
-                      cryptohome::KeyData* data = reply.add_key_data();
-                      data->set_type(cryptohome::KeyData::KEY_TYPE_PASSWORD);
-                      data->set_label(label);
-                      data->mutable_policy()->set_low_entropy_credential(true);
-                      data->mutable_policy()->set_auth_locked(pin.locked);
-                    },
-                    [&](const RecoveryFactor& recovery) {
-                      // Retrieving key data for recovery code via the legacy
-                      // API is not allowed.
-                      LOG(WARNING) << "Not reporting recovery key: " << label;
-                    },
-                    [&](const KioskFactor& kiosk) {
-                      cryptohome::KeyData* data = reply.add_key_data();
-                      data->set_type(cryptohome::KeyData::KEY_TYPE_KIOSK);
-                      data->set_label(label);
-                    }),
-                factor);
+    absl::optional<cryptohome::KeyData> key_data =
+        AuthFactorToKeyData(label, factor);
+    if (key_data.has_value()) {
+      reply.mutable_key_data()->Add(std::move(*key_data));
+    } else {
+      LOG(WARNING) << "Ignoring auth factor incompatible with legacy API: "
+                   << label;
+    }
   }
 
   if (reply.key_data().empty()) {
@@ -584,6 +595,9 @@
 void FakeUserDataAuthClient::StartAuthSession(
     const ::user_data_auth::StartAuthSessionRequest& request,
     StartAuthSessionCallback callback) {
+  ::user_data_auth::StartAuthSessionReply reply;
+  ReplyOnReturn auto_reply(&reply, std::move(callback));
+
   std::string auth_session_id =
       base::StringPrintf(kAuthSessionIdTemplate, next_auth_session_id_++);
 
@@ -592,37 +606,62 @@
   session.id = auth_session_id;
   session.account = request.account_id();
 
-  std::string user_id = request.account_id().account_id();
-  // See device_local_account.h
-  bool is_kiosk = base::EndsWith(user_id, "kiosk-apps.device-local.localhost");
-
-  ::user_data_auth::StartAuthSessionReply reply;
   if (cryptohome_error_ !=
       ::user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_NOT_SET) {
     reply.set_error(cryptohome_error_);
-  } else {
-    reply.set_auth_session_id(auth_session_id);
-    bool user_exists = UserExists(request.account_id());
-    reply.set_user_exists(user_exists);
-    if (user_exists) {
-      if (is_kiosk) {
-        // see kCryptohomePublicMountLabel
-        std::string kiosk_label = "publicmount";
-        cryptohome::KeyData kiosk_key;
-        kiosk_key.set_label(kiosk_label);
-        kiosk_key.set_type(cryptohome::KeyData::KEY_TYPE_KIOSK);
-        (*reply.mutable_key_label_data())[kiosk_label] = std::move(kiosk_key);
+    return;
+  }
+
+  reply.set_auth_session_id(auth_session_id);
+  bool user_exists = UserExists(request.account_id());
+  reply.set_user_exists(user_exists);
+
+  const auto user_it = users_.find(request.account_id());
+  if (user_it != std::end(users_)) {
+    const UserCryptohomeState& user_state = user_it->second;
+    for (const auto& [label, factor] : user_state.auth_factors) {
+      absl::optional<cryptohome::KeyData> key_data =
+          AuthFactorToKeyData(label, factor);
+      if (key_data) {
+        reply.mutable_key_label_data()->insert({label, std::move(*key_data)});
       } else {
-        // see kCryptohomeGaiaKeyLabel
-        std::string gaia_label = "gaia";
-        cryptohome::KeyData gaia_key;
-        gaia_key.set_label(gaia_label);
-        gaia_key.set_type(cryptohome::KeyData::KEY_TYPE_PASSWORD);
-        (*reply.mutable_key_label_data())[gaia_label] = std::move(gaia_key);
+        LOG(WARNING) << "Ignoring auth factor incompatible with legacy API: "
+                     << label;
       }
     }
   }
-  ReturnProtobufMethodCallback(reply, std::move(callback));
+
+  // TODO(crbug.com/1334538): Some tests expect that kiosk or gaia keys exist
+  // for existing users, but don't set those keys up. Until those tests are
+  // fixed, we explicitly add keys here.
+  if (user_exists) {
+    const std::string& account_id = request.account_id().account_id();
+    // See device_local_account.h
+    const bool is_kiosk =
+        base::EndsWith(account_id, "kiosk-apps.device-local.localhost");
+
+    if (is_kiosk) {
+      // See kCryptohomePublicMountLabel.
+      std::string kiosk_label = "publicmount";
+      cryptohome::KeyData kiosk_key;
+      kiosk_key.set_label(kiosk_label);
+      kiosk_key.set_type(cryptohome::KeyData::KEY_TYPE_KIOSK);
+      const auto [_, was_inserted] = reply.mutable_key_label_data()->insert(
+          {std::move(kiosk_label), std::move(kiosk_key)});
+      LOG_IF(ERROR, was_inserted)
+          << "Listing kiosk key even though it was not set up";
+    } else {
+      // See kCryptohomeGaiaKeyLabel.
+      std::string gaia_label = "gaia";
+      cryptohome::KeyData gaia_key;
+      gaia_key.set_label(gaia_label);
+      gaia_key.set_type(cryptohome::KeyData::KEY_TYPE_PASSWORD);
+      const auto [_, was_inserted] = reply.mutable_key_label_data()->insert(
+          {std::move(gaia_label), std::move(gaia_key)});
+      LOG_IF(ERROR, was_inserted)
+          << "Listing gaia key even though it was not set up";
+    }
+  }
 }
 
 void FakeUserDataAuthClient::AuthenticateAuthSession(
@@ -966,6 +1005,9 @@
     return true;
   }
 
+  if (user_data_dir_.empty())
+    return false;
+
   base::ScopedAllowBlockingForTesting allow_io;
   bool result = base::PathExists(GetUserProfileDir(account_id));
   LOG(INFO) << "User " << (result ? "exists" : "does not exist")
diff --git a/chromeos/ash/components/human_presence/BUILD.gn b/chromeos/ash/components/human_presence/BUILD.gn
index e8566de7..650ef18c 100644
--- a/chromeos/ash/components/human_presence/BUILD.gn
+++ b/chromeos/ash/components/human_presence/BUILD.gn
@@ -20,8 +20,8 @@
 
   public_deps = [
     "//base",
-    "//chromeos/dbus/human_presence",
-    "//chromeos/dbus/human_presence:hps_proto",
+    "//chromeos/ash/components/dbus/human_presence",
+    "//chromeos/ash/components/dbus/human_presence:hps_proto",
   ]
 }
 
diff --git a/chromeos/ash/components/human_presence/DEPS b/chromeos/ash/components/human_presence/DEPS
new file mode 100644
index 0000000..2fe32d2
--- /dev/null
+++ b/chromeos/ash/components/human_presence/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+chromeos/ash/components/dbus",
+]
diff --git a/chromeos/ash/components/human_presence/human_presence_configuration.cc b/chromeos/ash/components/human_presence/human_presence_configuration.cc
index 034e981..c5d1e1a 100644
--- a/chromeos/ash/components/human_presence/human_presence_configuration.cc
+++ b/chromeos/ash/components/human_presence/human_presence_configuration.cc
@@ -10,7 +10,7 @@
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/hps/hps_service.pb.h"
+#include "chromeos/ash/components/dbus/hps/hps_service.pb.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace hps {
diff --git a/chromeos/ash/components/human_presence/human_presence_configuration.h b/chromeos/ash/components/human_presence/human_presence_configuration.h
index 5ea65a01..694fb165 100644
--- a/chromeos/ash/components/human_presence/human_presence_configuration.h
+++ b/chromeos/ash/components/human_presence/human_presence_configuration.h
@@ -7,7 +7,7 @@
 
 #include "base/component_export.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/hps/hps_service.pb.h"
+#include "chromeos/ash/components/dbus/hps/hps_service.pb.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
diff --git a/chromeos/ash/components/human_presence/human_presence_configuration_unittest.cc b/chromeos/ash/components/human_presence/human_presence_configuration_unittest.cc
index d6b4b40..3333030 100644
--- a/chromeos/ash/components/human_presence/human_presence_configuration_unittest.cc
+++ b/chromeos/ash/components/human_presence/human_presence_configuration_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "ash/constants/ash_features.h"
 #include "base/test/scoped_feature_list.h"
-#include "chromeos/dbus/hps/hps_service.pb.h"
+#include "chromeos/ash/components/dbus/hps/hps_service.pb.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chromeos/ash/components/human_presence/test/human_presence_internals_browsertest.js b/chromeos/ash/components/human_presence/test/human_presence_internals_browsertest.js
index defa5f58..300ce4a 100644
--- a/chromeos/ash/components/human_presence/test/human_presence_internals_browsertest.js
+++ b/chromeos/ash/components/human_presence/test/human_presence_internals_browsertest.js
@@ -7,8 +7,8 @@
  */
 
 GEN('#include "content/public/test/browser_test.h"');
-GEN('#include "chromeos/dbus/human_presence/fake_human_presence_dbus_client.h"');
-GEN('#include "chromeos/dbus/human_presence/human_presence_dbus_client.h"');
+GEN('#include "chromeos/ash/components/dbus/human_presence/fake_human_presence_dbus_client.h"');
+GEN('#include "chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h"');
 
 const HOST_ORIGIN = 'chrome://hps-internals';
 
@@ -30,16 +30,16 @@
   /** @override */
   testGenPreamble() {
     GEN(`
-        chromeos::HumanPresenceDBusClient::InitializeFake();
-        chromeos::FakeHumanPresenceDBusClient::Get()->Reset();
-        chromeos::FakeHumanPresenceDBusClient::Get()->
+        ash::HumanPresenceDBusClient::InitializeFake();
+        ash::FakeHumanPresenceDBusClient::Get()->Reset();
+        ash::FakeHumanPresenceDBusClient::Get()->
             set_hps_service_is_available(true);
         hps::HpsResultProto result_proto;
         result_proto.set_value(hps::HpsResult::POSITIVE);
-        chromeos::FakeHumanPresenceDBusClient::Get()->set_hps_sense_result(
+        ash::FakeHumanPresenceDBusClient::Get()->set_hps_sense_result(
             result_proto);
         result_proto.set_value(hps::HpsResult::NEGATIVE);
-        chromeos::FakeHumanPresenceDBusClient::Get()->set_hps_notify_result(
+        ash::FakeHumanPresenceDBusClient::Get()->set_hps_notify_result(
             result_proto);
     `);
   }
diff --git a/chromeos/crosapi/mojom/test_controller.mojom b/chromeos/crosapi/mojom/test_controller.mojom
index 126acf2..fdb008c 100644
--- a/chromeos/crosapi/mojom/test_controller.mojom
+++ b/chromeos/crosapi/mojom/test_controller.mojom
@@ -4,8 +4,9 @@
 
 module crosapi.mojom;
 
-import "ui/gfx/geometry/mojom/geometry.mojom";
 import "chromeos/crosapi/mojom/app_service_types.mojom";
+import "mojo/public/mojom/base/values.mojom";
+import "ui/gfx/geometry/mojom/geometry.mojom";
 
 [Stable, Extensible]
 enum TouchEventType {
@@ -65,10 +66,58 @@
 };
 
 // This interface is implemented by Ash-Chrome.
+// It enables tests in Lacros-Chrome to access the TestInterfaces
+// of chromeos::Shill*Client classes.
+[Stable, Uuid="12d5dbb4-e974-4f41-820e-6d92c2215452"]
+interface ShillClientTestInterface {
+  // From chromeos::ShillDeviceClient::TestInterface:
+
+  // Adds a fake networking device.
+  AddDevice@0(string device_path, string type,string name) => ();
+  // Clear all fake networking devices.
+  ClearDevices@1() => ();
+  // Sets a property on the given fake device.
+  SetDeviceProperty@2(string device_path,
+      string name,
+      mojo_base.mojom.Value value,
+      bool notify_changed) => ();
+  // Sets whether the SIM in the given fake device should be locked.
+  SetSimLocked@3(string device_path, bool enabled) => ();
+
+  // From chromeos::ShillServiceClient::TestInterface:
+
+  // Adds a Service to the Manager and Service stubs.
+  AddService@4(string service_path,
+      string guid,
+      string name,
+      string type,
+      string state,
+      bool visible) => ();
+  // Clears all Services from the Manager and Service stubs.
+  ClearServices@5() => ();
+  // Sets a property of the specified service.
+  SetServiceProperty@6(string service_path, string property,
+      mojo_base.mojom.Value value) => ();
+
+  // From chromeos::ShillProfileClient::TestInterface:
+
+  // Adds a profile.
+  AddProfile@7(string profile_path, string userhash) => ();
+  // Adds a service to the profile, copying properties from the
+  // ShillServiceClient entry matching |service_path|.
+  AddServiceToProfile@8(string profile_path, string service_path) => ();
+
+  // From chromeos::ShillIPConfigClient::TestInterface:
+
+  // Adds an IPConfig entry.
+  AddIPConfig@9(string ip_config_path, mojo_base.mojom.Value properties) => ();
+};
+
+// This interface is implemented by Ash-Chrome.
 // This interface provides tests a mechanism to mutate or query ash.
 // In the future, this interface may merge with an automation or a11y interface.
-// Next version: 16
-// Next method id: 25
+// Next version: 17
+// Next method id: 27
 [Stable, Uuid="1f93f9d7-e466-466c-a675-c21b48cf30d3"]
 interface TestController {
   // Clicks the middle of the views element identified by |element_name|.
@@ -209,4 +258,14 @@
   // Creates and then cancels a print job.
   [MinVersion=15]
   CreateAndCancelPrintJob@24(string job_title) => ();
+
+  // Binds a |shill_client| that Lacros-Chrome can use to access the Shill
+  // test intefaces in Ash-Chrome.
+  [MinVersion=16]
+  BindShillClientTestInterface@25(
+      pending_receiver<ShillClientTestInterface> shill_client) => ();
+
+  // Returns the sanitized (aka "hashed") username of the active user.
+  [MinVersion=16]
+  GetSanitizedActiveUsername@26() => (string sanitized_active_username);
 };
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn
index 7d37ef6..c126a177 100644
--- a/chromeos/dbus/BUILD.gn
+++ b/chromeos/dbus/BUILD.gn
@@ -39,8 +39,6 @@
     "//chromeos/dbus/oobe_config:proto",
     "//chromeos/dbus/runtime_probe",
     "//chromeos/dbus/runtime_probe:proto",
-    "//chromeos/dbus/smbprovider",
-    "//chromeos/dbus/smbprovider:proto",
     "//chromeos/dbus/util",
     "//components/account_id",
     "//components/device_event_log",
diff --git a/chromeos/dbus/resourced/fake_resourced_client.cc b/chromeos/dbus/resourced/fake_resourced_client.cc
index cca24dc..c00fe77 100644
--- a/chromeos/dbus/resourced/fake_resourced_client.cc
+++ b/chromeos/dbus/resourced/fake_resourced_client.cc
@@ -13,17 +13,16 @@
 FakeResourcedClient::~FakeResourcedClient() = default;
 
 void FakeResourcedClient::SetGameModeWithTimeout(
-    bool state,
+    GameMode state,
     uint32_t refresh_seconds,
-    DBusMethodCallback<bool> callback) {
-  absl::optional<bool> response = previous_game_mode_state_;
-  if (state) {
-    enter_game_mode_count_++;
-    previous_game_mode_state_ = true;
-  } else {
+    DBusMethodCallback<GameMode> callback) {
+  absl::optional<GameMode> response = previous_game_mode_state_;
+  if (state == GameMode::OFF) {
     exit_game_mode_count_++;
-    previous_game_mode_state_ = false;
+  } else {
+    enter_game_mode_count_++;
   }
+  previous_game_mode_state_ = state;
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), response));
 }
diff --git a/chromeos/dbus/resourced/fake_resourced_client.h b/chromeos/dbus/resourced/fake_resourced_client.h
index 020c11b2..2a17082 100644
--- a/chromeos/dbus/resourced/fake_resourced_client.h
+++ b/chromeos/dbus/resourced/fake_resourced_client.h
@@ -20,9 +20,9 @@
   FakeResourcedClient& operator=(const FakeResourcedClient&) = delete;
 
   // ResourcedClient:
-  void SetGameModeWithTimeout(bool state,
+  void SetGameModeWithTimeout(GameMode game_mode,
                               uint32_t refresh_seconds,
-                              DBusMethodCallback<bool> callback) override;
+                              DBusMethodCallback<GameMode> callback) override;
 
   void SetMemoryMarginsBps(uint32_t critical,
                            uint32_t moderate,
@@ -32,11 +32,12 @@
     total_system_memory_kb_ = mem_kb;
   }
 
-  void set_set_game_mode_response(absl::optional<bool> response) {
+  void set_set_game_mode_response(absl::optional<GameMode> response) {
     set_game_mode_response_ = response;
   }
 
-  void set_set_game_mode_with_timeout_response(absl::optional<bool> response) {
+  void set_set_game_mode_with_timeout_response(
+      absl::optional<GameMode> response) {
     previous_game_mode_state_ = response;
   }
 
@@ -55,8 +56,8 @@
                                uint64_t reclaim_target_kb);
 
  private:
-  absl::optional<bool> set_game_mode_response_;
-  absl::optional<bool> previous_game_mode_state_ = false;
+  absl::optional<GameMode> set_game_mode_response_;
+  absl::optional<GameMode> previous_game_mode_state_ = GameMode::OFF;
 
   int enter_game_mode_count_ = 0;
   int exit_game_mode_count_ = 0;
diff --git a/chromeos/dbus/resourced/resourced_client.cc b/chromeos/dbus/resourced/resourced_client.cc
index d0b51bfa..ed76928 100644
--- a/chromeos/dbus/resourced/resourced_client.cc
+++ b/chromeos/dbus/resourced/resourced_client.cc
@@ -54,9 +54,9 @@
   }
 
   // ResourcedClient interface.
-  void SetGameModeWithTimeout(bool state,
+  void SetGameModeWithTimeout(GameMode game_mode,
                               uint32_t refresh_seconds,
-                              DBusMethodCallback<bool> callback) override;
+                              DBusMethodCallback<GameMode> callback) override;
 
   void SetMemoryMarginsBps(uint32_t critical_margin,
                            uint32_t moderate_margin,
@@ -72,8 +72,9 @@
 
  private:
   // D-Bus response handlers.
-  void HandleSetGameModeWithTimeoutResponse(DBusMethodCallback<bool> callback,
-                                            dbus::Response* response);
+  void HandleSetGameModeWithTimeoutResponse(
+      DBusMethodCallback<GameMode> callback,
+      dbus::Response* response);
 
   void HandleSetMemoryMarginBps(uint32_t critical_margin,
                                 uint32_t moderate_margin,
@@ -204,7 +205,7 @@
 
 // Response will be true if game mode was on previously, false otherwise.
 void ResourcedClientImpl::HandleSetGameModeWithTimeoutResponse(
-    DBusMethodCallback<bool> callback,
+    DBusMethodCallback<GameMode> callback,
     dbus::Response* response) {
   dbus::MessageReader reader(response);
   uint8_t previous;
@@ -212,17 +213,17 @@
     std::move(callback).Run(absl::nullopt);
     return;
   }
-  std::move(callback).Run(previous);
+  std::move(callback).Run(static_cast<GameMode>(previous));
 }
 
 void ResourcedClientImpl::SetGameModeWithTimeout(
-    bool status,
+    GameMode game_mode,
     uint32_t refresh_seconds,
-    DBusMethodCallback<bool> callback) {
+    DBusMethodCallback<GameMode> callback) {
   dbus::MethodCall method_call(resource_manager::kResourceManagerInterface,
                                resource_manager::kSetGameModeWithTimeoutMethod);
   dbus::MessageWriter writer(&method_call);
-  writer.AppendByte(status);
+  writer.AppendByte(static_cast<uint8_t>(game_mode));
   writer.AppendUint32(refresh_seconds);
 
   proxy_->CallMethod(
diff --git a/chromeos/dbus/resourced/resourced_client.h b/chromeos/dbus/resourced/resourced_client.h
index 15a6cf0..9bb4189 100644
--- a/chromeos/dbus/resourced/resourced_client.h
+++ b/chromeos/dbus/resourced/resourced_client.h
@@ -9,6 +9,8 @@
 #include "base/observer_list_types.h"
 #include "chromeos/dbus/common/dbus_method_call_status.h"
 
+#include <cstdint>
+
 namespace dbus {
 class Bus;
 }
@@ -50,6 +52,16 @@
     FOREGROUND = 3,
   };
 
+  // Indicates whether game mode is on, and which kind of game mode if it is on.
+  // Borealis game mode will put more memory pressure on ARCVM processes than
+  // will ARC game mode.
+  // D-Bus serializes this as a u8, hence the uint8_t specifier.
+  enum class GameMode : uint8_t {
+    OFF = 0,
+    BOREALIS = 1,
+    ARC = 2,
+  };
+
   // Observer class for ARCVM memory pressure signal.
   class ArcVmObserver : public base::CheckedObserver {
    public:
@@ -74,12 +86,13 @@
   // Returns the global instance which may be null if not initialized.
   static ResourcedClient* Get();
 
-  // Attempts to enter game mode if state is true, exit if state is false.
+  // Attempts to enter or exit game mode depending on the value of |game_mode|.
   // Will automatically exit game mode once refresh_seconds is reached.
   // Callback will be called with whether game mode was on prior to this.
-  virtual void SetGameModeWithTimeout(bool state,
-                                      uint32_t refresh_seconds,
-                                      DBusMethodCallback<bool> callback) = 0;
+  virtual void SetGameModeWithTimeout(
+      GameMode game_mode,
+      uint32_t refresh_seconds,
+      DBusMethodCallback<GameMode> callback) = 0;
 
   using SetMemoryMarginsBpsCallback =
       base::OnceCallback<void(bool, uint64_t, uint64_t)>;
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 581749d..30f0395 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -373,6 +373,7 @@
       "//components/paint_preview/player:unit_tests",
       "//components/paint_preview/renderer:unit_tests",
       "//components/password_manager/content/browser:unit_tests",
+      "//components/password_manager/services/csv_password:unit_tests",
       "//components/payments/content:unit_tests",
       "//components/payments/content/utility:unit_tests",
       "//components/performance_manager:unit_tests",
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc
index 28a2c71..fcb909e1 100644
--- a/components/autofill/content/renderer/form_autofill_util.cc
+++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -307,21 +307,14 @@
 
 bool IsLabelValid(base::StringPiece16 inferred_label) {
   // List of characters a label can't be entirely made of (this list can grow).
-  auto IsStopWord = [](char16_t c) {
-    switch (c) {
-      case u' ':
-      case u'*':
-      case u':':
-      case u'-':
-      case u'–':  // U+2013
-      case u'(':
-      case u')':
-        return true;
-      default:
-        return false;
-    }
-  };
-  return !base::ranges::all_of(inferred_label, IsStopWord);
+  const base::StringPiece16 invalid_chars =
+      base::FeatureList::IsEnabled(
+          features::kAutofillConsiderPhoneNumberSeparatorsValidLabels)
+          ? u" *:"
+          : u" *:-–()";  // U+2013 dash
+  return !base::ranges::all_of(inferred_label, [&](char16_t c) {
+    return base::Contains(invalid_chars, c);
+  });
 }
 
 // Shared function for InferLabelFromPrevious() and InferLabelFromNext().
diff --git a/components/autofill/content/renderer/form_autofill_util_browsertest.cc b/components/autofill/content/renderer/form_autofill_util_browsertest.cc
index e7d45b0..562d0d2e 100644
--- a/components/autofill/content/renderer/form_autofill_util_browsertest.cc
+++ b/components/autofill/content/renderer/form_autofill_util_browsertest.cc
@@ -207,11 +207,11 @@
       {"DIV table test 6", R"(
        <div>
          label
-         <div>-</div>
+         <div>*</div>
          <div><input id='target'></div>
        </div>)",
-       // TODO(crbug.com/796918): Should be "label" or "label-". This happens
-       // because "-" is inferred, but discarded because `!IsLabelValid()`.
+       // TODO(crbug.com/796918): Should be "label" or "label*". This happens
+       // because "*" is inferred, but discarded because `!IsLabelValid()`.
        u""},
       {"Infer from next sibling",
        "<input id='target' type='checkbox'>hello <b>world</b>", u"hello world"},
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
index a610fead..6b4a77e9 100644
--- a/components/autofill/core/browser/BUILD.gn
+++ b/components/autofill/core/browser/BUILD.gn
@@ -198,6 +198,8 @@
     "form_parsing/search_field.h",
     "form_parsing/travel_field.cc",
     "form_parsing/travel_field.h",
+    "form_processing/autocomplete_attribute_processing_util.cc",
+    "form_processing/autocomplete_attribute_processing_util.h",
     "form_processing/label_processing_util.cc",
     "form_processing/label_processing_util.h",
     "form_processing/name_processing_util.cc",
diff --git a/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.cc b/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.cc
new file mode 100644
index 0000000..d9e296f7
--- /dev/null
+++ b/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.cc
@@ -0,0 +1,299 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.h"
+
+#include <vector>
+
+#include "base/containers/fixed_flat_map.h"
+#include "base/notreached.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/autofill_regexes.h"
+#include "components/autofill/core/common/autofill_features.h"
+#include "components/autofill/core/common/autofill_util.h"
+
+namespace autofill {
+
+namespace {
+
+// Returns true iff the `token` is a type hint for a contact field, as
+// specified in the implementation section of http://is.gd/whatwg_autocomplete
+// Note that "fax" and "pager" are intentionally ignored, as Chrome does not
+// support filling either type of information.
+bool IsContactTypeHint(const std::string& token) {
+  return token == "home" || token == "work" || token == "mobile";
+}
+
+// Returns true iff the `token` is a type hint appropriate for a field of the
+// given `field_type`, as specified in the implementation section of
+// http://is.gd/whatwg_autocomplete
+bool ContactTypeHintMatchesFieldType(const std::string& token,
+                                     HtmlFieldType field_type) {
+  // The "home" and "work" type hints are only appropriate for email and phone
+  // number field types.
+  if (token == "home" || token == "work") {
+    return field_type == HTML_TYPE_EMAIL ||
+           (field_type >= HTML_TYPE_TEL &&
+            field_type <= HTML_TYPE_TEL_LOCAL_SUFFIX);
+  }
+
+  // The "mobile" type hint is only appropriate for phone number field types.
+  // Note that "fax" and "pager" are intentionally ignored, as Chrome does not
+  // support filling either type of information.
+  if (token == "mobile") {
+    return field_type >= HTML_TYPE_TEL &&
+           field_type <= HTML_TYPE_TEL_LOCAL_SUFFIX;
+  }
+
+  return false;
+}
+
+// Rationalizes the HTML `type` of `field`, based on the fields properties. At
+// the moment only `max_length` is considered. For example, a max_length of 4
+// might indicate a 4 digit year.
+// In case no rationalization rule applies, the original type is returned.
+HtmlFieldType RationalizeAutocompleteType(HtmlFieldType type,
+                                          const AutofillField& field) {
+  // (original-type, max-length) -> new-type
+  static constexpr auto rules =
+      base::MakeFixedFlatMap<std::pair<HtmlFieldType, uint64_t>, HtmlFieldType>(
+          {
+              {{HTML_TYPE_ADDITIONAL_NAME, 1},
+               HTML_TYPE_ADDITIONAL_NAME_INITIAL},
+              {{HTML_TYPE_CREDIT_CARD_EXP, 5},
+               HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR},
+              {{HTML_TYPE_CREDIT_CARD_EXP, 7},
+               HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR},
+              {{HTML_TYPE_CREDIT_CARD_EXP_YEAR, 2},
+               HTML_TYPE_CREDIT_CARD_EXP_2_DIGIT_YEAR},
+              {{HTML_TYPE_CREDIT_CARD_EXP_YEAR, 4},
+               HTML_TYPE_CREDIT_CARD_EXP_4_DIGIT_YEAR},
+          });
+
+  auto* it = rules.find(std::make_pair(type, field.max_length));
+  return it == rules.end() ? type : it->second;
+}
+
+// Chrome Autofill supports a subset of the field types listed at
+// http://is.gd/whatwg_autocomplete. Returns the corresponding HtmlFieldType, if
+// `value` matches any of them.
+absl::optional<HtmlFieldType> ParseStandardizedAutocompleteAttribute(
+    base::StringPiece value) {
+  static constexpr auto standardized_attributes =
+      base::MakeFixedFlatMap<base::StringPiece, HtmlFieldType>({
+          {"additional-name", HTML_TYPE_ADDITIONAL_NAME},
+          {"address-level1", HTML_TYPE_ADDRESS_LEVEL1},
+          {"address-level2", HTML_TYPE_ADDRESS_LEVEL2},
+          {"address-level3", HTML_TYPE_ADDRESS_LEVEL3},
+          {"address-line1", HTML_TYPE_ADDRESS_LINE1},
+          {"address-line2", HTML_TYPE_ADDRESS_LINE2},
+          {"address-line3", HTML_TYPE_ADDRESS_LINE3},
+          {"cc-csc", HTML_TYPE_CREDIT_CARD_VERIFICATION_CODE},
+          {"cc-exp", HTML_TYPE_CREDIT_CARD_EXP},
+          {"cc-exp-month", HTML_TYPE_CREDIT_CARD_EXP_MONTH},
+          {"cc-exp-year", HTML_TYPE_CREDIT_CARD_EXP_YEAR},
+          {"cc-family-name", HTML_TYPE_CREDIT_CARD_NAME_LAST},
+          {"cc-given-name", HTML_TYPE_CREDIT_CARD_NAME_FIRST},
+          {"cc-name", HTML_TYPE_CREDIT_CARD_NAME_FULL},
+          {"cc-number", HTML_TYPE_CREDIT_CARD_NUMBER},
+          {"cc-type", HTML_TYPE_CREDIT_CARD_TYPE},
+          {"country", HTML_TYPE_COUNTRY_CODE},
+          {"country-name", HTML_TYPE_COUNTRY_NAME},
+          {"email", HTML_TYPE_EMAIL},
+          {"family-name", HTML_TYPE_FAMILY_NAME},
+          {"given-name", HTML_TYPE_GIVEN_NAME},
+          {"honorific-prefix", HTML_TYPE_HONORIFIC_PREFIX},
+          {"name", HTML_TYPE_NAME},
+          {"one-time-code", HTML_TYPE_ONE_TIME_CODE},
+          {"organization", HTML_TYPE_ORGANIZATION},
+          {"postal-code", HTML_TYPE_POSTAL_CODE},
+          {"street-address", HTML_TYPE_STREET_ADDRESS},
+          {"tel-area-code", HTML_TYPE_TEL_AREA_CODE},
+          {"tel-country-code", HTML_TYPE_TEL_COUNTRY_CODE},
+          {"tel-extension", HTML_TYPE_TEL_EXTENSION},
+          {"tel", HTML_TYPE_TEL},
+          {"tel-local", HTML_TYPE_TEL_LOCAL},
+          {"tel-local-prefix", HTML_TYPE_TEL_LOCAL_PREFIX},
+          {"tel-local-suffix", HTML_TYPE_TEL_LOCAL_SUFFIX},
+          {"tel-national", HTML_TYPE_TEL_NATIONAL},
+          {"transaction-amount", HTML_TYPE_TRANSACTION_AMOUNT},
+          {"transaction-currency", HTML_TYPE_TRANSACTION_CURRENCY},
+      });
+
+  auto* it = standardized_attributes.find(value);
+  return it != standardized_attributes.end()
+             ? absl::optional<HtmlFieldType>(it->second)
+             : absl::nullopt;
+}
+
+// Maps `value`s that Autofill has proposed for the HTML autocomplete standard,
+// but which are not standardized, to their HtmlFieldType.
+absl::optional<HtmlFieldType> ParseProposedAutocompleteAttribute(
+    base::StringPiece value) {
+  static constexpr auto proposed_attributes =
+      base::MakeFixedFlatMap<base::StringPiece, HtmlFieldType>({
+          {"address", HTML_TYPE_STREET_ADDRESS},
+          {"coupon-code", HTML_TYPE_MERCHANT_PROMO_CODE},
+          {"username", HTML_TYPE_EMAIL},
+      });
+
+  auto* it = proposed_attributes.find(value);
+  return it != proposed_attributes.end()
+             ? absl::optional<HtmlFieldType>(it->second)
+             : absl::nullopt;
+}
+
+// Maps non-standardized `value`s for the HTML autocomplete attribute to an
+// HtmlFieldType. This is primarily a list of "reasonable guesses".
+absl::optional<HtmlFieldType> ParseNonStandarizedAutocompleteAttribute(
+    base::StringPiece value) {
+  static constexpr auto non_standardized_attributes =
+      base::MakeFixedFlatMap<base::StringPiece, HtmlFieldType>({
+          {"company", HTML_TYPE_ORGANIZATION},
+          {"first-name", HTML_TYPE_GIVEN_NAME},
+          {"gift-code", HTML_TYPE_MERCHANT_PROMO_CODE},
+          {"locality", HTML_TYPE_ADDRESS_LEVEL2},
+          {"promo-code", HTML_TYPE_MERCHANT_PROMO_CODE},
+          {"promotional-code", HTML_TYPE_MERCHANT_PROMO_CODE},
+          {"promotion-code", HTML_TYPE_MERCHANT_PROMO_CODE},
+          {"region", HTML_TYPE_ADDRESS_LEVEL1},
+          {"tel-ext", HTML_TYPE_TEL_EXTENSION},
+          {"upi", HTML_TYPE_UPI_VPA},
+          {"upi-vpa", HTML_TYPE_UPI_VPA},
+      });
+
+  auto* it = non_standardized_attributes.find(value);
+  return it != non_standardized_attributes.end()
+             ? absl::optional<HtmlFieldType>(it->second)
+             : absl::nullopt;
+}
+
+// If the autocomplete `value` doesn't match any of Autofill's supported values,
+// Autofill should remain enabled for good intended values. This function checks
+// if there is reason to believe so, by matching `value` against patterns like
+// "address".
+// Ignoring autocomplete="off" and alike is treated separately in
+// `ParseFieldTypesFromAutocompleteAttributes()`.
+bool ShouldIgnoreAutocompleteValue(const std::string& value) {
+  return MatchesPattern(base::UTF8ToUTF16(value), u"address");
+}
+
+// Returns the Chrome Autofill-supported field type corresponding to a given
+// autocomplete `value`, if there is one, in the context of the given
+// `field`.
+HtmlFieldType FieldTypeFromAutocompleteAttributeValue(
+    std::string value,
+    const AutofillField& field) {
+  if (value.empty())
+    return HTML_TYPE_UNSPECIFIED;
+
+  // We are lenient and accept '_' instead of '-' as a separator. E.g.
+  // "given_name" is treated like "given-name".
+  base::ReplaceChars(value, "_", "-", &value);
+  // We accept e.g. "phone-country" instead of "tel-country".
+  if (base::StartsWith(value, "phone"))
+    base::ReplaceFirstSubstringAfterOffset(&value, 0, "phone", "tel");
+
+  absl::optional<HtmlFieldType> type =
+      ParseStandardizedAutocompleteAttribute(value);
+  if (!type.has_value()) {
+    type = ParseProposedAutocompleteAttribute(value);
+    if (!type.has_value())
+      type = ParseNonStandarizedAutocompleteAttribute(value);
+  }
+
+  if (type.has_value())
+    return RationalizeAutocompleteType(type.value(), field);
+
+  // `value` cannot be mapped to any HtmlFieldType. By classifying the field
+  // as HTML_TYPE_UNRECOGNIZED Autofill is effectively disabled. Instead, check
+  // if we have reason to ignore the value and treat the field as
+  // HTML_TYPE_UNSPECIFIED. This makes us ignore the autocomplete value.
+  return ShouldIgnoreAutocompleteValue(value) &&
+                 base::FeatureList::IsEnabled(
+                     features::kAutofillIgnoreUnmappableAutocompleteValues)
+             ? HTML_TYPE_UNSPECIFIED
+             : HTML_TYPE_UNRECOGNIZED;
+}
+
+}  // namespace
+
+absl::optional<AutocompleteParsingResult> ParseAutocompleteAttribute(
+    const AutofillField& field) {
+  std::vector<std::string> tokens =
+      LowercaseAndTokenizeAttributeString(field.autocomplete_attribute);
+
+  // The autocomplete attribute is overloaded: it can specify either a field
+  // type hint or whether autocomplete should be enabled at all. Ignore the
+  // latter type of attribute value.
+  if (tokens.empty() ||
+      (tokens.size() == 1 &&
+       (tokens[0] == "on" || tokens[0] == "off" || tokens[0] == "false"))) {
+    return absl::nullopt;
+  }
+
+  AutocompleteParsingResult result;
+
+  // The "webauthn" token is unused by Autofill, but skipped to parse the type
+  // correctly.
+  if (tokens.back() == "webauthn") {
+    tokens.pop_back();
+    if (tokens.empty())
+      return absl::nullopt;
+  }
+
+  // (1) The final token must be the field type.
+  std::string field_type_token = tokens.back();
+  tokens.pop_back();
+  result.field_type =
+      FieldTypeFromAutocompleteAttributeValue(field_type_token, field);
+
+  // (2) The preceding token, if any, may be a type hint.
+  if (!tokens.empty() && IsContactTypeHint(tokens.back())) {
+    // If it is, it must match the field type; otherwise, abort.
+    // Note that an invalid token invalidates the entire attribute value, even
+    // if the other tokens are valid.
+    if (!ContactTypeHintMatchesFieldType(tokens.back(), result.field_type))
+      return absl::nullopt;
+    // Chrome Autofill ignores these type hints.
+    tokens.pop_back();
+  }
+
+  // (3) The preceding token, if any, may be a fixed string that is either
+  // "shipping" or "billing".
+  result.mode = HTML_MODE_NONE;
+  if (!tokens.empty()) {
+    for (HtmlFieldMode mode : {HTML_MODE_BILLING, HTML_MODE_SHIPPING})
+      if (tokens.back() == HtmlFieldModeToStringPiece(mode)) {
+        result.mode = mode;
+        tokens.pop_back();
+        break;
+      }
+  }
+
+  // (4) The preceding token, if any, may be a named section.
+  constexpr base::StringPiece kSectionPrefix = "section-";
+  if (!tokens.empty() && base::StartsWith(tokens.back(), kSectionPrefix,
+                                          base::CompareCase::SENSITIVE)) {
+    // Prepend this section name to the suffix set in the preceding block.
+    result.section = tokens.back().substr(kSectionPrefix.size());
+    tokens.pop_back();
+  }
+
+  // (5) No other tokens are allowed. If there are any remaining, abort.
+  if (!tokens.empty())
+    return absl::nullopt;
+
+  return result;
+}
+
+base::StringPiece HtmlFieldModeToStringPiece(HtmlFieldMode mode) {
+  if (mode == HTML_MODE_BILLING)
+    return "billing";
+  if (mode == HTML_MODE_SHIPPING)
+    return "shipping";
+  NOTREACHED();
+  return "";
+}
+
+}  // namespace autofill
diff --git a/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.h b/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.h
new file mode 100644
index 0000000..7b18b98
--- /dev/null
+++ b/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.h
@@ -0,0 +1,44 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_PROCESSING_AUTOCOMPLETE_ATTRIBUTE_PROCESSING_UTIL_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_PROCESSING_AUTOCOMPLETE_ATTRIBUTE_PROCESSING_UTIL_H_
+
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "components/autofill/core/browser/autofill_field.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace autofill {
+
+// The autocomplete attribute consists of several components, as described at
+// http://is.gd/whatwg_autocomplete. Autofill supports part of the specification
+// and parses the following tokens:
+// [section-*] [shipping|billing] [type_hint] field_type [webauthn]
+// The parsing extracts these components from `field.autocomplete_attribute` or
+// returns absl::nullopt, if the parsing fails. The latter happens if:
+// - The autocomplete value is empty or contains more than 5 tokens.
+// - The type_hint doesn't match the field_type.
+// - Only "on", "off" or "false" is specified (currently ignored by Autofill).
+// An unrecognizable field_type doesn't stop parsing and yields
+// HTML_TYPE_UNRECOGNIZED instead.
+struct AutocompleteParsingResult {
+  // `section` corresponds to the string after "section-".
+  std::string section;
+  HtmlFieldMode mode;
+  // Type hints are parsed and validated, but otherwise unused.
+  HtmlFieldType field_type;
+};
+absl::optional<AutocompleteParsingResult> ParseAutocompleteAttribute(
+    const AutofillField& field);
+
+// Maps HTML_MODE_BILLING and HTML_MODE_SHIPPING to their string constants, as
+// specified in the autocomplete standard.
+base::StringPiece HtmlFieldModeToStringPiece(HtmlFieldMode mode);
+
+}  // namespace autofill
+
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_PROCESSING_AUTOCOMPLETE_ATTRIBUTE_PROCESSING_UTIL_H_
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index 75a7905d..9e5451e 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -40,6 +40,7 @@
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/form_parsing/buildflags.h"
 #include "components/autofill/core/browser/form_parsing/form_field.h"
+#include "components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.h"
 #include "components/autofill/core/browser/form_processing/label_processing_util.h"
 #include "components/autofill/core/browser/form_processing/name_processing_util.h"
 #include "components/autofill/core/browser/logging/log_manager.h"
@@ -73,9 +74,6 @@
 
 namespace {
 
-constexpr char kBillingMode[] = "billing";
-constexpr char kShippingMode[] = "shipping";
-
 // Default section name for the fields.
 constexpr char kDefaultSection[] = "-default";
 
@@ -121,208 +119,6 @@
   return data_presence;
 }
 
-// Returns |true| iff the |token| is a type hint for a contact field, as
-// specified in the implementation section of http://is.gd/whatwg_autocomplete
-// Note that "fax" and "pager" are intentionally ignored, as Chrome does not
-// support filling either type of information.
-bool IsContactTypeHint(const std::string& token) {
-  return token == "home" || token == "work" || token == "mobile";
-}
-
-// Returns |true| iff the |token| is a type hint appropriate for a field of the
-// given |field_type|, as specified in the implementation section of
-// http://is.gd/whatwg_autocomplete
-bool ContactTypeHintMatchesFieldType(const std::string& token,
-                                     HtmlFieldType field_type) {
-  // The "home" and "work" type hints are only appropriate for email and phone
-  // number field types.
-  if (token == "home" || token == "work") {
-    return field_type == HTML_TYPE_EMAIL ||
-           (field_type >= HTML_TYPE_TEL &&
-            field_type <= HTML_TYPE_TEL_LOCAL_SUFFIX);
-  }
-
-  // The "mobile" type hint is only appropriate for phone number field types.
-  // Note that "fax" and "pager" are intentionally ignored, as Chrome does not
-  // support filling either type of information.
-  if (token == "mobile") {
-    return field_type >= HTML_TYPE_TEL &&
-           field_type <= HTML_TYPE_TEL_LOCAL_SUFFIX;
-  }
-
-  return false;
-}
-
-// Rationalizes the HTML `type` of `field`, based on the fields properties. At
-// the moment only `max_length` is considered. For example, a max_length of 4
-// might indicate a 4 digit year.
-// In case no rationalization rule applies, the original type is returned.
-HtmlFieldType RationalizeAutocompleteType(HtmlFieldType type,
-                                          const AutofillField& field) {
-  // (original-type, max-length) -> new-type
-  static constexpr auto rules =
-      base::MakeFixedFlatMap<std::pair<HtmlFieldType, uint64_t>, HtmlFieldType>(
-          {
-              {{HTML_TYPE_ADDITIONAL_NAME, 1},
-               HTML_TYPE_ADDITIONAL_NAME_INITIAL},
-              {{HTML_TYPE_CREDIT_CARD_EXP, 5},
-               HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR},
-              {{HTML_TYPE_CREDIT_CARD_EXP, 7},
-               HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR},
-              {{HTML_TYPE_CREDIT_CARD_EXP_YEAR, 2},
-               HTML_TYPE_CREDIT_CARD_EXP_2_DIGIT_YEAR},
-              {{HTML_TYPE_CREDIT_CARD_EXP_YEAR, 4},
-               HTML_TYPE_CREDIT_CARD_EXP_4_DIGIT_YEAR},
-          });
-
-  auto* it = rules.find(std::make_pair(type, field.max_length));
-  return it == rules.end() ? type : it->second;
-}
-
-// Chrome Autofill supports a subset of the field types listed at
-// http://is.gd/whatwg_autocomplete. Returns the corresponding HtmlFieldType, if
-// `value` matches any of them.
-absl::optional<HtmlFieldType> ParseStandardizedAutocompleteAttribute(
-    base::StringPiece value) {
-  static constexpr auto standardized_attributes =
-      base::MakeFixedFlatMap<base::StringPiece, HtmlFieldType>({
-          {"additional-name", HTML_TYPE_ADDITIONAL_NAME},
-          {"address-level1", HTML_TYPE_ADDRESS_LEVEL1},
-          {"address-level2", HTML_TYPE_ADDRESS_LEVEL2},
-          {"address-level3", HTML_TYPE_ADDRESS_LEVEL3},
-          {"address-line1", HTML_TYPE_ADDRESS_LINE1},
-          {"address-line2", HTML_TYPE_ADDRESS_LINE2},
-          {"address-line3", HTML_TYPE_ADDRESS_LINE3},
-          {"cc-csc", HTML_TYPE_CREDIT_CARD_VERIFICATION_CODE},
-          {"cc-exp", HTML_TYPE_CREDIT_CARD_EXP},
-          {"cc-exp-month", HTML_TYPE_CREDIT_CARD_EXP_MONTH},
-          {"cc-exp-year", HTML_TYPE_CREDIT_CARD_EXP_YEAR},
-          {"cc-family-name", HTML_TYPE_CREDIT_CARD_NAME_LAST},
-          {"cc-given-name", HTML_TYPE_CREDIT_CARD_NAME_FIRST},
-          {"cc-name", HTML_TYPE_CREDIT_CARD_NAME_FULL},
-          {"cc-number", HTML_TYPE_CREDIT_CARD_NUMBER},
-          {"cc-type", HTML_TYPE_CREDIT_CARD_TYPE},
-          {"country", HTML_TYPE_COUNTRY_CODE},
-          {"country-name", HTML_TYPE_COUNTRY_NAME},
-          {"email", HTML_TYPE_EMAIL},
-          {"family-name", HTML_TYPE_FAMILY_NAME},
-          {"given-name", HTML_TYPE_GIVEN_NAME},
-          {"honorific-prefix", HTML_TYPE_HONORIFIC_PREFIX},
-          {"name", HTML_TYPE_NAME},
-          {"one-time-code", HTML_TYPE_ONE_TIME_CODE},
-          {"organization", HTML_TYPE_ORGANIZATION},
-          {"postal-code", HTML_TYPE_POSTAL_CODE},
-          {"street-address", HTML_TYPE_STREET_ADDRESS},
-          {"tel-area-code", HTML_TYPE_TEL_AREA_CODE},
-          {"tel-country-code", HTML_TYPE_TEL_COUNTRY_CODE},
-          {"tel-extension", HTML_TYPE_TEL_EXTENSION},
-          {"tel", HTML_TYPE_TEL},
-          {"tel-local", HTML_TYPE_TEL_LOCAL},
-          {"tel-local-prefix", HTML_TYPE_TEL_LOCAL_PREFIX},
-          {"tel-local-suffix", HTML_TYPE_TEL_LOCAL_SUFFIX},
-          {"tel-national", HTML_TYPE_TEL_NATIONAL},
-          {"transaction-amount", HTML_TYPE_TRANSACTION_AMOUNT},
-          {"transaction-currency", HTML_TYPE_TRANSACTION_CURRENCY},
-      });
-
-  auto* it = standardized_attributes.find(value);
-  return it != standardized_attributes.end()
-             ? absl::optional<HtmlFieldType>(it->second)
-             : absl::nullopt;
-}
-
-// Maps `value`s that Autofill has proposed for the HTML autocomplete standard,
-// but which are not standardized, to their HtmlFieldType.
-absl::optional<HtmlFieldType> ParseProposedAutocompleteAttribute(
-    base::StringPiece value) {
-  static constexpr auto proposed_attributes =
-      base::MakeFixedFlatMap<base::StringPiece, HtmlFieldType>({
-          {"address", HTML_TYPE_STREET_ADDRESS},
-          {"coupon-code", HTML_TYPE_MERCHANT_PROMO_CODE},
-          {"username", HTML_TYPE_EMAIL},
-      });
-
-  auto* it = proposed_attributes.find(value);
-  return it != proposed_attributes.end()
-             ? absl::optional<HtmlFieldType>(it->second)
-             : absl::nullopt;
-}
-
-// Maps non standardized `value`s for the HTML autocomplete attribute to an
-// HtmlFieldType. This is primarily a list of "reasonable guesses".
-absl::optional<HtmlFieldType> ParseNonStandarizedAutocompleteAttribute(
-    base::StringPiece value) {
-  static constexpr auto non_standardized_attributes =
-      base::MakeFixedFlatMap<base::StringPiece, HtmlFieldType>({
-          {"company", HTML_TYPE_ORGANIZATION},
-          {"first-name", HTML_TYPE_GIVEN_NAME},
-          {"gift-code", HTML_TYPE_MERCHANT_PROMO_CODE},
-          {"locality", HTML_TYPE_ADDRESS_LEVEL2},
-          {"promo-code", HTML_TYPE_MERCHANT_PROMO_CODE},
-          {"promotional-code", HTML_TYPE_MERCHANT_PROMO_CODE},
-          {"promotion-code", HTML_TYPE_MERCHANT_PROMO_CODE},
-          {"region", HTML_TYPE_ADDRESS_LEVEL1},
-          {"tel-ext", HTML_TYPE_TEL_EXTENSION},
-          {"upi", HTML_TYPE_UPI_VPA},
-          {"upi-vpa", HTML_TYPE_UPI_VPA},
-      });
-
-  auto* it = non_standardized_attributes.find(value);
-  return it != non_standardized_attributes.end()
-             ? absl::optional<HtmlFieldType>(it->second)
-             : absl::nullopt;
-}
-
-// If the autocomplete `value` doesn't match any of Autofill's supported values,
-// Autofill should remain enabled for good intended values. This function checks
-// if there is reason to believe so, by matching `value` against patterns like
-// "address".
-// Ignoring autocomplete="off" and alike is treated separately in
-// `ParseFieldTypesFromAutocompleteAttributes()`.
-bool ShouldIgnoreAutocompleteValue(const std::string& value) {
-  // For now, only ignore unrecognizable autocomplete attributes containing
-  // "address".
-  return MatchesPattern(base::UTF8ToUTF16(value), u"address");
-}
-
-// Returns the Chrome Autofill-supported field type corresponding to a given
-// autocomplete `value`, if there is one, in the context of the given
-// `field`.
-HtmlFieldType FieldTypeFromAutocompleteAttributeValue(
-    std::string value,
-    const AutofillField& field) {
-  if (value.empty())
-    return HTML_TYPE_UNSPECIFIED;
-
-  // We are lenient and accept '_' instead of '-' as a separator. E.g.
-  // "given_name" is treated like "given-name".
-  base::ReplaceChars(value, "_", "-", &value);
-  // We accept e.g. "phone-country" instead of "tel-country".
-  if (base::StartsWith(value, "phone"))
-    base::ReplaceFirstSubstringAfterOffset(&value, 0, "phone", "tel");
-
-  absl::optional<HtmlFieldType> type =
-      ParseStandardizedAutocompleteAttribute(value);
-  if (!type.has_value()) {
-    type = ParseProposedAutocompleteAttribute(value);
-    if (!type.has_value())
-      type = ParseNonStandarizedAutocompleteAttribute(value);
-  }
-
-  if (type.has_value())
-    return RationalizeAutocompleteType(type.value(), field);
-
-  // `value` cannot be mapped to any HtmlFieldType. By classifying the field
-  // as HTML_TYPE_UNRECOGNIZED Autofill is effectively disabled. Instead, check
-  // if we have reason to ignore the value and treat the field as
-  // HTML_TYPE_UNSPECIFIED. This makes us ignore the autocomplete value.
-  return ShouldIgnoreAutocompleteValue(value) &&
-                 base::FeatureList::IsEnabled(
-                     features::kAutofillIgnoreUnmappableAutocompleteValues)
-             ? HTML_TYPE_UNSPECIFIED
-             : HTML_TYPE_UNRECOGNIZED;
-}
-
 std::ostream& operator<<(std::ostream& out,
                          const AutofillQueryResponse& response) {
   for (const auto& form : response.form_suggestions()) {
@@ -1485,105 +1281,45 @@
   has_author_specified_upi_vpa_hint_ = false;
   for (const std::unique_ptr<AutofillField>& field : fields_) {
     // To prevent potential section name collisions, add a default suffix for
-    // other fields.  Without this, 'autocomplete' attribute values
+    // other fields. Without this, 'autocomplete' attribute values
     // "section--shipping street-address" and "shipping street-address" would be
-    // parsed identically, given the section handling code below.  We do this
+    // parsed identically, given the section handling code below. We do this
     // before any validation so that fields with invalid attributes still end up
-    // in the default section.  These default section names will be overridden
+    // in the default section. These default section names will be overridden
     // by subsequent heuristic parsing steps if there are no author-specified
     // section names.
     field->section = kDefaultSection;
 
-    std::vector<std::string> tokens =
-        LowercaseAndTokenizeAttributeString(field->autocomplete_attribute);
-
-    // The autocomplete attribute is overloaded: it can specify either a field
-    // type hint or whether autocomplete should be enabled at all.  Ignore the
-    // latter type of attribute value.
-    if (tokens.empty() ||
-        (tokens.size() == 1 &&
-         (tokens[0] == "on" || tokens[0] == "off" || tokens[0] == "false"))) {
+    auto parsing_result = ParseAutocompleteAttribute(*field);
+    if (!parsing_result)
       continue;
-    }
 
-    // Any other value, even it is invalid, is considered to be a type hint.
-    // This allows a website's author to specify an attribute like
-    // autocomplete="other" on a field to disable all Autofill heuristics for
-    // the form.
+    // A parsable autocomplete value was specified. Even an invalid field_type
+    // is considered a type hint. This allows a website's author to specify an
+    // attribute like autocomplete="other" on a field to disable all Autofill
+    // heuristics for the form.
     has_author_specified_types_ = true;
+    if (parsing_result->field_type == HTML_TYPE_UNSPECIFIED)
+      continue;
 
-    // Per the spec, the tokens are parsed in reverse order. The expected
-    // pattern is:
-    // [section-*] [shipping|billing] [type_hint] field_type
-
-    // (1) The final token must be the field type. If it is not one of the known
-    // types, abort.
-    std::string field_type_token = tokens.back();
-    tokens.pop_back();
-    HtmlFieldType field_type =
-        FieldTypeFromAutocompleteAttributeValue(field_type_token, *field);
-    if (field_type == HTML_TYPE_UPI_VPA) {
+    // TODO(crbug.com/702223): Flesh out support for UPI-VPA.
+    if (parsing_result->field_type == HTML_TYPE_UPI_VPA) {
       has_author_specified_upi_vpa_hint_ = true;
-      // TODO(crbug.com/702223): Flesh out support for UPI-VPA.
-      field_type = HTML_TYPE_UNRECOGNIZED;
-    }
-    if (field_type == HTML_TYPE_UNSPECIFIED)
-      continue;
-
-    // (2) The preceding token, if any, may be a type hint.
-    if (!tokens.empty() && IsContactTypeHint(tokens.back())) {
-      // If it is, it must match the field type; otherwise, abort.
-      // Note that an invalid token invalidates the entire attribute value, even
-      // if the other tokens are valid.
-      if (!ContactTypeHintMatchesFieldType(tokens.back(), field_type))
-        continue;
-
-      // Chrome Autofill ignores these type hints.
-      tokens.pop_back();
+      parsing_result->field_type = HTML_TYPE_UNRECOGNIZED;
     }
 
-    DCHECK_EQ(kDefaultSection, field->section);
-    std::string section = field->section;
-    HtmlFieldMode mode = HTML_MODE_NONE;
+    // Compute a section name based on the specified hints and apply the result.
+    field->section =
+        parsing_result->section +
+        (parsing_result->mode != HTML_MODE_NONE
+             ? "-" +
+                   std::string(HtmlFieldModeToStringPiece(parsing_result->mode))
+             : kDefaultSection);
+    field->SetHtmlType(parsing_result->field_type, parsing_result->mode);
 
-    // (3) The preceding token, if any, may be a fixed string that is either
-    // "shipping" or "billing".  Chrome Autofill treats these as implicit
-    // section name suffixes.
-    if (!tokens.empty()) {
-      if (tokens.back() == kShippingMode)
-        mode = HTML_MODE_SHIPPING;
-      else if (tokens.back() == kBillingMode)
-        mode = HTML_MODE_BILLING;
-
-      if (mode != HTML_MODE_NONE) {
-        section = "-" + tokens.back();
-        tokens.pop_back();
-      }
-    }
-
-    // (4) The preceding token, if any, may be a named section.
-    const base::StringPiece kSectionPrefix = "section-";
-    if (!tokens.empty() && base::StartsWith(tokens.back(), kSectionPrefix,
-                                            base::CompareCase::SENSITIVE)) {
-      // Prepend this section name to the suffix set in the preceding block.
-      section = tokens.back().substr(kSectionPrefix.size()) + section;
-      tokens.pop_back();
-    }
-
-    // (5) No other tokens are allowed.  If there are any remaining, abort.
-    if (!tokens.empty())
-      continue;
-
-    if (section != kDefaultSection) {
+    if (field->section != kDefaultSection)
       has_author_specified_sections_ = true;
-      field->section = section;
-    }
-
-    // No errors encountered while parsing!
-    // Update the |field|'s type based on what was parsed from the attribute.
-    field->SetHtmlType(field_type, mode);
   }
-
   was_parsed_for_autocomplete_attributes_ = true;
 }
 
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index 33790d6..7fe0a6f 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -97,6 +97,13 @@
 const base::Feature kAutofillComplementCountryCodeOnImport{
     "AutofillComplementCountryCodeOnImport", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// If enabled, label inference considers strings entirely made up of  '(', ')'
+// and '-' as valid labels.
+// TODO(crbug.com/1311937): Cleanup when launched.
+const base::Feature kAutofillConsiderPhoneNumberSeparatorsValidLabels{
+    "AutofillConsiderPhoneNumberSeparatorsValidLabels",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
 // If enabled, local heuristics fall back to the fields placeholder attribute.
 const base::Feature kAutofillConsiderPlaceholderForParsing{
     "AutofillConsiderPlaceholderForParsing", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -267,7 +274,7 @@
 // TODO(crbug.com/1098943): Remove once launched.
 const base::Feature kAutofillEnableSupportForMoreStructureInAddresses{
     "AutofillEnableSupportForMoreStructureInAddresses",
-    base::FEATURE_ENABLED_BY_DEFAULT};
+    base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Controls if Autofill supports merging subset names.
 // TODO(crbug.com/1098943): Remove once launched.
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h
index 6e05f297..327f003 100644
--- a/components/autofill/core/common/autofill_features.h
+++ b/components/autofill/core/common/autofill_features.h
@@ -49,6 +49,8 @@
 COMPONENT_EXPORT(AUTOFILL)
 extern const base::Feature kAutofillComplementCountryCodeOnImport;
 COMPONENT_EXPORT(AUTOFILL)
+extern const base::Feature kAutofillConsiderPhoneNumberSeparatorsValidLabels;
+COMPONENT_EXPORT(AUTOFILL)
 extern const base::Feature kAutofillConsiderPlaceholderForParsing;
 COMPONENT_EXPORT(AUTOFILL)
 extern const base::Feature kAutofillConsiderVariationCountryCodeForPhoneNumbers;
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java
index 42e25dbe..aec64ba 100644
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java
@@ -13,9 +13,7 @@
 import org.chromium.components.image_fetcher.ImageFetcher;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
 
-/**
- * Coordinator responsible for showing an InfoBox.
- */
+/** Coordinator responsible for showing an InfoBox. */
 public class AssistantInfoBoxCoordinator {
     private final View mView;
     private AssistantInfoBoxViewBinder mViewBinder;
@@ -31,31 +29,22 @@
 
         // InfoBox view is initially hidden.
         setVisible(false);
-
         // Observe InfoBox in model to hide or show this coordinator view.
         model.addObserver((source, propertyKey) -> {
             if (AssistantInfoBoxModel.INFO_BOX == propertyKey) {
                 AssistantInfoBox infoBox = model.get(AssistantInfoBoxModel.INFO_BOX);
-                if (infoBox != null) {
-                    setVisible(true);
-                } else {
-                    setVisible(false);
-                }
+                setVisible(!isEmpty(infoBox));
             }
         });
     }
 
-    /**
-     * Explicitly clean up.
-     */
+    /** Explicitly clean up. */
     public void destroy() {
         mViewBinder.destroy();
         mViewBinder = null;
     }
 
-    /**
-     * Return the view associated to the info box.
-     */
+    /** Return the view associated to the info box. */
     public View getView() {
         return mView;
     }
@@ -70,4 +59,9 @@
             mView.setVisibility(visibility);
         }
     }
+
+    private boolean isEmpty(AssistantInfoBox infoBox) {
+        return infoBox == null
+                || (infoBox.getImagePath().isEmpty() && infoBox.getExplanation().isEmpty());
+    }
 }
diff --git a/components/autofill_assistant/browser/BUILD.gn b/components/autofill_assistant/browser/BUILD.gn
index 88b373d..79b049a 100644
--- a/components/autofill_assistant/browser/BUILD.gn
+++ b/components/autofill_assistant/browser/BUILD.gn
@@ -432,6 +432,8 @@
     "mock_personal_data_manager.h",
     "mock_ui_controller_observer.cc",
     "mock_ui_controller_observer.h",
+    "mock_user_model.cc",
+    "mock_user_model.h",
     "mock_user_model_observer.cc",
     "mock_user_model_observer.h",
     "mock_website_login_manager.cc",
diff --git a/components/autofill_assistant/browser/actions/action_delegate.h b/components/autofill_assistant/browser/actions/action_delegate.h
index de599fd..c7c9b21 100644
--- a/components/autofill_assistant/browser/actions/action_delegate.h
+++ b/components/autofill_assistant/browser/actions/action_delegate.h
@@ -419,6 +419,9 @@
   // Gets the user data.
   virtual const UserData* GetUserData() const = 0;
 
+  // Gets the user data (mutable).
+  virtual UserData* GetMutableUserData() const = 0;
+
   // Access to the user model.
   virtual UserModel* GetUserModel() const = 0;
 
@@ -500,6 +503,9 @@
   // Returns the Autofill Assistant intent for the current flow.
   virtual absl::optional<std::string> GetIntent() const = 0;
 
+  // Returns the client's locale.
+  virtual const std::string GetLocale() const = 0;
+
   virtual base::WeakPtr<ActionDelegate> GetWeakPtr() const = 0;
 
  protected:
diff --git a/components/autofill_assistant/browser/actions/external_action.cc b/components/autofill_assistant/browser/actions/external_action.cc
index ec25401d..a4d621e 100644
--- a/components/autofill_assistant/browser/actions/external_action.cc
+++ b/components/autofill_assistant/browser/actions/external_action.cc
@@ -5,10 +5,30 @@
 #include "components/autofill_assistant/browser/actions/external_action.h"
 
 #include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill_assistant/browser/actions/action_delegate.h"
 #include "components/autofill_assistant/browser/client_status.h"
+#include "components/autofill_assistant/browser/user_model.h"
 
 namespace autofill_assistant {
+namespace {
+
+void SetInfoOnAutofillDataModel(
+    const google::protobuf::Map<google::protobuf::int32, std::string>&
+        server_field_type_int_to_value,
+    const std::string locale,
+    autofill::AutofillDataModel* model) {
+  for (const auto& [server_field_type_int, value] :
+       server_field_type_int_to_value) {
+    model->SetInfo(
+        static_cast<autofill::ServerFieldType>(server_field_type_int),
+        base::UTF8ToUTF16(value), locale);
+  }
+}
+
+}  // namespace
 
 ExternalAction::ExternalAction(ActionDelegate* delegate,
                                const ActionProto& proto)
@@ -162,7 +182,7 @@
   // external response and report the error, as we might not be in a state to
   // continue with the script.
   if (status.ok() && external_action_end_requested_) {
-    EndWithExternalResult();
+    ProcessExternalResult();
     return;
   }
   EndAction(status);
@@ -182,10 +202,17 @@
     return;
   }
 
-  EndWithExternalResult();
+  ProcessExternalResult();
 }
 
-void ExternalAction::EndWithExternalResult() {
+void ExternalAction::ProcessExternalResult() {
+  if (!external_action_result_.selected_profiles().empty()) {
+    SetSelectedProfiles(external_action_result_.selected_profiles());
+  }
+  if (external_action_result_.has_selected_credit_card()) {
+    SetSelectedCreditCard(external_action_result_.selected_credit_card());
+  }
+
   *processed_action_proto_->mutable_external_action_result()
        ->mutable_result_info() = external_action_result_.result_info();
   EndAction(external_action_result_.success()
@@ -198,4 +225,52 @@
   std::move(callback_).Run(std::move(processed_action_proto_));
 }
 
+void ExternalAction::SetSelectedProfiles(
+    const google::protobuf::Map<std::string,
+                                autofill_assistant::external::ProfileProto>&
+        profiles_proto) {
+  for (const auto& [profile_name, profile_proto] : profiles_proto) {
+    auto autofill_profile = std::make_unique<autofill::AutofillProfile>();
+
+    SetInfoOnAutofillDataModel(profile_proto.values(), delegate_->GetLocale(),
+                               autofill_profile.get());
+
+    autofill_profile->FinalizeAfterImport();
+
+    delegate_->GetUserModel()->SetSelectedAutofillProfile(
+        profile_name, std::move(autofill_profile),
+        delegate_->GetMutableUserData());
+  }
+}
+
+void ExternalAction::SetSelectedCreditCard(
+    const autofill_assistant::external::CreditCardProto& credit_card_proto) {
+  auto credit_card = std::make_unique<autofill::CreditCard>();
+
+  SetInfoOnAutofillDataModel(credit_card_proto.values(), delegate_->GetLocale(),
+                             credit_card.get());
+
+  if (credit_card_proto.has_record_type()) {
+    credit_card->set_record_type(static_cast<autofill::CreditCard::RecordType>(
+        credit_card_proto.record_type()));
+  }
+
+  if (credit_card_proto.has_instrument_id()) {
+    credit_card->set_instrument_id(credit_card_proto.instrument_id());
+  }
+
+  if (!credit_card_proto.network().empty() &&
+      credit_card->record_type() ==
+          autofill::CreditCard::RecordType::MASKED_SERVER_CARD) {
+    credit_card->SetNetworkForMaskedCard(credit_card_proto.network());
+  }
+
+  if (!credit_card_proto.server_id().empty()) {
+    credit_card->set_server_id(credit_card_proto.server_id());
+  }
+
+  delegate_->GetUserModel()->SetSelectedCreditCard(
+      std::move(credit_card), delegate_->GetMutableUserData());
+}
+
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/external_action.h b/components/autofill_assistant/browser/actions/external_action.h
index 08ad8c8..99bca53 100644
--- a/components/autofill_assistant/browser/actions/external_action.h
+++ b/components/autofill_assistant/browser/actions/external_action.h
@@ -51,8 +51,14 @@
       base::OnceCallback<void(const ClientStatus&)> wait_for_dom_callback);
   void OnDoneWaitForDom(const ClientStatus& status);
   void OnExternalActionFinished(const external::Result& success);
-  void EndWithExternalResult();
+  void ProcessExternalResult();
   void EndAction(const ClientStatus& status);
+  void SetSelectedProfiles(
+      const google::protobuf::Map<std::string,
+                                  autofill_assistant::external::ProfileProto>&
+          profiles_proto);
+  void SetSelectedCreditCard(
+      const autofill_assistant::external::CreditCardProto& credit_card_proto);
 
   ProcessActionCallback callback_;
 
diff --git a/components/autofill_assistant/browser/actions/external_action_unittest.cc b/components/autofill_assistant/browser/actions/external_action_unittest.cc
index 90dbea5..c1ca02b 100644
--- a/components/autofill_assistant/browser/actions/external_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/external_action_unittest.cc
@@ -4,13 +4,21 @@
 
 #include "components/autofill_assistant/browser/actions/external_action.h"
 
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/test/gmock_callback_support.h"
 #include "base/test/mock_callback.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_simple_task_runner.h"
+#include "base/time/time.h"
+#include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/test_autofill_clock.h"
+#include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
 #include "components/autofill_assistant/browser/actions/wait_for_dom_test_base.h"
 #include "components/autofill_assistant/browser/external_action_extension_test.pb.h"
+#include "components/autofill_assistant/browser/mock_user_model.h"
 #include "components/autofill_assistant/browser/service.pb.h"
 #include "components/autofill_assistant/browser/web/mock_web_controller.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -18,6 +26,7 @@
 namespace autofill_assistant {
 namespace {
 
+using ::autofill::ServerFieldType;
 using ::base::test::RunOnceCallback;
 using ::testing::_;
 using ::testing::ElementsAre;
@@ -25,13 +34,43 @@
 using ::testing::Pointee;
 using ::testing::Property;
 using ::testing::Return;
+using ::testing::SaveArg;
 using ::testing::UnorderedElementsAre;
 using ::testing::WithArgs;
 
+namespace {
+
+constexpr char kCreditCardNumber[] = "4111111111111111";
+constexpr char kProfileName[] = "SHIPPING";
+constexpr char kFirstName[] = "John";
+constexpr char kLastName[] = "Doe";
+constexpr char kEmail[] = "jd@example.com";
+constexpr char kAddressLine1[] = "Erika-Mann-Str. 33";
+constexpr char kAddressCity[] = "Munich";
+constexpr char kAddressZip[] = "80636";
+constexpr int64_t kInstrumentId = 123;
+constexpr char kServerId[] = "server id";
+constexpr autofill::CreditCard::RecordType kRecordType =
+    autofill::CreditCard::RecordType::LOCAL_CARD;
+}  // namespace
+
 class ExternalActionTest : public WaitForDomTestBase {
  public:
   ExternalActionTest() = default;
 
+  void SetUp() override {
+    mock_user_model_ = std::make_unique<MockUserModel>();
+    ON_CALL(mock_action_delegate_, GetUserModel)
+        .WillByDefault(Return(GetMockUserModel()));
+    user_data_ = std::make_unique<UserData>();
+    ON_CALL(mock_action_delegate_, GetMutableUserData)
+        .WillByDefault(Return(user_data_.get()));
+    ON_CALL(mock_action_delegate_, GetLocale).WillByDefault(Return(locale_));
+    base::Time fake_now;
+    if (base::Time::FromUTCString("2022-07-01 00:00:00", &fake_now))
+      test_clock_.SetNow(fake_now);
+  }
+
  protected:
   void Run() {
     ON_CALL(mock_action_delegate_, SupportsExternalActions)
@@ -44,9 +83,17 @@
     action_->ProcessAction(callback_.Get());
   }
 
+  MockUserModel* GetMockUserModel() { return mock_user_model_.get(); }
+
   base::MockCallback<Action::ProcessActionCallback> callback_;
   ExternalActionProto proto_;
   std::unique_ptr<ExternalAction> action_;
+
+ private:
+  const std::string locale_ = "en-US";
+  std::unique_ptr<UserData> user_data_;
+  std::unique_ptr<MockUserModel> mock_user_model_;
+  autofill::TestAutofillClock test_clock_;
 };
 
 external::Result MakeResult(bool success) {
@@ -179,6 +226,113 @@
   Run();
 }
 
+TEST_F(ExternalActionTest, ExternalActionWithSelectedProfileAndCreditCard) {
+  proto_.mutable_info();
+  proto_.set_allow_interrupt(false);
+
+  base::Time credit_card_exp_date =
+      autofill::AutofillClock::Now() + base::Days(31);
+  base::Time::Exploded credit_card_exp_date_exploded;
+  credit_card_exp_date.UTCExplode(&credit_card_exp_date_exploded);
+
+  // Result proto
+  external::Result result = MakeResult(/* success= */ true);
+
+  // Credit card proto
+  auto credit_card_proto = std::make_unique<external::CreditCardProto>();
+  (*credit_card_proto->mutable_values())[ServerFieldType::CREDIT_CARD_NUMBER] =
+      kCreditCardNumber;
+  (*credit_card_proto
+        ->mutable_values())[ServerFieldType::CREDIT_CARD_EXP_MONTH] =
+      base::NumberToString(credit_card_exp_date_exploded.month);
+  (*credit_card_proto
+        ->mutable_values())[ServerFieldType::CREDIT_CARD_EXP_4_DIGIT_YEAR] =
+      base::NumberToString(credit_card_exp_date_exploded.year);
+  credit_card_proto->set_record_type(kRecordType);
+  credit_card_proto->set_instrument_id(kInstrumentId);
+  credit_card_proto->set_server_id(kServerId);
+  result.set_allocated_selected_credit_card(credit_card_proto.get());
+  credit_card_proto.release();
+
+  // Profile proto
+  auto profile_proto = std::make_unique<external::ProfileProto>();
+  (*profile_proto->mutable_values())[ServerFieldType::NAME_FIRST] = kFirstName;
+  (*profile_proto->mutable_values())[ServerFieldType::NAME_LAST] = kLastName;
+  (*profile_proto->mutable_values())[ServerFieldType::EMAIL_ADDRESS] = kEmail;
+  (*profile_proto->mutable_values())[ServerFieldType::ADDRESS_HOME_LINE1] =
+      kAddressLine1;
+  (*profile_proto->mutable_values())[ServerFieldType::ADDRESS_HOME_CITY] =
+      kAddressCity;
+  (*profile_proto->mutable_values())[ServerFieldType::ADDRESS_HOME_ZIP] =
+      kAddressZip;
+  (result.mutable_selected_profiles())->insert({kProfileName, *profile_proto});
+
+  EXPECT_CALL(mock_action_delegate_, RequestExternalAction)
+      .WillOnce(
+          [&result](const ExternalActionProto& external_action,
+                    base::OnceCallback<void(
+                        ExternalActionDelegate::DomUpdateCallback)>
+                        start_dom_checks_callback,
+                    base::OnceCallback<void(const external::Result& result)>
+                        end_action_callback) {
+            std::move(start_dom_checks_callback).Run(base::DoNothing());
+            std::move(end_action_callback).Run(result);
+          });
+  EXPECT_CALL(mock_action_delegate_, WaitForDom).Times(0);
+  std::unique_ptr<autofill::CreditCard> credit_card;
+  EXPECT_CALL(*GetMockUserModel(),
+              SetSelectedCreditCard(::testing::NotNull(), _))
+      .WillOnce([&credit_card](std::unique_ptr<autofill::CreditCard> cc, auto) {
+        credit_card = std::move(cc);
+      });
+  std::unique_ptr<autofill::AutofillProfile> autofill_profile;
+  EXPECT_CALL(*GetMockUserModel(),
+              SetSelectedAutofillProfile(kProfileName, ::testing::NotNull(), _))
+      .WillOnce([&autofill_profile](
+                    auto, std::unique_ptr<autofill::AutofillProfile> ap, auto) {
+        autofill_profile = std::move(ap);
+      });
+  EXPECT_CALL(
+      callback_,
+      Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+
+  Run();
+
+  // Verify credit card data
+  EXPECT_EQ(credit_card->expiration_month(),
+            credit_card_exp_date_exploded.month);
+  EXPECT_EQ(credit_card->expiration_year(), credit_card_exp_date_exploded.year);
+  EXPECT_EQ(base::UTF16ToUTF8(credit_card->number()), kCreditCardNumber);
+  EXPECT_EQ(credit_card->record_type(), kRecordType);
+  EXPECT_EQ(credit_card->instrument_id(), kInstrumentId);
+  EXPECT_EQ(credit_card->server_id(), kServerId);
+
+  // Verify profile data
+  EXPECT_EQ(
+      base::UTF16ToUTF8(autofill_profile->GetInfo(
+          ServerFieldType::NAME_FIRST, mock_action_delegate_.GetLocale())),
+      kFirstName);
+  EXPECT_EQ(base::UTF16ToUTF8(autofill_profile->GetInfo(
+                ServerFieldType::NAME_LAST, mock_action_delegate_.GetLocale())),
+            kLastName);
+  EXPECT_EQ(
+      base::UTF16ToUTF8(autofill_profile->GetInfo(
+          ServerFieldType::EMAIL_ADDRESS, mock_action_delegate_.GetLocale())),
+      kEmail);
+  EXPECT_EQ(base::UTF16ToUTF8(
+                autofill_profile->GetInfo(ServerFieldType::ADDRESS_HOME_LINE1,
+                                          mock_action_delegate_.GetLocale())),
+            kAddressLine1);
+  EXPECT_EQ(base::UTF16ToUTF8(
+                autofill_profile->GetInfo(ServerFieldType::ADDRESS_HOME_CITY,
+                                          mock_action_delegate_.GetLocale())),
+            kAddressCity);
+  EXPECT_EQ(base::UTF16ToUTF8(
+                autofill_profile->GetInfo(ServerFieldType::ADDRESS_HOME_ZIP,
+                                          mock_action_delegate_.GetLocale())),
+            kAddressZip);
+}
+
 TEST_F(ExternalActionTest, DoesNotStartWaitForDomIfDomChecksAreNotRequested) {
   proto_.mutable_info();
   proto_.set_allow_interrupt(true);
diff --git a/components/autofill_assistant/browser/actions/mock_action_delegate.h b/components/autofill_assistant/browser/actions/mock_action_delegate.h
index 6bce150..be48880 100644
--- a/components/autofill_assistant/browser/actions/mock_action_delegate.h
+++ b/components/autofill_assistant/browser/actions/mock_action_delegate.h
@@ -130,6 +130,7 @@
   MOCK_METHOD1(Shutdown, void(bool show_feedback_chip));
   MOCK_METHOD0(Close, void());
   MOCK_METHOD0(Restart, void());
+  MOCK_CONST_METHOD0(GetMutableUserData, UserData*());
   MOCK_CONST_METHOD0(GetUserData, UserData*());
   MOCK_CONST_METHOD0(GetPersonalDataManager, autofill::PersonalDataManager*());
   MOCK_CONST_METHOD0(GetWebsiteLoginManager, WebsiteLoginManager*());
@@ -231,6 +232,7 @@
   MOCK_METHOD1(MaybeSetPreviousAction,
                void(const ProcessedActionProto& processed_action));
   MOCK_CONST_METHOD0(GetIntent, absl::optional<std::string>());
+  MOCK_CONST_METHOD0(GetLocale, const std::string());
 
   base::WeakPtr<ActionDelegate> GetWeakPtr() const override {
     return weak_ptr_factory_.GetWeakPtr();
@@ -244,6 +246,7 @@
   FakeElementStore fake_element_store_;
   ClientSettings client_settings_;
   ProcessedActionStatusDetailsProto log_info_;
+  UserData user_data_;
 
   base::WeakPtrFactory<MockActionDelegate> weak_ptr_factory_{this};
 };
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc
index e568c7d3..e0405c61 100644
--- a/components/autofill_assistant/browser/controller.cc
+++ b/components/autofill_assistant/browser/controller.cc
@@ -148,6 +148,10 @@
   return web_contents();
 }
 
+const std::string Controller::GetLocale() {
+  return client_->GetLocale();
+}
+
 void Controller::SetJsFlowLibrary(const std::string& js_flow_library) {
   if (js_flow_library.empty()) {
     return;
diff --git a/components/autofill_assistant/browser/controller.h b/components/autofill_assistant/browser/controller.h
index ad17c202..0379c34 100644
--- a/components/autofill_assistant/browser/controller.h
+++ b/components/autofill_assistant/browser/controller.h
@@ -124,6 +124,7 @@
   password_manager::PasswordChangeSuccessTracker*
   GetPasswordChangeSuccessTracker() override;
   content::WebContents* GetWebContents() override;
+  const std::string GetLocale() override;
   void SetJsFlowLibrary(const std::string& js_flow_library) override;
   JsFlowDevtoolsWrapper* GetJsFlowDevtoolsWrapper() override;
   std::string GetEmailAddressForAccessTokenAccount() override;
@@ -438,6 +439,9 @@
   // DOM nodes. May be nullptr.
   const raw_ptr<AnnotateDomModelService> annotate_dom_model_service_;
 
+  // Holds the client's locale.
+  std::string locale_;
+
   base::WeakPtrFactory<Controller> weak_ptr_factory_{this};
 };
 
diff --git a/components/autofill_assistant/browser/fake_script_executor_delegate.cc b/components/autofill_assistant/browser/fake_script_executor_delegate.cc
index cc48be0..602f708b 100644
--- a/components/autofill_assistant/browser/fake_script_executor_delegate.cc
+++ b/components/autofill_assistant/browser/fake_script_executor_delegate.cc
@@ -61,6 +61,10 @@
   return web_contents_;
 }
 
+const std::string FakeScriptExecutorDelegate::GetLocale() {
+  return "en-US";
+}
+
 void FakeScriptExecutorDelegate::SetJsFlowLibrary(
     const std::string& js_flow_library) {
   GetJsFlowDevtoolsWrapper()->SetJsFlowLibrary(js_flow_library);
@@ -162,6 +166,10 @@
   return user_model_;
 }
 
+UserData* FakeScriptExecutorDelegate::GetUserData() {
+  return user_data_;
+}
+
 void FakeScriptExecutorDelegate::SetOverlayBehavior(
     ConfigureUiStateProto::OverlayBehavior overaly_behavior) {}
 
diff --git a/components/autofill_assistant/browser/fake_script_executor_delegate.h b/components/autofill_assistant/browser/fake_script_executor_delegate.h
index 2d70a86..32360e9f 100644
--- a/components/autofill_assistant/browser/fake_script_executor_delegate.h
+++ b/components/autofill_assistant/browser/fake_script_executor_delegate.h
@@ -45,6 +45,7 @@
   password_manager::PasswordChangeSuccessTracker*
   GetPasswordChangeSuccessTracker() override;
   content::WebContents* GetWebContents() override;
+  const std::string GetLocale() override;
   void SetJsFlowLibrary(const std::string& js_flow_library) override;
   JsFlowDevtoolsWrapper* GetJsFlowDevtoolsWrapper() override;
   std::string GetEmailAddressForAccessTokenAccount() override;
@@ -58,6 +59,7 @@
   ViewportMode GetViewportMode() override;
   void SetClientSettings(const ClientSettingsProto& client_settings) override;
   UserModel* GetUserModel() override;
+  UserData* GetUserData() override;
   void ExpectNavigation() override;
   bool HasNavigationError() override;
   bool IsNavigatingToNewDocument() override;
@@ -139,6 +141,7 @@
   ViewportMode viewport_mode_ = ViewportMode::NO_RESIZE;
   std::vector<std::string> browse_domains_;
   raw_ptr<UserModel> user_model_ = nullptr;
+  raw_ptr<UserData> user_data_ = nullptr;
   ProcessedActionStatusDetailsProto log_info_;
   bool must_use_backend_data_ = false;
 
diff --git a/components/autofill_assistant/browser/mock_script_executor_delegate.h b/components/autofill_assistant/browser/mock_script_executor_delegate.h
index 46c75c3a..a9653de 100644
--- a/components/autofill_assistant/browser/mock_script_executor_delegate.h
+++ b/components/autofill_assistant/browser/mock_script_executor_delegate.h
@@ -49,6 +49,7 @@
               (),
               (override));
   MOCK_METHOD(content::WebContents*, GetWebContents, (), (override));
+  MOCK_METHOD(const std::string, GetLocale, (), (override));
   MOCK_METHOD(void,
               SetJsFlowLibrary,
               (const std::string& js_flow_library),
@@ -82,6 +83,7 @@
               (const ClientSettingsProto& client_settings),
               (override));
   MOCK_METHOD(UserModel*, GetUserModel, (), (override));
+  MOCK_METHOD(UserData*, GetUserData, (), (override));
   MOCK_METHOD(void, ExpectNavigation, (), (override));
   MOCK_METHOD(bool, IsNavigatingToNewDocument, (), (override));
   MOCK_METHOD(bool, HasNavigationError, (), (override));
diff --git a/components/autofill_assistant/browser/mock_user_model.cc b/components/autofill_assistant/browser/mock_user_model.cc
new file mode 100644
index 0000000..af21c10
--- /dev/null
+++ b/components/autofill_assistant/browser/mock_user_model.cc
@@ -0,0 +1,14 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/mock_user_model.h"
+#include "iostream"
+
+namespace autofill_assistant {
+
+MockUserModel::MockUserModel() = default;
+
+MockUserModel::~MockUserModel() = default;
+
+}  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/mock_user_model.h b/components/autofill_assistant/browser/mock_user_model.h
new file mode 100644
index 0000000..4c3cfa0
--- /dev/null
+++ b/components/autofill_assistant/browser/mock_user_model.h
@@ -0,0 +1,36 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_USER_MODEL_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_USER_MODEL_H_
+
+#include "components/autofill_assistant/browser/user_model.h"
+
+#include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_model/credit_card.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace autofill_assistant {
+
+class MockUserModel : public UserModel {
+ public:
+  MockUserModel();
+  ~MockUserModel() override;
+
+  MOCK_METHOD(void,
+              SetSelectedCreditCard,
+              (std::unique_ptr<autofill::CreditCard> card, UserData* user_data),
+              (override));
+
+  MOCK_METHOD(void,
+              SetSelectedAutofillProfile,
+              (const std::string& profile_name,
+               std::unique_ptr<autofill::AutofillProfile> profile,
+               UserData* user_data),
+              (override));
+};
+
+}  // namespace autofill_assistant
+
+#endif  // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_USER_MODEL_H_
diff --git a/components/autofill_assistant/browser/public/external_action.proto b/components/autofill_assistant/browser/public/external_action.proto
index 571261c..bddca4c2 100644
--- a/components/autofill_assistant/browser/public/external_action.proto
+++ b/components/autofill_assistant/browser/public/external_action.proto
@@ -23,7 +23,30 @@
   extensions 100 to max;
 }
 
-// The result of the execution of |Action|
+// Proto representation of autofill::AutofillProfile.
+message ProfileProto {
+  // The values, where the key is one of autofill::ServerFieldType.
+  map<int32, string> values = 1;
+}
+
+// Proto representation of autofill:CreditCard.
+message CreditCardProto {
+  // The values for the card, where the key is one of autofill::ServerFieldType.
+  map<int32, string> values = 1;
+  // Remaining autofill::CreditCard fields not in autofill::ServerFieldType :
+  // Specifies e.g. if a card is local, one of autofill::CreditCard::RecordType.
+  optional int64 record_type = 2;
+  // The payments instrument id used to identify and unmask the credit card.
+  optional int64 instrument_id = 3;
+  // The network of the card.
+  optional string network = 4;
+  // Server ID of the card.
+  // TODO(crbug.com/1121806): Remove after autofill::CreditCard::server_id_ was
+  // removed.
+  optional string server_id = 5 [deprecated = true];
+}
+
+// The result of the execution of |Action|.
 message Result {
   // Integrator-specific information. This will be forwarded to the backend
   // without modification.
@@ -31,6 +54,16 @@
 
   // Whether the action was successful.
   optional bool success = 2;
+
+  // Profiles selected by the user, where the key is the client address
+  // identifier - sometimes referred to as profile name. The key is a
+  // compile-time constant; e.g. "SHIPPING" with the mapped value being the
+  // shipping address selected by the user. It needs to be in sync with Autofill
+  // Assistant's server version.
+  map<string, ProfileProto> selected_profiles = 3;
+
+  // Credit card selected by the user.
+  optional CreditCardProto selected_credit_card = 4;
 }
 
 // Extended by the integrator.
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc
index 7667671..eea924c 100644
--- a/components/autofill_assistant/browser/script_executor.cc
+++ b/components/autofill_assistant/browser/script_executor.cc
@@ -133,6 +133,10 @@
   return user_data_;
 }
 
+UserData* ScriptExecutor::GetMutableUserData() const {
+  return delegate_->GetUserData();
+}
+
 UserModel* ScriptExecutor::GetUserModel() const {
   return delegate_->GetUserModel();
 }
@@ -1181,4 +1185,8 @@
       {delegate_->GetTriggerContext(), additional_context_.get()});
 }
 
+const std::string ScriptExecutor::GetLocale() const {
+  return delegate_->GetLocale();
+}
+
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/script_executor.h b/components/autofill_assistant/browser/script_executor.h
index 0e1087b..55d57ec 100644
--- a/components/autofill_assistant/browser/script_executor.h
+++ b/components/autofill_assistant/browser/script_executor.h
@@ -114,6 +114,7 @@
   void Run(const UserData* user_data, RunScriptCallback callback);
 
   const UserData* GetUserData() const override;
+  UserData* GetMutableUserData() const override;
   UserModel* GetUserModel() const override;
 
   // Override ScriptExecutorDelegate::NavigationListener
@@ -278,6 +279,7 @@
   void MaybeSetPreviousAction(
       const ProcessedActionProto& processed_action) override;
   absl::optional<std::string> GetIntent() const override;
+  const std::string GetLocale() const override;
 
  private:
   // TODO(b/220079189): remove this friend declaration.
diff --git a/components/autofill_assistant/browser/script_executor_delegate.h b/components/autofill_assistant/browser/script_executor_delegate.h
index 787cb4a..577c3fbd 100644
--- a/components/autofill_assistant/browser/script_executor_delegate.h
+++ b/components/autofill_assistant/browser/script_executor_delegate.h
@@ -64,6 +64,7 @@
   virtual password_manager::PasswordChangeSuccessTracker*
   GetPasswordChangeSuccessTracker() = 0;
   virtual content::WebContents* GetWebContents() = 0;
+  virtual const std::string GetLocale() = 0;
 
   virtual void SetJsFlowLibrary(const std::string& js_flow_library) = 0;
   virtual JsFlowDevtoolsWrapper* GetJsFlowDevtoolsWrapper() = 0;
@@ -92,6 +93,7 @@
   virtual void SetClientSettings(
       const ClientSettingsProto& client_settings) = 0;
   virtual UserModel* GetUserModel() = 0;
+  virtual UserData* GetUserData() = 0;
 
   // The next navigation is expected and will not cause an error.
   virtual void ExpectNavigation() = 0;
diff --git a/components/autofill_assistant/browser/user_model.h b/components/autofill_assistant/browser/user_model.h
index e1ed68b..df4d0500 100644
--- a/components/autofill_assistant/browser/user_model.h
+++ b/components/autofill_assistant/browser/user_model.h
@@ -48,7 +48,7 @@
   UserModel(const UserModel&) = delete;
   UserModel& operator=(const UserModel&) = delete;
 
-  ~UserModel();
+  virtual ~UserModel();
 
   base::WeakPtr<UserModel> GetWeakPtr();
 
@@ -94,8 +94,8 @@
   // Sets the selected credit card. A nullptr |card| will clear the selected
   // card. This also sets it to |user_data|.
   // TODO(b/187286050) complete the migration to UserModel and remove UserData.
-  void SetSelectedCreditCard(std::unique_ptr<autofill::CreditCard> card,
-                             UserData* user_data);
+  virtual void SetSelectedCreditCard(std::unique_ptr<autofill::CreditCard> card,
+                                     UserData* user_data);
 
   // Sets the selected login choice. A nullptr |login_choice| will clear the
   // selected login choice. This sets it to |user_data|.
@@ -119,7 +119,7 @@
   // Sets the selected autofill profile for |profile_name|. A nullptr |profile|
   // will clear the entry. The profile is also set in |user_data|.
   // TODO(b/187286050) complete the migration to UserModel and remove UserData.
-  void SetSelectedAutofillProfile(
+  virtual void SetSelectedAutofillProfile(
       const std::string& profile_name,
       std::unique_ptr<autofill::AutofillProfile> profile,
       UserData* user_data);
diff --git a/components/components_strings.grd b/components/components_strings.grd
index acaf495..d62bb020 100644
--- a/components/components_strings.grd
+++ b/components/components_strings.grd
@@ -527,6 +527,9 @@
       <message name="IDS_PATCH_SERVICE_DISPLAY_NAME" desc="The display name (in the system task manager, etc) of the service process used for patching file operations.">
         Patch Service
       </message>
+      <message name="IDS_PASSWORD_MANAGER_CSV_PASSWORD_PARSER_SERVICE_DISPLAY_NAME" desc="The display name (in the system task manager, etc) of the service process used for parsing a csv passwords file.">
+        CSV Password Parser Service
+      </message>
       <message name="IDS_UNZIP_SERVICE_DISPLAY_NAME" desc="The display name (in the system task manager, etc) of the service process used for unzipping files.">
         Unzip Service
       </message>
diff --git a/components/components_strings_grd/IDS_PASSWORD_MANAGER_CSV_PASSWORD_PARSER_SERVICE_DISPLAY_NAME.png.sha1 b/components/components_strings_grd/IDS_PASSWORD_MANAGER_CSV_PASSWORD_PARSER_SERVICE_DISPLAY_NAME.png.sha1
new file mode 100644
index 0000000..ffc4715b
--- /dev/null
+++ b/components/components_strings_grd/IDS_PASSWORD_MANAGER_CSV_PASSWORD_PARSER_SERVICE_DISPLAY_NAME.png.sha1
@@ -0,0 +1 @@
+6d04d52cd3940dccf5ecb3c39c6fee87d330e10b
\ No newline at end of file
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamTest.java
index c5c843b4..d585d4e 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamTest.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamTest.java
@@ -203,8 +203,10 @@
     private void runBuilderCheckJavaImpl() {
         try {
             TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCallback();
-            mTestRule.createJavaEngineBuilder().build().newBidirectionalStreamBuilder(
-                    Http2TestServer.getServerUrl(), callback, callback.getExecutor());
+            CronetTestRule.createJavaEngineBuilder(CronetTestRule.getContext())
+                    .build()
+                    .newBidirectionalStreamBuilder(
+                            Http2TestServer.getServerUrl(), callback, callback.getExecutor());
             fail("JavaCronetEngine doesn't support BidirectionalStream."
                     + " Expected UnsupportedOperationException");
         } catch (UnsupportedOperationException e) {
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java
index 7121d78d..a66fcec 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java
@@ -4,7 +4,10 @@
 
 package org.chromium.net;
 
+import static org.junit.Assume.assumeTrue;
+
 import android.content.Context;
+import android.os.Build;
 import android.os.StrictMode;
 import android.support.test.InstrumentationRegistry;
 
@@ -18,6 +21,7 @@
 import org.chromium.base.PathUtils;
 import org.chromium.net.impl.JavaCronetEngine;
 import org.chromium.net.impl.JavaCronetProvider;
+import org.chromium.net.impl.NativeCronetProvider;
 import org.chromium.net.impl.UserAgent;
 
 import java.io.File;
@@ -31,21 +35,10 @@
 
 /**
  * Custom TestRule for Cronet instrumentation tests.
- *
- * TODO(yolandyan): refactor this to three TestRules, one for setUp and tearDown,
- * one for tests under org.chromium.net.urlconnection, one for test under
- * org.chromium.net
  */
 public class CronetTestRule implements TestRule {
     private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "cronet_test";
 
-    private CronetTestFramework mCronetTestFramework;
-
-    // {@code true} when test is being run against system HttpURLConnection implementation.
-    private boolean mTestingSystemHttpURLConnection;
-    private boolean mTestingJavaImpl;
-    private StrictMode.VmPolicy mOldVmPolicy;
-
     /**
      * Name of the file that contains the test server certificate in PEM format.
      */
@@ -56,18 +49,67 @@
      */
     public static final String SERVER_KEY_PKCS8_PEM = "quic-leaf-cert.key.pkcs8.pem";
 
-    private static final String TAG = CronetTestRule.class.getSimpleName();
+    private static final String TAG = "CronetTestRule";
+
+    private CronetTestFramework mCronetTestFramework;
+
+    private boolean mTestingSystemHttpURLConnection;
+    private boolean mTestingJavaImpl;
+    private StrictMode.VmPolicy mOldVmPolicy;
 
     /**
      * Creates and holds pointer to CronetEngine.
      */
     public static class CronetTestFramework {
         public ExperimentalCronetEngine mCronetEngine;
+        public ExperimentalCronetEngine.Builder mBuilder;
 
-        public CronetTestFramework(Context context) {
-            mCronetEngine = new ExperimentalCronetEngine.Builder(context).enableQuic(true).build();
+        private Context mContext;
+        private boolean mIsTestingJavaImpl;
+
+        private CronetTestFramework(Context context, boolean isTestingJavaImpl) {
+            mContext = context;
+            mIsTestingJavaImpl = isTestingJavaImpl;
+            mBuilder = mIsTestingJavaImpl ? createJavaEngineBuilder() : createNativeEngineBuilder();
+        }
+
+        private static CronetTestFramework createUsingJavaImpl(Context context) {
+            return new CronetTestFramework(context, true /* isTestingJavaImpl */);
+        }
+
+        private static CronetTestFramework createUsingNativeImpl(Context context) {
+            return new CronetTestFramework(context, false /* isTestingJavaImpl */);
+        }
+
+        public ExperimentalCronetEngine startEngine() {
+            assert mCronetEngine == null;
+
+            mCronetEngine = mBuilder.build();
+            if (mIsTestingJavaImpl) {
+                // Make sure that the instantiated engine is JavaCronetEngine.
+                assert mCronetEngine.getClass() == JavaCronetEngine.class;
+            }
+
             // Start collecting metrics.
             mCronetEngine.getGlobalMetricsDeltas();
+
+            return mCronetEngine;
+        }
+
+        public void shutdownEngine() {
+            if (mCronetEngine == null) return;
+            mCronetEngine.shutdown();
+            mCronetEngine = null;
+        }
+
+        private ExperimentalCronetEngine.Builder createJavaEngineBuilder() {
+            return CronetTestRule.createJavaEngineBuilder(mContext)
+                    .setUserAgent(UserAgent.from(getContext()))
+                    .enableQuic(true);
+        }
+
+        private ExperimentalCronetEngine.Builder createNativeEngineBuilder() {
+            return CronetTestRule.createNativeEngineBuilder(mContext).enableQuic(true);
         }
     }
 
@@ -89,8 +131,11 @@
             @Override
             public void evaluate() throws Throwable {
                 setUp();
-                runBase(base, desc);
-                tearDown();
+                try {
+                    runBase(base, desc);
+                } finally {
+                    tearDown();
+                }
             }
         };
     }
@@ -115,57 +160,86 @@
         setTestingJavaImpl(false);
         String packageName = desc.getTestClass().getPackage().getName();
 
+        boolean onlyRunTestForNative = desc.getAnnotation(OnlyRunNativeCronet.class) != null;
+        boolean onlyRunTestForJava = desc.getAnnotation(OnlyRunJavaCronet.class) != null;
+        if (onlyRunTestForNative && onlyRunTestForJava) {
+            throw new IllegalArgumentException(desc.getMethodName()
+                    + " skipped because it specified both "
+                    + "OnlyRunNativeCronet and OnlyRunJavaCronet annotations");
+        }
+        boolean doRunTestForNative = onlyRunTestForNative || !onlyRunTestForJava;
+        boolean doRunTestForJava = onlyRunTestForJava || !onlyRunTestForNative;
+
         // Find the API version required by the test.
         int requiredApiVersion = getMaximumAvailableApiLevel();
+        int requiredAndroidApiVersion = Build.VERSION_CODES.KITKAT;
         for (Annotation a : desc.getTestClass().getAnnotations()) {
             if (a instanceof RequiresMinApi) {
                 requiredApiVersion = ((RequiresMinApi) a).value();
             }
-        }
-        for (Annotation a : desc.getAnnotations()) {
-            if (a instanceof RequiresMinApi) {
-                // Method scoped requirements take precedence over class scoped
-                // requirements.
-                requiredApiVersion = ((RequiresMinApi) a).value();
+            if (a instanceof RequiresMinAndroidApi) {
+                requiredAndroidApiVersion = ((RequiresMinAndroidApi) a).value();
             }
         }
+        for (Annotation a : desc.getAnnotations()) {
+            // Method scoped requirements take precedence over class scoped
+            // requirements.
+            if (a instanceof RequiresMinApi) {
+                requiredApiVersion = ((RequiresMinApi) a).value();
+            }
+            if (a instanceof RequiresMinAndroidApi) {
+                requiredAndroidApiVersion = ((RequiresMinAndroidApi) a).value();
+            }
+        }
+        assumeTrue(desc.getMethodName() + " skipped because it requires API " + requiredApiVersion
+                        + " but only API " + getMaximumAvailableApiLevel() + " is present.",
+                getMaximumAvailableApiLevel() >= requiredApiVersion);
+        assumeTrue(desc.getMethodName() + " skipped because it Android's API level "
+                        + requiredAndroidApiVersion + " but test device supports only API "
+                        + Build.VERSION.SDK_INT,
+                Build.VERSION.SDK_INT >= requiredAndroidApiVersion);
 
-        if (requiredApiVersion > getMaximumAvailableApiLevel()) {
-            Log.i(TAG,
-                    desc.getMethodName() + " skipped because it requires API " + requiredApiVersion
-                            + " but only API " + getMaximumAvailableApiLevel() + " is present.");
-        } else if (packageName.equals("org.chromium.net.urlconnection")) {
-            try {
-                if (desc.getAnnotation(CompareDefaultWithCronet.class) != null) {
+        if (packageName.equals("org.chromium.net.urlconnection")) {
+            if (desc.getAnnotation(CompareDefaultWithCronet.class) != null) {
+                try {
                     // Run with the default HttpURLConnection implementation first.
                     setTestingSystemHttpURLConnection(true);
                     base.evaluate();
                     // Use Cronet's implementation, and run the same test.
                     setTestingSystemHttpURLConnection(false);
                     base.evaluate();
-                } else {
-                    // For all other tests.
+                } catch (Throwable e) {
+                    throw new AssertionError("CronetTestBase#runTest failed for "
+                                    + (testingSystemHttpURLConnection() ? "System" : "Cronet")
+                                    + " implementation.",
+                            e);
+                }
+            } else {
+                // For all other tests.
+                base.evaluate();
+            }
+        } else if (packageName.startsWith("org.chromium.net")) {
+            try {
+                if (doRunTestForNative) {
+                    Log.i(TAG, "Running test against Native implementation.");
                     base.evaluate();
                 }
-            } catch (Throwable e) {
-                throw new Throwable("Cronet Test failed.", e);
-            }
-        } else if (packageName.equals("org.chromium.net")) {
-            try {
-                base.evaluate();
-                if (desc.getAnnotation(OnlyRunNativeCronet.class) == null) {
+                if (doRunTestForJava) {
+                    Log.i(TAG, "Running test against Java implementation.");
                     setTestingJavaImpl(true);
                     base.evaluate();
                 }
             } catch (Throwable e) {
-                throw new Throwable("CronetTestBase#runTest failed.", e);
+                throw new AssertionError("CronetTestBase#runTest failed for "
+                                + (testingJavaImpl() ? "Java" : "Native") + " implementation.",
+                        e);
             }
         } else {
             base.evaluate();
         }
     }
 
-    void setUp() throws Exception {
+    private void setUp() throws Exception {
         System.loadLibrary("cronet_tests");
         ContextUtils.initApplicationContext(getContext().getApplicationContext());
         PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
@@ -181,7 +255,7 @@
         }
     }
 
-    void tearDown() throws Exception {
+    private void tearDown() throws Exception {
         try {
             // Run GC and finalizers a few times to pick up leaked closeables
             for (int i = 0; i < 10; i++) {
@@ -195,30 +269,47 @@
         }
     }
 
+    private CronetTestFramework createCronetTestFramework() {
+        mCronetTestFramework = testingJavaImpl()
+                ? CronetTestFramework.createUsingJavaImpl(getContext())
+                : CronetTestFramework.createUsingNativeImpl(getContext());
+        return mCronetTestFramework;
+    }
+
     /**
-     * Starts the CronetTest framework.
+     * Builds and starts the CronetTest framework.
      */
     public CronetTestFramework startCronetTestFramework() {
-        mCronetTestFramework = new CronetTestFramework(getContext());
-        if (testingJavaImpl()) {
-            ExperimentalCronetEngine.Builder builder = createJavaEngineBuilder();
-            builder.setUserAgent(UserAgent.from(getContext()));
-            mCronetTestFramework.mCronetEngine = builder.build();
-            // Make sure that the instantiated engine is JavaCronetEngine.
-            assert mCronetTestFramework.mCronetEngine.getClass() == JavaCronetEngine.class;
-        }
+        createCronetTestFramework();
+        mCronetTestFramework.startEngine();
         return mCronetTestFramework;
     }
 
     /**
+     * Builds the CronetTest framework.
+     */
+    public CronetTestFramework buildCronetTestFramework() {
+        return createCronetTestFramework();
+    }
+
+    /**
      * Creates and returns {@link ExperimentalCronetEngine.Builder} that creates
      * Java (platform) based {@link CronetEngine.Builder}.
      *
      * @return the {@code CronetEngine.Builder} that builds Java-based {@code Cronet engine}.
      */
-    public ExperimentalCronetEngine.Builder createJavaEngineBuilder() {
-        return (ExperimentalCronetEngine.Builder) new JavaCronetProvider(getContext())
-                .createBuilder();
+    public static ExperimentalCronetEngine.Builder createJavaEngineBuilder(Context context) {
+        return (ExperimentalCronetEngine.Builder) new JavaCronetProvider(context).createBuilder();
+    }
+
+    /**
+     * Creates and returns {@link ExperimentalCronetEngine.Builder} that creates
+     * Chromium (native) based {@link CronetEngine.Builder}.
+     *
+     * @return the {@code CronetEngine.Builder} that builds Chromium-based {@code Cronet engine}.
+     */
+    public static ExperimentalCronetEngine.Builder createNativeEngineBuilder(Context context) {
+        return (ExperimentalCronetEngine.Builder) new NativeCronetProvider(context).createBuilder();
     }
 
     public void assertResponseEquals(UrlResponseInfo expected, UrlResponseInfo actual) {
@@ -289,6 +380,15 @@
     public @interface OnlyRunNativeCronet {}
 
     /**
+     * Annotation for test methods in org.chromium.net package that disables rerunning the test
+     * against the Native/Chromium implementation. When this annotation is present the test is only
+     * run against the Java implementation.
+     */
+    @Target(ElementType.METHOD)
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface OnlyRunJavaCronet {}
+
+    /**
      * Annotation allowing classes or individual tests to be skipped based on the version of the
      * Cronet API present. Takes the minimum API version upon which the test should be run.
      * For example if a test should only be run with API version 2 or greater:
@@ -300,6 +400,20 @@
     public @interface RequiresMinApi {
         int value();
     }
+
+    /**
+     * Annotation allowing classes or individual tests to be skipped based on the Android OS version
+     * installed in the deviced used for testing. Takes the minimum API version upon which the test
+     * should be run. For example if a test should only be run with Android Oreo or greater:
+     *   @RequiresMinApi(Build.VERSION_CODES.O)
+     *   public void testFoo() {}
+     */
+    @Target({ElementType.TYPE, ElementType.METHOD})
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface RequiresMinAndroidApi {
+        int value();
+    }
+
     /**
      * Prepares the path for the test storage (http cache, QUIC server info).
      */
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRuleTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRuleTest.java
index 05ac2dfd94..46b2b1a 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRuleTest.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRuleTest.java
@@ -6,6 +6,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import android.support.test.runner.AndroidJUnit4;
@@ -21,6 +22,7 @@
 
 import org.chromium.base.test.util.Feature;
 import org.chromium.net.CronetTestRule.CronetTestFramework;
+import org.chromium.net.CronetTestRule.OnlyRunJavaCronet;
 import org.chromium.net.CronetTestRule.OnlyRunNativeCronet;
 import org.chromium.net.CronetTestRule.RequiresMinApi;
 import org.chromium.net.impl.CronetUrlRequestContext;
@@ -97,4 +99,15 @@
         mTestWasRun = true;
         assertEquals(mTestFramework.mCronetEngine.getClass(), CronetUrlRequestContext.class);
     }
-}
\ No newline at end of file
+
+    @Test
+    @SmallTest
+    @Feature({"Cronet"})
+    @OnlyRunJavaCronet
+    public void testRunOnlyJavaMustRun() {
+        assertTrue(mTestRule.testingJavaImpl());
+        assertFalse(mTestWasRun);
+        mTestWasRun = true;
+        assertEquals(mTestFramework.mCronetEngine.getClass(), JavaCronetEngine.class);
+    }
+}
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java
index 0440c1c1..aadcc5ba 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java
@@ -164,7 +164,8 @@
         ExperimentalCronetEngine.Builder cronetEngineBuilder =
                 new ExperimentalCronetEngine.Builder(getContext());
         if (mTestRule.testingJavaImpl()) {
-            cronetEngineBuilder = mTestRule.createJavaEngineBuilder();
+            cronetEngineBuilder =
+                    CronetTestRule.createJavaEngineBuilder(CronetTestRule.getContext());
         }
         cronetEngineBuilder.setUserAgent(userAgentValue);
         final CronetEngine cronetEngine = cronetEngineBuilder.build();
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetFixedModeOutputStreamTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetFixedModeOutputStreamTest.java
index 96a2f05c..fd7b050 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetFixedModeOutputStreamTest.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetFixedModeOutputStreamTest.java
@@ -441,23 +441,16 @@
     private static class CauseMatcher extends TypeSafeMatcher<Throwable> {
         private final Class<? extends Throwable> mType;
         private final String mExpectedMessage;
-        private final Class<? extends Throwable> mInnerCauseType;
-        private final String mInnerCauseExpectedMessage;
 
-        public CauseMatcher(Class<? extends Throwable> type, String expectedMessage,
-                Class<? extends Throwable> innerCauseType, String innerCauseExpectedMessage) {
+        public CauseMatcher(Class<? extends Throwable> type, String expectedMessage) {
             this.mType = type;
             this.mExpectedMessage = expectedMessage;
-            this.mInnerCauseType = innerCauseType;
-            this.mInnerCauseExpectedMessage = innerCauseExpectedMessage;
         }
 
         @Override
         protected boolean matchesSafely(Throwable item) {
             return item.getClass().isAssignableFrom(mType)
-                    && item.getMessage().equals(mExpectedMessage)
-                    && item.getCause().getClass().isAssignableFrom(mInnerCauseType)
-                    && item.getCause().getMessage().equals(mInnerCauseExpectedMessage);
+                    && item.getMessage().equals(mExpectedMessage);
         }
         @Override
         public void describeTo(Description description) {}
@@ -476,11 +469,10 @@
         connection.setDoOutput(true);
         connection.setRequestMethod("POST");
         connection.setFixedLengthStreamingMode(TestUtil.UPLOAD_DATA.length);
-        thrown.expectMessage("Cronet Test failed.");
-        thrown.expectCause(instanceOf(CallbackExceptionImpl.class));
-        thrown.expectCause(new CauseMatcher(CallbackExceptionImpl.class,
-                "Exception received from UploadDataProvider", HttpRetryException.class,
-                "Cannot retry streamed Http body"));
+        thrown.expect(instanceOf(CallbackExceptionImpl.class));
+        thrown.expectMessage("Exception received from UploadDataProvider");
+        thrown.expectCause(
+                new CauseMatcher(HttpRetryException.class, "Cannot retry streamed Http body"));
         OutputStream out = connection.getOutputStream();
         out.write(TestUtil.UPLOAD_DATA);
         connection.getResponseCode();
diff --git a/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.cc b/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.cc
index 963d46a..73ccd257 100644
--- a/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.cc
+++ b/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.cc
@@ -410,6 +410,15 @@
 }
 
 page_load_metrics::PageLoadMetricsObserver::ObservePolicy
+UmaPageLoadMetricsObserver::OnPrerenderStart(
+    content::NavigationHandle* navigation_handle,
+    const GURL& currently_committed_url) {
+  // PrerenderPageLoadMetricsObserver records prerendering version of metrics
+  // and this PLMO can stop on prerendering.
+  return STOP_OBSERVING;
+}
+
+page_load_metrics::PageLoadMetricsObserver::ObservePolicy
 UmaPageLoadMetricsObserver::OnRedirect(
     content::NavigationHandle* navigation_handle) {
   redirect_chain_size_++;
diff --git a/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.h b/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.h
index f36abf780..4c64515a 100644
--- a/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.h
+++ b/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.h
@@ -182,6 +182,8 @@
   ObservePolicy OnFencedFramesStart(
       content::NavigationHandle* navigation_handle,
       const GURL& currently_committed_url) override;
+  ObservePolicy OnPrerenderStart(content::NavigationHandle* navigation_handle,
+                                 const GURL& currently_committed_url) override;
   ObservePolicy OnRedirect(
       content::NavigationHandle* navigation_handle) override;
   ObservePolicy OnCommit(content::NavigationHandle* navigation_handle) override;
diff --git a/components/password_manager/core/browser/import/csv_password.cc b/components/password_manager/core/browser/import/csv_password.cc
index 67510ba..574e66b 100644
--- a/components/password_manager/core/browser/import/csv_password.cc
+++ b/components/password_manager/core/browser/import/csv_password.cc
@@ -20,17 +20,29 @@
 
 namespace {
 
-// Convert() unescapes a CSV field |str| and converts the result to a 16-bit
+// ConvertUTF8() unescapes a CSV field |str| and converts the result to a 8-bit
 // string. |str| is assumed to exclude the outer pair of quotation marks, if
 // originally present.
-std::u16string Convert(base::StringPiece str) {
+std::string ConvertUTF8(base::StringPiece str) {
   std::string str_copy(str);
   base::ReplaceSubstringsAfterOffset(&str_copy, 0, "\"\"", "\"");
-  return base::UTF8ToUTF16(str_copy);
+  return str_copy;
+}
+
+// Convert() converts the result to a 16-bit string.
+std::u16string Convert(const std::string& str) {
+  return base::UTF8ToUTF16(str);
 }
 
 }  // namespace
 
+CSVPassword::CSVPassword() : status_(Status::kSemanticError) {}
+CSVPassword::CSVPassword(GURL url, std::string username, std::string password)
+    : url_(std::move(url)),
+      username_(std::move(username)),
+      password_(std::move(password)),
+      status_(Status::kOK) {}
+
 CSVPassword::CSVPassword(const ColumnMap& map, base::StringPiece row) {
   if (map.size() != kLabelCount) {
     status_ = Status::kSemanticError;
@@ -60,11 +72,11 @@
         url_ = GURL(field);
         break;
       case Label::kUsername:
-        username_ = field;
+        username_ = ConvertUTF8(field);
         username_set = true;
         break;
       case Label::kPassword:
-        password_ = field;
+        password_ = ConvertUTF8(field);
         break;
     }
   }
@@ -76,6 +88,11 @@
   }
 }
 
+CSVPassword::CSVPassword(const CSVPassword&) = default;
+CSVPassword::CSVPassword(CSVPassword&&) = default;
+CSVPassword& CSVPassword::operator=(const CSVPassword&) = default;
+CSVPassword& CSVPassword::operator=(CSVPassword&&) = default;
+
 CSVPassword::Status CSVPassword::GetParseStatus() const {
   return status_;
 }
@@ -99,4 +116,16 @@
   return form;
 }
 
+const std::string& CSVPassword::GetPassword() const {
+  return password_;
+}
+
+const std::string& CSVPassword::GetUsername() const {
+  return username_;
+}
+
+const GURL& CSVPassword::GetURL() const {
+  return url_;
+}
+
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/import/csv_password.h b/components/password_manager/core/browser/import/csv_password.h
index e536680..18c16953 100644
--- a/components/password_manager/core/browser/import/csv_password.h
+++ b/components/password_manager/core/browser/import/csv_password.h
@@ -27,23 +27,34 @@
   // Number of values in the Label enum.
   static constexpr size_t kLabelCount = 3;
 
+  explicit CSVPassword();
   explicit CSVPassword(const ColumnMap& map, base::StringPiece csv_row);
-  CSVPassword(const CSVPassword&) = delete;
-  CSVPassword(CSVPassword&&) = delete;
-  CSVPassword& operator=(const CSVPassword&) = delete;
-  CSVPassword& operator=(CSVPassword&&) = delete;
+  explicit CSVPassword(GURL url, std::string username, std::string password);
+  CSVPassword(const CSVPassword&);
+  CSVPassword(CSVPassword&&);
+  CSVPassword& operator=(const CSVPassword&);
+  CSVPassword& operator=(CSVPassword&&);
 
   // Returns the status of the parse.
   Status GetParseStatus() const;
 
+  // Returns the password.
+  const std::string& GetPassword() const;
+
+  // Returns the username.
+  const std::string& GetUsername() const;
+
+  // Returns the URL.
+  const GURL& GetURL() const;
+
   // Returns PasswordForm populated with parsed data, if initial parsing
   // completed successfully.
   PasswordForm ToPasswordForm() const;
 
  private:
   GURL url_;
-  base::StringPiece username_;
-  base::StringPiece password_;
+  std::string username_;
+  std::string password_;
 
   Status status_;
 };
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc
index a077578..b92520d6 100644
--- a/components/password_manager/core/browser/password_store.cc
+++ b/components/password_manager/core/browser/password_store.cc
@@ -109,9 +109,8 @@
 
 void PasswordStore::AddLogin(const PasswordForm& form) {
   DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
-  // TODO(crbug.com/1324588): Replace by DCHECK
-  CHECK(!form.blocked_by_user ||
-        (form.username_value.empty() && form.password_value.empty()));
+  DCHECK(!form.blocked_by_user ||
+         (form.username_value.empty() && form.password_value.empty()));
   if (!backend_)
     return;  // Once the shutdown started, ignore new requests.
   backend_->AddLoginAsync(
@@ -123,9 +122,8 @@
 
 void PasswordStore::UpdateLogin(const PasswordForm& form) {
   DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
-  // TODO(crbug.com/1324588): Replace by DCHECK
-  CHECK(!form.blocked_by_user ||
-        (form.username_value.empty() && form.password_value.empty()));
+  DCHECK(!form.blocked_by_user ||
+         (form.username_value.empty() && form.password_value.empty()));
   if (!backend_)
     return;  // Once the shutdown started, ignore new requests.
   backend_->UpdateLoginAsync(
diff --git a/components/password_manager/core/browser/password_store_backend_metrics_recorder.cc b/components/password_manager/core/browser/password_store_backend_metrics_recorder.cc
index 20dc480..d953bac 100644
--- a/components/password_manager/core/browser/password_store_backend_metrics_recorder.cc
+++ b/components/password_manager/core/browser/password_store_backend_metrics_recorder.cc
@@ -15,7 +15,7 @@
 namespace {
 constexpr char kMetricPrefix[] = "PasswordManager.PasswordStore";
 
-bool ShouldRecordLatency(
+bool HasRunToCompletion(
     PasswordStoreBackendMetricsRecorder::SuccessStatus success_status) {
   switch (success_status) {
     case PasswordStoreBackendMetricsRecorder::SuccessStatus::kSuccess:
@@ -37,7 +37,9 @@
     BackendInfix backend_infix,
     MetricInfix metric_infix)
     : backend_infix_(std::move(backend_infix)),
-      metric_infix_(std::move(metric_infix)) {}
+      metric_infix_(std::move(metric_infix)) {
+  RecordRequestStatus(StoreBackendRequestStatus::kRequestIssued);
+}
 
 PasswordStoreBackendMetricsRecorder::PasswordStoreBackendMetricsRecorder(
     PasswordStoreBackendMetricsRecorder&&) = default;
@@ -53,8 +55,11 @@
     SuccessStatus success_status,
     absl::optional<ErrorFromPasswordStoreOrAndroidBackend> error) const {
   RecordSuccess(success_status);
-  if (ShouldRecordLatency(success_status)) {
+  if (HasRunToCompletion(success_status)) {
     RecordLatency();
+    RecordRequestStatus(StoreBackendRequestStatus::kCompleted);
+  } else {
+    RecordRequestStatus(StoreBackendRequestStatus::kTimeout);
   }
   if (error.has_value()) {
     DCHECK_NE(success_status, SuccessStatus::kSuccess);
@@ -69,6 +74,12 @@
   return base::Time::Now() - start_;
 }
 
+void PasswordStoreBackendMetricsRecorder::RecordRequestStatus(
+    StoreBackendRequestStatus request_status) const {
+  base::UmaHistogramEnumeration(GetBackendMetricName(), request_status);
+  base::UmaHistogramEnumeration(GetOverallMetricName(), request_status);
+}
+
 void PasswordStoreBackendMetricsRecorder::RecordSuccess(
     SuccessStatus success_status) const {
   base::UmaHistogramBoolean(BuildMetricName("Success"),
@@ -103,14 +114,21 @@
   base::UmaHistogramSparse(BuildMetricName("APIError"), api_error_code);
 }
 
+std::string PasswordStoreBackendMetricsRecorder::GetBackendMetricName() const {
+  return base::StrCat({kMetricPrefix, *backend_infix_, ".", *metric_infix_});
+}
+
 std::string PasswordStoreBackendMetricsRecorder::BuildMetricName(
     base::StringPiece suffix) const {
-  return base::StrCat(
-      {kMetricPrefix, *backend_infix_, ".", *metric_infix_, ".", suffix});
+  return base::StrCat({GetBackendMetricName(), ".", suffix});
+}
+
+std::string PasswordStoreBackendMetricsRecorder::GetOverallMetricName() const {
+  return base::StrCat({kMetricPrefix, "Backend.", *metric_infix_});
 }
 
 std::string PasswordStoreBackendMetricsRecorder::BuildOverallMetricName(
     base::StringPiece suffix) const {
-  return base::StrCat({kMetricPrefix, "Backend.", *metric_infix_, ".", suffix});
+  return base::StrCat({GetOverallMetricName(), ".", suffix});
 }
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/password_store_backend_metrics_recorder.h b/components/password_manager/core/browser/password_store_backend_metrics_recorder.h
index 04f950fb..f3308a4 100644
--- a/components/password_manager/core/browser/password_store_backend_metrics_recorder.h
+++ b/components/password_manager/core/browser/password_store_backend_metrics_recorder.h
@@ -31,6 +31,8 @@
   enum class SuccessStatus { kSuccess, kError, kCancelled };
 
   PasswordStoreBackendMetricsRecorder();
+  // Constructs a new recorder and immediately calls `RecordRequestStatus()` to
+  // indicate a new request is started.
   explicit PasswordStoreBackendMetricsRecorder(BackendInfix backend_name,
                                                MetricInfix metric_name);
   PasswordStoreBackendMetricsRecorder(PasswordStoreBackendMetricsRecorder&&);
@@ -49,6 +51,20 @@
   base::TimeDelta GetElapsedTimeSinceCreation() const;
 
  private:
+  // These values are persisted to logs. Entries should not be renumbered and
+  // numeric values should never be reused.
+  enum class StoreBackendRequestStatus {
+    kRequestIssued = 0,
+    kTimeout = 1,
+    kCompleted = 2,
+    kMaxValue = kCompleted
+  };
+
+  // Records a broad status for an ongoing request:
+  // - "PasswordManager.PasswordStoreBackend.<metric_infix_>"
+  // - "PasswordManager.PasswordStore<backend_infix_>.<metric_infix_>"
+  void RecordRequestStatus(StoreBackendRequestStatus request_status) const;
+
   // Records the following metrics:
   // - "PasswordManager.PasswordStore<backend_infix_>.<metric_infix_>.Success"
   // - "PasswordManager.PasswordStoreBackend.<metric_infix_>.Success"
@@ -70,7 +86,9 @@
   // - "PasswordManager.PasswordStoreAndroidBackend.<metric_infix_>.APIError"
   void RecordApiErrorCode(int api_error_code) const;
 
+  std::string GetBackendMetricName() const;
   std::string BuildMetricName(base::StringPiece suffix) const;
+  std::string GetOverallMetricName() const;
   std::string BuildOverallMetricName(base::StringPiece suffix) const;
 
   BackendInfix backend_infix_;
diff --git a/components/password_manager/core/browser/password_store_backend_metrics_recorder_unittest.cc b/components/password_manager/core/browser/password_store_backend_metrics_recorder_unittest.cc
index 63f7be3..8a1c6cf4 100644
--- a/components/password_manager/core/browser/password_store_backend_metrics_recorder_unittest.cc
+++ b/components/password_manager/core/browser/password_store_backend_metrics_recorder_unittest.cc
@@ -22,6 +22,8 @@
 
 constexpr char kSomeBackend[] = "SomeBackend";
 constexpr char kSomeMethod[] = "MethodName";
+constexpr char kSpecificMetric[] =
+    "PasswordManager.PasswordStoreSomeBackend.MethodName";
 constexpr char kDurationMetric[] =
     "PasswordManager.PasswordStoreSomeBackend.MethodName.Latency";
 constexpr char kSuccessMetric[] =
@@ -30,6 +32,8 @@
     "PasswordManager.PasswordStoreSomeBackend.MethodName.ErrorCode";
 constexpr char kApiErrorMetric[] =
     "PasswordManager.PasswordStoreSomeBackend.MethodName.APIError";
+constexpr char kOverallMetric[] =
+    "PasswordManager.PasswordStoreBackend.MethodName";
 constexpr char kDurationOverallMetric[] =
     "PasswordManager.PasswordStoreBackend.MethodName.Latency";
 constexpr char kSuccessOverallMetric[] =
@@ -64,6 +68,12 @@
       PasswordStoreBackendMetricsRecorder(BackendInfix(kSomeBackend),
                                           MetricInfix(kSomeMethod));
 
+  // Checking started requests in the overall and backend-specific histogram.
+  EXPECT_THAT(histogram_tester.GetAllSamples(kSpecificMetric),
+              ElementsAre(Bucket(/* Requested */ 0, 1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples(kOverallMetric),
+              ElementsAre(Bucket(/* Requested */ 0, 1)));
+
   AdvanceClock(kLatencyDelta);
 
   metrics_recorder.RecordMetrics(SuccessStatus::kSuccess,
@@ -81,6 +91,14 @@
                                          1);
   EXPECT_THAT(histogram_tester.GetAllSamples(kSuccessOverallMetric),
               ElementsAre(Bucket(true, 1)));
+
+  // Checking completed requests in the overall and backend-specific histogram.
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples(kSpecificMetric),
+      ElementsAre(Bucket(/* Requested */ 0, 1), Bucket(/* Completed */ 2, 1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples(kOverallMetric),
+      ElementsAre(Bucket(/* Requested */ 0, 1), Bucket(/* Completed */ 2, 1)));
 }
 
 TEST_F(PasswordStoreBackendMetricsRecorderTest, RecordMetrics_ExternalError) {
@@ -117,6 +135,14 @@
               ElementsAre(Bucket(7, 1)));
   EXPECT_THAT(histogram_tester.GetAllSamples(kApiErrorOverallMetric),
               ElementsAre(Bucket(11010, 1)));
+
+  // Checking completed requests in the overall and backend-specific histogram.
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples(kSpecificMetric),
+      ElementsAre(Bucket(/* Requested */ 0, 1), Bucket(/* Completed */ 2, 1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples(kOverallMetric),
+      ElementsAre(Bucket(/* Requested */ 0, 1), Bucket(/* Completed */ 2, 1)));
 }
 
 TEST_F(PasswordStoreBackendMetricsRecorderTest, RecordMetrics_Cancelled) {
@@ -132,15 +158,23 @@
   metrics_recorder.RecordMetrics(SuccessStatus::kCancelled,
                                  /*error=*/absl::nullopt);
 
-  // Checking records in the backend-specific histogram
+  // Checking records in the backend-specific histogram.
   histogram_tester.ExpectTotalCount(kDurationMetric, 0);
   EXPECT_THAT(histogram_tester.GetAllSamples(kSuccessMetric),
               ElementsAre(Bucket(false, 1)));
 
-  // Checking records in the overall histogram
+  // Checking records in the overall histogram.
   histogram_tester.ExpectTotalCount(kDurationOverallMetric, 0);
   EXPECT_THAT(histogram_tester.GetAllSamples(kSuccessOverallMetric),
               ElementsAre(Bucket(false, 1)));
+
+  // Checking timed-out requests in the overall and backend-specific histogram.
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples(kSpecificMetric),
+      ElementsAre(Bucket(/* Requested */ 0, 1), Bucket(/* Timeout */ 1, 1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples(kOverallMetric),
+      ElementsAre(Bucket(/* Requested */ 0, 1), Bucket(/* Timeout */ 1, 1)));
 }
 
 }  // namespace password_manager
diff --git a/components/password_manager/services/csv_password/BUILD.gn b/components/password_manager/services/csv_password/BUILD.gn
new file mode 100644
index 0000000..e8133fa
--- /dev/null
+++ b/components/password_manager/services/csv_password/BUILD.gn
@@ -0,0 +1,50 @@
+# Copyright 2022 The Chromium Authors.All rights reserved.
+# Use of this source code is governed by a BSD - style license that can be
+# found in the LICENSE file.
+
+source_set("lib") {
+  sources = [
+    "csv_password_parser_impl.cc",
+    "csv_password_parser_impl.h",
+  ]
+
+  deps = [
+    "//base",
+    "//components/password_manager/core/browser:csv",
+    "//mojo/public/cpp/bindings",
+  ]
+
+  public_deps =
+      [ "//components/password_manager/services/csv_password/public/mojom" ]
+}
+
+if (!is_ios) {
+  source_set("service") {
+    sources = [
+      "csv_password_parser_service.cc",
+      "csv_password_parser_service.h",
+    ]
+
+    deps = [
+      "//components/strings",
+      "//content/public/browser",
+    ]
+
+    public_deps = [
+      "//components/password_manager/services/csv_password/public/mojom",
+      "//mojo/public/cpp/bindings",
+    ]
+  }
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [ "csv_password_parser_impl_unittest.cc" ]
+
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//components/password_manager/services/csv_password:lib",
+    "//testing/gtest",
+  ]
+}
diff --git a/components/password_manager/services/csv_password/DEPS b/components/password_manager/services/csv_password/DEPS
new file mode 100644
index 0000000..7b625eef
--- /dev/null
+++ b/components/password_manager/services/csv_password/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+  "+components/strings",
+  "+content/public/browser",
+  "+mojo/public",
+]
diff --git a/components/password_manager/services/csv_password/csv_password_parser_impl.cc b/components/password_manager/services/csv_password/csv_password_parser_impl.cc
new file mode 100644
index 0000000..62eeb26
--- /dev/null
+++ b/components/password_manager/services/csv_password/csv_password_parser_impl.cc
@@ -0,0 +1,33 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/services/csv_password/csv_password_parser_impl.h"
+
+#include "components/password_manager/core/browser/import/csv_password.h"
+#include "components/password_manager/core/browser/import/csv_password_sequence.h"
+
+#include <utility>
+#include <vector>
+
+namespace password_manager {
+
+CSVPasswordParserImpl::CSVPasswordParserImpl(
+    mojo::PendingReceiver<mojom::CSVPasswordParser> receiver)
+    : receiver_(this, std::move(receiver)) {}
+
+CSVPasswordParserImpl::~CSVPasswordParserImpl() = default;
+
+void CSVPasswordParserImpl::ParseCSV(const std::string& raw_json,
+                                     ParseCSVCallback callback) {
+  mojom::CSVPasswordSequencePtr result = nullptr;
+  CSVPasswordSequence seq(raw_json);
+  if (seq.result() == CSVPassword::Status::kOK) {
+    result = mojom::CSVPasswordSequence::New();
+    for (const auto& pwd : seq)
+      result->csv_passwords.push_back(pwd);
+  }
+  std::move(callback).Run(std::move(result));
+}
+
+}  // namespace password_manager
diff --git a/components/password_manager/services/csv_password/csv_password_parser_impl.h b/components/password_manager/services/csv_password/csv_password_parser_impl.h
new file mode 100644
index 0000000..f0e8c5d
--- /dev/null
+++ b/components/password_manager/services/csv_password/csv_password_parser_impl.h
@@ -0,0 +1,36 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_SERVICES_CSV_PASSWORD_CSV_PASSWORD_PARSER_IMPL_H_
+#define COMPONENTS_PASSWORD_MANAGER_SERVICES_CSV_PASSWORD_CSV_PASSWORD_PARSER_IMPL_H_
+
+#include <string>
+
+#include "components/password_manager/services/csv_password/public/mojom/csv_password_parser.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+
+namespace password_manager {
+
+// Implementation of the CSVPasswordParser mojom interface.
+class CSVPasswordParserImpl : public mojom::CSVPasswordParser {
+ public:
+  // Constructs a CSVPasswordParserImpl bound to |receiver|.
+  explicit CSVPasswordParserImpl(
+      mojo::PendingReceiver<mojom::CSVPasswordParser> receiver);
+  ~CSVPasswordParserImpl() override;
+  CSVPasswordParserImpl(const CSVPasswordParserImpl&) = delete;
+  CSVPasswordParserImpl& operator=(const CSVPasswordParserImpl&) = delete;
+
+  // password_manager::mojom::CSVPasswordParser:
+  void ParseCSV(const std::string& raw_json,
+                ParseCSVCallback callback) override;
+
+ private:
+  mojo::Receiver<mojom::CSVPasswordParser> receiver_;
+};
+
+}  // namespace password_manager
+
+#endif  // COMPONENTS_PASSWORD_MANAGER_SERVICES_CSV_PASSWORD_CSV_PASSWORD_PARSER_IMPL_H_
diff --git a/components/password_manager/services/csv_password/csv_password_parser_impl_unittest.cc b/components/password_manager/services/csv_password/csv_password_parser_impl_unittest.cc
new file mode 100644
index 0000000..2868aa9
--- /dev/null
+++ b/components/password_manager/services/csv_password/csv_password_parser_impl_unittest.cc
@@ -0,0 +1,120 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/services/csv_password/csv_password_parser_impl.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/run_loop.h"
+#include "base/test/bind.h"
+#include "base/test/task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+using testing::IsEmpty;
+
+namespace password_manager {
+
+class CSVPasswordParserImplTest : public testing::Test {
+ protected:
+  CSVPasswordParserImplTest() {
+    mojo::PendingReceiver<mojom::CSVPasswordParser> receiver;
+    parser_ = std::make_unique<CSVPasswordParserImpl>(std::move(receiver));
+  }
+
+  void ParseCSV(const std::string& raw_json,
+                mojom::CSVPasswordParser::ParseCSVCallback callback) {
+    parser_->ParseCSV(raw_json, std::move(callback));
+  }
+
+ private:
+  std::unique_ptr<CSVPasswordParserImpl> parser_;
+};
+
+TEST_F(CSVPasswordParserImplTest, ParseEmptyFile) {
+  ParseCSV("", base::BindLambdaForTesting(
+                   [](mojom::CSVPasswordSequencePtr sequence) {
+                     EXPECT_FALSE(sequence);
+                   }));
+}
+
+TEST_F(CSVPasswordParserImplTest, ParseHeaderOnlyFile) {
+  const std::string raw_csv =
+      R"(Display Name,   ,Login,Secret Question,Password,URL,Timestamp)";
+
+  ParseCSV(raw_csv, base::BindLambdaForTesting(
+                        [](mojom::CSVPasswordSequencePtr sequence) {
+                          EXPECT_TRUE(sequence);
+                          EXPECT_THAT(sequence->csv_passwords, IsEmpty());
+                        }));
+}
+
+TEST_F(CSVPasswordParserImplTest, ParseHeaderOnlyFileOnlyBasics) {
+  const std::string raw_csv = R"(Login,Password,URL)";
+
+  ParseCSV(raw_csv, base::BindLambdaForTesting(
+                        [](mojom::CSVPasswordSequencePtr sequence) {
+                          EXPECT_TRUE(sequence);
+                          EXPECT_THAT(sequence->csv_passwords, IsEmpty());
+                        }));
+}
+
+TEST_F(CSVPasswordParserImplTest, ParseGoodFile) {
+  const std::string raw_csv =
+      R"(Display Name,   ,Login,Secret Question,Password,URL,Timestamp
+        DN           , v ,user,?               ,pwd,http://example.com,123
+                     , < ,Alice,123?           ,even,https://example.net,213,pas
+        :)           ,   ,Bob,ABCD!            ,odd,https://example.org,132)";
+
+  ParseCSV(
+      raw_csv,
+      base::BindLambdaForTesting([&](mojom::CSVPasswordSequencePtr sequence) {
+        EXPECT_TRUE(sequence);
+        EXPECT_EQ(3u, sequence->csv_passwords.size());
+
+        EXPECT_EQ(GURL("http://example.com"),
+                  sequence->csv_passwords[0].GetURL());
+        EXPECT_EQ("user", sequence->csv_passwords[0].GetUsername());
+        EXPECT_EQ("pwd", sequence->csv_passwords[0].GetPassword());
+
+        EXPECT_EQ(GURL("https://example.net"),
+                  sequence->csv_passwords[1].GetURL());
+        EXPECT_EQ("Alice", sequence->csv_passwords[1].GetUsername());
+        EXPECT_EQ("even", sequence->csv_passwords[1].GetPassword());
+
+        EXPECT_EQ(GURL("https://example.org"),
+                  sequence->csv_passwords[2].GetURL());
+        EXPECT_EQ("Bob", sequence->csv_passwords[2].GetUsername());
+        EXPECT_EQ("odd", sequence->csv_passwords[2].GetPassword());
+      }));
+}
+
+TEST_F(CSVPasswordParserImplTest, ParseFileMissingPassword) {
+  const std::string raw_csv =
+      R"(Display Name,   ,Login,Secret Question,Password,URL,Timestamp
+        :)           ,   ,Bob,ABCD!            ,,https://example.org,132)";
+
+  ParseCSV(raw_csv, base::BindLambdaForTesting(
+                        [&](mojom::CSVPasswordSequencePtr sequence) {
+                          EXPECT_TRUE(sequence);
+                          EXPECT_THAT(sequence->csv_passwords, IsEmpty());
+                        }));
+}
+
+TEST_F(CSVPasswordParserImplTest, ParseFileMissingFields) {
+  const std::string raw_csv =
+      R"(Display Name,   ,Login,Secret Question,Password,URL,Timestamp
+        :)            Bob,ABCD!,blabla,https://example.org,132)";
+
+  ParseCSV(raw_csv, base::BindLambdaForTesting(
+                        [&](mojom::CSVPasswordSequencePtr sequence) {
+                          EXPECT_TRUE(sequence);
+                          EXPECT_THAT(sequence->csv_passwords, IsEmpty());
+                        }));
+}
+
+}  // namespace password_manager
diff --git a/components/password_manager/services/csv_password/csv_password_parser_service.cc b/components/password_manager/services/csv_password/csv_password_parser_service.cc
new file mode 100644
index 0000000..739dab69
--- /dev/null
+++ b/components/password_manager/services/csv_password/csv_password_parser_service.cc
@@ -0,0 +1,22 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/services/csv_password/csv_password_parser_service.h"
+
+#include "components/strings/grit/components_strings.h"
+#include "content/public/browser/service_process_host.h"
+
+namespace password_manager {
+
+mojo::Remote<password_manager::mojom::CSVPasswordParser>
+LaunchCSVPasswordParser() {
+  return content::ServiceProcessHost::Launch<
+      password_manager::mojom::CSVPasswordParser>(
+      content::ServiceProcessHost::Options()
+          .WithDisplayName(
+              IDS_PASSWORD_MANAGER_CSV_PASSWORD_PARSER_SERVICE_DISPLAY_NAME)
+          .Pass());
+}
+
+}  // namespace password_manager
diff --git a/components/password_manager/services/csv_password/csv_password_parser_service.h b/components/password_manager/services/csv_password/csv_password_parser_service.h
new file mode 100644
index 0000000..41e000b3
--- /dev/null
+++ b/components/password_manager/services/csv_password/csv_password_parser_service.h
@@ -0,0 +1,22 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_SERVICES_CSV_PASSWORD_CSV_PASSWORD_PARSER_SERVICE_H_
+#define COMPONENTS_PASSWORD_MANAGER_SERVICES_CSV_PASSWORD_CSV_PASSWORD_PARSER_SERVICE_H_
+
+#include "components/password_manager/services/csv_password/public/mojom/csv_password_parser.mojom.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace password_manager {
+
+// Launches a new instance of the CSVPasswordParser service in an
+// isolated, sandboxed process, and returns a remote interface to control the
+// service. The lifetime of the process is tied to that of the Remote. May be
+// called from any thread.
+mojo::Remote<password_manager::mojom::CSVPasswordParser>
+LaunchCSVPasswordParser();
+
+}  // namespace password_manager
+
+#endif  // COMPONENTS_PASSWORD_MANAGER_SERVICES_CSV_PASSWORD_CSV_PASSWORD_PARSER_SERVICE_H_
diff --git a/components/password_manager/services/csv_password/public/mojom/BUILD.gn b/components/password_manager/services/csv_password/public/mojom/BUILD.gn
new file mode 100644
index 0000000..24d5837
--- /dev/null
+++ b/components/password_manager/services/csv_password/public/mojom/BUILD.gn
@@ -0,0 +1,28 @@
+# 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.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("mojom") {
+  sources = [ "csv_password_parser.mojom" ]
+
+  public_deps = [
+    "//sandbox/policy/mojom",
+    "//url/mojom:url_mojom_gurl",
+  ]
+
+  cpp_typemaps = [
+    {
+      types = [
+        {
+          mojom = "password_manager.mojom.CSVPassword"
+          cpp = "::password_manager::CSVPassword"
+        },
+      ]
+      traits_headers = [ "csv_password_parser_traits.h" ]
+      traits_sources = [ "csv_password_parser_traits.cc" ]
+      traits_public_deps = [ "//components/password_manager/core/browser:csv" ]
+    },
+  ]
+}
diff --git a/components/password_manager/services/csv_password/public/mojom/OWNERS b/components/password_manager/services/csv_password/public/mojom/OWNERS
new file mode 100644
index 0000000..08850f4
--- /dev/null
+++ b/components/password_manager/services/csv_password/public/mojom/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/components/password_manager/services/csv_password/public/mojom/csv_password_parser.mojom b/components/password_manager/services/csv_password/public/mojom/csv_password_parser.mojom
new file mode 100644
index 0000000..4455882
--- /dev/null
+++ b/components/password_manager/services/csv_password/public/mojom/csv_password_parser.mojom
@@ -0,0 +1,29 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module password_manager.mojom;
+
+import "sandbox/policy/mojom/sandbox.mojom";
+import "url/mojom/url.mojom";
+
+struct CSVPasswordSequence {
+  array<CSVPassword> csv_passwords;
+};
+
+struct CSVPassword {
+  string username;
+  string password;
+  url.mojom.Url url;
+};
+
+// Interface for parsing csv raw string that is expected to
+// confrom to the password manager CSV format.
+// Lives in a utility process, and used as part of the Password Import feature.
+// If parsing failed, |sequence| will be null.
+[ServiceSandbox=sandbox.mojom.Sandbox.kService]
+interface CSVPasswordParser {
+  // Parses the |raw_csv| into a CSVPasswordSequence object.
+  ParseCSV(string raw_csv)
+    => (CSVPasswordSequence? sequence);
+};
diff --git a/components/password_manager/services/csv_password/public/mojom/csv_password_parser_traits.cc b/components/password_manager/services/csv_password/public/mojom/csv_password_parser_traits.cc
new file mode 100644
index 0000000..9c13064
--- /dev/null
+++ b/components/password_manager/services/csv_password/public/mojom/csv_password_parser_traits.cc
@@ -0,0 +1,30 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/services/csv_password/public/mojom/csv_password_parser_traits.h"
+
+#include "components/password_manager/core/browser/import/csv_password.h"
+#include "url/mojom/url_gurl_mojom_traits.h"
+
+namespace mojo {
+
+// static
+bool StructTraits<password_manager::mojom::CSVPasswordDataView,
+                  password_manager::CSVPassword>::
+    Read(password_manager::mojom::CSVPasswordDataView data,
+         password_manager::CSVPassword* out) {
+  GURL url;
+  std::string username;
+  std::string password;
+  if (!data.ReadUrl(&url))
+    return false;
+  if (!data.ReadUsername(&username))
+    return false;
+  if (!data.ReadPassword(&password))
+    return false;
+  *out = password_manager::CSVPassword(url, username, password);
+  return true;
+}
+
+}  // namespace mojo
diff --git a/components/password_manager/services/csv_password/public/mojom/csv_password_parser_traits.h b/components/password_manager/services/csv_password/public/mojom/csv_password_parser_traits.h
new file mode 100644
index 0000000..9c60bdd
--- /dev/null
+++ b/components/password_manager/services/csv_password/public/mojom/csv_password_parser_traits.h
@@ -0,0 +1,32 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_SERVICES_CSV_PASSWORD_PUBLIC_MOJOM_CSV_PASSWORD_PARSER_TRAITS_H_
+#define COMPONENTS_PASSWORD_MANAGER_SERVICES_CSV_PASSWORD_PUBLIC_MOJOM_CSV_PASSWORD_PARSER_TRAITS_H_
+
+#include "components/password_manager/core/browser/import/csv_password.h"
+#include "components/password_manager/services/csv_password/public/mojom/csv_password_parser.mojom.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
+
+namespace mojo {
+
+template <>
+struct StructTraits<password_manager::mojom::CSVPasswordDataView,
+                    password_manager::CSVPassword> {
+  static const GURL& url(const password_manager::CSVPassword& r) {
+    return r.GetURL();
+  }
+  static const std::string& username(const password_manager::CSVPassword& r) {
+    return r.GetUsername();
+  }
+  static const std::string& password(const password_manager::CSVPassword& r) {
+    return r.GetPassword();
+  }
+  static bool Read(password_manager::mojom::CSVPasswordDataView data,
+                   password_manager::CSVPassword* out);
+};
+
+}  // namespace mojo
+
+#endif  // COMPONENTS_PASSWORD_MANAGER_SERVICES_CSV_PASSWORD_PUBLIC_MOJOM_CSV_PASSWORD_PARSER_TRAITS_H_
diff --git a/components/plugins/renderer/webview_plugin.cc b/components/plugins/renderer/webview_plugin.cc
index dcef5df6..c58536f2 100644
--- a/components/plugins/renderer/webview_plugin.cc
+++ b/components/plugins/renderer/webview_plugin.cc
@@ -26,6 +26,7 @@
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
 #include "third_party/blink/public/mojom/input/focus_type.mojom.h"
 #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
+#include "third_party/blink/public/platform/web_policy_container.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/platform/web_url_response.h"
 #include "third_party/blink/public/web/web_document.h"
@@ -411,14 +412,17 @@
 void WebViewPlugin::LoadHTML(const std::string& html_data, const GURL& url) {
   auto params = std::make_unique<blink::WebNavigationParams>();
   params->url = url;
+  params->policy_container = std::make_unique<blink::WebPolicyContainer>();
+
   // The |html_data| comes from files in: chrome/renderer/resources/plugins/
   // Executing scripts is the only capability required.
   //
   // WebSandboxFlags is a bit field. This removes all the capabilities, except
   // script execution.
   using network::mojom::WebSandboxFlags;
-  params->sandbox_flags = static_cast<WebSandboxFlags>(
-      ~static_cast<int>(WebSandboxFlags::kScripts));
+  params->policy_container->policies.sandbox_flags =
+      static_cast<WebSandboxFlags>(
+          ~static_cast<int>(WebSandboxFlags::kScripts));
   blink::WebNavigationParams::FillStaticResponse(params.get(), "text/html",
                                                  "UTF-8", html_data);
   web_view_helper_.main_frame()->CommitNavigation(std::move(params),
diff --git a/components/policy/test_support/client_storage.cc b/components/policy/test_support/client_storage.cc
index bd6480e..bc37024 100644
--- a/components/policy/test_support/client_storage.cc
+++ b/components/policy/test_support/client_storage.cc
@@ -109,4 +109,11 @@
   return hashes;
 }
 
+std::vector<ClientStorage::ClientInfo> ClientStorage::GetAllClients() {
+  std::vector<ClientStorage::ClientInfo> result;
+  for (const auto& [device_id, client_info] : clients_) {
+    result.push_back(client_info);
+  }
+  return result;
+}
 }  // namespace policy
diff --git a/components/policy/test_support/client_storage.h b/components/policy/test_support/client_storage.h
index 999909eeb..40c72ae4 100644
--- a/components/policy/test_support/client_storage.h
+++ b/components/policy/test_support/client_storage.h
@@ -69,6 +69,9 @@
   std::vector<std::string> GetMatchingStateKeyHashes(uint64_t modulus,
                                                      uint64_t remainder) const;
 
+  // Returns all the clients in the storage.
+  std::vector<ClientInfo> GetAllClients();
+
  private:
   // Key: device ids.
   std::map<std::string, ClientInfo> clients_;
diff --git a/components/policy/test_support/embedded_policy_test_server.cc b/components/policy/test_support/embedded_policy_test_server.cc
index 106a1d6c..8a811b0 100644
--- a/components/policy/test_support/embedded_policy_test_server.cc
+++ b/components/policy/test_support/embedded_policy_test_server.cc
@@ -74,9 +74,8 @@
 const char kInvalidEnrollmentToken[] = "invalid_enrollment_token";
 
 EmbeddedPolicyTestServer::RequestHandler::RequestHandler(
-    ClientStorage* client_storage,
-    PolicyStorage* policy_storage)
-    : client_storage_(client_storage), policy_storage_(policy_storage) {}
+    EmbeddedPolicyTestServer* parent)
+    : parent_(parent) {}
 
 EmbeddedPolicyTestServer::RequestHandler::~RequestHandler() = default;
 
@@ -84,40 +83,28 @@
     : http_server_(EmbeddedTestServer::TYPE_HTTP),
       client_storage_(std::make_unique<ClientStorage>()),
       policy_storage_(std::make_unique<PolicyStorage>()) {
-  RegisterHandler(std::make_unique<RequestHandlerForApiAuthorization>(
-      client_storage_.get(), policy_storage_.get()));
-  RegisterHandler(std::make_unique<RequestHandlerForAutoEnrollment>(
-      client_storage_.get(), policy_storage_.get()));
-  RegisterHandler(std::make_unique<RequestHandlerForCheckAndroidManagement>(
-      client_storage_.get(), policy_storage_.get()));
-  RegisterHandler(std::make_unique<RequestHandlerForChromeDesktopReport>(
-      client_storage_.get(), policy_storage_.get()));
-  RegisterHandler(std::make_unique<RequestHandlerForDeviceAttributeUpdate>(
-      client_storage_.get(), policy_storage_.get()));
+  RegisterHandler(std::make_unique<RequestHandlerForApiAuthorization>(this));
+  RegisterHandler(std::make_unique<RequestHandlerForAutoEnrollment>(this));
   RegisterHandler(
-      std::make_unique<RequestHandlerForDeviceAttributeUpdatePermission>(
-          client_storage_.get(), policy_storage_.get()));
+      std::make_unique<RequestHandlerForCheckAndroidManagement>(this));
+  RegisterHandler(std::make_unique<RequestHandlerForChromeDesktopReport>(this));
   RegisterHandler(
-      std::make_unique<RequestHandlerForDeviceInitialEnrollmentState>(
-          client_storage_.get(), policy_storage_.get()));
-  RegisterHandler(std::make_unique<RequestHandlerForDeviceStateRetrieval>(
-      client_storage_.get(), policy_storage_.get()));
-  RegisterHandler(std::make_unique<RequestHandlerForPolicy>(
-      client_storage_.get(), policy_storage_.get()));
-  RegisterHandler(std::make_unique<RequestHandlerForPsmAutoEnrollment>(
-      client_storage_.get(), policy_storage_.get()));
-  RegisterHandler(std::make_unique<RequestHandlerForRegisterBrowser>(
-      client_storage_.get(), policy_storage_.get()));
-  RegisterHandler(std::make_unique<RequestHandlerForRegisterCertBased>(
-      client_storage_.get(), policy_storage_.get()));
-  RegisterHandler(std::make_unique<RequestHandlerForRegisterDeviceAndUser>(
-      client_storage_.get(), policy_storage_.get()));
-  RegisterHandler(std::make_unique<RequestHandlerForRemoteCommands>(
-      client_storage_.get(), policy_storage_.get()));
-  RegisterHandler(std::make_unique<RequestHandlerForStatusUpload>(
-      client_storage_.get(), policy_storage_.get()));
-  RegisterHandler(std::make_unique<RequestHandlerForUnregister>(
-      client_storage_.get(), policy_storage_.get()));
+      std::make_unique<RequestHandlerForDeviceAttributeUpdate>(this));
+  RegisterHandler(
+      std::make_unique<RequestHandlerForDeviceAttributeUpdatePermission>(this));
+  RegisterHandler(
+      std::make_unique<RequestHandlerForDeviceInitialEnrollmentState>(this));
+  RegisterHandler(
+      std::make_unique<RequestHandlerForDeviceStateRetrieval>(this));
+  RegisterHandler(std::make_unique<RequestHandlerForPolicy>(this));
+  RegisterHandler(std::make_unique<RequestHandlerForPsmAutoEnrollment>(this));
+  RegisterHandler(std::make_unique<RequestHandlerForRegisterBrowser>(this));
+  RegisterHandler(std::make_unique<RequestHandlerForRegisterCertBased>(this));
+  RegisterHandler(
+      std::make_unique<RequestHandlerForRegisterDeviceAndUser>(this));
+  RegisterHandler(std::make_unique<RequestHandlerForRemoteCommands>(this));
+  RegisterHandler(std::make_unique<RequestHandlerForStatusUpload>(this));
+  RegisterHandler(std::make_unique<RequestHandlerForUnregister>(this));
 
   http_server_.RegisterDefaultHandler(base::BindRepeating(
       &EmbeddedPolicyTestServer::HandleRequest, base::Unretained(this)));
@@ -142,8 +129,8 @@
 void EmbeddedPolicyTestServer::ConfigureRequestError(
     const std::string& request_type,
     net::HttpStatusCode error_code) {
-  RegisterHandler(std::make_unique<FailingRequestHandler>(
-      client_storage_.get(), policy_storage_.get(), request_type, error_code));
+  RegisterHandler(
+      std::make_unique<FailingRequestHandler>(this, request_type, error_code));
 }
 
 #if !BUILDFLAG(IS_ANDROID)
@@ -212,4 +199,12 @@
   return LogStatusAndReturn(url, std::move(response));
 }
 
+void EmbeddedPolicyTestServer::ResetPolicyStorage() {
+  policy_storage_ = std::make_unique<PolicyStorage>();
+}
+
+void EmbeddedPolicyTestServer::ResetClientStorage() {
+  client_storage_ = std::make_unique<ClientStorage>();
+}
+
 }  // namespace policy
diff --git a/components/policy/test_support/embedded_policy_test_server.h b/components/policy/test_support/embedded_policy_test_server.h
index 736b7cb7..9c788bd 100644
--- a/components/policy/test_support/embedded_policy_test_server.h
+++ b/components/policy/test_support/embedded_policy_test_server.h
@@ -36,8 +36,7 @@
  public:
   class RequestHandler {
    public:
-    RequestHandler(ClientStorage* client_storage,
-                   PolicyStorage* policy_storage);
+    explicit RequestHandler(EmbeddedPolicyTestServer* parent);
     virtual ~RequestHandler();
 
     // Returns the value associated with the "request_type" query param handled
@@ -49,15 +48,18 @@
     virtual std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
         const net::test_server::HttpRequest& request) = 0;
 
-    const ClientStorage* client_storage() const { return client_storage_; }
-    ClientStorage* client_storage() { return client_storage_; }
+    const ClientStorage* client_storage() const {
+      return parent_->client_storage();
+    }
+    ClientStorage* client_storage() { return parent_->client_storage(); }
 
-    const PolicyStorage* policy_storage() const { return policy_storage_; }
-    PolicyStorage* policy_storage() { return policy_storage_; }
+    const PolicyStorage* policy_storage() const {
+      return parent_->policy_storage();
+    }
+    PolicyStorage* policy_storage() { return parent_->policy_storage(); }
 
    private:
-    raw_ptr<ClientStorage> client_storage_;
-    raw_ptr<PolicyStorage> policy_storage_;
+    const raw_ptr<EmbeddedPolicyTestServer> parent_;
   };
 
   EmbeddedPolicyTestServer();
@@ -84,6 +86,10 @@
   void ConfigureRequestError(const std::string& request_type,
                              net::HttpStatusCode error_code);
 
+  // Resets the policy/client storage to its original state.
+  void ResetPolicyStorage();
+  void ResetClientStorage();
+
 #if !BUILDFLAG(IS_ANDROID)
   // Updates policy selected by |type| and optional |entity_id|. The
   // |raw_policy| is served via an external endpoint. This does not trigger
diff --git a/components/policy/test_support/embedded_policy_test_server_unittest.cc b/components/policy/test_support/embedded_policy_test_server_unittest.cc
index 63da4dad..bc5807b 100644
--- a/components/policy/test_support/embedded_policy_test_server_unittest.cc
+++ b/components/policy/test_support/embedded_policy_test_server_unittest.cc
@@ -38,7 +38,7 @@
 
 class FakeRequestHandler : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  FakeRequestHandler() : RequestHandler(nullptr, nullptr) {}
+  FakeRequestHandler() : RequestHandler(nullptr) {}
   ~FakeRequestHandler() override = default;
 
   std::string RequestType() override { return kFakeRequestType; }
diff --git a/components/policy/test_support/failing_request_handler.cc b/components/policy/test_support/failing_request_handler.cc
index 0c39f976..bdcd483 100644
--- a/components/policy/test_support/failing_request_handler.cc
+++ b/components/policy/test_support/failing_request_handler.cc
@@ -11,11 +11,10 @@
 
 namespace policy {
 
-FailingRequestHandler::FailingRequestHandler(ClientStorage* client_storage,
-                                             PolicyStorage* policy_storage,
+FailingRequestHandler::FailingRequestHandler(EmbeddedPolicyTestServer* parent,
                                              const std::string& request_type,
                                              net::HttpStatusCode error_code)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage),
+    : EmbeddedPolicyTestServer::RequestHandler(parent),
       request_type_(request_type),
       error_code_(error_code) {}
 
diff --git a/components/policy/test_support/failing_request_handler.h b/components/policy/test_support/failing_request_handler.h
index 7b5f284..ef09c3c 100644
--- a/components/policy/test_support/failing_request_handler.h
+++ b/components/policy/test_support/failing_request_handler.h
@@ -13,8 +13,7 @@
 // Handler that always returns specified error code for a given request type.
 class FailingRequestHandler : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  FailingRequestHandler(ClientStorage* client_storage,
-                        PolicyStorage* policy_storage,
+  FailingRequestHandler(EmbeddedPolicyTestServer* parent,
                         const std::string& request_type,
                         net::HttpStatusCode error_code);
   FailingRequestHandler(FailingRequestHandler&& handler) = delete;
diff --git a/components/policy/test_support/request_handler_for_api_authorization.cc b/components/policy/test_support/request_handler_for_api_authorization.cc
index e9e3798..acdb0b0 100644
--- a/components/policy/test_support/request_handler_for_api_authorization.cc
+++ b/components/policy/test_support/request_handler_for_api_authorization.cc
@@ -20,10 +20,8 @@
 namespace policy {
 
 RequestHandlerForApiAuthorization::RequestHandlerForApiAuthorization(
-    ClientStorage* client_storage,
-    PolicyStorage* policy_storage)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage) {
-}
+    EmbeddedPolicyTestServer* parent)
+    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
 
 RequestHandlerForApiAuthorization::~RequestHandlerForApiAuthorization() =
     default;
diff --git a/components/policy/test_support/request_handler_for_api_authorization.h b/components/policy/test_support/request_handler_for_api_authorization.h
index cc230b2..c15ecea4 100644
--- a/components/policy/test_support/request_handler_for_api_authorization.h
+++ b/components/policy/test_support/request_handler_for_api_authorization.h
@@ -13,8 +13,7 @@
 class RequestHandlerForApiAuthorization
     : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  RequestHandlerForApiAuthorization(ClientStorage* client_storage,
-                                    PolicyStorage* policy_storage);
+  explicit RequestHandlerForApiAuthorization(EmbeddedPolicyTestServer* parent);
   RequestHandlerForApiAuthorization(
       RequestHandlerForApiAuthorization&& handler) = delete;
   RequestHandlerForApiAuthorization& operator=(
diff --git a/components/policy/test_support/request_handler_for_auto_enrollment.cc b/components/policy/test_support/request_handler_for_auto_enrollment.cc
index 6c4a505..dcfaa8f9 100644
--- a/components/policy/test_support/request_handler_for_auto_enrollment.cc
+++ b/components/policy/test_support/request_handler_for_auto_enrollment.cc
@@ -32,10 +32,8 @@
 }  // namespace
 
 RequestHandlerForAutoEnrollment::RequestHandlerForAutoEnrollment(
-    ClientStorage* client_storage,
-    PolicyStorage* policy_storage)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage) {
-}
+    EmbeddedPolicyTestServer* parent)
+    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
 
 RequestHandlerForAutoEnrollment::~RequestHandlerForAutoEnrollment() = default;
 
diff --git a/components/policy/test_support/request_handler_for_auto_enrollment.h b/components/policy/test_support/request_handler_for_auto_enrollment.h
index 9e13d65..95b0cda8 100644
--- a/components/policy/test_support/request_handler_for_auto_enrollment.h
+++ b/components/policy/test_support/request_handler_for_auto_enrollment.h
@@ -13,8 +13,7 @@
 class RequestHandlerForAutoEnrollment
     : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  RequestHandlerForAutoEnrollment(ClientStorage* client_storage,
-                                  PolicyStorage* policy_storage);
+  explicit RequestHandlerForAutoEnrollment(EmbeddedPolicyTestServer* parent);
   RequestHandlerForAutoEnrollment(RequestHandlerForAutoEnrollment&& handler) =
       delete;
   RequestHandlerForAutoEnrollment& operator=(
diff --git a/components/policy/test_support/request_handler_for_check_android_management.cc b/components/policy/test_support/request_handler_for_check_android_management.cc
index 45eb5a1..ab584f07 100644
--- a/components/policy/test_support/request_handler_for_check_android_management.cc
+++ b/components/policy/test_support/request_handler_for_check_android_management.cc
@@ -25,10 +25,8 @@
 const char kUnmanagedAuthToken[] = "unmanaged-auth-token";
 
 RequestHandlerForCheckAndroidManagement::
-    RequestHandlerForCheckAndroidManagement(ClientStorage* client_storage,
-                                            PolicyStorage* policy_storage)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage) {
-}
+    RequestHandlerForCheckAndroidManagement(EmbeddedPolicyTestServer* parent)
+    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
 
 RequestHandlerForCheckAndroidManagement::
     ~RequestHandlerForCheckAndroidManagement() = default;
diff --git a/components/policy/test_support/request_handler_for_check_android_management.h b/components/policy/test_support/request_handler_for_check_android_management.h
index c7343d62..32dc2c4 100644
--- a/components/policy/test_support/request_handler_for_check_android_management.h
+++ b/components/policy/test_support/request_handler_for_check_android_management.h
@@ -18,8 +18,8 @@
 class RequestHandlerForCheckAndroidManagement
     : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  RequestHandlerForCheckAndroidManagement(ClientStorage* client_storage,
-                                          PolicyStorage* policy_storage);
+  explicit RequestHandlerForCheckAndroidManagement(
+      EmbeddedPolicyTestServer* parent);
   RequestHandlerForCheckAndroidManagement(
       RequestHandlerForCheckAndroidManagement&& handler) = delete;
   RequestHandlerForCheckAndroidManagement& operator=(
diff --git a/components/policy/test_support/request_handler_for_chrome_desktop_report.cc b/components/policy/test_support/request_handler_for_chrome_desktop_report.cc
index b8102ad4..63aa7d3 100644
--- a/components/policy/test_support/request_handler_for_chrome_desktop_report.cc
+++ b/components/policy/test_support/request_handler_for_chrome_desktop_report.cc
@@ -21,10 +21,8 @@
 namespace policy {
 
 RequestHandlerForChromeDesktopReport::RequestHandlerForChromeDesktopReport(
-    ClientStorage* client_storage,
-    PolicyStorage* policy_storage)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage) {
-}
+    EmbeddedPolicyTestServer* parent)
+    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
 
 RequestHandlerForChromeDesktopReport::~RequestHandlerForChromeDesktopReport() =
     default;
diff --git a/components/policy/test_support/request_handler_for_chrome_desktop_report.h b/components/policy/test_support/request_handler_for_chrome_desktop_report.h
index 15d572c..c1ece19 100644
--- a/components/policy/test_support/request_handler_for_chrome_desktop_report.h
+++ b/components/policy/test_support/request_handler_for_chrome_desktop_report.h
@@ -13,8 +13,8 @@
 class RequestHandlerForChromeDesktopReport
     : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  RequestHandlerForChromeDesktopReport(ClientStorage* client_storage,
-                                       PolicyStorage* policy_storage);
+  explicit RequestHandlerForChromeDesktopReport(
+      EmbeddedPolicyTestServer* parent);
   RequestHandlerForChromeDesktopReport(
       RequestHandlerForChromeDesktopReport&& handler) = delete;
   RequestHandlerForChromeDesktopReport& operator=(
diff --git a/components/policy/test_support/request_handler_for_device_attribute_update.cc b/components/policy/test_support/request_handler_for_device_attribute_update.cc
index 1d98d40..144bc12b 100644
--- a/components/policy/test_support/request_handler_for_device_attribute_update.cc
+++ b/components/policy/test_support/request_handler_for_device_attribute_update.cc
@@ -21,10 +21,8 @@
 namespace policy {
 
 RequestHandlerForDeviceAttributeUpdate::RequestHandlerForDeviceAttributeUpdate(
-    ClientStorage* client_storage,
-    PolicyStorage* policy_storage)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage) {
-}
+    EmbeddedPolicyTestServer* parent)
+    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
 
 RequestHandlerForDeviceAttributeUpdate::
     ~RequestHandlerForDeviceAttributeUpdate() = default;
diff --git a/components/policy/test_support/request_handler_for_device_attribute_update.h b/components/policy/test_support/request_handler_for_device_attribute_update.h
index 36783bf..b1a597a 100644
--- a/components/policy/test_support/request_handler_for_device_attribute_update.h
+++ b/components/policy/test_support/request_handler_for_device_attribute_update.h
@@ -13,8 +13,8 @@
 class RequestHandlerForDeviceAttributeUpdate
     : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  RequestHandlerForDeviceAttributeUpdate(ClientStorage* client_storage,
-                                         PolicyStorage* policy_storage);
+  explicit RequestHandlerForDeviceAttributeUpdate(
+      EmbeddedPolicyTestServer* parent);
   RequestHandlerForDeviceAttributeUpdate(
       RequestHandlerForDeviceAttributeUpdate&& handler) = delete;
   RequestHandlerForDeviceAttributeUpdate& operator=(
diff --git a/components/policy/test_support/request_handler_for_device_attribute_update_permission.cc b/components/policy/test_support/request_handler_for_device_attribute_update_permission.cc
index 4d846b30..a685afc8 100644
--- a/components/policy/test_support/request_handler_for_device_attribute_update_permission.cc
+++ b/components/policy/test_support/request_handler_for_device_attribute_update_permission.cc
@@ -23,10 +23,8 @@
 
 RequestHandlerForDeviceAttributeUpdatePermission::
     RequestHandlerForDeviceAttributeUpdatePermission(
-        ClientStorage* client_storage,
-        PolicyStorage* policy_storage)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage) {
-}
+        EmbeddedPolicyTestServer* parent)
+    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
 
 RequestHandlerForDeviceAttributeUpdatePermission::
     ~RequestHandlerForDeviceAttributeUpdatePermission() = default;
diff --git a/components/policy/test_support/request_handler_for_device_attribute_update_permission.h b/components/policy/test_support/request_handler_for_device_attribute_update_permission.h
index 4ee54f5..2160284 100644
--- a/components/policy/test_support/request_handler_for_device_attribute_update_permission.h
+++ b/components/policy/test_support/request_handler_for_device_attribute_update_permission.h
@@ -13,9 +13,8 @@
 class RequestHandlerForDeviceAttributeUpdatePermission
     : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  RequestHandlerForDeviceAttributeUpdatePermission(
-      ClientStorage* client_storage,
-      PolicyStorage* policy_storage);
+  explicit RequestHandlerForDeviceAttributeUpdatePermission(
+      EmbeddedPolicyTestServer* parent);
   RequestHandlerForDeviceAttributeUpdatePermission(
       RequestHandlerForDeviceAttributeUpdatePermission&& handler) = delete;
   RequestHandlerForDeviceAttributeUpdatePermission& operator=(
diff --git a/components/policy/test_support/request_handler_for_device_initial_enrollment_state.cc b/components/policy/test_support/request_handler_for_device_initial_enrollment_state.cc
index 3e47e31d..fce5693d 100644
--- a/components/policy/test_support/request_handler_for_device_initial_enrollment_state.cc
+++ b/components/policy/test_support/request_handler_for_device_initial_enrollment_state.cc
@@ -22,10 +22,9 @@
 namespace policy {
 
 RequestHandlerForDeviceInitialEnrollmentState::
-    RequestHandlerForDeviceInitialEnrollmentState(ClientStorage* client_storage,
-                                                  PolicyStorage* policy_storage)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage) {
-}
+    RequestHandlerForDeviceInitialEnrollmentState(
+        EmbeddedPolicyTestServer* parent)
+    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
 
 RequestHandlerForDeviceInitialEnrollmentState::
     ~RequestHandlerForDeviceInitialEnrollmentState() = default;
diff --git a/components/policy/test_support/request_handler_for_device_initial_enrollment_state.h b/components/policy/test_support/request_handler_for_device_initial_enrollment_state.h
index 9205a90..8454ced 100644
--- a/components/policy/test_support/request_handler_for_device_initial_enrollment_state.h
+++ b/components/policy/test_support/request_handler_for_device_initial_enrollment_state.h
@@ -13,8 +13,8 @@
 class RequestHandlerForDeviceInitialEnrollmentState
     : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  RequestHandlerForDeviceInitialEnrollmentState(ClientStorage* client_storage,
-                                                PolicyStorage* policy_storage);
+  explicit RequestHandlerForDeviceInitialEnrollmentState(
+      EmbeddedPolicyTestServer* parent);
   RequestHandlerForDeviceInitialEnrollmentState(
       RequestHandlerForDeviceInitialEnrollmentState&& handler) = delete;
   RequestHandlerForDeviceInitialEnrollmentState& operator=(
diff --git a/components/policy/test_support/request_handler_for_device_state_retrieval.cc b/components/policy/test_support/request_handler_for_device_state_retrieval.cc
index fb5a929..990129a9 100644
--- a/components/policy/test_support/request_handler_for_device_state_retrieval.cc
+++ b/components/policy/test_support/request_handler_for_device_state_retrieval.cc
@@ -22,10 +22,8 @@
 namespace policy {
 
 RequestHandlerForDeviceStateRetrieval::RequestHandlerForDeviceStateRetrieval(
-    ClientStorage* client_storage,
-    PolicyStorage* policy_storage)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage) {
-}
+    EmbeddedPolicyTestServer* parent)
+    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
 
 RequestHandlerForDeviceStateRetrieval::
     ~RequestHandlerForDeviceStateRetrieval() = default;
diff --git a/components/policy/test_support/request_handler_for_device_state_retrieval.h b/components/policy/test_support/request_handler_for_device_state_retrieval.h
index c5765a3..1314586 100644
--- a/components/policy/test_support/request_handler_for_device_state_retrieval.h
+++ b/components/policy/test_support/request_handler_for_device_state_retrieval.h
@@ -13,8 +13,8 @@
 class RequestHandlerForDeviceStateRetrieval
     : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  RequestHandlerForDeviceStateRetrieval(ClientStorage* client_storage,
-                                        PolicyStorage* policy_storage);
+  explicit RequestHandlerForDeviceStateRetrieval(
+      EmbeddedPolicyTestServer* parent);
   RequestHandlerForDeviceStateRetrieval(
       RequestHandlerForDeviceStateRetrieval&& handler) = delete;
   RequestHandlerForDeviceStateRetrieval& operator=(
diff --git a/components/policy/test_support/request_handler_for_policy.cc b/components/policy/test_support/request_handler_for_policy.cc
index dbc94bb..8089159 100644
--- a/components/policy/test_support/request_handler_for_policy.cc
+++ b/components/policy/test_support/request_handler_for_policy.cc
@@ -26,10 +26,9 @@
 
 namespace policy {
 
-RequestHandlerForPolicy::RequestHandlerForPolicy(ClientStorage* client_storage,
-                                                 PolicyStorage* policy_storage)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage) {
-}
+RequestHandlerForPolicy::RequestHandlerForPolicy(
+    EmbeddedPolicyTestServer* parent)
+    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
 
 RequestHandlerForPolicy::~RequestHandlerForPolicy() = default;
 
@@ -176,7 +175,7 @@
   policy_data.set_device_id(client_info.device_id);
   policy_data.set_username(
       client_info.username.value_or(policy_storage()->policy_user().empty()
-                                        ? "username@example.com"
+                                        ? kDefaultUsername
                                         : policy_storage()->policy_user()));
   policy_data.set_policy_invalidation_topic(
       policy_storage()->policy_invalidation_topic());
diff --git a/components/policy/test_support/request_handler_for_policy.h b/components/policy/test_support/request_handler_for_policy.h
index e8b2594..faeec935 100644
--- a/components/policy/test_support/request_handler_for_policy.h
+++ b/components/policy/test_support/request_handler_for_policy.h
@@ -18,12 +18,13 @@
 
 namespace policy {
 
+inline constexpr char kDefaultUsername[] = "username@example.com";
+
 // Handler for request type `policy`.
 class RequestHandlerForPolicy
     : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  RequestHandlerForPolicy(ClientStorage* client_storage,
-                          PolicyStorage* policy_storage);
+  explicit RequestHandlerForPolicy(EmbeddedPolicyTestServer* parent);
   RequestHandlerForPolicy(RequestHandlerForPolicy&& handler) = delete;
   RequestHandlerForPolicy& operator=(RequestHandlerForPolicy&& handler) =
       delete;
diff --git a/components/policy/test_support/request_handler_for_psm_auto_enrollment.cc b/components/policy/test_support/request_handler_for_psm_auto_enrollment.cc
index df820f83..01c41d39 100644
--- a/components/policy/test_support/request_handler_for_psm_auto_enrollment.cc
+++ b/components/policy/test_support/request_handler_for_psm_auto_enrollment.cc
@@ -31,10 +31,8 @@
 }  // namespace
 
 RequestHandlerForPsmAutoEnrollment::RequestHandlerForPsmAutoEnrollment(
-    ClientStorage* client_storage,
-    PolicyStorage* policy_storage)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage) {
-}
+    EmbeddedPolicyTestServer* parent)
+    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
 
 RequestHandlerForPsmAutoEnrollment::~RequestHandlerForPsmAutoEnrollment() =
     default;
diff --git a/components/policy/test_support/request_handler_for_psm_auto_enrollment.h b/components/policy/test_support/request_handler_for_psm_auto_enrollment.h
index 23b732af..e078a27 100644
--- a/components/policy/test_support/request_handler_for_psm_auto_enrollment.h
+++ b/components/policy/test_support/request_handler_for_psm_auto_enrollment.h
@@ -18,8 +18,7 @@
     kPirResponseHasNoMembership = 2,
   };
 
-  RequestHandlerForPsmAutoEnrollment(ClientStorage* client_storage,
-                                     PolicyStorage* policy_storage);
+  explicit RequestHandlerForPsmAutoEnrollment(EmbeddedPolicyTestServer* parent);
   RequestHandlerForPsmAutoEnrollment(
       RequestHandlerForPsmAutoEnrollment&& handler) = delete;
   RequestHandlerForPsmAutoEnrollment& operator=(
diff --git a/components/policy/test_support/request_handler_for_register_browser.cc b/components/policy/test_support/request_handler_for_register_browser.cc
index 04426d7a..4b091c0 100644
--- a/components/policy/test_support/request_handler_for_register_browser.cc
+++ b/components/policy/test_support/request_handler_for_register_browser.cc
@@ -22,10 +22,8 @@
 namespace policy {
 
 RequestHandlerForRegisterBrowser::RequestHandlerForRegisterBrowser(
-    ClientStorage* client_storage,
-    PolicyStorage* policy_storage)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage) {
-}
+    EmbeddedPolicyTestServer* parent)
+    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
 
 RequestHandlerForRegisterBrowser::~RequestHandlerForRegisterBrowser() = default;
 
diff --git a/components/policy/test_support/request_handler_for_register_browser.h b/components/policy/test_support/request_handler_for_register_browser.h
index 741761b..5dff54d 100644
--- a/components/policy/test_support/request_handler_for_register_browser.h
+++ b/components/policy/test_support/request_handler_for_register_browser.h
@@ -13,8 +13,7 @@
 class RequestHandlerForRegisterBrowser
     : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  RequestHandlerForRegisterBrowser(ClientStorage* client_storage,
-                                   PolicyStorage* policy_storage);
+  explicit RequestHandlerForRegisterBrowser(EmbeddedPolicyTestServer* parent);
   RequestHandlerForRegisterBrowser(RequestHandlerForRegisterBrowser&& handler) =
       delete;
   RequestHandlerForRegisterBrowser& operator=(
diff --git a/components/policy/test_support/request_handler_for_register_cert_based.cc b/components/policy/test_support/request_handler_for_register_cert_based.cc
index eded203..81c9d95 100644
--- a/components/policy/test_support/request_handler_for_register_cert_based.cc
+++ b/components/policy/test_support/request_handler_for_register_cert_based.cc
@@ -28,9 +28,8 @@
 namespace policy {
 
 RequestHandlerForRegisterCertBased::RequestHandlerForRegisterCertBased(
-    ClientStorage* client_storage,
-    PolicyStorage* policy_storage)
-    : RequestHandlerForRegisterDeviceAndUser(client_storage, policy_storage) {}
+    EmbeddedPolicyTestServer* parent)
+    : RequestHandlerForRegisterDeviceAndUser(parent) {}
 
 RequestHandlerForRegisterCertBased::~RequestHandlerForRegisterCertBased() =
     default;
diff --git a/components/policy/test_support/request_handler_for_register_cert_based.h b/components/policy/test_support/request_handler_for_register_cert_based.h
index 2810842..5f464ed 100644
--- a/components/policy/test_support/request_handler_for_register_cert_based.h
+++ b/components/policy/test_support/request_handler_for_register_cert_based.h
@@ -14,8 +14,7 @@
 class RequestHandlerForRegisterCertBased
     : public RequestHandlerForRegisterDeviceAndUser {
  public:
-  RequestHandlerForRegisterCertBased(ClientStorage* client_storage,
-                                     PolicyStorage* policy_storage);
+  explicit RequestHandlerForRegisterCertBased(EmbeddedPolicyTestServer* parent);
   RequestHandlerForRegisterCertBased(
       RequestHandlerForRegisterCertBased&& handler) = delete;
   RequestHandlerForRegisterCertBased& operator=(
diff --git a/components/policy/test_support/request_handler_for_register_device_and_user.cc b/components/policy/test_support/request_handler_for_register_device_and_user.cc
index 85118dd..53e9759 100644
--- a/components/policy/test_support/request_handler_for_register_device_and_user.cc
+++ b/components/policy/test_support/request_handler_for_register_device_and_user.cc
@@ -107,10 +107,8 @@
 }  // namespace
 
 RequestHandlerForRegisterDeviceAndUser::RequestHandlerForRegisterDeviceAndUser(
-    ClientStorage* client_storage,
-    PolicyStorage* policy_storage)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage) {
-}
+    EmbeddedPolicyTestServer* parent)
+    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
 
 RequestHandlerForRegisterDeviceAndUser::
     ~RequestHandlerForRegisterDeviceAndUser() = default;
diff --git a/components/policy/test_support/request_handler_for_register_device_and_user.h b/components/policy/test_support/request_handler_for_register_device_and_user.h
index 1aba73a..49c9b1c7 100644
--- a/components/policy/test_support/request_handler_for_register_device_and_user.h
+++ b/components/policy/test_support/request_handler_for_register_device_and_user.h
@@ -17,8 +17,8 @@
 class RequestHandlerForRegisterDeviceAndUser
     : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  RequestHandlerForRegisterDeviceAndUser(ClientStorage* client_storage,
-                                         PolicyStorage* policy_storage);
+  explicit RequestHandlerForRegisterDeviceAndUser(
+      EmbeddedPolicyTestServer* parent);
   RequestHandlerForRegisterDeviceAndUser(
       RequestHandlerForRegisterDeviceAndUser&& handler) = delete;
   RequestHandlerForRegisterDeviceAndUser& operator=(
diff --git a/components/policy/test_support/request_handler_for_remote_commands.cc b/components/policy/test_support/request_handler_for_remote_commands.cc
index e719c1a..0d8f0459 100644
--- a/components/policy/test_support/request_handler_for_remote_commands.cc
+++ b/components/policy/test_support/request_handler_for_remote_commands.cc
@@ -21,10 +21,8 @@
 namespace policy {
 
 RequestHandlerForRemoteCommands::RequestHandlerForRemoteCommands(
-    ClientStorage* client_storage,
-    PolicyStorage* policy_storage)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage) {
-}
+    EmbeddedPolicyTestServer* parent)
+    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
 
 RequestHandlerForRemoteCommands::~RequestHandlerForRemoteCommands() = default;
 
diff --git a/components/policy/test_support/request_handler_for_remote_commands.h b/components/policy/test_support/request_handler_for_remote_commands.h
index ceca731..0f98797 100644
--- a/components/policy/test_support/request_handler_for_remote_commands.h
+++ b/components/policy/test_support/request_handler_for_remote_commands.h
@@ -13,8 +13,7 @@
 class RequestHandlerForRemoteCommands
     : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  RequestHandlerForRemoteCommands(ClientStorage* client_storage,
-                                  PolicyStorage* policy_storage);
+  explicit RequestHandlerForRemoteCommands(EmbeddedPolicyTestServer* parent);
   RequestHandlerForRemoteCommands(RequestHandlerForRemoteCommands&& handler) =
       delete;
   RequestHandlerForRemoteCommands& operator=(
diff --git a/components/policy/test_support/request_handler_for_status_upload.cc b/components/policy/test_support/request_handler_for_status_upload.cc
index 32679ac..30a534d 100644
--- a/components/policy/test_support/request_handler_for_status_upload.cc
+++ b/components/policy/test_support/request_handler_for_status_upload.cc
@@ -21,10 +21,8 @@
 namespace policy {
 
 RequestHandlerForStatusUpload::RequestHandlerForStatusUpload(
-    ClientStorage* client_storage,
-    PolicyStorage* policy_storage)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage) {
-}
+    EmbeddedPolicyTestServer* parent)
+    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
 
 RequestHandlerForStatusUpload::~RequestHandlerForStatusUpload() = default;
 
diff --git a/components/policy/test_support/request_handler_for_status_upload.h b/components/policy/test_support/request_handler_for_status_upload.h
index f48f539c..3f10a1c 100644
--- a/components/policy/test_support/request_handler_for_status_upload.h
+++ b/components/policy/test_support/request_handler_for_status_upload.h
@@ -13,8 +13,7 @@
 class RequestHandlerForStatusUpload
     : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  RequestHandlerForStatusUpload(ClientStorage* client_storage,
-                                PolicyStorage* policy_storage);
+  explicit RequestHandlerForStatusUpload(EmbeddedPolicyTestServer* parent);
   RequestHandlerForStatusUpload(RequestHandlerForStatusUpload&& handler) =
       delete;
   RequestHandlerForStatusUpload& operator=(
diff --git a/components/policy/test_support/request_handler_for_unregister.cc b/components/policy/test_support/request_handler_for_unregister.cc
index ff8360d..749d797 100644
--- a/components/policy/test_support/request_handler_for_unregister.cc
+++ b/components/policy/test_support/request_handler_for_unregister.cc
@@ -20,10 +20,8 @@
 namespace policy {
 
 RequestHandlerForUnregister::RequestHandlerForUnregister(
-    ClientStorage* client_storage,
-    PolicyStorage* policy_storage)
-    : EmbeddedPolicyTestServer::RequestHandler(client_storage, policy_storage) {
-}
+    EmbeddedPolicyTestServer* parent)
+    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
 
 RequestHandlerForUnregister::~RequestHandlerForUnregister() = default;
 
diff --git a/components/policy/test_support/request_handler_for_unregister.h b/components/policy/test_support/request_handler_for_unregister.h
index 19aedfb2..6934c8d 100644
--- a/components/policy/test_support/request_handler_for_unregister.h
+++ b/components/policy/test_support/request_handler_for_unregister.h
@@ -13,8 +13,7 @@
 class RequestHandlerForUnregister
     : public EmbeddedPolicyTestServer::RequestHandler {
  public:
-  RequestHandlerForUnregister(ClientStorage* client_storage,
-                              PolicyStorage* policy_storage);
+  explicit RequestHandlerForUnregister(EmbeddedPolicyTestServer* parent);
   RequestHandlerForUnregister(RequestHandlerForUnregister&& handler) = delete;
   RequestHandlerForUnregister& operator=(
       RequestHandlerForUnregister&& handler) = delete;
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index 1513d6d6..d7f2f70 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -3769,8 +3769,7 @@
           frame_entry->committed_origin(),
           // The correct storage key will be computed before committing the
           // navigation.
-          blink::StorageKey(), network::mojom::WebSandboxFlags(),
-          override_user_agent, params.redirect_chain,
+          blink::StorageKey(), override_user_agent, params.redirect_chain,
           std::vector<network::mojom::URLResponseHeadPtr>(),
           std::vector<net::RedirectInfo>(), params.post_content_type,
           common_params->url, common_params->method,
diff --git a/content/browser/renderer_host/navigation_entry_impl.cc b/content/browser/renderer_host/navigation_entry_impl.cc
index 0529006..146640e 100644
--- a/content/browser/renderer_host/navigation_entry_impl.cc
+++ b/content/browser/renderer_host/navigation_entry_impl.cc
@@ -890,8 +890,7 @@
           origin_to_commit,
           // The correct storage key will be computed before committing the
           // navigation.
-          blink::StorageKey(), network::mojom::WebSandboxFlags(),
-          GetIsOverridingUserAgent(), redirects,
+          blink::StorageKey(), GetIsOverridingUserAgent(), redirects,
           std::vector<network::mojom::URLResponseHeadPtr>(),
           std::vector<net::RedirectInfo>(), std::string(), original_url,
           original_method, GetCanLoadLocalResources(),
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index c8b7a36..acf488e 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -1181,8 +1181,7 @@
           absl::nullopt,
           // The correct storage key will be computed before committing the
           // navigation.
-          blink::StorageKey(), network::mojom::WebSandboxFlags(),
-          override_user_agent,
+          blink::StorageKey(), override_user_agent,
           /*redirects=*/std::vector<GURL>(),
           /*redirect_response=*/
           std::vector<network::mojom::URLResponseHeadPtr>(),
@@ -1314,8 +1313,7 @@
           origin,
           // The correct storage key is computed right after creating the
           // NavigationRequest below.
-          blink::StorageKey(), network::mojom::WebSandboxFlags(),
-          is_overriding_user_agent, redirects,
+          blink::StorageKey(), is_overriding_user_agent, redirects,
           std::vector<network::mojom::URLResponseHeadPtr>(),
           std::vector<net::RedirectInfo>(),
           std::string() /* redirect_response */, original_url,
@@ -7452,16 +7450,11 @@
   policy_container_builder_->ComputePolicies(
       url, IsMhtmlOrSubframe(), commit_params_->frame_policy.sandbox_flags,
       is_anonymous());
-
-  commit_params_->sandbox_flags =
-      policy_container_builder_->FinalPolicies().sandbox_flags;
 }
 
 void NavigationRequest::ComputePoliciesToCommitForError() {
   policy_container_builder_->ComputePoliciesForError(
       IsMhtmlOrSubframe(), commit_params_->frame_policy.sandbox_flags);
-  commit_params_->sandbox_flags =
-      policy_container_builder_->FinalPolicies().sandbox_flags;
 }
 
 void NavigationRequest::CheckStateTransition(NavigationState state) const {
diff --git a/content/browser/renderer_host/policy_container_host.cc b/content/browser/renderer_host/policy_container_host.cc
index e3c544f..22964658 100644
--- a/content/browser/renderer_host/policy_container_host.cc
+++ b/content/browser/renderer_host/policy_container_host.cc
@@ -223,7 +223,7 @@
           policies_.cross_origin_embedder_policy.value,
           policies_.referrer_policy,
           mojo::Clone(policies_.content_security_policies),
-          policies_.is_anonymous),
+          policies_.is_anonymous, policies_.sandbox_flags),
       std::move(remote));
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc
index 6e6955a7..43dbbac 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -412,6 +412,9 @@
   if (view == last_mouse_down_target_)
     last_mouse_down_target_ = nullptr;
 
+  if (view == last_emulated_event_root_view_)
+    last_emulated_event_root_view_ = nullptr;
+
   event_targeter_->ViewWillBeDestroyed(view);
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.h b/content/browser/renderer_host/render_widget_host_input_event_router.h
index 087889de..a8c7da7a 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.h
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -379,8 +379,7 @@
 
   // Tracked for the purpose of providing a root_view when dispatching emulated
   // touch/gesture events.
-  raw_ptr<RenderWidgetHostViewBase, DanglingUntriaged>
-      last_emulated_event_root_view_;
+  raw_ptr<RenderWidgetHostViewBase> last_emulated_event_root_view_;
 
   // Used to send a GSE with proper source device to terminate scroll bubbling
   // whenever needed.
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
index 7ff5283..e526731 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
@@ -187,7 +187,8 @@
 // resizes the nested widget.
 // See https://crbug.com/726743 and https://crbug.com/1050635.
 // TODO(crbug.com/1315346): Flaky on Android and Linux.
-#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX)
+// TODO(crbug.com/1341838): Flaky on Mac (Sheriff 2022-07-04)
+#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
 #define MAYBE_VisualPropertiesPropagation_VisibleViewportSize \
   DISABLED_VisualPropertiesPropagation_VisibleViewportSize
 #else
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index 8a193bf..95735cf 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -780,7 +780,6 @@
       base::TimeTicks() /* input_start */,
       network::mojom::RequestDestination::kDocument);
   auto commit_params = blink::CreateCommitNavigationParams();
-  commit_params->sandbox_flags = network::mojom::WebSandboxFlags::kNone;
   TestRenderFrame* frame = static_cast<TestRenderFrame*>(GetMainRenderFrame());
   FrameLoadWaiter waiter(frame);
   frame->Navigate(std::move(common_params), std::move(commit_params));
@@ -917,7 +916,6 @@
   commit_params->pending_history_list_offset = pending_offset;
   commit_params->current_history_list_offset = webview->HistoryBackListCount();
   commit_params->current_history_list_length = history_list_length;
-  commit_params->sandbox_flags = network::mojom::WebSandboxFlags::kNone;
 
   auto* frame = static_cast<TestRenderFrame*>(GetMainRenderFrame());
   FrameLoadWaiter waiter(frame);
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 40d5e5e5..f40e6c53 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -987,7 +987,6 @@
         commit_params.origin_to_commit.value();
   }
   navigation_params->storage_key = std::move(commit_params.storage_key);
-  navigation_params->sandbox_flags = commit_params.sandbox_flags;
   navigation_params->frame_policy = commit_params.frame_policy;
 
   if (common_params.navigation_type == blink::mojom::NavigationType::RESTORE) {
@@ -1070,6 +1069,7 @@
           ToWebContentSecurityPolicies(
               std::move(in->policies->content_security_policies)),
           in->policies->is_anonymous,
+          in->policies->sandbox_flags,
       },
       std::move(in->remote));
 }
@@ -5993,7 +5993,6 @@
 
   auto navigation_params = std::make_unique<WebNavigationParams>();
   navigation_params->url = base_url;
-  navigation_params->sandbox_flags = network::mojom::WebSandboxFlags::kNone;
   WebNavigationParams::FillStaticResponse(navigation_params.get(), "text/html",
                                           WebString::FromUTF8(text_encoding),
                                           html);
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index a1fb20a..dbd90c2e 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -260,7 +260,6 @@
 blink::mojom::CommitNavigationParamsPtr DummyCommitNavigationParams() {
   blink::mojom::CommitNavigationParamsPtr params =
       blink::CreateCommitNavigationParams();
-  params->sandbox_flags = network::mojom::WebSandboxFlags::kNone;
   return params;
 }
 
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index 2d54bf8..be0d2521 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -359,6 +359,10 @@
           navigation_params.get(), blink::WebString::FromUTF8(mime_type),
           blink::WebString::FromUTF8(charset), data);
     }
+
+    navigation_params->policy_container->policies.sandbox_flags =
+        navigation_params->frame_policy->sandbox_flags;
+
     frame_->CommitNavigation(std::move(navigation_params),
                              nullptr /* extra_data */);
     return;
diff --git a/google_apis/gcm/engine/registration_request.cc b/google_apis/gcm/engine/registration_request.cc
index f32c02f..0b86337a 100644
--- a/google_apis/gcm/engine/registration_request.cc
+++ b/google_apis/gcm/engine/registration_request.cc
@@ -9,6 +9,8 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/debug/crash_logging.h"
+#include "base/debug/dump_without_crashing.h"
 #include "base/location.h"
 #include "base/metrics/histogram.h"
 #include "base/strings/string_number_conversions.h"
@@ -195,7 +197,8 @@
   url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
       url_loader_factory_.get(),
       base::BindOnce(&RegistrationRequest::OnURLLoadComplete,
-                     base::Unretained(this), url_loader_.get()));
+                     base::Unretained(this), std::move(body),
+                     url_loader_.get()));
 }
 
 void RegistrationRequest::BuildRequestHeaders(
@@ -240,6 +243,7 @@
 }
 
 RegistrationRequest::Status RegistrationRequest::ParseResponse(
+    const std::string& request_body,
     const network::SimpleURLLoader* source,
     std::unique_ptr<std::string> body,
     std::string* token) {
@@ -262,7 +266,20 @@
     std::string error =
         response.substr(error_pos + std::size(kErrorPrefix) - 1);
     LOG(ERROR) << "Registration response error message: " << error;
-    return GetStatusFromError(error);
+    RegistrationRequest::Status status = GetStatusFromError(error);
+
+    // TODO(crbug.com/1327973): Temporarily log additional information for
+    // INVALID_SENDER errors. Remove once the investigation is complete!
+    if (status == RegistrationRequest::Status::INVALID_SENDER) {
+      SCOPED_CRASH_KEY_STRING32("gcm_registration", "url",
+                                source->GetFinalURL().spec());
+      SCOPED_CRASH_KEY_STRING32("gcm_registration", "request_body",
+                                request_body);
+      SCOPED_CRASH_KEY_STRING32("gcm_registration", "response_body", response);
+      base::debug::DumpWithoutCrashing(FROM_HERE,
+                                       /*time_between_dumps=*/base::Hours(12));
+    }
+    return status;
   }
 
   // Can't even get any header info.
@@ -290,10 +307,11 @@
 }
 
 void RegistrationRequest::OnURLLoadComplete(
+    const std::string& request_body,
     const network::SimpleURLLoader* source,
     std::unique_ptr<std::string> body) {
   std::string token;
-  Status status = ParseResponse(source, std::move(body), &token);
+  Status status = ParseResponse(request_body, source, std::move(body), &token);
   recorder_->RecordRegistrationResponse(request_info_.app_id(),
                                         source_to_record_, status);
 
diff --git a/google_apis/gcm/engine/registration_request.h b/google_apis/gcm/engine/registration_request.h
index 291819d..ca753ad 100644
--- a/google_apis/gcm/engine/registration_request.h
+++ b/google_apis/gcm/engine/registration_request.h
@@ -133,7 +133,8 @@
   void Start();
 
   // Invoked from SimpleURLLoader.
-  void OnURLLoadComplete(const network::SimpleURLLoader* source,
+  void OnURLLoadComplete(const std::string& request_body,
+                         const network::SimpleURLLoader* source,
                          std::unique_ptr<std::string> body);
 
  private:
@@ -145,7 +146,8 @@
 
   // Parse the response returned by the URL loader into token, and returns the
   // status.
-  Status ParseResponse(const network::SimpleURLLoader* source,
+  Status ParseResponse(const std::string& request_body,
+                       const network::SimpleURLLoader* source,
                        std::unique_ptr<std::string> body,
                        std::string* token);
 
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_color_space_metadata.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_color_space_metadata.txt
deleted file mode 100644
index e0a0c7f..0000000
--- a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_color_space_metadata.txt
+++ /dev/null
@@ -1,62 +0,0 @@
-Name
-
-    CHROMIUM_color_space_metadata
-
-Name Strings
-
-    GL_CHROMIUM_color_space_metadata
-
-Contributors
-
-    John Bauman, Google
-    Sunny Sachanandani, Google
-
-Contact
-
-    Sunny Sachanandani, Google (sunnyps 'at' google.com)
-
-Status
-
-    In Progress
-
-Version
-
-    Last Modified Date: October 6, 2017
-    Version:            1
-
-Number
-
-    OpenGL ES Extension #???
-
-Dependencies
-
-    This extension is written against the OpenGL ES 2.0 Specification.
-
-Overview
-
-    This allows clients to specify color space metadata for a texture. The color
-    space may be passed to the windowing system if the texture is used as an
-    overlay.
-
-New Tokens
-
-
-New Procedures and Functions
-
-    The command
-
-        void SetColorSpaceMetadata(GLuint texture_id, ColorSpace color_space)
-
-    specifies the color space for the given texture.
-
-Errors
-
-    A context lost will result when this call fails, either because of an
-    invalid parameter value or because of a runtime error such as an out of
-    memory condition.
-
-Revision History
-
-    Rev.    Date      Author     Changes
-    ----  ----------- ---------  ----------------------------------------
-      1   23 Oct 2017 sunnyps    Initial revision
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h
index 3051102f..e184ea5e 100644
--- a/gpu/GLES2/gl2chromium_autogen.h
+++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -354,8 +354,6 @@
   GLES2_GET_FUN(UnlockDiscardableTextureCHROMIUM)
 #define glLockDiscardableTextureCHROMIUM \
   GLES2_GET_FUN(LockDiscardableTextureCHROMIUM)
-#define glSetColorSpaceMetadataCHROMIUM \
-  GLES2_GET_FUN(SetColorSpaceMetadataCHROMIUM)
 #define glWindowRectanglesEXT GLES2_GET_FUN(WindowRectanglesEXT)
 #define glCreateGpuFenceCHROMIUM GLES2_GET_FUN(CreateGpuFenceCHROMIUM)
 #define glCreateClientGpuFenceCHROMIUM \
diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h
index 5d5c5108..f214691 100644
--- a/gpu/GLES2/gl2extchromium.h
+++ b/gpu/GLES2/gl2extchromium.h
@@ -701,17 +701,6 @@
 #define GL_TEXTURE_FILTERING_HINT_CHROMIUM 0x8AF0
 #endif /* GL_CHROMIUM_texture_filtering_hint */
 
-#ifndef GL_CHROMIUM_color_space_metadata
-#define GL_CHROMIUM_color_space_metadata 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY
-glSetColorSpaceMetadataCHROMIUM(GLuint texture_id, GLcolorSpace color_space);
-#endif
-typedef void(GL_APIENTRYP PFNGLSETCOLORSPACEMETADATACHROMIUM)(
-    GLuint texture_id,
-    GLcolorSpace color_space);
-#endif /* GL_CHROMIUM_color_space_metadata */
-
 #ifndef GL_QUERY_RESULT_AVAILABLE_NO_FLUSH_CHROMIUM_EXT
 #define GL_QUERY_RESULT_AVAILABLE_NO_FLUSH_CHROMIUM_EXT 0x8868
 #endif
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 21ff785c..95bc02a82 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -3939,14 +3939,6 @@
     'client_test': False,
     'extension': True,
   },
-  'SetColorSpaceMetadataCHROMIUM': {
-    'type': 'Custom',
-    'impl_func': False,
-    'client_test': False,
-    'cmd_args': 'GLuint texture_id, GLuint shm_id, GLuint shm_offset, '
-                'GLsizei color_space_size',
-    'extension': 'CHROMIUM_color_space_metadata',
-  },
   'WindowRectanglesEXT': {
     'type': 'PUTn',
     'count': 4,
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index 161077a..c44bf12b 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -1612,10 +1612,6 @@
 bool GL_APIENTRY GLES2LockDiscardableTextureCHROMIUM(GLuint texture_id) {
   return gles2::GetGLContext()->LockDiscardableTextureCHROMIUM(texture_id);
 }
-void GL_APIENTRY GLES2SetColorSpaceMetadataCHROMIUM(GLuint texture_id,
-                                                    GLcolorSpace color_space) {
-  gles2::GetGLContext()->SetColorSpaceMetadataCHROMIUM(texture_id, color_space);
-}
 void GL_APIENTRY GLES2WindowRectanglesEXT(GLenum mode,
                                           GLsizei count,
                                           const GLint* box) {
@@ -3006,10 +3002,6 @@
             glLockDiscardableTextureCHROMIUM),
     },
     {
-        "glSetColorSpaceMetadataCHROMIUM",
-        reinterpret_cast<GLES2FunctionPointer>(glSetColorSpaceMetadataCHROMIUM),
-    },
-    {
         "glWindowRectanglesEXT",
         reinterpret_cast<GLES2FunctionPointer>(glWindowRectanglesEXT),
     },
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index 14ab09a..cf7ca53 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -3075,17 +3075,6 @@
   }
 }
 
-void SetColorSpaceMetadataCHROMIUM(GLuint texture_id,
-                                   GLuint shm_id,
-                                   GLuint shm_offset,
-                                   GLsizei color_space_size) {
-  gles2::cmds::SetColorSpaceMetadataCHROMIUM* c =
-      GetCmdSpace<gles2::cmds::SetColorSpaceMetadataCHROMIUM>();
-  if (c) {
-    c->Init(texture_id, shm_id, shm_offset, color_space_size);
-  }
-}
-
 void WindowRectanglesEXTImmediate(GLenum mode,
                                   GLsizei count,
                                   const GLint* box) {
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 0cfb87e..5c61920b 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -5589,33 +5589,6 @@
   return GL_NO_ERROR;
 }
 
-void GLES2Implementation::SetColorSpaceMetadataCHROMIUM(
-    GLuint texture_id,
-    GLcolorSpace color_space) {
-#if defined(__native_client__)
-  // Including gfx::ColorSpace would bring Skia and a lot of other code into
-  // NaCl's IRT.
-  SetGLError(GL_INVALID_VALUE, "GLES2::SetColorSpaceMetadataCHROMIUM",
-             "not supported");
-#else
-  gfx::ColorSpace gfx_color_space;
-  if (color_space)
-    gfx_color_space = *reinterpret_cast<const gfx::ColorSpace*>(color_space);
-  base::Pickle color_space_data;
-  IPC::ParamTraits<gfx::ColorSpace>::Write(&color_space_data, gfx_color_space);
-  ScopedTransferBufferPtr buffer(color_space_data.size(), helper_,
-                                 transfer_buffer_);
-  if (!buffer.valid() || buffer.size() < color_space_data.size()) {
-    SetGLError(GL_OUT_OF_MEMORY, "GLES2::SetColorSpaceMetadataCHROMIUM",
-               "out of memory");
-    return;
-  }
-  memcpy(buffer.address(), color_space_data.data(), color_space_data.size());
-  helper_->SetColorSpaceMetadataCHROMIUM(
-      texture_id, buffer.shm_id(), buffer.offset(), color_space_data.size());
-#endif
-}
-
 GLboolean GLES2Implementation::EnableFeatureCHROMIUM(const char* feature) {
   GPU_CLIENT_SINGLE_THREAD_CHECK();
   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableFeatureCHROMIUM("
@@ -5961,8 +5934,7 @@
     ScopedTransferBufferPtr buffer(color_space_data.size(), helper_,
                                    transfer_buffer_);
     if (!buffer.valid() || buffer.size() < color_space_data.size()) {
-      SetGLError(GL_OUT_OF_MEMORY, "GLES2::SetColorSpaceMetadataCHROMIUM",
-                 "out of memory");
+      SetGLError(GL_OUT_OF_MEMORY, "GLES2::ResizeCHROMIUM", "out of memory");
       return;
     }
     memcpy(buffer.address(), color_space_data.data(), color_space_data.size());
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 72cba99e..2bab658d 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -1136,9 +1136,6 @@
 
 bool LockDiscardableTextureCHROMIUM(GLuint texture_id) override;
 
-void SetColorSpaceMetadataCHROMIUM(GLuint texture_id,
-                                   GLcolorSpace color_space) override;
-
 void WindowRectanglesEXT(GLenum mode, GLsizei count, const GLint* box) override;
 
 GLuint CreateGpuFenceCHROMIUM() override;
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h
index f963eca..68c974c 100644
--- a/gpu/command_buffer/client/gles2_interface_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -841,8 +841,6 @@
 virtual void InitializeDiscardableTextureCHROMIUM(GLuint texture_id) = 0;
 virtual void UnlockDiscardableTextureCHROMIUM(GLuint texture_id) = 0;
 virtual bool LockDiscardableTextureCHROMIUM(GLuint texture_id) = 0;
-virtual void SetColorSpaceMetadataCHROMIUM(GLuint texture_id,
-                                           GLcolorSpace color_space) = 0;
 virtual void WindowRectanglesEXT(GLenum mode,
                                  GLsizei count,
                                  const GLint* box) = 0;
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
index f2df4f1c..5fb92ea 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -817,8 +817,6 @@
 void InitializeDiscardableTextureCHROMIUM(GLuint texture_id) override;
 void UnlockDiscardableTextureCHROMIUM(GLuint texture_id) override;
 bool LockDiscardableTextureCHROMIUM(GLuint texture_id) override;
-void SetColorSpaceMetadataCHROMIUM(GLuint texture_id,
-                                   GLcolorSpace color_space) override;
 void WindowRectanglesEXT(GLenum mode, GLsizei count, const GLint* box) override;
 GLuint CreateGpuFenceCHROMIUM() override;
 GLuint CreateClientGpuFenceCHROMIUM(ClientGpuFence source) override;
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
index c02dd5b..01fbe72 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -1100,9 +1100,6 @@
     GLuint /* texture_id */) {
   return 0;
 }
-void GLES2InterfaceStub::SetColorSpaceMetadataCHROMIUM(
-    GLuint /* texture_id */,
-    GLcolorSpace /* color_space */) {}
 void GLES2InterfaceStub::WindowRectanglesEXT(GLenum /* mode */,
                                              GLsizei /* count */,
                                              const GLint* /* box */) {}
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
index 685dace..7962acd8 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -817,8 +817,6 @@
 void InitializeDiscardableTextureCHROMIUM(GLuint texture_id) override;
 void UnlockDiscardableTextureCHROMIUM(GLuint texture_id) override;
 bool LockDiscardableTextureCHROMIUM(GLuint texture_id) override;
-void SetColorSpaceMetadataCHROMIUM(GLuint texture_id,
-                                   GLcolorSpace color_space) override;
 void WindowRectanglesEXT(GLenum mode, GLsizei count, const GLint* box) override;
 GLuint CreateGpuFenceCHROMIUM() override;
 GLuint CreateClientGpuFenceCHROMIUM(ClientGpuFence source) override;
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
index 277bacb..e7942da 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -2335,14 +2335,6 @@
   return gl_->LockDiscardableTextureCHROMIUM(texture_id);
 }
 
-void GLES2TraceImplementation::SetColorSpaceMetadataCHROMIUM(
-    GLuint texture_id,
-    GLcolorSpace color_space) {
-  TRACE_EVENT_BINARY_EFFICIENT0("gpu",
-                                "GLES2Trace::SetColorSpaceMetadataCHROMIUM");
-  gl_->SetColorSpaceMetadataCHROMIUM(texture_id, color_space);
-}
-
 void GLES2TraceImplementation::WindowRectanglesEXT(GLenum mode,
                                                    GLsizei count,
                                                    const GLint* box) {
diff --git a/gpu/command_buffer/client/raster_implementation_gles_unittest.cc b/gpu/command_buffer/client/raster_implementation_gles_unittest.cc
index 9fc5da5..6bfaa31 100644
--- a/gpu/command_buffer/client/raster_implementation_gles_unittest.cc
+++ b/gpu/command_buffer/client/raster_implementation_gles_unittest.cc
@@ -81,8 +81,6 @@
   MOCK_METHOD2(BindTexture, void(GLenum target, GLuint texture));
   MOCK_METHOD1(ActiveTexture, void(GLenum texture));
   MOCK_METHOD1(GenerateMipmap, void(GLenum target));
-  MOCK_METHOD2(SetColorSpaceMetadataCHROMIUM,
-               void(GLuint texture_id, GLcolorSpace color_space));
   MOCK_METHOD3(TexParameteri, void(GLenum target, GLenum pname, GLint param));
 
   // Mailboxes.
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index 1c916a87..877e2fe 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -15185,61 +15185,6 @@
     offsetof(LockDiscardableTextureCHROMIUM, texture_id) == 4,
     "offset of LockDiscardableTextureCHROMIUM texture_id should be 4");
 
-struct SetColorSpaceMetadataCHROMIUM {
-  typedef SetColorSpaceMetadataCHROMIUM ValueType;
-  static const CommandId kCmdId = kSetColorSpaceMetadataCHROMIUM;
-  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
-  static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
-
-  static uint32_t ComputeSize() {
-    return static_cast<uint32_t>(sizeof(ValueType));  // NOLINT
-  }
-
-  void SetHeader() { header.SetCmd<ValueType>(); }
-
-  void Init(GLuint _texture_id,
-            GLuint _shm_id,
-            GLuint _shm_offset,
-            GLsizei _color_space_size) {
-    SetHeader();
-    texture_id = _texture_id;
-    shm_id = _shm_id;
-    shm_offset = _shm_offset;
-    color_space_size = _color_space_size;
-  }
-
-  void* Set(void* cmd,
-            GLuint _texture_id,
-            GLuint _shm_id,
-            GLuint _shm_offset,
-            GLsizei _color_space_size) {
-    static_cast<ValueType*>(cmd)->Init(_texture_id, _shm_id, _shm_offset,
-                                       _color_space_size);
-    return NextCmdAddress<ValueType>(cmd);
-  }
-
-  gpu::CommandHeader header;
-  uint32_t texture_id;
-  uint32_t shm_id;
-  uint32_t shm_offset;
-  int32_t color_space_size;
-};
-
-static_assert(sizeof(SetColorSpaceMetadataCHROMIUM) == 20,
-              "size of SetColorSpaceMetadataCHROMIUM should be 20");
-static_assert(offsetof(SetColorSpaceMetadataCHROMIUM, header) == 0,
-              "offset of SetColorSpaceMetadataCHROMIUM header should be 0");
-static_assert(offsetof(SetColorSpaceMetadataCHROMIUM, texture_id) == 4,
-              "offset of SetColorSpaceMetadataCHROMIUM texture_id should be 4");
-static_assert(offsetof(SetColorSpaceMetadataCHROMIUM, shm_id) == 8,
-              "offset of SetColorSpaceMetadataCHROMIUM shm_id should be 8");
-static_assert(
-    offsetof(SetColorSpaceMetadataCHROMIUM, shm_offset) == 12,
-    "offset of SetColorSpaceMetadataCHROMIUM shm_offset should be 12");
-static_assert(
-    offsetof(SetColorSpaceMetadataCHROMIUM, color_space_size) == 16,
-    "offset of SetColorSpaceMetadataCHROMIUM color_space_size should be 16");
-
 struct WindowRectanglesEXTImmediate {
   typedef WindowRectanglesEXTImmediate ValueType;
   static const CommandId kCmdId = kWindowRectanglesEXTImmediate;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index c81c8d1..e5f38cb 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -5015,22 +5015,6 @@
   CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
 }
 
-TEST_F(GLES2FormatTest, SetColorSpaceMetadataCHROMIUM) {
-  cmds::SetColorSpaceMetadataCHROMIUM& cmd =
-      *GetBufferAs<cmds::SetColorSpaceMetadataCHROMIUM>();
-  void* next_cmd =
-      cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLuint>(12),
-              static_cast<GLuint>(13), static_cast<GLsizei>(14));
-  EXPECT_EQ(static_cast<uint32_t>(cmds::SetColorSpaceMetadataCHROMIUM::kCmdId),
-            cmd.header.command);
-  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
-  EXPECT_EQ(static_cast<GLuint>(11), cmd.texture_id);
-  EXPECT_EQ(static_cast<GLuint>(12), cmd.shm_id);
-  EXPECT_EQ(static_cast<GLuint>(13), cmd.shm_offset);
-  EXPECT_EQ(static_cast<GLsizei>(14), cmd.color_space_size);
-  CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
-}
-
 TEST_F(GLES2FormatTest, WindowRectanglesEXTImmediate) {
   const int kSomeBaseValueToTestWith = 51;
   static GLint data[] = {
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index 7a569f0c..42c03a3 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -318,27 +318,26 @@
   OP(InitializeDiscardableTextureCHROMIUM)                     /* 559 */ \
   OP(UnlockDiscardableTextureCHROMIUM)                         /* 560 */ \
   OP(LockDiscardableTextureCHROMIUM)                           /* 561 */ \
-  OP(SetColorSpaceMetadataCHROMIUM)                            /* 562 */ \
-  OP(WindowRectanglesEXTImmediate)                             /* 563 */ \
-  OP(CreateGpuFenceINTERNAL)                                   /* 564 */ \
-  OP(WaitGpuFenceCHROMIUM)                                     /* 565 */ \
-  OP(DestroyGpuFenceCHROMIUM)                                  /* 566 */ \
-  OP(SetReadbackBufferShadowAllocationINTERNAL)                /* 567 */ \
-  OP(FramebufferTextureMultiviewOVR)                           /* 568 */ \
-  OP(MaxShaderCompilerThreadsKHR)                              /* 569 */ \
-  OP(CreateAndTexStorage2DSharedImageINTERNALImmediate)        /* 570 */ \
-  OP(BeginSharedImageAccessDirectCHROMIUM)                     /* 571 */ \
-  OP(EndSharedImageAccessDirectCHROMIUM)                       /* 572 */ \
-  OP(BeginBatchReadAccessSharedImageCHROMIUM)                  /* 573 */ \
-  OP(EndBatchReadAccessSharedImageCHROMIUM)                    /* 574 */ \
-  OP(EnableiOES)                                               /* 575 */ \
-  OP(DisableiOES)                                              /* 576 */ \
-  OP(BlendEquationiOES)                                        /* 577 */ \
-  OP(BlendEquationSeparateiOES)                                /* 578 */ \
-  OP(BlendFunciOES)                                            /* 579 */ \
-  OP(BlendFuncSeparateiOES)                                    /* 580 */ \
-  OP(ColorMaskiOES)                                            /* 581 */ \
-  OP(IsEnablediOES)                                            /* 582 */
+  OP(WindowRectanglesEXTImmediate)                             /* 562 */ \
+  OP(CreateGpuFenceINTERNAL)                                   /* 563 */ \
+  OP(WaitGpuFenceCHROMIUM)                                     /* 564 */ \
+  OP(DestroyGpuFenceCHROMIUM)                                  /* 565 */ \
+  OP(SetReadbackBufferShadowAllocationINTERNAL)                /* 566 */ \
+  OP(FramebufferTextureMultiviewOVR)                           /* 567 */ \
+  OP(MaxShaderCompilerThreadsKHR)                              /* 568 */ \
+  OP(CreateAndTexStorage2DSharedImageINTERNALImmediate)        /* 569 */ \
+  OP(BeginSharedImageAccessDirectCHROMIUM)                     /* 570 */ \
+  OP(EndSharedImageAccessDirectCHROMIUM)                       /* 571 */ \
+  OP(BeginBatchReadAccessSharedImageCHROMIUM)                  /* 572 */ \
+  OP(EndBatchReadAccessSharedImageCHROMIUM)                    /* 573 */ \
+  OP(EnableiOES)                                               /* 574 */ \
+  OP(DisableiOES)                                              /* 575 */ \
+  OP(BlendEquationiOES)                                        /* 576 */ \
+  OP(BlendEquationSeparateiOES)                                /* 577 */ \
+  OP(BlendFunciOES)                                            /* 578 */ \
+  OP(BlendFuncSeparateiOES)                                    /* 579 */ \
+  OP(ColorMaskiOES)                                            /* 580 */ \
+  OP(IsEnablediOES)                                            /* 581 */
 
 enum CommandId {
   kOneBeforeStartPoint =
diff --git a/gpu/command_buffer/gles2_cmd_buffer_functions.txt b/gpu/command_buffer/gles2_cmd_buffer_functions.txt
index 5ee9e3c..92629331 100644
--- a/gpu/command_buffer/gles2_cmd_buffer_functions.txt
+++ b/gpu/command_buffer/gles2_cmd_buffer_functions.txt
@@ -355,9 +355,6 @@
 GL_APICALL void         GL_APIENTRY glUnlockDiscardableTextureCHROMIUM (GLuint texture_id);
 GL_APICALL bool         GL_APIENTRY glLockDiscardableTextureCHROMIUM (GLuint texture_id);
 
-// Extension CHROMIUM_color_space_metadata
-GL_APICALL void         GL_APIENTRY glSetColorSpaceMetadataCHROMIUM (GLuint texture_id, GLcolorSpace color_space);
-
 // Extension EXT_window_rectangles
 GL_APICALL void         GL_APIENTRY glWindowRectanglesEXT (GLenumWindowRectanglesMode mode, GLsizeiNotNegative count, const GLint* box);
 
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn
index 40e86c2..0801282f 100644
--- a/gpu/command_buffer/service/BUILD.gn
+++ b/gpu/command_buffer/service/BUILD.gn
@@ -48,8 +48,6 @@
     "gpu_switches.h",
     "image_factory.cc",
     "image_factory.h",
-    "image_manager.cc",
-    "image_manager.h",
     "mailbox_manager.h",
     "memory_tracking.cc",
     "memory_tracking.h",
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc
index 6a2cf3bb..0e5ce2d8 100644
--- a/gpu/command_buffer/service/context_group.cc
+++ b/gpu/command_buffer/service/context_group.cc
@@ -76,7 +76,6 @@
     FramebufferCompletenessCache* framebuffer_completeness_cache,
     const scoped_refptr<FeatureInfo>& feature_info,
     bool bind_generates_resource,
-    ImageManager* image_manager,
     gpu::ImageFactory* image_factory,
     gl::ProgressReporter* progress_reporter,
     const GpuFeatureInfo& gpu_feature_info,
@@ -119,7 +118,6 @@
       uniform_buffer_offset_alignment_(1u),
       program_cache_(nullptr),
       feature_info_(feature_info),
-      image_manager_(image_manager),
       image_factory_(image_factory),
       use_passthrough_cmd_decoder_(false),
       passthrough_resources_(new PassthroughResources),
diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h
index ffe42a2..0d4197c 100644
--- a/gpu/command_buffer/service/context_group.h
+++ b/gpu/command_buffer/service/context_group.h
@@ -44,7 +44,6 @@
 
 class ProgramCache;
 class BufferManager;
-class ImageManager;
 class RenderbufferManager;
 class ProgramManager;
 class SamplerManager;
@@ -69,7 +68,6 @@
                FramebufferCompletenessCache* framebuffer_completeness_cache,
                const scoped_refptr<FeatureInfo>& feature_info,
                bool bind_generates_resource,
-               ImageManager* image_manager,
                gpu::ImageFactory* image_factory,
                gl::ProgressReporter* progress_reporter,
                const GpuFeatureInfo& gpu_feature_info,
@@ -166,8 +164,6 @@
     return feature_info_.get();
   }
 
-  ImageManager* image_manager() const { return image_manager_; }
-
   gpu::ImageFactory* image_factory() const { return image_factory_; }
 
   const GpuPreferences& gpu_preferences() const {
@@ -313,8 +309,6 @@
 
   scoped_refptr<FeatureInfo> feature_info_;
 
-  raw_ptr<ImageManager> image_manager_;
-
   raw_ptr<gpu::ImageFactory> image_factory_;
 
   std::vector<base::WeakPtr<DecoderContext>> decoders_;
diff --git a/gpu/command_buffer/service/context_group_unittest.cc b/gpu/command_buffer/service/context_group_unittest.cc
index 5cb347b..c30603f 100644
--- a/gpu/command_buffer/service/context_group_unittest.cc
+++ b/gpu/command_buffer/service/context_group_unittest.cc
@@ -12,7 +12,6 @@
 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
 #include "gpu/command_buffer/service/gpu_service_test.h"
 #include "gpu/command_buffer/service/gpu_tracer.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/service_discardable_manager.h"
 #include "gpu/command_buffer/service/shared_image_manager.h"
@@ -52,14 +51,13 @@
         gpu_preferences_, false, &mailbox_manager_,
         nullptr /* memory_tracker */, nullptr /* shader_translator_cache */,
         nullptr /* framebuffer_completeness_cache */, feature_info,
-        kBindGeneratesResource, &image_manager_, nullptr /* image_factory */,
+        kBindGeneratesResource, nullptr /* image_factory */,
         nullptr /* progress_reporter */, GpuFeatureInfo(),
         &discardable_manager_, nullptr /* passthrough_discardable_manager */,
         &shared_image_manager_));
   }
 
   GpuPreferences gpu_preferences_;
-  ImageManager image_manager_;
   ServiceDiscardableManager discardable_manager_;
   SharedImageManager shared_image_manager_;
   FakeCommandBufferServiceBase command_buffer_service_;
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index 7dd54f98..26cf037 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -498,7 +498,6 @@
 
   AddExtensionString("GL_CHROMIUM_async_pixel_transfers");
   AddExtensionString("GL_CHROMIUM_bind_uniform_location");
-  AddExtensionString("GL_CHROMIUM_color_space_metadata");
   AddExtensionString("GL_CHROMIUM_command_buffer_query");
   AddExtensionString("GL_CHROMIUM_command_buffer_latency_query");
   AddExtensionString("GL_CHROMIUM_copy_texture");
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index c2012717..c181699d 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -65,7 +65,6 @@
 #include "gpu/command_buffer/service/gpu_state_tracer.h"
 #include "gpu/command_buffer/service/gpu_tracer.h"
 #include "gpu/command_buffer/service/image_factory.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/logger.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
@@ -739,9 +738,6 @@
   VertexArrayManager* GetVertexArrayManager() override {
     return vertex_array_manager_.get();
   }
-  ImageManager* GetImageManagerForTest() override {
-    return group_->image_manager();
-  }
 
   bool HasPendingQueries() const override;
   void ProcessPendingQueries(bool did_finish) override;
@@ -966,8 +962,6 @@
     return group_->mailbox_manager();
   }
 
-  ImageManager* image_manager() { return group_->image_manager(); }
-
   VertexArrayManager* vertex_array_manager() {
     return vertex_array_manager_.get();
   }
@@ -13549,39 +13543,6 @@
   return error::kNoError;
 }
 
-error::Error GLES2DecoderImpl::HandleSetColorSpaceMetadataCHROMIUM(
-    uint32_t immediate_data_size,
-    const volatile void* cmd_data) {
-  const volatile gles2::cmds::SetColorSpaceMetadataCHROMIUM& c =
-      *static_cast<const volatile gles2::cmds::SetColorSpaceMetadataCHROMIUM*>(
-          cmd_data);
-
-  GLuint texture_id = c.texture_id;
-  gfx::ColorSpace color_space;
-  if (!ReadColorSpace(c.shm_id, c.shm_offset, c.color_space_size,
-                      &color_space)) {
-    return error::kOutOfBounds;
-  }
-
-  TextureRef* ref = texture_manager()->GetTexture(texture_id);
-  if (!ref) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glSetColorSpaceMetadataCHROMIUM",
-                       "unknown texture");
-    return error::kNoError;
-  }
-
-  scoped_refptr<gl::GLImage> image =
-      ref->texture()->GetLevelImage(ref->texture()->target(), 0);
-  if (!image) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glSetColorSpaceMetadataCHROMIUM",
-                       "no image associated with texture");
-    return error::kNoError;
-  }
-
-  image->SetColorSpace(color_space);
-  return error::kNoError;
-}
-
 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
     GLuint client_id,
     uint32_t location_shm_id,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index aa78cd6d..10d099d 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -46,7 +46,6 @@
 class CopyTextureCHROMIUMResourceManager;
 class FramebufferManager;
 class GLES2Util;
-class ImageManager;
 class Logger;
 class Outputter;
 class ShaderTranslatorInterface;
@@ -184,9 +183,6 @@
   // Gets the VertexArrayManager for this context.
   virtual VertexArrayManager* GetVertexArrayManager() = 0;
 
-  // Gets the ImageManager for this context.
-  virtual ImageManager* GetImageManagerForTest() = 0;
-
   // Get the service texture ID corresponding to a client texture ID.
   // If no such record is found then return false.
   virtual bool GetServiceTextureId(uint32_t client_texture_id,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index 9a3fec9..e971d26 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -104,7 +104,6 @@
   MOCK_METHOD0(
       GetTransformFeedbackManager, gpu::gles2::TransformFeedbackManager*());
   MOCK_METHOD0(GetVertexArrayManager, gpu::gles2::VertexArrayManager*());
-  MOCK_METHOD0(GetImageManagerForTest, gpu::gles2::ImageManager*());
   MOCK_METHOD1(SetIgnoreCachedStateForTest, void(bool ignore));
   MOCK_METHOD1(SetForceShaderNameHashingForTest, void(bool force));
   MOCK_METHOD1(SetAllowExit, void(bool allow));
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
index c63c8ed..0906a535 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -1810,11 +1810,6 @@
   return nullptr;
 }
 
-gpu::gles2::ImageManager*
-GLES2DecoderPassthroughImpl::GetImageManagerForTest() {
-  return group_->image_manager();
-}
-
 bool GLES2DecoderPassthroughImpl::HasPendingQueries() const {
   return !pending_queries_.empty();
 }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
index fe7c243a..797fd08 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -25,7 +25,6 @@
 #include "gpu/command_buffer/service/client_service_map.h"
 #include "gpu/command_buffer/service/context_group.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/logger.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/passthrough_abstract_texture_impl.h"
@@ -260,9 +259,6 @@
   // Gets the VertexArrayManager for this context.
   VertexArrayManager* GetVertexArrayManager() override;
 
-  // Gets the ImageManager for this context.
-  ImageManager* GetImageManagerForTest() override;
-
   // Returns false if there are no pending queries.
   bool HasPendingQueries() const override;
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h
index 05ba8f39..7d62ee6 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h
@@ -886,8 +886,7 @@
                                      GLuint64 release_count);
 error::Error DoDrawBuffersEXT(GLsizei count, const volatile GLenum* bufs);
 error::Error DoDiscardBackbufferCHROMIUM();
-error::Error DoSetColorSpaceMetadataCHROMIUM(GLuint texture_id,
-                                             gfx::ColorSpace color_space);
+
 error::Error DoFlushDriverCachesCHROMIUM();
 error::Error DoMatrixLoadfCHROMIUM(GLenum matrixMode,
                                    const volatile GLfloat* m);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
index 38cd207..d9b16dc 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
@@ -4682,28 +4682,6 @@
   return error::kNoError;
 }
 
-error::Error GLES2DecoderPassthroughImpl::DoSetColorSpaceMetadataCHROMIUM(
-    GLuint texture_id,
-    gfx::ColorSpace color_space) {
-  scoped_refptr<TexturePassthrough> passthrough_texture;
-  if (!resources_->texture_object_map.GetServiceID(texture_id,
-                                                   &passthrough_texture) ||
-      passthrough_texture == nullptr) {
-    InsertError(GL_INVALID_VALUE, "unknown texture.");
-    return error::kNoError;
-  }
-
-  scoped_refptr<gl::GLImage> image =
-      passthrough_texture->GetLevelImage(passthrough_texture->target(), 0);
-  if (image == nullptr) {
-    InsertError(GL_INVALID_VALUE, "no image associated with texture.");
-    return error::kNoError;
-  }
-
-  image->SetColorSpace(color_space);
-  return error::kNoError;
-}
-
 error::Error GLES2DecoderPassthroughImpl::DoFlushDriverCachesCHROMIUM() {
   // On Adreno Android devices we need to use a workaround to force caches to
   // clear.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc
index 44a5318..e2f6109 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc
@@ -2206,21 +2206,6 @@
   return DoDiscardBackbufferCHROMIUM();
 }
 
-error::Error GLES2DecoderPassthroughImpl::HandleSetColorSpaceMetadataCHROMIUM(
-    uint32_t immediate_data_size,
-    const volatile void* cmd_data) {
-  const volatile gles2::cmds::SetColorSpaceMetadataCHROMIUM& c =
-      *static_cast<const volatile gles2::cmds::SetColorSpaceMetadataCHROMIUM*>(
-          cmd_data);
-  GLuint texture_id = c.texture_id;
-  gfx::ColorSpace color_space;
-  if (!ReadColorSpace(c.shm_id, c.shm_offset, c.color_space_size,
-                      &color_space)) {
-    return error::kOutOfBounds;
-  }
-  return DoSetColorSpaceMetadataCHROMIUM(texture_id, color_space);
-}
-
 error::Error
 GLES2DecoderPassthroughImpl::HandleBindFragDataLocationIndexedEXTBucket(
     uint32_t immediate_data_size,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 0973e010..12ef6d38 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -16,7 +16,6 @@
 #include "gpu/command_buffer/service/context_state.h"
 #include "gpu/command_buffer/service/gl_surface_mock.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/mocks.h"
 #include "gpu/command_buffer/service/program_manager.h"
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc
index ca36199..c6d0df36 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc
@@ -14,7 +14,6 @@
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/mocks.h"
 #include "gpu/command_buffer/service/program_manager.h"
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 76450c5..4148b86f 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -207,14 +207,13 @@
   scoped_refptr<FeatureInfo> feature_info =
       new FeatureInfo(workarounds, gpu_feature_info);
 
-  group_ = scoped_refptr<ContextGroup>(
-      new ContextGroup(gpu_preferences_, GetParam(), &mailbox_manager_,
-                       std::move(memory_tracker_), &shader_translator_cache_,
-                       &framebuffer_completeness_cache_, feature_info,
-                       normalized_init.bind_generates_resource, &image_manager_,
-                       nullptr /* image_factory */,
-                       nullptr /* progress_reporter */, gpu_feature_info,
-                       &discardable_manager_, nullptr, &shared_image_manager_));
+  group_ = scoped_refptr<ContextGroup>(new ContextGroup(
+      gpu_preferences_, GetParam(), &mailbox_manager_,
+      std::move(memory_tracker_), &shader_translator_cache_,
+      &framebuffer_completeness_cache_, feature_info,
+      normalized_init.bind_generates_resource, nullptr /* image_factory */,
+      nullptr /* progress_reporter */, gpu_feature_info, &discardable_manager_,
+      nullptr, &shared_image_manager_));
   bool use_default_textures = normalized_init.bind_generates_resource;
 
   InSequence sequence;
@@ -2440,7 +2439,7 @@
   group_ = new gles2::ContextGroup(
       gpu_preferences_, true, &mailbox_manager_, nullptr /* memory_tracker */,
       &shader_translator_cache_, &framebuffer_completeness_cache_, feature_info,
-      context_creation_attribs_.bind_generates_resource, &image_manager_,
+      context_creation_attribs_.bind_generates_resource,
       nullptr /* image_factory */, nullptr /* progress_reporter */,
       GpuFeatureInfo(), &discardable_manager_,
       &passthrough_discardable_manager_, &shared_image_manager_);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
index 1d4fda2..c14d269 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -26,7 +26,6 @@
 #include "gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h"
 #include "gpu/command_buffer/service/gles2_query_manager.h"
 #include "gpu/command_buffer/service/gpu_tracer.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/passthrough_discardable_manager.h"
 #include "gpu/command_buffer/service/program_manager.h"
@@ -192,10 +191,6 @@
     return decoder_->GetFramebufferManager();
   }
 
-  ImageManager* GetImageManagerForTest() {
-    return decoder_->GetImageManagerForTest();
-  }
-
   void DoCreateProgram(GLuint client_id, GLuint service_id);
   void DoCreateShader(GLenum shader_type, GLuint client_id, GLuint service_id);
   void DoFenceSync(GLuint client_id, GLuint service_id);
@@ -800,7 +795,6 @@
   MailboxManagerImpl mailbox_manager_;
   ShaderTranslatorCache shader_translator_cache_;
   FramebufferCompletenessCache framebuffer_completeness_cache_;
-  ImageManager image_manager_;
   ServiceDiscardableManager discardable_manager_;
   SharedImageManager shared_image_manager_;
   scoped_refptr<ContextGroup> group_;
@@ -1024,7 +1018,6 @@
   MailboxManagerImpl mailbox_manager_;
   ShaderTranslatorCache shader_translator_cache_;
   FramebufferCompletenessCache framebuffer_completeness_cache_;
-  ImageManager image_manager_;
   ServiceDiscardableManager discardable_manager_;
   PassthroughDiscardableManager passthrough_discardable_manager_;
   SharedImageManager shared_image_manager_;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc
index 099dda5..030de82 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc
@@ -16,7 +16,6 @@
 #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
 
 #include "gpu/command_buffer/service/gpu_switches.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/mocks.h"
 #include "gpu/command_buffer/service/program_manager.h"
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
index 5fc92d6..71e17d9 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
@@ -16,7 +16,6 @@
 #include "gpu/command_buffer/service/gl_surface_mock.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
 
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/mocks.h"
 #include "gpu/command_buffer/service/program_manager.h"
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
index 7e839beb..de080ff 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
@@ -20,7 +20,6 @@
 #include "gpu/command_buffer/service/gl_surface_mock.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/mocks.h"
 #include "gpu/command_buffer/service/program_manager.h"
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
index 1ef7c47..00998ef 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
@@ -14,7 +14,6 @@
 #include "gpu/command_buffer/service/gl_surface_mock.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/mocks.h"
 #include "gpu/command_buffer/service/program_manager.h"
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
index fe05334b..60aaf1b 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
@@ -17,7 +17,6 @@
 #include "gpu/command_buffer/service/gl_surface_mock.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/mocks.h"
 #include "gpu/command_buffer/service/program_manager.h"
diff --git a/gpu/command_buffer/service/image_manager.cc b/gpu/command_buffer/service/image_manager.cc
deleted file mode 100644
index d7ca6d01..0000000
--- a/gpu/command_buffer/service/image_manager.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "gpu/command_buffer/service/image_manager.h"
-
-#include <stdint.h>
-
-#include "base/check.h"
-#include "ui/gl/gl_image.h"
-
-namespace gpu {
-namespace gles2 {
-
-ImageManager::ImageManager() = default;
-
-ImageManager::~ImageManager() = default;
-
-void ImageManager::AddImage(gl::GLImage* image, int32_t service_id) {
-  DCHECK(images_.find(service_id) == images_.end());
-  images_[service_id] = image;
-}
-
-void ImageManager::RemoveImage(int32_t service_id) {
-  DCHECK(images_.find(service_id) != images_.end());
-  images_.erase(service_id);
-}
-
-gl::GLImage* ImageManager::LookupImage(int32_t service_id) {
-  GLImageMap::const_iterator iter = images_.find(service_id);
-  if (iter != images_.end())
-    return iter->second.get();
-
-  return nullptr;
-}
-
-}  // namespace gles2
-}  // namespace gpu
diff --git a/gpu/command_buffer/service/image_manager.h b/gpu/command_buffer/service/image_manager.h
deleted file mode 100644
index 0fa194e10c..0000000
--- a/gpu/command_buffer/service/image_manager.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GPU_COMMAND_BUFFER_SERVICE_IMAGE_MANAGER_H_
-#define GPU_COMMAND_BUFFER_SERVICE_IMAGE_MANAGER_H_
-
-#include <stdint.h>
-
-#include <unordered_map>
-
-#include "base/memory/ref_counted.h"
-#include "gpu/gpu_export.h"
-
-namespace gl {
-class GLImage;
-}
-
-namespace gpu {
-namespace gles2 {
-
-// This class keeps track of the images and their state.
-class GPU_EXPORT ImageManager {
- public:
-  ImageManager();
-
-  ImageManager(const ImageManager&) = delete;
-  ImageManager& operator=(const ImageManager&) = delete;
-
-  ~ImageManager();
-
-  void AddImage(gl::GLImage* image, int32_t service_id);
-  void RemoveImage(int32_t service_id);
-  gl::GLImage* LookupImage(int32_t service_id);
-
- private:
-  typedef std::unordered_map<int32_t, scoped_refptr<gl::GLImage>> GLImageMap;
-  GLImageMap images_;
-};
-
-}  // namespage gles2
-}  // namespace gpu
-
-#endif  // GPU_COMMAND_BUFFER_SERVICE_IMAGE_MANAGER_H_
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 26548ab..6c2d084 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -592,7 +592,6 @@
   gles2::Logger* GetLogger() override;
 
   void SetIgnoreCachedStateForTest(bool ignore) override;
-  gles2::ImageManager* GetImageManagerForTest() override;
 
   void SetCopyTextureResourceManagerForTest(
       gles2::CopyTextureCHROMIUMResourceManager* copy_texture_resource_manager)
@@ -1511,11 +1510,6 @@
   state()->SetIgnoreCachedStateForTest(ignore);
 }
 
-gles2::ImageManager* RasterDecoderImpl::GetImageManagerForTest() {
-  NOTREACHED();
-  return nullptr;
-}
-
 void RasterDecoderImpl::SetCopyTextureResourceManagerForTest(
     gles2::CopyTextureCHROMIUMResourceManager* copy_texture_resource_manager) {
   copy_texture_chromium_.reset(copy_texture_resource_manager);
diff --git a/gpu/command_buffer/service/raster_decoder.h b/gpu/command_buffer/service/raster_decoder.h
index 9848cd3..647bb8a 100644
--- a/gpu/command_buffer/service/raster_decoder.h
+++ b/gpu/command_buffer/service/raster_decoder.h
@@ -24,7 +24,6 @@
 namespace gles2 {
 class CopyTextureCHROMIUMResourceManager;
 class GLES2Util;
-class ImageManager;
 class Logger;
 class Outputter;
 }  // namespace gles2
@@ -73,9 +72,6 @@
   virtual gles2::Logger* GetLogger() = 0;
   virtual void SetIgnoreCachedStateForTest(bool ignore) = 0;
 
-  // Gets the ImageManager for this context.
-  virtual gles2::ImageManager* GetImageManagerForTest() = 0;
-
   void set_initialized() { initialized_ = true; }
 
   // Set to true to call glGetError after every command.
diff --git a/gpu/command_buffer/service/service_discardable_manager_unittest.cc b/gpu/command_buffer/service/service_discardable_manager_unittest.cc
index 145a113..b5e4d627 100644
--- a/gpu/command_buffer/service/service_discardable_manager_unittest.cc
+++ b/gpu/command_buffer/service/service_discardable_manager_unittest.cc
@@ -11,7 +11,6 @@
 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
 #include "gpu/command_buffer/service/gpu_service_test.h"
 #include "gpu/command_buffer/service/gpu_tracer.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
 #include "gpu/command_buffer/service/mocks.h"
@@ -80,9 +79,8 @@
     feature_info_ = new FeatureInfo();
     context_group_ = scoped_refptr<ContextGroup>(new ContextGroup(
         gpu_preferences_, false, &mailbox_manager_, nullptr, nullptr, nullptr,
-        feature_info_, false, &image_manager_, nullptr, nullptr,
-        GpuFeatureInfo(), &discardable_manager_, nullptr,
-        &shared_image_manager_));
+        feature_info_, false, nullptr, nullptr, GpuFeatureInfo(),
+        &discardable_manager_, nullptr, &shared_image_manager_));
     TestHelper::SetupContextGroupInitExpectations(
         gl_.get(), DisallowedFeatures(), "", "", CONTEXT_TYPE_OPENGLES2, false);
     context_group_->Initialize(decoder_.get(), CONTEXT_TYPE_OPENGLES2,
@@ -125,7 +123,6 @@
 
   MailboxManagerImpl mailbox_manager_;
   TraceOutputter outputter_;
-  ImageManager image_manager_;
   ServiceDiscardableManager discardable_manager_;
   SharedImageManager shared_image_manager_;
   GpuPreferences gpu_preferences_;
diff --git a/gpu/command_buffer/tests/decoder_perftest.cc b/gpu/command_buffer/tests/decoder_perftest.cc
index fa96ff81..35a6171 100644
--- a/gpu/command_buffer/tests/decoder_perftest.cc
+++ b/gpu/command_buffer/tests/decoder_perftest.cc
@@ -22,7 +22,6 @@
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "gpu/command_buffer/service/gpu_tracer.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/logger.h"
 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
@@ -182,7 +181,7 @@
     scoped_refptr<gles2::ContextGroup> context_group = new gles2::ContextGroup(
         gpu_preferences_, true, &mailbox_manager_, nullptr /* memory_tracker */,
         &translator_cache_, &completeness_cache_, feature_info,
-        bind_generates_resource, &image_manager_, nullptr /* image_factory */,
+        bind_generates_resource, nullptr /* image_factory */,
         nullptr /* progress_reporter */, GpuFeatureInfo(),
         &discardable_manager_, &passthrough_discardable_manager_,
         &shared_image_manager_);
@@ -321,7 +320,6 @@
 
   gles2::MailboxManagerImpl mailbox_manager_;
   scoped_refptr<gl::GLShareGroup> share_group_;
-  gles2::ImageManager image_manager_;
   ServiceDiscardableManager discardable_manager_;
   PassthroughDiscardableManager passthrough_discardable_manager_;
   SharedImageManager shared_image_manager_;
diff --git a/gpu/command_buffer/tests/fuzzer_main.cc b/gpu/command_buffer/tests/fuzzer_main.cc
index 9f8eb7b..85703c3 100644
--- a/gpu/command_buffer/tests/fuzzer_main.cc
+++ b/gpu/command_buffer/tests/fuzzer_main.cc
@@ -27,7 +27,6 @@
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "gpu/command_buffer/service/gpu_tracer.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/logger.h"
 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/passthrough_discardable_manager.h"
@@ -446,7 +445,7 @@
     scoped_refptr<gles2::ContextGroup> context_group = new gles2::ContextGroup(
         gpu_preferences_, true, &mailbox_manager_, nullptr /* memory_tracker */,
         &translator_cache_, &completeness_cache_, decoder_feature_info,
-        config_.attrib_helper.bind_generates_resource, &image_manager_,
+        config_.attrib_helper.bind_generates_resource,
         nullptr /* image_factory */, nullptr /* progress_reporter */,
         gpu_feature_info, discardable_manager_.get(),
         passthrough_discardable_manager_.get(), shared_image_manager_.get());
@@ -630,7 +629,6 @@
   gles2::MailboxManagerImpl mailbox_manager_;
   gles2::TraceOutputter outputter_;
   scoped_refptr<gl::GLShareGroup> share_group_;
-  gles2::ImageManager image_manager_;
   std::unique_ptr<ServiceDiscardableManager> discardable_manager_;
   std::unique_ptr<PassthroughDiscardableManager>
       passthrough_discardable_manager_;
diff --git a/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc b/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc
index 27594417..b481002d 100644
--- a/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc
+++ b/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc
@@ -16,7 +16,6 @@
 #include "build/build_config.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
 #include "gpu/command_buffer/service/command_buffer_service.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/tests/gl_manager.h"
 #include "gpu/command_buffer/tests/gl_test_utils.h"
 #include "gpu/config/gpu_test_config.h"
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc
index 07b7f55..ea1168d 100644
--- a/gpu/command_buffer/tests/gl_manager.cc
+++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -354,7 +354,7 @@
     context_group = new gles2::ContextGroup(
         gpu_preferences_, true, mailbox_manager_, nullptr /* memory_tracker */,
         translator_cache_.get(), &completeness_cache_, feature_info,
-        options.bind_generates_resource, &image_manager_, options.image_factory,
+        options.bind_generates_resource, options.image_factory,
         nullptr /* progress_reporter */, gpu_feature_info,
         discardable_manager_.get(), passthrough_discardable_manager_.get(),
         &shared_image_manager_);
diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h
index 5d91745..81c7811 100644
--- a/gpu/command_buffer/tests/gl_manager.h
+++ b/gpu/command_buffer/tests/gl_manager.h
@@ -17,7 +17,6 @@
 #include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/service/feature_info.h"
 #include "gpu/command_buffer/service/gpu_tracer.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/passthrough_discardable_manager.h"
 #include "gpu/command_buffer/service/service_discardable_manager.h"
@@ -178,7 +177,6 @@
 
   gles2::MailboxManagerImpl owned_mailbox_manager_;
   gles2::TraceOutputter outputter_;
-  gles2::ImageManager image_manager_;
   std::unique_ptr<ServiceDiscardableManager> discardable_manager_;
   std::unique_ptr<PassthroughDiscardableManager>
       passthrough_discardable_manager_;
diff --git a/gpu/gles2_conform_support/egl/context.cc b/gpu/gles2_conform_support/egl/context.cc
index b820c42..10aaffd 100644
--- a/gpu/gles2_conform_support/egl/context.cc
+++ b/gpu/gles2_conform_support/egl/context.cc
@@ -12,7 +12,6 @@
 #include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "gpu/command_buffer/service/context_group.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
 #include "gpu/command_buffer/service/service_discardable_manager.h"
 #include "gpu/command_buffer/service/shared_image_manager.h"
@@ -256,8 +255,8 @@
   scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup(
       gpu_preferences, true, &mailbox_manager_, nullptr /* memory_tracker */,
       &translator_cache_, &completeness_cache_, feature_info, true,
-      &image_manager_, nullptr /* image_factory */,
-      nullptr /* progress_reporter */, gpu_feature_info, &discardable_manager_,
+      nullptr /* image_factory */, nullptr /* progress_reporter */,
+      gpu_feature_info, &discardable_manager_,
       &passthrough_discardable_manager_, &shared_image_manager_));
 
   auto command_buffer = std::make_unique<gpu::CommandBufferDirect>();
diff --git a/gpu/gles2_conform_support/egl/context.h b/gpu/gles2_conform_support/egl/context.h
index d2d7e96..c389d993 100644
--- a/gpu/gles2_conform_support/egl/context.h
+++ b/gpu/gles2_conform_support/egl/context.h
@@ -15,7 +15,6 @@
 #include "gpu/command_buffer/service/command_buffer_direct.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/gpu_tracer.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/passthrough_discardable_manager.h"
 #include "gpu/command_buffer/service/service_discardable_manager.h"
@@ -117,7 +116,6 @@
 
   gpu::gles2::MailboxManagerImpl mailbox_manager_;
   gpu::gles2::TraceOutputter outputter_;
-  gpu::gles2::ImageManager image_manager_;
   gpu::ServiceDiscardableManager discardable_manager_;
   gpu::PassthroughDiscardableManager passthrough_discardable_manager_;
   gpu::SharedImageManager shared_image_manager_;
diff --git a/gpu/ipc/command_buffer_task_executor.h b/gpu/ipc/command_buffer_task_executor.h
index 0d72c21e..20054d0 100644
--- a/gpu/ipc/command_buffer_task_executor.h
+++ b/gpu/ipc/command_buffer_task_executor.h
@@ -13,7 +13,6 @@
 #include "gpu/command_buffer/common/activity_flags.h"
 #include "gpu/command_buffer/common/sync_token.h"
 #include "gpu/command_buffer/service/framebuffer_completeness_cache.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/passthrough_discardable_manager.h"
 #include "gpu/command_buffer/service/sequence_id.h"
 #include "gpu/command_buffer/service/service_discardable_manager.h"
@@ -92,7 +91,6 @@
   MailboxManager* mailbox_manager() const { return mailbox_manager_; }
 
   // Not const because these return inner pointers.
-  gles2::ImageManager* image_manager() { return &image_manager_; }
   ServiceDiscardableManager* discardable_manager() {
     return &discardable_manager_;
   }
@@ -120,7 +118,6 @@
   gl::GLSurfaceFormat share_group_surface_format_;
   std::unique_ptr<gles2::ProgramCache> owned_program_cache_;
   raw_ptr<gles2::ProgramCache> program_cache_;
-  gles2::ImageManager image_manager_;
   ServiceDiscardableManager discardable_manager_;
   PassthroughDiscardableManager passthrough_discardable_manager_;
   gles2::ShaderTranslatorCache shader_translator_cache_;
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc
index 09aa8e88..5527eee 100644
--- a/gpu/ipc/in_process_command_buffer.cc
+++ b/gpu/ipc/in_process_command_buffer.cc
@@ -258,9 +258,9 @@
       task_executor_->mailbox_manager(), std::move(memory_tracker),
       task_executor_->shader_translator_cache(),
       task_executor_->framebuffer_completeness_cache(), feature_info,
-      params.attribs.bind_generates_resource, task_executor_->image_manager(),
-      params.image_factory, nullptr /* progress_reporter */,
-      task_executor_->gpu_feature_info(), task_executor_->discardable_manager(),
+      params.attribs.bind_generates_resource, params.image_factory,
+      nullptr /* progress_reporter */, task_executor_->gpu_feature_info(),
+      task_executor_->discardable_manager(),
       task_executor_->passthrough_discardable_manager(),
       task_executor_->shared_image_manager());
 
diff --git a/gpu/ipc/service/gles2_command_buffer_stub.cc b/gpu/ipc/service/gles2_command_buffer_stub.cc
index b9595b45..ac6e3f5 100644
--- a/gpu/ipc/service/gles2_command_buffer_stub.cc
+++ b/gpu/ipc/service/gles2_command_buffer_stub.cc
@@ -26,7 +26,6 @@
 #include "gpu/command_buffer/service/gl_context_virtual.h"
 #include "gpu/command_buffer/service/gl_state_restorer_impl.h"
 #include "gpu/command_buffer/service/gpu_fence_manager.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/logger.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
@@ -109,7 +108,7 @@
         manager->mailbox_manager(), CreateMemoryTracker(),
         manager->shader_translator_cache(),
         manager->framebuffer_completeness_cache(), feature_info,
-        init_params.attribs.bind_generates_resource, channel_->image_manager(),
+        init_params.attribs.bind_generates_resource,
         gmb_factory ? gmb_factory->AsImageFactory() : nullptr,
         manager->watchdog() /* progress_reporter */,
         manager->gpu_feature_info(), manager->discardable_manager(),
diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc
index 7066df9..6030d8e 100644
--- a/gpu/ipc/service/gpu_channel.cc
+++ b/gpu/ipc/service/gpu_channel.cc
@@ -42,7 +42,6 @@
 #include "build/build_config.h"
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/command_buffer/service/image_factory.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
 #include "gpu/command_buffer/service/scheduler.h"
@@ -549,7 +548,6 @@
       task_runner_(task_runner),
       io_task_runner_(io_task_runner),
       share_group_(share_group),
-      image_manager_(new gles2::ImageManager()),
       is_gpu_host_(is_gpu_host),
       filter_(base::MakeRefCounted<GpuChannelMessageFilter>(
           this,
diff --git a/gpu/ipc/service/gpu_channel.h b/gpu/ipc/service/gpu_channel.h
index 3cf479f..4da8ec77 100644
--- a/gpu/ipc/service/gpu_channel.h
+++ b/gpu/ipc/service/gpu_channel.h
@@ -101,8 +101,6 @@
 
   SyncPointManager* sync_point_manager() const { return sync_point_manager_; }
 
-  gles2::ImageManager* image_manager() const { return image_manager_.get(); }
-
   const scoped_refptr<base::SingleThreadTaskRunner>& task_runner() const {
     return task_runner_;
   }
@@ -281,7 +279,6 @@
   // process use.
   scoped_refptr<gl::GLShareGroup> share_group_;
 
-  std::unique_ptr<gles2::ImageManager> image_manager_;
   std::unique_ptr<SharedImageStub> shared_image_stub_;
 
   const bool is_gpu_host_;
diff --git a/gpu/ipc/service/raster_command_buffer_stub.cc b/gpu/ipc/service/raster_command_buffer_stub.cc
index 9b48099..49ba1d6 100644
--- a/gpu/ipc/service/raster_command_buffer_stub.cc
+++ b/gpu/ipc/service/raster_command_buffer_stub.cc
@@ -14,7 +14,6 @@
 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/command_buffer/service/gl_context_virtual.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/logger.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
diff --git a/gpu/ipc/service/webgpu_command_buffer_stub.cc b/gpu/ipc/service/webgpu_command_buffer_stub.cc
index c0afd00..d3c8c552 100644
--- a/gpu/ipc/service/webgpu_command_buffer_stub.cc
+++ b/gpu/ipc/service/webgpu_command_buffer_stub.cc
@@ -15,7 +15,6 @@
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/command_buffer/service/gl_context_virtual.h"
 #include "gpu/command_buffer/service/gl_state_restorer_impl.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/logger.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
index 01ab0eb..df8a56c 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -79,7 +79,6 @@
 #import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_commands.h"
 #import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_scene_agent.h"
 #import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_view.h"
-#import "ios/chrome/browser/ui/infobars/infobar_positioner.h"
 #import "ios/chrome/browser/ui/main/scene_state.h"
 #import "ios/chrome/browser/ui/main/scene_state_browser_agent.h"
 #import "ios/chrome/browser/ui/main_content/main_content_ui.h"
@@ -245,7 +244,6 @@
 @interface BrowserViewController () <CRWWebStateObserver,
                                      FindBarPresentationDelegate,
                                      FullscreenUIElement,
-                                     InfobarPositioner,
                                      KeyCommandsPlumbing,
                                      MainContentUI,
                                      SideSwipeControllerDelegate,
@@ -3898,12 +3896,6 @@
   [animatedView animateFrom:origin withCompletion:completionBlock];
 }
 
-#pragma mark - InfobarPositioner
-
-- (UIView*)parentView {
-  return self.contentArea;
-}
-
 #pragma mark - IncognitoReauthConsumer
 
 - (void)setItemsRequireAuthentication:(BOOL)require {
diff --git a/ios/chrome/browser/ui/infobars/BUILD.gn b/ios/chrome/browser/ui/infobars/BUILD.gn
index 761d3282..0f35b6001 100644
--- a/ios/chrome/browser/ui/infobars/BUILD.gn
+++ b/ios/chrome/browser/ui/infobars/BUILD.gn
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 source_set("public") {
-  sources = [ "infobar_positioner.h" ]
+  sources = []
 }
 
 source_set("constants") {
diff --git a/ios/chrome/browser/ui/infobars/infobar_positioner.h b/ios/chrome/browser/ui/infobars/infobar_positioner.h
deleted file mode 100644
index bc5e0ac..0000000
--- a/ios/chrome/browser/ui/infobars/infobar_positioner.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_POSITIONER_H_
-#define IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_POSITIONER_H_
-
-#import <UIKit/UIKit.h>
-
-// InfobarPositioner contains methods that are used to position the infobars
-// on the screen.
-@protocol InfobarPositioner
-
-// View to which the popup view should be added as subview.
-- (UIView*)parentView;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_POSITIONER_H_
diff --git a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
index a12ffefe..2579eab 100644
--- a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
+++ b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
@@ -90,6 +90,7 @@
     "//ios/chrome/browser/ui/main:default_browser_scene_agent",
     "//ios/chrome/browser/ui/main:scene_state_header",
     "//ios/chrome/browser/ui/ntp:util",
+    "//ios/chrome/browser/ui/omnibox:features",
     "//ios/chrome/browser/ui/omnibox:omnibox_util",
     "//ios/chrome/browser/ui/omnibox/resources:pedal_clear_browsing_data",
     "//ios/chrome/browser/ui/omnibox/resources:pedal_default_browser",
@@ -189,6 +190,7 @@
     "//ios/chrome/browser/net:crurl",
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/colors",
+    "//ios/chrome/browser/ui/omnibox:features",
     "//ios/chrome/browser/ui/omnibox:omnibox_util",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/common/ui/colors",
diff --git a/ios/chrome/browser/ui/omnibox/popup/autocomplete_match_formatter.mm b/ios/chrome/browser/ui/omnibox/popup/autocomplete_match_formatter.mm
index 578b118a..6b477c7 100644
--- a/ios/chrome/browser/ui/omnibox/popup/autocomplete_match_formatter.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/autocomplete_match_formatter.mm
@@ -11,6 +11,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/omnibox/browser/suggestion_answer.h"
+#import "ios/chrome/browser/ui/omnibox/omnibox_ui_features.h"
 #import "ios/chrome/browser/ui/omnibox/omnibox_util.h"
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_icon_formatter.h"
 #import "ios/chrome/browser/ui/omnibox/popup/popup_swift.h"
@@ -234,6 +235,16 @@
   return _match.has_tab_match.value_or(false);
 }
 
+- (BOOL)isClipboardMatch {
+  if (base::FeatureList::IsEnabled(kOmniboxPasteButton)) {
+    return _match.type == AutocompleteMatchType::CLIPBOARD_URL ||
+           _match.type == AutocompleteMatchType::CLIPBOARD_TEXT ||
+           _match.type == AutocompleteMatchType::CLIPBOARD_IMAGE;
+  } else {
+    return NO;
+  }
+}
+
 - (id<OmniboxPedal>)pedal {
   return self.pedalData;
 }
diff --git a/ios/chrome/browser/ui/omnibox/popup/autocomplete_suggestion.h b/ios/chrome/browser/ui/omnibox/popup/autocomplete_suggestion.h
index 9546864..9921b85 100644
--- a/ios/chrome/browser/ui/omnibox/popup/autocomplete_suggestion.h
+++ b/ios/chrome/browser/ui/omnibox/popup/autocomplete_suggestion.h
@@ -24,7 +24,8 @@
 @property(nonatomic, readonly) BOOL isAppendable;
 // Some suggestions are opened in an other tab.
 @property(nonatomic, readonly) BOOL isTabMatch;
-
+// Some suggestions come from the clipboard provider.
+@property(nonatomic, readonly) BOOL isClipboardMatch;
 // Text of the suggestion.
 @property(nonatomic, readonly) NSAttributedString* text;
 // Second line of text.
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm
index 1b51668..899c34e 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm
@@ -19,6 +19,7 @@
 #import "ios/chrome/browser/ui/main/default_browser_scene_agent.h"
 #import "ios/chrome/browser/ui/main/scene_state_browser_agent.h"
 #import "ios/chrome/browser/ui/ntp/ntp_util.h"
+#import "ios/chrome/browser/ui/omnibox/omnibox_ui_features.h"
 #import "ios/chrome/browser/ui/omnibox/popup/content_providing.h"
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_pedal_annotator.h"
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_container_view.h"
@@ -105,6 +106,12 @@
         initWithStyle:isIncognito ? INCOGNITO : NORMAL];
     self.uiConfiguration = [[PopupUIConfiguration alloc]
         initWithToolbarConfiguration:toolbarConfiguration];
+    if (@available(iOS 16, *)) {
+      self.uiConfiguration.shouldDismissKeyboardOnScroll =
+          (ui::GetDeviceFormFactor() != ui::DEVICE_FORM_FACTOR_TABLET ||
+           base::FeatureList::IsEnabled(kEnableSuggestionsScrollingOnIPad));
+    }
+
     BOOL popupShouldSelfSize =
         (ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET);
     self.mediator.model = self.model;
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell_unittest.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell_unittest.mm
index d4bbab520..250e0aab 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell_unittest.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell_unittest.mm
@@ -21,6 +21,7 @@
 @property(nonatomic, assign) BOOL isURL;
 @property(nonatomic, assign) BOOL isAppendable;
 @property(nonatomic, assign) BOOL isTabMatch;
+@property(nonatomic, assign) BOOL isClipboardMatch;
 @property(nonatomic, strong) NSAttributedString* text;
 @property(nonatomic, strong) NSAttributedString* detailText;
 @property(nonatomic, assign) NSInteger numberOfLines;
diff --git a/ios/chrome/browser/ui/omnibox/popup/pedal_suggestion_wrapper.mm b/ios/chrome/browser/ui/omnibox/popup/pedal_suggestion_wrapper.mm
index 94bac0e0..1ac5c04d 100644
--- a/ios/chrome/browser/ui/omnibox/popup/pedal_suggestion_wrapper.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/pedal_suggestion_wrapper.mm
@@ -42,6 +42,9 @@
 - (BOOL)isTabMatch {
   return NO;
 }
+- (BOOL)isClipboardMatch {
+  return NO;
+}
 - (BOOL)isTailSuggestion {
   return NO;
 }
diff --git a/ios/chrome/browser/ui/omnibox/popup/shared/popup_match.swift b/ios/chrome/browser/ui/omnibox/popup/shared/popup_match.swift
index 8b7484f..02f057ea 100644
--- a/ios/chrome/browser/ui/omnibox/popup/shared/popup_match.swift
+++ b/ios/chrome/browser/ui/omnibox/popup/shared/popup_match.swift
@@ -28,6 +28,11 @@
     return suggestion.isTabMatch
   }
 
+  /// Some suggestions are from the clipboard provider.
+  var isClipboardMatch: Bool {
+    return suggestion.isClipboardMatch
+  }
+
   /// Some suggestions can be deleted with a swipe-to-delete gesture.
   var supportsDeletion: Bool {
     return suggestion.supportsDeletion
@@ -67,6 +72,7 @@
     let detailText: NSAttributedString?
     let isAppendable: Bool
     let isTabMatch: Bool
+    let isClipboardMatch: Bool
     let supportsDeletion: Bool
     let icon: OmniboxIcon?
     let pedal: (OmniboxIcon & OmniboxPedal)?
@@ -79,8 +85,8 @@
 
     init(
       text: String, detailText: String? = nil, isAppendable: Bool = false, isTabMatch: Bool = false,
-      supportsDeletion: Bool = false, icon: OmniboxIcon? = nil, hasAnswer: Bool = false,
-      numberOfLines: Int = 1, pedal: OmniboxPedalData? = nil
+      isClipboardMatch: Bool = false, supportsDeletion: Bool = false, icon: OmniboxIcon? = nil,
+      hasAnswer: Bool = false, numberOfLines: Int = 1, pedal: OmniboxPedalData? = nil
     ) {
       self.text = NSAttributedString(string: text, attributes: [:])
       self.detailText = detailText.flatMap { string in
@@ -88,6 +94,7 @@
       }
       self.isAppendable = isAppendable
       self.isTabMatch = isTabMatch
+      self.isClipboardMatch = isClipboardMatch
       self.supportsDeletion = supportsDeletion
       self.icon = icon
       self.pedal = pedal
@@ -97,7 +104,8 @@
 
     init(
       attributedText: NSAttributedString, attributedDetailText: NSAttributedString? = nil,
-      isAppendable: Bool = false, isTabMatch: Bool = false, hasAnswer: Bool = false,
+      isAppendable: Bool = false, isTabMatch: Bool = false, isClipboardMatch: Bool = false,
+      hasAnswer: Bool = false,
       supportsDeletion: Bool = false, icon: OmniboxIcon? = nil, numberOfLines: Int = 1,
       pedal: OmniboxPedalData? = nil
     ) {
@@ -105,6 +113,7 @@
       self.detailText = attributedDetailText
       self.isAppendable = isAppendable
       self.isTabMatch = isTabMatch
+      self.isClipboardMatch = isClipboardMatch
       self.supportsDeletion = supportsDeletion
       self.icon = icon
       self.pedal = pedal
diff --git a/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_row_view.swift b/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_row_view.swift
index 525f0ce..d26eace 100644
--- a/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_row_view.swift
+++ b/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_row_view.swift
@@ -211,6 +211,27 @@
         if match.isAppendable || match.isTabMatch {
           PopupMatchTrailingButton(match: match, action: trailingButtonHandler)
             .foregroundColor(isHighlighted ? highlightColor : .chromeBlue)
+        } else if match.isClipboardMatch {
+          // Clipboard matches are never appendable or tab matches.
+          #if __IPHONE_16_0
+            if #available(iOS 16.0, *) {
+              PasteButton(
+                // The clipboard suggestion row is only going to appear for these
+                // types of clipboard content.
+                supportedContentTypes: [.text, .image, .url],
+                payloadAction: { _ in
+                  DispatchQueue.main.async {
+                    // The clipboard content will be retrieved in a later stage by the
+                    // clipboard provider. After the tap on `PasteButton`, later request
+                    // on the same clipboard content won't trigger the permission popup.
+                    selectionHandler()
+                  }
+                }
+              )
+              .buttonBorderShape(.capsule)
+              .labelStyle(.iconOnly)
+            }
+          #endif  // __IPHONE_16_0
         }
         Color.clear.frame(width: trailingMarginForRowContent)
       }
diff --git a/ios/chrome/browser/ui/omnibox/popup/shared/popup_ui_configuration.swift b/ios/chrome/browser/ui/omnibox/popup/shared/popup_ui_configuration.swift
index e3efc02..5dd9cf2c 100644
--- a/ios/chrome/browser/ui/omnibox/popup/shared/popup_ui_configuration.swift
+++ b/ios/chrome/browser/ui/omnibox/popup/shared/popup_ui_configuration.swift
@@ -66,6 +66,10 @@
   /// where the text field starts.
   @PublishedOnChange var omniboxTextFieldLeadingSpace: CGFloat = 0
 
+  /// Enables keyboard dismissal. When set, the keyboard will be dismissed when popup is scrolled. The corresponding AutocompleteResultConsumer callback is then never called.
+  /// Ignored on iOS  < 16.
+  var shouldDismissKeyboardOnScroll: Bool = true
+
   /// The current toolbar configuration, used to color items that should match
   /// the toolbar's color.
   let toolbarConfiguration: ToolbarConfiguration
diff --git a/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift b/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift
index d743d0c..d65300f 100644
--- a/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift
+++ b/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift
@@ -17,6 +17,16 @@
   }
 }
 
+#if __IPHONE_16_0
+  @available(iOS 16, *)
+  struct ScrollDismissesKeyboardModifier: ViewModifier {
+    let mode: ScrollDismissesKeyboardMode
+    func body(content: Content) -> some View {
+      content.scrollDismissesKeyboard(mode)
+    }
+  }
+#endif  // __IPHONE_16_0
+
 /// Utility which provides a way to treat the `accessibilityIdentifier` view modifier as a value.
 struct AccessibilityIdentifierModifier: ViewModifier {
   let identifier: String
@@ -134,6 +144,11 @@
   /// The current height of the self-sizing list.
   @State private var selfSizingListHeight: CGFloat? = nil
 
+  /// This is an ugly workaround that is not necessary in iOS 16.
+  /// This flag is set on trailing button tap, and is reset a fraction of a second later. This
+  /// prevents the onScroll event from being dispatched to the delegate.
+  @State private var shouldIgnoreScrollEvents: Bool = false
+
   init(
     model: PopupModel, uiConfiguration: PopupUIConfiguration, shouldSelfSize: Bool = false,
     appearanceContainerType: UIAppearanceContainer.Type? = nil
@@ -186,6 +201,10 @@
           model.delegate?.autocompleteResultConsumer(
             model, didTapTrailingButtonForRow: UInt(matchIndex),
             inSection: UInt(sectionIndex))
+          shouldIgnoreScrollEvents = true
+          DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
+            shouldIgnoreScrollEvents = false
+          }
         },
         uiConfiguration: uiConfiguration,
         shouldDisplayCustomSeparator: shouldDisplayCustomSeparators(
@@ -245,16 +264,29 @@
     }
   }
 
+  func scrollModifier() -> some ViewModifier {
+    #if __IPHONE_16_0
+      if #available(iOS 16.0, *) {
+        return ScrollDismissesKeyboardModifier(
+          mode: uiConfiguration.shouldDismissKeyboardOnScroll ? .immediately : .never)
+      } else {
+        return ListScrollDetectionModifier(onScroll: onScroll)
+      }
+    #else  // __IPHONE_16_0
+      return ListScrollDetectionModifier(onScroll: onScroll)
+    #endif  // __IPHONE_16_0
+  }
+
   @ViewBuilder
   var listView: some View {
     let commonListModifier = AccessibilityIdentifierModifier(
       identifier: kOmniboxPopupTableViewAccessibilityIdentifier
     )
-    .concat(ListScrollDetectionModifier(onScroll: onScroll))
     .concat(ScrollOnChangeModifier(value: $model.sections, action: onNewSections))
     .concat(ListStyleModifier())
     .concat(EnvironmentValueModifier(\.defaultMinListHeaderHeight, 0))
     .concat(omniboxPaddingModifier)
+    .concat(scrollModifier())
 
     GeometryReader { geometry in
       ZStack(alignment: .top) {
@@ -424,6 +456,9 @@
   }
 
   func onScroll() {
+    guard !shouldIgnoreScrollEvents else {
+      return
+    }
     model.highlightedMatchIndexPath = nil
     model.delegate?.autocompleteResultConsumerDidScroll(model)
   }
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 83e898f3..ea9b794 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 @@
-e28add7579074585f2358812de8776efcef27a32
\ No newline at end of file
+1d2ca3640ff21fe577ba32bfd404c9facc14718a
\ 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 dd4ccf3..b473bf4 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 @@
-75d2c2195192db8266f3c4c3f214ac36a0634468
\ No newline at end of file
+f994274d40ce3b550d85329391a1f6c84630ba81
\ 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 20320a9..86cb68d 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 @@
-4528b355a44b47fd44587dc51c681e52641f0903
\ No newline at end of file
+ad6b36d2d292de6a109062bdf4e3e0e985cd4e92
\ 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 8a7f8d6..6443bf52 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 @@
-8990eecbbcf363af85698cacffdbf1a1adb38014
\ No newline at end of file
+539da355cee7fb5fa9bdccc4f4d871f6d78163bc
\ 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 1e149ca..2ce0c737 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 @@
-af826a673db2920221ef80504e48fceab58a7a13
\ No newline at end of file
+30f5e2c9e2a34427b84ba1765b84f4c0d532f4ed
\ 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 25165702..098d532 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 @@
-7a278100e98f913e2cd8f9b4357cced8fa1c985c
\ No newline at end of file
+88e0293c54f516d49119e2f11d2d0fadf74281b0
\ 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 3668ef41..5e14f11 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 @@
-81334c644a60a78ac290277c2bed676d641f0937
\ No newline at end of file
+c8a141fb27e68f10ceb754a2d6fb4fe274b2fc45
\ 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 d9d8366..ea264bc 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 @@
-6a5cf11949e7d42bfbe98995d29477b09a717c40
\ No newline at end of file
+0d6d89f9651c5cde59d6f55dcf5c3c70721d1fff
\ 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 661ffcc..3774eb3 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 @@
-a9e4fd58c599b71d271aaf59561bca20f6e67423
\ No newline at end of file
+75c1939d938f398c74779ad221a5d07d8e41a3d4
\ 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 e8481e56..8b437ef 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 @@
-a57095dd2db43bd3263c05bb74223e21f59a670f
\ No newline at end of file
+d34be43ec81fd96994c95b0d3fc9868c9775d792
\ No newline at end of file
diff --git a/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm b/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm
index 0b7f9bc..7e6a6ec9 100644
--- a/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm
+++ b/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm
@@ -281,6 +281,8 @@
 
 @implementation FakeAutocompleteSuggestion
 
+@synthesize isClipboardMatch = _isClipboardMatch;
+
 - (instancetype)init {
   self = [super init];
   if (self) {
@@ -292,6 +294,7 @@
         [[UIImage imageNamed:@"omnibox_completion_default_favicon"]
             imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
     _icon = [[SimpleOmniboxIcon alloc] init];
+    _isClipboardMatch = NO;
   }
   return self;
 }
diff --git a/media/gpu/vaapi/vaapi_video_decode_accelerator.cc b/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
index 3a07fa21..bf791d8 100644
--- a/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
+++ b/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
@@ -44,7 +44,6 @@
 #include "media/gpu/vp8_decoder.h"
 #include "media/gpu/vp9_decoder.h"
 #include "media/video/picture.h"
-#include "ui/gl/gl_image.h"
 
 namespace media {
 
diff --git a/media/gpu/windows/d3d11_h264_accelerator.h b/media/gpu/windows/d3d11_h264_accelerator.h
index 0f3693d..d9d9d6d 100644
--- a/media/gpu/windows/d3d11_h264_accelerator.h
+++ b/media/gpu/windows/d3d11_h264_accelerator.h
@@ -25,7 +25,6 @@
 #include "media/video/picture.h"
 #include "third_party/angle/include/EGL/egl.h"
 #include "third_party/angle/include/EGL/eglext.h"
-#include "ui/gl/gl_image.h"
 
 namespace media {
 
diff --git a/media/gpu/windows/d3d11_h265_accelerator.h b/media/gpu/windows/d3d11_h265_accelerator.h
index c2f43b5..8397622 100644
--- a/media/gpu/windows/d3d11_h265_accelerator.h
+++ b/media/gpu/windows/d3d11_h265_accelerator.h
@@ -25,7 +25,6 @@
 #include "media/video/picture.h"
 #include "third_party/angle/include/EGL/egl.h"
 #include "third_party/angle/include/EGL/eglext.h"
-#include "ui/gl/gl_image.h"
 
 namespace media {
 
diff --git a/media/gpu/windows/d3d11_picture_buffer.h b/media/gpu/windows/d3d11_picture_buffer.h
index 6aabb56..e63b9231 100644
--- a/media/gpu/windows/d3d11_picture_buffer.h
+++ b/media/gpu/windows/d3d11_picture_buffer.h
@@ -25,7 +25,6 @@
 #include "media/video/picture.h"
 #include "third_party/angle/include/EGL/egl.h"
 #include "third_party/angle/include/EGL/eglext.h"
-#include "ui/gl/gl_image.h"
 
 namespace media {
 
diff --git a/media/gpu/windows/d3d11_texture_wrapper.cc b/media/gpu/windows/d3d11_texture_wrapper.cc
index 59c3e39..5b5f9644 100644
--- a/media/gpu/windows/d3d11_texture_wrapper.cc
+++ b/media/gpu/windows/d3d11_texture_wrapper.cc
@@ -18,7 +18,6 @@
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/win/mf_helpers.h"
 #include "mojo/public/cpp/bindings/callback_helpers.h"
-#include "ui/gl/gl_image.h"
 
 namespace media {
 
diff --git a/media/gpu/windows/d3d11_texture_wrapper_unittest.cc b/media/gpu/windows/d3d11_texture_wrapper_unittest.cc
index e5b4543..93c4b0b 100644
--- a/media/gpu/windows/d3d11_texture_wrapper_unittest.cc
+++ b/media/gpu/windows/d3d11_texture_wrapper_unittest.cc
@@ -17,7 +17,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gl/gl_context_egl.h"
 #include "ui/gl/gl_egl_api_implementation.h"
-#include "ui/gl/gl_image.h"
 #include "ui/gl/gl_share_group.h"
 #include "ui/gl/gl_surface.h"
 #include "ui/gl/init/gl_factory.h"
diff --git a/media/gpu/windows/d3d11_video_decoder.cc b/media/gpu/windows/d3d11_video_decoder.cc
index b9d7931..4669bea 100644
--- a/media/gpu/windows/d3d11_video_decoder.cc
+++ b/media/gpu/windows/d3d11_video_decoder.cc
@@ -14,6 +14,7 @@
 #include "base/debug/crash_logging.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/feature_list.h"
+#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted_delete_on_sequence.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
diff --git a/media/gpu/windows/d3d11_video_decoder.h b/media/gpu/windows/d3d11_video_decoder.h
index f1ee977..a3ec976 100644
--- a/media/gpu/windows/d3d11_video_decoder.h
+++ b/media/gpu/windows/d3d11_video_decoder.h
@@ -6,6 +6,7 @@
 #define MEDIA_GPU_WINDOWS_D3D11_VIDEO_DECODER_H_
 
 #include <d3d11.h>
+#include <list>
 #include <vector>
 
 #include "base/memory/ptr_util.h"
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index 9f9d54b..c2824b6 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -989,6 +989,10 @@
       url_request_context_, std::move(filter), start_time, end_time,
       base::BindOnce(&NetworkContext::OnHttpCacheCleared,
                      base::Unretained(this), std::move(callback))));
+
+  NetworkServiceMemoryCache* memory_cache = GetMemoryCache();
+  if (memory_cache)
+    memory_cache->Clear();
 }
 
 void NetworkContext::ComputeHttpCacheSize(
diff --git a/services/network/network_service_memory_cache.cc b/services/network/network_service_memory_cache.cc
index 90b46ecc..495794b1 100644
--- a/services/network/network_service_memory_cache.cc
+++ b/services/network/network_service_memory_cache.cc
@@ -66,6 +66,10 @@
 
 NetworkServiceMemoryCache::~NetworkServiceMemoryCache() = default;
 
+void NetworkServiceMemoryCache::Clear() {
+  entries_.Clear();
+}
+
 base::WeakPtr<NetworkServiceMemoryCache>
 NetworkServiceMemoryCache::GetWeakPtr() {
   return weak_ptr_factory_.GetWeakPtr();
diff --git a/services/network/network_service_memory_cache.h b/services/network/network_service_memory_cache.h
index d5fb185..8f32596 100644
--- a/services/network/network_service_memory_cache.h
+++ b/services/network/network_service_memory_cache.h
@@ -47,6 +47,9 @@
 
   base::WeakPtr<NetworkServiceMemoryCache> GetWeakPtr();
 
+  // Clears all cache entries.
+  void Clear();
+
   // Creates a NetworkServiceMemoryCacheWriter when the response is 200 and it
   // can be cacheable.
   std::unique_ptr<NetworkServiceMemoryCacheWriter> MaybeCreateWriter(
diff --git a/services/network/network_service_memory_cache_unittest.cc b/services/network/network_service_memory_cache_unittest.cc
index 7cf27a1..1f12bdb 100644
--- a/services/network/network_service_memory_cache_unittest.cc
+++ b/services/network/network_service_memory_cache_unittest.cc
@@ -459,6 +459,33 @@
   ASSERT_TRUE(CanServeFromMemoryCache(request3));
 }
 
+TEST_F(NetworkServiceMemoryCacheTest, Clear) {
+  constexpr int kBodySize = 64;
+
+  // Stores three responses.
+  ResourceRequest request1 = CreateRequest(
+      base::StringPrintf("/cacheable?id=1&body-size=%d", kBodySize));
+  StoreResponseToMemoryCache(request1);
+
+  ResourceRequest request2 = CreateRequest(
+      base::StringPrintf("/cacheable?id=2&body-size=%d", kBodySize));
+  StoreResponseToMemoryCache(request2);
+
+  ResourceRequest request3 = CreateRequest(
+      base::StringPrintf("/cacheable?id=3&body-size=%d", kBodySize));
+  StoreResponseToMemoryCache(request3);
+
+  ASSERT_TRUE(CanServeFromMemoryCache(request1));
+  ASSERT_TRUE(CanServeFromMemoryCache(request2));
+  ASSERT_TRUE(CanServeFromMemoryCache(request3));
+
+  memory_cache().Clear();
+
+  ASSERT_FALSE(CanServeFromMemoryCache(request1));
+  ASSERT_FALSE(CanServeFromMemoryCache(request2));
+  ASSERT_FALSE(CanServeFromMemoryCache(request3));
+}
+
 TEST_F(NetworkServiceMemoryCacheTest, ClientDisconnectedWhileCaching) {
   ResourceRequest request = CreateRequest("/cacheable");
   LoaderPair pair = CreateLoaderAndStart(request);
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 537e8796..a284e8c 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -8331,15 +8331,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8416,15 +8416,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8841,15 +8841,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8926,15 +8926,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 5913518..18df060 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -46508,15 +46508,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -46593,15 +46593,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47018,15 +47018,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47103,15 +47103,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47532,15 +47532,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47617,15 +47617,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48042,15 +48042,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48127,15 +48127,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48624,15 +48624,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48709,15 +48709,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49134,15 +49134,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49219,15 +49219,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49716,15 +49716,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49801,15 +49801,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -50226,15 +50226,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -50311,15 +50311,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index e52d3c1..4cac2a9 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -529,16 +529,16 @@
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
-      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--implementation-outdir',
-      '../../weblayer_instrumentation_test_M104/out/Release',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--impl-version=104',
+      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
+      '--implementation-outdir',
+      '../../weblayer_instrumentation_test_M104/out/Release',
+      '--impl-version=104'
     ],
     'identifier': 'with_impl_from_104',
     'swarming': {
@@ -546,23 +546,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.35',
+          'revision': 'version:104.0.5112.35'
         }
-      ],
-    },
+      ]
+    }
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
-      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--implementation-outdir',
-      '../../weblayer_instrumentation_test_M103/out/Release',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--impl-version=103',
+      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
+      '--implementation-outdir',
+      '../../weblayer_instrumentation_test_M103/out/Release',
+      '--impl-version=103'
     ],
     'identifier': 'with_impl_from_103',
     'swarming': {
@@ -570,10 +570,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.117',
+          'revision': 'version:103.0.5060.117'
         }
-      ],
-    },
+      ]
+    }
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -673,16 +673,16 @@
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--implementation-outdir',
-      '../../weblayer_instrumentation_test_M104/out/Release',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--impl-version=104',
+      '--webview-apk-path=apks/SystemWebView.apk',
+      '--implementation-outdir',
+      '../../weblayer_instrumentation_test_M104/out/Release',
+      '--impl-version=104'
     ],
     'identifier': 'with_impl_from_104',
     'swarming': {
@@ -690,23 +690,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.35',
+          'revision': 'version:104.0.5112.35'
         }
-      ],
-    },
+      ]
+    }
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--implementation-outdir',
-      '../../weblayer_instrumentation_test_M103/out/Release',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--impl-version=103',
+      '--webview-apk-path=apks/SystemWebView.apk',
+      '--implementation-outdir',
+      '../../weblayer_instrumentation_test_M103/out/Release',
+      '--impl-version=103'
     ],
     'identifier': 'with_impl_from_103',
     'swarming': {
@@ -714,10 +714,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.117',
+          'revision': 'version:103.0.5060.117'
         }
-      ],
-    },
+      ]
+    }
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -817,16 +817,16 @@
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
-      '--client-outdir',
-      '../../weblayer_instrumentation_test_M104/out/Release',
       '--implementation-outdir',
       '.',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--client-version=104',
+      '--webview-apk-path=apks/SystemWebView.apk',
+      '--client-outdir',
+      '../../weblayer_instrumentation_test_M104/out/Release',
+      '--client-version=104'
     ],
     'identifier': 'with_client_from_104',
     'swarming': {
@@ -834,23 +834,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.35',
+          'revision': 'version:104.0.5112.35'
         }
-      ],
-    },
+      ]
+    }
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
-      '--client-outdir',
-      '../../weblayer_instrumentation_test_M103/out/Release',
       '--implementation-outdir',
       '.',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--client-version=103',
+      '--webview-apk-path=apks/SystemWebView.apk',
+      '--client-outdir',
+      '../../weblayer_instrumentation_test_M103/out/Release',
+      '--client-version=103'
     ],
     'identifier': 'with_client_from_103',
     'swarming': {
@@ -858,10 +858,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.117',
+          'revision': 'version:103.0.5060.117'
         }
-      ],
-    },
+      ]
+    }
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
diff --git a/third_party/blink/public/mojom/frame/policy_container.mojom b/third_party/blink/public/mojom/frame/policy_container.mojom
index e772879..f769bc3 100644
--- a/third_party/blink/public/mojom/frame/policy_container.mojom
+++ b/third_party/blink/public/mojom/frame/policy_container.mojom
@@ -7,7 +7,12 @@
 import "services/network/public/mojom/content_security_policy.mojom";
 import "services/network/public/mojom/cross_origin_embedder_policy.mojom";
 import "services/network/public/mojom/referrer_policy.mojom";
+import "services/network/public/mojom/web_sandbox_flags.mojom";
 
+// This are the document policies contained within PolicyContainer. These are
+// owned by the browser, and remain constant for the lifetime of the document
+// except for referrer_policy and content_security_policies which might be
+// updated through meta tags (see PolicyContainerHost).
 struct PolicyContainerPolicies {
   network.mojom.CrossOriginEmbedderPolicyValue cross_origin_embedder_policy =
     network.mojom.CrossOriginEmbedderPolicyValue.kNone;
@@ -15,6 +20,8 @@
     network.mojom.ReferrerPolicy.kDefault;
   array<network.mojom.ContentSecurityPolicy> content_security_policies;
   bool is_anonymous = false;
+  network.mojom.WebSandboxFlags sandbox_flags =
+    network.mojom.WebSandboxFlags.kNone;
 };
 
 // This interface is implemented in the browser process. It defines methods to
diff --git a/third_party/blink/public/mojom/navigation/navigation_params.mojom b/third_party/blink/public/mojom/navigation/navigation_params.mojom
index 39fe3e4..6f5c6c9 100644
--- a/third_party/blink/public/mojom/navigation/navigation_params.mojom
+++ b/third_party/blink/public/mojom/navigation/navigation_params.mojom
@@ -283,15 +283,6 @@
   // taking into account the origin computed by the renderer.
   blink.mojom.StorageKey storage_key;
 
-  // The sandbox flags to apply to the new document. This is the union of:
-  // - the frame's current sandbox, taken when the navigation started.
-  // - the navigation response's CSP sandbox flags.
-  // - the result of CSP embedded enforcement required CSP sandbox flags.
-  // - Various edge cases: MHTML document, error pages, ...
-  // See content/browser/renderer_host/sandbox_flags.md
-  network.mojom.WebSandboxFlags sandbox_flags =
-    network.mojom.WebSandboxFlags.kAll;
-
   // Whether or not the user agent override string should be used.
   bool is_overriding_user_agent = false;
 
diff --git a/third_party/blink/public/mojom/timing/resource_timing.mojom b/third_party/blink/public/mojom/timing/resource_timing.mojom
index 65dddd4a..09911f3 100644
--- a/third_party/blink/public/mojom/timing/resource_timing.mojom
+++ b/third_party/blink/public/mojom/timing/resource_timing.mojom
@@ -118,4 +118,8 @@
   // PerformanceResourceTiming. See
   // https://w3c.github.io/server-timing/#extension-to-the-performanceresourcetiming-interface
   array<ServerTimingInfo> server_timing;
+
+  // Holds the boolean used to determine |renderBlockingStatus| in
+  // PerformanceResourceTiming (http://www.w3.org/TR/resource-timing-2/).
+  bool render_blocking_status;
 };
\ No newline at end of file
diff --git a/third_party/blink/public/platform/DEPS b/third_party/blink/public/platform/DEPS
index 04aa0d8..df1c7750 100644
--- a/third_party/blink/public/platform/DEPS
+++ b/third_party/blink/public/platform/DEPS
@@ -70,6 +70,7 @@
     "+services/network/public/mojom/url_loader_factory.mojom-shared.h",
     "+services/network/public/mojom/url_response_head.mojom-forward.h",
     "+services/network/public/mojom/web_client_hints_types.mojom-shared.h",
+    "+services/network/public/mojom/web_sandbox_flags.mojom-shared.h",
 
     "+services/service_manager/public/mojom",
     "+third_party/blink/public/common/web_cache/web_cache_resource_type_stats.h",
diff --git a/third_party/blink/public/platform/web_policy_container.h b/third_party/blink/public/platform/web_policy_container.h
index 9cacdbbf..2c391b9 100644
--- a/third_party/blink/public/platform/web_policy_container.h
+++ b/third_party/blink/public/platform/web_policy_container.h
@@ -7,6 +7,7 @@
 
 #include "services/network/public/mojom/cross_origin_embedder_policy.mojom-shared.h"
 #include "services/network/public/mojom/referrer_policy.mojom-shared.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
 #include "third_party/blink/public/mojom/frame/policy_container.mojom-shared.h"
 #include "third_party/blink/public/platform/cross_variant_mojo_util.h"
 #include "third_party/blink/public/platform/web_content_security_policy_struct.h"
@@ -17,15 +18,21 @@
 // TODO(antoniosartori): Remove this when CommitNavigation IPC will be handled
 // directly in blink.
 struct WebPolicyContainerPolicies {
-  network::mojom::CrossOriginEmbedderPolicyValue cross_origin_embedder_policy;
-  network::mojom::ReferrerPolicy referrer_policy;
+  network::mojom::CrossOriginEmbedderPolicyValue cross_origin_embedder_policy =
+      network::mojom::CrossOriginEmbedderPolicyValue::kNone;
+  network::mojom::ReferrerPolicy referrer_policy =
+      network::mojom::ReferrerPolicy::kDefault;
   WebVector<WebContentSecurityPolicy> content_security_policies;
-  bool is_anonymous;
+  bool is_anonymous = false;
+  network::mojom::WebSandboxFlags sandbox_flags =
+      network::mojom::WebSandboxFlags::kNone;
 };
 
 // TODO(antoniosartori): Remove this when CommitNavigation IPC will be handled
 // directly in blink.
 struct WebPolicyContainer {
+  WebPolicyContainer() = default;
+
   WebPolicyContainer(
       WebPolicyContainerPolicies policies,
       CrossVariantMojoAssociatedRemote<mojom::PolicyContainerHostInterfaceBase>
diff --git a/third_party/blink/public/web/web_navigation_params.h b/third_party/blink/public/web/web_navigation_params.h
index 5927e37e..22626f68 100644
--- a/third_party/blink/public/web/web_navigation_params.h
+++ b/third_party/blink/public/web/web_navigation_params.h
@@ -324,15 +324,6 @@
   // taking into account the origin computed by the renderer.
   StorageKey storage_key;
 
-  // The sandbox flags to apply to the new document. This is the union of:
-  // - the frame's current sandbox attribute, taken when the navigation started.
-  // - the navigation response's CSP sandbox flags.
-  // - the result of CSP embedded enforcement required CSP sandbox flags.
-  // - Various edge cases: MHTML document, error pages, ...
-  // See content/browser/renderer_host/sandbox_flags.md
-  network::mojom::WebSandboxFlags sandbox_flags =
-      network::mojom::WebSandboxFlags::kAll;
-
   // The devtools token for this navigation. See DocumentLoader
   // for details.
   base::UnguessableToken devtools_navigation_token;
diff --git a/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc b/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc
index 35374fde..151a2d5 100644
--- a/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc
+++ b/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc
@@ -99,9 +99,21 @@
     }
     if (auto* tracker =
             ThreadScheduler::Current()->GetTaskAttributionTracker()) {
-      task_attribution_scope_ =
-          tracker->CreateTaskScope(callback_->CallbackRelevantScriptState(),
-                                   callback_->GetParentTaskId());
+      // There are 3 possible callbacks here:
+      // a) Callbacks which track their registering task as their parent
+      // b) Callbacks which don't do the above, split into two groups:
+      //   1) If there's a current running task, use it as your parent. We could
+      //   have also elided creating a new scope entirely. 2) If there is no
+      //   current running task, set the parent to absl::nullopt, making the
+      //   current callback a root task.
+      absl::optional<scheduler::TaskId> parent_id =
+          callback_->GetParentTaskId();
+      if (!parent_id) {
+        parent_id =
+            tracker->RunningTaskId(callback_->CallbackRelevantScriptState());
+      }
+      task_attribution_scope_ = tracker->CreateTaskScope(
+          callback_->CallbackRelevantScriptState(), parent_id);
     }
   }
 
diff --git a/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc b/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
index aa1d9cc6..958b916 100644
--- a/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
+++ b/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
@@ -44,6 +44,7 @@
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
 namespace blink {
@@ -61,6 +62,10 @@
           BindingSecurity::ErrorReportOption::kDoNotReport)) {
     function_ = handler;
     arguments_ = arguments;
+    auto* tracker = ThreadScheduler::Current()->GetTaskAttributionTracker();
+    if (tracker && script_state->World().IsMainWorld()) {
+      function_->SetParentTaskId(tracker->RunningTaskId(script_state));
+    }
   } else {
     UseCounter::Count(target, WebFeature::kScheduledActionIgnored);
   }
diff --git a/third_party/blink/renderer/bindings/generated_in_core.gni b/third_party/blink/renderer/bindings/generated_in_core.gni
index 8fe675d..dae1ae2a 100644
--- a/third_party/blink/renderer/bindings/generated_in_core.gni
+++ b/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -321,6 +321,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_readable_writable_pair.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_reporting_observer_options.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_reporting_observer_options.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_request_duplex.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_request_duplex.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_request_init.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_request_init.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_resize_observer_options.cc",
diff --git a/third_party/blink/renderer/core/dom/document_test.cc b/third_party/blink/renderer/core/dom/document_test.cc
index 9533b2d7..4bfe654 100644
--- a/third_party/blink/renderer/core/dom/document_test.cc
+++ b/third_party/blink/renderer/core/dom/document_test.cc
@@ -76,6 +76,7 @@
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/core/page/validation_message_client.h"
 #include "third_party/blink/renderer/core/testing/color_scheme_helper.h"
+#include "third_party/blink/renderer/core/testing/mock_policy_container_host.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/core/testing/scoped_mock_overlay_scrollbars.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_request.h"
@@ -114,7 +115,12 @@
   void NavigateWithSandbox(const KURL& url) {
     auto params = WebNavigationParams::CreateWithHTMLStringForTesting(
         /*html=*/"", url);
-    params->sandbox_flags = network::mojom::blink::WebSandboxFlags::kAll;
+    MockPolicyContainerHost mock_policy_container_host;
+    params->policy_container = std::make_unique<blink::WebPolicyContainer>(
+        blink::WebPolicyContainerPolicies(),
+        mock_policy_container_host.BindNewEndpointAndPassDedicatedRemote());
+    params->policy_container->policies.sandbox_flags =
+        network::mojom::blink::WebSandboxFlags::kAll;
     GetFrame().Loader().CommitNavigation(std::move(params),
                                          /*extra_data=*/nullptr);
     test::RunPendingTasks();
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index c3b623d..2b2bcd6 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -594,10 +594,6 @@
   // contexts: if ancestorBC's active document's origin is not same origin with
   // target's origin, then return.
   for (Frame* frame = doc.GetFrame(); frame; frame = frame->Parent()) {
-    // TODO(crbug.com/1318055): With MPArch there may be multiple main frames so
-    // we should use IsCrossOriginToOutermostMainFrame when we intend to check
-    // if any embedded frame (eg, iframe or fenced frame) is cross-origin with
-    // respect to the outermost main frame. Follow up to confirm correctness.
     if (!frame->IsCrossOriginToOutermostMainFrame())
       continue;
     window->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc
index ffa2fac..a72b46b 100644
--- a/third_party/blink/renderer/core/dom/node.cc
+++ b/third_party/blink/renderer/core/dom/node.cc
@@ -2336,10 +2336,16 @@
     builder.Append(" ");
     builder.Append(nodeValue().EncodeForDebugging());
     return builder.ReleaseString();
+  } else if (const auto* element = DynamicTo<Element>(this)) {
+    const AtomicString& pseudo = element->ShadowPseudoId();
+    if (!pseudo.IsEmpty()) {
+      builder.Append(" ::");
+      builder.Append(pseudo);
+    }
+    DumpAttributeDesc(*this, html_names::kIdAttr, builder);
+    DumpAttributeDesc(*this, html_names::kClassAttr, builder);
+    DumpAttributeDesc(*this, html_names::kStyleAttr, builder);
   }
-  DumpAttributeDesc(*this, html_names::kIdAttr, builder);
-  DumpAttributeDesc(*this, html_names::kClassAttr, builder);
-  DumpAttributeDesc(*this, html_names::kStyleAttr, builder);
   if (IsEditable(*this))
     builder.Append(" (editable)");
   if (GetDocument().FocusedElement() == this)
diff --git a/third_party/blink/renderer/core/execution_context/execution_context.cc b/third_party/blink/renderer/core/execution_context/execution_context.cc
index a38cecd..b672e8f 100644
--- a/third_party/blink/renderer/core/execution_context/execution_context.cc
+++ b/third_party/blink/renderer/core/execution_context/execution_context.cc
@@ -533,6 +533,8 @@
 void ExecutionContext::SetPolicyContainer(
     std::unique_ptr<PolicyContainer> container) {
   policy_container_ = std::move(container);
+  security_context_.SetSandboxFlags(
+      policy_container_->GetPolicies().sandbox_flags);
 }
 
 std::unique_ptr<PolicyContainer> ExecutionContext::TakePolicyContainer() {
diff --git a/third_party/blink/renderer/core/execution_context/security_context.h b/third_party/blink/renderer/core/execution_context/security_context.h
index 0f4dda9..385ec0fb 100644
--- a/third_party/blink/renderer/core/execution_context/security_context.h
+++ b/third_party/blink/renderer/core/execution_context/security_context.h
@@ -37,7 +37,6 @@
 #include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink-forward.h"
 #include "third_party/blink/public/platform/web_vector.h"
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/execution_context/security_context.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/third_party/blink/renderer/core/exported/web_document_test.cc b/third_party/blink/renderer/core/exported/web_document_test.cc
index 2c4b5a86..6e2b78b 100644
--- a/third_party/blink/renderer/core/exported/web_document_test.cc
+++ b/third_party/blink/renderer/core/exported/web_document_test.cc
@@ -21,6 +21,7 @@
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/core/testing/mock_policy_container_host.h"
 #include "third_party/blink/renderer/platform/graphics/color.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
@@ -282,7 +283,12 @@
   WebLocalFrameImpl* frame = web_view_helper_.GetWebView()->MainFrameImpl();
   auto params = WebNavigationParams::CreateWithHTMLStringForTesting(
       /*html=*/"", KURL("https://a.com"));
-  params->sandbox_flags = network::mojom::blink::WebSandboxFlags::kAll;
+  MockPolicyContainerHost mock_policy_container_host;
+  params->policy_container = std::make_unique<blink::WebPolicyContainer>(
+      blink::WebPolicyContainerPolicies(),
+      mock_policy_container_host.BindNewEndpointAndPassDedicatedRemote());
+  params->policy_container->policies.sandbox_flags =
+      network::mojom::blink::WebSandboxFlags::kAll;
   frame->CommitNavigation(std::move(params), nullptr /* extra_data */);
   frame_test_helpers::PumpPendingRequestsForFrameToLoad(frame);
 
diff --git a/third_party/blink/renderer/core/exported/web_navigation_params.cc b/third_party/blink/renderer/core/exported/web_navigation_params.cc
index 4d2ef0f..17fb81d 100644
--- a/third_party/blink/renderer/core/exported/web_navigation_params.cc
+++ b/third_party/blink/renderer/core/exported/web_navigation_params.cc
@@ -42,7 +42,6 @@
       info.initiator_origin_trial_features;
   result->frame_policy = info.frame_policy;
   result->had_transient_user_activation = info.url_request.HasUserGesture();
-  result->sandbox_flags = info.frame_policy.sandbox_flags;
   return result;
 }
 
@@ -52,7 +51,6 @@
                                                     const WebURL& base_url) {
   auto result = std::make_unique<WebNavigationParams>();
   result->url = base_url;
-  result->sandbox_flags = network::mojom::WebSandboxFlags::kNone;
   FillStaticResponse(result.get(), "text/html", "UTF-8", html);
   return result;
 }
@@ -65,7 +63,6 @@
     const KURL& base_url) {
   auto result = std::make_unique<WebNavigationParams>();
   result->url = base_url;
-  result->sandbox_flags = network::mojom::WebSandboxFlags::kNone;
   FillStaticResponse(result.get(), "text/html", "UTF-8",
                      base::make_span(buffer->Data(), buffer->size()));
   return result;
diff --git a/third_party/blink/renderer/core/fetch/request.cc b/third_party/blink/renderer/core/fetch/request.cc
index 29579a6..221dfbf 100644
--- a/third_party/blink/renderer/core/fetch/request.cc
+++ b/third_party/blink/renderer/core/fetch/request.cc
@@ -119,7 +119,7 @@
          init->hasReferrer() || init->hasReferrerPolicy() || init->hasMode() ||
          init->hasCredentials() || init->hasCache() || init->hasRedirect() ||
          init->hasIntegrity() || init->hasKeepalive() || init->hasPriority() ||
-         init->hasSignal() || init->hasTrustToken();
+         init->hasSignal() || init->hasDuplex() || init->hasTrustToken();
 }
 
 static BodyStreamBuffer* ExtractBody(ScriptState* script_state,
@@ -677,8 +677,18 @@
       return nullptr;
   }
 
-  // "If |body| is non-null and |body|’s source is null, then:"
+  // "If `inputOrInitBody` is non-null and `inputOrInitBody`’s source is null,
+  // then:"
   if (body && body->IsMadeFromReadableStream()) {
+    // "If `initBody` is non-null and `init["duplex"]` does not exist, then
+    // throw a TypeError."
+    if (!init_body.IsEmpty() && !init_body->IsNull() && !init->hasDuplex()) {
+      exception_state.ThrowTypeError(
+          "The `duplex` member must be specified for a request with a "
+          "streaming body");
+      return nullptr;
+    }
+
     // "If |this|’s request’s mode is neither "same-origin" nor "cors", then
     // throw a TypeError."
     if (request->Mode() != network::mojom::RequestMode::kSameOrigin &&
diff --git a/third_party/blink/renderer/core/fetch/request.idl b/third_party/blink/renderer/core/fetch/request.idl
index 4341bd0..644898e 100644
--- a/third_party/blink/renderer/core/fetch/request.idl
+++ b/third_party/blink/renderer/core/fetch/request.idl
@@ -14,6 +14,7 @@
 enum RequestCache { "default", "no-store", "reload", "no-cache", "force-cache",
                     "only-if-cached" };
 enum FetchPriority {"low", "auto", "high"};
+enum RequestDuplex {"half"};
 
 // https://w3c.github.io/webappsec-referrer-policy/#referrer-policies
 
diff --git a/third_party/blink/renderer/core/fetch/request_init.idl b/third_party/blink/renderer/core/fetch/request_init.idl
index ce2c4b2..5039d22 100644
--- a/third_party/blink/renderer/core/fetch/request_init.idl
+++ b/third_party/blink/renderer/core/fetch/request_init.idl
@@ -23,6 +23,7 @@
     boolean keepalive;
     [RuntimeEnabled=PriorityHints] FetchPriority priority;
     AbortSignal? signal;
+    [RuntimeEnabled=FetchUploadStreaming] RequestDuplex duplex;
     // Even though Trust Tokens operations are only available in secure
     // contexts, this has to be enforced after the fact because the
     // SecureContext IDL attribute doesn't affect dictionary members.
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
index edfd3a3f..755bf03 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -42,6 +42,7 @@
 #include "cc/trees/render_frame_metadata_observer.h"
 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
+#include "services/network/public/cpp/web_sandbox_flags.h"
 #include "services/network/public/mojom/content_security_policy.mojom-blink-forward.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/frame/fenced_frame_sandbox_flags.h"
@@ -175,7 +176,7 @@
     params->policy_container = std::make_unique<WebPolicyContainer>(
         WebPolicyContainerPolicies(),
         mock_policy_container_host.BindNewEndpointAndPassDedicatedRemote());
-    params->sandbox_flags =
+    params->policy_container->policies.sandbox_flags =
         static_cast<TestWebFrameClient*>(frame->Client())->sandbox_flags();
     FillNavigationParamsResponse(params.get());
     impl->CommitNavigation(std::move(params), nullptr /* extra_data */);
@@ -195,7 +196,6 @@
   std::unique_ptr<WebNavigationParams> navigation_params =
       WebNavigationParams::CreateWithHTMLStringForTesting(html, base_url);
   navigation_params->tick_clock = clock;
-  navigation_params->sandbox_flags = network::mojom::WebSandboxFlags::kNone;
   impl->CommitNavigation(std::move(navigation_params),
                          nullptr /* extra_data */);
   PumpPendingRequestsForFrameToLoad(frame);
@@ -212,8 +212,6 @@
   params->history_item = item;
   params->navigation_timings.navigation_start = base::TimeTicks::Now();
   params->navigation_timings.fetch_start = base::TimeTicks::Now();
-  params->sandbox_flags =
-      static_cast<TestWebFrameClient*>(frame->Client())->sandbox_flags();
   FillNavigationParamsResponse(params.get());
   impl->CommitNavigation(std::move(params), nullptr /* extra_data */);
   PumpPendingRequestsForFrameToLoad(frame);
@@ -252,6 +250,7 @@
            network::mojom::blink::ContentSecurityPolicyType::kEnforce,
            network::mojom::blink::ContentSecurityPolicySource::kHTTP,
            params->response.ResponseUrl())) {
+    params->policy_container->policies.sandbox_flags |= csp->sandbox;
     params->policy_container->policies.content_security_policies.emplace_back(
         ConvertToPublic(std::move(csp)));
   }
@@ -764,6 +763,13 @@
       mock_policy_container_host.BindNewEndpointAndPassDedicatedRemote());
   if (info->archive_status != WebNavigationInfo::ArchiveStatus::Present)
     FillNavigationParamsResponse(params.get());
+  // Merge frame policy sandbox flags in the policy container's sandbox flags.
+  // This is required since we are initializing policy container above and it
+  // must contain the frame's sandbox flags. This is normally done by the
+  // browser process during the navigation when computing the policy container
+  // and the included sandbox flags to commit, and then passed on within the
+  // WebNavigationParams.
+  params->policy_container->policies.sandbox_flags |= sandbox_flags();
   frame_->CommitNavigation(std::move(params), nullptr /* extra_data */);
 }
 
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index 0ef9e5c..6633a96 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -137,6 +137,7 @@
 #include "third_party/blink/renderer/platform/network/network_state_notifier.h"
 #include "third_party/blink/renderer/platform/scheduler/public/dummy_schedulers.h"
 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "third_party/blink/renderer/platform/storage/blink_storage_key.h"
 #include "third_party/blink/renderer/platform/timer.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -1826,6 +1827,11 @@
 }
 
 void LocalDOMWindow::queueMicrotask(V8VoidFunction* callback) {
+  ScriptState* script_state = callback->CallbackRelevantScriptState();
+  auto* tracker = ThreadScheduler::Current()->GetTaskAttributionTracker();
+  if (tracker && script_state->World().IsMainWorld()) {
+    callback->SetParentTaskId(tracker->RunningTaskId(script_state));
+  }
   Microtask::EnqueueMicrotask(
       WTF::Bind(&V8VoidFunction::InvokeAndReportException,
                 WrapPersistent(callback), nullptr));
diff --git a/third_party/blink/renderer/core/frame/local_dom_window_test.cc b/third_party/blink/renderer/core/frame/local_dom_window_test.cc
index 70d84d5..11bb16a 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window_test.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window_test.cc
@@ -42,6 +42,7 @@
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/inspector/console_message_storage.h"
+#include "third_party/blink/renderer/core/testing/mock_policy_container_host.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -64,7 +65,11 @@
       WebSandboxFlags sandbox_flags = WebSandboxFlags::kAll) {
     auto params = WebNavigationParams::CreateWithHTMLStringForTesting(
         /*html=*/"", url);
-    params->sandbox_flags = sandbox_flags;
+    MockPolicyContainerHost mock_policy_container_host;
+    params->policy_container = std::make_unique<blink::WebPolicyContainer>(
+        blink::WebPolicyContainerPolicies(),
+        mock_policy_container_host.BindNewEndpointAndPassDedicatedRemote());
+    params->policy_container->policies.sandbox_flags = sandbox_flags;
     GetFrame().Loader().CommitNavigation(std::move(params),
                                          /*extra_data=*/nullptr);
     test::RunPendingTasks();
diff --git a/third_party/blink/renderer/core/frame/mhtml_loading_test.cc b/third_party/blink/renderer/core/frame/mhtml_loading_test.cc
index b10dfae..ce80dca 100644
--- a/third_party/blink/renderer/core/frame/mhtml_loading_test.cc
+++ b/third_party/blink/renderer/core/frame/mhtml_loading_test.cc
@@ -46,6 +46,7 @@
 #include "third_party/blink/renderer/core/frame/location.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/testing/mock_policy_container_host.h"
 #include "third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
@@ -86,7 +87,11 @@
     params->response.SetMimeType("multipart/related");
     params->response.SetHttpStatusCode(200);
     params->response.SetExpectedContentLength(buffer->size());
-    params->sandbox_flags = kMhtmlSandboxFlags;
+    MockPolicyContainerHost mock_policy_container_host;
+    params->policy_container = std::make_unique<blink::WebPolicyContainer>(
+        blink::WebPolicyContainerPolicies(),
+        mock_policy_container_host.BindNewEndpointAndPassDedicatedRemote());
+    params->policy_container->policies.sandbox_flags = kMhtmlSandboxFlags;
     auto body_loader = std::make_unique<StaticDataNavigationBodyLoader>();
     body_loader->Write(*buffer);
     body_loader->Finish();
diff --git a/third_party/blink/renderer/core/frame/policy_container.cc b/third_party/blink/renderer/core/frame/policy_container.cc
index 40be4c9a..d1edb075 100644
--- a/third_party/blink/renderer/core/frame/policy_container.cc
+++ b/third_party/blink/renderer/core/frame/policy_container.cc
@@ -6,6 +6,7 @@
 
 #include <tuple>
 
+#include "services/network/public/cpp/web_sandbox_flags.h"
 #include "third_party/blink/renderer/core/frame/csp/conversion_util.h"
 
 namespace blink {
@@ -38,7 +39,8 @@
           container->policies.referrer_policy,
           ConvertToMojoBlink(
               std::move(container->policies.content_security_policies)),
-          container->policies.is_anonymous);
+          container->policies.is_anonymous, container->policies.sandbox_flags);
+
   return std::make_unique<PolicyContainer>(std::move(container->remote),
                                            std::move(policies));
 }
diff --git a/third_party/blink/renderer/core/frame/policy_container.h b/third_party/blink/renderer/core/frame/policy_container.h
index 593cb37..39fa38c 100644
--- a/third_party/blink/renderer/core/frame/policy_container.h
+++ b/third_party/blink/renderer/core/frame/policy_container.h
@@ -9,6 +9,7 @@
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "services/network/public/mojom/content_security_policy.mojom-blink-forward.h"
 #include "services/network/public/mojom/referrer_policy.mojom-shared.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
 #include "third_party/blink/public/mojom/frame/policy_container.mojom-blink.h"
 #include "third_party/blink/public/platform/web_policy_container.h"
 #include "third_party/blink/renderer/core/core_export.h"
diff --git a/third_party/blink/renderer/core/frame/policy_container_test.cc b/third_party/blink/renderer/core/frame/policy_container_test.cc
index 9571fbf..a9f4bc6 100644
--- a/third_party/blink/renderer/core/frame/policy_container_test.cc
+++ b/third_party/blink/renderer/core/frame/policy_container_test.cc
@@ -18,7 +18,7 @@
       network::mojom::blink::CrossOriginEmbedderPolicyValue::kNone,
       network::mojom::blink::ReferrerPolicy::kNever,
       Vector<network::mojom::blink::ContentSecurityPolicyPtr>(),
-      /*anonymous=*/false);
+      /*anonymous=*/false, network::mojom::WebSandboxFlags::kNone);
   PolicyContainer policy_container(host.BindNewEndpointAndPassDedicatedRemote(),
                                    std::move(policies));
 
@@ -32,7 +32,7 @@
       network::mojom::blink::CrossOriginEmbedderPolicyValue::kNone,
       network::mojom::blink::ReferrerPolicy::kAlways,
       Vector<network::mojom::blink::ContentSecurityPolicyPtr>(),
-      /*anonymous=*/false);
+      /*anonymous=*/false, network::mojom::WebSandboxFlags::kNone);
   PolicyContainer policy_container(host.BindNewEndpointAndPassDedicatedRemote(),
                                    std::move(policies));
 
diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc
index 7ebf58c..2f564e2f 100644
--- a/third_party/blink/renderer/core/frame/web_frame_test.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_test.cc
@@ -7959,10 +7959,8 @@
   params->policy_container = std::make_unique<WebPolicyContainer>(
       WebPolicyContainerPolicies(),
       mock_policy_container_host.BindNewEndpointAndPassDedicatedRemote());
-  params->sandbox_flags = network::mojom::WebSandboxFlags::kNone;
   params->is_synchronous_commit_for_bug_778318 = true;
 
-  params->sandbox_flags = network::mojom::WebSandboxFlags::kNone;
   child_frame->CommitNavigation(std::move(params), nullptr);
   frame_test_helpers::PumpPendingRequestsForFrameToLoad(child_frame);
 
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 868cb68..4db9e53d 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -2233,14 +2233,21 @@
           policy_container_remote.InitWithNewEndpointAndPassReceiver();
 
   FramePolicy frame_policy = owner_element->GetFramePolicy();
-  // Documents create iframes, iframes host new documents. Both are associated
-  // with sandbox flags. They are required to be stricter or equal as we go
-  // down. The iframe owner element only returns the additional restrictions
-  // defined in the HTMLIFrameElement's sanbox attribute. It needs to be
-  // combined with the document's sandbox flags to get the frame's sandbox
-  // policy right.
-  frame_policy.sandbox_flags |=
-      GetFrame()->GetDocument()->GetExecutionContext()->GetSandboxFlags();
+
+  // The initial empty document's policy container is inherited from its parent.
+  mojom::blink::PolicyContainerPoliciesPtr policy_container_data =
+      GetFrame()->DomWindow()->GetPolicyContainer()->GetPolicies().Clone();
+
+  // The frame sandbox flags and the initial empty document's sandbox flags
+  // are restricted by the parent document's sandbox flags and the iframe's
+  // sandbox attribute. It is the union of:
+  //  - The parent's sandbox flags which are contained in
+  //    policy_container_data and were cloned from the parent's document policy
+  //    container above.
+  //  - The iframe's sandbox attribute which is contained in frame_policy, from
+  //    the owner element's frame policy.
+  policy_container_data->sandbox_flags |= frame_policy.sandbox_flags;
+  frame_policy.sandbox_flags = policy_container_data->sandbox_flags;
 
   // FIXME: Using subResourceAttributeName as fallback is not a perfect
   // solution. subResourceAttributeName returns just one attribute name. The
@@ -2256,10 +2263,6 @@
   if (!webframe_child)
     return nullptr;
 
-  // Inherit policy container from parent.
-  mojom::blink::PolicyContainerPoliciesPtr policy_container_data =
-      GetFrame()->DomWindow()->GetPolicyContainer()->GetPolicies().Clone();
-
   // The initial empty document's anonymous bit is the union of:
   // - its parent's anonymous bit.
   // - its frame's anonymous attribute.
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc
index 58140c5..6929ba17 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc
@@ -4,6 +4,8 @@
 
 #include "third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h"
 
+#include <list>
+
 #include "components/ukm/test_ukm_recorder.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/blink/renderer/core/html/image_document_test.cc b/third_party/blink/renderer/core/html/image_document_test.cc
index f556a1d..3f2703f 100644
--- a/third_party/blink/renderer/core/html/image_document_test.cc
+++ b/third_party/blink/renderer/core/html/image_document_test.cc
@@ -150,7 +150,6 @@
   auto params = std::make_unique<WebNavigationParams>();
   params->url = is_animated ? KURL("http://www.example.com/image.webp")
                             : KURL("http://www.example.com/image.jpg");
-  params->sandbox_flags = network::mojom::WebSandboxFlags::kNone;
 
   const Vector<unsigned char>& data =
       is_animated ? AnimatedWebpImage() : JpegImage();
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc
index 905cbf4..09bf0313 100644
--- a/third_party/blink/renderer/core/layout/layout_inline.cc
+++ b/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -410,6 +410,9 @@
       style.MayHaveMargin())
     return true;
 
+  if (!style.AnchorName().IsNull())
+    return true;
+
   return ComputeIsAbsoluteContainer(&style) ||
          NGOutlineUtils::HasPaintedOutline(style, GetNode()) ||
          CanBeHitTestTargetPseudoNodeStyle(style);
diff --git a/third_party/blink/renderer/core/layout/layout_tree_as_text.cc b/third_party/blink/renderer/core/layout/layout_tree_as_text.cc
index 4dff687..a381787 100644
--- a/third_party/blink/renderer/core/layout/layout_tree_as_text.cc
+++ b/third_party/blink/renderer/core/layout/layout_tree_as_text.cc
@@ -78,6 +78,11 @@
     return "";
   if (n->getNodeType() == Node::kCommentNode)
     return "COMMENT";
+  if (const auto* element = DynamicTo<Element>(n)) {
+    const AtomicString& pseudo = element->ShadowPseudoId();
+    if (!pseudo.IsEmpty())
+      return "::" + pseudo;
+  }
   return n->nodeName();
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_anchor_query_test.cc b/third_party/blink/renderer/core/layout/ng/ng_anchor_query_test.cc
index e8818ee..e60567fe 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_anchor_query_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_anchor_query_test.cc
@@ -105,6 +105,65 @@
                   AnchorTestData{"--div3", PhysicalRect(0, 70, 800, 0)}));
 }
 
+TEST_F(NGAnchorQueryTest, Inline) {
+  LoadAhem();
+  SetBodyInnerHTML(R"HTML(
+    <style>
+    html, body {
+      margin: 0;
+      width: 800px;
+      font-family: Ahem;
+      font-size: 10px;
+      line-height: 1;
+    }
+    img {
+      width: 10px;
+      height: 8px;
+    }
+    .after .add {
+      anchor-name: --add;
+    }
+    </style>
+    <div id="container">
+      0
+      <!-- culled and non-culled inline boxes. -->
+      <span style="anchor-name: --culled">23</span>
+      <span style="anchor-name: --non-culled; background: yellow">56</span>
+
+      <!-- Adding `anchor-name` dynamically should uncull. -->
+      <span class="add">89</span>
+
+      <!-- Atomic inlines: replaced elements and inline blocks. -->
+      <img style="anchor-name: --img" src="data:image/gif;base64,R0lGODlhAQABAAAAACw=">
+      <span style="anchor-name: --inline-block; display: inline-block">X</span>
+    </div>
+  )HTML");
+  Element* container = GetElementById("container");
+  const NGPhysicalAnchorQuery* anchor_query = AnchorQuery(*container);
+  ASSERT_NE(anchor_query, nullptr);
+  EXPECT_THAT(
+      AnchorTestData::ToList(*anchor_query),
+      testing::ElementsAre(
+          AnchorTestData{"--culled", PhysicalRect(20, 0, 20, 10)},
+          AnchorTestData{"--img", PhysicalRect(110, 0, 10, 8)},
+          AnchorTestData{"--inline-block", PhysicalRect(130, 0, 10, 10)},
+          AnchorTestData{"--non-culled", PhysicalRect(50, 0, 20, 10)}));
+
+  // Add the "after" class and test anchors are updated accordingly.
+  container->classList().Add("after");
+  UpdateAllLifecyclePhasesForTest();
+  anchor_query = AnchorQuery(*container);
+  ASSERT_NE(anchor_query, nullptr);
+  EXPECT_THAT(
+      AnchorTestData::ToList(*anchor_query),
+      testing::ElementsAre(
+          AnchorTestData{"--add", PhysicalRect(80, 0, 20, 10)},
+          AnchorTestData{"--culled", PhysicalRect(20, 0, 20, 10)},
+          AnchorTestData{"--img", PhysicalRect(110, 0, 10, 8)},
+          AnchorTestData{"--inline-block", PhysicalRect(130, 0, 10, 10)},
+          AnchorTestData{"--non-culled", PhysicalRect(50, 0, 20, 10)}));
+}
+
 TEST_F(NGAnchorQueryTest, OutOfFlow) {
   SetBodyInnerHTML(R"HTML(
     <style>
diff --git a/third_party/blink/renderer/core/loader/cross_thread_resource_timing_info_copier.cc b/third_party/blink/renderer/core/loader/cross_thread_resource_timing_info_copier.cc
index 0e546c3..a69a820 100644
--- a/third_party/blink/renderer/core/loader/cross_thread_resource_timing_info_copier.cc
+++ b/third_party/blink/renderer/core/loader/cross_thread_resource_timing_info_copier.cc
@@ -34,7 +34,8 @@
       info->decoded_body_size, info->did_reuse_connection,
       info->is_secure_transport, info->allow_timing_details,
       info->allow_redirect_details, info->allow_negative_values,
-      CloneServerTimingInfoArray(info->server_timing));
+      CloneServerTimingInfoArray(info->server_timing),
+      info->render_blocking_status);
 }
 
 CrossThreadCopier<blink::mojom::blink::ServerTimingInfoPtr>::Type
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index 80f9dc9..1bc7536f 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -240,7 +240,6 @@
   mojo::Remote<mojom::blink::ContentSecurityNotifier> content_security_notifier;
   scoped_refptr<SecurityOrigin> origin_to_commit;
   BlinkStorageKey storage_key;
-  network::mojom::WebSandboxFlags sandbox_flags;
   WebNavigationType navigation_type;
   DocumentLoadTiming document_load_timing;
   base::TimeTicks time_of_last_data_received;
@@ -360,7 +359,6 @@
                             ? nullptr
                             : params_->origin_to_commit.Get()->IsolatedCopy()),
       storage_key_(std::move(params_->storage_key)),
-      sandbox_flags_(params_->sandbox_flags),
       navigation_type_(navigation_type),
       document_load_timing_(*this),
       service_worker_network_provider_(
@@ -511,7 +509,6 @@
   // the origin to no longer be aliased).
   params->origin_to_commit = window->GetSecurityOrigin();
   params->storage_key = window->GetStorageKey();
-  params->sandbox_flags = sandbox_flags_;
   params->origin_agent_cluster = origin_agent_cluster_;
   params->origin_agent_cluster_left_as_default =
       origin_agent_cluster_left_as_default_;
@@ -1918,7 +1915,7 @@
   if (origin_to_commit_) {
     // Origin to commit is specified by the browser process, it must be taken
     // and used directly. It is currently supplied only for session history
-    // navigations, where the origin was already calcuated previously and
+    // navigations, where the origin was already calculated previously and
     // stored on the session history entry.
     origin = origin_to_commit_;
   } else if (IsPagePopupRunningInWebTest(frame_)) {
@@ -1959,7 +1956,8 @@
     origin = SecurityOrigin::CreateWithReferenceOrigin(url_, precursor.get());
   }
 
-  if ((sandbox_flags_ & network::mojom::blink::WebSandboxFlags::kOrigin) !=
+  if ((policy_container_->GetPolicies().sandbox_flags &
+       network::mojom::blink::WebSandboxFlags::kOrigin) !=
       network::mojom::blink::WebSandboxFlags::kNone) {
     auto sandbox_origin = origin->DeriveNewOpaqueOrigin();
 
@@ -2209,9 +2207,6 @@
   security_origin = security_origin->GetOriginForAgentCluster(
       frame_->DomWindow()->GetAgent()->cluster_id());
 
-  SecurityContext& security_context = frame_->DomWindow()->GetSecurityContext();
-  security_context.SetSandboxFlags(sandbox_flags_);
-
   // TODO(https://crbug.com/888079): Just use the storage key sent by the
   // browser once the browser will be able to compute the origin in all cases.
   // TODO(https://crbug.com/1271402): Make sure we have the intended behavior
@@ -2223,6 +2218,7 @@
   // Conceptually, SecurityOrigin doesn't have to be initialized after sandbox
   // flags are applied, but there's a UseCounter in SetSecurityOrigin() that
   // wants to inspect sandbox flags.
+  SecurityContext& security_context = frame_->DomWindow()->GetSecurityContext();
   security_context.SetSecurityOrigin(std::move(security_origin));
   // Requires SecurityOrigin to be initialized.
   OriginTrialContext::AddTokensFromHeader(
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h
index 7190fc9..571f7920 100644
--- a/third_party/blink/renderer/core/loader/document_loader.h
+++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -576,7 +576,6 @@
 
   const scoped_refptr<SecurityOrigin> origin_to_commit_;
   blink::BlinkStorageKey storage_key_;
-  const network::mojom::WebSandboxFlags sandbox_flags_;
   WebNavigationType navigation_type_;
 
   DocumentLoadTiming document_load_timing_;
diff --git a/third_party/blink/renderer/core/loader/document_loader_test.cc b/third_party/blink/renderer/core/loader/document_loader_test.cc
index 469a77b1..4646ee8f 100644
--- a/third_party/blink/renderer/core/loader/document_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/document_loader_test.cc
@@ -442,7 +442,6 @@
   std::unique_ptr<WebNavigationParams> params =
       std::make_unique<WebNavigationParams>();
   params->url = about_blank_url;
-  params->sandbox_flags = network::mojom::WebSandboxFlags::kNone;
   params->requestor_origin = WebSecurityOrigin::Create(WebURL(requestor_url));
   LocalFrame* local_frame =
       To<LocalFrame>(web_view_impl->GetPage()->MainFrame());
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index 0f2ea24..564ba7a 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -258,18 +258,6 @@
   navigation_params->frame_policy =
       frame_->Owner() ? frame_->Owner()->GetFramePolicy() : FramePolicy();
 
-  // An interesting edge case to consider: A document has:
-  // CSP: sandbox allow-popups allow-popups-to-escape-sandbox
-  // It opens a blank popup.
-  //
-  // The popup's main frame doesn't inherit sandbox. However the initial empty
-  // document inherits sandbox from the opener, through inherited CSP.
-  navigation_params->sandbox_flags = PendingEffectiveSandboxFlags();
-  for (const auto& csp :
-       policy_container->GetPolicies().content_security_policies) {
-    navigation_params->sandbox_flags |= csp->sandbox;
-  }
-
   DocumentLoader* new_document_loader = MakeGarbageCollected<DocumentLoader>(
       frame_, kWebNavigationTypeOther, std::move(navigation_params),
       std::move(policy_container), nullptr /* extra_data */);
diff --git a/third_party/blink/renderer/core/loader/frame_loader_test.cc b/third_party/blink/renderer/core/loader/frame_loader_test.cc
index 1535c79c..096d0282 100644
--- a/third_party/blink/renderer/core/loader/frame_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader_test.cc
@@ -167,7 +167,7 @@
                 network::mojom::CrossOriginEmbedderPolicyValue::kNone,
                 network::mojom::ReferrerPolicy::kAlways,
                 Vector<network::mojom::blink::ContentSecurityPolicyPtr>(),
-                /*anonymous=*/false),
+                /*anonymous=*/false, network::mojom::WebSandboxFlags::kNone),
             local_frame->DomWindow()->GetPolicyContainer()->GetPolicies());
 }
 
diff --git a/third_party/blink/renderer/core/page/validation_message_client_impl.cc b/third_party/blink/renderer/core/page/validation_message_client_impl.cc
index 09adb63..26aafa5 100644
--- a/third_party/blink/renderer/core/page/validation_message_client_impl.cc
+++ b/third_party/blink/renderer/core/page/validation_message_client_impl.cc
@@ -69,13 +69,9 @@
   if (!anchor.GetLayoutObject())
     return;
 
-  // If this frame is cross origin to the main frame, then shorten the
-  // validation message to prevent validation popups that cover too much of the
-  // main frame.
-  // TODO(crbug.com/1318055): With MPArch there may be multiple main frames
-  // so we should use IsCrossOriginToOutermostMainFrame when we intend to check
-  // if any embedded frame (eg, iframe or fenced frame) is cross-origin with
-  // respect to the outermost main frame. Follow up to confirm correctness.
+  // If this subframe or fencedframe is cross origin to the main frame, then
+  // shorten the validation message to prevent validation popups that cover too
+  // much of the main frame.
   String message = original_message;
   if (original_message.length() > kMaxValidationStringLength &&
       anchor.GetDocument().GetFrame()->IsCrossOriginToOutermostMainFrame()) {
diff --git a/third_party/blink/renderer/core/testing/core_unit_test_helper.cc b/third_party/blink/renderer/core/testing/core_unit_test_helper.cc
index a71be5b..aba817e 100644
--- a/third_party/blink/renderer/core/testing/core_unit_test_helper.cc
+++ b/third_party/blink/renderer/core/testing/core_unit_test_helper.cc
@@ -4,8 +4,10 @@
 
 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
 
+#include "services/network/public/cpp/web_sandbox_flags.h"
 #include "third_party/blink/public/common/tokens/tokens.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/html/html_iframe_element.h"
 #include "third_party/blink/renderer/core/input/event_handler.h"
 #include "third_party/blink/renderer/core/page/page.h"
@@ -29,7 +31,31 @@
       nullptr, FrameInsertType::kInsertInConstructor, LocalFrameToken(),
       &parent_frame->window_agent_factory(), nullptr);
   child->CreateView(gfx::Size(500, 500), Color::kTransparent);
-  child->Init(/*opener=*/nullptr, /*policy_container=*/nullptr);
+
+  // The initial empty document's policy container is inherited from its parent.
+  mojom::blink::PolicyContainerPoliciesPtr policy_container_data =
+      parent_frame->GetDocument()
+          ->GetExecutionContext()
+          ->GetPolicyContainer()
+          ->GetPolicies()
+          .Clone();
+
+  // The initial empty document's sandbox flags is further restricted by its
+  // frame's sandbox attribute. At the end, it becomes the union of:
+  // - The parent's sandbox flags.
+  // - The iframe's sandbox attribute.
+  policy_container_data->sandbox_flags |=
+      child->Owner()->GetFramePolicy().sandbox_flags;
+
+  // Create a dummy PolicyContainerHost remote. The messages are normally
+  // handled by by the browser process, but they are dropped here.
+  mojo::AssociatedRemote<mojom::blink::PolicyContainerHost> dummy_host;
+  std::ignore = dummy_host.BindNewEndpointAndPassDedicatedReceiver();
+
+  auto policy_container = std::make_unique<PolicyContainer>(
+      dummy_host.Unbind(), std::move(policy_container_data));
+
+  child->Init(/*opener=*/nullptr, std::move(policy_container));
 
   return child;
 }
diff --git a/third_party/blink/renderer/core/timing/performance.cc b/third_party/blink/renderer/core/timing/performance.cc
index 373c63d..2d81157 100644
--- a/third_party/blink/renderer/core/timing/performance.cc
+++ b/third_party/blink/renderer/core/timing/performance.cc
@@ -586,6 +586,8 @@
                       WebFeature::kPerformanceServerTiming);
   }
 
+  result->render_blocking_status = info.RenderBlockingStatus();
+
   return result;
 }
 
diff --git a/third_party/blink/renderer/core/timing/performance_resource_timing.cc b/third_party/blink/renderer/core/timing/performance_resource_timing.cc
index 2b52e472..3db32d1 100644
--- a/third_party/blink/renderer/core/timing/performance_resource_timing.cc
+++ b/third_party/blink/renderer/core/timing/performance_resource_timing.cc
@@ -45,6 +45,7 @@
 #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 
 namespace blink {
@@ -73,6 +74,8 @@
       alpn_negotiated_protocol_(
           static_cast<String>(info.alpn_negotiated_protocol)),
       connection_info_(static_cast<String>(info.connection_info)),
+      render_blocking_status_(info.render_blocking_status ? "blocking"
+                                                          : "non-blocking"),
       time_origin_(time_origin),
       cross_origin_isolated_capability_(cross_origin_isolated_capability),
       timing_(ResourceLoadTiming::FromMojo(info.timing.get())),
@@ -165,6 +168,10 @@
   return initiator_type_;
 }
 
+AtomicString PerformanceResourceTiming::renderBlockingStatus() const {
+  return render_blocking_status_;
+}
+
 AtomicString PerformanceResourceTiming::AlpnNegotiatedProtocol() const {
   return alpn_negotiated_protocol_;
 }
@@ -437,6 +444,9 @@
   PerformanceEntry::BuildJSONValue(builder);
   builder.AddString("initiatorType", initiatorType());
   builder.AddString("nextHopProtocol", nextHopProtocol());
+  if (RuntimeEnabledFeatures::RenderBlockingStatusEnabled()) {
+    builder.AddString("renderBlockingStatus", renderBlockingStatus());
+  }
   builder.AddNumber("workerStart", workerStart());
   builder.AddNumber("redirectStart", redirectStart());
   builder.AddNumber("redirectEnd", redirectEnd());
diff --git a/third_party/blink/renderer/core/timing/performance_resource_timing.h b/third_party/blink/renderer/core/timing/performance_resource_timing.h
index d377cbcf..8b73204 100644
--- a/third_party/blink/renderer/core/timing/performance_resource_timing.h
+++ b/third_party/blink/renderer/core/timing/performance_resource_timing.h
@@ -76,6 +76,7 @@
   // Related doc: https://goo.gl/uNecAj.
   virtual AtomicString initiatorType() const;
   AtomicString nextHopProtocol() const;
+  virtual AtomicString renderBlockingStatus() const;
   DOMHighResTimeStamp workerStart() const;
   virtual DOMHighResTimeStamp redirectStart() const;
   virtual DOMHighResTimeStamp redirectEnd() const;
@@ -136,6 +137,7 @@
   AtomicString initiator_type_;
   AtomicString alpn_negotiated_protocol_;
   AtomicString connection_info_;
+  AtomicString render_blocking_status_;
   base::TimeTicks time_origin_;
   bool cross_origin_isolated_capability_;
   scoped_refptr<ResourceLoadTiming> timing_;
diff --git a/third_party/blink/renderer/core/timing/performance_resource_timing.idl b/third_party/blink/renderer/core/timing/performance_resource_timing.idl
index 64cfd01..63d8935 100644
--- a/third_party/blink/renderer/core/timing/performance_resource_timing.idl
+++ b/third_party/blink/renderer/core/timing/performance_resource_timing.idl
@@ -50,5 +50,9 @@
     [MeasureAs=PerformanceResourceTimingSizes] readonly attribute unsigned long long encodedBodySize;
     [MeasureAs=PerformanceResourceTimingSizes] readonly attribute unsigned long long decodedBodySize;
     readonly attribute FrozenArray<PerformanceServerTiming> serverTiming;
+    // PerformanceResourceTiming#renderBlockingStatus
+    // See: https://github.com/abinpaul1/resource-timing/blob/render-blocking-status-explainer/Explainer/Render_Blocking_Status.md
+    [RuntimeEnabled=RenderBlockingStatus]
+        readonly attribute DOMString renderBlockingStatus;
     [CallWith=ScriptState, ImplementedAs=toJSONForBinding] object toJSON();
 };
diff --git a/third_party/blink/renderer/modules/lock_screen/lock_screen_data.cc b/third_party/blink/renderer/modules/lock_screen/lock_screen_data.cc
index 24f56bb..d94a01e1 100644
--- a/third_party/blink/renderer/modules/lock_screen/lock_screen_data.cc
+++ b/third_party/blink/renderer/modules/lock_screen/lock_screen_data.cc
@@ -4,8 +4,10 @@
 
 #include "third_party/blink/renderer/modules/lock_screen/lock_screen_data.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/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace blink {
 
@@ -30,7 +32,7 @@
 ScriptPromise LockScreenData::GetLockScreenData(ScriptState* script_state) {
   ScriptPromiseResolver* resolver =
       MakeGarbageCollected<ScriptPromiseResolver>(script_state);
-  auto promise = resolver->Promise();
+  ScriptPromise promise = resolver->Promise();
 
   resolver->Resolve(this);
   return promise;
@@ -38,38 +40,48 @@
 
 ScriptPromise LockScreenData::getKeys(ScriptState* script_state) {
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  ScriptPromise promise = resolver->Promise();
 
-  // TODO(crbug.com/1006642): This should call out to a mojo service.
-  resolver->Reject("Not implemented");
-  return resolver->Promise();
+  // TODO(crbug.com/1006642): This should call out to a mojo service instead.
+  Vector<String> keys;
+  keys.ReserveInitialCapacity(static_cast<wtf_size_t>(fake_data_store_.size()));
+  for (const auto& it : fake_data_store_) {
+    keys.push_back(it.key);
+  }
+  resolver->Resolve(std::move(keys));
+  return promise;
 }
 
 ScriptPromise LockScreenData::getData(ScriptState* script_state,
                                       const String& key) {
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  ScriptPromise promise = resolver->Promise();
 
-  // TODO(crbug.com/1006642): This should call out to a mojo service.
-  resolver->Reject("Not implemented");
-  return resolver->Promise();
+  // TODO(crbug.com/1006642): This should call out to a mojo service instead.
+  auto it = fake_data_store_.find(key);
+  if (it == fake_data_store_.end()) {
+    resolver->Resolve();
+  } else {
+    resolver->Resolve(it->value);
+  }
+  return promise;
 }
 
 ScriptPromise LockScreenData::setData(ScriptState* script_state,
                                       const String& key,
                                       const String& data) {
-  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  // TODO(crbug.com/1006642): This should call out to a mojo service instead.
+  fake_data_store_.Set(key, data);
 
-  // TODO(crbug.com/1006642): This should call out to a mojo service.
-  resolver->Reject("Not implemented");
-  return resolver->Promise();
+  return ScriptPromise::CastUndefined(script_state);
 }
 
 ScriptPromise LockScreenData::deleteData(ScriptState* script_state,
                                          const String& key) {
-  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  // TODO(crbug.com/1006642): This should call out to a mojo service instead.
+  fake_data_store_.erase(key);
 
-  // TODO(crbug.com/1006642): This should call out to a mojo service.
-  resolver->Reject("Not implemented");
-  return resolver->Promise();
+  return ScriptPromise::CastUndefined(script_state);
 }
 
 void LockScreenData::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/modules/lock_screen/lock_screen_data.h b/third_party/blink/renderer/modules/lock_screen/lock_screen_data.h
index a5ad966..094681b4 100644
--- a/third_party/blink/renderer/modules/lock_screen/lock_screen_data.h
+++ b/third_party/blink/renderer/modules/lock_screen/lock_screen_data.h
@@ -8,6 +8,8 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/supplementable.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
 
@@ -32,6 +34,10 @@
   ScriptPromise deleteData(ScriptState*, const String& key);
 
   void Trace(Visitor* visitor) const override;
+
+ private:
+  // Fake data store for use in testing before implementation is complete.
+  HashMap<String, String> fake_data_store_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/lock_screen/lock_screen_data.idl b/third_party/blink/renderer/modules/lock_screen/lock_screen_data.idl
index ec231c2..12cb3983 100644
--- a/third_party/blink/renderer/modules/lock_screen/lock_screen_data.idl
+++ b/third_party/blink/renderer/modules/lock_screen/lock_screen_data.idl
@@ -11,7 +11,9 @@
   Promise<sequence<DOMString>> getKeys();
 
   [CallWith=ScriptState]
-  Promise<DOMString> getData(DOMString key);
+  // TODO (crbug.com/1293259): Use `(DOMString or undefined)` instead of `any`
+  // when supported by the Blink IDL compiler.
+  Promise<any> getData(DOMString key);
 
   [CallWith=ScriptState]
   Promise<void> setData(DOMString key, DOMString data);
diff --git a/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc b/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
index 6bfa6004..5fc5703 100644
--- a/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
+++ b/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
@@ -7,6 +7,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_scheduler_post_task_callback.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_scheduler_post_task_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_task_signal.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
@@ -77,6 +78,10 @@
     return ScriptPromise();
   }
 
+  auto* tracker = ThreadScheduler::Current()->GetTaskAttributionTracker();
+  if (tracker && script_state->World().IsMainWorld()) {
+    callback_function->SetParentTaskId(tracker->RunningTaskId(script_state));
+  }
   // Always honor the priority and the task signal if given.
   DOMTaskQueue* task_queue;
   AbortSignal* signal = options->hasSignal() ? options->signal() : nullptr;
diff --git a/third_party/blink/renderer/platform/bindings/callback_function_base.cc b/third_party/blink/renderer/platform/bindings/callback_function_base.cc
index 38010b7f..fcdfd35 100644
--- a/third_party/blink/renderer/platform/bindings/callback_function_base.cc
+++ b/third_party/blink/renderer/platform/bindings/callback_function_base.cc
@@ -7,7 +7,6 @@
 #include "third_party/blink/renderer/platform/bindings/binding_security_for_platform.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/scheduler/public/task_attribution_tracker.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 
 namespace blink {
 
@@ -30,10 +29,6 @@
           BindingSecurityForPlatform::ErrorReportOption::kDoNotReport)) {
     callback_relevant_script_state_ =
         ScriptState::From(creation_context.ToLocalChecked());
-    if (auto* tracker =
-            ThreadScheduler::Current()->GetTaskAttributionTracker()) {
-      parent_task_id_ = tracker->RunningTaskId(callback_relevant_script_state_);
-    }
   }
 }
 
diff --git a/third_party/blink/renderer/platform/bindings/callback_function_base.h b/third_party/blink/renderer/platform/bindings/callback_function_base.h
index 3ee271c..68025ed 100644
--- a/third_party/blink/renderer/platform/bindings/callback_function_base.h
+++ b/third_party/blink/renderer/platform/bindings/callback_function_base.h
@@ -93,6 +93,10 @@
     return parent_task_id_;
   }
 
+  void SetParentTaskId(absl::optional<scheduler::TaskId> task_id) {
+    parent_task_id_ = task_id;
+  }
+
  protected:
   explicit CallbackFunctionBase(v8::Local<v8::Object>);
 
diff --git a/third_party/blink/renderer/platform/bindings/callback_interface_base.cc b/third_party/blink/renderer/platform/bindings/callback_interface_base.cc
index cfce04f..d183bf81 100644
--- a/third_party/blink/renderer/platform/bindings/callback_interface_base.cc
+++ b/third_party/blink/renderer/platform/bindings/callback_interface_base.cc
@@ -7,7 +7,6 @@
 #include "third_party/blink/renderer/platform/bindings/binding_security_for_platform.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/scheduler/public/task_attribution_tracker.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 
 namespace blink {
 
@@ -33,10 +32,6 @@
           BindingSecurityForPlatform::ErrorReportOption::kDoNotReport)) {
     callback_relevant_script_state_ =
         ScriptState::From(creation_context.ToLocalChecked());
-    if (auto* tracker =
-            ThreadScheduler::Current()->GetTaskAttributionTracker()) {
-      parent_task_id_ = tracker->RunningTaskId(callback_relevant_script_state_);
-    }
   }
 }
 
diff --git a/third_party/blink/renderer/platform/bindings/callback_interface_base.h b/third_party/blink/renderer/platform/bindings/callback_interface_base.h
index 6d84207c..e1b880b 100644
--- a/third_party/blink/renderer/platform/bindings/callback_interface_base.h
+++ b/third_party/blink/renderer/platform/bindings/callback_interface_base.h
@@ -84,7 +84,7 @@
   DOMWrapperWorld& GetWorld() const { return incumbent_script_state_->World(); }
 
   absl::optional<scheduler::TaskId> GetParentTaskId() const {
-    return parent_task_id_;
+    return absl::nullopt;
   }
 
  protected:
@@ -103,8 +103,6 @@
   // converted to an IDL value.
   // https://webidl.spec.whatwg.org/#dfn-callback-context
   Member<ScriptState> incumbent_script_state_;
-
-  absl::optional<scheduler::TaskId> parent_task_id_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index 86d2b99..f0c7721e 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -636,6 +636,8 @@
     final_response.SetResourceLoadTiming(nullptr);
     info->SetFinalResponse(final_response);
     info->SetLoadResponseEnd(info->InitialTime());
+    if (render_blocking_behavior == RenderBlockingBehavior::kBlocking)
+      info->SetRenderBlockingStatus(/*render_blocking_status=*/true);
     scheduled_resource_timing_reports_.push_back(std::move(info));
     if (!resource_timing_report_timer_.IsActive())
       resource_timing_report_timer_.StartOneShot(base::TimeDelta(), FROM_HERE);
@@ -1066,7 +1068,8 @@
   if (blocked_reason) {
     auto* resource = ResourceForBlockedRequest(params, factory,
                                                blocked_reason.value(), client);
-    StorePerformanceTimingInitiatorInformation(resource);
+    StorePerformanceTimingInitiatorInformation(
+        resource, params.GetRenderBlockingBehavior());
     if (auto info = resource_timing_info_map_.Take(resource)) {
       PopulateAndAddResourceTimingInfo(resource, info,
                                        /*response_end=*/base::TimeTicks::Now());
@@ -1342,7 +1345,8 @@
 }
 
 void ResourceFetcher::StorePerformanceTimingInitiatorInformation(
-    Resource* resource) {
+    Resource* resource,
+    RenderBlockingBehavior render_blocking_behavior) {
   const AtomicString& fetch_initiator = resource->Options().initiator_info.name;
   if (fetch_initiator == fetch_initiator_type_names::kInternal)
     return;
@@ -1352,6 +1356,9 @@
       resource->GetResourceRequest().GetRequestContext(),
       resource->GetResourceRequest().GetRequestDestination());
 
+  if (render_blocking_behavior == RenderBlockingBehavior::kBlocking)
+    info->SetRenderBlockingStatus(/*render_blocking_status=*/true);
+
   resource_timing_info_map_.insert(resource, std::move(info));
 }
 
@@ -2120,7 +2127,8 @@
     }
     resource->VirtualTimePauser().PauseVirtualTime();
 
-    StorePerformanceTimingInitiatorInformation(resource);
+    StorePerformanceTimingInitiatorInformation(resource,
+                                               render_blocking_behavior);
   }
 
   loader->Start();
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
index 3ef90de..f8d9c5d0 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -337,7 +337,8 @@
   void AddToMemoryCacheIfNeeded(const FetchParameters&, Resource*);
   Resource* CreateResourceForLoading(const FetchParameters&,
                                      const ResourceFactory&);
-  void StorePerformanceTimingInitiatorInformation(Resource*);
+  void StorePerformanceTimingInitiatorInformation(Resource*,
+                                                  RenderBlockingBehavior);
   ResourceLoadPriority ComputeLoadPriority(
       ResourceType,
       const ResourceRequestHead&,
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h b/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h
index ebcd8662..0edf058 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h
@@ -63,6 +63,11 @@
   void SetInitiatorType(const AtomicString& type) { type_ = type; }
   const AtomicString& InitiatorType() const { return type_; }
 
+  void SetRenderBlockingStatus(bool render_blocking_status) {
+    render_blocking_status_ = render_blocking_status;
+  }
+  bool RenderBlockingStatus() const { return render_blocking_status_; }
+
   void SetLoadResponseEnd(base::TimeTicks time) { load_response_end_ = time; }
   base::TimeTicks LoadResponseEnd() const { return load_response_end_; }
 
@@ -110,6 +115,7 @@
         request_destination_(request_destination) {}
 
   AtomicString type_;
+  bool render_blocking_status_ = false;
   base::TimeTicks initial_time_;
   mojom::blink::RequestContextType context_type_;
   network::mojom::RequestDestination request_destination_;
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader_unittest.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader_unittest.cc
index 2cca490..ae77923 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader_unittest.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/navigation_body_loader_unittest.cc
@@ -100,7 +100,6 @@
     auto endpoints = network::mojom::URLLoaderClientEndpoints::New();
     endpoints->url_loader_client = client_remote_.BindNewPipeAndPassReceiver();
     WebNavigationParams navigation_params;
-    navigation_params.sandbox_flags = network::mojom::WebSandboxFlags::kNone;
     auto common_params = CreateCommonNavigationParams();
     common_params->request_destination =
         network::mojom::RequestDestination::kDocument;
@@ -408,7 +407,6 @@
   auto commit_params = CreateCommitNavigationParams();
 
   WebNavigationParams navigation_params;
-  navigation_params.sandbox_flags = network::mojom::WebSandboxFlags::kNone;
   auto endpoints = network::mojom::URLLoaderClientEndpoints::New();
   mojo::ScopedDataPipeProducerHandle producer_handle;
   mojo::ScopedDataPipeConsumerHandle consumer_handle;
@@ -458,7 +456,6 @@
   commit_params->redirects.push_back(second_redirect_url);
 
   WebNavigationParams navigation_params;
-  navigation_params.sandbox_flags = network::mojom::WebSandboxFlags::kNone;
   auto endpoints = network::mojom::URLLoaderClientEndpoints::New();
   mojo::ScopedDataPipeProducerHandle producer_handle;
   mojo::ScopedDataPipeConsumerHandle consumer_handle;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 7089064..86fd84cf 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -2006,6 +2006,10 @@
       status: "stable"
     },
     {
+      name: "RenderBlockingStatus",
+      status: "experimental"
+    },
+    {
       // The renderpriority attribute feature.
       // https://github.com/WICG/display-locking/blob/main/explainers/update-rendering.md
       name: "RenderPriorityAttribute"
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index ffd5b07..2017a2b 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -3365,6 +3365,8 @@
 crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/css/css-color/currentcolor-003.html [ Failure ]
+crbug.com/626703 [ Mac11 ] virtual/document-transition/wpt_internal/document-transition/commit-timeout-crash.html [ Timeout ]
 crbug.com/626703 [ Win11 ] virtual/conversions-debug-mode/wpt_internal/attribution-reporting/source-registration.sub.https.html?method=a [ Timeout ]
 crbug.com/626703 [ Win11 ] virtual/conversions-debug-mode/wpt_internal/attribution-reporting/source-registration.sub.https.html?method=fetch&eligible=event-source [ Timeout ]
 crbug.com/626703 [ Win11 ] virtual/conversions-debug-mode/wpt_internal/attribution-reporting/source-registration.sub.https.html?method=script&eligible [ Timeout ]
@@ -7154,8 +7156,8 @@
 
 # Temporarily disable the tests during the rollout of V8 that fixes the
 # behaviors that the test cases excersise.
-crbug.com/1305302 external/wpt/WebIDL/ecmascript-binding/global-object-implicit-this-value-cross-realm.html [ Skip ]
-crbug.com/1305302 external/wpt/WebIDL/ecmascript-binding/global-object-implicit-this-value.any.html [ Skip ]
+crbug.com/1305302 external/wpt/webidl/ecmascript-binding/global-object-implicit-this-value-cross-realm.html [ Skip ]
+crbug.com/1305302 external/wpt/webidl/ecmascript-binding/global-object-implicit-this-value.any.html [ Skip ]
 
 # Sheriff 2022-07-04
 crbug.com/1340981 virtual/conversions-debug-mode/wpt_internal/attribution-reporting/source-registration.sub.https.html [ Timeout ]
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version
index 56d2701..c4d36fc 100644
--- a/third_party/blink/web_tests/external/Version
+++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@
-Version: c1b24fce6e625c1b79124a58f27bf9adce02d5d7
+Version: ae12e0f25aeb1ec3bf6b96324e9a0898362ea2b5
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index da1adc6..52f05dca 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -89411,6 +89411,19 @@
        {}
       ]
      ],
+     "currentcolor-003.html": [
+      "d3ad9c4c15dd0ef58ae303c60cf6106b43c3a617",
+      [
+       null,
+       [
+        [
+         "/css/css-color/currentcolor-003-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "deprecated-sameas-001.html": [
       "b03af9eb29fb6f4e23a036a927dd35bbf12bf112",
       [
@@ -145354,6 +145367,58 @@
        {}
       ]
      ],
+     "overflow-img-border-radius.html": [
+      "cec70d6b942b426864b9a1a2648ebf1f71514c4b",
+      [
+       null,
+       [
+        [
+         "/css/css-overflow/overflow-img-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "overflow-img-object-position.html": [
+      "67e6febef275ccd07957db6687bdbefddf02c23b",
+      [
+       null,
+       [
+        [
+         "/css/css-overflow/overflow-img-object-position-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "overflow-img-svg.html": [
+      "15285ca3b67451daf3deb7ed17249f1efe279d79",
+      [
+       null,
+       [
+        [
+         "/css/css-overflow/overflow-img-svg-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "overflow-img.html": [
+      "cd9d30ffaa3318d7c9df288260c104c4cd7f0bbe",
+      [
+       null,
+       [
+        [
+         "/css/css-overflow/overflow-img-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "overflow-inline-block-with-opacity.html": [
       "20288f8a0d5ecf520d1e4114f7949ebd4b159e0d",
       [
@@ -263737,6 +263802,10 @@
       "73b420189ec8bc073e8b6a2e4bfd628653bd4a78",
       []
      ],
+     "currentcolor-003-ref.html": [
+      "7cabf85f3b4f95449bd8cd3af847283a61de58eb",
+      []
+     ],
      "deprecated-sameas-ButtonBorder-ref.html": [
       "99359aa4a776757973814748a9b74032b55cb8d8",
       []
@@ -278050,67 +278119,67 @@
       []
      ],
      "object-view-box-fit-contain-canvas-ref.html": [
-      "b7998653f32a520e5a22342dba7870247f935170",
+      "821c2f333f8a41c02e32661c4eebd8d504877d4a",
       []
      ],
      "object-view-box-fit-contain-img-ref.html": [
-      "93624ff0f91b56299616b560c45c71c294512e0c",
+      "7a4ac607d501463a03e4670c71b984bf0234f12e",
       []
      ],
      "object-view-box-fit-contain-svg-ref.html": [
-      "66ba39e5de0548073a51b9f7f2d9726e34c1fdad",
+      "b6fea8087bc7912d8a1338eaf1ee8d311272a70c",
       []
      ],
      "object-view-box-fit-contain-video-ref.html": [
-      "9d33d38417540fe269a3f2e77541b8b6bf5b82b9",
+      "174c4d3bf9371d40ff0ed514fddb94f3caa51562",
       []
      ],
      "object-view-box-fit-cover-canvas-ref.html": [
-      "cd1902b65a6ee67d550e4b4f24d08081ea090237",
+      "558cfe8ee36f341f40247b3d23861414417c8df3",
       []
      ],
      "object-view-box-fit-cover-img-ref.html": [
-      "dd52c52e88f3d65fbe1fdc8ecd108b9794cb674e",
+      "7e2bdc754dce11e71526847759794ff38865d4fc",
       []
      ],
      "object-view-box-fit-cover-svg-ref.html": [
-      "36f1941411d21846dba24b827f27baeb1af8368a",
+      "e449c60f5eb7ec515f6b95f7a0c17f19a50cd97a",
       []
      ],
      "object-view-box-fit-cover-video-ref.html": [
-      "4ffac13bab50bb4acd4a4c9c52715f53056892fd",
+      "5f67394f61d69d8d783296650c6b249a1a6fc9a7",
       []
      ],
      "object-view-box-fit-fill-canvas-ref.html": [
-      "88781621ef870042305e89aa67436ba36f7540ad",
+      "be3b221400a4e889d258ee887a63635d0c55baba",
       []
      ],
      "object-view-box-fit-fill-img-ref.html": [
-      "f6bf841abe0a1a4a40875867b33213051e41b64d",
+      "32c97c8312f4eb78faa9018b0cf8a5f791d451bc",
       []
      ],
      "object-view-box-fit-fill-svg-ref.html": [
-      "5b0f9a8afccb946b0b5512f6efffad245b35a37c",
+      "74c98d6fd3a6865848154dbbebfc10beb1070c14",
       []
      ],
      "object-view-box-fit-fill-video-ref.html": [
-      "6eeb1b29f66eacaf6a1d9b1f752d6fdd7da195bd",
+      "eb46dde08769e66efafedb1daf9d523fb1c8bd12",
       []
      ],
      "object-view-box-fit-none-canvas-ref.html": [
-      "a1b3f5e349f36f97057154fe5a9c65b8d318f35d",
+      "afb695bf34968a7ad9584090229234cd61c487ce",
       []
      ],
      "object-view-box-fit-none-img-ref.html": [
-      "b988298bfae0a94caac24576f205e7ec632d5053",
+      "74d5fc737f06783f276a493cce790394974cd440",
       []
      ],
      "object-view-box-fit-none-svg-ref.html": [
-      "b15cb6235106cc864c16ff7306d7d30f9b790049",
+      "da14fa024dde348295546ab8ac692716c6e12baf",
       []
      ],
      "object-view-box-fit-none-video-ref.html": [
-      "2aacfa8ff7b12a554f347a9d494a291aa2ee4944",
+      "f10e1c18d4989f05c3211463248be2b9619cd724",
       []
      ],
      "object-view-box-iframe-ref.html": [
@@ -278150,19 +278219,19 @@
       []
      ],
      "object-view-box-writing-mode-canvas-ref.html": [
-      "56fa32d58ac6fc1f9e7e3a344d7949ad810bfb57",
+      "d9942ed5356717967166b61e2648d1bcb57e2c1f",
       []
      ],
      "object-view-box-writing-mode-img-ref.html": [
-      "8db7bc679fc1137d1b9b2517f4feb63725c4519b",
+      "9bcdb8ba0b83392fd0c8567b1b3ee8d64deea19b",
       []
      ],
      "object-view-box-writing-mode-svg-ref.html": [
-      "c15b12a73ff7930e8bb9ff5f1c1f3abf0f08c1e2",
+      "c350dcfe5f36b191e9a107a8b5739922babce2da",
       []
      ],
      "object-view-box-writing-mode-video-ref.html": [
-      "e9b5be9c238770394ce6e0aa783439e358af2d8a",
+      "f42fe0162b9c97b6061862a7e3b59f3dfb5f4b24",
       []
      ],
      "object-view-box-xywh-percentage-ref.html": [
@@ -278333,7 +278402,7 @@
        []
       ],
       "object-view-box-fit-contain-ref-template.html": [
-       "1277b833c7d83fd0f36a471f4ccf158222cfdb9c",
+       "2f11249570dfdfe2a1d220cd43bf96d7b9a8fcfd",
        []
       ],
       "object-view-box-fit-contain-template.html": [
@@ -278341,7 +278410,7 @@
        []
       ],
       "object-view-box-fit-cover-ref-template.html": [
-       "9d1fb74b6dd60b80f6305add7faba6f1b1b441a0",
+       "2e830c0bae29e719376c36feedd946924f2b8f62",
        []
       ],
       "object-view-box-fit-cover-template.html": [
@@ -278349,7 +278418,7 @@
        []
       ],
       "object-view-box-fit-fill-ref-template.html": [
-       "b26ce3eacff5b182edf97d967afa1e1a65e8e4d2",
+       "574e29128600a4e5298c663928debb25a3ac8875",
        []
       ],
       "object-view-box-fit-fill-template.html": [
@@ -278357,7 +278426,7 @@
        []
       ],
       "object-view-box-fit-none-ref-template.html": [
-       "421a4a0a568fde852dce7a905e8cf5fe08de9367",
+       "861d9230a38709d61c82c056b2b77abfb3c3d619",
        []
       ],
       "object-view-box-fit-none-template.html": [
@@ -278365,7 +278434,7 @@
        []
       ],
       "object-view-box-writing-mode-ref-template.html": [
-       "2986e5acf2ec3d45a745d45d7562fd4f339c7719",
+       "764ba985fd7b8666e901fd2a4b23f7df1f7ee6e7",
        []
       ],
       "object-view-box-writing-mode-template.html": [
@@ -280971,6 +281040,18 @@
       "5a265c7a73978fdf7e84fbfbf72e2593433cd264",
       []
      ],
+     "overflow-img-object-position-ref.html": [
+      "dde966c99174c4d82fa4f6e1d7d10da0c301f087",
+      []
+     ],
+     "overflow-img-ref.html": [
+      "7764371702dc018e0911d1c90de12c1f23af9655",
+      []
+     ],
+     "overflow-img-svg-ref.html": [
+      "e81f5c158a91b87f7c9d385331842ed56f09e4b3",
+      []
+     ],
      "overflow-scroll-big-border-small-content-ref.html": [
       "c7ea1807443ef1b2d454edd547e65c89a59cea16",
       []
@@ -423422,7 +423503,7 @@
        ]
       ],
       "request-upload.h2.any.js": [
-       "70d11eca76694ba2c184773b751a547da0ff2d66",
+       "aee0ea34fdeb70c2c5c76ce03fd2bc24ba13eba5",
        [
         "fetch/api/basic/request-upload.h2.any.html",
         {
@@ -426563,7 +426644,7 @@
        ]
       ],
       "redirect-upload.h2.any.js": [
-       "82ec43b64e91ab956b8ec2b2edcad6d673152c45",
+       "521bd3adc28bffff38fd2bbdfa7154e566cae3bb",
        [
         "fetch/api/redirect/redirect-upload.h2.any.html",
         {
@@ -428024,7 +428105,7 @@
        ]
       ],
       "request-init-contenttype.any.js": [
-       "d8e048c4fc994a93644f67317fbcdd7dd48e140a",
+       "18a6969d4f8acdfb01261fdc3c1621f2f6bb6708",
        [
         "fetch/api/request/request-init-contenttype.any.html",
         {}
@@ -428035,7 +428116,7 @@
        ]
       ],
       "request-init-stream.any.js": [
-       "ac78a253f7d0df96f81f1b7d0de174c5cdb1b226",
+       "f0ae441a00258ddd37998387a347d801b4029cec",
        [
         "fetch/api/request/request-init-stream.any.html",
         {
@@ -439527,6 +439608,13 @@
          }
         ]
        ],
+       "location-properties-smoke-test.html": [
+        "1d1c1136a6dc9263a964218d6c50408176b7f83f",
+        [
+         null,
+         {}
+        ]
+       ],
        "window-location-and-location-href-cross-realm-set.html": [
         "f03550a1415fb570644fd3d846698f5df0a35e5d",
         [
@@ -461809,36 +461897,144 @@
       ]
      ],
      "reflection-credentialless.tentative.https.any.js": [
-      "82d4223039d821f12370ee968cd1797d82ed8116",
+      "83344e51e5b13e80264b571251080abd302a3319",
       [
        "html/cross-origin-embedder-policy/reflection-credentialless.tentative.https.any.html",
-       {}
+       {
+        "script_metadata": [
+         [
+          "global",
+          "window,dedicatedworker,sharedworker,serviceworker"
+         ]
+        ]
+       }
+      ],
+      [
+       "html/cross-origin-embedder-policy/reflection-credentialless.tentative.https.any.serviceworker.html",
+       {
+        "script_metadata": [
+         [
+          "global",
+          "window,dedicatedworker,sharedworker,serviceworker"
+         ]
+        ]
+       }
+      ],
+      [
+       "html/cross-origin-embedder-policy/reflection-credentialless.tentative.https.any.sharedworker.html",
+       {
+        "script_metadata": [
+         [
+          "global",
+          "window,dedicatedworker,sharedworker,serviceworker"
+         ]
+        ]
+       }
       ],
       [
        "html/cross-origin-embedder-policy/reflection-credentialless.tentative.https.any.worker.html",
-       {}
+       {
+        "script_metadata": [
+         [
+          "global",
+          "window,dedicatedworker,sharedworker,serviceworker"
+         ]
+        ]
+       }
       ]
      ],
      "reflection-require-corp.tentative.https.any.js": [
-      "c96b8f3b5deef700266d0d74d818d760432ac9bb",
+      "ed668d8720db3231b7830057837f5402b69fc7f5",
       [
        "html/cross-origin-embedder-policy/reflection-require-corp.tentative.https.any.html",
-       {}
+       {
+        "script_metadata": [
+         [
+          "global",
+          "window,dedicatedworker,sharedworker,serviceworker"
+         ]
+        ]
+       }
+      ],
+      [
+       "html/cross-origin-embedder-policy/reflection-require-corp.tentative.https.any.serviceworker.html",
+       {
+        "script_metadata": [
+         [
+          "global",
+          "window,dedicatedworker,sharedworker,serviceworker"
+         ]
+        ]
+       }
+      ],
+      [
+       "html/cross-origin-embedder-policy/reflection-require-corp.tentative.https.any.sharedworker.html",
+       {
+        "script_metadata": [
+         [
+          "global",
+          "window,dedicatedworker,sharedworker,serviceworker"
+         ]
+        ]
+       }
       ],
       [
        "html/cross-origin-embedder-policy/reflection-require-corp.tentative.https.any.worker.html",
-       {}
+       {
+        "script_metadata": [
+         [
+          "global",
+          "window,dedicatedworker,sharedworker,serviceworker"
+         ]
+        ]
+       }
       ]
      ],
      "reflection-unsafe-none.tentative.https.any.js": [
-      "4694f9110ec93012f8a25d120ab6ecc456cd070f",
+      "0746d73183296a896e747d5dbcfc2147b5b94000",
       [
        "html/cross-origin-embedder-policy/reflection-unsafe-none.tentative.https.any.html",
-       {}
+       {
+        "script_metadata": [
+         [
+          "global",
+          "window,dedicatedworker,sharedworker,serviceworker"
+         ]
+        ]
+       }
+      ],
+      [
+       "html/cross-origin-embedder-policy/reflection-unsafe-none.tentative.https.any.serviceworker.html",
+       {
+        "script_metadata": [
+         [
+          "global",
+          "window,dedicatedworker,sharedworker,serviceworker"
+         ]
+        ]
+       }
+      ],
+      [
+       "html/cross-origin-embedder-policy/reflection-unsafe-none.tentative.https.any.sharedworker.html",
+       {
+        "script_metadata": [
+         [
+          "global",
+          "window,dedicatedworker,sharedworker,serviceworker"
+         ]
+        ]
+       }
       ],
       [
        "html/cross-origin-embedder-policy/reflection-unsafe-none.tentative.https.any.worker.html",
-       {}
+       {
+        "script_metadata": [
+         [
+          "global",
+          "window,dedicatedworker,sharedworker,serviceworker"
+         ]
+        ]
+       }
       ]
      ],
      "report-only-require-corp.https.html": [
@@ -490602,7 +490798,7 @@
       ]
      ],
      "mediasource-worker-handle-transfer.html": [
-      "cab5073299745764bc74aeadab31b288dbd73065",
+      "9e8f31898df9aa1f4801f08d04b8116f857dce0c",
       [
        null,
        {}
@@ -522770,7 +522966,7 @@
       ]
      ],
      "fetch-event.https.html": [
-      "771f1e319ca47e6cfe60db83fc7d42c2c55cb649",
+      "59a0988b490f6e7378baecc98a0b44dd20315e5d",
       [
        null,
        {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/currentcolor-003-ref.html b/third_party/blink/web_tests/external/wpt/css/css-color/currentcolor-003-ref.html
new file mode 100644
index 0000000..7cabf85f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-color/currentcolor-003-ref.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+  <meta charset="utf-8">
+  <style>
+    div.red {
+      color: red;
+    }
+    div.green {
+      color: green;
+    }
+    span {
+      box-decoration-break: clone;
+      -webkit-box-decoration-break: clone;
+      line-height: 50px;
+      background-image: linear-gradient(currentcolor, currentcolor);
+      background-color: currentColor;
+      background-size: 100% 75%;
+      background-repeat: no-repeat;
+      border: 5px solid currentColor;
+      outline: 5px solid currentColor;
+      box-shadow: 111px 0 5px currentColor;
+      text-shadow: 222px 0 2px currentColor;
+      filter: drop-shadow(333px 0 0 currentColor);
+    }
+  </style>
+ </head>
+ <body>
+  <p>The first and third lines should have no red. The second line should have no green</p>
+   <div class="green"><span>Lorem ipsum</span></div>
+   <div class="red"><span>dolor amet.</span></div>
+   <div class="green"><span>Lorem ipsum.</span></div>
+ </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/currentcolor-003.html b/third_party/blink/web_tests/external/wpt/css/css-color/currentcolor-003.html
new file mode 100644
index 0000000..d3ad9c4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-color/currentcolor-003.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+ <head>
+  <meta charset="utf-8">
+  <title>CSS Color 4: currentcolor</title>
+  <link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
+  <link rel="author" title="Mike Bremford" href="mailto:mike@bfo.com">
+  <link rel="help" href="https://drafts.csswg.org/css-color-4/#currentcolor-color">
+  <link rel="help" href="https://www.w3.org/TR/css-cascade-5/#fragments">
+  <link rel="match" href="currentcolor-003-ref.html">
+  <meta name="assert" content="The currentcolor value applies to the first-line fragment, as discussed in https://github.com/w3c/csswg-drafts/issues/1510">
+  <style>
+    div {
+      color: red;
+    }
+    div::first-line {
+      color: green;
+    }
+    br {
+      line-height: 0;
+    }
+    span {
+      box-decoration-break: clone;
+      -webkit-box-decoration-break: clone;
+      line-height: 50px;
+      background-image: linear-gradient(currentcolor, currentcolor);
+      background-color: currentColor;
+      background-size: 100% 75%;
+      background-repeat: no-repeat;
+      border: 5px solid currentColor;
+      outline: 5px solid currentColor;
+      box-shadow: 111px 0 5px currentColor;
+      text-shadow: 222px 0 2px currentColor;
+      filter: drop-shadow(333px 0 0 currentColor);
+    }
+  </style>
+ </head>
+ <body>
+  <p>The first and third lines should have no red. The second line should have no green</p>
+   <div><span>Lorem ipsum<br />dolor amet.</span></div>
+   <div><span>Lorem ipsum.</span></div>
+ </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/basic/request-upload.h2.any.js b/third_party/blink/web_tests/external/wpt/fetch/api/basic/request-upload.h2.any.js
index e89a039..aee0ea3 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/api/basic/request-upload.h2.any.js
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/basic/request-upload.h2.any.js
@@ -72,6 +72,7 @@
   const request = new Request('', {
     body: new ReadableStream(),
     method: 'POST',
+    duplex,
   });
 
   assert_equals(request.headers.get('Content-Type'), null, `Request should not have a content-type set`);
@@ -79,6 +80,7 @@
   const response = await fetch('data:a/a;charset=utf-8,test', {
     method: 'POST',
     body: new ReadableStream(),
+    duplex,
   });
 
   assert_equals(await response.text(), 'test', `Response has correct body`);
@@ -88,6 +90,7 @@
   const request = new Request('data:a/a;charset=utf-8,test', {
     body: new ReadableStream(),
     method: 'POST',
+    duplex,
  });
 
   assert_equals(request.headers.get('Content-Type'), null, `Request should not have a content-type set`);
@@ -114,22 +117,6 @@
 }, "Streaming upload with body containing a number");
 
 promise_test(async (t) => {
-  const url = "/fetch/api/resources/redirect.h2.py?location=/common/blank.html";
-  const body = createStream([]);
-  const method = "POST";
-  await promise_rejects_js(t, TypeError, fetch(url, { method, body, duplex }));
-}, "Streaming upload should fail on redirect (302)");
-
-promise_test(async (t) => {
-  const url = "/fetch/api/resources/redirect.h2.py?" +
-              "redirect_status=303&location=/common/blank.html";
-  const body = createStream([]);
-  const method = "POST";
-  const resp = await fetch(url, { method, body, duplex });
-  assert_equals(resp.status, 200, 'status');
-}, "Streaming upload should work with 303");
-
-promise_test(async (t) => {
   const url = "/fetch/api/resources/authentication.py?realm=test";
   const body = createStream([]);
   const method = "POST";
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-upload.h2.any.js b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-upload.h2.any.js
index 82ec43b64..521bd3a 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-upload.h2.any.js
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-upload.h2.any.js
@@ -15,6 +15,7 @@
     controller.enqueue(encoder.encode("Test"));
     controller.close();
   }});
+  requestInit.duplex = "half";
   return fetch(url, requestInit);
 }
 
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/request/request-init-contenttype.any.js b/third_party/blink/web_tests/external/wpt/fetch/api/request/request-init-contenttype.any.js
index d8e048c..18a6969d 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/api/request/request-init-contenttype.any.js
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/request/request-init-contenttype.any.js
@@ -4,6 +4,7 @@
     {
       method: "POST",
       body,
+      duplex: "half",
     },
   );
 }
@@ -82,6 +83,7 @@
       method: "POST",
       body,
       headers: { "Content-Type": OVERRIDE_MIME },
+      duplex: "half",
     },
   );
 }
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/cross-origin-access-is-restricted.html b/third_party/blink/web_tests/external/wpt/html/browsers/origin/cross-origin-objects/location-properties-smoke-test.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/cross-origin-access-is-restricted.html
rename to third_party/blink/web_tests/external/wpt/html/browsers/origin/cross-origin-objects/location-properties-smoke-test.html
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/render-blocking-status-link.html b/third_party/blink/web_tests/external/wpt/resource-timing/render-blocking-status-link.html
new file mode 100644
index 0000000..8c6544d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/render-blocking-status-link.html
@@ -0,0 +1,222 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8" />
+<title>This test validates the render blocking status of resources.</title>
+<link rel="help" href="https://www.w3.org/TR/resource-timing-2/#sec-performanceresourcetiming"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<!-- Start of test cases -->
+<script>
+    // Dynamic style using document.write in head
+    document.write(`
+        <link rel=stylesheet
+              href='resources/empty_style.css?stylesheet-head-dynamic-docWrite'>
+    `);
+    document.write(`
+        <link rel=stylesheet
+              href='resources/empty_style.css?stylesheet-head-dynamic-docWrite-print'
+              media=print>
+    `);
+</script>
+
+<link rel=stylesheet href="resources/empty_style.css?stylesheet-head">
+<link rel=stylesheet href="resources/empty_style.css?stylesheet-head-media-print"
+      media=print>
+<link rel="alternate stylesheet"
+      href="resources/empty_style.css?stylesheet-head-alternate">
+<link rel=preload as=style href="resources/empty_style.css?link-style-head-preload">
+<link rel=preload as=style href="resources/empty_style.css?link-style-preload-used">
+<link rel=stylesheet href="resources/importer.css?stylesheet-importer-head">
+<link rel=stylesheet id="link-head-remove-attr" blocking="render"
+    href="resources/empty_style.css?stylesheet-head-blocking-render-remove-attr">
+<link rel=modulepreload href="resources/empty_script.js?link-head-modulepreload">
+
+<style>@import url(resources/empty_style.css?stylesheet-inline-imported);</style>
+<style media=print>
+    @import url(resources/empty_style.css?stylesheet-inline-imported-print);
+</style>
+</head>
+
+<body>
+
+<link rel=stylesheet href="resources/empty_style.css?stylesheet-body">
+<link rel=stylesheet href="resources/importer.css?stylesheet-importer-body">
+<link rel=stylesheet href="resources/empty_style.css?stylesheet-body-media-print"
+      media=print>
+<link rel=stylesheet blocking="render"
+    href="resources/empty_style.css?stylesheet-body-blocking-render">
+
+<!-- https://html.spec.whatwg.org/multipage/urls-and-fetching.html#blocking-attributes
+     mentions that an element is potentially render-blocking if its blocking
+     tokens set contains "render", or if it is implicitly potentially
+     render-blocking. By default, an element is not implicitly potentially
+     render-blocking.
+     https://html.spec.whatwg.org/multipage/links.html#link-type-stylesheet
+     specifies that a link element of type stylesheet is implicitly potentially
+     render-blocking only if the element was created by its node document's parser. -->
+<script>
+    // Dynamic style using document.write in body
+    document.write(`
+        <link rel=stylesheet
+              href='resources/empty_style.css?stylesheet-body-dynamic-docWrite'>
+    `);
+    document.write(`
+        <link rel=stylesheet
+              href='resources/empty_style.css?stylesheet-body-dynamic-docWrite-print'
+              media=print>
+    `);
+
+    // Dynamic style using innerHTML
+    document.head.innerHTML += `
+        <link rel=stylesheet
+              href='resources/empty_style.css?stylesheet-head-dynamic-innerHTML'>
+    `;
+    document.head.innerHTML += `
+        <link rel=stylesheet
+              href='resources/empty_style.css?stylesheet-head-dynamic-innerHTML-print'
+              media=print>
+    `;
+    document.head.innerHTML += `
+        <link rel=stylesheet blocking=render
+              href='resources/empty_style.css?stylesheet-head-blocking-render-dynamic-innerHTML'>
+    `;
+
+    // Dynamic style using DOM API
+    var link = document.createElement("link");
+    link.href = "resources/empty_style.css?stylesheet-head-dynamic-dom";
+    link.rel = "stylesheet";
+    document.head.appendChild(link);
+
+    // Add a dynamic render-blocking style with DOM API
+    link = document.createElement("link");
+    link.href = "resources/empty_style.css?stylesheet-head-blocking-render-dynamic-dom";
+    link.rel = "stylesheet";
+    link.blocking = "render";
+    document.head.appendChild(link);
+
+    // Dynamic style preload using DOM API
+    link = document.createElement("link");
+    link.href = "resources/empty_style.css?link-style-head-preload-dynamic-dom";
+    link.rel = "preload";
+    link.as = "style";
+    document.head.appendChild(link);
+
+    // Dynamic module via modulepreload using DOM API
+    link = document.createElement("link");
+    link.href = "resources/empty_script.js?link-head-modulepreload-dynamic-dom";
+    link.rel = "modulepreload";
+    document.head.appendChild(link);
+
+    // Add a style preload with DOM API to be used later
+    link = document.createElement("link");
+    link.href = "resources/empty_style.css?link-style-preload-used-dynamic";
+    link.rel = "preload";
+    link.as = "style";
+    document.head.appendChild(link);
+    // Use the preload
+    link = document.createElement("link");
+    link.href = "resources/empty_style.css?link-style-preload-used-dynamic";
+    link.rel = "stylesheet";
+    document.head.appendChild(link);
+
+    // Dynamic inline CSS
+    // Add an inline CSS importer
+    document.write(`
+        <style>
+            @import url('resources/empty_style.css?stylesheet-inline-imported-dynamic-docwrite')
+        </style>
+    `);
+    document.write(`
+        <style media=print>
+            @import url('resources/empty_style.css?stylesheet-inline-imported-dynamic-docwrite-print')
+        </style>
+    `);
+
+    // Add a dynamic inline CSS importer using DOM API
+    let style = document.createElement("style");
+    style.textContent = "@import url('resources/empty_style.css?stylesheet-inline-imported-dynamic-dom')";
+    document.head.appendChild(style);
+
+    // Add a dynamic render-blocking inline CSS importer
+    style = document.createElement("style");
+    style.textContent = "@import url('resources/empty_style.css?stylesheet-inline-imported-blocking-render-dynamic-dom')";
+    style.blocking = "render";
+    document.head.appendChild(style);
+
+    // Dynamic CSS importer
+    document.write(`
+        <link rel=stylesheet href='resources/importer_dynamic.css'>
+    `);
+    document.write(`
+        <link rel=stylesheet href='resources/importer_print.css' media=print>
+    `);
+
+    // Removing blocking render attribute after request is made
+    const sheet = document.getElementById("link-head-remove-attr");
+    sheet.blocking = "";
+</script>
+
+<link rel=stylesheet href="resources/empty_style.css?link-style-preload-used">
+
+<script>
+
+const wait_for_onload = () => {
+  return new Promise(resolve => {
+    window.addEventListener("load", resolve);
+})};
+
+promise_test(
+  async () => {
+    const expectedRenderBlockingStatus = {
+        'stylesheet-head-dynamic-docWrite': 'blocking',
+        'stylesheet-head-dynamic-docWrite-print': 'non-blocking',
+        'stylesheet-head': 'blocking',
+        'stylesheet-head-media-print' : 'non-blocking',
+        'stylesheet-head-alternate' : 'non-blocking',
+        'link-style-head-preload' : 'non-blocking',
+        'stylesheet-importer-head' : 'blocking',
+        'stylesheet-head-blocking-render-remove-attr' : 'blocking',
+        'link-head-modulepreload' : 'non-blocking',
+        'stylesheet-inline-imported' : 'blocking',
+        'stylesheet-inline-imported-print' : 'non-blocking',
+        'stylesheet-body': 'non-blocking',
+        'stylesheet-importer-body' : 'non-blocking',
+        'stylesheet-body-media-print' : 'non-blocking',
+        'stylesheet-body-blocking-render' : 'non-blocking',
+        'stylesheet-body-dynamic-docWrite' : 'non-blocking',
+        'stylesheet-body-dynamic-docWrite-print': 'non-blocking',
+        'stylesheet-head-dynamic-innerHTML' : 'non-blocking',
+        'stylesheet-head-dynamic-innerHTML-print' : 'non-blocking',
+        'stylesheet-head-blocking-render-dynamic-innerHTML' : 'blocking',
+        'stylesheet-head-dynamic-dom' : 'non-blocking',
+        'stylesheet-head-blocking-render-dynamic-dom' : 'blocking',
+        'link-style-head-preload-dynamic-dom' : 'non-blocking',
+        'link-head-modulepreload-dynamic-dom' : 'non-blocking',
+        'link-style-preload-used' : 'non-blocking',
+        'link-style-preload-used-dynamic' : 'non-blocking',
+        'stylesheet-inline-imported-dynamic-docwrite': 'blocking',
+        'stylesheet-inline-imported-dynamic-docwrite-print' : 'non-blocking',
+        'stylesheet-inline-imported-dynamic-dom' : 'non-blocking',
+        'stylesheet-inline-imported-blocking-render-dynamic-dom' : 'blocking',
+        'stylesheet-imported' : 'blocking',
+        'stylesheet-imported-print' : 'non-blocking',
+        'stylesheet-imported-dynamic' : 'non-blocking'
+    };
+
+    await wait_for_onload();
+
+    const entry_list = performance.getEntriesByType("resource");
+    for (entry of entry_list) {
+        if (entry.name.includes("empty_style.css") ||
+                entry.name.includes("importer.css") ||
+                entry.name.includes("empty_script.js")) {
+            key = entry.name.split("?").pop();
+            expectedStatus = expectedRenderBlockingStatus[key];
+            assert_equals(entry.renderBlockingStatus, expectedStatus,
+                `render blocking status for ${entry.name} should be ${expectedStatus}`);
+        }
+    }
+}, "Validate render blocking status of link resources in PerformanceResourceTiming");
+
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/render-blocking-status-script.html b/third_party/blink/web_tests/external/wpt/resource-timing/render-blocking-status-script.html
new file mode 100644
index 0000000..bcd55b89
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/render-blocking-status-script.html
@@ -0,0 +1,196 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8" />
+<title>This test validates the render blocking status of resources.</title>
+<link rel="help" href="https://www.w3.org/TR/resource-timing-2/#sec-performanceresourcetiming"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<!-- Start of test cases -->
+<script src="resources/empty_script.js?script-head"></script>
+<script type="module" src="resources/empty_script.js?script-head-module"></script>
+<script async type=module
+        src="resources/empty_script.js?script-head-async-module">
+</script>
+<script async src="resources/empty_script.js?script-head-async"></script>
+<script defer src="resources/empty_script.js?script-head-defer"></script>
+<script blocking=render
+        src="resources/empty_script.js?script-head-blocking-render">
+</script>
+<script async blocking=render
+        src="resources/empty_script.js?script-head-async-blocking-render">
+</script>
+<script type=module blocking=render
+        src="resources/empty_script.js?script-head-module-blocking-render">
+</script>
+<script async type=module blocking=render
+        src="resources/empty_script.js?script-head-async-module-blocking-render">
+</script>
+<script defer blocking=render
+        src="resources/empty_script.js?script-head-defer-blocking-render">
+</script>
+
+<script id="script-head-remove-attr" blocking=render
+        src="resources/empty_script.js?script-head-blocking-render-remove-attr">
+</script>
+
+<script>
+    document.write(`
+        <script defer
+            src="resources/empty_script.js?script-head-defer-dynamic-docwrite">
+        <\/script>`);
+</script>
+</head>
+
+<body>
+
+<script src="resources/empty_script.js?script-body"></script>
+<script type="module" src="resources/empty_script.js?script-body-module"></script>
+<script async type=module
+        src="resources/empty_script.js?script-body-async-module">
+</script>
+<script async src="resources/empty_script.js?script-body-async"></script>
+<script defer src="resources/empty_script.js?script-body-defer"></script>
+
+<script>
+    const script = document.createElement("script");
+    script.src = "resources/empty_script.js?script-head-dynamic-dom";
+    document.head.appendChild(script);
+
+    // Dynamic explicitly async script
+    const async_script = document.createElement("script");
+    async_script.src = "resources/empty_script.js?script-head-async-dynamic-dom";
+    async_script.async = true;
+    document.head.appendChild(async_script);
+
+    // Dynamic non-async script
+    // https://html.spec.whatwg.org/multipage/scripting.html#script-processing-model
+    // mentions that a script element has to be parser-inserted to be
+    // implicitly potentially render-blocking
+    const non_async_script = document.createElement("script");
+    non_async_script.src = "resources/empty_script.js?script-head-non-async-dynamic-dom";
+    non_async_script.async = false;
+    document.head.appendChild(non_async_script);
+
+    // Dynamic defer script
+    const defer_script = document.createElement("script");
+    defer_script.src = "resources/empty_script.js?script-head-defer-dynamic-dom";
+    defer_script.defer = true;
+    document.head.appendChild(defer_script);
+
+    // Dynamic explicitly render-blocking script
+    const blocking_script = document.createElement("script");
+    blocking_script.src = "resources/empty_script.js?script-head-blocking-render-dynamic-dom";
+    blocking_script.blocking = "render";
+    document.head.appendChild(blocking_script);
+
+    // Dynamic explicitly render-blocking module script
+    const blocking_module_script = document.createElement("script");
+    blocking_module_script.src = "resources/empty_script.js?script-head-module-blocking-render-dynamic-dom";
+    blocking_module_script.type = "module";
+    blocking_module_script.blocking = "render";
+    document.head.appendChild(blocking_module_script);
+
+    // Dynamic async module script
+    const async_module_script = document.createElement("script");
+    async_module_script.src = "resources/empty_script.js?script-head-async-module-dynamic-dom";
+    async_module_script.type = "module";
+    async_module_script.async = true;
+    document.head.appendChild(async_module_script);
+
+    // Dynamic async render-blocking module script
+    const async_blocking_module_script = document.createElement("script");
+    async_blocking_module_script.src = "resources/empty_script.js?script-head-async-module-blocking-render-dynamic-dom";
+    async_blocking_module_script.type = "module";
+    async_blocking_module_script.async = true;
+    async_blocking_module_script.blocking = "render"
+    document.head.appendChild(async_blocking_module_script);
+
+    // Add a module that imports more modules
+    const importer_script = document.createElement("script");
+    importer_script.src = "resources/fake_responses.py?url=importer.js";
+    importer_script.type = "module";
+    document.head.appendChild(importer_script);
+
+    // Add an async module that imports more modules
+    const importer_async_script = document.createElement("script");
+    importer_async_script.src = "resources/fake_responses.py?url=importer_async.js";
+    importer_async_script.type = "module";
+    importer_async_script.async = true;
+    document.head.appendChild(importer_async_script);
+
+    // Removing blocking render attribute after request is made
+    const script_element = document.getElementById("script-head-remove-attr");
+    script_element.blocking = "";
+</script>
+
+
+<script>
+
+const wait_for_onload = () => {
+  return new Promise(resolve => {
+    window.addEventListener("load", resolve);
+})};
+
+promise_test(
+  async () => {
+    const expectedRenderBlockingStatus = {
+        'script-head': 'blocking',
+        'script-head-module' : 'non-blocking',
+        'script-head-async-module' : 'non-blocking',
+        'script-head-async' : 'non-blocking',
+        'script-head-defer' : 'non-blocking',
+        'script-head-blocking-render' : 'blocking',
+        'script-head-async-blocking-render' : 'blocking',
+        'script-head-module-blocking-render' : 'blocking',
+        'script-head-async-module-blocking-render' : 'blocking',
+        'script-head-defer-blocking-render' : 'blocking',
+        'script-head-blocking-render-remove-attr' : 'blocking',
+        'script-head-defer-dynamic-docwrite' : 'non-blocking',
+        'script-body' : 'non-blocking',
+        'script-body-module' : 'non-blocking',
+        'script-body-async-module' : 'non-blocking',
+        'script-body-async' : 'non-blocking',
+        'script-body-defer' : 'non-blocking',
+        'script-head-dynamic-dom': 'non-blocking',
+        'script-head-async-dynamic-dom' : 'non-blocking',
+        'script-head-non-async-dynamic-dom': 'non-blocking',
+        'script-head-defer-dynamic-dom' : 'non-blocking',
+        'script-head-blocking-render-dynamic-dom' : 'blocking',
+        'script-head-module-blocking-render-dynamic-dom' : 'blocking',
+        'script-head-async-module-dynamic-dom' : 'non-blocking',
+        'script-head-async-module-blocking-render-dynamic-dom' : 'blocking',
+        'script-head-import-defer' : 'non-blocking',
+        'script-head-import-defer-dynamic' : 'non-blocking',
+        'script-head-import-async' : 'non-blocking',
+        'script-head-import-async-dynamic' : 'non-blocking',
+        'script-importer' : 'non-blocking',
+        'script-importer-async' : 'non-blocking'
+    };
+
+    await wait_for_onload();
+
+    const entry_list = performance.getEntriesByType("resource");
+    for (entry of entry_list) {
+        if (entry.name.includes("empty_script.js")) {
+            key = entry.name.split("?").pop();
+            expectedStatus = expectedRenderBlockingStatus[key];
+            assert_equals(entry.renderBlockingStatus, expectedStatus,
+                `render blocking status for ${entry.name} should be ${expectedStatus}`);
+        }
+        else if (entry.name.includes("importer.js")){
+            key = 'script-importer';
+            expectedStatus = expectedRenderBlockingStatus[key];
+            assert_equals(entry.renderBlockingStatus, expectedStatus,
+                `render blocking status for ${entry.name} should be ${expectedStatus}`);
+        }
+        else if (entry.name.includes("importer_async.js")){
+            key = 'script-importer-async';
+            expectedStatus = expectedRenderBlockingStatus[key];
+            assert_equals(entry.renderBlockingStatus, expectedStatus,
+                `render blocking status for ${entry.name} should be ${expectedStatus}`);
+        }
+    }
+}, "Validate render blocking status of script resources in PerformanceResourceTiming");
+
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/empty_style.css b/third_party/blink/web_tests/external/wpt/resource-timing/resources/empty_style.css
new file mode 100644
index 0000000..eb90b43
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/empty_style.css
@@ -0,0 +1 @@
+/*Nothing here*/
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/fake_responses.py b/third_party/blink/web_tests/external/wpt/resource-timing/resources/fake_responses.py
index e33adbf..66b17be 100644
--- a/third_party/blink/web_tests/external/wpt/resource-timing/resources/fake_responses.py
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/fake_responses.py
@@ -12,6 +12,7 @@
     match = request.headers.get(b"If-None-Match", None)
     date = request.GET.first(b"date", b"")
     modified = request.headers.get(b"If-Modified-Since", None)
+    url = request.GET.first(b"url", None)
     response.headers.set(b"Access-Control-Allow-Origin", b"*");
     response.headers.set(b"Timing-Allow-Origin", b"*");
     if tag:
@@ -23,6 +24,14 @@
         response.status = (302, b"Moved")
         return b""
 
+    if url:
+        filename = url.decode('utf-8').split("?")[0]
+        filepath = "./resource-timing/resources/{}".format(filename)
+        response.headers.set(b"Content-Type", b"text/javascript")
+        with open(filepath, 'rb') as f:
+            filedata = f.read()
+        return filedata
+
     if ((match is not None and match == tag) or
         (modified is not None and modified == date)):
         response.status = (304, b"SUPERCOOL")
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/importer.css b/third_party/blink/web_tests/external/wpt/resource-timing/resources/importer.css
new file mode 100644
index 0000000..771204c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/importer.css
@@ -0,0 +1 @@
+@import 'empty_style.css?stylesheet-imported'
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/importer.js b/third_party/blink/web_tests/external/wpt/resource-timing/resources/importer.js
new file mode 100644
index 0000000..e73d45d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/importer.js
@@ -0,0 +1,2 @@
+import './fake_responses.py?url=empty_script.js?script-head-import-defer';
+import('./fake_responses.py?url=empty_script.js?script-head-import-defer-dynamic').then(module => {});
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/importer_async.js b/third_party/blink/web_tests/external/wpt/resource-timing/resources/importer_async.js
new file mode 100644
index 0000000..4b1cd4d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/importer_async.js
@@ -0,0 +1,2 @@
+import './fake_responses.py?url=empty_script.js?script-head-import-async';
+import('./fake_responses.py?url=empty_script.js?script-head-import-async-dynamic').then(module => {});
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/importer_dynamic.css b/third_party/blink/web_tests/external/wpt/resource-timing/resources/importer_dynamic.css
new file mode 100644
index 0000000..f0ba069
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/importer_dynamic.css
@@ -0,0 +1 @@
+@import 'empty_style.css?stylesheet-imported-dynamic'
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/importer_print.css b/third_party/blink/web_tests/external/wpt/resource-timing/resources/importer_print.css
new file mode 100644
index 0000000..aac191635
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/importer_print.css
@@ -0,0 +1 @@
+@import 'empty_style.css?stylesheet-imported-print'
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/tojson.html b/third_party/blink/web_tests/external/wpt/resource-timing/tojson.html
index 2fe2a60e..7a6187d 100644
--- a/third_party/blink/web_tests/external/wpt/resource-timing/tojson.html
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/tojson.html
@@ -46,7 +46,8 @@
         'responseEnd',
         'transferSize',
         'encodedBodySize',
-        'decodedBodySize'
+        'decodedBodySize',
+        'renderBlockingStatus'
       ];
       for (const key of performanceResourceTimingKeys) {
         try {
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event.https.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event.https.html
index 771f1e3..59a0988b 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event.https.html
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event.https.html
@@ -446,7 +446,8 @@
     t.add_cleanup(() => { frame.remove(); });
     const res = await frame.contentWindow.fetch('simple.html?request-body', {
       method: 'POST',
-      body: rs.pipeThrough(new TextEncoderStream())
+      body: rs.pipeThrough(new TextEncoderStream()),
+      duplex: 'half',
     });
     assert_equals(await res.text(), 'i am the request body');
   }, 'FetchEvent#body is a ReadableStream');
@@ -503,7 +504,8 @@
     const echo_url = '/fetch/api/resources/echo-content.py?ignore';
     const response = await frame.contentWindow.fetch(echo_url, {
         method: 'POST',
-        body: rs.pipeThrough(new TextEncoderStream())
+        body: rs.pipeThrough(new TextEncoderStream()),
+        duplex: 'half',
     });
     const text = await response.text();
     assert_equals(text,
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/fetch/api/request/request-init-stream.any-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/fetch/api/request/request-init-stream.any-expected.txt
deleted file mode 100644
index c500108..0000000
--- a/third_party/blink/web_tests/platform/generic/external/wpt/fetch/api/request/request-init-stream.any-expected.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-This is a testharness.js-based test.
-PASS Constructing a Request with a stream holds the original object.
-PASS Constructing a Request with a stream on which getReader() is called
-PASS Constructing a Request with a stream on which read() is called
-PASS Constructing a Request with a stream on which read() and releaseLock() are called
-PASS Constructing a Request with a Request on which body.getReader() is called
-PASS Constructing a Request with a Request on which body.getReader().read() is called
-PASS Constructing a Request with a Request on which read() and releaseLock() are called
-PASS It is OK to omit .duplex when the body is null.
-PASS It is OK to omit .duplex when the body is a string.
-PASS It is OK to omit .duplex when the body is a Uint8Array.
-PASS It is OK to omit .duplex when the body is a Blob.
-FAIL It is error to omit .duplex when the body is a ReadableStream. assert_throws_js: function "() => new Request("...", { method, body })" did not throw
-PASS It is OK to set .duplex = 'half' when the body is null.
-PASS It is OK to set .duplex = 'half' when the body is a string.
-PASS It is OK to set .duplex = 'half' when the body is a Uint8Array.
-PASS It is OK to set .duplex = 'half' when the body is a Blob.
-PASS It is OK to set .duplex = 'half' when the body is a ReadableStream.
-FAIL It is error to set .duplex = 'full' when the body is null. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a string. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a Uint8Array. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a Blob. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a ReadableStream. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-PASS It is OK to omit duplex when init.body is not given and input.body is given.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/fetch/api/request/request-init-stream.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/fetch/api/request/request-init-stream.any.serviceworker-expected.txt
deleted file mode 100644
index c500108..0000000
--- a/third_party/blink/web_tests/platform/generic/external/wpt/fetch/api/request/request-init-stream.any.serviceworker-expected.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-This is a testharness.js-based test.
-PASS Constructing a Request with a stream holds the original object.
-PASS Constructing a Request with a stream on which getReader() is called
-PASS Constructing a Request with a stream on which read() is called
-PASS Constructing a Request with a stream on which read() and releaseLock() are called
-PASS Constructing a Request with a Request on which body.getReader() is called
-PASS Constructing a Request with a Request on which body.getReader().read() is called
-PASS Constructing a Request with a Request on which read() and releaseLock() are called
-PASS It is OK to omit .duplex when the body is null.
-PASS It is OK to omit .duplex when the body is a string.
-PASS It is OK to omit .duplex when the body is a Uint8Array.
-PASS It is OK to omit .duplex when the body is a Blob.
-FAIL It is error to omit .duplex when the body is a ReadableStream. assert_throws_js: function "() => new Request("...", { method, body })" did not throw
-PASS It is OK to set .duplex = 'half' when the body is null.
-PASS It is OK to set .duplex = 'half' when the body is a string.
-PASS It is OK to set .duplex = 'half' when the body is a Uint8Array.
-PASS It is OK to set .duplex = 'half' when the body is a Blob.
-PASS It is OK to set .duplex = 'half' when the body is a ReadableStream.
-FAIL It is error to set .duplex = 'full' when the body is null. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a string. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a Uint8Array. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a Blob. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a ReadableStream. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-PASS It is OK to omit duplex when init.body is not given and input.body is given.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/fetch/api/request/request-init-stream.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/fetch/api/request/request-init-stream.any.sharedworker-expected.txt
deleted file mode 100644
index c500108..0000000
--- a/third_party/blink/web_tests/platform/generic/external/wpt/fetch/api/request/request-init-stream.any.sharedworker-expected.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-This is a testharness.js-based test.
-PASS Constructing a Request with a stream holds the original object.
-PASS Constructing a Request with a stream on which getReader() is called
-PASS Constructing a Request with a stream on which read() is called
-PASS Constructing a Request with a stream on which read() and releaseLock() are called
-PASS Constructing a Request with a Request on which body.getReader() is called
-PASS Constructing a Request with a Request on which body.getReader().read() is called
-PASS Constructing a Request with a Request on which read() and releaseLock() are called
-PASS It is OK to omit .duplex when the body is null.
-PASS It is OK to omit .duplex when the body is a string.
-PASS It is OK to omit .duplex when the body is a Uint8Array.
-PASS It is OK to omit .duplex when the body is a Blob.
-FAIL It is error to omit .duplex when the body is a ReadableStream. assert_throws_js: function "() => new Request("...", { method, body })" did not throw
-PASS It is OK to set .duplex = 'half' when the body is null.
-PASS It is OK to set .duplex = 'half' when the body is a string.
-PASS It is OK to set .duplex = 'half' when the body is a Uint8Array.
-PASS It is OK to set .duplex = 'half' when the body is a Blob.
-PASS It is OK to set .duplex = 'half' when the body is a ReadableStream.
-FAIL It is error to set .duplex = 'full' when the body is null. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a string. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a Uint8Array. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a Blob. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a ReadableStream. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-PASS It is OK to omit duplex when init.body is not given and input.body is given.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/fetch/api/request/request-init-stream.any.worker-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/fetch/api/request/request-init-stream.any.worker-expected.txt
deleted file mode 100644
index c500108..0000000
--- a/third_party/blink/web_tests/platform/generic/external/wpt/fetch/api/request/request-init-stream.any.worker-expected.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-This is a testharness.js-based test.
-PASS Constructing a Request with a stream holds the original object.
-PASS Constructing a Request with a stream on which getReader() is called
-PASS Constructing a Request with a stream on which read() is called
-PASS Constructing a Request with a stream on which read() and releaseLock() are called
-PASS Constructing a Request with a Request on which body.getReader() is called
-PASS Constructing a Request with a Request on which body.getReader().read() is called
-PASS Constructing a Request with a Request on which read() and releaseLock() are called
-PASS It is OK to omit .duplex when the body is null.
-PASS It is OK to omit .duplex when the body is a string.
-PASS It is OK to omit .duplex when the body is a Uint8Array.
-PASS It is OK to omit .duplex when the body is a Blob.
-FAIL It is error to omit .duplex when the body is a ReadableStream. assert_throws_js: function "() => new Request("...", { method, body })" did not throw
-PASS It is OK to set .duplex = 'half' when the body is null.
-PASS It is OK to set .duplex = 'half' when the body is a string.
-PASS It is OK to set .duplex = 'half' when the body is a Uint8Array.
-PASS It is OK to set .duplex = 'half' when the body is a Blob.
-PASS It is OK to set .duplex = 'half' when the body is a ReadableStream.
-FAIL It is error to set .duplex = 'full' when the body is null. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a string. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a Uint8Array. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a Blob. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-FAIL It is error to set .duplex = 'full' when the body is a ReadableStream. assert_throws_js: function "() => new Request("...", { method, body, duplex })" did not throw
-PASS It is OK to omit duplex when init.body is not given and input.body is given.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/generic/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/platform/generic/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 6e450c1..b66e6bf2 100644
--- a/third_party/blink/web_tests/platform/generic/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1174,6 +1174,7 @@
     getter nextHopProtocol
     getter redirectEnd
     getter redirectStart
+    getter renderBlockingStatus
     getter requestStart
     getter responseEnd
     getter responseStart
diff --git a/third_party/blink/web_tests/platform/generic/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/platform/generic/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 8761ef6..7c19ffd 100644
--- a/third_party/blink/web_tests/platform/generic/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1224,6 +1224,7 @@
 [Worker]     getter nextHopProtocol
 [Worker]     getter redirectEnd
 [Worker]     getter redirectStart
+[Worker]     getter renderBlockingStatus
 [Worker]     getter requestStart
 [Worker]     getter responseEnd
 [Worker]     getter responseStart
diff --git a/third_party/blink/web_tests/platform/generic/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/platform/generic/webexposed/global-interface-listing-expected.txt
index 32cbe9e..9988324 100644
--- a/third_party/blink/web_tests/platform/generic/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/webexposed/global-interface-listing-expected.txt
@@ -6503,6 +6503,7 @@
     getter nextHopProtocol
     getter redirectEnd
     getter redirectStart
+    getter renderBlockingStatus
     getter requestStart
     getter responseEnd
     getter responseStart
diff --git a/third_party/blink/web_tests/platform/generic/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/platform/generic/webexposed/global-interface-listing-shared-worker-expected.txt
index 1b7a82dc..5744835 100644
--- a/third_party/blink/web_tests/platform/generic/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -1080,6 +1080,7 @@
 [Worker]     getter nextHopProtocol
 [Worker]     getter redirectEnd
 [Worker]     getter redirectStart
+[Worker]     getter renderBlockingStatus
 [Worker]     getter requestStart
 [Worker]     getter responseEnd
 [Worker]     getter responseStart
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/prerender/wpt_internal/prerender/activate-from-iframe-expected.txt b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/prerender/wpt_internal/prerender/activate-from-iframe-expected.txt
index 3263cfc..1f067a86 100644
--- a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/prerender/wpt_internal/prerender/activate-from-iframe-expected.txt
+++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/prerender/wpt_internal/prerender/activate-from-iframe-expected.txt
@@ -1,4 +1,4 @@
 This is a testharness.js-based test.
-FAIL Navigation on the main frame initiated by window opened by an iframe opening via window.parent.location should not activate a prerendered page assert_equals: expected "attempting prerender activation" but got "loaded from scratch"
+PASS Navigation on the main frame initiated by window opened by an iframe opening via window.parent.location should not activate a prerendered page
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/mac/virtual/prerender/wpt_internal/prerender/activate-from-iframe-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/prerender/wpt_internal/prerender/activate-from-iframe-expected.txt
new file mode 100644
index 0000000..3263cfc
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/prerender/wpt_internal/prerender/activate-from-iframe-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Navigation on the main frame initiated by window opened by an iframe opening via window.parent.location should not activate a prerendered page assert_equals: expected "attempting prerender activation" but got "loaded from scratch"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/autofocus-denied.https.html b/third_party/blink/web_tests/wpt_internal/fenced_frame/autofocus-denied.https.html
new file mode 100644
index 0000000..ff6955a
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/fenced_frame/autofocus-denied.https.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Autofocusing is blocked in a fenced frame</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="resources/utils.js"></script>
+
+<body>
+<script>
+promise_test(async () => {
+  const frame = attachFencedFrameContext();
+  let autofocusIsFocused = await frame.execute(async () => {
+    let autofocusInput = document.createElement('input');
+    autofocusInput.autofocus = true;
+    document.body.appendChild(autofocusInput);
+    await new Promise(resolve => requestAnimationFrame(resolve));
+    return document.activeElement == autofocusInput;
+  });
+  assert_false(autofocusIsFocused, "<input autofocus> received focus");
+}, "Autofocusing is blocked on an element in a fenced frame as "+
+     "it's treated like a cross-origin subframe.");
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/task-tracking/track-settimeout.html b/third_party/blink/web_tests/wpt_internal/task-tracking/track-settimeout.html
index e9681cd..d02d982f 100644
--- a/third_party/blink/web_tests/wpt_internal/task-tracking/track-settimeout.html
+++ b/third_party/blink/web_tests/wpt_internal/task-tracking/track-settimeout.html
@@ -26,6 +26,25 @@
 promise_test(() => {
   return new Promise(async (resolve, reject) => {
     const initialId = scheduler.taskId;
+    await new Promise(internal_resolve => {
+      window.resolve = internal_resolve;
+      setTimeout("resolve()", 100);
+    });
+    queueMicrotask(() => {
+      try {
+        assert_equals(scheduler.isAncestor(initialId), "ancestor");
+        resolve();
+      } catch {
+        reject("Not an ancestor");
+      }
+    });
+  });
+}, "A microtask queued after a long setTimeout task with text input is a " +
+   "descendant of the dispatching task");
+
+promise_test(() => {
+  return new Promise(async (resolve, reject) => {
+    const initialId = scheduler.taskId;
     await new Promise(resolve => setTimeout(resolve, 100));
     queueMicrotask(() => {
       try {
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index e6d9520..26f478f 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-12-1-41-gbec4ef415
-Revision: bec4ef415ef07ad1fa9542978136d9863dd7a6d0
+Version: VER-2-12-1-45-g31b14fd4d
+Revision: 31b14fd4dce4b017090f5ba7c15a178fa0ce6d7d
 CPEPrefix: cpe:/a:freetype:freetype:2.11.1
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 45d5619..a19c0202 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -23119,6 +23119,11 @@
   <description>Set system time dialog was launched.</description>
 </action>
 
+<action name="Options_ShowAddresses">
+  <owner>vidhanj@google.com</owner>
+  <description>Settings: Show addresses</description>
+</action>
+
 <action name="Options_ShowAdvancedSettings">
   <owner>stevenjb@chromium.org</owner>
   <description>Settings: Show advanced settings</description>
@@ -23171,6 +23176,11 @@
   <description>Settings: saved passwords</description>
 </action>
 
+<action name="Options_ShowPaymentMethods">
+  <owner>vidhanj@google.com</owner>
+  <description>Settings: Show payment options</description>
+</action>
+
 <action name="Options_ShowPowerSettings">
   <owner>michaelpg@chromium.org</owner>
   <description>Settings: Manage power</description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 49735d3..f7642e2 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -39601,7 +39601,7 @@
   <int value="3361" label="OBSOLETE_MainFrameCSPViaOriginPolicy"/>
   <int value="3362" label="HtmlClipboardApiRead"/>
   <int value="3363" label="HtmlClipboardApiWrite"/>
-  <int value="3364" label="CSSSystemColorComputeToSelf"/>
+  <int value="3364" label="OBSOLETE_CSSSystemColorComputeToSelf"/>
   <int value="3365" label="ConversionAPIAll"/>
   <int value="3366" label="ImpressionRegistration"/>
   <int value="3367" label="ConversionRegistration"/>
@@ -40567,6 +40567,7 @@
   <int value="4290" label="DeviceOrientationUsedWithoutPermissionRequest"/>
   <int value="4291" label="DeviceMotionPermissionRequested"/>
   <int value="4292" label="DeviceMotionUsedWithoutPermissionRequest"/>
+  <int value="4293" label="PrivateNetworkAccessPermissionPrompt"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
@@ -75218,6 +75219,12 @@
   <int value="8" label="API was successfully called, but result is unknown."/>
 </enum>
 
+<enum name="PasswordStoreAndroidBackendRequestStatus">
+  <int value="0" label="Requested"/>
+  <int value="1" label="Timeout"/>
+  <int value="2" label="Completed"/>
+</enum>
+
 <enum name="PasswordStoreChange">
   <int value="0" label="Add - If the PasswordForm login was added."/>
   <int value="1" label="Update - If the PasswordForm login was updated."/>
diff --git a/tools/metrics/histograms/metadata/accessibility/histograms.xml b/tools/metrics/histograms/metadata/accessibility/histograms.xml
index c395de0b..dca0fea 100644
--- a/tools/metrics/histograms/metadata/accessibility/histograms.xml
+++ b/tools/metrics/histograms/metadata/accessibility/histograms.xml
@@ -190,7 +190,7 @@
 </histogram>
 
 <histogram name="Accessibility.Android.OnDemand.OneHundredPercentEventsDropped"
-    units="count" expires_after="2022-12-25">
+    units="count" expires_after="2023-01-01">
   <owner>mschillaci@google.com</owner>
   <owner>abigailbklein@google.com</owner>
   <summary>
@@ -221,7 +221,7 @@
 </histogram>
 
 <histogram name="Accessibility.Android.OnDemand.PercentageDropped" units="%"
-    expires_after="2022-12-25">
+    expires_after="2023-01-01">
   <owner>mschillaci@google.com</owner>
   <owner>abigailbklein@google.com</owner>
   <summary>
@@ -279,7 +279,7 @@
 </histogram>
 
 <histogram name="Accessibility.Android.UserFontSizePref.Change" units="%"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>twellington@chromium.org</owner>
   <owner>skym@chromium.org</owner>
   <summary>
@@ -290,7 +290,7 @@
 </histogram>
 
 <histogram name="Accessibility.Android.UserFontSizePref.OnStartup" units="%"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>twellington@chromium.org</owner>
   <owner>skym@chromium.org</owner>
   <summary>
@@ -1284,7 +1284,7 @@
 </histogram>
 
 <histogram name="Accessibility.ManuallyEnabled" enum="BooleanEnabled"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>aleventhal@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>chrome-a11y-core@google.com</owner>
@@ -1348,7 +1348,7 @@
 </histogram>
 
 <histogram name="Accessibility.Performance.ProcessDeferredAccessibilityEvents"
-    units="ms" expires_after="2022-10-30">
+    units="ms" expires_after="2023-01-01">
   <owner>aleventhal@chromium.org</owner>
   <owner>janewman@microsoft.com</owner>
   <owner>chrome-a11y-core@google.com</owner>
@@ -1360,7 +1360,7 @@
 </histogram>
 
 <histogram name="Accessibility.Performance.SendPendingAccessibilityEvents"
-    units="ms" expires_after="2022-10-30">
+    units="ms" expires_after="2023-01-01">
   <owner>aleventhal@chromium.org</owner>
   <owner>janewman@microsoft.com</owner>
   <owner>chrome-a11y-core@google.com</owner>
@@ -1767,7 +1767,7 @@
 </histogram>
 
 <histogram name="DomDistiller.ReaderShownForPageLoad" enum="Boolean"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>mdjones@chromium.org</owner>
   <summary>
     Records if the panel became visible at any point after a page was navigated.
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml
index df3be15..bfdd792 100644
--- a/tools/metrics/histograms/metadata/android/histograms.xml
+++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -353,7 +353,7 @@
 </histogram>
 
 <histogram name="Android.AutofillAssistant.DependenciesInvalidated"
-    enum="AutofillAssistantDependenciesInvalidated" expires_after="2022-10-27">
+    enum="AutofillAssistantDependenciesInvalidated" expires_after="2023-01-01">
   <owner>fga@google.com</owner>
   <owner>autofill_assistant+watch@google.com</owner>
   <summary>
@@ -669,7 +669,7 @@
 </histogram>
 
 <histogram name="Android.BackgroundTaskScheduler.TaskScheduled.Failure"
-    enum="BackgroundTaskId" expires_after="2022-10-30">
+    enum="BackgroundTaskId" expires_after="2023-01-01">
   <owner>fgorski@chromium.org</owner>
   <owner>nyquist@chromium.org</owner>
   <summary>
@@ -678,7 +678,7 @@
 </histogram>
 
 <histogram name="Android.BackgroundTaskScheduler.TaskScheduled.Success"
-    enum="BackgroundTaskId" expires_after="2022-10-30">
+    enum="BackgroundTaskId" expires_after="2023-01-01">
   <owner>fgorski@chromium.org</owner>
   <owner>nyquist@chromium.org</owner>
   <summary>
@@ -1259,7 +1259,7 @@
 </histogram>
 
 <histogram name="Android.DownloadManager.NotificationInteraction"
-    enum="DownloadNotificationInteractions" expires_after="2022-10-30">
+    enum="DownloadNotificationInteractions" expires_after="2023-01-01">
   <owner>qinmin@chromium.org</owner>
   <owner>clank-downloads@google.com</owner>
   <summary>
@@ -1269,7 +1269,7 @@
 </histogram>
 
 <histogram name="Android.DownloadManager.OpenSource.Audio"
-    enum="AndroidDownloadOpenSource" expires_after="2022-10-30">
+    enum="AndroidDownloadOpenSource" expires_after="2023-01-01">
   <owner>shaktisahu@chromium.org</owner>
   <owner>clank-downloads@google.com</owner>
   <summary>Records how users open audio download files on Android.</summary>
@@ -1674,7 +1674,7 @@
 </histogram>
 
 <histogram name="Android.FontLookup.FetchFontResult" enum="FetchFontResult"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>twellington@chromium.org</owner>
   <owner>clank-app-team@google.com</owner>
   <summary>
@@ -1686,7 +1686,7 @@
 </histogram>
 
 <histogram name="Android.FontLookup.GmsFontRequest.Time" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>twellington@chromium.org</owner>
   <owner>clank-app-team@google.com</owner>
   <summary>
@@ -2437,7 +2437,7 @@
 </histogram>
 
 <histogram name="Android.NTP.Impression" enum="NTPImpressionType"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>finkm@chromium.org</owner>
   <summary>
     Counts impressions of the NTP on Android. It also counts potential
@@ -2779,7 +2779,7 @@
 </histogram>
 
 <histogram name="Android.PackageStats.CacheSize" units="MB"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>nyquist@chromium.org</owner>
   <owner>yfriedman@chromium.org</owner>
   <summary>
@@ -2788,7 +2788,7 @@
 </histogram>
 
 <histogram name="Android.PackageStats.CodeSize" units="MB"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>nyquist@chromium.org</owner>
   <owner>yfriedman@chromium.org</owner>
   <summary>
@@ -2799,7 +2799,7 @@
 </histogram>
 
 <histogram name="Android.PackageStats.DataSize" units="MB"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>nyquist@chromium.org</owner>
   <owner>yfriedman@chromium.org</owner>
   <summary>
@@ -3243,7 +3243,7 @@
 </histogram>
 
 <histogram name="Android.StrictMode.OverrideUrlLoadingTime" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>yfriedman@chromium.org</owner>
   <owner>wnwen@chromium.org</owner>
   <summary>
@@ -3566,7 +3566,7 @@
 </histogram>
 
 <histogram name="Android.View.onDraw.30Seconds" units="count"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>nuskos@chromium.org</owner>
   <owner>chrometto-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/apps/histograms.xml b/tools/metrics/histograms/metadata/apps/histograms.xml
index da64dc90..3d2220d 100644
--- a/tools/metrics/histograms/metadata/apps/histograms.xml
+++ b/tools/metrics/histograms/metadata/apps/histograms.xml
@@ -2605,7 +2605,7 @@
 </histogram>
 
 <histogram name="Apps.PreferredApps.EntryCount" units="entries"
-    expires_after="2022-11-01">
+    expires_after="2023-01-01">
   <owner>mxcai@chromium.org</owner>
   <owner>chromeos-apps-foundation-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml
index 484a519..94a9f6f 100644
--- a/tools/metrics/histograms/metadata/ash/histograms.xml
+++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -2179,7 +2179,7 @@
 </histogram>
 
 <histogram name="Ash.DeviceActiveClient.StateCount"
-    enum="DeviceActiveClientState" expires_after="2022-11-01">
+    enum="DeviceActiveClientState" expires_after="2023-01-01">
   <owner>hirthanan@google.com</owner>
   <owner>chromeos-data-team@google.com</owner>
   <summary>
@@ -2976,7 +2976,7 @@
 </histogram>
 
 <histogram name="Ash.NotificationPopup.AnimationSmoothness" units="%"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>leandre@chromium.org</owner>
   <owner>amehfooz@chromium.org</owner>
   <owner>tbarzic@chromium.org</owner>
@@ -4201,13 +4201,14 @@
 </histogram>
 
 <histogram name="Ash.StateKeysPresent" enum="BooleanPresent"
-    expires_after="2022-07-03">
+    expires_after="2023-06-01">
   <owner>igorcov@chromium.org</owner>
   <owner>vsavu@google.com</owner>
   <summary>
     The presense of state keys on first device policy fetch response. It is
     expected for state keys to be present. The histogram is logged only in case
-    of successful device policy fetch response.
+    of successful device policy fetch response. Warning: This histogram was
+    expired from 2022-07-03 to 2022-07-05; data may be missing.
   </summary>
 </histogram>
 
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml
index 3e8e6ff..07b487b6 100644
--- a/tools/metrics/histograms/metadata/autofill/histograms.xml
+++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -1406,7 +1406,7 @@
 </histogram>
 
 <histogram name="Autofill.FormForest.GetBrowserFormOfRendererForm.Duration"
-    units="microseconds" expires_after="2022-10-31">
+    units="microseconds" expires_after="2023-01-01">
   <owner>schwering@google.com</owner>
   <owner>chrome-autofill-alerts@google.com</owner>
   <summary>
@@ -1420,7 +1420,7 @@
 </histogram>
 
 <histogram name="Autofill.FormForest.GetRendererFormsOfBrowserForm.Duration"
-    units="microseconds" expires_after="2022-10-31">
+    units="microseconds" expires_after="2023-01-01">
   <owner>schwering@google.com</owner>
   <owner>chrome-autofill-alerts@google.com</owner>
   <summary>
@@ -1434,7 +1434,7 @@
 </histogram>
 
 <histogram name="Autofill.FormForest.UpdateTreeOfRendererForm.Duration"
-    units="microseconds" expires_after="2022-10-31">
+    units="microseconds" expires_after="2023-01-01">
   <owner>schwering@google.com</owner>
   <owner>chrome-autofill-alerts@google.com</owner>
   <summary>
@@ -1446,7 +1446,7 @@
 </histogram>
 
 <histogram name="Autofill.FormForest.UpdateTreeOfRendererForm.Visits"
-    units="node-visits" expires_after="2022-10-31">
+    units="node-visits" expires_after="2023-01-01">
   <owner>schwering@google.com</owner>
   <owner>chrome-autofill-alerts@google.com</owner>
   <summary>
@@ -1611,7 +1611,7 @@
 </histogram>
 
 <histogram name="Autofill.Iframes.NumberOfFramesWithAutofilledCreditCardFields"
-    units="frames" expires_after="2022-10-31">
+    units="frames" expires_after="2023-01-01">
   <owner>schwering@google.com</owner>
   <owner>chrome-autofill-alerts@google.com</owner>
   <summary>
@@ -1627,7 +1627,7 @@
 </histogram>
 
 <histogram name="Autofill.Iframes.NumberOfFramesWithDetectedCreditCardFields"
-    units="frames" expires_after="2022-10-31">
+    units="frames" expires_after="2023-01-01">
   <owner>schwering@google.com</owner>
   <owner>chrome-autofill-alerts@google.com</owner>
   <summary>
@@ -1643,7 +1643,7 @@
 </histogram>
 
 <histogram name="Autofill.Iframes.NumberOfFramesWithDetectedFields"
-    units="frames" expires_after="2022-10-31">
+    units="frames" expires_after="2023-01-01">
   <owner>schwering@google.com</owner>
   <owner>chrome-autofill-alerts@google.com</owner>
   <summary>
@@ -2382,7 +2382,7 @@
 </histogram>
 
 <histogram name="Autofill.PopupHidingReason" enum="AutofillPopupHidingReason"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>mamir@google.com</owner>
   <owner>koerber@google.com</owner>
   <summary>
@@ -3149,7 +3149,7 @@
 
 <histogram
     name="Autofill.StrikeDatabase.CreditCardSaveNotOfferedDueToMaxStrikes"
-    enum="AutofillSaveType" expires_after="2022-10-31">
+    enum="AutofillSaveType" expires_after="2023-01-01">
   <owner>jsaul@google.com</owner>
   <owner>payments-autofill-team@google.com</owner>
   <summary>
@@ -3161,7 +3161,7 @@
 
 <histogram
     name="Autofill.StrikeDatabase.LocalCardMigrationNotOfferedDueToMaxStrikes"
-    enum="AutofillSaveType" expires_after="2022-10-31">
+    enum="AutofillSaveType" expires_after="2023-01-01">
   <owner>jsaul@google.com</owner>
   <owner>payments-autofill-team@google.com</owner>
   <summary>
@@ -3207,7 +3207,7 @@
 </histogram>
 
 <histogram name="Autofill.StrikeDatabase.StrikesPresentWhenLocalCardSaved"
-    units="strikes" expires_after="2022-10-31">
+    units="strikes" expires_after="2023-01-01">
   <owner>jsaul@google.com</owner>
   <owner>payments-autofill-team@google.com</owner>
   <summary>
@@ -3217,7 +3217,7 @@
 </histogram>
 
 <histogram name="Autofill.StrikeDatabase.StrikesPresentWhenServerCardSaved"
-    units="strikes" expires_after="2022-10-31">
+    units="strikes" expires_after="2023-01-01">
   <owner>jsaul@google.com</owner>
   <owner>payments-autofill-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml
index 140fb6f7..c59626661 100644
--- a/tools/metrics/histograms/metadata/blink/histograms.xml
+++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -37,7 +37,7 @@
 </variants>
 
 <histogram name="Blink.Accessibility.NumTreeUpdatesQueuedBeforeLayout"
-    units="updates" expires_after="2022-10-30">
+    units="updates" expires_after="2023-01-01">
   <owner>aleventhal@chromium.org</owner>
   <owner>chrome-a11y-core@chromium.org</owner>
   <summary>
@@ -743,7 +743,7 @@
 </histogram>
 
 <histogram name="Blink.DecodedImage.WebPFileFormat" enum="WebPFileFormat"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>mcasas@chromium.org</owner>
   <owner>andrescj@chromium.org</owner>
   <summary>
@@ -753,7 +753,7 @@
 </histogram>
 
 <histogram name="Blink.DecodedImageType" enum="DecodedImageType"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>urvang@chromium.org</owner>
   <summary>
     Image codec inferred during decode. The histogram is incremented when enough
@@ -1475,7 +1475,7 @@
 </histogram>
 
 <histogram name="Blink.ImageDecoders.ImageHasMultipleGeneratorClientIds"
-    enum="ImageHasMultipleGeneratorClientIds" expires_after="2022-09-30">
+    enum="ImageHasMultipleGeneratorClientIds" expires_after="2023-01-01">
   <owner>vmpstr@chromium.org</owner>
   <owner>khushalsagar@chromium.org</owner>
   <summary>
@@ -1694,7 +1694,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.JavascriptDocumentUpdate.UpdateTime"
-    units="microseconds" expires_after="2022-10-30">
+    units="microseconds" expires_after="2023-01-01">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
 
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" -->
@@ -1861,7 +1861,7 @@
 </histogram>
 
 <histogram name="Blink.Loading.CachedResponseArrivalAtRenderer"
-    units="Milliseconds" expires_after="2022-11-01">
+    units="Milliseconds" expires_after="2023-01-01">
   <owner>yhirano@chromium.org</owner>
   <owner>loadingg-dev@chromium.org</owner>
   <summary>
@@ -1872,7 +1872,7 @@
 </histogram>
 
 <histogram name="Blink.Loading.CodeCacheArrivalAtRenderer" units="Milliseconds"
-    expires_after="2022-11-01">
+    expires_after="2023-01-01">
   <owner>yhirano@chromium.org</owner>
   <owner>loading-dev@chromium.org</owner>
   <summary>
@@ -2176,7 +2176,7 @@
 </histogram>
 
 <histogram name="Blink.ResourceRequest.StartDelay" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>cduvall@chromium.org</owner>
   <owner>jam@chromium.org</owner>
   <summary>
@@ -2325,7 +2325,7 @@
 </histogram>
 
 <histogram name="Blink.Sms.BackendAvailability"
-    enum="WebOTPBackendAvailability" expires_after="2022-10-30">
+    enum="WebOTPBackendAvailability" expires_after="2023-01-01">
   <owner>yigu@chromium.org</owner>
   <owner>fedcm-core@google.com</owner>
   <summary>
@@ -2346,7 +2346,7 @@
 </histogram>
 
 <histogram name="Blink.Sms.Receive.CrossDeviceFailure"
-    enum="WebOTPCrossDeviceFailure" expires_after="2022-10-30">
+    enum="WebOTPCrossDeviceFailure" expires_after="2023-01-01">
   <owner>yigu@chromium.org</owner>
   <owner>fedcm-core@google.com</owner>
   <summary>
@@ -2367,7 +2367,7 @@
 </histogram>
 
 <histogram name="Blink.Sms.Receive.Outcome" enum="WebOTPServiceOutcome"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>yigu@chromium.org</owner>
   <owner>goto@chromium.org</owner>
   <owner>fedcm-core@google.com</owner>
@@ -2442,7 +2442,7 @@
 </histogram>
 
 <histogram name="Blink.Sms.Receive.TimeSuccess" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>yigu@chromium.org</owner>
   <owner>goto@chromium.org</owner>
   <owner>fedcm-core@google.com</owner>
@@ -2466,7 +2466,7 @@
 </histogram>
 
 <histogram name="Blink.Sms.WebContentsVisibleOnReceive" enum="Boolean"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>yigu@chromium.org</owner>
   <owner>fedcm-core@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/bookmarks/histograms.xml b/tools/metrics/histograms/metadata/bookmarks/histograms.xml
index a6716e9..e482d27 100644
--- a/tools/metrics/histograms/metadata/bookmarks/histograms.xml
+++ b/tools/metrics/histograms/metadata/bookmarks/histograms.xml
@@ -59,7 +59,7 @@
 </histogram>
 
 <histogram name="BookmarkManager.ResultsRenderedTime" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>johntlee@chromium.org</owner>
   <owner>dbeam@chromium.org</owner>
   <summary>
@@ -83,7 +83,7 @@
 </histogram>
 
 <histogram name="Bookmarks.BookmarkAllTabsWithTabsCount.Incognito" units="tabs"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>roagarwal@chromium.org</owner>
   <owner>sideyilmaz@chromium.org</owner>
   <owner>chrome-incognito@google.com</owner>
@@ -650,7 +650,7 @@
 </histogram>
 
 <histogram name="Bookmarks.ReadingList.NumberOfUnreadItems" units="items"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>shaktisahu@chromium.org</owner>
   <component>UI&gt;Browser&gt;Bookmarks</component>
   <component>UI&gt;Browser&gt;Mobile&gt;ReadingList</component>
diff --git a/tools/metrics/histograms/metadata/browser/histograms.xml b/tools/metrics/histograms/metadata/browser/histograms.xml
index 58dbd85d..d2aef7c 100644
--- a/tools/metrics/histograms/metadata/browser/histograms.xml
+++ b/tools/metrics/histograms/metadata/browser/histograms.xml
@@ -110,7 +110,7 @@
 </histogram>
 
 <histogram name="Browser.DarkModeStatus" enum="DarkModeStatus"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>lgrey@chromium.org</owner>
   <owner>robliao@chromium.org</owner>
   <summary>
@@ -487,7 +487,7 @@
 </histogram>
 
 <histogram name="Browser.Tabs.SelectionToVisibilityRequestTime"
-    units="microseconds" expires_after="2022-10-30">
+    units="microseconds" expires_after="2023-01-01">
   <owner>sadrul@chromium.org</owner>
   <owner>sky@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/commerce/histograms.xml b/tools/metrics/histograms/metadata/commerce/histograms.xml
index 71bec267..e9aec49 100644
--- a/tools/metrics/histograms/metadata/commerce/histograms.xml
+++ b/tools/metrics/histograms/metadata/commerce/histograms.xml
@@ -192,7 +192,7 @@
 </histogram>
 
 <histogram name="Commerce.PowerBookmarks.ShoppingDataProvider.IsProductPage"
-    enum="Boolean" expires_after="2022-10-30">
+    enum="Boolean" expires_after="2023-01-01">
   <owner>ayman@chromium.org</owner>
   <owner>mdjones@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/compositing/histograms.xml b/tools/metrics/histograms/metadata/compositing/histograms.xml
index ae8ee14a..280384d 100644
--- a/tools/metrics/histograms/metadata/compositing/histograms.xml
+++ b/tools/metrics/histograms/metadata/compositing/histograms.xml
@@ -672,7 +672,7 @@
 </histogram>
 
 <histogram name="Compositing.Renderer.NumRenderSurfaces" units="surfaces"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/content/histograms.xml b/tools/metrics/histograms/metadata/content/histograms.xml
index ce5d071..c045a0f 100644
--- a/tools/metrics/histograms/metadata/content/histograms.xml
+++ b/tools/metrics/histograms/metadata/content/histograms.xml
@@ -585,7 +585,7 @@
 </histogram>
 
 <histogram name="ContentSettings.Popups.StrongBlockerActions"
-    enum="StrongPopupBlockerAction" expires_after="2022-10-30">
+    enum="StrongPopupBlockerAction" expires_after="2023-01-01">
   <owner>csharrison@chromium.org</owner>
   <summary>
     Counts of various events related to the strong popup blocker (aka abusive
diff --git a/tools/metrics/histograms/metadata/content_creation/histograms.xml b/tools/metrics/histograms/metadata/content_creation/histograms.xml
index f01a835..719c906b 100644
--- a/tools/metrics/histograms/metadata/content_creation/histograms.xml
+++ b/tools/metrics/histograms/metadata/content_creation/histograms.xml
@@ -343,7 +343,7 @@
 </histogram>
 
 <histogram name="SharedHighlights.AsyncTask.Iterations" units="iterations"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>jeffreycohen@chromium.org</owner>
   <owner>chrome-shared-highlighting@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/cookie/histograms.xml b/tools/metrics/histograms/metadata/cookie/histograms.xml
index 324f0b2..75b2a2f2 100644
--- a/tools/metrics/histograms/metadata/cookie/histograms.xml
+++ b/tools/metrics/histograms/metadata/cookie/histograms.xml
@@ -32,7 +32,7 @@
 </histogram>
 
 <histogram name="Cookie.ClockSkew.ExpiredWithoutSkew" enum="Boolean"
-    expires_after="2022-11-01">
+    expires_after="2023-01-01">
   <owner>kyraseevers@chromium.org</owner>
   <owner>bingler@chromium.org</owner>
   <summary>
@@ -388,7 +388,7 @@
 </histogram>
 
 <histogram name="Cookie.IncludedRequestEffectiveSameSite"
-    enum="CookieEffectiveSameSite" expires_after="2022-10-30">
+    enum="CookieEffectiveSameSite" expires_after="2023-01-01">
   <owner>bingler@chromium.org</owner>
   <owner>miketaylr@chromium.org</owner>
   <summary>
@@ -442,7 +442,7 @@
 </histogram>
 
 <histogram name="Cookie.LoadProblem" enum="CookieLoadProblem"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>morlovich@chromium.org</owner>
   <summary>
     Recorded when a problem is recorded when loading the persistent cookie
@@ -768,7 +768,7 @@
 </histogram>
 
 <histogram name="Cookie.SameSiteAttributeValue" enum="CookieSameSiteString"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>bingler@chromium.org</owner>
   <owner>miketaylr@chromium.org</owner>
   <summary>
@@ -794,7 +794,7 @@
 </histogram>
 
 <histogram name="Cookie.TimeBlockedOnLoad" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>nharper@chromium.org</owner>
   <summary>
     The amount of time (ms) between the cookie store load starting and
@@ -888,7 +888,7 @@
   </summary>
 </histogram>
 
-<histogram name="Cookie.Type" enum="CookieType" expires_after="2022-10-30">
+<histogram name="Cookie.Type" enum="CookieType" expires_after="2023-01-01">
   <owner>mkwst@chromium.org</owner>
   <summary>For each cookie added to the store, record it's type(s).</summary>
 </histogram>
diff --git a/tools/metrics/histograms/metadata/data/histograms.xml b/tools/metrics/histograms/metadata/data/histograms.xml
index 5c817ed38..f47e2ffa 100644
--- a/tools/metrics/histograms/metadata/data/histograms.xml
+++ b/tools/metrics/histograms/metadata/data/histograms.xml
@@ -170,7 +170,7 @@
   </summary>
 </histogram>
 
-<histogram name="DataUse.AppTabState" units="bytes" expires_after="2022-10-30">
+<histogram name="DataUse.AppTabState" units="bytes" expires_after="2023-01-01">
   <owner>rajendrant@chromium.org</owner>
   <owner>mcrouse@chromium.org</owner>
   <summary>
@@ -252,7 +252,7 @@
 </histogram>
 
 <histogram name="DataUse.ContentType.UserTrafficKB" enum="DataUseContentType"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>rajendrant@chromium.org</owner>
   <owner>mcrouse@chromium.org</owner>
   <summary>
@@ -293,7 +293,7 @@
 </histogram>
 
 <histogram name="DataUse.TrafficSize.User" units="bytes"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>rajendrant@chromium.org</owner>
   <owner>mcrouse@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/enterprise/histograms.xml b/tools/metrics/histograms/metadata/enterprise/histograms.xml
index 327c7524..92ec486 100644
--- a/tools/metrics/histograms/metadata/enterprise/histograms.xml
+++ b/tools/metrics/histograms/metadata/enterprise/histograms.xml
@@ -453,7 +453,7 @@
 </histogram>
 
 <histogram name="Enterprise.CloudReportingRequestCount" units="requests"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>zmin@chromium.org</owner>
   <owner>pastarmovj@chromium.org</owner>
   <summary>
@@ -463,7 +463,7 @@
 </histogram>
 
 <histogram name="Enterprise.CloudReportingRequestSize" units="KB"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>zmin@chromium.org</owner>
   <owner>pastarmovj@chromium.org</owner>
   <summary>
@@ -1840,7 +1840,7 @@
 </histogram>
 
 <histogram name="Enterprise.OnBulkDataEntry.DataSize" units="bytes"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>domfc@chromium.org</owner>
   <owner>webprotect-team@google.com</owner>
   <summary>
@@ -1857,7 +1857,7 @@
 </histogram>
 
 <histogram name="Enterprise.Policies" enum="EnterprisePolicies"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>mnissler@chromium.org</owner>
   <summary>
     A set of enterprise policy rules that are in use. This is recorded every 24
@@ -2096,7 +2096,7 @@
 </histogram>
 
 <histogram name="Enterprise.UserPolicyChromeOS.ChildUser.OAuthTokenError"
-    enum="GoogleServiceAuthError" expires_after="2022-10-30">
+    enum="GoogleServiceAuthError" expires_after="2023-01-01">
   <owner>agawronska@chromium.org</owner>
   <owner>michaelpg@chromium.org</owner>
   <summary>Failure reason for OAuth token fetch for child user.</summary>
diff --git a/tools/metrics/histograms/metadata/event/histograms.xml b/tools/metrics/histograms/metadata/event/histograms.xml
index c834d37d..fc71f45 100644
--- a/tools/metrics/histograms/metadata/event/histograms.xml
+++ b/tools/metrics/histograms/metadata/event/histograms.xml
@@ -403,7 +403,7 @@
 
 <histogram
     name="Event.Latency.ScrollBegin.Scrollbar.BrowserNotifiedToBeforeGpuSwap2"
-    units="microseconds" expires_after="2022-10-30">
+    units="microseconds" expires_after="2023-01-01">
   <owner>flackr@chromium.org</owner>
   <owner>gerchiko@microsoft.com</owner>
   <owner>input-dev@chromium.org</owner>
@@ -512,7 +512,7 @@
 
 <histogram
     name="Event.Latency.ScrollBegin.Scrollbar.TimeToScrollUpdateSwapBegin4"
-    units="microseconds" expires_after="2022-10-30">
+    units="microseconds" expires_after="2023-01-01">
   <owner>nzolghadr@chromium.org</owner>
   <owner>gerchiko@microsoft.com</owner>
   <owner>input-dev@chromium.org</owner>
@@ -1110,7 +1110,7 @@
 </histogram>
 
 <histogram name="Event.Latency.ScrollUpdate.TimeToScrollUpdateSwapBegin2"
-    units="microseconds" expires_after="2022-10-30">
+    units="microseconds" expires_after="2023-01-01">
   <owner>nzolghadr@chromium.org</owner>
   <summary>
     Time between initial creation of a wheel/touch event and start of the frame
diff --git a/tools/metrics/histograms/metadata/extensions/histograms.xml b/tools/metrics/histograms/metadata/extensions/histograms.xml
index 1a9b87fd..5995b9c 100644
--- a/tools/metrics/histograms/metadata/extensions/histograms.xml
+++ b/tools/metrics/histograms/metadata/extensions/histograms.xml
@@ -223,7 +223,7 @@
 </histogram>
 
 <histogram name="Extensions.BackgroundHostCreatedForExtension"
-    enum="BackgroundHostCreatedForExtensionValues" expires_after="2022-10-30">
+    enum="BackgroundHostCreatedForExtensionValues" expires_after="2023-01-01">
   <owner>fdoray@chromium.org</owner>
   <owner>catan-team@chromium.org</owner>
   <summary>
@@ -326,7 +326,7 @@
 </histogram>
 
 <histogram name="Extensions.BookmarkAppLaunchSource" enum="AppLaunchSource"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>phillis@chromium.org</owner>
   <owner>benwells@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
@@ -2535,7 +2535,7 @@
   <summary>The number of platform apps loaded at profile open.</summary>
 </histogram>
 
-<histogram name="Extensions.LoadTheme" units="units" expires_after="2022-10-30">
+<histogram name="Extensions.LoadTheme" units="units" expires_after="2023-01-01">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>The number of themes loaded at profile open.</summary>
@@ -2561,7 +2561,7 @@
 </histogram>
 
 <histogram name="Extensions.Management_Refresh" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>jam@chromium.org</owner>
   <owner>cduvall@chromium.org</owner>
   <summary>
@@ -3161,7 +3161,7 @@
 
 <histogram
     name="Extensions.SettingsOverridden.BackToOtherSearchOverriddenDialogResult"
-    enum="SettingsOverriddenDialogResult" expires_after="2022-10-30">
+    enum="SettingsOverriddenDialogResult" expires_after="2023-01-01">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/gpu/histograms.xml b/tools/metrics/histograms/metadata/gpu/histograms.xml
index 92091153..3361184e 100644
--- a/tools/metrics/histograms/metadata/gpu/histograms.xml
+++ b/tools/metrics/histograms/metadata/gpu/histograms.xml
@@ -292,7 +292,7 @@
 </histogram>
 
 <histogram name="GPU.ANGLE.D3D11CreateDeviceError" enum="Hresult"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>jonahr@google.com</owner>
   <owner>angle-team@google.com</owner>
   <summary>
@@ -455,7 +455,7 @@
 </histogram>
 
 <histogram name="GPU.BlocklistFeatureTestResults"
-    enum="GPUBlocklistFeatureTestResults" expires_after="2022-10-30">
+    enum="GPUBlocklistFeatureTestResults" expires_after="2023-01-01">
   <owner>vmiura@chromium.org</owner>
   <owner>graphics-dev@chromium.org</owner>
   <summary>
@@ -475,7 +475,7 @@
 </histogram>
 
 <histogram name="GPU.CanvasOopRaster.OopRasterAndGpuAcceleration"
-    enum="CanvasOopRasterAndGpuAcceleration" expires_after="2022-11-01">
+    enum="CanvasOopRasterAndGpuAcceleration" expires_after="2023-01-01">
   <owner>vasilyt@chromium.org</owner>
   <owner>nazabris@microsoft.com</owner>
   <owner>jochin@microsoft.com</owner>
@@ -609,7 +609,7 @@
 </histogram>
 
 <histogram name="GPU.DirectComposition.DCLayer.YUVOverlayCount"
-    units="overlays" expires_after="2022-10-30">
+    units="overlays" expires_after="2023-01-01">
   <owner>magchen@chromium.org</owner>
   <owner>zmo@chromium.org</owner>
   <summary>
@@ -934,7 +934,7 @@
 </histogram>
 
 <histogram name="GPU.GLImplementation" enum="GLImplementation"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>magchen@chromium.org</owner>
   <owner>zmo@chromium.org</owner>
   <summary>
@@ -964,7 +964,7 @@
 </histogram>
 
 <histogram name="GPU.GPUProcessExitCode" enum="GPUProcessExitCode"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>zmo@chromium.org</owner>
   <owner>graphics-dev@chromium.org</owner>
   <summary>
@@ -982,7 +982,7 @@
 </histogram>
 
 <histogram name="GPU.GPUProcessLaunchTime" units="ms"
-    expires_after="2022-10-16">
+    expires_after="2023-01-01">
   <owner>vmiura@chromium.org</owner>
   <summary>
     Startup time of the GPU process as measured by the GPU process host.
@@ -1003,7 +1003,7 @@
 </histogram>
 
 <histogram name="GPU.GPUProcessTerminationStatus2" enum="GpuTerminationStatus"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>vmiura@chromium.org</owner>
   <summary>
     Counts for each time the GPU Process Host detects the process dies.
@@ -1182,7 +1182,7 @@
 </histogram>
 
 <histogram name="GPU.MultiGpu.AMD" enum="AMDDeviceId"
-    expires_after="2022-10-09">
+    expires_after="2023-01-01">
   <owner>zmo@chromium.org</owner>
   <owner>graphics-dev@chromium.org</owner>
   <summary>
@@ -1502,7 +1502,7 @@
 </histogram>
 
 <histogram name="GPU.SoftwareRendering" enum="BooleanSoftwareRendering"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>sadrul@chromium.org</owner>
   <owner>zmo@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml
index ee7e6c9..0f37433 100644
--- a/tools/metrics/histograms/metadata/history/histograms.xml
+++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -1663,7 +1663,7 @@
   </summary>
 </histogram>
 
-<histogram name="History.URLTableCount" units="URLs" expires_after="2022-10-30">
+<histogram name="History.URLTableCount" units="URLs" expires_after="2023-01-01">
   <owner>mpearson@chromium.org</owner>
   <owner>sky@chromium.org</owner>
   <component>UI&gt;Browser&gt;History</component>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml
index d66ac087..9f4de4d 100644
--- a/tools/metrics/histograms/metadata/media/histograms.xml
+++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -459,7 +459,7 @@
 </histogram>
 
 <histogram name="Media.Audio.Capture.Win.InitError" enum="Hresult"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>tommi@chromium.org</owner>
   <owner>guidou@chromium.org</owner>
   <owner>olka@chromium.org</owner>
@@ -1332,7 +1332,7 @@
 </histogram>
 
 <histogram name="Media.AudioCapturerDroppedData" units="%"
-    expires_after="2022-12-25">
+    expires_after="2023-01-01">
   <owner>olka@chromium.org</owner>
   <owner>gustaf@chromium.org</owner>
   <summary>
@@ -1359,7 +1359,7 @@
 </histogram>
 
 <histogram name="Media.AudioCapturerMissedReadDeadline" units="%"
-    expires_after="2022-12-25">
+    expires_after="2023-01-01">
   <owner>olka@chromium.org</owner>
   <owner>gustaf@chromium.org</owner>
   <summary>
@@ -1597,7 +1597,7 @@
 </histogram>
 
 <histogram name="Media.AudioRendererAudioGlitches" enum="AudioGlitchResult"
-    expires_after="2022-12-25">
+    expires_after="2023-01-01">
   <owner>henrika@chromium.org</owner>
   <owner>olka@chromium.org</owner>
   <summary>
@@ -1640,7 +1640,7 @@
 </histogram>
 
 <histogram name="Media.AudioRendererMissedDeadline" units="%"
-    expires_after="2022-12-25">
+    expires_after="2023-01-01">
   <owner>dalecurtis@chromium.org</owner>
   <owner>olka@chromium.org</owner>
   <summary>
@@ -1833,7 +1833,7 @@
 </histogram>
 
 <histogram name="Media.ConditionalFocus.Decision"
-    enum="ConditionalFocusDecision" expires_after="2022-10-30">
+    enum="ConditionalFocusDecision" expires_after="2023-01-01">
   <owner>eladalon@chromium.org</owner>
   <owner>toprice@chromium.org</owner>
   <summary>
@@ -1879,7 +1879,7 @@
 </histogram>
 
 <histogram base="true" name="Media.ConfigChangeDecoderSelectionTime" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>cassew@google.com</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -2708,7 +2708,7 @@
 </histogram>
 
 <histogram name="Media.GlobalMediaControls.DismissReason"
-    enum="GlobalMediaControlsDismissReason" expires_after="2022-10-30">
+    enum="GlobalMediaControlsDismissReason" expires_after="2023-01-01">
   <owner>steimel@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -2765,7 +2765,7 @@
 </histogram>
 
 <histogram name="Media.GlobalMediaControls.RepeatUsage" enum="BooleanIsRepeat"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>steimel@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -3265,7 +3265,7 @@
 </histogram>
 
 <histogram name="Media.MediaFoundationRenderer.PlaybackError" enum="Hresult"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>xhwang@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -3330,7 +3330,7 @@
 </histogram>
 
 <histogram name="Media.MicrophoneMuted" enum="MicrophoneMuteResult"
-    expires_after="2022-10-31">
+    expires_after="2023-01-01">
   <owner>henrika@chromium.org</owner>
   <owner>webrtc-audio@google.com</owner>
   <summary>
@@ -3684,7 +3684,7 @@
 </histogram>
 
 <histogram name="Media.Notification.Source" enum="MediaNotificationSource"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>beccahughes@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -4909,7 +4909,7 @@
 </histogram>
 
 <histogram name="Media.VideoCapture.Mac.Device.RequestedPixelFormat"
-    enum="VideoPixelFormatUnion" expires_after="2022-10-30">
+    enum="VideoPixelFormatUnion" expires_after="2023-01-01">
   <owner>eshr@google.com</owner>
   <owner>handellm@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/memory/histograms.xml b/tools/metrics/histograms/metadata/memory/histograms.xml
index 701e60da..e86d5b9 100644
--- a/tools/metrics/histograms/metadata/memory/histograms.xml
+++ b/tools/metrics/histograms/metadata/memory/histograms.xml
@@ -501,7 +501,7 @@
 </histogram>
 
 <histogram name="Memory.Discardable.FreelistSize.Foreground" units="KiB"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>thiabaud@google.com</owner>
   <owner>lizeb@chromium.org</owner>
   <summary>
@@ -521,7 +521,7 @@
 </histogram>
 
 <histogram name="Memory.Discardable.LockingSuccess"
-    enum="BooleanLockingSuccess" expires_after="2022-10-30">
+    enum="BooleanLockingSuccess" expires_after="2023-01-01">
   <owner>thiabaud@google.com</owner>
   <owner>lizeb@chromium.org</owner>
   <summary>
@@ -531,7 +531,7 @@
 </histogram>
 
 <histogram name="Memory.Discardable.Size.Foreground" units="KiB"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>thiabaud@google.com</owner>
   <owner>lizeb@chromium.org</owner>
   <summary>
@@ -2776,7 +2776,7 @@
 </histogram>
 
 <histogram name="Memory.Total.SystemCommitLimit" units="GB"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>sadrul@chromium.org</owner>
   <owner>zmo@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/mobile/histograms.xml b/tools/metrics/histograms/metadata/mobile/histograms.xml
index 826b9251..55ad3ce 100644
--- a/tools/metrics/histograms/metadata/mobile/histograms.xml
+++ b/tools/metrics/histograms/metadata/mobile/histograms.xml
@@ -70,7 +70,7 @@
 </histogram>
 
 <histogram name="Mobile.AppMenu.TimeToTakeAction.Abandoned" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>gangwu@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
@@ -984,7 +984,7 @@
 </histogram>
 
 <histogram name="MobileIntent.FirstPartyToInternalScheme" enum="Boolean"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>peconn@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
@@ -1205,7 +1205,7 @@
 </histogram>
 
 <histogram name="MobileStartup.LaunchCause" enum="LaunchCause"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>mthiesse@chromium.org</owner>
   <owner>tedchoc@chromium.org</owner>
   <owner>yfriedman@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml
index e6d49305..0820978 100644
--- a/tools/metrics/histograms/metadata/navigation/histograms.xml
+++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -98,7 +98,7 @@
 <histogram
     name="BackForwardCache.AllSites.HistoryNavigationOutcome.BrowsingInstanceNotSwappedReason"
     enum="BackForwardCacheBrowsingInstanceNotSwappedReason"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>hajimehoshi@chromium.org</owner>
   <owner>bfcache-dev@chromium.org</owner>
   <summary>
@@ -342,7 +342,7 @@
 </histogram>
 
 <histogram name="BackForwardCache.HistoryNavigationOutcome.NotRestoredReason"
-    enum="BackForwardCacheNotRestoredReason" expires_after="2022-10-30">
+    enum="BackForwardCacheNotRestoredReason" expires_after="2023-01-01">
   <owner>hajimehoshi@chromium.org</owner>
   <owner>bfcache-dev@chromium.org</owner>
   <summary>
@@ -712,7 +712,7 @@
 </histogram>
 
 <histogram name="Navigation.IsSameSiteInstance"
-    enum="NavigationIsSameSiteInstance" expires_after="2022-10-30">
+    enum="NavigationIsSameSiteInstance" expires_after="2023-01-01">
   <owner>arthursonzogni@chromium.org</owner>
   <owner>clamy@chromium.org</owner>
   <owner>nasko@chromium.org</owner>
@@ -774,7 +774,7 @@
 </histogram>
 
 <histogram name="Navigation.MainFrame.SiteEngagementLevel"
-    enum="SiteEngagementLevel" expires_after="2022-10-30">
+    enum="SiteEngagementLevel" expires_after="2023-01-01">
   <owner>meacer@chromium.org</owner>
   <owner>security-enamel@chromium.org</owner>
   <summary>
@@ -851,7 +851,7 @@
 </histogram>
 
 <histogram name="Navigation.MainFrameSchemeDifferentPage2"
-    enum="NavigationScheme" expires_after="2022-11-01">
+    enum="NavigationScheme" expires_after="2023-01-01">
   <owner>estark@chromium.org</owner>
   <owner>elawrence@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
@@ -1107,7 +1107,7 @@
 </histogram>
 
 <histogram name="Navigation.ReadyToCommitUntilCommit2" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>clamy@chromium.org</owner>
   <owner>nasko@chromium.org</owner>
   <summary>
@@ -1204,7 +1204,7 @@
 </histogram>
 
 <histogram name="Navigation.StartToCommit" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>nasko@chromium.org</owner>
   <owner>csharrison@chromium.org</owner>
   <summary>
@@ -1254,7 +1254,7 @@
 </histogram>
 
 <histogram name="Navigation.TimeToReadyToCommit2" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>clamy@chromium.org</owner>
   <owner>nasko@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml
index e07e0e21..8bf47d7 100644
--- a/tools/metrics/histograms/metadata/net/histograms.xml
+++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -121,7 +121,7 @@
 </histogram>
 
 <histogram name="HttpCache.Pattern" enum="HttpCachePattern"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>morlovich@chromium.org</owner>
   <owner>jkarlin@chromium.org</owner>
   <summary>For each http cache transaction, the recorded pattern.</summary>
@@ -355,7 +355,7 @@
 </histogram>
 
 <histogram name="Net.CertVerifier.PathBuilderIterationCount" units="units"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>mattm@chromium.org</owner>
   <owner>rsleevi@chromium.org</owner>
   <summary>
@@ -756,7 +756,7 @@
 </histogram>
 
 <histogram name="Net.DNS.DnsTask.SuccessTime" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>ericorth@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
@@ -767,7 +767,7 @@
 </histogram>
 
 <histogram name="Net.DNS.DnsTask.SvcbHttpsTransactionError"
-    enum="DNS.SvcbHttpsTransactionError" expires_after="2022-10-30">
+    enum="DNS.SvcbHttpsTransactionError" expires_after="2023-01-01">
   <owner>ericorth@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
@@ -3495,7 +3495,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ReadError" enum="NetErrorCodes"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3505,7 +3505,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ReadError.CurrentNetwork.HandshakeConfirmed"
-    enum="NetErrorCodes" expires_after="2022-10-30">
+    enum="NetErrorCodes" expires_after="2023-01-01">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3730,7 +3730,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.StreamCloseErrorCodeClient.HandshakeConfirmed"
-    enum="QuicErrorCodes" expires_after="2022-10-30">
+    enum="QuicErrorCodes" expires_after="2023-01-01">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -4265,7 +4265,7 @@
 </histogram>
 
 <histogram name="Net.RestrictedCookieManager.TopFrameOriginOK" enum="Boolean"
-    expires_after="2022-09-11">
+    expires_after="2023-01-01">
   <owner>morlovich@chromium.org</owner>
   <owner>src/net/cookies/OWNERS</owner>
   <summary>
@@ -4610,7 +4610,7 @@
 </histogram>
 
 <histogram name="Net.SSLHandshakeDetails" enum="SSLHandshakeDetails"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>davidben@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/network/histograms.xml b/tools/metrics/histograms/metadata/network/histograms.xml
index 9803c579..8e12f593 100644
--- a/tools/metrics/histograms/metadata/network/histograms.xml
+++ b/tools/metrics/histograms/metadata/network/histograms.xml
@@ -133,7 +133,7 @@
 </histogram>
 
 <histogram name="Network.CacheTransparency.CacheNotUsed"
-    enum="CacheTransparencyCacheNotUsedReason" expires_after="2022-11-01">
+    enum="CacheTransparencyCacheNotUsedReason" expires_after="2023-01-01">
   <owner>nidhijaju@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
   <summary>
@@ -155,7 +155,7 @@
 </histogram>
 
 <histogram name="Network.CacheTransparency.MarkedUnusable" units="list index"
-    expires_after="2022-11-01">
+    expires_after="2023-01-01">
   <owner>nidhijaju@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
   <summary>
@@ -166,7 +166,7 @@
 </histogram>
 
 <histogram name="Network.CacheTransparency.MismatchedChecksums"
-    units="list index" expires_after="2022-11-01">
+    units="list index" expires_after="2023-01-01">
   <owner>nidhijaju@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
   <summary>
@@ -178,7 +178,7 @@
 </histogram>
 
 <histogram name="Network.CacheTransparency.SingleKeyedCacheIsUsed"
-    units="list index" expires_after="2022-11-01">
+    units="list index" expires_after="2023-01-01">
   <owner>nidhijaju@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
   <summary>
@@ -191,7 +191,7 @@
 </histogram>
 
 <histogram name="Network.CacheTransparency.URLMatched" units="list index"
-    expires_after="2022-11-01">
+    expires_after="2023-01-01">
   <owner>nidhijaju@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
index c64dd1e..7756686 100644
--- a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
+++ b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
@@ -116,7 +116,7 @@
 </histogram>
 
 <histogram name="NewTabPage.Carts.ClickCart.HasDiscount"
-    enum="BooleanHasDiscount" expires_after="2022-10-30">
+    enum="BooleanHasDiscount" expires_after="2023-01-01">
   <owner>meiliang@chromium.org</owner>
   <owner>yuezhanggg@chromium.org</owner>
   <owner>chrome-shopping@google.com</owner>
@@ -143,7 +143,7 @@
 </histogram>
 
 <histogram name="NewTabPage.Carts.DiscountAt" units="index"
-    expires_after="2022-09-25">
+    expires_after="2023-01-01">
   <owner>meiliang@chromium.org</owner>
   <owner>yuezhanggg@chromium.org</owner>
   <owner>chrome-shopping@google.com</owner>
@@ -172,7 +172,7 @@
 </histogram>
 
 <histogram name="NewTabPage.Carts.DiscountConsentStatusAtLoad"
-    enum="CartDiscountConsentStatus" expires_after="2022-12-25">
+    enum="CartDiscountConsentStatus" expires_after="2023-01-01">
   <owner>yuezhanggg@chromium.org</owner>
   <owner>wychen@chromium.org</owner>
   <owner>chrome-shopping@google.com</owner>
@@ -1915,7 +1915,7 @@
 </histogram>
 
 <histogram name="NewTabPage.VoiceActions" enum="NewTabPageVoiceAction"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>tiborg@chromium.org</owner>
   <owner>yyushkina@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/notifications/histograms.xml b/tools/metrics/histograms/metadata/notifications/histograms.xml
index 18c34c5..c848d53 100644
--- a/tools/metrics/histograms/metadata/notifications/histograms.xml
+++ b/tools/metrics/histograms/metadata/notifications/histograms.xml
@@ -128,7 +128,7 @@
 </histogram>
 
 <histogram name="Notifications.Blocker.ScreenCapture.ClosedCount"
-    units="notifications" expires_after="2022-10-30">
+    units="notifications" expires_after="2023-01-01">
   <owner>knollr@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
@@ -152,7 +152,7 @@
 </histogram>
 
 <histogram name="Notifications.Blocker.ScreenCapture.ReplacedCount"
-    units="notifications" expires_after="2022-10-30">
+    units="notifications" expires_after="2023-01-01">
   <owner>knollr@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/omnibox/histograms.xml b/tools/metrics/histograms/metadata/omnibox/histograms.xml
index f13533fc..a7fd5e54 100644
--- a/tools/metrics/histograms/metadata/omnibox/histograms.xml
+++ b/tools/metrics/histograms/metadata/omnibox/histograms.xml
@@ -127,7 +127,7 @@
 </histogram>
 
 <histogram name="Omnibox.CharTypedToRepaintLatency.InsertToPresent" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>asvitkine@chromium.org</owner>
   <owner>mpearson@chromium.org</owner>
   <owner>jdonnelly@chromium.org</owner>
@@ -155,7 +155,7 @@
 </histogram>
 
 <histogram name="Omnibox.CharTypedToRepaintLatency.ToPaint" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>asvitkine@chromium.org</owner>
   <owner>mpearson@chromium.org</owner>
   <owner>jdonnelly@chromium.org</owner>
@@ -1188,7 +1188,7 @@
 
 <histogram
     name="Omnibox.SearchPrefetch.PrefetchEligibilityReason.SuggestionPrefetch"
-    enum="SearchPrefetchEligibilityReason" expires_after="2022-10-30">
+    enum="SearchPrefetchEligibilityReason" expires_after="2023-01-01">
   <owner>ryansturm@chromium.org</owner>
   <owner>chrome-omnibox-team@google.com</owner>
   <summary>
@@ -1311,7 +1311,7 @@
 </histogram>
 
 <histogram name="Omnibox.SelectedPosition" units="position"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>jdonnelly@chromium.org</owner>
   <owner>mpearson@chromium.org</owner>
   <owner>chrome-omnibox-team@google.com</owner>
@@ -1757,7 +1757,7 @@
 
 <histogram
     name="Omnibox.SuggestionUsed.URL.Experimental.NavigationToFirstMeaningfulPaint"
-    units="ms" expires_after="2022-10-30">
+    units="ms" expires_after="2023-01-01">
   <owner>jdonnelly@chromium.org</owner>
   <owner>mpearson@chromium.org</owner>
   <owner>chrome-omnibox-team@google.com</owner>
@@ -1971,7 +1971,7 @@
 </histogram>
 
 <histogram name="Omnibox.ToggleSuggestionGroupId.Off" enum="SuggestionGroupId"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>mahmadi@google.com</owner>
   <owner>chrome-omnibox-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/optimization/histograms.xml b/tools/metrics/histograms/metadata/optimization/histograms.xml
index 8b6f449..570a5893 100644
--- a/tools/metrics/histograms/metadata/optimization/histograms.xml
+++ b/tools/metrics/histograms/metadata/optimization/histograms.xml
@@ -266,7 +266,7 @@
 </histogram>
 
 <histogram name="OptimizationGuide.HintsFetcher.GetHintsRequest.HintCount"
-    units="units" expires_after="2022-10-30">
+    units="units" expires_after="2023-01-01">
   <owner>mcrouse@chromium.org</owner>
   <owner>sophiechang@chromium.org</owner>
   <summary>
@@ -276,7 +276,7 @@
 </histogram>
 
 <histogram name="OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount"
-    units="total host count" expires_after="2022-10-30">
+    units="total host count" expires_after="2023-01-01">
   <owner>mcrouse@chromium.org</owner>
   <owner>sophiechang@chromium.org</owner>
   <summary>
@@ -306,7 +306,7 @@
 </histogram>
 
 <histogram name="OptimizationGuide.HintsFetcher.GetHintsRequest.UrlCount"
-    units="total url count" expires_after="2022-10-30">
+    units="total url count" expires_after="2023-01-01">
   <owner>mcrouse@chromium.org</owner>
   <owner>sophiechang@chromium.org</owner>
   <summary>
@@ -328,7 +328,7 @@
 </histogram>
 
 <histogram name="OptimizationGuide.HintsManager.ActiveTabUrlsToFetchFor"
-    units="counts" expires_after="2022-10-30">
+    units="counts" expires_after="2023-01-01">
   <owner>sophiechang@chromium.org</owner>
   <owner>mcrouse@chromium.org</owner>
   <summary>
@@ -377,7 +377,7 @@
 <histogram
     name="OptimizationGuide.HintsManager.RaceNavigationFetchAttemptStatus"
     enum="OptimizationGuideRaceNavigationFetchAttemptStatus"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>mcrouse@chromium.org</owner>
   <owner>sophiechang@chromium.org</owner>
   <summary>
@@ -583,7 +583,7 @@
 </histogram>
 
 <histogram name="OptimizationGuide.OptimizationHintsComponent.MajorVersion"
-    units="major version number" expires_after="2022-10-30">
+    units="major version number" expires_after="2023-01-01">
   <owner>sophiechang@chromium.org</owner>
   <owner>mcrouse@chromium.org</owner>
   <summary>
@@ -1049,7 +1049,7 @@
 <histogram
     name="OptimizationGuide.PredictionModelDownloadManager.DownloadStatus"
     enum="OptimizationGuidePredictionModelDownloadStatus"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>sophiechang@chromium.org</owner>
   <owner>mcrouse@chromium.org</owner>
   <summary>
@@ -1060,7 +1060,7 @@
 
 <histogram
     name="OptimizationGuide.PredictionModelDownloadManager.DownloadSucceeded"
-    enum="BooleanSuccess" expires_after="2022-10-30">
+    enum="BooleanSuccess" expires_after="2023-01-01">
   <owner>sophiechang@chromium.org</owner>
   <owner>mcrouse@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml
index 79c5476..8523e5c 100644
--- a/tools/metrics/histograms/metadata/others/histograms.xml
+++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -404,7 +404,7 @@
 </histogram>
 
 <histogram name="Ads.InterestGroup.Auction.First6AuctionsBitsPerPage"
-    units="bitfield" expires_after="2022-10-30">
+    units="bitfield" expires_after="2023-01-01">
   <owner>caraitto@chromium.org</owner>
   <owner>pauljensen@chromium.org</owner>
   <owner>privacy-sandbox-dev@chromium.org</owner>
@@ -449,7 +449,7 @@
 </histogram>
 
 <histogram name="Ads.InterestGroup.Auction.NumAuctionsPerPage" units="auctions"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>caraitto@chromium.org</owner>
   <owner>pauljensen@chromium.org</owner>
   <owner>privacy-sandbox-dev@chromium.org</owner>
@@ -466,7 +466,7 @@
 </histogram>
 
 <histogram name="Ads.InterestGroup.Auction.NumAuctionsSkippedDueToAuctionLimit"
-    units="auctions" expires_after="2022-10-30">
+    units="auctions" expires_after="2023-01-01">
   <owner>caraitto@chromium.org</owner>
   <owner>pauljensen@chromium.org</owner>
   <owner>privacy-sandbox-dev@chromium.org</owner>
@@ -497,7 +497,7 @@
 </histogram>
 
 <histogram name="Ads.InterestGroup.Auction.NumOwnersWithInterestGroups"
-    units="owners" expires_after="2022-10-30">
+    units="owners" expires_after="2023-01-01">
   <owner>mmenke@chromium.org</owner>
   <owner>morlovich@chromium.org</owner>
   <summary>
@@ -533,7 +533,7 @@
 </histogram>
 
 <histogram name="Ads.InterestGroup.Auction.PercentAuctionsSuccessfulPerPage"
-    units="%" expires_after="2022-10-30">
+    units="%" expires_after="2023-01-01">
   <owner>caraitto@chromium.org</owner>
   <owner>pauljensen@chromium.org</owner>
   <owner>privacy-sandbox-dev@chromium.org</owner>
@@ -551,7 +551,7 @@
 </histogram>
 
 <histogram name="Ads.InterestGroup.Auction.Result" enum="AuctionResult"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>mmenke@chromium.org</owner>
   <owner>morlovich@chromium.org</owner>
   <summary>
@@ -564,7 +564,7 @@
 </histogram>
 
 <histogram name="Ads.InterestGroup.Auction.TimeSinceLastAuctionPerPage"
-    units="ms" expires_after="2022-10-30">
+    units="ms" expires_after="2023-01-01">
   <owner>caraitto@chromium.org</owner>
   <owner>pauljensen@chromium.org</owner>
   <owner>privacy-sandbox-dev@chromium.org</owner>
@@ -1699,7 +1699,7 @@
 </histogram>
 
 <histogram name="BrotliFilter.CompressionPercent" units="%"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>eustas@chromium.org</owner>
   <summary>Compressed/Decompressed size ratio.</summary>
 </histogram>
@@ -3363,7 +3363,7 @@
 </histogram>
 
 <histogram name="Conversions.AggregatableKeysPerSource" units="keys"
-    expires_after="2022-10-12">
+    expires_after="2023-01-01">
   <owner>linnan@chromium.org</owner>
   <owner>johnidel@chromium.org</owner>
   <owner>measurement-api-dev+metrics@google.com</owner>
@@ -3653,7 +3653,7 @@
 </histogram>
 
 <histogram name="Conversions.ExtraReportDelay2" units="ms"
-    expires_after="2022-10-23">
+    expires_after="2023-01-01">
   <owner>apaseltiner@chromium.org</owner>
   <owner>johnidel@chromium.org</owner>
   <owner>csharrison@chromium.org</owner>
@@ -3820,7 +3820,7 @@
 </histogram>
 
 <histogram name="Conversions.Report.HttpResponseOrNetErrorCode"
-    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-10-09">
+    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2023-01-01">
   <owner>johnidel@chromium.org</owner>
   <owner>measurement-api-dev+metrics@google.com</owner>
   <summary>
@@ -3926,7 +3926,7 @@
 </histogram>
 
 <histogram name="Conversions.ReportStatus2" enum="ConversionReportStatus"
-    expires_after="2022-10-09">
+    expires_after="2023-01-01">
   <owner>johnidel@chromium.org</owner>
   <owner>csharrison@chromium.org</owner>
   <summary>
@@ -4021,7 +4021,7 @@
 </histogram>
 
 <histogram name="Conversions.TimeFromConversionToReportSend" units="hours"
-    expires_after="2022-10-23">
+    expires_after="2023-01-01">
   <owner>johnidel@chromium.org</owner>
   <owner>csharrison@chromium.org</owner>
   <summary>
@@ -5752,24 +5752,27 @@
 </histogram>
 
 <histogram name="Feedback.Duration.FetchSystemInformation" units="ms"
-    expires_after="2022-12-25">
+    expires_after="2023-03-25">
   <owner>xiangdongkong@google.com</owner>
+  <owner>fernandex@google.com</owner>
   <owner>cros-feedback-app@google.com</owner>
   <summary>
     Records the elapsed time from the start of fetching system information to
     when the data has been retrieved. Fires during the process of sending a
-    feedback report on Chrome or Chrome OS.
+    feedback report on Chrome (Desktop + Android) or Chrome OS.
   </summary>
 </histogram>
 
-<histogram name="Feedback.Duration.FormOpenToSubmit" units="s"
-    expires_after="2022-11-27">
+<histogram name="Feedback.Duration.FormOpenToSubmit" units="ms"
+    expires_after="2023-03-25">
   <owner>xiangdongkong@google.com</owner>
+  <owner>fernandex@google.com</owner>
   <owner>cros-feedback-app@google.com</owner>
   <summary>
     Records the elapsed time from when the feedback app window is opened to when
     the backend receives the send report request submitted by a user. Fires
-    during the process of sending a feedback report on Chrome or Chrome OS.
+    during the process of sending a feedback report on Chrome (Desktop +
+    Android) or Chrome OS.
   </summary>
 </histogram>
 
@@ -6252,7 +6255,7 @@
 </histogram>
 
 <histogram name="Gamepad.KnownGamepadConnectedWithId"
-    enum="GamepadVendorProduct" expires_after="2022-10-30">
+    enum="GamepadVendorProduct" expires_after="2023-01-01">
   <owner>mattreynolds@chromium.org</owner>
   <owner>deviceapi-team@google.com</owner>
   <summary>
@@ -7869,7 +7872,7 @@
 </histogram>
 
 <histogram name="Manifest.HasProperty" enum="Boolean"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>mgiuca@chromium.org</owner>
   <summary>
     Tracks which properties of a Manifest were present when it was parsed. If a
@@ -8179,7 +8182,7 @@
 </histogram>
 
 <histogram name="Mojo.Channel.WriteMessageLatency" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>amistry@chromium.org</owner>
   <owner>bgeffon@chromium.org</owner>
   <owner>rockot@google.com</owner>
@@ -8208,7 +8211,7 @@
 </histogram>
 
 <histogram name="Mojo.Channel.WriteQueuePendingMessages" units="count"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>amistry@chromium.org</owner>
   <owner>bgeffon@chromium.org</owner>
   <owner>rockot@google.com</owner>
@@ -8335,7 +8338,7 @@
 </histogram>
 
 <histogram name="MPArch.ChildProcessLaunchSubsequent" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>pasko@chromium.org</owner>
   <owner>yfriedman@chromium.org</owner>
   <summary>
@@ -8971,7 +8974,7 @@
 </histogram>
 
 <histogram name="OSCrypt.Win.Decrypt.Result" enum="BooleanSuccess"
-    expires_after="M106">
+    expires_after="2023-01-01">
   <owner>wfh@chromium.org</owner>
   <owner>nparker@chromium.org</owner>
   <summary>
@@ -8980,7 +8983,8 @@
   </summary>
 </histogram>
 
-<histogram name="OSCrypt.Win.Decrypt.Time" units="ms" expires_after="M106">
+<histogram name="OSCrypt.Win.Decrypt.Time" units="ms"
+    expires_after="2023-01-01">
   <owner>wfh@chromium.org</owner>
   <owner>nparker@chromium.org</owner>
   <summary>
@@ -8990,7 +8994,7 @@
 </histogram>
 
 <histogram name="OSCrypt.Win.Encrypt.Result" enum="BooleanSuccess"
-    expires_after="M106">
+    expires_after="2023-01-01">
   <owner>wfh@chromium.org</owner>
   <owner>nparker@chromium.org</owner>
   <summary>
@@ -9002,7 +9006,8 @@
   </summary>
 </histogram>
 
-<histogram name="OSCrypt.Win.Encrypt.Time" units="ms" expires_after="M106">
+<histogram name="OSCrypt.Win.Encrypt.Time" units="ms"
+    expires_after="2023-01-01">
   <owner>wfh@chromium.org</owner>
   <owner>nparker@chromium.org</owner>
   <summary>
@@ -9382,7 +9387,7 @@
 </histogram>
 
 <histogram name="PaintHolding.InputTiming2" enum="PaintHoldingInputTiming"
-    expires_after="2022-10-09">
+    expires_after="2023-01-01">
   <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
   <summary>
@@ -10621,7 +10626,7 @@
 </histogram>
 
 <histogram name="ReadingList.WebUI.LoadDocumentTime" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>corising@chromium.org</owner>
   <owner>chrome-desktop-ui-sea@google.com</owner>
   <summary>
@@ -10969,7 +10974,7 @@
 </histogram>
 
 <histogram name="ReportingAndNEL.NumberOfLoadedReportingEndpointGroups"
-    units="endpoint group count" expires_after="2022-10-30">
+    units="endpoint group count" expires_after="2023-01-01">
   <owner>yhirano@chromium.org</owner>
   <owner>src/net/reporting/OWNERS</owner>
   <summary>
@@ -10981,7 +10986,7 @@
 </histogram>
 
 <histogram name="ReportingAndNEL.NumberOfLoadedReportingEndpointGroups2"
-    units="endpoint group count" expires_after="2022-10-30">
+    units="endpoint group count" expires_after="2023-01-01">
   <owner>yhirano@chromium.org</owner>
   <owner>src/net/reporting/OWNERS</owner>
   <summary>
@@ -10993,7 +10998,7 @@
 </histogram>
 
 <histogram name="ReportingAndNEL.NumberOfLoadedReportingEndpoints"
-    units="endpoint count" expires_after="2022-10-30">
+    units="endpoint count" expires_after="2023-01-01">
   <owner>yhirano@chromium.org</owner>
   <owner>src/net/reporting/OWNERS</owner>
   <summary>
@@ -11005,7 +11010,7 @@
 </histogram>
 
 <histogram name="ReportingAndNEL.NumberOfLoadedReportingEndpoints2"
-    units="endpoint count" expires_after="2022-10-30">
+    units="endpoint count" expires_after="2023-01-01">
   <owner>yhirano@chromium.org</owner>
   <owner>src/net/reporting/OWNERS</owner>
   <summary>
@@ -11882,7 +11887,7 @@
 </histogram>
 
 <histogram name="Servicification.Startup3" enum="ServicificationStartupMode"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>hanxi@chromium.org</owner>
   <owner>yfriedman@chromium.org</owner>
   <owner>hnakashima@chromium.org</owner>
@@ -12077,7 +12082,8 @@
   </summary>
 </histogram>
 
-<histogram name="Shutdown.EndSession.Time" units="ms" expires_after="M107">
+<histogram name="Shutdown.EndSession.Time" units="ms"
+    expires_after="2023-01-01">
   <owner>etienneb@chromium.org</owner>
   <owner>gab@chromium.org</owner>
   <summary>
@@ -12566,7 +12572,7 @@
 </histogram>
 
 <histogram name="SpellCheck.SpellingService.RequestDuration" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>yyushkina@google.com</owner>
   <owner>gujen@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -12578,7 +12584,7 @@
 </histogram>
 
 <histogram name="SpellCheck.SpellingService.RequestHttpResponseCode"
-    enum="HttpResponseCode" expires_after="2022-10-30">
+    enum="HttpResponseCode" expires_after="2023-01-01">
   <owner>yyushkina@google.com</owner>
   <owner>gujen@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -12802,7 +12808,7 @@
 </histogram>
 
 <histogram name="Style.InvalidationTime" units="microseconds"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>futhark@chromium.org</owner>
   <summary>
     Microseconds spent in StyleEngine::InvalidateStyle. Only samples from high
@@ -12811,7 +12817,7 @@
 </histogram>
 
 <histogram name="Style.RebuildLayoutTreeTime" units="microseconds"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>futhark@chromium.org</owner>
   <summary>
     Microseconds spent in RebuildLayoutTree called from Document::UpdateStyle.
@@ -12819,7 +12825,7 @@
 </histogram>
 
 <histogram name="Style.RecalcTime" units="microseconds"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>futhark@chromium.org</owner>
   <summary>
     Microseconds spent in RecalcStyle called from Document::UpdateStyle.
@@ -13980,7 +13986,7 @@
 </histogram>
 
 <histogram name="UsageStats.Events" enum="UsageStatsEvents"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>pnoland@chromium.org</owner>
   <owner>fgorski@chromium.org</owner>
   <summary>
@@ -14446,7 +14452,7 @@
 </histogram>
 
 <histogram name="VoiceInteraction.VoiceResultConfidenceValue" units="%"
-    expires_after="2022-12-25">
+    expires_after="2023-01-01">
   <owner>jds@google.com</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -14793,7 +14799,7 @@
 </histogram>
 
 <histogram name="WebShare.ApiCount" enum="WebShareMethod"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>mgiuca@chromium.org</owner>
   <summary>
     Counts the number of calls to navigator.share. Includes both successful and
@@ -14826,13 +14832,13 @@
 </histogram>
 
 <histogram name="WebUI.CreatedForUrl" enum="WebUIUrlHashes"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>dbeam@chromium.org</owner>
   <summary>URLs for which Chrome creates WebUIControllers.</summary>
 </histogram>
 
 <histogram name="WebUI.Settings.PathVisited" enum="WebUISettingsPathHashes"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>dschuyler@chromium.org</owner>
   <owner>tbuckley@chromium.org</owner>
   <owner>bettes@chromium.org</owner>
@@ -14857,7 +14863,7 @@
 </histogram>
 
 <histogram name="WebUITabStrip.CloseAction" enum="WebUITabStripCloseActions"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>collinbaker@chromium.org</owner>
   <owner>tluk@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml
index 457ddea..25f8378af 100644
--- a/tools/metrics/histograms/metadata/page/histograms.xml
+++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -1154,7 +1154,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.ThirdParty.Origins.CookieRead2" units="Count"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>jkarlin@chromium.org</owner>
   <owner>yaoxia@chromium.org</owner>
   <summary>
@@ -1636,7 +1636,7 @@
 
 <histogram
     name="PageLoad.Experimental.NavigationTiming.NavigationStartToFirstLoaderCallback"
-    units="ms" expires_after="2022-10-30">
+    units="ms" expires_after="2023-01-01">
   <owner>nhiroki@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -2124,7 +2124,7 @@
 </histogram>
 
 <histogram name="PageLoad.InteractiveTiming.ProcessingTime" units="ms"
-    expires_after="2022-11-01">
+    expires_after="2023-01-01">
   <owner>iclelland@chromium.org</owner>
   <owner>speed-metrics-dev@chromium.org</owner>
   <summary>
@@ -2137,7 +2137,7 @@
 </histogram>
 
 <histogram name="PageLoad.InteractiveTiming.TimeToNextPaint" units="ms"
-    expires_after="2022-11-01">
+    expires_after="2023-01-01">
   <owner>iclelland@chromium.org</owner>
   <owner>speed-metrics-dev@chromium.org</owner>
   <summary>
@@ -2183,7 +2183,7 @@
 </histogram>
 
 <histogram name="PageLoad.Internal.ErrorCode" enum="InternalErrorLoadEvent"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>csharrison@chromium.org</owner>
   <owner>bmcquade@chromium.org</owner>
   <summary>
@@ -2518,7 +2518,7 @@
 </histogram>
 
 <histogram name="PageLoad.PageTiming.ForegroundDuration" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>bmcquade@chromium.org</owner>
   <summary>
     For page loads that start in the foreground, measures the duration of time
@@ -2544,7 +2544,7 @@
 </histogram>
 
 <histogram name="PageLoad.PageTiming.NavigationToFirstForeground" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>bmcquade@chromium.org</owner>
   <owner>csharrison@chromium.org</owner>
   <summary>
@@ -2691,7 +2691,7 @@
 
 <histogram
     name="PageLoad.PaintTiming.NavigationToLargestContentfulPaint2.CrossSiteSubFrame"
-    units="ms" expires_after="2022-10-30">
+    units="ms" expires_after="2023-01-01">
   <owner>sisidovski@google.com</owner>
   <owner>kouhei@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml
index 13f1cad..21f113a 100644
--- a/tools/metrics/histograms/metadata/password/histograms.xml
+++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -209,7 +209,7 @@
 </histogram>
 
 <histogram name="PasswordBubble.DisplayDisposition"
-    enum="PasswordBubbleDisplayDisposition" expires_after="2022-10-30">
+    enum="PasswordBubbleDisplayDisposition" expires_after="2023-01-01">
   <owner>vasilii@chromium.org</owner>
   <summary>
     When the password management bubble opened, what state was it in?
@@ -234,7 +234,7 @@
 </histogram>
 
 <histogram name="PasswordGeneration.GeneratedPasswordWasEdited"
-    enum="BooleanGeneratedPasswordWasEdited" expires_after="2022-10-30">
+    enum="BooleanGeneratedPasswordWasEdited" expires_after="2023-01-01">
   <owner>kolos@chromium.org</owner>
   <summary>
     Measures the frequency of user editing of generated passwords. Uploaded once
@@ -243,7 +243,7 @@
 </histogram>
 
 <histogram name="PasswordGeneration.PopupShown"
-    enum="PasswordGenerationPopupShown" expires_after="2022-10-30">
+    enum="PasswordGenerationPopupShown" expires_after="2023-01-01">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>Records an entry if (and only if) a popup was shown.</summary>
@@ -304,7 +304,7 @@
 </histogram>
 
 <histogram name="PasswordManager.AbleToSavePasswordsOnSuccessfulLogin"
-    enum="BooleanSuccess" expires_after="2022-10-30">
+    enum="BooleanSuccess" expires_after="2023-01-01">
   <owner>vasilii@chromium.org</owner>
   <owner>src/components/password_manager/OWNERS</owner>
   <summary>
@@ -326,7 +326,7 @@
 </histogram>
 
 <histogram name="PasswordManager.AccessPasswordInSettings"
-    enum="AccessPasswordInSettingsEvent" expires_after="2022-10-30">
+    enum="AccessPasswordInSettingsEvent" expires_after="2023-01-01">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -625,7 +625,7 @@
 </histogram>
 
 <histogram name="PasswordManager.AffiliationBackend.SubsequentFetchDelay"
-    units="ms" expires_after="2022-10-30">
+    units="ms" expires_after="2023-01-01">
   <owner>vsemeniuk@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -814,7 +814,7 @@
 </histogram>
 
 <histogram name="PasswordManager.ApplySyncChanges.AddLoginSyncError"
-    enum="PasswordAddLoginSyncError" expires_after="2022-10-30">
+    enum="PasswordAddLoginSyncError" expires_after="2023-01-01">
   <owner>mamir@chromium.org</owner>
   <owner>mastiz@chromium.org</owner>
   <summary>
@@ -847,7 +847,7 @@
 </histogram>
 
 <histogram name="PasswordManager.AutomaticChange.AcceptanceWithAutoButton"
-    enum="PasswordCheckResolutionAction" expires_after="2022-10-30">
+    enum="PasswordCheckResolutionAction" expires_after="2023-01-01">
   <owner>kolos@chromium.org</owner>
   <owner>battre@chromium.org</owner>
   <summary>
@@ -878,7 +878,7 @@
 </histogram>
 
 <histogram name="PasswordManager.AutoSigninFirstRunDialog"
-    enum="AutoSigninFirstRun" expires_after="2022-10-30">
+    enum="AutoSigninFirstRun" expires_after="2023-01-01">
   <owner>vasilii@chromium.org</owner>
   <owner>kazinova@google.com</owner>
   <summary>
@@ -932,7 +932,7 @@
 </histogram>
 
 <histogram name="PasswordManager.BulkCheck.CanceledTime" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>vasilii@chromium.org</owner>
   <owner>vsemeniuk@google.com</owner>
   <summary>
@@ -941,7 +941,7 @@
 </histogram>
 
 <histogram name="PasswordManager.BulkCheck.CheckedCredentials"
-    units="credentials" expires_after="2022-10-30">
+    units="credentials" expires_after="2023-01-01">
   <owner>vasilii@chromium.org</owner>
   <owner>vsemeniuk@google.com</owner>
   <summary>
@@ -954,7 +954,7 @@
 </histogram>
 
 <histogram name="PasswordManager.BulkCheck.CheckedCredentialsOnErrorOrCanceled"
-    units="credentials" expires_after="2022-10-30">
+    units="credentials" expires_after="2023-01-01">
   <owner>vasilii@chromium.org</owner>
   <owner>vsemeniuk@google.com</owner>
   <summary>
@@ -968,7 +968,7 @@
 
 <histogram
     name="PasswordManager.BulkCheck.CompromisedCredentialsCountAfterCheckAndroid"
-    units="credentials" expires_after="2022-10-30">
+    units="credentials" expires_after="2023-01-01">
   <owner>ioanap@chromium.org</owner>
   <owner>fhorschig@chromium.org</owner>
   <summary>
@@ -982,7 +982,7 @@
 
 <histogram
     name="PasswordManager.BulkCheck.CompromisedCredentialsCountWithAutoChangeAfterCheckAndroid"
-    units="credentials" expires_after="2022-10-30">
+    units="credentials" expires_after="2023-01-01">
   <owner>ioanap@chromium.org</owner>
   <owner>fhorschig@chromium.org</owner>
   <summary>
@@ -1000,7 +1000,7 @@
 </histogram>
 
 <histogram name="PasswordManager.BulkCheck.LeaksFound" units="credentials"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>vasilii@chromium.org</owner>
   <owner>vsemeniuk@google.com</owner>
   <summary>
@@ -1063,7 +1063,7 @@
 </histogram>
 
 <histogram name="PasswordManager.BulkCheck.Time" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>vasilii@chromium.org</owner>
   <owner>vsemeniuk@google.com</owner>
   <summary>
@@ -1082,14 +1082,14 @@
 </histogram>
 
 <histogram name="PasswordManager.BulkCheck.UserAction"
-    enum="PasswordCheckInteraction" expires_after="2022-10-30">
+    enum="PasswordCheckInteraction" expires_after="2023-01-01">
   <owner>vsemeniuk@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>User actions performed on the Password Check settings page.</summary>
 </histogram>
 
 <histogram name="PasswordManager.BulkCheck.UserActionAndroid"
-    enum="PasswordCheckUIUserActionAndroid" expires_after="2022-10-30">
+    enum="PasswordCheckUIUserActionAndroid" expires_after="2023-01-01">
   <owner>ioanap@chromium.org</owner>
   <owner>fhorschigg@chromium.org</owner>
   <summary>User actions performed on the Password Check settings view.</summary>
@@ -1416,7 +1416,7 @@
 </histogram>
 
 <histogram name="PasswordManager.Enabled3" enum="BooleanEnabled"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -1492,7 +1492,7 @@
 </histogram>
 
 <histogram name="PasswordManager.FirstRendererFillingResult"
-    enum="PasswordManagerFirstRendererFillingResult" expires_after="2022-10-30">
+    enum="PasswordManagerFirstRendererFillingResult" expires_after="2023-01-01">
   <owner>kazinova@google.com</owner>
   <owner>battre@chromium.org</owner>
   <summary>
@@ -1505,7 +1505,7 @@
 </histogram>
 
 <histogram name="PasswordManager.FirstWaitForUsernameReason"
-    enum="PasswordManagerFirstWaitForUsernameReason" expires_after="2022-10-30">
+    enum="PasswordManagerFirstWaitForUsernameReason" expires_after="2023-01-01">
   <owner>kazinova@google.com</owner>
   <owner>battre@chromium.org</owner>
   <summary>
@@ -1591,7 +1591,7 @@
 </histogram>
 
 <histogram name="PasswordManager.ImportedPasswordsPerUserInCSV" units="units"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>vasilii@chromium.org</owner>
   <owner>src/components/password_manager/OWNERS</owner>
   <summary>
@@ -1601,7 +1601,7 @@
 </histogram>
 
 <histogram name="PasswordManager.ImportPasswordFromCSVResult"
-    enum="PasswordImportFromCSVResult" expires_after="2022-10-30">
+    enum="PasswordImportFromCSVResult" expires_after="2023-01-01">
   <owner>vasilii@chromium.org</owner>
   <owner>src/components/password_manager/OWNERS</owner>
   <summary>
@@ -1671,7 +1671,7 @@
 </histogram>
 
 <histogram name="PasswordManager.LeakDetection.AnalyzeSingleLeakResponseResult"
-    enum="PasswordAnalyzeLeakResponseResult" expires_after="2022-10-30">
+    enum="PasswordAnalyzeLeakResponseResult" expires_after="2023-01-01">
   <owner>vsemeniuk@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>Result of analyzing a single leak response.</summary>
@@ -1737,7 +1737,7 @@
 </histogram>
 
 <histogram name="PasswordManager.LeakDetection.NotifyIsLeakedTime" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>vsemeniuk@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -1747,7 +1747,7 @@
 </histogram>
 
 <histogram name="PasswordManager.LeakDetection.ObtainAccessTokenTime"
-    units="ms" expires_after="2022-10-30">
+    units="ms" expires_after="2023-01-01">
   <owner>vsemeniuk@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -1779,7 +1779,7 @@
 </histogram>
 
 <histogram name="PasswordManager.LeakDetection.SingleLeakResponsePrefixes"
-    units="prefixes" expires_after="2022-10-30">
+    units="prefixes" expires_after="2023-01-01">
   <owner>vsemeniuk@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -1789,7 +1789,7 @@
 </histogram>
 
 <histogram name="PasswordManager.LeakDetection.SingleLeakResponseSize"
-    units="bytes" expires_after="2022-10-30">
+    units="bytes" expires_after="2023-01-01">
   <owner>vsemeniuk@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -1817,7 +1817,7 @@
 </histogram>
 
 <histogram name="PasswordManager.MatchedFormType"
-    enum="PasswordManagerMatchedFormType" expires_after="2022-10-30">
+    enum="PasswordManagerMatchedFormType" expires_after="2023-01-01">
   <owner>vsemeniuk@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -1828,7 +1828,7 @@
 </histogram>
 
 <histogram name="PasswordManager.MediationOptional"
-    enum="CredentialManagerGetResult" expires_after="2022-10-30">
+    enum="CredentialManagerGetResult" expires_after="2023-01-01">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -2072,7 +2072,7 @@
 </histogram>
 
 <histogram name="PasswordManager.PasswordDropdownItemSelected"
-    enum="PasswordDropdownSelectedOption" expires_after="2022-10-30">
+    enum="PasswordDropdownSelectedOption" expires_after="2023-01-01">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -2088,7 +2088,7 @@
 </histogram>
 
 <histogram name="PasswordManager.PasswordEditUpdatedValues"
-    enum="PasswordEditUpdatedValues" expires_after="2022-10-30">
+    enum="PasswordEditUpdatedValues" expires_after="2023-01-01">
   <owner>vsemeniuk@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -2196,7 +2196,7 @@
 </histogram>
 
 <histogram name="PasswordManager.PasswordScriptsFetcher.ResponseTime"
-    units="ms" expires_after="2022-10-30">
+    units="ms" expires_after="2023-01-01">
   <owner>kolos@chromium.org</owner>
   <owner>battre@chromium.org</owner>
   <summary>
@@ -2488,6 +2488,41 @@
   </token>
 </histogram>
 
+<histogram name="PasswordManager.PasswordStore{Backend}{Function}"
+    enum="PasswordStoreAndroidBackendRequestStatus" expires_after="M108">
+  <owner>fhorschig@chromium.org</owner>
+  <owner>vasilii@chromium.org</owner>
+  <summary>
+    Records each {Function} call by the PasswordStore {Backend}. Recorded twice:
+    1) when the store issues the request, and 2) as the asynchronous job has
+    finished or times out. The first bucket may exceed others if Chrome closes
+    before the request finishes.
+  </summary>
+  <token key="Backend">
+    <variant name="AndroidBackend" summary="Android backend"/>
+    <variant name="Backend" summary="backend"/>
+    <variant name="BuiltInBackend" summary="built-in backend"/>
+  </token>
+  <token key="Function">
+    <variant name=".AddLoginAsync" summary="AddLoginAsync()"/>
+    <variant name=".ClearAllLocalPasswords" summary="ClearAllLocalPasswords()"/>
+    <variant name=".DisableAutoSignInForOriginsAsync"
+        summary="DisableAutoSignInForOriginsAsync()"/>
+    <variant name=".FillMatchingLoginsAsync"
+        summary="FillMatchingLoginsAsync()"/>
+    <variant name=".GetAllLoginsAsync" summary="GetAllLoginsAsync()"/>
+    <variant name=".GetAutofillableLoginsAsync"
+        summary="GetAutofillableLoginsAsync()"/>
+    <variant name=".GetLoginsAsync" summary="GetLoginsAsync()"/>
+    <variant name=".RemoveLoginAsync" summary="RemoveLoginAsync()"/>
+    <variant name=".RemoveLoginsByURLAndTimeAsync"
+        summary="RemoveLoginsByURLAndTimeAsync()"/>
+    <variant name=".RemoveLoginsCreatedBetweenAsync"
+        summary="RemoveLoginsCreatedBetweenAsync()"/>
+    <variant name=".UpdateLoginAsync" summary="UpdateLoginAsync()"/>
+  </token>
+</histogram>
+
 <histogram name="PasswordManager.PasswordStore{Backend}{Function}.Latency"
     units="ms" expires_after="M108">
   <owner>fhorschig@chromium.org</owner>
@@ -2840,7 +2875,7 @@
 </histogram>
 
 <histogram name="PasswordManager.SubmittedFormFrame2"
-    enum="SubmittedPasswordFormFrame" expires_after="2022-10-30">
+    enum="SubmittedPasswordFormFrame" expires_after="2023-01-01">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -2862,7 +2897,7 @@
 </histogram>
 
 <histogram name="PasswordManager.SuccessfulLoginHappened"
-    enum="BooleanSuccessfulLoginHappenedOnHttps" expires_after="2022-10-30">
+    enum="BooleanSuccessfulLoginHappenedOnHttps" expires_after="2023-01-01">
   <owner>kazinova@google.com</owner>
   <owner>kolos@chromium.org</owner>
   <summary>
@@ -2884,7 +2919,7 @@
 
 <histogram
     name="PasswordManager.SyncControllerDelegateNotifiesCredentialManager.APIErrorCode"
-    enum="CredentialManagerAPIError" expires_after="2022-08-10">
+    enum="CredentialManagerAPIError" expires_after="M108">
   <owner>kazinova@google.com</owner>
   <owner>ioanap@chromium.org</owner>
   <summary>
@@ -2896,7 +2931,7 @@
 
 <histogram
     name="PasswordManager.SyncControllerDelegateNotifiesCredentialManager.ErrorCode"
-    enum="PasswordStoreAndroidBackendError" expires_after="2022-11-06">
+    enum="PasswordStoreAndroidBackendError" expires_after="M108">
   <owner>kazinova@google.com</owner>
   <owner>ioanap@chromium.org</owner>
   <summary>
@@ -2910,7 +2945,7 @@
 
 <histogram
     name="PasswordManager.SyncControllerDelegateNotifiesCredentialManager.Success"
-    enum="Boolean" expires_after="2022-11-06">
+    enum="Boolean" expires_after="M108">
   <owner>kazinova@google.com</owner>
   <owner>ioanap@chromium.org</owner>
   <summary>
@@ -2967,7 +3002,7 @@
 </histogram>
 
 <histogram name="PasswordManager.TimeBetweenStoreAndServer" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>kazinova@google.com</owner>
   <owner>battre@chromium.org</owner>
   <summary>
@@ -3031,7 +3066,7 @@
 </histogram>
 
 <histogram name="PasswordManager.TouchToFill.SuccessfulSubmissionWasObserved"
-    enum="Boolean" expires_after="2022-10-30">
+    enum="Boolean" expires_after="2023-01-01">
   <owner>ioanap@chromium.org</owner>
   <owner>fhorschig@chromium.org</owner>
   <owner>kolos@chromium.org</owner>
@@ -3051,7 +3086,7 @@
 </histogram>
 
 <histogram name="PasswordManager.TouchToFill.TimeToSuccessfulLogin" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>ioanap@chromium.org</owner>
   <owner>fhorschig@chromium.org</owner>
   <owner>kolos@chromium.org</owner>
@@ -3156,7 +3191,7 @@
 </histogram>
 
 <histogram name="PasswordManager.UpdateUIDismissalReason"
-    enum="PasswordManagerUIDismissalReason" expires_after="2022-10-30">
+    enum="PasswordManagerUIDismissalReason" expires_after="2023-01-01">
   <owner>vasilii@chromium.org</owner>
   <summary>Why was the update password UI (bubble or infobar) closed?</summary>
 </histogram>
@@ -3188,7 +3223,7 @@
 </histogram>
 
 <histogram name="PasswordManager.WeakCheck.CheckedPasswords" units="passwords"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -3197,7 +3232,7 @@
 </histogram>
 
 <histogram name="PasswordManager.WeakCheck.PasswordScore"
-    enum="PasswordWeaknessScore" expires_after="2022-10-30">
+    enum="PasswordWeaknessScore" expires_after="2023-01-01">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -3214,7 +3249,7 @@
 </histogram>
 
 <histogram name="PasswordManager.WeakCheck.WeakPasswords" units="passwords"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -3544,7 +3579,7 @@
 </histogram>
 
 <histogram name="PasswordProtection.PasswordProtectionResponseOrErrorCode"
-    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-10-30">
+    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2023-01-01">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/payment/histograms.xml b/tools/metrics/histograms/metadata/payment/histograms.xml
index 01614ebf..fa7eb4d 100644
--- a/tools/metrics/histograms/metadata/payment/histograms.xml
+++ b/tools/metrics/histograms/metadata/payment/histograms.xml
@@ -185,7 +185,7 @@
 </histogram>
 
 <histogram name="PaymentRequest.PaymentHandlerInstallSuccess"
-    enum="BooleanSuccess" expires_after="2022-10-30">
+    enum="BooleanSuccess" expires_after="2023-01-01">
   <owner>rouslan@chromium.org</owner>
   <owner>web-payments-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/pdf/histograms.xml b/tools/metrics/histograms/metadata/pdf/histograms.xml
index 35b5405..52f5bf0 100644
--- a/tools/metrics/histograms/metadata/pdf/histograms.xml
+++ b/tools/metrics/histograms/metadata/pdf/histograms.xml
@@ -23,7 +23,7 @@
 <histograms>
 
 <histogram name="PDF.Actions" enum="ChromePDFViewerActions"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>hnakashima@chromium.org</owner>
   <summary>
     Tracks user actions in the PDF viewer. Logged when the document is opened
diff --git a/tools/metrics/histograms/metadata/permissions/histograms.xml b/tools/metrics/histograms/metadata/permissions/histograms.xml
index b4097ef..2ad6cc21 100644
--- a/tools/metrics/histograms/metadata/permissions/histograms.xml
+++ b/tools/metrics/histograms/metadata/permissions/histograms.xml
@@ -392,7 +392,7 @@
 </histogram>
 
 <histogram name="Permissions.Engagement.Accepted" units="%"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>engedy@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -413,7 +413,7 @@
 </histogram>
 
 <histogram name="Permissions.Engagement.Denied" units="%"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>engedy@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -443,7 +443,7 @@
 </histogram>
 
 <histogram name="Permissions.MissingOSLevelPermission.Action"
-    enum="PermissionAction" expires_after="2022-10-30">
+    enum="PermissionAction" expires_after="2023-01-01">
   <owner>andypaicu@chromium.org</owner>
   <owner>engedy@chromium.org</owner>
   <owner>hkamila@chromium.org</owner>
@@ -455,7 +455,7 @@
 </histogram>
 
 <histogram name="Permissions.MissingOSLevelPermission.ShouldShow"
-    enum="Boolean" expires_after="2022-10-30">
+    enum="Boolean" expires_after="2023-01-01">
   <owner>andypaicu@chromium.org</owner>
   <owner>engedy@chromium.org</owner>
   <owner>hkamila@chromium.org</owner>
@@ -538,7 +538,7 @@
 </histogram>
 
 <histogram name="Permissions.Prompt.Accepted" enum="PermissionRequestType"
-    expires_after="2022-10-31">
+    expires_after="2023-01-01">
   <owner>engedy@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -612,7 +612,7 @@
 </histogram>
 
 <histogram name="Permissions.Prompt.Denied" enum="PermissionRequestType"
-    expires_after="2022-10-31">
+    expires_after="2023-01-01">
   <owner>engedy@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -648,7 +648,7 @@
 </histogram>
 
 <histogram name="Permissions.Prompt.Dismissed.PriorDismissCount2" units="units"
-    expires_after="2022-10-31">
+    expires_after="2023-01-01">
   <owner>engedy@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -725,7 +725,7 @@
 </histogram>
 
 <histogram name="Permissions.Prompt.Shown" enum="PermissionRequestType"
-    expires_after="2022-10-31">
+    expires_after="2023-01-01">
   <owner>engedy@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -901,7 +901,7 @@
 </histogram>
 
 <histogram name="Permissions.QuietChip.TimeToInteraction" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>elklm@chromium.org</owner>
   <owner>engedy@chromium.org</owner>
   <summary>
@@ -915,7 +915,7 @@
 
 <histogram
     name="Permissions.QuietNotificationPrompts.DidEnableAdapativelyInPrefs"
-    enum="Boolean" expires_after="2022-10-30">
+    enum="Boolean" expires_after="2023-01-01">
   <owner>andypaicu@chromium.org</owner>
   <owner>engedy@chromium.org</owner>
   <owner>hkamila@chromium.org</owner>
@@ -928,7 +928,7 @@
 
 <histogram
     name="Permissions.QuietNotificationPrompts.EnabledStateInPrefsChangedTo"
-    enum="BooleanEnabled" expires_after="2022-10-30">
+    enum="BooleanEnabled" expires_after="2023-01-01">
   <owner>andypaicu@chromium.org</owner>
   <owner>engedy@chromium.org</owner>
   <owner>hkamila@chromium.org</owner>
@@ -940,7 +940,7 @@
 </histogram>
 
 <histogram name="Permissions.QuietNotificationPrompts.IsEnabledInPrefs"
-    enum="BooleanEnabled" expires_after="2022-10-30">
+    enum="BooleanEnabled" expires_after="2023-01-01">
   <owner>andypaicu@chromium.org</owner>
   <owner>engedy@chromium.org</owner>
   <owner>hkamila@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/platform/histograms.xml b/tools/metrics/histograms/metadata/platform/histograms.xml
index 950d4bd..1d371e128 100644
--- a/tools/metrics/histograms/metadata/platform/histograms.xml
+++ b/tools/metrics/histograms/metadata/platform/histograms.xml
@@ -805,7 +805,7 @@
 </histogram>
 
 <histogram name="Platform.MountEncrypted.EncryptionKeyStatus"
-    enum="MountEncryptedEncryptionKeyStatus" expires_after="2022-10-30">
+    enum="MountEncryptedEncryptionKeyStatus" expires_after="2023-01-01">
   <owner>apronin@chromium.org</owner>
   <owner>mnissler@chromium.org</owner>
   <owner>cros-hwsec+uma@chromium.org</owner>
@@ -817,7 +817,7 @@
 </histogram>
 
 <histogram name="Platform.MountEncrypted.SystemKeyStatus"
-    enum="MountEncryptedSystemKeyStatus" expires_after="2022-10-30">
+    enum="MountEncryptedSystemKeyStatus" expires_after="2023-01-01">
   <owner>apronin@chromium.org</owner>
   <owner>mnissler@chromium.org</owner>
   <owner>cros-hwsec+uma@chromium.org</owner>
@@ -1104,7 +1104,7 @@
 </histogram>
 
 <histogram name="Platform.TPM.AuthErrorCode" enum="TPMResultCodeEnum"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>yich@google.com</owner>
   <owner>cros-hwsec-userland-eng+uma@google.com</owner>
   <summary>
@@ -1135,7 +1135,7 @@
 </histogram>
 
 <histogram name="Platform.TPM.DictionaryAttackCounter" units="units"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>cylai@chromium.org</owner>
   <owner>cros-hwsec-userland-eng+uma@google.com</owner>
   <summary>
@@ -1155,7 +1155,7 @@
 </histogram>
 
 <histogram name="Platform.TPM.ErrorCode" enum="TPMResultCodeEnum"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>yich@google.com</owner>
   <owner>cros-hwsec-userland-eng+uma@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/power/histograms.xml b/tools/metrics/histograms/metadata/power/histograms.xml
index 8fa595b..35568d63 100644
--- a/tools/metrics/histograms/metadata/power/histograms.xml
+++ b/tools/metrics/histograms/metadata/power/histograms.xml
@@ -2106,7 +2106,7 @@
 </histogram>
 
 <histogram name="PowerML.SmartDimModel.RequestCanceledDuration" units="ms"
-    expires_after="2022-11-01">
+    expires_after="2023-01-01">
   <owner>amoylan@chromium.org</owner>
   <owner>napper@chromium.org</owner>
   <owner>napper@chromium.org</owner>
@@ -2118,7 +2118,7 @@
 </histogram>
 
 <histogram name="PowerML.SmartDimModel.RequestCompleteDuration" units="ms"
-    expires_after="2022-11-01">
+    expires_after="2023-01-01">
   <owner>amoylan@chromium.org</owner>
   <owner>napper@chromium.org</owner>
   <owner>napper@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/print/histograms.xml b/tools/metrics/histograms/metadata/print/histograms.xml
index 22fd7a1..5bbe942 100644
--- a/tools/metrics/histograms/metadata/print/histograms.xml
+++ b/tools/metrics/histograms/metadata/print/histograms.xml
@@ -66,7 +66,7 @@
 </histogram>
 
 <histogram name="PrintPreview.NumberOfPrinters" units="units"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>thestig@chromium.org</owner>
   <owner>dhoss@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/printing/histograms.xml b/tools/metrics/histograms/metadata/printing/histograms.xml
index 973d4bb..436b0d1 100644
--- a/tools/metrics/histograms/metadata/printing/histograms.xml
+++ b/tools/metrics/histograms/metadata/printing/histograms.xml
@@ -294,7 +294,7 @@
 </histogram>
 
 <histogram name="Printing.CUPS.TotalNetworkPrintersCount" units="printers"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>bmgordon@chromium.org</owner>
   <owner>project-bolton@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/privacy/histograms.xml b/tools/metrics/histograms/metadata/privacy/histograms.xml
index 5a728a39..753f034c 100644
--- a/tools/metrics/histograms/metadata/privacy/histograms.xml
+++ b/tools/metrics/histograms/metadata/privacy/histograms.xml
@@ -327,7 +327,7 @@
 
 <histogram name="PrivacySandbox.AggregationService.ReportAssembler.Status"
     enum="PrivacySandboxAggregationServiceReportAssemblerStatus"
-    expires_after="2022-08-23">
+    expires_after="2023-01-01">
   <owner>alexmt@chromium.org</owner>
   <owner>linnan@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/profile/histograms.xml b/tools/metrics/histograms/metadata/profile/histograms.xml
index 1cf2a51..7953067 100644
--- a/tools/metrics/histograms/metadata/profile/histograms.xml
+++ b/tools/metrics/histograms/metadata/profile/histograms.xml
@@ -133,7 +133,7 @@
 </histogram>
 
 <histogram name="Profile.DeleteProfileAction" enum="ProfileDeleteAction"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>msarda@chromium.org</owner>
   <owner>droger@chromium.org</owner>
   <owner>anthonyvd@chromium.org</owner>
@@ -273,7 +273,7 @@
 </histogram>
 
 <histogram name="Profile.Incognito.ResumedAfterReportedDuration"
-    units="minutes" expires_after="2022-10-30">
+    units="minutes" expires_after="2023-01-01">
   <owner>rhalavati@chromium.org</owner>
   <owner>chrome-incognito@google.com</owner>
   <summary>
@@ -390,7 +390,7 @@
 </histogram>
 
 <histogram name="Profile.NetUserCount" enum="ProfileNetUserCount"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>rogerta@chromium.org</owner>
   <summary>
     Counts of users added and deleted. Percentages are not meaningful. Please
@@ -564,7 +564,7 @@
 </histogram>
 
 <histogram base="true" name="Profile.State.SyncEnabled" enum="BooleanEnabled"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>jkrcal@chromium.org</owner>
   <owner>droger@chromium.org</owner>
   <summary>
@@ -708,7 +708,7 @@
 </histogram>
 
 <histogram name="ProfileChooser.HasProfilesShown" enum="BooleanShown"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>vasilii@chromium.org</owner>
   <owner>ewald@chromium.org</owner>
   <summary>
@@ -872,7 +872,7 @@
 </histogram>
 
 <histogram name="ProfilePicker.UserAction" enum="ProfilePickerAction"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>msalama@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/renderer/histograms.xml b/tools/metrics/histograms/metadata/renderer/histograms.xml
index b023b47d..65918efc2 100644
--- a/tools/metrics/histograms/metadata/renderer/histograms.xml
+++ b/tools/metrics/histograms/metadata/renderer/histograms.xml
@@ -251,7 +251,7 @@
 </histogram>
 
 <histogram name="Renderer.Font.PrimaryFont.DomContentLoaded" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>kojii@chromium.org</owner>
   <owner>tkent@chromium.org</owner>
   <owner>yosin@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/renderer4/histograms.xml b/tools/metrics/histograms/metadata/renderer4/histograms.xml
index 1d2e1dbf..386984e 100644
--- a/tools/metrics/histograms/metadata/renderer4/histograms.xml
+++ b/tools/metrics/histograms/metadata/renderer4/histograms.xml
@@ -37,7 +37,7 @@
 </histogram>
 
 <histogram name="Renderer4.Browser.RasterTaskTotalDuration"
-    units="microseconds" expires_after="2022-10-30">
+    units="microseconds" expires_after="2023-01-01">
   <owner>khushalsagar@chromium.org</owner>
   <owner>chrome-gpu@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
index 4c80b530..22f4adf 100644
--- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
+++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -102,7 +102,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.AdvancedProtection.TokenFetchStatus"
-    enum="GoogleServiceAuthError" expires_after="2022-10-30">
+    enum="GoogleServiceAuthError" expires_after="2023-01-01">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -135,7 +135,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.AndroidTelemetry.ApkDownload.Outcome"
-    enum="ApkDownloadTelemetryOutcome" expires_after="2022-10-30">
+    enum="ApkDownloadTelemetryOutcome" expires_after="2023-01-01">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -145,7 +145,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.BlockingPage.RequestDestination"
-    enum="RequestDestination" expires_after="2022-10-30">
+    enum="RequestDestination" expires_after="2023-01-01">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -850,7 +850,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.DeepScan.Upload.Duration" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>domfc@chromium.org</owner>
   <owner>webprotect-team@google.com</owner>
   <summary>
@@ -1186,7 +1186,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.ExtensionTelemetry.Signals.SignalType"
-    enum="SBExtensionTelemetrySignalsSignalType" expires_after="2022-10-30">
+    enum="SBExtensionTelemetrySignalsSignalType" expires_after="2023-01-01">
   <owner>anunoy@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -1377,7 +1377,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.PageLoadToken.ClearReason"
-    enum="SafeBrowsingPageLoadTokenClearReason" expires_after="2022-10-01">
+    enum="SafeBrowsingPageLoadTokenClearReason" expires_after="2023-01-01">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -1484,7 +1484,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.Pref.Daily.SafeBrowsingModeManaged"
-    enum="BooleanManagedPref" expires_after="2022-10-30">
+    enum="BooleanManagedPref" expires_after="2023-01-01">
   <owner>bhatiarohit@google.com</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -1645,7 +1645,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.RT.CacheManager.RealTimeVerdictCount"
-    units="entries" expires_after="2022-10-30">
+    units="entries" expires_after="2023-01-01">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -1880,7 +1880,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.RT.RequestDestinations.Checked"
-    enum="RequestDestination" expires_after="2022-10-30">
+    enum="RequestDestination" expires_after="2023-01-01">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -2108,7 +2108,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.V4Database.Size" units="KB"
-    expires_after="2022-12-25">
+    expires_after="2023-01-01">
   <owner>vakh@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -2333,7 +2333,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.V4ProcessPartialUpdate.ApplyUpdateDuration"
-    units="ms" expires_after="2022-10-30">
+    units="ms" expires_after="2023-01-01">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -2416,7 +2416,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.V4ReadFromDisk.VerifyChecksumDuration" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -2618,7 +2618,7 @@
 </histogram>
 
 <histogram name="SafeBrowsingBinaryUploadRequest.TimeToGetFCMToken" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/sb_client/histograms.xml b/tools/metrics/histograms/metadata/sb_client/histograms.xml
index 4658523..66795f2 100644
--- a/tools/metrics/histograms/metadata/sb_client/histograms.xml
+++ b/tools/metrics/histograms/metadata/sb_client/histograms.xml
@@ -242,7 +242,7 @@
 </histogram>
 
 <histogram name="SBClientDownload.DownloadRequestResponseCode"
-    enum="HttpResponseCode" expires_after="2022-10-30">
+    enum="HttpResponseCode" expires_after="2023-01-01">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <owner>mattm@chromium.org</owner>
@@ -562,7 +562,7 @@
 </histogram>
 
 <histogram name="SBClientPhishing.Classifier.Event"
-    enum="SBPhishingClassifierEvent" expires_after="2022-10-30">
+    enum="SBPhishingClassifierEvent" expires_after="2023-01-01">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -719,7 +719,7 @@
 </histogram>
 
 <histogram name="SBClientPhishing.PhishingDetectionDuration" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/search/histograms.xml b/tools/metrics/histograms/metadata/search/histograms.xml
index 1b76150..21e3c23 100644
--- a/tools/metrics/histograms/metadata/search/histograms.xml
+++ b/tools/metrics/histograms/metadata/search/histograms.xml
@@ -754,7 +754,7 @@
 </histogram>
 
 <histogram name="Search.ContextualSearchPromoCardChoice" enum="BooleanOptedIn"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>donnd@chromium.org</owner>
   <owner>contextual-search-eng@google.com</owner>
   <summary>
@@ -1335,7 +1335,7 @@
 </histogram>
 
 <histogram name="Search.QueryTiles.Fetcher.FirstFlowDuration" units="hours"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>qinmin@chromium.org</owner>
   <owner>chrome-upboarding-eng@google.com</owner>
   <summary>
@@ -1345,14 +1345,14 @@
 </histogram>
 
 <histogram name="Search.QueryTiles.Fetcher.Start" units="hours"
-    expires_after="2022-10-31">
+    expires_after="2023-01-01">
   <owner>qinmin@chromium.org</owner>
   <owner>chrome-upboarding-eng@google.com</owner>
   <summary>Records the hour (0-23) when the TileFetcher task starts.</summary>
 </histogram>
 
 <histogram name="Search.QueryTiles.FetcherHttpResponseCode"
-    enum="HttpResponseCode" expires_after="2022-10-31">
+    enum="HttpResponseCode" expires_after="2023-01-01">
   <owner>qinmin@chromium.org</owner>
   <owner>chrome-upboarding-eng@google.com</owner>
   <summary>Records the HTTP response code get from TileFetcher.</summary>
@@ -1495,7 +1495,7 @@
 </histogram>
 
 <histogram name="Search.QueryTiles.TrendingTileEvent" enum="TrendingTileEvent"
-    expires_after="2022-10-31">
+    expires_after="2023-01-01">
   <owner>qinmin@chromium.org</owner>
   <owner>chrome-upboarding-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/security/histograms.xml b/tools/metrics/histograms/metadata/security/histograms.xml
index c9007e6..79a5759d 100644
--- a/tools/metrics/histograms/metadata/security/histograms.xml
+++ b/tools/metrics/histograms/metadata/security/histograms.xml
@@ -157,7 +157,7 @@
 </histogram>
 
 <histogram name="Security.HttpsFirstMode.SettingChanged" enum="BooleanEnabled"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>cthomp@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
   <summary>
@@ -179,7 +179,7 @@
 </histogram>
 
 <histogram name="Security.JSONParser.ChromiumExtensionUsage"
-    enum="JsonParserExtension" expires_after="2022-10-30">
+    enum="JsonParserExtension" expires_after="2023-01-01">
   <owner>rsesek@chromium.org</owner>
   <owner>chrome-platform-security@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
index 24099f3..e6e1793 100644
--- a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
+++ b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
@@ -82,7 +82,7 @@
 </histogram>
 
 <histogram name="SegmentationPlatform.AdaptiveToolbar.SegmentSelected.Startup"
-    enum="AdaptiveToolbarButtonVariant" expires_after="2022-10-30">
+    enum="AdaptiveToolbarButtonVariant" expires_after="2023-01-01">
   <owner>shaktisahu@chromium.org</owner>
   <owner>chrome-segmentation-platform@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/session/histograms.xml b/tools/metrics/histograms/metadata/session/histograms.xml
index 0ae7ce1..29d7db2d 100644
--- a/tools/metrics/histograms/metadata/session/histograms.xml
+++ b/tools/metrics/histograms/metadata/session/histograms.xml
@@ -391,7 +391,7 @@
 </histogram>
 
 <histogram name="Session.TotalDuration.TouchMode" units="times"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>collinbaker@chromium.org</owner>
   <owner>chrome-desktop-ui-sea@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/settings/histograms.xml b/tools/metrics/histograms/metadata/settings/histograms.xml
index 380c91b..fefca39 100644
--- a/tools/metrics/histograms/metadata/settings/histograms.xml
+++ b/tools/metrics/histograms/metadata/settings/histograms.xml
@@ -23,7 +23,7 @@
 <histograms>
 
 <histogram name="Settings.AdvancedSpellcheck.OnStartup" enum="BooleanEnabled"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>harrisonsean@chromium.org</owner>
   <owner>chrome-friendly-settings@google.com</owner>
   <summary>
@@ -109,7 +109,7 @@
 </histogram>
 
 <histogram name="Settings.Homepage.LocationType" enum="HomepageLocationType"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>bttk@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <owner>wenyufu@chromium.org</owner>
@@ -261,7 +261,7 @@
 </histogram>
 
 <histogram name="Settings.PrivacySandbox.Enabled"
-    enum="SettingsPrivacySandboxEnabled" expires_after="2022-10-30">
+    enum="SettingsPrivacySandboxEnabled" expires_after="2023-01-01">
   <owner>harrisonsean@chromium.org</owner>
   <owner>msramek@chromium.org</owner>
   <owner>chrome-friendly-settings@google.com</owner>
@@ -312,7 +312,7 @@
 </histogram>
 
 <histogram name="Settings.SafetyCheck.ChromeCleanerResult"
-    enum="SafetyCheckChromeCleanerStatus" expires_after="2022-10-30">
+    enum="SafetyCheckChromeCleanerStatus" expires_after="2023-01-01">
   <owner>rainhard@chromium.org</owner>
   <owner>msramek@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/sharing/histograms.xml b/tools/metrics/histograms/metadata/sharing/histograms.xml
index a88aaaa8..abde38a51 100644
--- a/tools/metrics/histograms/metadata/sharing/histograms.xml
+++ b/tools/metrics/histograms/metadata/sharing/histograms.xml
@@ -104,7 +104,7 @@
 </histogram>
 
 <histogram name="Sharing.ClickToCallSelectedAppIndex" units="index"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
 <!-- Name completed by histogram_suffixes name="SharingClickToCallUi" -->
 
   <owner>mvanouwerkerk@chromium.org</owner>
@@ -116,7 +116,7 @@
 </histogram>
 
 <histogram name="Sharing.ClickToCallSelectedDeviceIndex" units="index"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
 <!-- Name completed by histogram_suffixes name="SharingClickToCallUi" -->
 
   <owner>mvanouwerkerk@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/signin/histograms.xml b/tools/metrics/histograms/metadata/signin/histograms.xml
index 7fa97dae..86858ae 100644
--- a/tools/metrics/histograms/metadata/signin/histograms.xml
+++ b/tools/metrics/histograms/metadata/signin/histograms.xml
@@ -210,7 +210,7 @@
 </histogram>
 
 <histogram name="Signin.AndroidAccountInfoFetchTime" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>aliceywang@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
   <summary>
@@ -221,7 +221,7 @@
 </histogram>
 
 <histogram name="Signin.AndroidDeviceAccountsNumberWhenEnteringFRE"
-    units="count" expires_after="2022-10-30">
+    units="count" expires_after="2023-01-01">
   <owner>bsazonov@chromium.org</owner>
   <owner>aliceywang@chromium.org</owner>
   <summary>
@@ -240,7 +240,7 @@
 </histogram>
 
 <histogram base="true" name="Signin.AndroidGetAccountsTime" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>alexilin@chromium.org</owner>
   <owner>bsazonov@chromium.org</owner>
   <summary>
@@ -589,7 +589,7 @@
 </histogram>
 
 <histogram name="Signin.IOSGaiaCookieStateOnSignedInNavigation"
-    enum="GaiaCookieStateOnSignedInNavigation" expires_after="2022-08-14">
+    enum="GaiaCookieStateOnSignedInNavigation" expires_after="2023-04-01">
   <owner>jlebel@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/software/histograms.xml b/tools/metrics/histograms/metadata/software/histograms.xml
index ab06cac2..8b4f7d947 100644
--- a/tools/metrics/histograms/metadata/software/histograms.xml
+++ b/tools/metrics/histograms/metadata/software/histograms.xml
@@ -268,7 +268,7 @@
 </histogram>
 
 <histogram name="SoftwareReporter.NoPromptReason"
-    enum="SoftwareReporterNoPromptReason" expires_after="2022-10-30">
+    enum="SoftwareReporterNoPromptReason" expires_after="2023-01-01">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -302,7 +302,7 @@
 </histogram>
 
 <histogram name="SoftwareReporter.PromptDialogResponse"
-    enum="SoftwareReporterPromptDialogResponse" expires_after="2022-10-30">
+    enum="SoftwareReporterPromptDialogResponse" expires_after="2023-01-01">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/stability/histograms.xml b/tools/metrics/histograms/metadata/stability/histograms.xml
index 22d734b2..e390e8b9 100644
--- a/tools/metrics/histograms/metadata/stability/histograms.xml
+++ b/tools/metrics/histograms/metadata/stability/histograms.xml
@@ -111,7 +111,7 @@
 </histogram>
 
 <histogram name="Stability.Android.RendererCrash" enum="Boolean"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>wnwen@chromium.org</owner>
   <summary>
     Counts renderer crashes including OOMs. Android only. Mirrors old stability
diff --git a/tools/metrics/histograms/metadata/startup/histograms.xml b/tools/metrics/histograms/metadata/startup/histograms.xml
index 4f0813c1..ae60bfc3 100644
--- a/tools/metrics/histograms/metadata/startup/histograms.xml
+++ b/tools/metrics/histograms/metadata/startup/histograms.xml
@@ -259,7 +259,7 @@
 </histogram>
 
 <histogram base="true" name="Startup.Android.FirstDrawCompletedTime" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
 <!-- Name completed by histogram_suffixes name="JavaStartMode" -->
 
   <owner>hanxi@chromium.org</owner>
@@ -427,7 +427,7 @@
 </histogram>
 
 <histogram name="Startup.BrowserMainRunnerImplInitializeLongTime" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>robliao@chromium.org</owner>
   <summary>
     The amount of time that elapsed during BrowserMainRunnerImpl::Initialize.
@@ -908,7 +908,7 @@
 </histogram>
 
 <histogram name="Startup.Temperature" enum="StartupTemperature"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
 <!-- expires-after: Diagnosis metric for changes in StartupTemperature suffix.
      Shouldn't truly expire but kColdStartHardFaultCountThreshold should be
      surveyed yearly. -->
diff --git a/tools/metrics/histograms/metadata/subresource/histograms.xml b/tools/metrics/histograms/metadata/subresource/histograms.xml
index 1a53497..21f47fe 100644
--- a/tools/metrics/histograms/metadata/subresource/histograms.xml
+++ b/tools/metrics/histograms/metadata/subresource/histograms.xml
@@ -353,7 +353,7 @@
 </histogram>
 
 <histogram name="SubresourceFilter.IndexRuleset.Verify.Status"
-    enum="SubresourceFilterVerifyStatus" expires_after="2022-10-30">
+    enum="SubresourceFilterVerifyStatus" expires_after="2023-01-01">
   <owner>alexmt@chromium.org</owner>
   <owner>chrome-ads-histograms@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/sync/histograms.xml b/tools/metrics/histograms/metadata/sync/histograms.xml
index 77d255b..f36bd6f1 100644
--- a/tools/metrics/histograms/metadata/sync/histograms.xml
+++ b/tools/metrics/histograms/metadata/sync/histograms.xml
@@ -165,7 +165,7 @@
 </histogram>
 
 <histogram name="Sync.BookmarksModelMetadataCorruptionReason"
-    enum="SyncBookmarkModelMetadataCorruptionReason" expires_after="2022-10-30">
+    enum="SyncBookmarkModelMetadataCorruptionReason" expires_after="2023-01-01">
   <owner>rushans@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -219,7 +219,7 @@
 </histogram>
 
 <histogram name="Sync.ConfigureDataTypes" enum="SyncModelTypes"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>mastiz@chromium.org</owner>
   <owner>treib@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -255,7 +255,7 @@
 <histogram
     name="Sync.Crypto.CustomPassphraseKeyDerivationMethodOnSuccessfulDecryption"
     enum="SyncCustomPassphraseKeyDerivationMethodState"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>mmoskvitin@google.com</owner>
   <owner>treib@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -270,7 +270,7 @@
 
 <histogram name="Sync.Crypto.CustomPassphraseKeyDerivationMethodStateOnStartup"
     enum="SyncCustomPassphraseKeyDerivationMethodState"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>mmoskvitin@google.com</owner>
   <owner>treib@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -359,7 +359,7 @@
 </histogram>
 
 <histogram name="Sync.DataTypeRunFailures2" enum="SyncModelTypes"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>rushans@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -372,7 +372,7 @@
 </histogram>
 
 <histogram name="Sync.DataTypeStartFailures2" enum="SyncModelTypes"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>rushans@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -456,7 +456,7 @@
 </histogram>
 
 <histogram name="Sync.InitialState" enum="SyncInitialState"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>treib@chromium.org</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml
index 76efaa66..7acdbd5 100644
--- a/tools/metrics/histograms/metadata/tab/histograms.xml
+++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -786,7 +786,7 @@
 </histogram>
 
 <histogram name="TabGroups.UserGroupCount" units="groups"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>yusufo@chromium.org</owner>
   <owner>wychen@chromium.org</owner>
   <summary>
@@ -806,7 +806,7 @@
 </histogram>
 
 <histogram name="TabGroups.UserNamedGroupCount" units="groups"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>yusufo@chromium.org</owner>
   <owner>wychen@chromium.org</owner>
   <summary>
@@ -1529,7 +1529,7 @@
   </summary>
 </histogram>
 
-<histogram name="Tabs.CountAtStartup" units="tabs" expires_after="2022-10-30">
+<histogram name="Tabs.CountAtStartup" units="tabs" expires_after="2023-01-01">
   <owner>marq@chromium.org</owner>
   <summary>[Android and iOS] The number of tabs open at cold launch.</summary>
 </histogram>
@@ -1938,7 +1938,7 @@
 </histogram>
 
 <histogram name="Tabs.SadTab.Feedback.Event" enum="SadTabEvent"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>sonnyrao@chromium.org</owner>
   <owner>jamescook@chromium.org</owner>
   <summary>
@@ -1994,7 +1994,7 @@
 </histogram>
 
 <histogram name="Tabs.ScrubbedInInterval.KeyPress" units="tabs"
-    expires_after="2022-09-01">
+    expires_after="2023-01-01">
   <owner>corising@chromium.org</owner>
   <owner>chrome-desktop-ui-sea@google.com</owner>
   <summary>
@@ -2006,7 +2006,7 @@
 </histogram>
 
 <histogram name="Tabs.ScrubbedInInterval.MousePress" units="tabs"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>corising@chromium.org</owner>
   <owner>chrome-desktop-ui-sea@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/translate/histograms.xml b/tools/metrics/histograms/metadata/translate/histograms.xml
index 7a86daf..eb57492 100644
--- a/tools/metrics/histograms/metadata/translate/histograms.xml
+++ b/tools/metrics/histograms/metadata/translate/histograms.xml
@@ -1056,7 +1056,7 @@
 
 <histogram
     name="TranslateModelService.LanguageDetectionModel.PendingRequestCallbacks"
-    units="requests" expires_after="2022-09-11">
+    units="requests" expires_after="2023-01-01">
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-language@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/uma/histograms.xml b/tools/metrics/histograms/metadata/uma/histograms.xml
index 741a378e..282b9e8 100644
--- a/tools/metrics/histograms/metadata/uma/histograms.xml
+++ b/tools/metrics/histograms/metadata/uma/histograms.xml
@@ -773,7 +773,7 @@
 </histogram>
 
 <histogram name="UMA.StartupVisibility" enum="StartupVisibility"
-    expires_after="2022-11-01">
+    expires_after="2023-01-01">
   <owner>caitlinfischer@google.com</owner>
   <owner>src/base/metrics/OWNERS</owner>
   <summary>
@@ -815,7 +815,7 @@
 </histogram>
 
 <histogram name="UMA.StructuredMetrics.InternalError2"
-    enum="StructuredMetricsInternalError2" expires_after="2022-11-01">
+    enum="StructuredMetricsInternalError2" expires_after="2023-01-01">
   <owner>tby@chromium.org</owner>
   <owner>rkaplow@chromium.org</owner>
   <owner>asvitkine@chromium.org</owner>
@@ -859,7 +859,7 @@
 </histogram>
 
 <histogram name="UMA.TruncatedEvents.UserAction" units="events"
-    expires_after="2022-12-25">
+    expires_after="2023-01-01">
   <owner>rkaplow@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/v8/histograms.xml b/tools/metrics/histograms/metadata/v8/histograms.xml
index 79bffe02..9a37488 100644
--- a/tools/metrics/histograms/metadata/v8/histograms.xml
+++ b/tools/metrics/histograms/metadata/v8/histograms.xml
@@ -111,7 +111,7 @@
 </histogram>
 
 <histogram name="V8.CompileLazyMicroSeconds" units="microseconds"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>hablich@chromium.org</owner>
   <summary>
     Aggregated time spent compiling functions lazily during a single script
@@ -359,7 +359,7 @@
 </histogram>
 
 <histogram name="V8.ExecuteMicroSeconds" units="microseconds"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>cbruni@chromium.org</owner>
   <owner>v8-runtime@google.com</owner>
   <summary>
@@ -1413,7 +1413,7 @@
 </histogram>
 
 <histogram name="V8.RegExpBacktracks" units="backtracks"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>jgruber@chromium.org</owner>
   <owner>mvstanton@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/web_apk/histograms.xml b/tools/metrics/histograms/metadata/web_apk/histograms.xml
index 680a139..51298df 100644
--- a/tools/metrics/histograms/metadata/web_apk/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_apk/histograms.xml
@@ -96,7 +96,7 @@
 </histogram>
 
 <histogram name="WebApk.Install.InstallEvent" enum="WebApkInstallEvent"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>hartmanng@chromium.org</owner>
   <owner>
     src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
diff --git a/tools/metrics/histograms/metadata/web_audio/histograms.xml b/tools/metrics/histograms/metadata/web_audio/histograms.xml
index fdedf3eb..784623b 100644
--- a/tools/metrics/histograms/metadata/web_audio/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_audio/histograms.xml
@@ -276,7 +276,7 @@
 </histogram>
 
 <histogram name="WebAudio.PushPullFIFO.UnderflowGlitches" enum="Boolean"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>hongchan@chromium.org</owner>
   <owner>mjwilson@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/web_core/histograms.xml b/tools/metrics/histograms/metadata/web_core/histograms.xml
index b6c8370..1597c2a 100644
--- a/tools/metrics/histograms/metadata/web_core/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_core/histograms.xml
@@ -68,7 +68,7 @@
 </histogram>
 
 <histogram name="WebCore.FindInPage.DurationBetweenKeystrokes" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>jarhar@chromium.org</owner>
   <owner>vmpstr@chromium.org</owner>
   <summary>
@@ -107,7 +107,7 @@
 </histogram>
 
 <histogram name="WebCore.FindInPage.TaskDuration" units="ms"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>rakina@chromium.org</owner>
   <owner>altimin@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/web_rtc/histograms.xml b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
index b5806d7..4e60e94 100644
--- a/tools/metrics/histograms/metadata/web_rtc/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
@@ -922,14 +922,14 @@
 </histogram>
 
 <histogram name="WebRTC.BWE.InitiallyLostPackets" units="packets"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>holmer@chromium.org</owner>
   <summary>
     The number of video packets lost durig the first 2 seconds in a WebRTC call.
   </summary>
 </histogram>
 
-<histogram name="WebRTC.BWE.InitialRtt" units="ms" expires_after="2022-10-30">
+<histogram name="WebRTC.BWE.InitialRtt" units="ms" expires_after="2023-01-01">
   <owner>holmer@chromium.org</owner>
   <summary>
     The round-trip time as measured 2 seconds into a WebRTC call.
@@ -1062,7 +1062,7 @@
 </histogram>
 
 <histogram name="WebRTC.Call.AudioBitrateReceivedInKbps" units="kbps"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>holmer@chromium.org</owner>
   <summary>
     Average audio bitrate received during a call, counted from first packet
@@ -1092,7 +1092,7 @@
 </histogram>
 
 <histogram name="WebRTC.Call.LifetimeInSeconds" units="seconds"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>asapersson@chromium.org</owner>
   <summary>
     The lifetime of a call. Recorded when a Call instance is destroyed.
@@ -1110,7 +1110,7 @@
 </histogram>
 
 <histogram name="WebRTC.Call.RtcpBitrateReceivedInBps" units="bits/s"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>holmer@chromium.org</owner>
   <summary>
     Average RTCP bitrate received during a call, counted from first packet
@@ -1325,7 +1325,7 @@
 </histogram>
 
 <histogram name="WebRTC.PeerConnection.AddIceCandidate"
-    enum="AddIceCandidateResult" expires_after="2022-11-01">
+    enum="AddIceCandidateResult" expires_after="2023-01-01">
   <owner>hta@chromium.org</owner>
   <owner>webrtc-dev@chromium.org</owner>
   <summary>
@@ -1878,7 +1878,7 @@
 </histogram>
 
 <histogram name="WebRTC.PeerConnection.ThermalState" enum="ThermalState"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>eshr@google.com</owner>
   <owner>hbos@chromium.org</owner>
   <summary>
@@ -1928,7 +1928,7 @@
 </histogram>
 
 <histogram name="WebRTC.PeerConnection.UsagePattern"
-    enum="WebRtcPeerConnectionUsagePattern" expires_after="2022-10-30">
+    enum="WebRtcPeerConnectionUsagePattern" expires_after="2023-01-01">
   <owner>hta@chromium.org</owner>
   <owner>webrtc-dev@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/webapps/histograms.xml b/tools/metrics/histograms/metadata/webapps/histograms.xml
index ab142048..09a4aed 100644
--- a/tools/metrics/histograms/metadata/webapps/histograms.xml
+++ b/tools/metrics/histograms/metadata/webapps/histograms.xml
@@ -121,7 +121,7 @@
 </histogram>
 
 <histogram name="Launch.HomeScreenSource" enum="LaunchFromHomeScreenSource"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>dominickn@chromium.org</owner>
   <owner>hartmanng@chromium.org</owner>
   <owner>peconn@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/webauthn/histograms.xml b/tools/metrics/histograms/metadata/webauthn/histograms.xml
index e6e28196..1c6035e3 100644
--- a/tools/metrics/histograms/metadata/webauthn/histograms.xml
+++ b/tools/metrics/histograms/metadata/webauthn/histograms.xml
@@ -180,7 +180,7 @@
 </histogram>
 
 <histogram name="WebAuthentication.GetAssertionRequestTransport"
-    enum="WebAuthenticationFidoTransport" expires_after="2022-10-30">
+    enum="WebAuthenticationFidoTransport" expires_after="2023-01-01">
   <owner>kenrb@chromium.org</owner>
   <owner>martinkr@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/windows/histograms.xml b/tools/metrics/histograms/metadata/windows/histograms.xml
index 67b4fa3..6ca0315b 100644
--- a/tools/metrics/histograms/metadata/windows/histograms.xml
+++ b/tools/metrics/histograms/metadata/windows/histograms.xml
@@ -89,7 +89,7 @@
 </histogram>
 
 <histogram name="Windows.HighResolutionTimerUsage" units="%"
-    expires_after="2022-10-30">
+    expires_after="2023-01-01">
   <owner>olivierli@chromium.org</owner>
   <owner>catan-team@chromium.org</owner>
   <summary>
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index a620aee..cd6bb60 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -69,10 +69,14 @@
 crbug.com/1337486 [ mac ] desktop_ui/tab_search:top10:loading:2020 [ Skip ]
 crbug.com/1337486 [ mac ] desktop_ui/tab_search:top50:2020 [ Skip ]
 crbug.com/1337486 [ mac ] desktop_ui/tab_search:top50:loading:2020 [ Skip ]
+crbug.com/1267328 [ chromeos ] desktop_ui/side_search:navigation [ Skip ]
+crbug.com/1267328 [ chromeos ] desktop_ui/tab_search:top10:2020 [ Skip ]
 
 # Benchmark: blink_perf.webcodecs
 crbug.com/1300680 [ android ] blink_perf.webcodecs/software-video-encoding.html [ Skip ]
 crbug.com/1301260 [ linux ] blink_perf.webcodecs/hardware-video-encoding.html [ Skip ]
+crbug.com/1341919 [ chromeos ] blink_perf.webcodecs/hardware-video-encoding.html [ Skip ]
+crbug.com/1341919 [ win ] blink_perf.webcodecs/hardware-video-encoding.html [ Skip ]
 
 # Benchmark: blink_perf.webgl
 crbug.com/1341884 [ linux ] blink_perf.webgl_fast_call/binding-buffer-sub-data.html [ Skip ]