Migrate chrome.login extension API to crosapi

This CL migrates the chrome.login extension API to crosapi so that it
can be called from both Ash-Chrome and LaCros. The respective API
methods are re-defined in chromeos/crosapi/mojom/login.mojom.
login_api.cc is now a thin layer which forwards the API calls to either
crosapi or the Login remote respectively.

BUG=b:199865661

Change-Id: I5c9a113dd98cfdc5f39125dc66a8cfa1a0f9a195
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3359741
Reviewed-by: Dominic Battré <[email protected]>
Reviewed-by: Erik Chen <[email protected]>
Reviewed-by: Devlin Cronin <[email protected]>
Reviewed-by: Alexander Hendrich <[email protected]>
Commit-Queue: Jit Yao Yap <[email protected]>
Cr-Commit-Position: refs/heads/main@{#965710}
diff --git a/chrome/browser/ash/crosapi/BUILD.gn b/chrome/browser/ash/crosapi/BUILD.gn
index fcc6c04..0f23c795 100644
--- a/chrome/browser/ash/crosapi/BUILD.gn
+++ b/chrome/browser/ash/crosapi/BUILD.gn
@@ -108,6 +108,8 @@
     "lacros_availability_policy_observer.h",
     "local_printer_ash.cc",
     "local_printer_ash.h",
+    "login_ash.cc",
+    "login_ash.h",
     "login_state_ash.cc",
     "login_state_ash.h",
     "message_center_ash.cc",
diff --git a/chrome/browser/ash/crosapi/browser_util.cc b/chrome/browser/ash/crosapi/browser_util.cc
index b4def30..73f0afbe 100644
--- a/chrome/browser/ash/crosapi/browser_util.cc
+++ b/chrome/browser/ash/crosapi/browser_util.cc
@@ -253,7 +253,7 @@
 }
 
 static_assert(
-    crosapi::mojom::Crosapi::Version_ == 62,
+    crosapi::mojom::Crosapi::Version_ == 63,
     "if you add a new crosapi, please add it to kInterfaceVersionEntries");
 
 }  // namespace
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.cc b/chrome/browser/ash/crosapi/crosapi_ash.cc
index e510fe5c..5d2c555 100644
--- a/chrome/browser/ash/crosapi/crosapi_ash.cc
+++ b/chrome/browser/ash/crosapi/crosapi_ash.cc
@@ -46,6 +46,7 @@
 #include "chrome/browser/ash/crosapi/keystore_service_ash.h"
 #include "chrome/browser/ash/crosapi/kiosk_session_service_ash.h"
 #include "chrome/browser/ash/crosapi/local_printer_ash.h"
+#include "chrome/browser/ash/crosapi/login_ash.h"
 #include "chrome/browser/ash/crosapi/login_state_ash.h"
 #include "chrome/browser/ash/crosapi/message_center_ash.h"
 #include "chrome/browser/ash/crosapi/metrics_reporting_ash.h"
@@ -152,6 +153,7 @@
       keystore_service_ash_(std::make_unique<KeystoreServiceAsh>()),
       kiosk_session_service_ash_(std::make_unique<KioskSessionServiceAsh>()),
       local_printer_ash_(std::make_unique<LocalPrinterAsh>()),
+      login_ash_(std::make_unique<LoginAsh>()),
       login_state_ash_(std::make_unique<LoginStateAsh>()),
       message_center_ash_(std::make_unique<MessageCenterAsh>()),
       metrics_reporting_ash_(std::make_unique<MetricsReportingAsh>(
@@ -341,6 +343,11 @@
   local_printer_ash_->BindReceiver(std::move(receiver));
 }
 
+void CrosapiAsh::BindLogin(
+    mojo::PendingReceiver<crosapi::mojom::Login> receiver) {
+  login_ash_->BindReceiver(std::move(receiver));
+}
+
 void CrosapiAsh::BindLoginState(
     mojo::PendingReceiver<crosapi::mojom::LoginState> receiver) {
   login_state_ash_->BindReceiver(std::move(receiver));
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.h b/chrome/browser/ash/crosapi/crosapi_ash.h
index b1bfa052..a96ab0f 100644
--- a/chrome/browser/ash/crosapi/crosapi_ash.h
+++ b/chrome/browser/ash/crosapi/crosapi_ash.h
@@ -49,6 +49,7 @@
 class KeystoreServiceAsh;
 class KioskSessionServiceAsh;
 class LocalPrinterAsh;
+class LoginAsh;
 class LoginStateAsh;
 class MessageCenterAsh;
 class MetricsReportingAsh;
@@ -154,6 +155,7 @@
       mojo::PendingReceiver<mojom::KioskSessionService> receiver) override;
   void BindLocalPrinter(
       mojo::PendingReceiver<mojom::LocalPrinter> receiver) override;
+  void BindLogin(mojo::PendingReceiver<mojom::Login> receiver) override;
   void BindLoginState(
       mojo::PendingReceiver<mojom::LoginState> receiver) override;
   void BindMessageCenter(
@@ -266,6 +268,8 @@
     return keystore_service_ash_.get();
   }
 
+  LoginAsh* login_ash() { return login_ash_.get(); }
+
   LoginStateAsh* login_state_ash() { return login_state_ash_.get(); }
 
   StructuredMetricsServiceAsh* structured_metrics_service_ash() {
@@ -305,6 +309,7 @@
   std::unique_ptr<KeystoreServiceAsh> keystore_service_ash_;
   std::unique_ptr<KioskSessionServiceAsh> kiosk_session_service_ash_;
   std::unique_ptr<LocalPrinterAsh> local_printer_ash_;
+  std::unique_ptr<LoginAsh> login_ash_;
   std::unique_ptr<LoginStateAsh> login_state_ash_;
   std::unique_ptr<MessageCenterAsh> message_center_ash_;
   std::unique_ptr<MetricsReportingAsh> metrics_reporting_ash_;
diff --git a/chrome/browser/ash/crosapi/crosapi_util.cc b/chrome/browser/ash/crosapi/crosapi_util.cc
index 2b2873a..184628d 100644
--- a/chrome/browser/ash/crosapi/crosapi_util.cc
+++ b/chrome/browser/ash/crosapi/crosapi_util.cc
@@ -54,6 +54,7 @@
 #include "chromeos/crosapi/mojom/kiosk_session_service.mojom.h"
 #include "chromeos/crosapi/mojom/launcher_search.mojom.h"
 #include "chromeos/crosapi/mojom/local_printer.mojom.h"
+#include "chromeos/crosapi/mojom/login.mojom.h"
 #include "chromeos/crosapi/mojom/login_state.mojom.h"
 #include "chromeos/crosapi/mojom/message_center.mojom.h"
 #include "chromeos/crosapi/mojom/metrics_reporting.mojom.h"
@@ -182,6 +183,7 @@
     MakeInterfaceVersionEntry<crosapi::mojom::KeystoreService>(),
     MakeInterfaceVersionEntry<crosapi::mojom::KioskSessionService>(),
     MakeInterfaceVersionEntry<crosapi::mojom::LocalPrinter>(),
+    MakeInterfaceVersionEntry<crosapi::mojom::Login>(),
     MakeInterfaceVersionEntry<crosapi::mojom::LoginState>(),
     MakeInterfaceVersionEntry<
         chromeos::machine_learning::mojom::MachineLearningService>(),
diff --git a/chrome/browser/ash/crosapi/login_ash.cc b/chrome/browser/ash/crosapi/login_ash.cc
new file mode 100644
index 0000000..6f3a7b6e
--- /dev/null
+++ b/chrome/browser/ash/crosapi/login_ash.cc
@@ -0,0 +1,246 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/crosapi/login_ash.h"
+
+#include "ash/components/login/auth/user_context.h"
+#include "chrome/browser/ash/login/existing_user_controller.h"
+#include "chrome/browser/ash/profiles/profile_helper.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/extensions/login_screen/login/errors.h"
+#include "chrome/browser/chromeos/extensions/login_screen/login/login_api_lock_handler.h"
+#include "chrome/browser/chromeos/extensions/login_screen/login/shared_session_handler.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/common/pref_names.h"
+#include "chromeos/crosapi/mojom/login.mojom.h"
+#include "components/session_manager/core/session_manager.h"
+#include "components/user_manager/user.h"
+#include "components/user_manager/user_manager.h"
+#include "components/user_manager/user_type.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/base/user_activity/user_activity_detector.h"
+
+namespace crosapi {
+
+LoginAsh::LoginAsh() = default;
+LoginAsh::~LoginAsh() = default;
+
+void LoginAsh::BindReceiver(mojo::PendingReceiver<mojom::Login> receiver) {
+  receivers_.Add(this, std::move(receiver));
+}
+
+void LoginAsh::LaunchManagedGuestSession(
+    const absl::optional<std::string>& password,
+    LaunchManagedGuestSessionCallback callback) {
+  ui::UserActivityDetector::Get()->HandleExternalUserActivity();
+
+  if (session_manager::SessionManager::Get()->session_state() !=
+      session_manager::SessionState::LOGIN_PRIMARY) {
+    std::move(callback).Run(
+        extensions::login_api_errors::kAlreadyActiveSession);
+    return;
+  }
+
+  auto* existing_user_controller =
+      ash::ExistingUserController::current_controller();
+  if (existing_user_controller->IsSigninInProgress()) {
+    std::move(callback).Run(
+        extensions::login_api_errors::kAnotherLoginAttemptInProgress);
+    return;
+  }
+
+  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
+  for (const user_manager::User* user : user_manager->GetUsers()) {
+    if (!user || user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT)
+      continue;
+    ash::UserContext context(user_manager::USER_TYPE_PUBLIC_ACCOUNT,
+                             user->GetAccountId());
+    if (password) {
+      context.SetKey(chromeos::Key(*password));
+      context.SetCanLockManagedGuestSession(true);
+    }
+
+    existing_user_controller->Login(context, ash::SigninSpecifics());
+    std::move(callback).Run(absl::nullopt);
+    return;
+  }
+  std::move(callback).Run(
+      extensions::login_api_errors::kNoManagedGuestSessionAccounts);
+}
+
+void LoginAsh::ExitCurrentSession(
+    const absl::optional<std::string>& data_for_next_login_attempt,
+    ExitCurrentSessionCallback callback) {
+  PrefService* local_state = g_browser_process->local_state();
+  DCHECK(local_state);
+
+  if (data_for_next_login_attempt) {
+    local_state->SetString(prefs::kLoginExtensionApiDataForNextLoginAttempt,
+                           *data_for_next_login_attempt);
+  } else {
+    local_state->ClearPref(prefs::kLoginExtensionApiDataForNextLoginAttempt);
+  }
+
+  chrome::AttemptUserExit();
+  std::move(callback).Run(absl::nullopt);
+}
+
+void LoginAsh::FetchDataForNextLoginAttempt(
+    FetchDataForNextLoginAttemptCallback callback) {
+  PrefService* local_state = g_browser_process->local_state();
+  DCHECK(local_state);
+  std::string data_for_next_login_attempt =
+      local_state->GetString(prefs::kLoginExtensionApiDataForNextLoginAttempt);
+  local_state->ClearPref(prefs::kLoginExtensionApiDataForNextLoginAttempt);
+
+  std::move(callback).Run(data_for_next_login_attempt);
+}
+
+void LoginAsh::LockManagedGuestSession(
+    LockManagedGuestSessionCallback callback) {
+  ui::UserActivityDetector::Get()->HandleExternalUserActivity();
+
+  const user_manager::UserManager* user_manager =
+      user_manager::UserManager::Get();
+  const user_manager::User* active_user = user_manager->GetActiveUser();
+  if (!active_user ||
+      active_user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT ||
+      !user_manager->CanCurrentUserLock()) {
+    std::move(callback).Run(
+        extensions::login_api_errors::kNoLockableManagedGuestSession);
+    return;
+  }
+
+  if (session_manager::SessionManager::Get()->session_state() !=
+      session_manager::SessionState::ACTIVE) {
+    std::move(callback).Run(extensions::login_api_errors::kSessionIsNotActive);
+    return;
+  }
+
+  chromeos::LoginApiLockHandler::Get()->RequestLockScreen();
+  std::move(callback).Run(absl::nullopt);
+}
+
+void LoginAsh::UnlockManagedGuestSession(
+    const std::string& password,
+    UnlockManagedGuestSessionCallback callback) {
+  ui::UserActivityDetector::Get()->HandleExternalUserActivity();
+
+  const user_manager::UserManager* user_manager =
+      user_manager::UserManager::Get();
+  const user_manager::User* active_user = user_manager->GetActiveUser();
+  if (!active_user ||
+      active_user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT ||
+      !user_manager->CanCurrentUserLock()) {
+    std::move(callback).Run(
+        extensions::login_api_errors::kNoUnlockableManagedGuestSession);
+    return;
+  }
+
+  if (session_manager::SessionManager::Get()->session_state() !=
+      session_manager::SessionState::LOCKED) {
+    std::move(callback).Run(extensions::login_api_errors::kSessionIsNotLocked);
+    return;
+  }
+
+  chromeos::LoginApiLockHandler* handler = chromeos::LoginApiLockHandler::Get();
+  if (handler->IsUnlockInProgress()) {
+    std::move(callback).Run(
+        extensions::login_api_errors::kAnotherUnlockAttemptInProgress);
+    return;
+  }
+
+  ash::UserContext context(user_manager::USER_TYPE_PUBLIC_ACCOUNT,
+                           active_user->GetAccountId());
+  context.SetKey(chromeos::Key(password));
+  handler->Authenticate(
+      context, base::BindOnce(&LoginAsh::OnScreenLockerAuthenticate,
+                              weak_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void LoginAsh::LaunchSharedManagedGuestSession(
+    const std::string& password,
+    LaunchSharedManagedGuestSessionCallback callback) {
+  ui::UserActivityDetector::Get()->HandleExternalUserActivity();
+
+  absl::optional<std::string> error =
+      chromeos::SharedSessionHandler::Get()->LaunchSharedManagedGuestSession(
+          password);
+  if (error) {
+    std::move(callback).Run(error);
+    return;
+  }
+
+  std::move(callback).Run(absl::nullopt);
+}
+
+void LoginAsh::EnterSharedSession(const std::string& password,
+                                  EnterSharedSessionCallback callback) {
+  ui::UserActivityDetector::Get()->HandleExternalUserActivity();
+
+  chromeos::SharedSessionHandler::Get()->EnterSharedSession(
+      password,
+      base::BindOnce(&LoginAsh::OnOptionalErrorCallbackComplete,
+                     weak_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void LoginAsh::UnlockSharedSession(const std::string& password,
+                                   UnlockSharedSessionCallback callback) {
+  ui::UserActivityDetector::Get()->HandleExternalUserActivity();
+
+  const user_manager::UserManager* user_manager =
+      user_manager::UserManager::Get();
+  const user_manager::User* active_user = user_manager->GetActiveUser();
+  if (!active_user ||
+      active_user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT ||
+      !user_manager->CanCurrentUserLock()) {
+    std::move(callback).Run(
+        extensions::login_api_errors::kNoUnlockableManagedGuestSession);
+    return;
+  }
+
+  chromeos::SharedSessionHandler::Get()->UnlockSharedSession(
+      password,
+      base::BindOnce(&LoginAsh::OnOptionalErrorCallbackComplete,
+                     weak_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void LoginAsh::EndSharedSession(EndSharedSessionCallback callback) {
+  chromeos::SharedSessionHandler::Get()->EndSharedSession(
+      base::BindOnce(&LoginAsh::OnOptionalErrorCallbackComplete,
+                     weak_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void LoginAsh::SetDataForNextLoginAttempt(
+    const std::string& data_for_next_login_attempt,
+    SetDataForNextLoginAttemptCallback callback) {
+  PrefService* local_state = g_browser_process->local_state();
+  DCHECK(local_state);
+  local_state->SetString(prefs::kLoginExtensionApiDataForNextLoginAttempt,
+                         data_for_next_login_attempt);
+
+  std::move(callback).Run();
+}
+
+void LoginAsh::OnScreenLockerAuthenticate(
+    base::OnceCallback<void(const absl::optional<std::string>&)> callback,
+    bool success) {
+  if (!success) {
+    std::move(callback).Run(
+        extensions::login_api_errors::kAuthenticationFailed);
+    return;
+  }
+
+  std::move(callback).Run(absl::nullopt);
+}
+
+void LoginAsh::OnOptionalErrorCallbackComplete(
+    base::OnceCallback<void(const absl::optional<std::string>&)> callback,
+    absl::optional<std::string> error) {
+  std::move(callback).Run(error);
+}
+
+}  // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/login_ash.h b/chrome/browser/ash/crosapi/login_ash.h
new file mode 100644
index 0000000..add7289
--- /dev/null
+++ b/chrome/browser/ash/crosapi/login_ash.h
@@ -0,0 +1,66 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_CROSAPI_LOGIN_ASH_H_
+#define CHROME_BROWSER_ASH_CROSAPI_LOGIN_ASH_H_
+
+#include "base/memory/weak_ptr.h"
+#include "base/scoped_observation.h"
+#include "chromeos/crosapi/mojom/login.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+
+namespace crosapi {
+
+// The ash-chrome implementation of the Login crosapi interface.
+class LoginAsh : public mojom::Login {
+ public:
+  LoginAsh();
+  LoginAsh(const LoginAsh&) = delete;
+  LoginAsh& operator=(const LoginAsh&) = delete;
+  ~LoginAsh() override;
+
+  void BindReceiver(mojo::PendingReceiver<mojom::Login> receiver);
+
+  // crosapi::mojom::Login:
+  void LaunchManagedGuestSession(
+      const absl::optional<std::string>& password,
+      LaunchManagedGuestSessionCallback callback) override;
+  void ExitCurrentSession(
+      const absl::optional<std::string>& data_for_next_login_attempt,
+      ExitCurrentSessionCallback callback) override;
+  void FetchDataForNextLoginAttempt(
+      FetchDataForNextLoginAttemptCallback callback) override;
+  void LockManagedGuestSession(
+      LockManagedGuestSessionCallback callback) override;
+  void UnlockManagedGuestSession(
+      const std::string& password,
+      UnlockManagedGuestSessionCallback callback) override;
+  void LaunchSharedManagedGuestSession(
+      const std::string& password,
+      LaunchSharedManagedGuestSessionCallback callback) override;
+  void EnterSharedSession(const std::string& password,
+                          EnterSharedSessionCallback callback) override;
+  void UnlockSharedSession(const std::string& password,
+                           UnlockSharedSessionCallback callback) override;
+  void EndSharedSession(EndSharedSessionCallback callback) override;
+  void SetDataForNextLoginAttempt(
+      const std::string& data_for_next_login_attempt,
+      SetDataForNextLoginAttemptCallback callback) override;
+
+ private:
+  void OnScreenLockerAuthenticate(
+      base::OnceCallback<void(const absl::optional<std::string>&)> callback,
+      bool success);
+  void OnOptionalErrorCallbackComplete(
+      base::OnceCallback<void(const absl::optional<std::string>&)> callback,
+      absl::optional<std::string> error);
+
+  mojo::ReceiverSet<mojom::Login> receivers_;
+  base::WeakPtrFactory<LoginAsh> weak_factory_{this};
+};
+
+}  // namespace crosapi
+
+#endif  // CHROME_BROWSER_ASH_CROSAPI_LOGIN_ASH_H_
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 06a505b6..f99f4a4 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -3503,10 +3503,12 @@
     "extensions/login_screen/login/cleanup/open_windows_cleanup_handler.h",
     "extensions/login_screen/login/cleanup/print_jobs_cleanup_handler.cc",
     "extensions/login_screen/login/cleanup/print_jobs_cleanup_handler.h",
-    "extensions/login_screen/login/login_api.cc",
-    "extensions/login_screen/login/login_api.h",
+    "extensions/login_screen/login/errors.cc",
+    "extensions/login_screen/login/errors.h",
     "extensions/login_screen/login/login_api_lock_handler.cc",
     "extensions/login_screen/login/login_api_lock_handler.h",
+    "extensions/login_screen/login/prefs.cc",
+    "extensions/login_screen/login/prefs.h",
     "extensions/login_screen/login/shared_session_handler.cc",
     "extensions/login_screen/login/shared_session_handler.h",
     "extensions/login_screen/login_screen_storage/login_screen_storage_api.cc",
diff --git a/chrome/browser/chromeos/extensions/login_screen/BUILD.gn b/chrome/browser/chromeos/extensions/login_screen/BUILD.gn
index b14a54c..1a5b485 100644
--- a/chrome/browser/chromeos/extensions/login_screen/BUILD.gn
+++ b/chrome/browser/chromeos/extensions/login_screen/BUILD.gn
@@ -10,6 +10,8 @@
 
 source_set("login_screen") {
   sources = [
+    "login/login_api.cc",
+    "login/login_api.h",
     "login_state/login_state_api.cc",
     "login_state/login_state_api.h",
     "login_state/session_state_changed_event_dispatcher.cc",
@@ -36,6 +38,7 @@
   }
 }
 
+# TODO(jityao, b/215502706): Move tests back into chrome/test/BUILD.gn.
 source_set("browser_tests") {
   testonly = true
   defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/errors.cc b/chrome/browser/chromeos/extensions/login_screen/login/errors.cc
new file mode 100644
index 0000000..5472ae70
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/login_screen/login/errors.cc
@@ -0,0 +1,41 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/extensions/login_screen/login/errors.h"
+
+namespace extensions {
+
+namespace login_api_errors {
+
+const char kAlreadyActiveSession[] = "There is already an active session";
+const char kLoginScreenIsNotActive[] = "Login screen is not active";
+const char kAnotherLoginAttemptInProgress[] =
+    "Another login attempt is in progress";
+const char kNoManagedGuestSessionAccounts[] =
+    "No managed guest session accounts";
+const char kNoLockableManagedGuestSession[] =
+    "There is no lockable Managed Guest Session";
+const char kSessionIsNotActive[] = "Session is not active";
+const char kNoUnlockableManagedGuestSession[] =
+    "There is no unlockable Managed Guest Session";
+const char kSessionIsNotLocked[] = "Session is not locked";
+const char kAnotherUnlockAttemptInProgress[] =
+    "Another unlock attempt is in progress";
+const char kSharedMGSAlreadyLaunched[] =
+    "Shared Managed Guest Session has already been launched";
+const char kAuthenticationFailed[] = "Authentication failed";
+const char kNoSharedMGSFound[] = "No shared Managed Guest Session found";
+const char kSharedSessionIsNotActive[] = "Shared session is not active";
+const char kSharedSessionAlreadyLaunched[] =
+    "Another shared session has already been launched";
+const char kScryptFailure[] = "Scrypt failed";
+const char kCleanupInProgress[] = "Cleanup is already in progress";
+const char kUnlockFailure[] = "Managed Guest Session unlock failed";
+const char kDeviceRestrictedManagedGuestSessionNotEnabled[] =
+    "DeviceRestrictedManagedGuestSessionEnabled policy is not enabled for "
+    "shared kiosk mode";
+
+}  // namespace login_api_errors
+
+}  // namespace extensions
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/errors.h b/chrome/browser/chromeos/extensions/login_screen/login/errors.h
new file mode 100644
index 0000000..dfc92f8
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/login_screen/login/errors.h
@@ -0,0 +1,35 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_LOGIN_SCREEN_LOGIN_ERRORS_H_
+#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_LOGIN_SCREEN_LOGIN_ERRORS_H_
+
+namespace extensions {
+
+namespace login_api_errors {
+
+extern const char kAlreadyActiveSession[];
+extern const char kLoginScreenIsNotActive[];
+extern const char kAnotherLoginAttemptInProgress[];
+extern const char kNoManagedGuestSessionAccounts[];
+extern const char kNoLockableManagedGuestSession[];
+extern const char kSessionIsNotActive[];
+extern const char kNoUnlockableManagedGuestSession[];
+extern const char kSessionIsNotLocked[];
+extern const char kAnotherUnlockAttemptInProgress[];
+extern const char kAuthenticationFailed[];
+extern const char kSharedMGSAlreadyLaunched[];
+extern const char kNoSharedMGSFound[];
+extern const char kSharedSessionIsNotActive[];
+extern const char kSharedSessionAlreadyLaunched[];
+extern const char kScryptFailure[];
+extern const char kCleanupInProgress[];
+extern const char kUnlockFailure[];
+extern const char kDeviceRestrictedManagedGuestSessionNotEnabled[];
+
+}  // namespace login_api_errors
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_LOGIN_SCREEN_LOGIN_ERRORS_H_
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/login_api.cc b/chrome/browser/chromeos/extensions/login_screen/login/login_api.cc
index aa4017f..dc4e359c 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login/login_api.cc
+++ b/chrome/browser/chromeos/extensions/login_screen/login/login_api.cc
@@ -6,70 +6,78 @@
 
 #include <memory>
 #include <string>
+#include <utility>
 
-#include "ash/components/login/auth/key.h"
-#include "ash/components/login/auth/user_context.h"
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/values.h"
-#include "chrome/browser/ash/login/existing_user_controller.h"
-#include "chrome/browser/ash/login/signin_specifics.h"
-#include "chrome/browser/ash/profiles/profile_helper.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/extensions/login_screen/login/login_api_lock_handler.h"
-#include "chrome/browser/chromeos/extensions/login_screen/login/shared_session_handler.h"
-#include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/common/extensions/api/login.h"
-#include "chrome/common/pref_names.h"
-#include "components/prefs/pref_service.h"
-#include "components/session_manager/core/session_manager.h"
-#include "components/user_manager/user.h"
-#include "components/user_manager/user_manager.h"
-#include "components/user_manager/user_type.h"
-#include "ui/base/user_activity/user_activity_detector.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#include "chromeos/lacros/lacros_service.h"
+#else
+#include "chrome/browser/ash/crosapi/crosapi_ash.h"
+#include "chrome/browser/ash/crosapi/crosapi_manager.h"
+#include "chrome/browser/ash/crosapi/login_ash.h"
+#endif
 
 namespace extensions {
 
-namespace login_api {
+namespace {
 
-void RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
-  registry->RegisterStringPref(prefs::kLoginExtensionApiDataForNextLoginAttempt,
-                               "");
+crosapi::mojom::Login* GetLoginApi() {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  return chromeos::LacrosService::Get()
+      ->GetRemote<crosapi::mojom::Login>()
+      .get();
+#else
+  return crosapi::CrosapiManager::Get()->crosapi_ash()->login_ash();
+#endif
 }
 
-}  // namespace login_api
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+// Performs common crosapi validation. These errors are not caused by the
+// extension so they are considered recoverable. Returns an error message on
+// error, or nullopt on success.
+absl::optional<std::string> ValidateCrosapi() {
+  if (!chromeos::LacrosService::Get()->IsAvailable<crosapi::mojom::Login>()) {
+    return "Unsupported by ash";
+  }
+  return absl::nullopt;
+}
 
-namespace login_api_errors {
+const char kCannotBeCalledFromLacros[] = "API cannot be called from Lacros";
 
-const char kAlreadyActiveSession[] = "There is already an active session";
-const char kLoginScreenIsNotActive[] = "Login screen is not active";
-const char kAnotherLoginAttemptInProgress[] =
-    "Another login attempt is in progress";
-const char kNoManagedGuestSessionAccounts[] =
-    "No managed guest session accounts";
-const char kNoLockableManagedGuestSession[] =
-    "There is no lockable Managed Guest Session";
-const char kSessionIsNotActive[] = "Session is not active";
-const char kNoUnlockableManagedGuestSession[] =
-    "There is no unlockable Managed Guest Session";
-const char kSessionIsNotLocked[] = "Session is not locked";
-const char kAnotherUnlockAttemptInProgress[] =
-    "Another unlock attempt is in progress";
-const char kSharedMGSAlreadyLaunched[] =
-    "Shared Managed Guest Session has already been launched";
-const char kAuthenticationFailed[] = "Authentication failed";
-const char kNoSharedMGSFound[] = "No shared Managed Guest Session found";
-const char kSharedSessionIsNotActive[] = "Shared session is not active";
-const char kSharedSessionAlreadyLaunched[] =
-    "Another shared session has already been launched";
-const char kScryptFailure[] = "Scrypt failed";
-const char kCleanupInProgress[] = "Cleanup is already in progress";
-const char kUnlockFailure[] = "Managed Guest Session unlock failed";
-const char kDeviceRestrictedManagedGuestSessionNotEnabled[] =
-    "DeviceRestrictedManagedGuestSessionEnabled policy is not enabled for "
-    "shared kiosk mode";
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
 
-}  // namespace login_api_errors
+}  // namespace
+
+ExtensionFunctionWithOptionalErrorResult::
+    ~ExtensionFunctionWithOptionalErrorResult() = default;
+
+void ExtensionFunctionWithOptionalErrorResult::OnResult(
+    const absl::optional<std::string>& error) {
+  if (error) {
+    Respond(Error(*error));
+    return;
+  }
+
+  return Respond(NoArguments());
+}
+
+ExtensionFunctionWithStringResult::~ExtensionFunctionWithStringResult() =
+    default;
+
+void ExtensionFunctionWithStringResult::OnResult(const std::string& result) {
+  Respond(OneArgument(base::Value(result)));
+}
+
+ExtensionFunctionWithVoidResult::~ExtensionFunctionWithVoidResult() = default;
+
+void ExtensionFunctionWithVoidResult::OnResult() {
+  Respond(NoArguments());
+}
 
 LoginLaunchManagedGuestSessionFunction::
     LoginLaunchManagedGuestSessionFunction() = default;
@@ -78,59 +86,50 @@
 
 ExtensionFunction::ResponseAction
 LoginLaunchManagedGuestSessionFunction::Run() {
-  ui::UserActivityDetector::Get()->HandleExternalUserActivity();
-
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  return RespondNow(Error(kCannotBeCalledFromLacros));
+#else
   auto parameters =
       api::login::LaunchManagedGuestSession::Params::Create(args());
   EXTENSION_FUNCTION_VALIDATE(parameters);
 
-  if (session_manager::SessionManager::Get()->session_state() !=
-      session_manager::SessionState::LOGIN_PRIMARY) {
-    return RespondNow(Error(login_api_errors::kAlreadyActiveSession));
-  }
+  auto callback =
+      base::BindOnce(&LoginLaunchManagedGuestSessionFunction::OnResult, this);
 
-  auto* existing_user_controller =
-      ash::ExistingUserController::current_controller();
-  if (existing_user_controller->IsSigninInProgress()) {
-    return RespondNow(Error(login_api_errors::kAnotherLoginAttemptInProgress));
+  absl::optional<std::string> password;
+  if (parameters->password) {
+    password = std::move(*parameters->password);
   }
-
-  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
-  for (const user_manager::User* user : user_manager->GetUsers()) {
-    if (!user || user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT)
-      continue;
-    ash::UserContext context(user_manager::USER_TYPE_PUBLIC_ACCOUNT,
-                             user->GetAccountId());
-    if (parameters->password) {
-      context.SetKey(ash::Key(*parameters->password));
-      context.SetCanLockManagedGuestSession(true);
-    }
-
-    existing_user_controller->Login(context, ash::SigninSpecifics());
-    return RespondNow(NoArguments());
-  }
-  return RespondNow(Error(login_api_errors::kNoManagedGuestSessionAccounts));
+  GetLoginApi()->LaunchManagedGuestSession(password, std::move(callback));
+  return did_respond() ? AlreadyResponded() : RespondLater();
+#endif
 }
 
 LoginExitCurrentSessionFunction::LoginExitCurrentSessionFunction() = default;
 LoginExitCurrentSessionFunction::~LoginExitCurrentSessionFunction() = default;
 
 ExtensionFunction::ResponseAction LoginExitCurrentSessionFunction::Run() {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  absl::optional<std::string> error = ValidateCrosapi();
+  if (error.has_value()) {
+    return RespondNow(Error(error.value()));
+  }
+#endif
+
   auto parameters = api::login::ExitCurrentSession::Params::Create(args());
   EXTENSION_FUNCTION_VALIDATE(parameters);
 
-  PrefService* local_state = g_browser_process->local_state();
-  DCHECK(local_state);
+  auto callback =
+      base::BindOnce(&LoginExitCurrentSessionFunction::OnResult, this);
 
+  absl::optional<std::string> data_for_next_login_attempt;
   if (parameters->data_for_next_login_attempt) {
-    local_state->SetString(prefs::kLoginExtensionApiDataForNextLoginAttempt,
-                           *parameters->data_for_next_login_attempt);
-  } else {
-    local_state->ClearPref(prefs::kLoginExtensionApiDataForNextLoginAttempt);
+    data_for_next_login_attempt =
+        std::move(*parameters->data_for_next_login_attempt);
   }
-
-  chrome::AttemptUserExit();
-  return RespondNow(NoArguments());
+  GetLoginApi()->ExitCurrentSession(data_for_next_login_attempt,
+                                    std::move(callback));
+  return did_respond() ? AlreadyResponded() : RespondLater();
 }
 
 LoginFetchDataForNextLoginAttemptFunction::
@@ -140,13 +139,18 @@
 
 ExtensionFunction::ResponseAction
 LoginFetchDataForNextLoginAttemptFunction::Run() {
-  PrefService* local_state = g_browser_process->local_state();
-  DCHECK(local_state);
-  std::string data_for_next_login_attempt =
-      local_state->GetString(prefs::kLoginExtensionApiDataForNextLoginAttempt);
-  local_state->ClearPref(prefs::kLoginExtensionApiDataForNextLoginAttempt);
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  absl::optional<std::string> error = ValidateCrosapi();
+  if (error.has_value()) {
+    return RespondNow(Error(error.value()));
+  }
+#endif
 
-  return RespondNow(OneArgument(base::Value(data_for_next_login_attempt)));
+  auto callback = base::BindOnce(
+      &LoginFetchDataForNextLoginAttemptFunction::OnResult, this);
+
+  GetLoginApi()->FetchDataForNextLoginAttempt(std::move(callback));
+  return did_respond() ? AlreadyResponded() : RespondLater();
 }
 
 LoginLockManagedGuestSessionFunction::LoginLockManagedGuestSessionFunction() =
@@ -155,24 +159,18 @@
     default;
 
 ExtensionFunction::ResponseAction LoginLockManagedGuestSessionFunction::Run() {
-  ui::UserActivityDetector::Get()->HandleExternalUserActivity();
-
-  const user_manager::UserManager* user_manager =
-      user_manager::UserManager::Get();
-  const user_manager::User* active_user = user_manager->GetActiveUser();
-  if (!active_user ||
-      active_user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT ||
-      !user_manager->CanCurrentUserLock()) {
-    return RespondNow(Error(login_api_errors::kNoLockableManagedGuestSession));
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  absl::optional<std::string> error = ValidateCrosapi();
+  if (error.has_value()) {
+    return RespondNow(Error(error.value()));
   }
+#endif
 
-  if (session_manager::SessionManager::Get()->session_state() !=
-      session_manager::SessionState::ACTIVE) {
-    return RespondNow(Error(login_api_errors::kSessionIsNotActive));
-  }
+  auto callback =
+      base::BindOnce(&LoginLockManagedGuestSessionFunction::OnResult, this);
 
-  chromeos::LoginApiLockHandler::Get()->RequestLockScreen();
-  return RespondNow(NoArguments());
+  GetLoginApi()->LockManagedGuestSession(std::move(callback));
+  return did_respond() ? AlreadyResponded() : RespondLater();
 }
 
 LoginUnlockManagedGuestSessionFunction::
@@ -182,51 +180,20 @@
 
 ExtensionFunction::ResponseAction
 LoginUnlockManagedGuestSessionFunction::Run() {
-  ui::UserActivityDetector::Get()->HandleExternalUserActivity();
-
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  return RespondNow(Error(kCannotBeCalledFromLacros));
+#else
   auto parameters =
       api::login::UnlockManagedGuestSession::Params::Create(args());
   EXTENSION_FUNCTION_VALIDATE(parameters);
 
-  const user_manager::UserManager* user_manager =
-      user_manager::UserManager::Get();
-  const user_manager::User* active_user = user_manager->GetActiveUser();
-  if (!active_user ||
-      active_user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT ||
-      !user_manager->CanCurrentUserLock()) {
-    return RespondNow(
-        Error(login_api_errors::kNoUnlockableManagedGuestSession));
-  }
+  auto callback =
+      base::BindOnce(&LoginUnlockManagedGuestSessionFunction::OnResult, this);
 
-  if (session_manager::SessionManager::Get()->session_state() !=
-      session_manager::SessionState::LOCKED) {
-    return RespondNow(Error(login_api_errors::kSessionIsNotLocked));
-  }
-
-  chromeos::LoginApiLockHandler* handler = chromeos::LoginApiLockHandler::Get();
-  if (handler->IsUnlockInProgress()) {
-    return RespondNow(Error(login_api_errors::kAnotherUnlockAttemptInProgress));
-  }
-
-  ash::UserContext context(user_manager::USER_TYPE_PUBLIC_ACCOUNT,
-                           active_user->GetAccountId());
-  context.SetKey(ash::Key(parameters->password));
-  handler->Authenticate(
-      context,
-      base::BindOnce(
-          &LoginUnlockManagedGuestSessionFunction::OnAuthenticationComplete,
-          this));
+  GetLoginApi()->UnlockManagedGuestSession(parameters->password,
+                                           std::move(callback));
   return did_respond() ? AlreadyResponded() : RespondLater();
-}
-
-void LoginUnlockManagedGuestSessionFunction::OnAuthenticationComplete(
-    bool success) {
-  if (!success) {
-    Respond(Error(login_api_errors::kAuthenticationFailed));
-    return;
-  }
-
-  Respond(NoArguments());
+#endif
 }
 
 LoginLaunchSharedManagedGuestSessionFunction::
@@ -236,104 +203,73 @@
 
 ExtensionFunction::ResponseAction
 LoginLaunchSharedManagedGuestSessionFunction::Run() {
-  ui::UserActivityDetector::Get()->HandleExternalUserActivity();
-
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  return RespondNow(Error(kCannotBeCalledFromLacros));
+#else
   auto parameters =
       api::login::LaunchSharedManagedGuestSession::Params::Create(args());
   EXTENSION_FUNCTION_VALIDATE(parameters);
 
-  absl::optional<std::string> error =
-      chromeos::SharedSessionHandler::Get()->LaunchSharedManagedGuestSession(
-          parameters->password);
-  if (error) {
-    return RespondNow(Error(*error));
-  }
+  auto callback = base::BindOnce(
+      &LoginLaunchSharedManagedGuestSessionFunction::OnResult, this);
 
-  return RespondNow(NoArguments());
+  GetLoginApi()->LaunchSharedManagedGuestSession(parameters->password,
+                                                 std::move(callback));
+  return did_respond() ? AlreadyResponded() : RespondLater();
+#endif
 }
 
 LoginEnterSharedSessionFunction::LoginEnterSharedSessionFunction() = default;
 LoginEnterSharedSessionFunction::~LoginEnterSharedSessionFunction() = default;
 
 ExtensionFunction::ResponseAction LoginEnterSharedSessionFunction::Run() {
-  ui::UserActivityDetector::Get()->HandleExternalUserActivity();
-
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  return RespondNow(Error(kCannotBeCalledFromLacros));
+#else
   auto parameters = api::login::EnterSharedSession::Params::Create(args());
   EXTENSION_FUNCTION_VALIDATE(parameters);
 
-  chromeos::SharedSessionHandler::Get()->EnterSharedSession(
-      parameters->password,
-      base::BindOnce(
-          &LoginEnterSharedSessionFunction::OnEnterSharedSessionComplete,
-          this));
+  auto callback =
+      base::BindOnce(&LoginEnterSharedSessionFunction::OnResult, this);
 
+  GetLoginApi()->EnterSharedSession(parameters->password, std::move(callback));
   return did_respond() ? AlreadyResponded() : RespondLater();
-}
-
-void LoginEnterSharedSessionFunction::OnEnterSharedSessionComplete(
-    absl::optional<std::string> error) {
-  if (error) {
-    Respond(Error(*error));
-    return;
-  }
-
-  Respond(NoArguments());
+#endif
 }
 
 LoginUnlockSharedSessionFunction::LoginUnlockSharedSessionFunction() = default;
 LoginUnlockSharedSessionFunction::~LoginUnlockSharedSessionFunction() = default;
 
 ExtensionFunction::ResponseAction LoginUnlockSharedSessionFunction::Run() {
-  ui::UserActivityDetector::Get()->HandleExternalUserActivity();
-
-  auto parameters = api::login::UnlockSharedSession::Params::Create(args());
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  return RespondNow(Error(kCannotBeCalledFromLacros));
+#else
+  auto parameters = api::login::EnterSharedSession::Params::Create(args());
   EXTENSION_FUNCTION_VALIDATE(parameters);
 
-  const user_manager::UserManager* user_manager =
-      user_manager::UserManager::Get();
-  const user_manager::User* active_user = user_manager->GetActiveUser();
-  if (!active_user || !user_manager->CanCurrentUserLock()) {
-    return RespondNow(
-        Error(login_api_errors::kNoUnlockableManagedGuestSession));
-  }
+  auto callback =
+      base::BindOnce(&LoginUnlockSharedSessionFunction::OnResult, this);
 
-  chromeos::SharedSessionHandler::Get()->UnlockSharedSession(
-      parameters->password,
-      base::BindOnce(
-          &LoginUnlockSharedSessionFunction::OnUnlockSharedSessionComplete,
-          this));
-
+  GetLoginApi()->UnlockSharedSession(parameters->password, std::move(callback));
   return did_respond() ? AlreadyResponded() : RespondLater();
-}
-
-void LoginUnlockSharedSessionFunction::OnUnlockSharedSessionComplete(
-    absl::optional<std::string> error) {
-  if (error) {
-    Respond(Error(*error));
-    return;
-  }
-
-  Respond(NoArguments());
+#endif
 }
 
 LoginEndSharedSessionFunction::LoginEndSharedSessionFunction() = default;
 LoginEndSharedSessionFunction::~LoginEndSharedSessionFunction() = default;
 
 ExtensionFunction::ResponseAction LoginEndSharedSessionFunction::Run() {
-  chromeos::SharedSessionHandler::Get()->EndSharedSession(base::BindOnce(
-      &LoginEndSharedSessionFunction::OnEndSharedSessionComplete, this));
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  // TODO(jityao, b:217155485): Enable for Lacros after cleanup handlers are
+  // added.
+  return RespondNow(Error(kCannotBeCalledFromLacros));
+#else
+  auto callback =
+      base::BindOnce(&LoginEndSharedSessionFunction::OnResult, this);
 
+  GetLoginApi()->EndSharedSession(std::move(callback));
   return did_respond() ? AlreadyResponded() : RespondLater();
-}
-
-void LoginEndSharedSessionFunction::OnEndSharedSessionComplete(
-    absl::optional<std::string> error) {
-  if (error) {
-    Respond(Error(*error));
-    return;
-  }
-
-  Respond(NoArguments());
+#endif
 }
 
 LoginSetDataForNextLoginAttemptFunction::
@@ -343,16 +279,23 @@
 
 ExtensionFunction::ResponseAction
 LoginSetDataForNextLoginAttemptFunction::Run() {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  absl::optional<std::string> error = ValidateCrosapi();
+  if (error.has_value()) {
+    return RespondNow(Error(error.value()));
+  }
+#endif
+
   auto parameters =
       api::login::SetDataForNextLoginAttempt::Params::Create(args());
   EXTENSION_FUNCTION_VALIDATE(parameters);
 
-  PrefService* local_state = g_browser_process->local_state();
-  DCHECK(local_state);
-  local_state->SetString(prefs::kLoginExtensionApiDataForNextLoginAttempt,
-                         parameters->data_for_next_login_attempt);
+  auto callback =
+      base::BindOnce(&LoginSetDataForNextLoginAttemptFunction::OnResult, this);
 
-  return RespondNow(NoArguments());
+  GetLoginApi()->SetDataForNextLoginAttempt(
+      parameters->data_for_next_login_attempt, std::move(callback));
+  return did_respond() ? AlreadyResponded() : RespondLater();
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/login_api.h b/chrome/browser/chromeos/extensions/login_screen/login/login_api.h
index 9263ac30..7e8e31b 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login/login_api.h
+++ b/chrome/browser/chromeos/extensions/login_screen/login/login_api.h
@@ -5,41 +5,35 @@
 #ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_LOGIN_SCREEN_LOGIN_LOGIN_API_H_
 #define CHROME_BROWSER_CHROMEOS_EXTENSIONS_LOGIN_SCREEN_LOGIN_LOGIN_API_H_
 
-#include "components/prefs/pref_registry_simple.h"
+#include "chromeos/crosapi/mojom/login.mojom.h"
 #include "extensions/browser/extension_function.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace extensions {
 
-namespace login_api {
+class ExtensionFunctionWithOptionalErrorResult : public ExtensionFunction {
+ protected:
+  ~ExtensionFunctionWithOptionalErrorResult() override;
 
-void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
+  void OnResult(const absl::optional<std::string>& error);
+};
 
-}  // namespace login_api
+class ExtensionFunctionWithStringResult : public ExtensionFunction {
+ protected:
+  ~ExtensionFunctionWithStringResult() override;
 
-namespace login_api_errors {
+  void OnResult(const std::string& result);
+};
 
-extern const char kAlreadyActiveSession[];
-extern const char kLoginScreenIsNotActive[];
-extern const char kAnotherLoginAttemptInProgress[];
-extern const char kNoManagedGuestSessionAccounts[];
-extern const char kNoLockableManagedGuestSession[];
-extern const char kSessionIsNotActive[];
-extern const char kNoUnlockableManagedGuestSession[];
-extern const char kSessionIsNotLocked[];
-extern const char kAnotherUnlockAttemptInProgress[];
-extern const char kAuthenticationFailed[];
-extern const char kSharedMGSAlreadyLaunched[];
-extern const char kNoSharedMGSFound[];
-extern const char kSharedSessionIsNotActive[];
-extern const char kSharedSessionAlreadyLaunched[];
-extern const char kScryptFailure[];
-extern const char kCleanupInProgress[];
-extern const char kUnlockFailure[];
-extern const char kDeviceRestrictedManagedGuestSessionNotEnabled[];
+class ExtensionFunctionWithVoidResult : public ExtensionFunction {
+ protected:
+  ~ExtensionFunctionWithVoidResult() override;
 
-}  // namespace login_api_errors
+  void OnResult();
+};
 
-class LoginLaunchManagedGuestSessionFunction : public ExtensionFunction {
+class LoginLaunchManagedGuestSessionFunction
+    : public ExtensionFunctionWithOptionalErrorResult {
  public:
   LoginLaunchManagedGuestSessionFunction();
 
@@ -59,7 +53,8 @@
   ResponseAction Run() override;
 };
 
-class LoginExitCurrentSessionFunction : public ExtensionFunction {
+class LoginExitCurrentSessionFunction
+    : public ExtensionFunctionWithOptionalErrorResult {
  public:
   LoginExitCurrentSessionFunction();
 
@@ -79,7 +74,8 @@
   ResponseAction Run() override;
 };
 
-class LoginFetchDataForNextLoginAttemptFunction : public ExtensionFunction {
+class LoginFetchDataForNextLoginAttemptFunction
+    : public ExtensionFunctionWithStringResult {
  public:
   LoginFetchDataForNextLoginAttemptFunction();
 
@@ -99,7 +95,8 @@
   ResponseAction Run() override;
 };
 
-class LoginLockManagedGuestSessionFunction : public ExtensionFunction {
+class LoginLockManagedGuestSessionFunction
+    : public ExtensionFunctionWithOptionalErrorResult {
  public:
   LoginLockManagedGuestSessionFunction();
 
@@ -119,7 +116,8 @@
   ResponseAction Run() override;
 };
 
-class LoginUnlockManagedGuestSessionFunction : public ExtensionFunction {
+class LoginUnlockManagedGuestSessionFunction
+    : public ExtensionFunctionWithOptionalErrorResult {
  public:
   LoginUnlockManagedGuestSessionFunction();
 
@@ -137,12 +135,10 @@
 
   // ExtensionFunction:
   ResponseAction Run() override;
-
- private:
-  void OnAuthenticationComplete(bool success);
 };
 
-class LoginLaunchSharedManagedGuestSessionFunction : public ExtensionFunction {
+class LoginLaunchSharedManagedGuestSessionFunction
+    : public ExtensionFunctionWithOptionalErrorResult {
  public:
   LoginLaunchSharedManagedGuestSessionFunction();
 
@@ -162,7 +158,8 @@
   ResponseAction Run() override;
 };
 
-class LoginEnterSharedSessionFunction : public ExtensionFunction {
+class LoginEnterSharedSessionFunction
+    : public ExtensionFunctionWithOptionalErrorResult {
  public:
   LoginEnterSharedSessionFunction();
 
@@ -180,12 +177,10 @@
 
   // ExtensionFunction:
   ResponseAction Run() override;
-
- private:
-  void OnEnterSharedSessionComplete(absl::optional<std::string> error);
 };
 
-class LoginUnlockSharedSessionFunction : public ExtensionFunction {
+class LoginUnlockSharedSessionFunction
+    : public ExtensionFunctionWithOptionalErrorResult {
  public:
   LoginUnlockSharedSessionFunction();
 
@@ -203,12 +198,10 @@
 
   // ExtensionFunction:
   ResponseAction Run() override;
-
- private:
-  void OnUnlockSharedSessionComplete(absl::optional<std::string> error);
 };
 
-class LoginEndSharedSessionFunction : public ExtensionFunction {
+class LoginEndSharedSessionFunction
+    : public ExtensionFunctionWithOptionalErrorResult {
  public:
   LoginEndSharedSessionFunction();
 
@@ -224,12 +217,10 @@
 
   // ExtensionFunction:
   ResponseAction Run() override;
-
- private:
-  void OnEndSharedSessionComplete(absl::optional<std::string> error);
 };
 
-class LoginSetDataForNextLoginAttemptFunction : public ExtensionFunction {
+class LoginSetDataForNextLoginAttemptFunction
+    : public ExtensionFunctionWithVoidResult {
  public:
   LoginSetDataForNextLoginAttemptFunction();
 
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/login_api_unittest.cc b/chrome/browser/chromeos/extensions/login_screen/login/login_api_unittest.cc
index a2302bc..313e477 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login/login_api_unittest.cc
+++ b/chrome/browser/chromeos/extensions/login_screen/login/login_api_unittest.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/extensions/login_screen/login/cleanup/cleanup_manager.h"
 #include "chrome/browser/chromeos/extensions/login_screen/login/cleanup/mock_cleanup_handler.h"
+#include "chrome/browser/chromeos/extensions/login_screen/login/errors.h"
 #include "chrome/browser/chromeos/extensions/login_screen/login/login_api_lock_handler.h"
 #include "chrome/browser/chromeos/extensions/login_screen/login/shared_session_handler.h"
 #include "chrome/browser/extensions/extension_api_unittest.h"
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/prefs.cc b/chrome/browser/chromeos/extensions/login_screen/login/prefs.cc
new file mode 100644
index 0000000..ed52585
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/login_screen/login/prefs.cc
@@ -0,0 +1,22 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/extensions/login_screen/login/errors.h"
+
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+
+namespace extensions {
+
+namespace login_api {
+
+void RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
+  registry->RegisterStringPref(prefs::kLoginExtensionApiDataForNextLoginAttempt,
+                               "");
+}
+
+}  // namespace login_api
+
+}  // namespace extensions
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/prefs.h b/chrome/browser/chromeos/extensions/login_screen/login/prefs.h
new file mode 100644
index 0000000..04bf25d3e
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/login_screen/login/prefs.h
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_LOGIN_SCREEN_LOGIN_PREFS_H_
+#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_LOGIN_SCREEN_LOGIN_PREFS_H_
+
+class PrefRegistrySimple;
+
+namespace extensions {
+
+namespace login_api {
+
+void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
+
+}  // namespace login_api
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_LOGIN_SCREEN_LOGIN_PREFS_H_
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/shared_session_handler.cc b/chrome/browser/chromeos/extensions/login_screen/login/shared_session_handler.cc
index e7375e6e..1333e882 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login/shared_session_handler.cc
+++ b/chrome/browser/chromeos/extensions/login_screen/login/shared_session_handler.cc
@@ -10,10 +10,11 @@
 #include "ash/components/settings/cros_settings_names.h"
 #include "base/bind.h"
 #include "base/no_destructor.h"
+#include "base/strings/string_number_conversions.h"
 #include "chrome/browser/ash/login/existing_user_controller.h"
 #include "chrome/browser/ash/settings/cros_settings.h"
 #include "chrome/browser/chromeos/extensions/login_screen/login/cleanup/cleanup_manager.h"
-#include "chrome/browser/chromeos/extensions/login_screen/login/login_api.h"
+#include "chrome/browser/chromeos/extensions/login_screen/login/errors.h"
 #include "chrome/browser/chromeos/extensions/login_screen/login/login_api_lock_handler.h"
 #include "chrome/browser/ui/ash/session_controller_client_impl.h"
 #include "components/session_manager/core/session_manager.h"
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 6b4119a..dc3fcc0 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -361,7 +361,7 @@
 #include "chrome/browser/ash/system/input_device_settings.h"
 #include "chrome/browser/ash/web_applications/help_app/help_app_notification_controller.h"
 #include "chrome/browser/chromeos/extensions/echo_private_api.h"
-#include "chrome/browser/chromeos/extensions/login_screen/login/login_api.h"
+#include "chrome/browser/chromeos/extensions/login_screen/login/prefs.h"
 #include "chrome/browser/chromeos/printing/cups_printers_manager.h"
 #include "chrome/browser/device_identity/chromeos/device_oauth2_token_store_chromeos.h"
 #include "chrome/browser/extensions/extension_assets_manager_chromeos.h"