[go: nahoru, domu]

Re-land "Mash cleanup: begin converting login mojo to C++"

This re-lands db977c4b6c6bc31bd6d601273acc921435edda83

Change to original: LoginUserInfo::fingerprint_state is
default initialized

Original change's description:
> Mash cleanup: begin converting login mojo to C++
>
> This patch moves types implemented in login_user_info.mojom to
> //ash/public/cpp/login_types.h. The handful of methods on
> mojom::LoginScreen which used these types are moved to C++
> interfaces.
>
> There are two new public-facing C++ interfaces:
> 1. ash::LoginScreen, which is a direct translation of the mojom.
>    This is implemented by ash::LoginScreenController.
> 2. ash::LoginScreenModel, which is used for the methods that
>    were simple thunks in LoginScreenController.
>    (LoginDataDispatcher implements this interface.)
>
> Bug: 958206
> Change-Id: I329d606b234556bf05aee40849f3aa5ccc6c0be0

TBR=tsepez@chromium.org,xiyuan@chromium.org

Bug: 958206
Change-Id: I9567af3331638e38590f143f1b43e55d4b609c81
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1626700
Reviewed-by: Xiyuan Xia <xiyuan@chromium.org>
Commit-Queue: Evan Stade <estade@chromium.org>
Cr-Commit-Position: refs/heads/master@{#662757}
diff --git a/ash/DEPS b/ash/DEPS
index deae74a..10e3040 100644
--- a/ash/DEPS
+++ b/ash/DEPS
@@ -107,6 +107,9 @@
   "ash_service\.*": [
     "+chromeos/cryptohome",
   ],
+  "login_types\.*": [
+    "+chromeos/components/proximity_auth/public/interfaces/auth_type.mojom.h",
+  ],
   "message_center_controller\.*": [
     "+components/arc/common/notifications.mojom.h"
   ],
diff --git a/ash/detachable_base/detachable_base_handler.cc b/ash/detachable_base/detachable_base_handler.cc
index 84f449e..67c29c9f 100644
--- a/ash/detachable_base/detachable_base_handler.cc
+++ b/ash/detachable_base/detachable_base_handler.cc
@@ -6,6 +6,7 @@
 
 #include "ash/detachable_base/detachable_base_observer.h"
 #include "ash/public/cpp/ash_pref_names.h"
+#include "ash/public/cpp/session/user_info.h"
 #include "ash/shell.h"
 #include "base/bind.h"
 #include "base/strings/string_number_conversions.h"
@@ -75,7 +76,7 @@
   observers_.RemoveObserver(observer);
 }
 
-void DetachableBaseHandler::RemoveUserData(const mojom::UserInfo& user) {
+void DetachableBaseHandler::RemoveUserData(const UserInfo& user) {
   last_used_devices_.erase(user.account_id);
 
   if (local_state_) {
@@ -94,7 +95,7 @@
 }
 
 bool DetachableBaseHandler::PairedBaseMatchesLastUsedByUser(
-    const mojom::UserInfo& user) const {
+    const UserInfo& user) const {
   if (GetPairingStatus() != DetachableBasePairingStatus::kAuthenticated)
     return false;
 
@@ -112,7 +113,7 @@
 }
 
 bool DetachableBaseHandler::SetPairedBaseAsLastUsedByUser(
-    const mojom::UserInfo& user) {
+    const UserInfo& user) {
   if (GetPairingStatus() != DetachableBasePairingStatus::kAuthenticated)
     return false;
 
@@ -202,8 +203,7 @@
 }
 
 DetachableBaseHandler::DetachableBaseId
-DetachableBaseHandler::GetLastUsedDeviceForUser(
-    const mojom::UserInfo& user) const {
+DetachableBaseHandler::GetLastUsedDeviceForUser(const UserInfo& user) const {
   const auto it = last_used_devices_.find(user.account_id);
   // If the last used device was set within this session, bypass local state.
   if (it != last_used_devices_.end())
diff --git a/ash/detachable_base/detachable_base_handler.h b/ash/detachable_base/detachable_base_handler.h
index ae1f0e5..ad6338d7 100644
--- a/ash/detachable_base/detachable_base_handler.h
+++ b/ash/detachable_base/detachable_base_handler.h
@@ -11,7 +11,6 @@
 
 #include "ash/ash_export.h"
 #include "ash/detachable_base/detachable_base_pairing_status.h"
-#include "ash/public/interfaces/user_info.mojom.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
@@ -19,6 +18,7 @@
 #include "base/scoped_observer.h"
 #include "chromeos/dbus/hammerd/hammerd_client.h"
 #include "chromeos/dbus/power/power_manager_client.h"
+#include "components/account_id/account_id.h"
 
 class PrefRegistrySimple;
 class PrefService;
@@ -26,6 +26,7 @@
 namespace ash {
 
 class DetachableBaseObserver;
+struct UserInfo;
 
 // Keeps track of the state of Chrome OS device's detachable base. It tracks
 // whether:
@@ -58,7 +59,7 @@
   void RemoveObserver(DetachableBaseObserver* observer);
 
   // Removes the detachable base data associated with a user from local state.
-  void RemoveUserData(const mojom::UserInfo& user);
+  void RemoveUserData(const UserInfo& user);
 
   // Gets the detachable base pairing state.
   DetachableBasePairingStatus GetPairingStatus() const;
@@ -67,7 +68,7 @@
   // Returns true only if the base has kAuthenticated pairing state.
   // If this the user has not previously used any detachable bases (i.e. the
   // last used detachable base is empty), this will return true.
-  bool PairedBaseMatchesLastUsedByUser(const mojom::UserInfo& user) const;
+  bool PairedBaseMatchesLastUsedByUser(const UserInfo& user) const;
 
   // Sets the currently paired base as the last used base for the user.
   // If the user is not ephemeral, the last used base information will be
@@ -79,7 +80,7 @@
   // yet initialized. Observers will be notified that pairing status
   // changed when local state is initialized (provided a base is still
   // paired) - setting the last used base can be retried at that point.
-  bool SetPairedBaseAsLastUsedByUser(const mojom::UserInfo& user);
+  bool SetPairedBaseAsLastUsedByUser(const UserInfo& user);
 
   // chromeos::HammerdClient::Observer:
   void BaseFirmwareUpdateNeeded() override;
@@ -111,7 +112,7 @@
 
   // Retrieves the last known base used by a user. Returns an empty string if
   // a detachable base usage was not previously recorded for the user.
-  DetachableBaseId GetLastUsedDeviceForUser(const mojom::UserInfo& user) const;
+  DetachableBaseId GetLastUsedDeviceForUser(const UserInfo& user) const;
 
   // Notifies observers that the detachable base pairing state has changed.
   void NotifyPairingStatusChanged();
diff --git a/ash/detachable_base/detachable_base_handler_unittest.cc b/ash/detachable_base/detachable_base_handler_unittest.cc
index 02602e8..03a2f00 100644
--- a/ash/detachable_base/detachable_base_handler_unittest.cc
+++ b/ash/detachable_base/detachable_base_handler_unittest.cc
@@ -9,7 +9,7 @@
 
 #include "ash/detachable_base/detachable_base_observer.h"
 #include "ash/detachable_base/detachable_base_pairing_status.h"
-#include "ash/public/interfaces/user_info.mojom.h"
+#include "ash/public/cpp/session/user_info.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
@@ -29,12 +29,12 @@
   kEphemeral,
 };
 
-mojom::UserInfoPtr CreateUser(const std::string& email,
-                              const std::string& gaia_id,
-                              UserType user_type) {
-  mojom::UserInfoPtr user = mojom::UserInfo::New();
-  user->account_id = AccountId::FromUserEmailGaiaId(email, gaia_id);
-  user->is_ephemeral = user_type == UserType::kEphemeral;
+UserInfo CreateUser(const std::string& email,
+                    const std::string& gaia_id,
+                    UserType user_type) {
+  UserInfo user;
+  user.account_id = AccountId::FromUserEmailGaiaId(email, gaia_id);
+  user.is_ephemeral = user_type == UserType::kEphemeral;
   return user;
 }
 
@@ -131,7 +131,7 @@
 
   std::unique_ptr<DetachableBaseHandler> handler_;
 
-  mojom::UserInfoPtr default_user_;
+  UserInfo default_user_;
 
  private:
   base::test::ScopedTaskEnvironment task_environment_;
@@ -147,7 +147,7 @@
 
   EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
   EXPECT_EQ(0, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
 }
 
 TEST_F(DetachableBaseHandlerTest, TabletModeOnOnStartup) {
@@ -165,7 +165,7 @@
   EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
 }
 
 TEST_F(DetachableBaseHandlerTest, SuccessfullPairing) {
@@ -181,7 +181,7 @@
   // The user should not be notified when they attach a base for the first time,
   // so the first paired base should be reported as kAuthenticated rather than
   // kAuthenticatedNotMatchingLastUsed.
-  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   // Assume the base has been detached when the device switches to tablet mode.
@@ -189,7 +189,7 @@
       chromeos::PowerManagerClient::TabletMode::ON, base::TimeTicks());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
   EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   // When the device exits tablet mode again, the base should not be reported
@@ -197,13 +197,13 @@
   chromeos::FakePowerManagerClient::Get()->SetTabletMode(
       chromeos::PowerManagerClient::TabletMode::OFF, base::TimeTicks());
   EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
 
   hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
   EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
   detachable_base_observer_.reset_pairing_status_changed_count();
 }
 
@@ -217,7 +217,7 @@
   EXPECT_EQ(DetachableBasePairingStatus::kNotAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   // Assume the base has been detached when the device switches to tablet mode.
@@ -225,7 +225,7 @@
       chromeos::PowerManagerClient::TabletMode::ON, base::TimeTicks());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
   EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
   detachable_base_observer_.reset_pairing_status_changed_count();
 }
 
@@ -239,7 +239,7 @@
   EXPECT_EQ(DetachableBasePairingStatus::kInvalidDevice,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   // Assume the base has been detached when the device switches to tablet mode.
@@ -247,7 +247,7 @@
       chromeos::PowerManagerClient::TabletMode::ON, base::TimeTicks());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
   EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
   detachable_base_observer_.reset_pairing_status_changed_count();
 }
 
@@ -258,7 +258,7 @@
   // device is not in tablet mode.
   EXPECT_EQ(0, detachable_base_observer_.pairing_status_changed_count());
   EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
 
   // Run loop so the callback for getting the initial power manager state gets
   // run.
@@ -267,7 +267,7 @@
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
   EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
             handler_->GetPairingStatus());
-  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
   detachable_base_observer_.reset_pairing_status_changed_count();
 }
 
@@ -278,7 +278,7 @@
   // device is not in tablet mode.
   EXPECT_EQ(0, detachable_base_observer_.pairing_status_changed_count());
   EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
 
   // Run loop so the callback for getting the initial power manager state gets
   // run.
@@ -287,7 +287,7 @@
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
   EXPECT_EQ(DetachableBasePairingStatus::kNotAuthenticated,
             handler_->GetPairingStatus());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
   detachable_base_observer_.reset_pairing_status_changed_count();
 }
 
@@ -298,7 +298,7 @@
   // device is not in tablet mode.
   EXPECT_EQ(0, detachable_base_observer_.pairing_status_changed_count());
   EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
 
   // Run loop so the callback for getting the initial power manager state gets
   // run.
@@ -307,7 +307,7 @@
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
   EXPECT_EQ(DetachableBasePairingStatus::kInvalidDevice,
             handler_->GetPairingStatus());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
   detachable_base_observer_.reset_pairing_status_changed_count();
 }
 
@@ -322,7 +322,7 @@
 
   EXPECT_EQ(0, detachable_base_observer_.pairing_status_changed_count());
   EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
 }
 
 TEST_F(DetachableBaseHandlerTest, DetachableBaseChangeDetection) {
@@ -336,11 +336,11 @@
   EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   // Set the current base as last used by the user.
-  handler_->SetPairedBaseAsLastUsedByUser(*default_user_);
+  handler_->SetPairedBaseAsLastUsedByUser(default_user_);
 
   // Simulate the paired base change.
   ChangePairedBase({0x04, 0x05, 0x06, 0x07});
@@ -348,7 +348,7 @@
   EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   // Switch back to last used base.
@@ -357,7 +357,7 @@
   EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   // The last used base should be preserved if the detachable base handler is
@@ -370,7 +370,7 @@
   EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
   detachable_base_observer_.reset_pairing_status_changed_count();
 }
 
@@ -378,7 +378,7 @@
   // Assume the user_1 has a last used base.
   base::RunLoop().RunUntilIdle();
   hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
-  handler_->SetPairedBaseAsLastUsedByUser(*default_user_);
+  handler_->SetPairedBaseAsLastUsedByUser(default_user_);
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   // Restart the handler, so it's initialized with the previously set up prefs
@@ -386,13 +386,13 @@
   RestartHandler();
   base::RunLoop().RunUntilIdle();
 
-  const mojom::UserInfoPtr second_user =
+  const UserInfo second_user =
       CreateUser("user_2@foo.bar", "222222", UserType::kNormal);
 
   EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
   EXPECT_EQ(0, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*second_user));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
 
   // Pair a detachable base different than the one used by user_1.
   hammerd_client_->FirePairChallengeSucceededSignal({0x04, 0x05, 0x06, 0x07});
@@ -401,14 +401,14 @@
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
   // The base for user_1 has changed.
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
   // User 2 has not used a detachable base yet - the base should be reported as
   // matching last used base.
-  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*second_user));
+  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   // Set the last used detachable base for user 2, and pair the initial base.
-  handler_->SetPairedBaseAsLastUsedByUser(*second_user);
+  handler_->SetPairedBaseAsLastUsedByUser(second_user);
 
   ChangePairedBase({0x01, 0x02, 0x03, 0x04});
 
@@ -416,14 +416,14 @@
   EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*second_user));
+  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   // Set the base for user 2 to the current one.
-  handler_->SetPairedBaseAsLastUsedByUser(*second_user);
+  handler_->SetPairedBaseAsLastUsedByUser(second_user);
 
-  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*second_user));
+  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
 
   // When the base is paired next time, it should be considered authenticated
   // for both users.
@@ -432,8 +432,8 @@
   EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
-  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*second_user));
+  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
+  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
   detachable_base_observer_.reset_pairing_status_changed_count();
 }
 
@@ -442,7 +442,7 @@
   base::RunLoop().RunUntilIdle();
 
   hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
-  handler_->SetPairedBaseAsLastUsedByUser(*default_user_);
+  handler_->SetPairedBaseAsLastUsedByUser(default_user_);
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   // Switch to non-trusted base, and verify it's reported as such regardless
@@ -455,14 +455,14 @@
 
   hammerd_client_->FirePairChallengeFailedSignal();
 
-  const mojom::UserInfoPtr second_user =
+  const UserInfo second_user =
       CreateUser("user_2@foo.bar", "222222", UserType::kNormal);
 
   EXPECT_EQ(DetachableBasePairingStatus::kNotAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*second_user));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
   detachable_base_observer_.reset_pairing_status_changed_count();
 }
 
@@ -471,7 +471,7 @@
   base::RunLoop().RunUntilIdle();
 
   hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
-  handler_->SetPairedBaseAsLastUsedByUser(*default_user_);
+  handler_->SetPairedBaseAsLastUsedByUser(default_user_);
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   // Switch to an invalid base, and verify it's reported as such regardless
@@ -484,26 +484,26 @@
 
   hammerd_client_->FireInvalidBaseConnectedSignal();
 
-  const mojom::UserInfoPtr second_user =
+  const UserInfo second_user =
       CreateUser("user_2@foo.bar", "222222", UserType::kNormal);
 
   EXPECT_EQ(DetachableBasePairingStatus::kInvalidDevice,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*second_user));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
   detachable_base_observer_.reset_pairing_status_changed_count();
 }
 
 TEST_F(DetachableBaseHandlerTest, RemoveUserData) {
-  const mojom::UserInfoPtr second_user =
+  const UserInfo second_user =
       CreateUser("user_2@foo.bar", "222222", UserType::kNormal);
 
   // Assume the user_1 has a last used base.
   base::RunLoop().RunUntilIdle();
   hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
-  handler_->SetPairedBaseAsLastUsedByUser(*default_user_);
-  handler_->SetPairedBaseAsLastUsedByUser(*second_user);
+  handler_->SetPairedBaseAsLastUsedByUser(default_user_);
+  handler_->SetPairedBaseAsLastUsedByUser(second_user);
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   ChangePairedBase({0x04, 0x05, 0x06});
@@ -511,42 +511,42 @@
   EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*second_user));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   // Remove the data for user_2, and verify that the paired base is reported
   // as authenticated when the paired base changes again.
-  handler_->RemoveUserData(*second_user);
+  handler_->RemoveUserData(second_user);
   ChangePairedBase({0x07, 0x08, 0x09});
 
   EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
-  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*second_user));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
+  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   // Verify that paired base will be properly set again for the previously
   // removed user.
-  handler_->SetPairedBaseAsLastUsedByUser(*second_user);
+  handler_->SetPairedBaseAsLastUsedByUser(second_user);
   ChangePairedBase({0x01, 0x02, 0x03, 0x04});
 
   EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_));
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*second_user));
+  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
   detachable_base_observer_.reset_pairing_status_changed_count();
 }
 
 TEST_F(DetachableBaseHandlerTest, EphemeralUser) {
   base::RunLoop().RunUntilIdle();
 
-  const mojom::UserInfoPtr ephemeral_user =
+  const UserInfo ephemeral_user =
       CreateUser("user_3@foo.bar", "333333", UserType::kEphemeral);
   hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
-  handler_->SetPairedBaseAsLastUsedByUser(*ephemeral_user);
+  handler_->SetPairedBaseAsLastUsedByUser(ephemeral_user);
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   ChangePairedBase({0x04, 0x05, 0x06});
@@ -554,7 +554,7 @@
   EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*ephemeral_user));
+  EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(ephemeral_user));
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   ChangePairedBase({0x01, 0x02, 0x03, 0x04});
@@ -562,7 +562,7 @@
   EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*ephemeral_user));
+  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(ephemeral_user));
   detachable_base_observer_.reset_pairing_status_changed_count();
 
   // Verify that the information about the last used base gets lost if the
@@ -575,7 +575,7 @@
   EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
             handler_->GetPairingStatus());
   EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
-  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*ephemeral_user));
+  EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(ephemeral_user));
   detachable_base_observer_.reset_pairing_status_changed_count();
 }
 
diff --git a/ash/detachable_base/detachable_base_notification_controller.cc b/ash/detachable_base/detachable_base_notification_controller.cc
index 54adc9f..47b9a45 100644
--- a/ash/detachable_base/detachable_base_notification_controller.cc
+++ b/ash/detachable_base/detachable_base_notification_controller.cc
@@ -116,14 +116,14 @@
   if (pairing_status == DetachableBasePairingStatus::kNone)
     return;
 
-  const mojom::UserInfoPtr user_info = active_session->user_info.ToMojom();
+  const UserInfo& user_info = active_session->user_info;
   if (pairing_status == DetachableBasePairingStatus::kAuthenticated &&
-      detachable_base_handler_->PairedBaseMatchesLastUsedByUser(*user_info)) {
+      detachable_base_handler_->PairedBaseMatchesLastUsedByUser(user_info)) {
     // Set the current base as last used by the user.
     // PairedBaseMatchesLastUsedByUser returns true if the user has not
     // previously used a base, so make sure the last used base value is actually
     // set.
-    detachable_base_handler_->SetPairedBaseAsLastUsedByUser(*user_info);
+    detachable_base_handler_->SetPairedBaseAsLastUsedByUser(user_info);
     return;
   }
 
@@ -156,7 +156,7 @@
   // At this point the session is unblocked - mark the current base as used by
   // user (as they have just been notified about the base change).
   if (pairing_status == DetachableBasePairingStatus::kAuthenticated)
-    detachable_base_handler_->SetPairedBaseAsLastUsedByUser(*user_info);
+    detachable_base_handler_->SetPairedBaseAsLastUsedByUser(user_info);
 }
 
 void DetachableBaseNotificationController::RemovePairingNotification() {
diff --git a/ash/detachable_base/detachable_base_notification_controller_unittest.cc b/ash/detachable_base/detachable_base_notification_controller_unittest.cc
index 6fd29c1..afd8fa8 100644
--- a/ash/detachable_base/detachable_base_notification_controller_unittest.cc
+++ b/ash/detachable_base/detachable_base_notification_controller_unittest.cc
@@ -7,7 +7,7 @@
 #include <string>
 
 #include "ash/detachable_base/detachable_base_handler.h"
-#include "ash/public/interfaces/user_info.mojom.h"
+#include "ash/public/cpp/session/user_info.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/session/test_session_controller_client.h"
 #include "ash/shell.h"
@@ -21,14 +21,14 @@
 
 namespace ash {
 
-mojom::UserInfoPtr CreateTestUserInfo(const std::string& user_email) {
-  auto user_info = mojom::UserInfo::New();
-  user_info->type = user_manager::USER_TYPE_REGULAR;
-  user_info->account_id = AccountId::FromUserEmail(user_email);
-  user_info->display_name = "Test user";
-  user_info->display_email = user_email;
-  user_info->is_ephemeral = false;
-  user_info->is_new_profile = false;
+UserInfo CreateTestUserInfo(const std::string& user_email) {
+  UserInfo user_info;
+  user_info.type = user_manager::USER_TYPE_REGULAR;
+  user_info.account_id = AccountId::FromUserEmail(user_email);
+  user_info.display_name = "Test user";
+  user_info.display_email = user_email;
+  user_info.is_ephemeral = false;
+  user_info.is_new_profile = false;
   return user_info;
 }
 
@@ -138,11 +138,11 @@
 TEST_F(DetachableBaseNotificationControllerTest,
        NoNotificationIfSessionNotStarted) {
   const char kTestUser[] = "user_1@test.com";
-  mojom::UserInfoPtr test_user_info = CreateTestUserInfo(kTestUser);
+  UserInfo test_user_info = CreateTestUserInfo(kTestUser);
   // Set a detachable base as previously used by the user before log in.
   detachable_base_handler()->PairChallengeSucceeded({0x01, 0x01});
-  EXPECT_TRUE(detachable_base_handler()->SetPairedBaseAsLastUsedByUser(
-      *test_user_info));
+  EXPECT_TRUE(
+      detachable_base_handler()->SetPairedBaseAsLastUsedByUser(test_user_info));
 
   // Set up another detachable base as attached when the user logs in.
   detachable_base_handler()->PairChallengeSucceeded({0x02, 0x02});
@@ -156,11 +156,11 @@
 TEST_F(DetachableBaseNotificationControllerTest,
        NoNotificationOnSessionStartIfBaseMarkedAsLastUsed) {
   const char kTestUser[] = "user_1@test.com";
-  mojom::UserInfoPtr test_user_info = CreateTestUserInfo(kTestUser);
+  UserInfo test_user_info = CreateTestUserInfo(kTestUser);
   // Set a detachable base as previously used by the user before log in.
   detachable_base_handler()->PairChallengeSucceeded({0x01, 0x01});
-  EXPECT_TRUE(detachable_base_handler()->SetPairedBaseAsLastUsedByUser(
-      *test_user_info));
+  EXPECT_TRUE(
+      detachable_base_handler()->SetPairedBaseAsLastUsedByUser(test_user_info));
 
   // Set up another detachable base as attached when the user logs in.
   detachable_base_handler()->PairChallengeSucceeded({0x02, 0x02});
@@ -169,8 +169,8 @@
 
   // Mark the current device as last used by the user, and verify there is no
   // notification when the user logs in.
-  EXPECT_TRUE(detachable_base_handler()->SetPairedBaseAsLastUsedByUser(
-      *test_user_info));
+  EXPECT_TRUE(
+      detachable_base_handler()->SetPairedBaseAsLastUsedByUser(test_user_info));
   SimulateUserLogin(kTestUser);
   EXPECT_FALSE(IsBaseChangedNotificationVisible());
 }
@@ -212,7 +212,7 @@
   EXPECT_FALSE(IsBaseChangedNotificationVisible());
 
   EXPECT_TRUE(detachable_base_handler()->SetPairedBaseAsLastUsedByUser(
-      *session_controller()->GetUserSession(0)->user_info.ToMojom()));
+      session_controller()->GetUserSession(0)->user_info));
 
   UnblockUserSession();
   EXPECT_FALSE(IsBaseChangedNotificationVisible());
diff --git a/ash/login/login_screen_controller.cc b/ash/login/login_screen_controller.cc
index 48bd1e8..169b9c4 100644
--- a/ash/login/login_screen_controller.cc
+++ b/ash/login/login_screen_controller.cc
@@ -306,6 +306,10 @@
   login_screen_client_.FlushForTesting();
 }
 
+LoginScreenModel* LoginScreenController::GetModel() {
+  return DataDispatcher();
+}
+
 void LoginScreenController::SetClient(mojom::LoginScreenClientPtr client) {
   login_screen_client_ = std::move(client);
 }
@@ -354,18 +358,6 @@
   NOTIMPLEMENTED();
 }
 
-void LoginScreenController::ShowUserPodCustomIcon(
-    const AccountId& account_id,
-    mojom::EasyUnlockIconOptionsPtr icon) {
-  DataDispatcher()->ShowEasyUnlockIcon(account_id, icon);
-}
-
-void LoginScreenController::HideUserPodCustomIcon(const AccountId& account_id) {
-  auto icon_options = mojom::EasyUnlockIconOptions::New();
-  icon_options->icon = mojom::EasyUnlockIconId::NONE;
-  DataDispatcher()->ShowEasyUnlockIcon(account_id, icon_options);
-}
-
 void LoginScreenController::SetAuthType(
     const AccountId& account_id,
     proximity_auth::mojom::AuthType auth_type,
@@ -380,13 +372,6 @@
   }
 }
 
-void LoginScreenController::SetUserList(
-    std::vector<mojom::LoginUserInfoPtr> users) {
-  DCHECK(DataDispatcher());
-
-  DataDispatcher()->NotifyUsers(users);
-}
-
 void LoginScreenController::SetPinEnabledForUser(const AccountId& account_id,
                                                  bool is_enabled) {
   // Chrome will update pin pod state every time user tries to authenticate.
@@ -395,12 +380,6 @@
     DataDispatcher()->SetPinEnabledForUser(account_id, is_enabled);
 }
 
-void LoginScreenController::SetFingerprintState(const AccountId& account_id,
-                                                mojom::FingerprintState state) {
-  if (DataDispatcher())
-    DataDispatcher()->SetFingerprintState(account_id, state);
-}
-
 void LoginScreenController::NotifyFingerprintAuthResult(
     const AccountId& account_id,
     bool successful) {
@@ -408,12 +387,6 @@
     DataDispatcher()->NotifyFingerprintAuthResult(account_id, successful);
 }
 
-void LoginScreenController::SetAvatarForUser(const AccountId& account_id,
-                                             mojom::UserAvatarPtr avatar) {
-  for (auto& observer : observers_)
-    observer.SetAvatarForUser(account_id, avatar);
-}
-
 void LoginScreenController::EnableAuthForUser(const AccountId& account_id) {
   if (DataDispatcher())
     DataDispatcher()->EnableAuthForUser(account_id);
@@ -456,27 +429,6 @@
     DataDispatcher()->SetPublicSessionDisplayName(account_id, display_name);
 }
 
-void LoginScreenController::SetPublicSessionLocales(
-    const AccountId& account_id,
-    std::vector<mojom::LocaleItemPtr> locales,
-    const std::string& default_locale,
-    bool show_advanced_view) {
-  if (DataDispatcher()) {
-    DataDispatcher()->SetPublicSessionLocales(
-        account_id, locales, default_locale, show_advanced_view);
-  }
-}
-
-void LoginScreenController::SetPublicSessionKeyboardLayouts(
-    const AccountId& account_id,
-    const std::string& locale,
-    std::vector<mojom::InputMethodItemPtr> keyboard_layouts) {
-  if (DataDispatcher()) {
-    DataDispatcher()->SetPublicSessionKeyboardLayouts(account_id, locale,
-                                                      keyboard_layouts);
-  }
-}
-
 void LoginScreenController::SetPublicSessionShowFullManagementDisclosure(
     bool is_full_management_disclosure_needed) {
   if (DataDispatcher()) {
diff --git a/ash/login/login_screen_controller.h b/ash/login/login_screen_controller.h
index 551e1a9..53468c7da 100644
--- a/ash/login/login_screen_controller.h
+++ b/ash/login/login_screen_controller.h
@@ -10,6 +10,7 @@
 #include "ash/ash_export.h"
 #include "ash/login/login_screen_controller_observer.h"
 #include "ash/public/cpp/kiosk_app_menu.h"
+#include "ash/public/cpp/login_screen.h"
 #include "ash/public/cpp/system_tray_focus_observer.h"
 #include "ash/public/interfaces/login_screen.mojom.h"
 #include "base/macros.h"
@@ -30,6 +31,7 @@
 // This could send requests to LoginScreenClient and also handle requests from
 // LoginScreenClient through mojo.
 class ASH_EXPORT LoginScreenController : public mojom::LoginScreen,
+                                         public LoginScreen,
                                          public KioskAppMenu,
                                          public SystemTrayFocusObserver {
  public:
@@ -111,6 +113,9 @@
     force_fail_auth_for_debug_overlay_ = force_fail;
   }
 
+  // LoginScreen:
+  LoginScreenModel* GetModel() override;
+
   // mojom::LoginScreen:
   void SetClient(mojom::LoginScreenClientPtr client) override;
   void ShowLockScreen(ShowLockScreenCallback on_shown) override;
@@ -122,21 +127,13 @@
   void ShowWarningBanner(const base::string16& message) override;
   void HideWarningBanner() override;
   void ClearErrors() override;
-  void ShowUserPodCustomIcon(const AccountId& account_id,
-                             mojom::EasyUnlockIconOptionsPtr icon) override;
-  void HideUserPodCustomIcon(const AccountId& account_id) override;
   void SetAuthType(const AccountId& account_id,
                    proximity_auth::mojom::AuthType auth_type,
                    const base::string16& initial_value) override;
-  void SetUserList(std::vector<mojom::LoginUserInfoPtr> users) override;
   void SetPinEnabledForUser(const AccountId& account_id,
                             bool is_enabled) override;
-  void SetFingerprintState(const AccountId& account_id,
-                           mojom::FingerprintState state) override;
   void NotifyFingerprintAuthResult(const AccountId& account_id,
                                    bool successful) override;
-  void SetAvatarForUser(const AccountId& account_id,
-                        mojom::UserAvatarPtr avatar) override;
   void EnableAuthForUser(const AccountId& account_id) override;
   void DisableAuthForUser(
       const AccountId& account_id,
@@ -149,14 +146,6 @@
   void IsReadyForPassword(IsReadyForPasswordCallback callback) override;
   void SetPublicSessionDisplayName(const AccountId& account_id,
                                    const std::string& display_name) override;
-  void SetPublicSessionLocales(const AccountId& account_id,
-                               std::vector<mojom::LocaleItemPtr> locales,
-                               const std::string& default_locale,
-                               bool show_advanced_view) override;
-  void SetPublicSessionKeyboardLayouts(
-      const AccountId& account_id,
-      const std::string& locale,
-      std::vector<mojom::InputMethodItemPtr> keyboard_layouts) override;
   void SetPublicSessionShowFullManagementDisclosure(
       bool is_full_management_disclosure_needed) override;
   void ShowKioskAppError(const std::string& message) override;
diff --git a/ash/login/login_screen_controller_observer.cc b/ash/login/login_screen_controller_observer.cc
index 1adca053..3826f07 100644
--- a/ash/login/login_screen_controller_observer.cc
+++ b/ash/login/login_screen_controller_observer.cc
@@ -4,16 +4,10 @@
 
 #include "ash/login/login_screen_controller_observer.h"
 
-#include "ash/login/login_screen_controller.h"
-
 namespace ash {
 
 LoginScreenControllerObserver::~LoginScreenControllerObserver() = default;
 
-void LoginScreenControllerObserver::SetAvatarForUser(
-    const AccountId& account_id,
-    const mojom::UserAvatarPtr& avatar) {}
-
 void LoginScreenControllerObserver::OnFocusLeavingLockScreenApps(bool reverse) {
 }
 
diff --git a/ash/login/login_screen_controller_observer.h b/ash/login/login_screen_controller_observer.h
index 888eb37..92c09a9b6 100644
--- a/ash/login/login_screen_controller_observer.h
+++ b/ash/login/login_screen_controller_observer.h
@@ -7,9 +7,6 @@
 
 #include "ash/ash_export.h"
 #include "ash/public/interfaces/login_screen.mojom.h"
-#include "ash/public/interfaces/user_info.mojom.h"
-
-class AccountId;
 
 namespace ash {
 
@@ -19,10 +16,6 @@
  public:
   virtual ~LoginScreenControllerObserver();
 
-  // Called when |avatar| for |account_id| has changed.
-  virtual void SetAvatarForUser(const AccountId& account_id,
-                                const mojom::UserAvatarPtr& avatar);
-
   // Called when focus is leaving a lock screen app window due to tabbing.
   // |reverse| - whether the tab order is reversed.
   virtual void OnFocusLeavingLockScreenApps(bool reverse);
diff --git a/ash/login/login_screen_test_api.cc b/ash/login/login_screen_test_api.cc
index 3041669..1372249 100644
--- a/ash/login/login_screen_test_api.cc
+++ b/ash/login/login_screen_test_api.cc
@@ -185,7 +185,7 @@
   // users this API needs to search all user views for the associated user and
   // potentially activate that user so it is showing its password field.
   CHECK_EQ(account_id,
-           auth_test.user_view()->current_user()->basic_user_info->account_id);
+           auth_test.user_view()->current_user().basic_user_info.account_id);
 
   password_test.SubmitPassword(password);
 
diff --git a/ash/login/ui/fake_login_detachable_base_model.cc b/ash/login/ui/fake_login_detachable_base_model.cc
index 6f9d187..6e01c6712 100644
--- a/ash/login/ui/fake_login_detachable_base_model.cc
+++ b/ash/login/ui/fake_login_detachable_base_model.cc
@@ -5,7 +5,7 @@
 #include "ash/login/ui/fake_login_detachable_base_model.h"
 
 #include "ash/login/ui/login_data_dispatcher.h"
-#include "ash/public/interfaces/user_info.mojom.h"
+#include "ash/public/cpp/session/user_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
@@ -46,7 +46,7 @@
 }
 
 bool FakeLoginDetachableBaseModel::PairedBaseMatchesLastUsedByUser(
-    const mojom::UserInfo& user_info) {
+    const UserInfo& user_info) {
   EXPECT_FALSE(current_authenticated_base_.empty());
 
   std::string last_used = GetLastUsedBase(user_info.account_id);
@@ -54,7 +54,7 @@
 }
 
 bool FakeLoginDetachableBaseModel::SetPairedBaseAsLastUsedByUser(
-    const mojom::UserInfo& user_info) {
+    const UserInfo& user_info) {
   if (current_authenticated_base_.empty())
     return false;
 
diff --git a/ash/login/ui/fake_login_detachable_base_model.h b/ash/login/ui/fake_login_detachable_base_model.h
index bbd87fe..624dee5 100644
--- a/ash/login/ui/fake_login_detachable_base_model.h
+++ b/ash/login/ui/fake_login_detachable_base_model.h
@@ -45,9 +45,8 @@
 
   // LoginDetachableBaseModel:
   DetachableBasePairingStatus GetPairingStatus() override;
-  bool PairedBaseMatchesLastUsedByUser(
-      const mojom::UserInfo& user_info) override;
-  bool SetPairedBaseAsLastUsedByUser(const mojom::UserInfo& user_info) override;
+  bool PairedBaseMatchesLastUsedByUser(const UserInfo& user_info) override;
+  bool SetPairedBaseAsLastUsedByUser(const UserInfo& user_info) override;
 
  private:
   LoginDataDispatcher* data_dispatcher_;
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc
index 33fc378bc..9d52fab 100644
--- a/ash/login/ui/lock_contents_view.cc
+++ b/ash/login/ui/lock_contents_view.cc
@@ -205,8 +205,8 @@
   return keyboard_window == this_window ? keyboard_controller : nullptr;
 }
 
-bool IsPublicAccountUser(const mojom::LoginUserInfoPtr& user) {
-  return user->basic_user_info->type == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
+bool IsPublicAccountUser(const LoginUserInfo& user) {
+  return user.basic_user_info.type == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
 }
 
 bool IsTabletMode() {
@@ -357,10 +357,10 @@
   return view_->main_view_;
 }
 
-LockContentsView::UserState::UserState(const mojom::LoginUserInfoPtr& user_info)
-    : account_id(user_info->basic_user_info->account_id) {
-  fingerprint_state = user_info->fingerprint_state;
-  if (user_info->auth_type == proximity_auth::mojom::AuthType::ONLINE_SIGN_IN)
+LockContentsView::UserState::UserState(const LoginUserInfo& user_info)
+    : account_id(user_info.basic_user_info.account_id) {
+  fingerprint_state = user_info.fingerprint_state;
+  if (user_info.auth_type == proximity_auth::mojom::AuthType::ONLINE_SIGN_IN)
     force_online_sign_in = true;
 }
 
@@ -603,8 +603,7 @@
   return true;
 }
 
-void LockContentsView::OnUsersChanged(
-    const std::vector<mojom::LoginUserInfoPtr>& users) {
+void LockContentsView::OnUsersChanged(const std::vector<LoginUserInfo>& users) {
   // The debug view will potentially call this method many times. Make sure to
   // invalidate any child references.
   primary_big_view_ = nullptr;
@@ -618,8 +617,8 @@
 
   // Build user state list. Preserve previous state if the user already exists.
   std::vector<UserState> new_users;
-  for (const mojom::LoginUserInfoPtr& user : users) {
-    UserState* old_state = FindStateForUser(user->basic_user_info->account_id);
+  for (const LoginUserInfo& user : users) {
+    UserState* old_state = FindStateForUser(user.basic_user_info.account_id);
     if (old_state)
       new_users.push_back(std::move(*old_state));
     else
@@ -668,6 +667,29 @@
     primary_big_view_->RequestFocus();
 }
 
+void LockContentsView::OnUserAvatarChanged(const AccountId& account_id,
+                                           const UserAvatar& avatar) {
+  auto replace = [&avatar](const LoginUserInfo& user) {
+    auto changed = user;
+    changed.basic_user_info.avatar = avatar;
+    return changed;
+  };
+
+  LoginBigUserView* big =
+      TryToFindBigUser(account_id, false /*require_auth_active*/);
+  if (big) {
+    big->UpdateForUser(replace(big->GetCurrentUser()));
+    return;
+  }
+
+  LoginUserView* user =
+      users_list_ ? users_list_->GetUserView(account_id) : nullptr;
+  if (user) {
+    user->UpdateForUser(replace(user->current_user()), false /*animate*/);
+    return;
+  }
+}
+
 void LockContentsView::OnPinEnabledForUserChanged(const AccountId& user,
                                                   bool enabled) {
   LockContentsView::UserState* state = FindStateForUser(user);
@@ -684,9 +706,8 @@
     LayoutAuth(big_user, nullptr /*opt_to_hide*/, true /*animate*/);
 }
 
-void LockContentsView::OnFingerprintStateChanged(
-    const AccountId& account_id,
-    mojom::FingerprintState state) {
+void LockContentsView::OnFingerprintStateChanged(const AccountId& account_id,
+                                                 FingerprintState state) {
   UserState* user_state = FindStateForUser(account_id);
   if (!user_state)
     return;
@@ -703,7 +724,7 @@
   // location to the target animation position and not the current position.
   bool animate = true;
   if (user_state->fingerprint_state ==
-      mojom::FingerprintState::DISABLED_FROM_TIMEOUT) {
+      FingerprintState::DISABLED_FROM_TIMEOUT) {
     animate = false;
   }
 
@@ -711,7 +732,7 @@
   LayoutAuth(big_view, nullptr /*opt_to_hide*/, animate);
 
   if (user_state->fingerprint_state ==
-      mojom::FingerprintState::DISABLED_FROM_TIMEOUT) {
+      FingerprintState::DISABLED_FROM_TIMEOUT) {
     base::string16 error_text = l10n_util::GetStringUTF16(
         IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_TIMEOUT);
     auto* label = new views::Label(error_text);
@@ -829,14 +850,13 @@
     LayoutAuth(big_user, nullptr /*opt_to_hide*/, true /*animate*/);
 }
 
-void LockContentsView::OnShowEasyUnlockIcon(
-    const AccountId& user,
-    const mojom::EasyUnlockIconOptionsPtr& icon) {
+void LockContentsView::OnShowEasyUnlockIcon(const AccountId& user,
+                                            const EasyUnlockIconOptions& icon) {
   UserState* state = FindStateForUser(user);
   if (!state)
     return;
 
-  state->easy_unlock_state = icon->Clone();
+  state->easy_unlock_state = icon;
   UpdateEasyUnlockIconForUser(user);
 
   // Show tooltip only if the user is actively showing auth.
@@ -848,9 +868,9 @@
   if (tooltip_bubble_->GetVisible())
     tooltip_bubble_->Hide();
 
-  if (icon->autoshow_tooltip) {
+  if (icon.autoshow_tooltip) {
     tooltip_bubble_->SetAnchorView(big_user->auth_user()->password_view());
-    tooltip_bubble_->SetText(icon->tooltip);
+    tooltip_bubble_->SetText(icon.tooltip);
     tooltip_bubble_->Show();
     tooltip_bubble_->SetVisible(true);
   }
@@ -955,41 +975,39 @@
   if (!user_view || !IsPublicAccountUser(user_view->current_user()))
     return;
 
-  mojom::LoginUserInfoPtr user_info = user_view->current_user()->Clone();
-  user_info->basic_user_info->display_name = display_name;
+  LoginUserInfo user_info = user_view->current_user();
+  user_info.basic_user_info.display_name = display_name;
   user_view->UpdateForUser(user_info, false /*animate*/);
 }
 
 void LockContentsView::OnPublicSessionLocalesChanged(
     const AccountId& account_id,
-    const std::vector<mojom::LocaleItemPtr>& locales,
+    const std::vector<LocaleItem>& locales,
     const std::string& default_locale,
     bool show_advanced_view) {
   LoginUserView* user_view = TryToFindUserView(account_id);
   if (!user_view || !IsPublicAccountUser(user_view->current_user()))
     return;
 
-  mojom::LoginUserInfoPtr user_info = user_view->current_user()->Clone();
-  user_info->public_account_info->available_locales = mojo::Clone(locales);
-  user_info->public_account_info->default_locale = default_locale;
-  user_info->public_account_info->show_advanced_view = show_advanced_view;
+  LoginUserInfo user_info = user_view->current_user();
+  user_info.public_account_info->available_locales = locales;
+  user_info.public_account_info->default_locale = default_locale;
+  user_info.public_account_info->show_advanced_view = show_advanced_view;
   user_view->UpdateForUser(user_info, false /*animate*/);
 }
 
 void LockContentsView::OnPublicSessionKeyboardLayoutsChanged(
     const AccountId& account_id,
     const std::string& locale,
-    const std::vector<mojom::InputMethodItemPtr>& keyboard_layouts) {
+    const std::vector<InputMethodItem>& keyboard_layouts) {
   // Update expanded view because keyboard layouts is user interactive content.
   // I.e. user selects a language locale and the corresponding keyboard layouts
   // will be changed.
   if (expanded_view_->GetVisible() &&
-      expanded_view_->current_user()->basic_user_info->account_id ==
-          account_id) {
-    mojom::LoginUserInfoPtr user_info = expanded_view_->current_user()->Clone();
-    user_info->public_account_info->default_locale = locale;
-    user_info->public_account_info->keyboard_layouts =
-        mojo::Clone(keyboard_layouts);
+      expanded_view_->current_user().basic_user_info.account_id == account_id) {
+    LoginUserInfo user_info = expanded_view_->current_user();
+    user_info.public_account_info->default_locale = locale;
+    user_info.public_account_info->keyboard_layouts = keyboard_layouts;
     expanded_view_->UpdateForUser(user_info);
   }
 
@@ -999,15 +1017,14 @@
     return;
   }
 
-  mojom::LoginUserInfoPtr user_info = user_view->current_user()->Clone();
+  LoginUserInfo user_info = user_view->current_user();
   // Skip updating keyboard layouts if |locale| is not the default locale
   // of the user. I.e. user changed the default locale in the expanded view,
   // and it should be handled by expanded view.
-  if (user_info->public_account_info->default_locale != locale)
+  if (user_info.public_account_info->default_locale != locale)
     return;
 
-  user_info->public_account_info->keyboard_layouts =
-      mojo::Clone(keyboard_layouts);
+  user_info.public_account_info->keyboard_layouts = keyboard_layouts;
   user_view->UpdateForUser(user_info, false /*animate*/);
 }
 
@@ -1027,7 +1044,7 @@
       pairing_status == DetachableBasePairingStatus::kNone ||
       (pairing_status == DetachableBasePairingStatus::kAuthenticated &&
        detachable_base_model_->PairedBaseMatchesLastUsedByUser(
-           *CurrentBigUserView()->GetCurrentUser()->basic_user_info))) {
+           CurrentBigUserView()->GetCurrentUser().basic_user_info))) {
     if (detachable_base_error_bubble_->GetVisible())
       detachable_base_error_bubble_->Hide();
     return;
@@ -1071,29 +1088,6 @@
   Layout();
 }
 
-void LockContentsView::SetAvatarForUser(const AccountId& account_id,
-                                        const mojom::UserAvatarPtr& avatar) {
-  auto replace = [&](const mojom::LoginUserInfoPtr& user) {
-    auto changed = user->Clone();
-    changed->basic_user_info->avatar = avatar->Clone();
-    return changed;
-  };
-
-  LoginBigUserView* big =
-      TryToFindBigUser(account_id, false /*require_auth_active*/);
-  if (big) {
-    big->UpdateForUser(replace(big->GetCurrentUser()));
-    return;
-  }
-
-  LoginUserView* user =
-      users_list_ ? users_list_->GetUserView(account_id) : nullptr;
-  if (user) {
-    user->UpdateForUser(replace(user->current_user()), false /*animate*/);
-    return;
-  }
-}
-
 void LockContentsView::OnFocusLeavingLockScreenApps(bool reverse) {
   if (!reverse || lock_screen_apps_active_)
     FocusNextWidget(reverse);
@@ -1193,7 +1187,7 @@
 }
 
 void LockContentsView::CreateLowDensityLayout(
-    const std::vector<mojom::LoginUserInfoPtr>& users) {
+    const std::vector<LoginUserInfo>& users) {
   DCHECK_LE(users.size(), 2u);
 
   main_view_->AddChildView(primary_big_view_);
@@ -1234,7 +1228,7 @@
 }
 
 void LockContentsView::CreateMediumDensityLayout(
-    const std::vector<mojom::LoginUserInfoPtr>& users) {
+    const std::vector<LoginUserInfo>& users) {
   // Here is a diagram of this layout:
   //
   //    a A x B y b
@@ -1303,7 +1297,7 @@
 }
 
 void LockContentsView::CreateHighDensityLayout(
-    const std::vector<mojom::LoginUserInfoPtr>& users,
+    const std::vector<LoginUserInfo>& users,
     views::BoxLayout* main_layout) {
   // Insert spacing before the auth view.
   auto* fill = new NonAccessibleView();
@@ -1414,7 +1408,7 @@
         detachable_base_model_->GetPairingStatus() ==
             DetachableBasePairingStatus::kAuthenticated) {
       detachable_base_model_->SetPairedBaseAsLastUsedByUser(
-          *CurrentBigUserView()->GetCurrentUser()->basic_user_info);
+          CurrentBigUserView()->GetCurrentUser().basic_user_info);
     }
   } else {
     ++unlock_attempt_;
@@ -1448,7 +1442,7 @@
     DCHECK(view);
     if (view->auth_user()) {
       UserState* state = FindStateForUser(
-          view->auth_user()->current_user()->basic_user_info->account_id);
+          view->auth_user()->current_user().basic_user_info.account_id);
       uint32_t to_update_auth;
       if (state->force_online_sign_in) {
         to_update_auth = LoginAuthUserView::AUTH_ONLINE_SIGN_IN;
@@ -1466,9 +1460,9 @@
           to_update_auth |= LoginAuthUserView::AUTH_PIN;
         if (state->enable_tap_auth)
           to_update_auth |= LoginAuthUserView::AUTH_TAP;
-        if (state->fingerprint_state != mojom::FingerprintState::UNAVAILABLE &&
+        if (state->fingerprint_state != FingerprintState::UNAVAILABLE &&
             state->fingerprint_state !=
-                mojom::FingerprintState::DISABLED_FROM_TIMEOUT) {
+                FingerprintState::DISABLED_FROM_TIMEOUT) {
           to_update_auth |= LoginAuthUserView::AUTH_FINGERPRINT;
         }
 
@@ -1521,9 +1515,8 @@
   DCHECK(users_list_);
   LoginUserView* view = users_list_->user_view_at(user_index);
   DCHECK(view);
-  mojom::LoginUserInfoPtr previous_big_user =
-      primary_big_view_->GetCurrentUser()->Clone();
-  mojom::LoginUserInfoPtr new_big_user = view->current_user()->Clone();
+  LoginUserInfo previous_big_user = primary_big_view_->GetCurrentUser();
+  LoginUserInfo new_big_user = view->current_user();
 
   view->UpdateForUser(previous_big_user, true /*animate*/);
   primary_big_view_->UpdateForUser(new_big_user);
@@ -1543,31 +1536,29 @@
 
   LoginBigUserView* to_remove =
       is_primary ? primary_big_view_ : opt_secondary_big_view_;
-  DCHECK(to_remove->GetCurrentUser()->can_remove);
-  AccountId user = to_remove->GetCurrentUser()->basic_user_info->account_id;
+  DCHECK(to_remove->GetCurrentUser().can_remove);
+  AccountId user = to_remove->GetCurrentUser().basic_user_info.account_id;
 
   // Ask chrome to remove the user.
   Shell::Get()->login_screen_controller()->RemoveUser(user);
 
   // Display the new user list less |user|.
-  std::vector<mojom::LoginUserInfoPtr> new_users;
+  std::vector<LoginUserInfo> new_users;
   if (!is_primary)
-    new_users.push_back(primary_big_view_->GetCurrentUser()->Clone());
+    new_users.push_back(primary_big_view_->GetCurrentUser());
   if (is_primary && opt_secondary_big_view_)
-    new_users.push_back(opt_secondary_big_view_->GetCurrentUser()->Clone());
+    new_users.push_back(opt_secondary_big_view_->GetCurrentUser());
   if (users_list_) {
     for (int i = 0; i < users_list_->user_count(); ++i) {
-      new_users.push_back(
-          users_list_->user_view_at(i)->current_user()->Clone());
+      new_users.push_back(users_list_->user_view_at(i)->current_user());
     }
   }
-  data_dispatcher_->NotifyUsers(new_users);
+  data_dispatcher_->SetUserList(new_users);
 }
 
 void LockContentsView::OnBigUserChanged() {
-  const mojom::LoginUserInfoPtr& big_user =
-      CurrentBigUserView()->GetCurrentUser();
-  const AccountId big_user_account_id = big_user->basic_user_info->account_id;
+  const LoginUserInfo& big_user = CurrentBigUserView()->GetCurrentUser();
+  const AccountId big_user_account_id = big_user.basic_user_info.account_id;
 
   CurrentBigUserView()->RequestFocus();
 
@@ -1586,7 +1577,7 @@
 
   // http://crbug/866790: After Supervised Users are deprecated, remove this.
   if (ash::features::IsSupervisedUserDeprecationNoticeEnabled() &&
-      big_user->basic_user_info->type == user_manager::USER_TYPE_SUPERVISED) {
+      big_user.basic_user_info.type == user_manager::USER_TYPE_SUPERVISED) {
     base::string16 message = l10n_util::GetStringUTF16(
         IDS_ASH_LOGIN_POD_LEGACY_SUPERVISED_EXPIRATION_WARNING);
     // Shows supervised user deprecation message as a persistent error bubble.
@@ -1628,7 +1619,7 @@
 
   // Hide easy unlock icon if there is no data is available.
   if (!state->easy_unlock_state) {
-    big_view->auth_user()->SetEasyUnlockIcon(mojom::EasyUnlockIconId::NONE,
+    big_view->auth_user()->SetEasyUnlockIcon(EasyUnlockIconId::NONE,
                                              base::string16());
     return;
   }
@@ -1662,7 +1653,7 @@
       unlock_attempt_ >= kLoginAttemptsBeforeGaiaDialog) {
     Shell::Get()->login_screen_controller()->ShowGaiaSignin(
         true /*can_close*/,
-        big_view->auth_user()->current_user()->basic_user_info->account_id);
+        big_view->auth_user()->current_user().basic_user_info.account_id);
     return;
   }
 
@@ -1718,28 +1709,26 @@
     return;
 
   UserState* state =
-      FindStateForUser(big_view->GetCurrentUser()->basic_user_info->account_id);
+      FindStateForUser(big_view->GetCurrentUser().basic_user_info.account_id);
   DCHECK(state);
-  mojom::EasyUnlockIconOptionsPtr& easy_unlock_state = state->easy_unlock_state;
-  DCHECK(easy_unlock_state);
+  DCHECK(state->easy_unlock_state);
 
-  if (!easy_unlock_state->tooltip.empty()) {
+  if (!state->easy_unlock_state->tooltip.empty()) {
     tooltip_bubble_->SetAnchorView(big_view->auth_user()->password_view());
-    tooltip_bubble_->SetText(easy_unlock_state->tooltip);
+    tooltip_bubble_->SetText(state->easy_unlock_state->tooltip);
     tooltip_bubble_->Show();
   }
 }
 
 void LockContentsView::OnEasyUnlockIconTapped() {
   UserState* state = FindStateForUser(
-      CurrentBigUserView()->GetCurrentUser()->basic_user_info->account_id);
+      CurrentBigUserView()->GetCurrentUser().basic_user_info.account_id);
   DCHECK(state);
-  mojom::EasyUnlockIconOptionsPtr& easy_unlock_state = state->easy_unlock_state;
-  DCHECK(easy_unlock_state);
+  DCHECK(state->easy_unlock_state);
 
-  if (easy_unlock_state->hardlock_on_click) {
+  if (state->easy_unlock_state->hardlock_on_click) {
     AccountId user =
-        CurrentBigUserView()->GetCurrentUser()->basic_user_info->account_id;
+        CurrentBigUserView()->GetCurrentUser().basic_user_info.account_id;
     Shell::Get()->login_screen_controller()->HardlockPod(user);
     // TODO(jdufault): This should get called as a result of HardlockPod.
     OnTapToUnlockEnabledForUserChanged(user, false /*enabled*/);
@@ -1759,18 +1748,18 @@
   const LoginBigUserView* user = CurrentBigUserView();
   // If the pod should not show an expanded view, tapping on it will launch
   // Public Session immediately.
-  if (!user->GetCurrentUser()->public_account_info->show_expanded_view) {
+  if (!user->GetCurrentUser().public_account_info->show_expanded_view) {
     std::string default_input_method;
     for (const auto& keyboard :
-         user->GetCurrentUser()->public_account_info->keyboard_layouts) {
-      if (keyboard->selected) {
-        default_input_method = keyboard->ime_id;
+         user->GetCurrentUser().public_account_info->keyboard_layouts) {
+      if (keyboard.selected) {
+        default_input_method = keyboard.ime_id;
         break;
       }
     }
     Shell::Get()->login_screen_controller()->LaunchPublicSession(
-        user->GetCurrentUser()->basic_user_info->account_id,
-        user->GetCurrentUser()->public_account_info->default_locale,
+        user->GetCurrentUser().basic_user_info.account_id,
+        user->GetCurrentUser().public_account_info->default_locale,
         default_input_method);
     return;
   }
@@ -1789,7 +1778,7 @@
 }
 
 LoginBigUserView* LockContentsView::AllocateLoginBigUserView(
-    const mojom::LoginUserInfoPtr& user,
+    const LoginUserInfo& user,
     bool is_primary) {
   LoginAuthUserView::Callbacks auth_user_callbacks;
   auth_user_callbacks.on_auth = base::BindRepeating(
@@ -1829,12 +1818,11 @@
 
   // Find auth instance.
   if (primary_big_view_ &&
-      primary_big_view_->GetCurrentUser()->basic_user_info->account_id ==
-          user) {
+      primary_big_view_->GetCurrentUser().basic_user_info.account_id == user) {
     view = primary_big_view_;
   } else if (opt_secondary_big_view_ &&
              opt_secondary_big_view_->GetCurrentUser()
-                     ->basic_user_info->account_id == user) {
+                     .basic_user_info.account_id == user) {
     view = opt_secondary_big_view_;
   }
 
@@ -1857,7 +1845,7 @@
 }
 
 ScrollableUsersListView* LockContentsView::BuildScrollableUsersListView(
-    const std::vector<mojom::LoginUserInfoPtr>& users,
+    const std::vector<LoginUserInfo>& users,
     LoginDisplayStyle display_style) {
   auto* view = new ScrollableUsersListView(
       users,
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h
index ccde9023..157d4ad 100644
--- a/ash/login/ui/lock_contents_view.h
+++ b/ash/login/ui/lock_contents_view.h
@@ -21,6 +21,7 @@
 #include "ash/login/ui/login_error_bubble.h"
 #include "ash/login/ui/login_tooltip_view.h"
 #include "ash/login/ui/non_accessible_view.h"
+#include "ash/public/cpp/login_types.h"
 #include "ash/public/cpp/system_tray_focus_observer.h"
 #include "ash/public/interfaces/login_screen.mojom.h"
 #include "ash/session/session_observer.h"
@@ -136,17 +137,16 @@
   bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
 
   // LoginScreenController::Observer:
-  void SetAvatarForUser(const AccountId& account_id,
-                        const mojom::UserAvatarPtr& avatar) override;
   void OnFocusLeavingLockScreenApps(bool reverse) override;
   void OnOobeDialogStateChanged(mojom::OobeDialogState state) override;
 
   // LoginDataDispatcher::Observer:
-  void OnUsersChanged(
-      const std::vector<mojom::LoginUserInfoPtr>& users) override;
+  void OnUsersChanged(const std::vector<LoginUserInfo>& users) override;
+  void OnUserAvatarChanged(const AccountId& account_id,
+                           const UserAvatar& avatar) override;
   void OnPinEnabledForUserChanged(const AccountId& user, bool enabled) override;
   void OnFingerprintStateChanged(const AccountId& account_id,
-                                 mojom::FingerprintState state) override;
+                                 FingerprintState state) override;
   void OnFingerprintAuthResult(const AccountId& account_id,
                                bool success) override;
   void OnAuthEnabledForUser(const AccountId& user) override;
@@ -157,9 +157,8 @@
   void OnTapToUnlockEnabledForUserChanged(const AccountId& user,
                                           bool enabled) override;
   void OnForceOnlineSignInForUser(const AccountId& user) override;
-  void OnShowEasyUnlockIcon(
-      const AccountId& user,
-      const mojom::EasyUnlockIconOptionsPtr& icon) override;
+  void OnShowEasyUnlockIcon(const AccountId& user,
+                            const EasyUnlockIconOptions& icon) override;
   void OnShowWarningBanner(const base::string16& message) override;
   void OnHideWarningBanner() override;
   void OnSystemInfoChanged(bool show,
@@ -169,15 +168,14 @@
   void OnPublicSessionDisplayNameChanged(
       const AccountId& account_id,
       const std::string& display_name) override;
-  void OnPublicSessionLocalesChanged(
-      const AccountId& account_id,
-      const std::vector<mojom::LocaleItemPtr>& locales,
-      const std::string& default_locale,
-      bool show_advanced_view) override;
+  void OnPublicSessionLocalesChanged(const AccountId& account_id,
+                                     const std::vector<LocaleItem>& locales,
+                                     const std::string& default_locale,
+                                     bool show_advanced_view) override;
   void OnPublicSessionKeyboardLayoutsChanged(
       const AccountId& account_id,
       const std::string& locale,
-      const std::vector<mojom::InputMethodItemPtr>& keyboard_layouts) override;
+      const std::vector<InputMethodItem>& keyboard_layouts) override;
   void OnPublicSessionShowFullManagementDisclosureChanged(
       bool show_full_management_disclosure) override;
   void OnDetachableBasePairingStatusChanged(
@@ -209,7 +207,7 @@
  private:
   class UserState {
    public:
-    explicit UserState(const mojom::LoginUserInfoPtr& user_info);
+    explicit UserState(const LoginUserInfo& user_info);
     UserState(UserState&&);
     ~UserState();
 
@@ -218,8 +216,8 @@
     bool enable_tap_auth = false;
     bool force_online_sign_in = false;
     bool disable_auth = false;
-    mojom::EasyUnlockIconOptionsPtr easy_unlock_state;
-    mojom::FingerprintState fingerprint_state;
+    base::Optional<EasyUnlockIconOptions> easy_unlock_state;
+    FingerprintState fingerprint_state;
 
    private:
     DISALLOW_COPY_AND_ASSIGN(UserState);
@@ -233,15 +231,12 @@
   void FocusNextWidget(bool reverse);
 
   // 1-2 users.
-  void CreateLowDensityLayout(
-      const std::vector<mojom::LoginUserInfoPtr>& users);
+  void CreateLowDensityLayout(const std::vector<LoginUserInfo>& users);
   // 3-6 users.
-  void CreateMediumDensityLayout(
-      const std::vector<mojom::LoginUserInfoPtr>& users);
+  void CreateMediumDensityLayout(const std::vector<LoginUserInfo>& users);
   // 7+ users.
-  void CreateHighDensityLayout(
-      const std::vector<mojom::LoginUserInfoPtr>& users,
-      views::BoxLayout* main_layout);
+  void CreateHighDensityLayout(const std::vector<LoginUserInfo>& users,
+                               views::BoxLayout* main_layout);
 
   // Lay out the entire view. This is called when the view is attached to a
   // widget and when the screen is rotated.
@@ -319,9 +314,8 @@
   void OnPublicAccountTapped(bool is_primary);
 
   // Helper method to allocate a LoginBigUserView instance.
-  LoginBigUserView* AllocateLoginBigUserView(
-      const mojom::LoginUserInfoPtr& user,
-      bool is_primary);
+  LoginBigUserView* AllocateLoginBigUserView(const LoginUserInfo& user,
+                                             bool is_primary);
 
   // Returns the big view for |user| if |user| is one of the active
   // big views. If |require_auth_active| is true then the view must
@@ -334,7 +328,7 @@
 
   // Returns scrollable view with initialized size and rows for all |users|.
   ScrollableUsersListView* BuildScrollableUsersListView(
-      const std::vector<mojom::LoginUserInfoPtr>& users,
+      const std::vector<LoginUserInfo>& users,
       LoginDisplayStyle display_style);
 
   // Change the visibility of child views based on the |style|.
diff --git a/ash/login/ui/lock_contents_view_unittest.cc b/ash/login/ui/lock_contents_view_unittest.cc
index 199632b..d418441 100644
--- a/ash/login/ui/lock_contents_view_unittest.cc
+++ b/ash/login/ui/lock_contents_view_unittest.cc
@@ -115,8 +115,8 @@
       LoginUserView::TestApi user_test_api(users_list.user_views()[i]);
       EXPECT_EQ(expected_style, user_test_api.display_style());
 
-      const mojom::LoginUserInfoPtr& user = users()[i + 1];
-      EXPECT_EQ(base::UTF8ToUTF16(user->basic_user_info->display_name),
+      const LoginUserInfo& user = users()[i + 1];
+      EXPECT_EQ(base::UTF8ToUTF16(user.basic_user_info.display_name),
                 user_test_api.displayed_name());
     }
   }
@@ -443,12 +443,11 @@
   std::unique_ptr<views::Widget> widget = CreateWidgetWithContent(contents);
 
   // Capture user info to validate it did not change during the swap.
-  AccountId primary_user = test_api.primary_big_view()
-                               ->GetCurrentUser()
-                               ->basic_user_info->account_id;
+  AccountId primary_user =
+      test_api.primary_big_view()->GetCurrentUser().basic_user_info.account_id;
   AccountId secondary_user = test_api.opt_secondary_big_view()
                                  ->GetCurrentUser()
-                                 ->basic_user_info->account_id;
+                                 .basic_user_info.account_id;
   EXPECT_NE(primary_user, secondary_user);
 
   // Primary user starts with auth. Secondary user does not have any auth.
@@ -465,12 +464,12 @@
   generator->ClickLeftButton();
 
   // User info is not swapped.
-  EXPECT_EQ(primary_user, test_api.primary_big_view()
-                              ->GetCurrentUser()
-                              ->basic_user_info->account_id);
+  EXPECT_EQ(
+      primary_user,
+      test_api.primary_big_view()->GetCurrentUser().basic_user_info.account_id);
   EXPECT_EQ(secondary_user, test_api.opt_secondary_big_view()
                                 ->GetCurrentUser()
-                                ->basic_user_info->account_id);
+                                .basic_user_info.account_id);
 
   // Active auth user (ie, which user is showing password) is swapped.
   EXPECT_FALSE(test_api.primary_big_view()->IsAuthEnabled());
@@ -494,10 +493,9 @@
 
   for (const LoginUserView* const list_user_view : users_list.user_views()) {
     // Capture user info to validate it did not change during the swap.
-    AccountId auth_id =
-        auth_view->GetCurrentUser()->basic_user_info->account_id;
+    AccountId auth_id = auth_view->GetCurrentUser().basic_user_info.account_id;
     AccountId list_user_id =
-        list_user_view->current_user()->basic_user_info->account_id;
+        list_user_view->current_user().basic_user_info.account_id;
     EXPECT_NE(auth_id, list_user_id);
 
     // Send event to swap users.
@@ -507,15 +505,15 @@
 
     // User info is swapped.
     EXPECT_EQ(list_user_id,
-              auth_view->GetCurrentUser()->basic_user_info->account_id);
+              auth_view->GetCurrentUser().basic_user_info.account_id);
     EXPECT_EQ(auth_id,
-              list_user_view->current_user()->basic_user_info->account_id);
+              list_user_view->current_user().basic_user_info.account_id);
 
     // Validate that every user is still unique.
     std::unordered_set<std::string> emails;
     for (const LoginUserView* const view : users_list.user_views()) {
       std::string email =
-          view->current_user()->basic_user_info->account_id.GetUserEmail();
+          view->current_user().basic_user_info.account_id.GetUserEmail();
       EXPECT_TRUE(emails.insert(email).second);
     }
   }
@@ -730,16 +728,16 @@
 
   // Show an icon with |autoshow_tooltip| is false. Tooltip bubble is not
   // activated.
-  auto icon = mojom::EasyUnlockIconOptions::New();
-  icon->icon = mojom::EasyUnlockIconId::LOCKED;
-  icon->autoshow_tooltip = false;
-  DataDispatcher()->ShowEasyUnlockIcon(users()[0]->basic_user_info->account_id,
+  EasyUnlockIconOptions icon;
+  icon.icon = EasyUnlockIconId::LOCKED;
+  icon.autoshow_tooltip = false;
+  DataDispatcher()->ShowEasyUnlockIcon(users()[0].basic_user_info.account_id,
                                        icon);
   EXPECT_FALSE(test_api.tooltip_bubble()->GetVisible());
 
   // Show icon with |autoshow_tooltip| set to true. Tooltip bubble is shown.
-  icon->autoshow_tooltip = true;
-  DataDispatcher()->ShowEasyUnlockIcon(users()[0]->basic_user_info->account_id,
+  icon.autoshow_tooltip = true;
+  DataDispatcher()->ShowEasyUnlockIcon(users()[0].basic_user_info.account_id,
                                        icon);
   EXPECT_TRUE(test_api.tooltip_bubble()->GetVisible());
 }
@@ -772,18 +770,18 @@
 
   // Enables easy unlock icon for |view|.
   auto enable_icon = [&](LoginBigUserView* view) {
-    auto icon = mojom::EasyUnlockIconOptions::New();
-    icon->icon = mojom::EasyUnlockIconId::LOCKED;
+    EasyUnlockIconOptions icon;
+    icon.icon = EasyUnlockIconId::LOCKED;
     DataDispatcher()->ShowEasyUnlockIcon(
-        view->GetCurrentUser()->basic_user_info->account_id, icon);
+        view->GetCurrentUser().basic_user_info.account_id, icon);
   };
 
   // Disables easy unlock icon for |view|.
   auto disable_icon = [&](LoginBigUserView* view) {
-    auto icon = mojom::EasyUnlockIconOptions::New();
-    icon->icon = mojom::EasyUnlockIconId::NONE;
+    EasyUnlockIconOptions icon;
+    icon.icon = EasyUnlockIconId::NONE;
     DataDispatcher()->ShowEasyUnlockIcon(
-        view->GetCurrentUser()->basic_user_info->account_id, icon);
+        view->GetCurrentUser().basic_user_info.account_id, icon);
   };
 
   // Makes |view| the active auth view so it will can show auth methods.
@@ -850,9 +848,8 @@
   // Password submit runs mojo.
   std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
   client->set_authenticate_user_callback_result(false);
-  EXPECT_CALL(*client,
-              AuthenticateUserWithPasswordOrPin_(
-                  users()[0]->basic_user_info->account_id, _, false, _));
+  EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin_(
+                           users()[0].basic_user_info.account_id, _, false, _));
 
   // Submit password.
   ui::test::EventGenerator* generator = GetEventGenerator();
@@ -882,9 +879,8 @@
   // Password submit runs mojo.
   std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
   client->set_authenticate_user_callback_result(false);
-  EXPECT_CALL(*client,
-              AuthenticateUserWithPasswordOrPin_(
-                  users()[0]->basic_user_info->account_id, _, false, _));
+  EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin_(
+                           users()[0].basic_user_info.account_id, _, false, _));
 
   // AuthErrorButton should not be visible yet.
   EXPECT_FALSE(test_api.auth_error_bubble()->GetVisible());
@@ -971,7 +967,7 @@
   EXPECT_CALL(*client,
               ShowGaiaSignin(true /*can_close*/,
                              base::Optional<AccountId>(
-                                 users()[0]->basic_user_info->account_id)))
+                                 users()[0].basic_user_info.account_id)))
       .Times(1);
   submit_password();
   Mock::VerifyAndClearExpectations(client.get());
@@ -989,10 +985,8 @@
       DataDispatcher(), std::move(fake_detachable_base_model));
   SetUserCount(2);
 
-  const AccountId& kFirstUserAccountId =
-      users()[0]->basic_user_info->account_id;
-  const AccountId& kSecondUserAccountId =
-      users()[1]->basic_user_info->account_id;
+  const AccountId& kFirstUserAccountId = users()[0].basic_user_info.account_id;
+  const AccountId& kSecondUserAccountId = users()[1].basic_user_info.account_id;
 
   // Initialize the detachable base state, so the user 1 has previously used
   // detachable base.
@@ -1071,10 +1065,8 @@
       DataDispatcher(), std::move(fake_detachable_base_model));
   SetUserCount(2);
 
-  const AccountId& kFirstUserAccountId =
-      users()[0]->basic_user_info->account_id;
-  const AccountId& kSecondUserAccountId =
-      users()[1]->basic_user_info->account_id;
+  const AccountId& kFirstUserAccountId = users()[0].basic_user_info.account_id;
+  const AccountId& kSecondUserAccountId = users()[1].basic_user_info.account_id;
 
   detachable_base_model->InitLastUsedBases({{kSecondUserAccountId, "5678"}});
 
@@ -1134,7 +1126,7 @@
       DataDispatcher(), std::move(fake_detachable_base_model));
   SetUserCount(1);
 
-  const AccountId& kUserAccountId = users()[0]->basic_user_info->account_id;
+  const AccountId& kUserAccountId = users()[0].basic_user_info.account_id;
 
   // Initialize the detachable base state, as if the user has previously used
   // detachable base.
@@ -1170,7 +1162,7 @@
       DataDispatcher(), std::move(fake_detachable_base_model));
   SetUserCount(1);
 
-  const AccountId& kUserAccountId = users()[0]->basic_user_info->account_id;
+  const AccountId& kUserAccountId = users()[0].basic_user_info.account_id;
 
   // Initialize the detachable base state, as if the user has previously used
   // detachable base.
@@ -1221,7 +1213,7 @@
       DataDispatcher(), std::move(fake_detachable_base_model));
   SetUserCount(1);
 
-  const AccountId& kUserAccountId = users()[0]->basic_user_info->account_id;
+  const AccountId& kUserAccountId = users()[0].basic_user_info.account_id;
 
   // Initialize the detachable base state, as if the user has previously used
   // detachable base.
@@ -1453,12 +1445,11 @@
   LockContentsView::TestApi test_api(contents);
 
   // Capture user info to validate it did not change during the swap.
-  AccountId primary_user = test_api.primary_big_view()
-                               ->GetCurrentUser()
-                               ->basic_user_info->account_id;
+  AccountId primary_user =
+      test_api.primary_big_view()->GetCurrentUser().basic_user_info.account_id;
   AccountId secondary_user = test_api.opt_secondary_big_view()
                                  ->GetCurrentUser()
-                                 ->basic_user_info->account_id;
+                                 .basic_user_info.account_id;
   EXPECT_NE(primary_user, secondary_user);
 
   // Primary user starts with auth. Secondary user does not have any auth.
@@ -1480,12 +1471,12 @@
   generator->ClickLeftButton();
 
   // User info is not swapped.
-  EXPECT_EQ(primary_user, test_api.primary_big_view()
-                              ->GetCurrentUser()
-                              ->basic_user_info->account_id);
+  EXPECT_EQ(
+      primary_user,
+      test_api.primary_big_view()->GetCurrentUser().basic_user_info.account_id);
   EXPECT_EQ(secondary_user, test_api.opt_secondary_big_view()
                                 ->GetCurrentUser()
-                                ->basic_user_info->account_id);
+                                .basic_user_info.account_id);
 
   // Child view of LoginBigUserView stays the same.
   ASSERT_TRUE(test_api.primary_big_view()->public_account());
@@ -1533,7 +1524,7 @@
   };
 
   auto is_public_account = [](const LoginUserView* view) -> bool {
-    return view->current_user()->basic_user_info->type ==
+    return view->current_user().basic_user_info.type ==
            user_manager::USER_TYPE_PUBLIC_ACCOUNT;
   };
 
@@ -1541,9 +1532,9 @@
   // account user).
   EXPECT_TRUE(is_public_account(user_view0));
   AccountId primary_id =
-      primary_big_view->GetCurrentUser()->basic_user_info->account_id;
+      primary_big_view->GetCurrentUser().basic_user_info.account_id;
   AccountId list_user_id =
-      user_view0->current_user()->basic_user_info->account_id;
+      user_view0->current_user().basic_user_info.account_id;
   EXPECT_NE(primary_id, list_user_id);
 
   // Send event to swap users.
@@ -1551,9 +1542,8 @@
 
   // User info is swapped.
   EXPECT_EQ(list_user_id,
-            primary_big_view->GetCurrentUser()->basic_user_info->account_id);
-  EXPECT_EQ(primary_id,
-            user_view0->current_user()->basic_user_info->account_id);
+            primary_big_view->GetCurrentUser().basic_user_info.account_id);
+  EXPECT_EQ(primary_id, user_view0->current_user().basic_user_info.account_id);
 
   // Child view of primary big user stays the same.
   ASSERT_TRUE(primary_big_view->public_account());
@@ -1564,8 +1554,8 @@
   // Case 2: Swap user_view1 (auth user) with primary big user (public account
   // user).
   EXPECT_FALSE(is_public_account(user_view1));
-  primary_id = primary_big_view->GetCurrentUser()->basic_user_info->account_id;
-  list_user_id = user_view1->current_user()->basic_user_info->account_id;
+  primary_id = primary_big_view->GetCurrentUser().basic_user_info.account_id;
+  list_user_id = user_view1->current_user().basic_user_info.account_id;
   EXPECT_NE(primary_id, list_user_id);
 
   // Send event to swap users.
@@ -1573,9 +1563,8 @@
 
   // User info is swapped.
   EXPECT_EQ(list_user_id,
-            primary_big_view->GetCurrentUser()->basic_user_info->account_id);
-  EXPECT_EQ(primary_id,
-            user_view1->current_user()->basic_user_info->account_id);
+            primary_big_view->GetCurrentUser().basic_user_info.account_id);
+  EXPECT_EQ(primary_id, user_view1->current_user().basic_user_info.account_id);
 
   // Primary big user becomes auth user and its child view is rebuilt.
   ASSERT_FALSE(primary_big_view->public_account());
@@ -1585,8 +1574,8 @@
 
   // Case 3: Swap user_view2 (auth user) with primary big user (auth user).
   EXPECT_FALSE(is_public_account(user_view2));
-  primary_id = primary_big_view->GetCurrentUser()->basic_user_info->account_id;
-  list_user_id = user_view2->current_user()->basic_user_info->account_id;
+  primary_id = primary_big_view->GetCurrentUser().basic_user_info.account_id;
+  list_user_id = user_view2->current_user().basic_user_info.account_id;
   EXPECT_NE(primary_id, list_user_id);
 
   // Send event to swap users.
@@ -1594,9 +1583,8 @@
 
   // User info is swapped.
   EXPECT_EQ(list_user_id,
-            primary_big_view->GetCurrentUser()->basic_user_info->account_id);
-  EXPECT_EQ(primary_id,
-            user_view2->current_user()->basic_user_info->account_id);
+            primary_big_view->GetCurrentUser().basic_user_info.account_id);
+  EXPECT_EQ(primary_id, user_view2->current_user().basic_user_info.account_id);
 
   // Child view of primary big user stays the same.
   ASSERT_FALSE(primary_big_view->public_account());
@@ -1607,8 +1595,8 @@
   // Case 4: Swap user_view0 (public account user) with with primary big user
   // (auth user).
   EXPECT_TRUE(is_public_account(user_view0));
-  primary_id = primary_big_view->GetCurrentUser()->basic_user_info->account_id;
-  list_user_id = user_view0->current_user()->basic_user_info->account_id;
+  primary_id = primary_big_view->GetCurrentUser().basic_user_info.account_id;
+  list_user_id = user_view0->current_user().basic_user_info.account_id;
   EXPECT_NE(primary_id, list_user_id);
 
   // Send event to swap users.
@@ -1616,9 +1604,8 @@
 
   // User info is swapped.
   EXPECT_EQ(list_user_id,
-            primary_big_view->GetCurrentUser()->basic_user_info->account_id);
-  EXPECT_EQ(primary_id,
-            user_view0->current_user()->basic_user_info->account_id);
+            primary_big_view->GetCurrentUser().basic_user_info.account_id);
+  EXPECT_EQ(primary_id, user_view0->current_user().basic_user_info.account_id);
 
   // Primary big user becomes public account user and its child view is rebuilt.
   ASSERT_TRUE(primary_big_view->public_account());
@@ -1774,7 +1761,7 @@
 
   LoginBigUserView* primary_big_view = lock_contents.primary_big_view();
   AccountId primary_id =
-      primary_big_view->GetCurrentUser()->basic_user_info->account_id;
+      primary_big_view->GetCurrentUser().basic_user_info.account_id;
 
   // Open the expanded public session view.
   ui::test::EventGenerator* generator = GetEventGenerator();
@@ -1782,7 +1769,7 @@
 
   EXPECT_FALSE(main_view->GetVisible());
   EXPECT_TRUE(expanded_view->GetVisible());
-  EXPECT_EQ(expanded_view->current_user()->basic_user_info->account_id,
+  EXPECT_EQ(expanded_view->current_user().basic_user_info.account_id,
             primary_id);
 
   // Expect LanuchPublicSession mojo call when the submit button is clicked.
@@ -1805,8 +1792,7 @@
   SetUserCount(1);
   SetWidget(CreateWidgetWithContent(contents));
 
-  const AccountId& kFirstUserAccountId =
-      users()[0]->basic_user_info->account_id;
+  const AccountId& kFirstUserAccountId = users()[0].basic_user_info.account_id;
   LockContentsView::TestApi contents_test_api(contents);
   LoginAuthUserView::TestApi auth_test_api(
       contents_test_api.primary_big_view()->auth_user());
@@ -1869,8 +1855,7 @@
   SetUserCount(1);
   SetWidget(CreateWidgetWithContent(contents));
 
-  const AccountId& kFirstUserAccountId =
-      users()[0]->basic_user_info->account_id;
+  const AccountId& kFirstUserAccountId = users()[0].basic_user_info.account_id;
   LockContentsView::TestApi contents_test_api(contents);
   views::View* note_action_button = contents_test_api.note_action();
 
@@ -1911,8 +1896,7 @@
   SetUserCount(1);
   SetWidget(CreateWidgetWithContent(contents));
 
-  const AccountId& kFirstUserAccountId =
-      users()[0]->basic_user_info->account_id;
+  const AccountId& kFirstUserAccountId = users()[0].basic_user_info.account_id;
   LockContentsView::TestApi contents_test_api(contents);
   LoginAuthUserView::TestApi auth_test_api(
       contents_test_api.primary_big_view()->auth_user());
@@ -2150,9 +2134,8 @@
 
   LockContentsView::TestApi test_api(contents);
 
-  AccountId primary_user = test_api.primary_big_view()
-                               ->GetCurrentUser()
-                               ->basic_user_info->account_id;
+  AccountId primary_user =
+      test_api.primary_big_view()->GetCurrentUser().basic_user_info.account_id;
   DataDispatcher()->SetPinEnabledForUser(primary_user, true);
 
   // This user should be identical to the user we enabled PIN for.
@@ -2173,7 +2156,7 @@
   SetUserCount(1);
   SetWidget(CreateWidgetWithContent(lock));
 
-  const AccountId& kUserAccountId = users()[0]->basic_user_info->account_id;
+  const AccountId& kUserAccountId = users()[0].basic_user_info.account_id;
 
   LockContentsView::TestApi test_api(lock);
   ui::test::EventGenerator* generator = GetEventGenerator();
@@ -2220,8 +2203,8 @@
       std::make_unique<FakeLoginDetachableBaseModel>(DataDispatcher()));
   AddPublicAccountUsers(1);
   AddUsers(1);
-  users()[1]->can_remove = true;
-  DataDispatcher()->NotifyUsers(users());
+  users()[1].can_remove = true;
+  DataDispatcher()->SetUserList(users());
   SetWidget(CreateWidgetWithContent(lock));
 
   LockContentsView::TestApi test_api(lock);
@@ -2271,8 +2254,8 @@
 
   // Change fingerprint state; backlights remain forced off.
   DataDispatcher()->SetFingerprintState(
-      users()[0]->basic_user_info->account_id,
-      mojom::FingerprintState::DISABLED_FROM_ATTEMPTS);
+      users()[0].basic_user_info.account_id,
+      FingerprintState::DISABLED_FROM_ATTEMPTS);
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(
       Shell::Get()->backlights_forced_off_setter()->backlights_forced_off());
@@ -2303,7 +2286,7 @@
   // Validate a fingerprint authentication attempt resets backlights being
   // forced off.
   DataDispatcher()->NotifyFingerprintAuthResult(
-      users()[0]->basic_user_info->account_id, false /*successful*/);
+      users()[0].basic_user_info.account_id, false /*successful*/);
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(
       Shell::Get()->backlights_forced_off_setter()->backlights_forced_off());
@@ -2386,9 +2369,9 @@
   LoginBigUserView* auth_view = lock_contents.primary_big_view();
 
   AccountId auth_view_user =
-      auth_view->GetCurrentUser()->basic_user_info->account_id;
+      auth_view->GetCurrentUser().basic_user_info.account_id;
   AccountId list_user =
-      list_user_view->current_user()->basic_user_info->account_id;
+      list_user_view->current_user().basic_user_info.account_id;
 
   Shell::Get()->login_screen_controller()->NotifyOobeDialogState(
       mojom::OobeDialogState::GAIA_SIGNIN);
@@ -2400,9 +2383,9 @@
 
   // User info is not swapped.
   EXPECT_EQ(auth_view_user,
-            auth_view->GetCurrentUser()->basic_user_info->account_id);
+            auth_view->GetCurrentUser().basic_user_info.account_id);
   EXPECT_EQ(list_user,
-            list_user_view->current_user()->basic_user_info->account_id);
+            list_user_view->current_user().basic_user_info.account_id);
 
   // Hide OOBE dialog.
   Shell::Get()->login_screen_controller()->NotifyOobeDialogState(
@@ -2413,10 +2396,9 @@
   generator->ClickLeftButton();
 
   // User info should be now swapped.
-  EXPECT_EQ(list_user,
-            auth_view->GetCurrentUser()->basic_user_info->account_id);
+  EXPECT_EQ(list_user, auth_view->GetCurrentUser().basic_user_info.account_id);
   EXPECT_EQ(auth_view_user,
-            list_user_view->current_user()->basic_user_info->account_id);
+            list_user_view->current_user().basic_user_info.account_id);
 }
 
 }  // namespace ash
diff --git a/ash/login/ui/lock_debug_view.cc b/ash/login/ui/lock_debug_view.cc
index 6d56df3..f5831f07 100644
--- a/ash/login/ui/lock_debug_view.cc
+++ b/ash/login/ui/lock_debug_view.cc
@@ -19,6 +19,7 @@
 #include "ash/login/ui/non_accessible_view.h"
 #include "ash/login/ui/views_utils.h"
 #include "ash/public/cpp/kiosk_app_menu.h"
+#include "ash/public/cpp/login_types.h"
 #include "ash/shelf/login_shelf_view.h"
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_widget.h"
@@ -28,6 +29,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/optional.h"
 #include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/base/ime/chromeos/ime_keyboard.h"
 #include "ui/views/controls/button/md_text_button.h"
@@ -98,10 +100,10 @@
 
 // Additional state for a user that the debug UI needs to reference.
 struct UserMetadata {
-  explicit UserMetadata(const mojom::UserInfoPtr& user_info)
-      : account_id(user_info->account_id),
-        display_name(user_info->display_name),
-        type(user_info->type) {}
+  explicit UserMetadata(const UserInfo& user_info)
+      : account_id(user_info.account_id),
+        display_name(user_info.display_name),
+        type(user_info.type) {}
 
   AccountId account_id;
   std::string display_name;
@@ -109,9 +111,8 @@
   bool enable_tap_to_unlock = false;
   bool enable_auth = true;
   user_manager::UserType type = user_manager::USER_TYPE_REGULAR;
-  mojom::EasyUnlockIconId easy_unlock_id = mojom::EasyUnlockIconId::NONE;
-  mojom::FingerprintState fingerprint_state =
-      mojom::FingerprintState::UNAVAILABLE;
+  EasyUnlockIconId easy_unlock_id = EasyUnlockIconId::NONE;
+  FingerprintState fingerprint_state = FingerprintState::UNAVAILABLE;
 };
 
 std::string DetachableBasePairingStatusToString(
@@ -130,43 +131,43 @@
 }
 
 // Update the user data based on |type| and |user_index|.
-mojom::LoginUserInfoPtr PopulateUserData(const mojom::LoginUserInfoPtr& user,
-                                         user_manager::UserType type,
-                                         int user_index) {
-  mojom::LoginUserInfoPtr result = user->Clone();
-  result->basic_user_info->type = type;
+LoginUserInfo PopulateUserData(const LoginUserInfo& user,
+                               user_manager::UserType type,
+                               int user_index) {
+  LoginUserInfo result = user;
+  result.basic_user_info.type = type;
 
   bool is_public_account = type == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
   // Set debug user names and email. Useful for the stub user, which does not
   // have a name  and email set.
-  result->basic_user_info->display_name =
+  result.basic_user_info.display_name =
       is_public_account
           ? kDebugPublicAccountNames[user_index %
                                      base::size(kDebugPublicAccountNames)]
           : kDebugUserNames[user_index % base::size(kDebugUserNames)];
-  result->basic_user_info->display_email =
-      result->basic_user_info->account_id.GetUserEmail();
+  result.basic_user_info.display_email =
+      result.basic_user_info.account_id.GetUserEmail();
 
   if (is_public_account) {
-    result->public_account_info = mojom::PublicAccountInfo::New();
-    result->public_account_info->enterprise_domain = kDebugEnterpriseDomain;
-    result->public_account_info->default_locale = kDebugDefaultLocaleCode;
-    result->public_account_info->show_expanded_view = true;
+    result.public_account_info.emplace();
+    result.public_account_info->enterprise_domain = kDebugEnterpriseDomain;
+    result.public_account_info->default_locale = kDebugDefaultLocaleCode;
+    result.public_account_info->show_expanded_view = true;
 
-    std::vector<mojom::LocaleItemPtr> locales;
-    mojom::LocaleItemPtr locale_item = mojom::LocaleItem::New();
-    locale_item->language_code = kDebugDefaultLocaleCode;
-    locale_item->title = kDebugDefaultLocaleTitle;
-    locales.push_back(std::move(locale_item));
-    result->public_account_info->available_locales = std::move(locales);
+    std::vector<LocaleItem> locales;
+    LocaleItem locale_item;
+    locale_item.language_code = kDebugDefaultLocaleCode;
+    locale_item.title = kDebugDefaultLocaleTitle;
+    result.public_account_info->available_locales.push_back(
+        std::move(locale_item));
 
     // Request keyboard layouts for the default locale.
     Shell::Get()
         ->login_screen_controller()
-        ->RequestPublicSessionKeyboardLayouts(
-            result->basic_user_info->account_id, kDebugDefaultLocaleCode);
+        ->RequestPublicSessionKeyboardLayouts(result.basic_user_info.account_id,
+                                              kDebugDefaultLocaleCode);
   } else {
-    result->public_account_info.reset();
+    result.public_account_info.reset();
   }
 
   return result;
@@ -174,9 +175,10 @@
 
 }  // namespace
 
-// Applies a series of user-defined transformations to a |LoginDataDispatcher|
-// instance; this is used for debugging and development. The debug overlay uses
-// this class to change what data is exposed to the UI.
+// Applies a series of user-defined transformations to a
+// |LoginDataDispatcher| instance; this is used for debugging and
+// development. The debug overlay uses this class to change what data is exposed
+// to the UI.
 class LockDebugView::DebugDataDispatcherTransformer
     : public LoginDataDispatcher::Observer {
  public:
@@ -199,7 +201,7 @@
   void SetUserCount(int count) { NotifyUsers(BuildUserList(count)); }
 
   // Create user list.
-  std::vector<mojom::LoginUserInfoPtr> BuildUserList(int count) {
+  std::vector<LoginUserInfo> BuildUserList(int count) {
     DCHECK(!root_users_.empty());
 
     count = std::max(count, 0);
@@ -209,36 +211,36 @@
       debug_users_.erase(debug_users_.begin() + count, debug_users_.end());
 
     // Build |users|, add any new users to |debug_users|.
-    std::vector<mojom::LoginUserInfoPtr> users;
+    std::vector<LoginUserInfo> users;
     for (size_t i = 0; i < size_t{count}; ++i) {
-      users.push_back(root_users_[i % root_users_.size()]->Clone());
+      users.push_back(root_users_[i % root_users_.size()]);
       if (i >= root_users_.size()) {
-        users[i]->basic_user_info->account_id = AccountId::FromUserEmailGaiaId(
-            users[i]->basic_user_info->account_id.GetUserEmail() +
-                std::to_string(i),
-            users[i]->basic_user_info->account_id.GetGaiaId() +
-                std::to_string(i));
+        users[i].basic_user_info.account_id = AccountId::FromUserEmailGaiaId(
+            users[i].basic_user_info.account_id.GetUserEmail() +
+                base::NumberToString(i),
+            users[i].basic_user_info.account_id.GetGaiaId() +
+                base::NumberToString(i));
       }
 
       // Setup user data based on the user type in debug_users_.
       user_manager::UserType type = (i < debug_users_.size())
                                         ? debug_users_[i].type
-                                        : users[i]->basic_user_info->type;
+                                        : users[i].basic_user_info.type;
       users[i] = PopulateUserData(users[i], type, i);
 
       if (i >= debug_users_.size())
-        debug_users_.push_back(UserMetadata(users[i]->basic_user_info));
+        debug_users_.push_back(UserMetadata(users[i].basic_user_info));
     }
 
     return users;
   }
 
-  void NotifyUsers(std::vector<mojom::LoginUserInfoPtr> users) {
+  void NotifyUsers(const std::vector<LoginUserInfo>& users) {
     // User notification resets PIN state.
     for (UserMetadata& user : debug_users_)
       user.enable_pin = false;
 
-    debug_dispatcher_.NotifyUsers(users);
+    debug_dispatcher_.SetUserList(users);
   }
 
   int GetUserCount() const { return debug_users_.size(); }
@@ -278,45 +280,45 @@
     UserMetadata* debug_user = &debug_users_[user_index];
 
     // EasyUnlockIconId state transition.
-    auto get_next_id = [](mojom::EasyUnlockIconId id) {
+    auto get_next_id = [](EasyUnlockIconId id) {
       switch (id) {
-        case mojom::EasyUnlockIconId::NONE:
-          return mojom::EasyUnlockIconId::SPINNER;
-        case mojom::EasyUnlockIconId::SPINNER:
-          return mojom::EasyUnlockIconId::LOCKED;
-        case mojom::EasyUnlockIconId::LOCKED:
-          return mojom::EasyUnlockIconId::LOCKED_TO_BE_ACTIVATED;
-        case mojom::EasyUnlockIconId::LOCKED_TO_BE_ACTIVATED:
-          return mojom::EasyUnlockIconId::LOCKED_WITH_PROXIMITY_HINT;
-        case mojom::EasyUnlockIconId::LOCKED_WITH_PROXIMITY_HINT:
-          return mojom::EasyUnlockIconId::HARDLOCKED;
-        case mojom::EasyUnlockIconId::HARDLOCKED:
-          return mojom::EasyUnlockIconId::UNLOCKED;
-        case mojom::EasyUnlockIconId::UNLOCKED:
-          return mojom::EasyUnlockIconId::NONE;
+        case EasyUnlockIconId::NONE:
+          return EasyUnlockIconId::SPINNER;
+        case EasyUnlockIconId::SPINNER:
+          return EasyUnlockIconId::LOCKED;
+        case EasyUnlockIconId::LOCKED:
+          return EasyUnlockIconId::LOCKED_TO_BE_ACTIVATED;
+        case EasyUnlockIconId::LOCKED_TO_BE_ACTIVATED:
+          return EasyUnlockIconId::LOCKED_WITH_PROXIMITY_HINT;
+        case EasyUnlockIconId::LOCKED_WITH_PROXIMITY_HINT:
+          return EasyUnlockIconId::HARDLOCKED;
+        case EasyUnlockIconId::HARDLOCKED:
+          return EasyUnlockIconId::UNLOCKED;
+        case EasyUnlockIconId::UNLOCKED:
+          return EasyUnlockIconId::NONE;
       }
-      return mojom::EasyUnlockIconId::NONE;
+      return EasyUnlockIconId::NONE;
     };
     debug_user->easy_unlock_id = get_next_id(debug_user->easy_unlock_id);
 
     // Enable/disable click to unlock.
     debug_user->enable_tap_to_unlock =
-        debug_user->easy_unlock_id == mojom::EasyUnlockIconId::UNLOCKED;
+        debug_user->easy_unlock_id == EasyUnlockIconId::UNLOCKED;
 
     // Prepare icon that we will show.
-    auto icon = mojom::EasyUnlockIconOptions::New();
-    icon->icon = debug_user->easy_unlock_id;
-    if (icon->icon == mojom::EasyUnlockIconId::SPINNER) {
-      icon->aria_label = base::ASCIIToUTF16("Icon is spinning");
-    } else if (icon->icon == mojom::EasyUnlockIconId::LOCKED ||
-               icon->icon == mojom::EasyUnlockIconId::LOCKED_TO_BE_ACTIVATED) {
-      icon->autoshow_tooltip = true;
-      icon->tooltip = base::ASCIIToUTF16(
+    EasyUnlockIconOptions icon;
+    icon.icon = debug_user->easy_unlock_id;
+    if (icon.icon == EasyUnlockIconId::SPINNER) {
+      icon.aria_label = base::ASCIIToUTF16("Icon is spinning");
+    } else if (icon.icon == EasyUnlockIconId::LOCKED ||
+               icon.icon == EasyUnlockIconId::LOCKED_TO_BE_ACTIVATED) {
+      icon.autoshow_tooltip = true;
+      icon.tooltip = base::ASCIIToUTF16(
           "This is a long message to trigger overflow. This should show up "
           "automatically. icon_id=" +
-          std::to_string(static_cast<int>(icon->icon)));
+          base::NumberToString(static_cast<int>(icon.icon)));
     } else {
-      icon->tooltip =
+      icon.tooltip =
           base::ASCIIToUTF16("This should not show up automatically.");
     }
 
@@ -331,9 +333,9 @@
     DCHECK(user_index >= 0 && user_index < debug_users_.size());
     UserMetadata* debug_user = &debug_users_[user_index];
 
-    debug_user->fingerprint_state = static_cast<mojom::FingerprintState>(
+    debug_user->fingerprint_state = static_cast<FingerprintState>(
         (static_cast<int>(debug_user->fingerprint_state) + 1) %
-        (static_cast<int>(mojom::FingerprintState::kMaxValue) + 1));
+        (static_cast<int>(FingerprintState::kMaxValue) + 1));
     debug_dispatcher_.SetFingerprintState(debug_user->account_id,
                                           debug_user->fingerprint_state);
   }
@@ -396,10 +398,9 @@
                     ? user_manager::USER_TYPE_PUBLIC_ACCOUNT
                     : user_manager::USER_TYPE_REGULAR;
 
-    std::vector<mojom::LoginUserInfoPtr> users =
-        BuildUserList(debug_users_.size());
+    std::vector<LoginUserInfo> users = BuildUserList(debug_users_.size());
     // Update display name and email in debug users.
-    debug_users_[user_index] = UserMetadata(users[user_index]->basic_user_info);
+    debug_users_[user_index] = UserMetadata(users[user_index].basic_user_info);
     NotifyUsers(std::move(users));
   }
 
@@ -442,12 +443,11 @@
   void HideWarningBanner() { debug_dispatcher_.HideWarningBanner(); }
 
   // LoginDataDispatcher::Observer:
-  void OnUsersChanged(
-      const std::vector<mojom::LoginUserInfoPtr>& users) override {
+  void OnUsersChanged(const std::vector<LoginUserInfo>& users) override {
     // Update root_users_ to new source data.
     root_users_.clear();
     for (auto& user : users)
-      root_users_.push_back(user->Clone());
+      root_users_.push_back(user);
 
     // Rebuild debug users using new source data.
     SetUserCount(root_users_.size());
@@ -480,9 +480,8 @@
     lock_screen_note_state_ = state;
     debug_dispatcher_.SetLockScreenNoteState(state);
   }
-  void OnShowEasyUnlockIcon(
-      const AccountId& user,
-      const mojom::EasyUnlockIconOptionsPtr& icon) override {
+  void OnShowEasyUnlockIcon(const AccountId& user,
+                            const EasyUnlockIconOptions& icon) override {
     debug_dispatcher_.ShowEasyUnlockIcon(user, icon);
   }
   void OnDetachableBasePairingStatusChanged(
@@ -493,7 +492,7 @@
   void OnPublicSessionKeyboardLayoutsChanged(
       const AccountId& account_id,
       const std::string& locale,
-      const std::vector<mojom::InputMethodItemPtr>& keyboard_layouts) override {
+      const std::vector<InputMethodItem>& keyboard_layouts) override {
     debug_dispatcher_.SetPublicSessionKeyboardLayouts(account_id, locale,
                                                       keyboard_layouts);
   }
@@ -512,7 +511,7 @@
   LoginDataDispatcher debug_dispatcher_;
 
   // Original set of users from |root_dispatcher_|.
-  std::vector<mojom::LoginUserInfoPtr> root_users_;
+  std::vector<LoginUserInfo> root_users_;
 
   // Metadata for users that the UI is displaying.
   std::vector<UserMetadata> debug_users_;
@@ -626,8 +625,7 @@
       return DetachableBasePairingStatus::kNone;
     return *pairing_status_;
   }
-  bool PairedBaseMatchesLastUsedByUser(
-      const mojom::UserInfo& user_info) override {
+  bool PairedBaseMatchesLastUsedByUser(const UserInfo& user_info) override {
     if (GetPairingStatus() != DetachableBasePairingStatus::kAuthenticated)
       return false;
 
@@ -635,8 +633,7 @@
       return true;
     return last_used_bases_[user_info.account_id] == base_id_;
   }
-  bool SetPairedBaseAsLastUsedByUser(
-      const mojom::UserInfo& user_info) override {
+  bool SetPairedBaseAsLastUsedByUser(const UserInfo& user_info) override {
     if (GetPairingStatus() != DetachableBasePairingStatus::kAuthenticated)
       return false;
 
diff --git a/ash/login/ui/lock_screen_sanity_unittest.cc b/ash/login/ui/lock_screen_sanity_unittest.cc
index 2b5a58a..b42b5ef 100644
--- a/ash/login/ui/lock_screen_sanity_unittest.cc
+++ b/ash/login/ui/lock_screen_sanity_unittest.cc
@@ -107,9 +107,8 @@
   // Password submit runs mojo.
   std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
   client->set_authenticate_user_callback_result(false);
-  EXPECT_CALL(*client,
-              AuthenticateUserWithPasswordOrPin_(
-                  users()[0]->basic_user_info->account_id, _, false, _));
+  EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin_(
+                           users()[0].basic_user_info.account_id, _, false, _));
   ui::test::EventGenerator* generator = GetEventGenerator();
   generator->PressKey(ui::KeyboardCode::VKEY_A, 0);
   generator->PressKey(ui::KeyboardCode::VKEY_RETURN, 0);
@@ -362,9 +361,9 @@
 
   // Add two users, the first of which can be removed.
   users().push_back(CreateUser("test1@test"));
-  users()[0]->can_remove = true;
+  users()[0].can_remove = true;
   users().push_back(CreateUser("test2@test"));
-  DataDispatcher()->NotifyUsers(users());
+  DataDispatcher()->SetUserList(users());
 
   std::unique_ptr<views::Widget> widget = CreateWidgetWithContent(contents);
 
@@ -406,7 +405,7 @@
   EXPECT_TRUE(HasFocusInAnyChildView(primary().menu()));
   EXPECT_CALL(*client, OnRemoveUserWarningShown()).Times(1);
   submit();
-  EXPECT_CALL(*client, RemoveUser(users()[0]->basic_user_info->account_id))
+  EXPECT_CALL(*client, RemoveUser(users()[0].basic_user_info.account_id))
       .Times(1);
   submit();
 
@@ -415,8 +414,8 @@
   EXPECT_TRUE(MakeLockContentsViewTestApi(contents)
                   .primary_big_view()
                   ->GetCurrentUser()
-                  ->basic_user_info->account_id ==
-              users()[1]->basic_user_info->account_id);
+                  .basic_user_info.account_id ==
+              users()[1].basic_user_info.account_id);
 }
 
 TEST_F(LockScreenSanityTest, LockScreenKillsPreventsClipboardPaste) {
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc
index 9140616..c748fce 100644
--- a/ash/login/ui/login_auth_user_view.cc
+++ b/ash/login/ui/login_auth_user_view.cc
@@ -168,7 +168,7 @@
     SetAutoColorReadabilityEnabled(false);
     SetEnabledColor(login_constants::kAuthMethodsTextColor);
 
-    SetTextBasedOnState(mojom::FingerprintState::AVAILABLE);
+    SetTextBasedOnState(FingerprintState::AVAILABLE);
   }
 
   void SetTextBasedOnAuthAttempt(bool success) {
@@ -180,22 +180,22 @@
                 : IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_ACCESSIBLE_AUTH_FAILED));
   }
 
-  void SetTextBasedOnState(mojom::FingerprintState state) {
+  void SetTextBasedOnState(FingerprintState state) {
     auto get_displayed_id = [&]() {
       switch (state) {
-        case mojom::FingerprintState::UNAVAILABLE:
-        case mojom::FingerprintState::AVAILABLE:
+        case FingerprintState::UNAVAILABLE:
+        case FingerprintState::AVAILABLE:
           return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_AVAILABLE;
-        case mojom::FingerprintState::DISABLED_FROM_ATTEMPTS:
+        case FingerprintState::DISABLED_FROM_ATTEMPTS:
           return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_ATTEMPTS;
-        case mojom::FingerprintState::DISABLED_FROM_TIMEOUT:
+        case FingerprintState::DISABLED_FROM_TIMEOUT:
           return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_TIMEOUT;
       }
       NOTREACHED();
     };
 
     auto get_accessible_id = [&]() {
-      if (state == mojom::FingerprintState::DISABLED_FROM_ATTEMPTS)
+      if (state == FingerprintState::DISABLED_FROM_ATTEMPTS)
         return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_ACCESSIBLE_AUTH_DISABLED_FROM_ATTEMPTS;
       return get_displayed_id();
     };
@@ -348,7 +348,7 @@
 
   ~FingerprintView() override = default;
 
-  void SetState(mojom::FingerprintState state) {
+  void SetState(FingerprintState state) {
     if (state_ == state)
       return;
 
@@ -370,7 +370,7 @@
                                             kFingerprintIconSizeDp,
                                             gfx::kGoogleGreenDark500));
     } else {
-      SetIcon(mojom::FingerprintState::DISABLED_FROM_ATTEMPTS);
+      SetIcon(FingerprintState::DISABLED_FROM_ATTEMPTS);
       // base::Unretained is safe because reset_state_ is owned by |this|.
       reset_state_.Start(
           FROM_HERE,
@@ -391,8 +391,8 @@
 
  private:
   void DisplayCurrentState() {
-    SetVisible(state_ != mojom::FingerprintState::UNAVAILABLE &&
-               state_ != mojom::FingerprintState::DISABLED_FROM_TIMEOUT);
+    SetVisible(state_ != FingerprintState::UNAVAILABLE &&
+               state_ != FingerprintState::DISABLED_FROM_TIMEOUT);
     SetIcon(state_);
     label_->SetTextBasedOnState(state_);
   }
@@ -402,15 +402,15 @@
                                      true /*send_native_event*/);
   }
 
-  void SetIcon(mojom::FingerprintState state) {
+  void SetIcon(FingerprintState state) {
     switch (state) {
-      case mojom::FingerprintState::UNAVAILABLE:
-      case mojom::FingerprintState::AVAILABLE:
-      case mojom::FingerprintState::DISABLED_FROM_TIMEOUT:
+      case FingerprintState::UNAVAILABLE:
+      case FingerprintState::AVAILABLE:
+      case FingerprintState::DISABLED_FROM_TIMEOUT:
         icon_->SetImage(gfx::CreateVectorIcon(
             kLockScreenFingerprintIcon, kFingerprintIconSizeDp, SK_ColorWHITE));
         break;
-      case mojom::FingerprintState::DISABLED_FROM_ATTEMPTS:
+      case FingerprintState::DISABLED_FROM_ATTEMPTS:
         icon_->SetAnimationDecoder(
             std::make_unique<HorizontalImageSequenceAnimationDecoder>(
                 *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
@@ -423,15 +423,15 @@
     }
   }
 
-  bool ShouldFireChromeVoxAlert(mojom::FingerprintState state) {
-    return state == mojom::FingerprintState::DISABLED_FROM_ATTEMPTS ||
-           state == mojom::FingerprintState::DISABLED_FROM_TIMEOUT;
+  bool ShouldFireChromeVoxAlert(FingerprintState state) {
+    return state == FingerprintState::DISABLED_FROM_ATTEMPTS ||
+           state == FingerprintState::DISABLED_FROM_TIMEOUT;
   }
 
   FingerprintLabel* label_ = nullptr;
   AnimatedRoundedImageView* icon_ = nullptr;
   base::OneShotTimer reset_state_;
-  mojom::FingerprintState state_ = mojom::FingerprintState::AVAILABLE;
+  FingerprintState state_ = FingerprintState::AVAILABLE;
 
   DISALLOW_COPY_AND_ASSIGN(FingerprintView);
 };
@@ -582,7 +582,7 @@
 
 LoginAuthUserView::Callbacks::~Callbacks() = default;
 
-LoginAuthUserView::LoginAuthUserView(const mojom::LoginUserInfoPtr& user,
+LoginAuthUserView::LoginAuthUserView(const LoginUserInfo& user,
                                      const Callbacks& callbacks)
     : NonAccessibleView(kLoginAuthUserViewClassName),
       on_auth_(callbacks.on_auth),
@@ -593,8 +593,7 @@
   DCHECK(callbacks.on_remove);
   DCHECK(callbacks.on_easy_unlock_icon_hovered);
   DCHECK(callbacks.on_easy_unlock_icon_tapped);
-  DCHECK_NE(user->basic_user_info->type,
-            user_manager::USER_TYPE_PUBLIC_ACCOUNT);
+  DCHECK_NE(user.basic_user_info.type, user_manager::USER_TYPE_PUBLIC_ACCOUNT);
 
   // Build child views.
   user_view_ = new LoginUserView(
@@ -630,7 +629,7 @@
       callbacks.on_easy_unlock_icon_tapped);
 
   online_sign_in_message_ = new views::LabelButton(
-      this, base::UTF8ToUTF16(user->basic_user_info->display_name));
+      this, base::UTF8ToUTF16(user.basic_user_info.display_name));
   DecorateOnlineSignInMessage(online_sign_in_message_);
 
   disabled_auth_message_ = new DisabledAuthMessageView();
@@ -799,7 +798,7 @@
 }
 
 void LoginAuthUserView::SetEasyUnlockIcon(
-    mojom::EasyUnlockIconId id,
+    EasyUnlockIconId id,
     const base::string16& accessibility_label) {
   password_view_->SetEasyUnlockIcon(id, accessibility_label);
 }
@@ -935,15 +934,15 @@
   cached_animation_state_.reset();
 }
 
-void LoginAuthUserView::UpdateForUser(const mojom::LoginUserInfoPtr& user) {
+void LoginAuthUserView::UpdateForUser(const LoginUserInfo& user) {
   user_view_->UpdateForUser(user, true /*animate*/);
   password_view_->UpdateForUser(user);
   password_view_->Clear();
   online_sign_in_message_->SetText(
-      base::UTF8ToUTF16(user->basic_user_info->display_name));
+      base::UTF8ToUTF16(user.basic_user_info.display_name));
 }
 
-void LoginAuthUserView::SetFingerprintState(mojom::FingerprintState state) {
+void LoginAuthUserView::SetFingerprintState(FingerprintState state) {
   fingerprint_view_->SetState(state);
 }
 
@@ -957,7 +956,7 @@
   Layout();
 }
 
-const mojom::LoginUserInfoPtr& LoginAuthUserView::current_user() const {
+const LoginUserInfo& LoginAuthUserView::current_user() const {
   return user_view_->current_user();
 }
 
@@ -1003,13 +1002,13 @@
   // enabled should attempt unlock.
   if (HasAuthMethod(AUTH_TAP) && password.empty()) {
     Shell::Get()->login_screen_controller()->AuthenticateUserWithEasyUnlock(
-        current_user()->basic_user_info->account_id);
+        current_user().basic_user_info.account_id);
     return;
   }
 
   password_view_->SetReadOnly(true);
   Shell::Get()->login_screen_controller()->AuthenticateUserWithPasswordOrPin(
-      current_user()->basic_user_info->account_id, base::UTF16ToUTF8(password),
+      current_user().basic_user_info.account_id, base::UTF16ToUTF8(password),
       can_use_pin_,
       base::BindOnce(&LoginAuthUserView::OnAuthComplete,
                      weak_factory_.GetWeakPtr()));
@@ -1052,7 +1051,7 @@
 void LoginAuthUserView::OnUserViewTap() {
   if (HasAuthMethod(AUTH_TAP)) {
     Shell::Get()->login_screen_controller()->AuthenticateUserWithEasyUnlock(
-        current_user()->basic_user_info->account_id);
+        current_user().basic_user_info.account_id);
   } else if (HasAuthMethod(AUTH_ONLINE_SIGN_IN)) {
     // Tapping anywhere in the user view is the same with tapping the message.
     OnOnlineSignInMessageTap();
@@ -1063,7 +1062,7 @@
 
 void LoginAuthUserView::OnOnlineSignInMessageTap() {
   Shell::Get()->login_screen_controller()->ShowGaiaSignin(
-      true /*can_close*/, current_user()->basic_user_info->account_id);
+      true /*can_close*/, current_user().basic_user_info.account_id);
 }
 
 bool LoginAuthUserView::HasAuthMethod(AuthMethods auth_method) const {
@@ -1075,7 +1074,7 @@
   external_binary_auth_button_->SetEnabled(false);
   external_binary_enrollment_button_->SetEnabled(false);
   Shell::Get()->login_screen_controller()->AuthenticateUserWithExternalBinary(
-      current_user()->basic_user_info->account_id,
+      current_user().basic_user_info.account_id,
       base::BindOnce(&LoginAuthUserView::OnAuthComplete,
                      weak_factory_.GetWeakPtr()));
 }
diff --git a/ash/login/ui/login_auth_user_view.h b/ash/login/ui/login_auth_user_view.h
index 28cf0f1..f952c2d 100644
--- a/ash/login/ui/login_auth_user_view.h
+++ b/ash/login/ui/login_auth_user_view.h
@@ -12,8 +12,8 @@
 #include "ash/login/ui/login_password_view.h"
 #include "ash/login/ui/login_user_view.h"
 #include "ash/login/ui/non_accessible_view.h"
+#include "ash/public/cpp/session/user_info.h"
 #include "ash/public/interfaces/login_screen.mojom.h"
-#include "ash/public/interfaces/user_info.mojom.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "base/scoped_observer.h"
@@ -98,8 +98,7 @@
                                     // message to user.
   };
 
-  LoginAuthUserView(const mojom::LoginUserInfoPtr& user,
-                    const Callbacks& callbacks);
+  LoginAuthUserView(const LoginUserInfo& user, const Callbacks& callbacks);
   ~LoginAuthUserView() override;
 
   // Set the displayed set of auth methods. |auth_methods| contains or-ed
@@ -109,7 +108,7 @@
   AuthMethods auth_methods() const { return auth_methods_; }
 
   // Add an easy unlock icon.
-  void SetEasyUnlockIcon(mojom::EasyUnlockIconId id,
+  void SetEasyUnlockIcon(EasyUnlockIconId id,
                          const base::string16& accessibility_label);
 
   // Captures any metadata about the current view state that will be used for
@@ -120,10 +119,10 @@
   void ApplyAnimationPostLayout();
 
   // Update the displayed name, icon, etc to that of |user|.
-  void UpdateForUser(const mojom::LoginUserInfoPtr& user);
+  void UpdateForUser(const LoginUserInfo& user);
 
   // Update the current fingerprint state.
-  void SetFingerprintState(mojom::FingerprintState state);
+  void SetFingerprintState(FingerprintState state);
 
   // Called to show a fingerprint authentication attempt result.
   void NotifyFingerprintAuthResult(bool success);
@@ -133,7 +132,7 @@
   void SetAuthDisabledMessage(
       const ash::mojom::AuthDisabledDataPtr& auth_disabled_data);
 
-  const mojom::LoginUserInfoPtr& current_user() const;
+  const LoginUserInfo& current_user() const;
 
   LoginPasswordView* password_view() { return password_view_; }
   LoginUserView* user_view() { return user_view_; }
diff --git a/ash/login/ui/login_auth_user_view_unittest.cc b/ash/login/ui/login_auth_user_view_unittest.cc
index 51be2c5..28eef7f 100644
--- a/ash/login/ui/login_auth_user_view_unittest.cc
+++ b/ash/login/ui/login_auth_user_view_unittest.cc
@@ -60,7 +60,7 @@
     view_->SetAuthMethods(auth_methods, can_use_pin);
   }
 
-  mojom::LoginUserInfoPtr user_;
+  LoginUserInfo user_;
   views::View* container_ = nullptr;   // Owned by test widget view hierarchy.
   LoginAuthUserView* view_ = nullptr;  // Owned by test widget view hierarchy.
 
@@ -116,7 +116,7 @@
 
   EXPECT_CALL(*client,
               AuthenticateUserWithEasyUnlock(
-                  user_view->current_user()->basic_user_info->account_id));
+                  user_view->current_user().basic_user_info.account_id));
   SetAuthMethods(LoginAuthUserView::AUTH_PASSWORD |
                  LoginAuthUserView::AUTH_TAP);
   password_view->Clear();
@@ -146,7 +146,7 @@
               ShowGaiaSignin(
                   true /*can_close*/,
                   base::Optional<AccountId>(
-                      user_view->current_user()->basic_user_info->account_id)));
+                      user_view->current_user().basic_user_info.account_id)));
   const ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
                              ui::EventTimeForNow(), 0, 0);
   view_->ButtonPressed(online_sign_in_message, event);
@@ -202,7 +202,7 @@
   EXPECT_CALL(*client, AuthenticateUserWithExternalBinary_(
                            test_auth_user_view.user_view()
                                ->current_user()
-                               ->basic_user_info->account_id,
+                               .basic_user_info.account_id,
                            _));
   power_manager_client()->SetLidState(
       chromeos::PowerManagerClient::LidState::OPEN, base::TimeTicks::Now());
diff --git a/ash/login/ui/login_big_user_view.cc b/ash/login/ui/login_big_user_view.cc
index e2fd1ac..80afdbf2 100644
--- a/ash/login/ui/login_big_user_view.cc
+++ b/ash/login/ui/login_big_user_view.cc
@@ -14,12 +14,12 @@
 
 namespace {
 
-bool IsPublicAccountUser(const mojom::LoginUserInfoPtr& user) {
-  return user->basic_user_info->type == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
+bool IsPublicAccountUser(const LoginUserInfo& user) {
+  return user.basic_user_info.type == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
 }
 
-bool IsChildAccountUser(const mojom::LoginUserInfoPtr& user) {
-  return user->basic_user_info->type == user_manager::USER_TYPE_CHILD;
+bool IsChildAccountUser(const LoginUserInfo& user) {
+  return user.basic_user_info.type == user_manager::USER_TYPE_CHILD;
 }
 
 // Returns true if either a or b have a value, but not both.
@@ -30,7 +30,7 @@
 }  // namespace
 
 LoginBigUserView::LoginBigUserView(
-    const mojom::LoginUserInfoPtr& user,
+    const LoginUserInfo& user,
     const LoginAuthUserView::Callbacks& auth_user_callbacks,
     const LoginPublicAccountUserView::Callbacks& public_account_callbacks,
     const ParentAccessView::Callbacks& parent_access_callbacks)
@@ -52,14 +52,14 @@
 
 LoginBigUserView::~LoginBigUserView() = default;
 
-void LoginBigUserView::CreateChildView(const mojom::LoginUserInfoPtr& user) {
+void LoginBigUserView::CreateChildView(const LoginUserInfo& user) {
   if (IsPublicAccountUser(user))
     CreatePublicAccount(user);
   else
     CreateAuthUser(user);
 }
 
-void LoginBigUserView::UpdateForUser(const mojom::LoginUserInfoPtr& user) {
+void LoginBigUserView::UpdateForUser(const LoginUserInfo& user) {
   // Rebuild child view for the following swap case:
   // 1. Public Account -> Auth User
   // 2. Auth User      -> Public Account
@@ -89,7 +89,7 @@
 
   DCHECK(IsChildAccountUser(auth_user_->current_user()));
   parent_access_ = new ParentAccessView(
-      auth_user_->current_user()->basic_user_info->account_id,
+      auth_user_->current_user().basic_user_info.account_id,
       parent_access_callbacks_);
   RemoveChildView(auth_user_);
   AddChildView(parent_access_);
@@ -112,7 +112,7 @@
   RequestFocus();
 }
 
-const mojom::LoginUserInfoPtr& LoginBigUserView::GetCurrentUser() const {
+const LoginUserInfo& LoginBigUserView::GetCurrentUser() const {
   DCHECK(OnlyOneSet(public_account_, auth_user_));
   if (public_account_) {
     DCHECK(!parent_access_);
@@ -171,7 +171,7 @@
   }
 }
 
-void LoginBigUserView::CreateAuthUser(const mojom::LoginUserInfoPtr& user) {
+void LoginBigUserView::CreateAuthUser(const LoginUserInfo& user) {
   DCHECK(!IsPublicAccountUser(user));
   DCHECK(!auth_user_);
   DCHECK(!parent_access_);
@@ -182,8 +182,7 @@
   AddChildView(auth_user_);
 }
 
-void LoginBigUserView::CreatePublicAccount(
-    const mojom::LoginUserInfoPtr& user) {
+void LoginBigUserView::CreatePublicAccount(const LoginUserInfo& user) {
   DCHECK(IsPublicAccountUser(user));
   DCHECK(!public_account_);
 
diff --git a/ash/login/ui/login_big_user_view.h b/ash/login/ui/login_big_user_view.h
index daeaed1..4ac774f 100644
--- a/ash/login/ui/login_big_user_view.h
+++ b/ash/login/ui/login_big_user_view.h
@@ -11,7 +11,7 @@
 #include "ash/login/ui/login_user_view.h"
 #include "ash/login/ui/non_accessible_view.h"
 #include "ash/login/ui/parent_access_view.h"
-#include "ash/public/interfaces/user_info.mojom.h"
+#include "ash/public/cpp/session/user_info.h"
 #include "ash/wallpaper/wallpaper_controller_observer.h"
 
 namespace ash {
@@ -31,20 +31,20 @@
                                     public WallpaperControllerObserver {
  public:
   LoginBigUserView(
-      const mojom::LoginUserInfoPtr& user,
+      const LoginUserInfo& user,
       const LoginAuthUserView::Callbacks& auth_user_callbacks,
       const LoginPublicAccountUserView::Callbacks& public_account_callbacks,
       const ParentAccessView::Callbacks& parent_access_callbacks);
   ~LoginBigUserView() override;
 
   // Base on the user type, call CreateAuthUser or CreatePublicAccount.
-  void CreateChildView(const mojom::LoginUserInfoPtr& user);
+  void CreateChildView(const LoginUserInfo& user);
 
   // Update the displayed name, icon, etc to that of |user|.
   // It is safe to call it when ParentAccessView is shown.
   // LoginPublicAccountUserView, even if not visible, will be updated and the
   // result will be displayed after ParentAccessView is dismissed.
-  void UpdateForUser(const mojom::LoginUserInfoPtr& user);
+  void UpdateForUser(const LoginUserInfo& user);
 
   // Replaces LoginAuthUserView with ParentAccessView. Does not destroy
   // LoginAuthUserView. Should not be called for LoginBigUserView that contains
@@ -58,7 +58,7 @@
   void HideParentAccessView();
 
   // Safe to call in any state.
-  const mojom::LoginUserInfoPtr& GetCurrentUser() const;
+  const LoginUserInfo& GetCurrentUser() const;
 
   // Safe to call in any state.
   LoginUserView* GetUserView();
@@ -80,12 +80,12 @@
  private:
   // Create LoginAuthUserView and add it as child view.
   // |public_account_| will be deleted if exists to ensure the single child.
-  void CreateAuthUser(const mojom::LoginUserInfoPtr& user);
+  void CreateAuthUser(const LoginUserInfo& user);
 
   // Create LoginPublicAccountUserView and add it as child view.
   // |auth_user_| and |parent_acesss_| will be deleted if exists to ensure the
   // single child.
-  void CreatePublicAccount(const mojom::LoginUserInfoPtr& user);
+  void CreatePublicAccount(const LoginUserInfo& user);
 
   // Either |auth_user_| or |public_account_| must be null.
   LoginPublicAccountUserView* public_account_ = nullptr;
diff --git a/ash/login/ui/login_data_dispatcher.cc b/ash/login/ui/login_data_dispatcher.cc
index 375f0ab..63e5a35 100644
--- a/ash/login/ui/login_data_dispatcher.cc
+++ b/ash/login/ui/login_data_dispatcher.cc
@@ -9,7 +9,11 @@
 LoginDataDispatcher::Observer::~Observer() = default;
 
 void LoginDataDispatcher::Observer::OnUsersChanged(
-    const std::vector<mojom::LoginUserInfoPtr>& users) {}
+    const std::vector<LoginUserInfo>& users) {}
+
+void LoginDataDispatcher::Observer::OnUserAvatarChanged(
+    const AccountId& account_id,
+    const UserAvatar& avatar) {}
 
 void LoginDataDispatcher::Observer::OnPinEnabledForUserChanged(
     const AccountId& user,
@@ -17,7 +21,7 @@
 
 void LoginDataDispatcher::Observer::OnFingerprintStateChanged(
     const AccountId& account_id,
-    mojom::FingerprintState state) {}
+    FingerprintState state) {}
 
 void LoginDataDispatcher::Observer::OnFingerprintAuthResult(
     const AccountId& account_id,
@@ -42,7 +46,7 @@
 
 void LoginDataDispatcher::Observer::OnShowEasyUnlockIcon(
     const AccountId& user,
-    const mojom::EasyUnlockIconOptionsPtr& icon) {}
+    const EasyUnlockIconOptions& icon) {}
 
 void LoginDataDispatcher::Observer::OnShowWarningBanner(
     const base::string16& message) {}
@@ -61,14 +65,14 @@
 
 void LoginDataDispatcher::Observer::OnPublicSessionLocalesChanged(
     const AccountId& account_id,
-    const std::vector<mojom::LocaleItemPtr>& locales,
+    const std::vector<LocaleItem>& locales,
     const std::string& default_locale,
     bool show_advanced_view) {}
 
 void LoginDataDispatcher::Observer::OnPublicSessionKeyboardLayoutsChanged(
     const AccountId& account_id,
     const std::string& locale,
-    const std::vector<mojom::InputMethodItemPtr>& keyboard_layouts) {}
+    const std::vector<InputMethodItem>& keyboard_layouts) {}
 
 void LoginDataDispatcher::Observer::
     OnPublicSessionShowFullManagementDisclosureChanged(
@@ -91,8 +95,7 @@
   observers_.RemoveObserver(observer);
 }
 
-void LoginDataDispatcher::NotifyUsers(
-    const std::vector<mojom::LoginUserInfoPtr>& users) {
+void LoginDataDispatcher::SetUserList(const std::vector<LoginUserInfo>& users) {
   for (auto& observer : observers_)
     observer.OnUsersChanged(users);
 }
@@ -104,11 +107,17 @@
 }
 
 void LoginDataDispatcher::SetFingerprintState(const AccountId& account_id,
-                                              mojom::FingerprintState state) {
+                                              FingerprintState state) {
   for (auto& observer : observers_)
     observer.OnFingerprintStateChanged(account_id, state);
 }
 
+void LoginDataDispatcher::SetAvatarForUser(const AccountId& account_id,
+                                           const UserAvatar& avatar) {
+  for (auto& observer : observers_)
+    observer.OnUserAvatarChanged(account_id, avatar);
+}
+
 void LoginDataDispatcher::NotifyFingerprintAuthResult(
     const AccountId& account_id,
     bool successful) {
@@ -147,7 +156,7 @@
 
 void LoginDataDispatcher::ShowEasyUnlockIcon(
     const AccountId& user,
-    const mojom::EasyUnlockIconOptionsPtr& icon) {
+    const EasyUnlockIconOptions& icon) {
   for (auto& observer : observers_)
     observer.OnShowEasyUnlockIcon(user, icon);
 }
@@ -182,7 +191,7 @@
 
 void LoginDataDispatcher::SetPublicSessionLocales(
     const AccountId& account_id,
-    const std::vector<mojom::LocaleItemPtr>& locales,
+    const std::vector<LocaleItem>& locales,
     const std::string& default_locale,
     bool show_advanced_view) {
   for (auto& observer : observers_) {
@@ -194,7 +203,7 @@
 void LoginDataDispatcher::SetPublicSessionKeyboardLayouts(
     const AccountId& account_id,
     const std::string& locale,
-    const std::vector<mojom::InputMethodItemPtr>& keyboard_layouts) {
+    const std::vector<InputMethodItem>& keyboard_layouts) {
   for (auto& observer : observers_) {
     observer.OnPublicSessionKeyboardLayoutsChanged(account_id, locale,
                                                    keyboard_layouts);
diff --git a/ash/login/ui/login_data_dispatcher.h b/ash/login/ui/login_data_dispatcher.h
index 41dcdc4..f10fec01 100644
--- a/ash/login/ui/login_data_dispatcher.h
+++ b/ash/login/ui/login_data_dispatcher.h
@@ -11,8 +11,8 @@
 
 #include "ash/ash_export.h"
 #include "ash/detachable_base/detachable_base_pairing_status.h"
+#include "ash/public/cpp/login_screen_model.h"
 #include "ash/public/interfaces/login_screen.mojom.h"
-#include "ash/public/interfaces/login_user_info.mojom.h"
 #include "ash/public/interfaces/tray_action.mojom.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
@@ -23,16 +23,16 @@
 // register observers which are then invoked when data is posted to the data
 // dispatcher.
 //
-// This provides access to data notification events only. LoginDataDispatcher is
-// not responsible for owning data (the login embedder should own the data).
-// This type provides a clean interface between the actual view/UI implemenation
-// and the embedder.
+// This provides access to data notification events only.
+// LoginDataDispatcher is not responsible for owning data (the login
+// embedder should own the data). This type provides a clean interface between
+// the actual view/UI implemenation and the embedder.
 //
 // There are various types which provide data to LoginDataDispatcher. For
 // example, the lock screen uses the session manager, whereas the login screen
 // uses the user manager. The debug overlay proxies the original data dispatcher
 // so it can provide fake state from an arbitrary source.
-class ASH_EXPORT LoginDataDispatcher {
+class ASH_EXPORT LoginDataDispatcher : public LoginScreenModel {
  public:
   // Types interested in login state should derive from |Observer| and register
   // themselves on the |LoginDataDispatcher| instance passed to the view
@@ -42,8 +42,11 @@
     virtual ~Observer();
 
     // Called when the displayed set of users has changed.
-    virtual void OnUsersChanged(
-        const std::vector<mojom::LoginUserInfoPtr>& users);
+    virtual void OnUsersChanged(const std::vector<LoginUserInfo>& users);
+
+    // Called when |avatar| for |account_id| has changed.
+    virtual void OnUserAvatarChanged(const AccountId& account_id,
+                                     const UserAvatar& avatar);
 
     // Called when pin should be enabled or disabled for |user|. By default, pin
     // should be disabled.
@@ -52,7 +55,7 @@
 
     // Called when fingerprint unlock state changes for user with |account_id|.
     virtual void OnFingerprintStateChanged(const AccountId& account_id,
-                                           mojom::FingerprintState state);
+                                           FingerprintState state);
 
     // Called after a fingerprint authentication attempt.
     virtual void OnFingerprintAuthResult(const AccountId& account_id,
@@ -80,9 +83,8 @@
     virtual void OnLockScreenNoteStateChanged(mojom::TrayActionState state);
 
     // Called when an easy unlock icon should be displayed.
-    virtual void OnShowEasyUnlockIcon(
-        const AccountId& user,
-        const mojom::EasyUnlockIconOptionsPtr& icon);
+    virtual void OnShowEasyUnlockIcon(const AccountId& user,
+                                      const EasyUnlockIconOptions& icon);
 
     // Called when a warning banner message should be displayed.
     virtual void OnShowWarningBanner(const base::string16& message);
@@ -106,7 +108,7 @@
     // |account_id|.
     virtual void OnPublicSessionLocalesChanged(
         const AccountId& account_id,
-        const std::vector<mojom::LocaleItemPtr>& locales,
+        const std::vector<LocaleItem>& locales,
         const std::string& default_locale,
         bool show_advanced_view);
 
@@ -115,7 +117,7 @@
     virtual void OnPublicSessionKeyboardLayoutsChanged(
         const AccountId& account_id,
         const std::string& locale,
-        const std::vector<mojom::InputMethodItemPtr>& keyboard_layouts);
+        const std::vector<InputMethodItem>& keyboard_layouts);
 
     // Called when conditions for showing full management disclosure message
     // are changed.
@@ -132,15 +134,23 @@
   };
 
   LoginDataDispatcher();
-  ~LoginDataDispatcher();
+  ~LoginDataDispatcher() override;
 
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
 
-  void NotifyUsers(const std::vector<mojom::LoginUserInfoPtr>& users);
+  // LoginScreenModel:
+  // TODO(estade): for now, LoginScreenModel overrides are mixed with
+  // non-virtual methods. More of the non-virtual methods will become a part of
+  // the LoginScreenModel interface, so ordering is being preserved. When
+  // LoginScreenModel is complete, separate out the methods that aren't
+  // overrides.
+  void SetUserList(const std::vector<LoginUserInfo>& users) override;
   void SetPinEnabledForUser(const AccountId& user, bool enabled);
   void SetFingerprintState(const AccountId& account_id,
-                           mojom::FingerprintState state);
+                           FingerprintState state) override;
+  void SetAvatarForUser(const AccountId& account_id,
+                        const UserAvatar& avatar) override;
   void NotifyFingerprintAuthResult(const AccountId& account_id,
                                    bool successful);
   void EnableAuthForUser(const AccountId& account_id);
@@ -150,7 +160,7 @@
   void SetForceOnlineSignInForUser(const AccountId& user);
   void SetLockScreenNoteState(mojom::TrayActionState state);
   void ShowEasyUnlockIcon(const AccountId& user,
-                          const mojom::EasyUnlockIconOptionsPtr& icon);
+                          const EasyUnlockIconOptions& icon) override;
   void ShowWarningBanner(const base::string16& message);
   void HideWarningBanner();
   void SetSystemInfo(bool show_if_hidden,
@@ -160,13 +170,13 @@
   void SetPublicSessionDisplayName(const AccountId& account_id,
                                    const std::string& display_name);
   void SetPublicSessionLocales(const AccountId& account_id,
-                               const std::vector<mojom::LocaleItemPtr>& locales,
+                               const std::vector<LocaleItem>& locales,
                                const std::string& default_locale,
-                               bool show_advanced_view);
+                               bool show_advanced_view) override;
   void SetPublicSessionKeyboardLayouts(
       const AccountId& account_id,
       const std::string& locale,
-      const std::vector<mojom::InputMethodItemPtr>& keyboard_layouts);
+      const std::vector<InputMethodItem>& keyboard_layouts) override;
   void SetPublicSessionShowFullManagementDisclosure(
       bool show_full_management_disclosure);
   void SetDetachableBasePairingStatus(
diff --git a/ash/login/ui/login_detachable_base_model.cc b/ash/login/ui/login_detachable_base_model.cc
index 935b70c9..95bd89b 100644
--- a/ash/login/ui/login_detachable_base_model.cc
+++ b/ash/login/ui/login_detachable_base_model.cc
@@ -8,7 +8,7 @@
 #include "ash/detachable_base/detachable_base_observer.h"
 #include "ash/detachable_base/detachable_base_pairing_status.h"
 #include "ash/login/ui/login_data_dispatcher.h"
-#include "ash/public/interfaces/user_info.mojom.h"
+#include "ash/public/cpp/session/user_info.h"
 #include "base/macros.h"
 #include "base/scoped_observer.h"
 
@@ -32,12 +32,10 @@
   DetachableBasePairingStatus GetPairingStatus() override {
     return detachable_base_handler_->GetPairingStatus();
   }
-  bool PairedBaseMatchesLastUsedByUser(
-      const mojom::UserInfo& user_info) override {
+  bool PairedBaseMatchesLastUsedByUser(const UserInfo& user_info) override {
     return detachable_base_handler_->PairedBaseMatchesLastUsedByUser(user_info);
   }
-  bool SetPairedBaseAsLastUsedByUser(
-      const mojom::UserInfo& user_info) override {
+  bool SetPairedBaseAsLastUsedByUser(const UserInfo& user_info) override {
     return detachable_base_handler_->SetPairedBaseAsLastUsedByUser(user_info);
   }
 
diff --git a/ash/login/ui/login_detachable_base_model.h b/ash/login/ui/login_detachable_base_model.h
index e21b0807..fcfbac6a 100644
--- a/ash/login/ui/login_detachable_base_model.h
+++ b/ash/login/ui/login_detachable_base_model.h
@@ -14,10 +14,7 @@
 class DetachableBaseHandler;
 enum class DetachableBasePairingStatus;
 class LoginDataDispatcher;
-
-namespace mojom {
-class UserInfo;
-}
+struct UserInfo;
 
 // Wrapper around ash::DetachableBaseHandler used by login UI. Exposed as an
 // interface to ease faking the detachable base state in login UI tests, and in
@@ -40,12 +37,10 @@
 
   // Checks if the currently paired base is different than the last base used by
   // the user.
-  virtual bool PairedBaseMatchesLastUsedByUser(
-      const mojom::UserInfo& user_info) = 0;
+  virtual bool PairedBaseMatchesLastUsedByUser(const UserInfo& user_info) = 0;
 
   // Sets the currently paired base as the last base used by the user.
-  virtual bool SetPairedBaseAsLastUsedByUser(
-      const mojom::UserInfo& user_info) = 0;
+  virtual bool SetPairedBaseAsLastUsedByUser(const UserInfo& user_info) = 0;
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/login_expanded_public_account_view.cc b/ash/login/ui/login_expanded_public_account_view.cc
index e567e88..172d657 100644
--- a/ash/login/ui/login_expanded_public_account_view.cc
+++ b/ash/login/ui/login_expanded_public_account_view.cc
@@ -14,6 +14,7 @@
 #include "ash/login/ui/login_user_view.h"
 #include "ash/login/ui/public_account_warning_dialog.h"
 #include "ash/login/ui/views_utils.h"
+#include "ash/public/cpp/login_types.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
@@ -414,7 +415,7 @@
       Layout();
     } else if (sender == submit_button_) {
       Shell::Get()->login_screen_controller()->LaunchPublicSession(
-          current_user_->basic_user_info->account_id,
+          current_user_.basic_user_info.account_id,
           selected_language_item_.value, selected_keyboard_item_.value);
     } else if (sender == language_selection_) {
       DCHECK(language_menu_view_);
@@ -451,22 +452,22 @@
     on_learn_more_tapped_.Run();
   }
 
-  void UpdateForUser(const mojom::LoginUserInfoPtr& user) {
-    DCHECK_EQ(user->basic_user_info->type,
+  void UpdateForUser(const LoginUserInfo& user) {
+    DCHECK_EQ(user.basic_user_info.type,
               user_manager::USER_TYPE_PUBLIC_ACCOUNT);
-    current_user_ = user->Clone();
+    current_user_ = user;
     if (!language_changed_by_user_)
-      selected_language_item_.value = user->public_account_info->default_locale;
+      selected_language_item_.value = user.public_account_info->default_locale;
 
-    PopulateLanguageItems(user->public_account_info->available_locales);
-    PopulateKeyboardItems(user->public_account_info->keyboard_layouts);
+    PopulateLanguageItems(user.public_account_info->available_locales);
+    PopulateKeyboardItems(user.public_account_info->keyboard_layouts);
     language_selection_->SetText(
         base::UTF8ToUTF16(selected_language_item_.title));
     keyboard_selection_->SetText(
         base::UTF8ToUTF16(selected_keyboard_item_.title));
 
     if (!show_advanced_changed_by_user_)
-      show_advanced_view_ = user->public_account_info->show_advanced_view;
+      show_advanced_view_ = user.public_account_info->show_advanced_view;
 
     Layout();
   }
@@ -482,14 +483,14 @@
     language_changed_by_user_ = true;
     selected_language_item_ = item;
     language_selection_->SetText(base::UTF8ToUTF16(item.title));
-    current_user_->public_account_info->default_locale = item.value;
+    current_user_.public_account_info->default_locale = item.value;
 
     // User changed the preferred locale, request to get corresponding keyboard
     // layouts.
     Shell::Get()
         ->login_screen_controller()
         ->RequestPublicSessionKeyboardLayouts(
-            current_user_->basic_user_info->account_id, item.value);
+            current_user_.basic_user_info.account_id, item.value);
   }
 
   void OnKeyboardSelected(LoginMenuView::Item item) {
@@ -497,22 +498,22 @@
     keyboard_selection_->SetText(base::UTF8ToUTF16(item.title));
   }
 
-  void PopulateLanguageItems(const std::vector<mojom::LocaleItemPtr>& locales) {
+  void PopulateLanguageItems(const std::vector<LocaleItem>& locales) {
     language_items_.clear();
     for (const auto& locale : locales) {
       LoginMenuView::Item item;
-      if (locale->group_name) {
-        item.title = locale->group_name.value();
+      if (locale.group_name) {
+        item.title = locale.group_name.value();
         item.is_group = true;
       } else {
-        item.title = locale->title;
-        item.value = locale->language_code;
+        item.title = locale.title;
+        item.value = locale.language_code;
         item.is_group = false;
-        item.selected = selected_language_item_.value == locale->language_code;
+        item.selected = selected_language_item_.value == locale.language_code;
       }
       language_items_.push_back(item);
 
-      if (selected_language_item_.value == locale->language_code)
+      if (selected_language_item_.value == locale.language_code)
         selected_language_item_ = item;
     }
 
@@ -526,17 +527,17 @@
   }
 
   void PopulateKeyboardItems(
-      const std::vector<mojom::InputMethodItemPtr>& keyboard_layouts) {
+      const std::vector<InputMethodItem>& keyboard_layouts) {
     keyboard_items_.clear();
     for (const auto& keyboard : keyboard_layouts) {
       LoginMenuView::Item item;
-      item.title = keyboard->title;
-      item.value = keyboard->ime_id;
+      item.title = keyboard.title;
+      item.value = keyboard.ime_id;
       item.is_group = false;
-      item.selected = keyboard->selected;
+      item.selected = keyboard.selected;
       keyboard_items_.push_back(item);
 
-      if (keyboard->selected)
+      if (keyboard.selected)
         selected_keyboard_item_ = item;
     }
 
@@ -563,7 +564,7 @@
   friend class LoginExpandedPublicAccountView::TestApi;
 
   bool show_advanced_view_ = false;
-  mojom::LoginUserInfoPtr current_user_;
+  LoginUserInfo current_user_;
 
   views::View* labels_view_ = nullptr;
   SelectionButtonView* advanced_view_button_ = nullptr;
@@ -727,14 +728,12 @@
   Hide();
 }
 
-void LoginExpandedPublicAccountView::UpdateForUser(
-    const mojom::LoginUserInfoPtr& user) {
+void LoginExpandedPublicAccountView::UpdateForUser(const LoginUserInfo& user) {
   user_view_->UpdateForUser(user, false /*animate*/);
   right_pane_->UpdateForUser(user);
 }
 
-const mojom::LoginUserInfoPtr& LoginExpandedPublicAccountView::current_user()
-    const {
+const LoginUserInfo& LoginExpandedPublicAccountView::current_user() const {
   return user_view_->current_user();
 }
 
diff --git a/ash/login/ui/login_expanded_public_account_view.h b/ash/login/ui/login_expanded_public_account_view.h
index a044503..dfa6cb4 100644
--- a/ash/login/ui/login_expanded_public_account_view.h
+++ b/ash/login/ui/login_expanded_public_account_view.h
@@ -10,7 +10,6 @@
 #include "ash/ash_export.h"
 #include "ash/login/ui/login_menu_view.h"
 #include "ash/login/ui/non_accessible_view.h"
-#include "ash/public/interfaces/login_user_info.mojom.h"
 #include "ui/events/event_handler.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/styled_label.h"
@@ -22,6 +21,7 @@
 class LoginUserView;
 class RightPaneView;
 class PublicAccountWarningDialog;
+struct LoginUserInfo;
 
 // Implements an expanded view for the public account user to select language
 // and keyboard options.
@@ -56,8 +56,8 @@
   ~LoginExpandedPublicAccountView() override;
 
   void ProcessPressedEvent(const ui::LocatedEvent* event);
-  void UpdateForUser(const mojom::LoginUserInfoPtr& user);
-  const mojom::LoginUserInfoPtr& current_user() const;
+  void UpdateForUser(const LoginUserInfo& user);
+  const LoginUserInfo& current_user() const;
   void Hide();
   void ShowWarningDialog();
   void OnWarningDialogClosed();
diff --git a/ash/login/ui/login_expanded_public_account_view_unittest.cc b/ash/login/ui/login_expanded_public_account_view_unittest.cc
index 3311e5ff..3eca940 100644
--- a/ash/login/ui/login_expanded_public_account_view_unittest.cc
+++ b/ash/login/ui/login_expanded_public_account_view_unittest.cc
@@ -3,12 +3,14 @@
 // found in the LICENSE file.
 
 #include "ash/login/ui/login_expanded_public_account_view.h"
+
 #include "ash/login/mock_login_screen_client.h"
 #include "ash/login/ui/arrow_button_view.h"
 #include "ash/login/ui/login_test_base.h"
 #include "ash/login/ui/login_test_utils.h"
 #include "ash/login/ui/public_account_warning_dialog.h"
 #include "ash/login/ui/views_utils.h"
+#include "ash/public/cpp/login_types.h"
 #include "base/bind_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/test/event_generator.h"
@@ -64,37 +66,35 @@
 
   // Add two fake language items, the first item is selected by default.
   void SetupLanguageInfo() {
-    std::vector<ash::mojom::LocaleItemPtr> result;
-    ash::mojom::LocaleItemPtr locale_item1 = ash::mojom::LocaleItem::New();
-    locale_item1->language_code = kEnglishLanguageCode;
-    locale_item1->title = kEnglishLanguageName;
+    std::vector<LocaleItem> result;
+    LocaleItem locale_item1;
+    locale_item1.language_code = kEnglishLanguageCode;
+    locale_item1.title = kEnglishLanguageName;
 
-    ash::mojom::LocaleItemPtr locale_item2 = ash::mojom::LocaleItem::New();
-    locale_item2->language_code = kFrenchLanguageCode;
-    locale_item2->title = kFrenchLanguageName;
+    LocaleItem locale_item2;
+    locale_item2.language_code = kFrenchLanguageCode;
+    locale_item2.title = kFrenchLanguageName;
     result.push_back(std::move(locale_item1));
     result.push_back(std::move(locale_item2));
-    user_->public_account_info->available_locales = std::move(result);
-    user_->public_account_info->default_locale = kEnglishLanguageCode;
+    user_.public_account_info->available_locales = std::move(result);
+    user_.public_account_info->default_locale = kEnglishLanguageCode;
   }
 
   // Add two fake keyboard items, the second item is selected by default.
   void SetupKeyboardInfo() {
-    std::vector<ash::mojom::InputMethodItemPtr> result;
-    ash::mojom::InputMethodItemPtr keyboard_item1 =
-        ash::mojom::InputMethodItem::New();
-    keyboard_item1->ime_id = kKeyboardIdForItem1;
-    keyboard_item1->title = kKeyboardNameForItem1;
+    std::vector<InputMethodItem> result;
+    InputMethodItem keyboard_item1;
+    keyboard_item1.ime_id = kKeyboardIdForItem1;
+    keyboard_item1.title = kKeyboardNameForItem1;
 
-    ash::mojom::InputMethodItemPtr keyboard_item2 =
-        ash::mojom::InputMethodItem::New();
-    keyboard_item2->ime_id = kKeyboardIdForItem2;
-    keyboard_item2->title = kKeyboardNameForItem2;
-    keyboard_item2->selected = true;
+    InputMethodItem keyboard_item2;
+    keyboard_item2.ime_id = kKeyboardIdForItem2;
+    keyboard_item2.title = kKeyboardNameForItem2;
+    keyboard_item2.selected = true;
     result.push_back(std::move(keyboard_item1));
     result.push_back(std::move(keyboard_item2));
 
-    user_->public_account_info->keyboard_layouts = std::move(result);
+    user_.public_account_info->keyboard_layouts = std::move(result);
   }
 
   void TapOnView(views::View* tap_target) {
@@ -110,7 +110,7 @@
     }
   }
 
-  mojom::LoginUserInfoPtr user_;
+  LoginUserInfo user_;
 
   // Owned by test widget view hierarchy.
   views::View* container_ = nullptr;
@@ -130,11 +130,11 @@
   EXPECT_EQ(public_account_->height(), kBubbleTotalHeightDp);
 
   LoginExpandedPublicAccountView::TestApi test_api(public_account_);
-  EXPECT_FALSE(user_->public_account_info->show_advanced_view);
+  EXPECT_FALSE(user_.public_account_info->show_advanced_view);
   EXPECT_FALSE(test_api.advanced_view()->GetVisible());
 
   // Toggle show_advanced_view.
-  user_->public_account_info->show_advanced_view = true;
+  user_.public_account_info->show_advanced_view = true;
   public_account_->UpdateForUser(user_);
 
   // Advanced view is shown and the overall size does not change.
@@ -202,7 +202,7 @@
   // Expect LanuchPublicSession mojo call when the submit button is clicked.
   std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
   EXPECT_CALL(*client,
-              LaunchPublicSession(user_->basic_user_info->account_id,
+              LaunchPublicSession(user_.basic_user_info.account_id,
                                   selected_language, selected_keyboard));
 
   // Click on the submit button.
@@ -213,11 +213,11 @@
 // Verifies both language and keyboard menus shows up correctly.
 TEST_P(LoginExpandedPublicAccountViewTest, ShowLanguageAndKeyboardMenu) {
   LoginExpandedPublicAccountView::TestApi test_api(public_account_);
-  EXPECT_FALSE(user_->public_account_info->show_advanced_view);
+  EXPECT_FALSE(user_.public_account_info->show_advanced_view);
   EXPECT_FALSE(test_api.advanced_view()->GetVisible());
 
   // Toggle show_advanced_view.
-  user_->public_account_info->show_advanced_view = true;
+  user_.public_account_info->show_advanced_view = true;
   public_account_->UpdateForUser(user_);
   EXPECT_TRUE(test_api.advanced_view()->GetVisible());
 
@@ -252,7 +252,7 @@
 
 TEST_P(LoginExpandedPublicAccountViewTest, ChangeMenuSelection) {
   LoginExpandedPublicAccountView::TestApi test_api(public_account_);
-  user_->public_account_info->show_advanced_view = true;
+  user_.public_account_info->show_advanced_view = true;
   public_account_->UpdateForUser(user_);
   EXPECT_TRUE(test_api.advanced_view()->GetVisible());
 
@@ -269,7 +269,7 @@
   std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
   EXPECT_CALL(*client,
               RequestPublicSessionKeyboardLayouts(
-                  user_->basic_user_info->account_id, kFrenchLanguageCode));
+                  user_.basic_user_info.account_id, kFrenchLanguageCode));
 
   EXPECT_EQ(test_api.selected_language_item().value, kEnglishLanguageCode);
   LoginMenuView::TestApi language_test_api(test_api.language_menu_view());
diff --git a/ash/login/ui/login_keyboard_test_base.h b/ash/login/ui/login_keyboard_test_base.h
index 94374e6..3f3d1d0 100644
--- a/ash/login/ui/login_keyboard_test_base.h
+++ b/ash/login/ui/login_keyboard_test_base.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "ash/login/ui/login_test_base.h"
-#include "ash/public/interfaces/login_user_info.mojom.h"
 #include "ash/test/ash_test_base.h"
 
 namespace ash {
@@ -36,7 +35,7 @@
   void SetUp() override;
 
  private:
-  std::vector<mojom::LoginUserInfoPtr> users_;
+  std::vector<LoginUserInfo> users_;
 
   DISALLOW_COPY_AND_ASSIGN(LoginKeyboardTestBase);
 };
diff --git a/ash/login/ui/login_password_view.cc b/ash/login/ui/login_password_view.cc
index 251ccce7..3833e32 100644
--- a/ash/login/ui/login_password_view.cc
+++ b/ash/login/ui/login_password_view.cc
@@ -10,6 +10,7 @@
 #include "ash/login/ui/login_button.h"
 #include "ash/login/ui/non_accessible_view.h"
 #include "ash/public/cpp/login_constants.h"
+#include "ash/public/cpp/login_types.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
@@ -124,31 +125,31 @@
   const int num_frames = 0;
 };
 
-// Construct an IconBundle instance for a given mojom::EasyUnlockIconId value.
-IconBundle GetEasyUnlockResources(mojom::EasyUnlockIconId id) {
+// Construct an IconBundle instance for a given EasyUnlockIconId value.
+IconBundle GetEasyUnlockResources(EasyUnlockIconId id) {
   switch (id) {
-    case mojom::EasyUnlockIconId::NONE:
+    case EasyUnlockIconId::NONE:
       break;
-    case mojom::EasyUnlockIconId::HARDLOCKED:
+    case EasyUnlockIconId::HARDLOCKED:
       return IconBundle(IDR_EASY_UNLOCK_HARDLOCKED,
                         IDR_EASY_UNLOCK_HARDLOCKED_HOVER,
                         IDR_EASY_UNLOCK_HARDLOCKED_PRESSED);
-    case mojom::EasyUnlockIconId::LOCKED:
+    case EasyUnlockIconId::LOCKED:
       return IconBundle(IDR_EASY_UNLOCK_LOCKED, IDR_EASY_UNLOCK_LOCKED_HOVER,
                         IDR_EASY_UNLOCK_LOCKED_PRESSED);
-    case mojom::EasyUnlockIconId::LOCKED_TO_BE_ACTIVATED:
+    case EasyUnlockIconId::LOCKED_TO_BE_ACTIVATED:
       return IconBundle(IDR_EASY_UNLOCK_LOCKED_TO_BE_ACTIVATED,
                         IDR_EASY_UNLOCK_LOCKED_TO_BE_ACTIVATED_HOVER,
                         IDR_EASY_UNLOCK_LOCKED_TO_BE_ACTIVATED_PRESSED);
-    case mojom::EasyUnlockIconId::LOCKED_WITH_PROXIMITY_HINT:
+    case EasyUnlockIconId::LOCKED_WITH_PROXIMITY_HINT:
       return IconBundle(IDR_EASY_UNLOCK_LOCKED_WITH_PROXIMITY_HINT,
                         IDR_EASY_UNLOCK_LOCKED_WITH_PROXIMITY_HINT_HOVER,
                         IDR_EASY_UNLOCK_LOCKED_WITH_PROXIMITY_HINT_PRESSED);
-    case mojom::EasyUnlockIconId::UNLOCKED:
+    case EasyUnlockIconId::UNLOCKED:
       return IconBundle(IDR_EASY_UNLOCK_UNLOCKED,
                         IDR_EASY_UNLOCK_UNLOCKED_HOVER,
                         IDR_EASY_UNLOCK_UNLOCKED_PRESSED);
-    case mojom::EasyUnlockIconId::SPINNER:
+    case EasyUnlockIconId::SPINNER:
       return IconBundle(IDR_EASY_UNLOCK_SPINNER,
                         base::TimeDelta::FromSeconds(2), 45 /*num_frames*/);
   }
@@ -186,7 +187,7 @@
                    base::Unretained(this)));
   }
 
-  void SetEasyUnlockIcon(mojom::EasyUnlockIconId icon_id,
+  void SetEasyUnlockIcon(EasyUnlockIconId icon_id,
                          const base::string16& accessibility_label) {
     bool changed_states = icon_id != icon_id_;
     icon_id_ = icon_id;
@@ -245,7 +246,7 @@
     if (!GetWidget() || !GetWidget()->GetRootView())
       return;
 
-    if (icon_id_ == mojom::EasyUnlockIconId::NONE)
+    if (icon_id_ == EasyUnlockIconId::NONE)
       return;
 
     IconBundle resources = GetEasyUnlockResources(icon_id_);
@@ -281,7 +282,7 @@
   }
 
   // Icon we are currently displaying.
-  mojom::EasyUnlockIconId icon_id_ = mojom::EasyUnlockIconId::NONE;
+  EasyUnlockIconId icon_id_ = EasyUnlockIconId::NONE;
 
   // View which renders the icon.
   AnimatedRoundedImageView* icon_;
@@ -445,22 +446,22 @@
 }
 
 void LoginPasswordView::SetEasyUnlockIcon(
-    mojom::EasyUnlockIconId id,
+    EasyUnlockIconId id,
     const base::string16& accessibility_label) {
   // Update icon.
   easy_unlock_icon_->SetEasyUnlockIcon(id, accessibility_label);
 
   // Update icon visiblity.
-  bool has_icon = id != mojom::EasyUnlockIconId::NONE;
+  bool has_icon = id != EasyUnlockIconId::NONE;
   easy_unlock_icon_->SetVisible(has_icon);
   easy_unlock_right_margin_->SetVisible(has_icon);
   password_row_->Layout();
 }
 
-void LoginPasswordView::UpdateForUser(const mojom::LoginUserInfoPtr& user) {
+void LoginPasswordView::UpdateForUser(const LoginUserInfo& user) {
   textfield_->SetAccessibleName(l10n_util::GetStringFUTF16(
       IDS_ASH_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME,
-      base::UTF8ToUTF16(user->basic_user_info->display_email)));
+      base::UTF8ToUTF16(user.basic_user_info.display_email)));
 }
 
 void LoginPasswordView::SetFocusEnabledForChildViews(bool enable) {
diff --git a/ash/login/ui/login_password_view.h b/ash/login/ui/login_password_view.h
index d68c5db..0e1d665 100644
--- a/ash/login/ui/login_password_view.h
+++ b/ash/login/ui/login_password_view.h
@@ -8,8 +8,7 @@
 #include "ash/ash_export.h"
 #include "ash/ime/ime_controller.h"
 #include "ash/login/ui/animated_rounded_image_view.h"
-#include "ash/public/interfaces/login_user_info.mojom.h"
-#include "ash/public/interfaces/user_info.mojom.h"
+#include "ash/public/cpp/session/user_info.h"
 #include "base/scoped_observer.h"
 #include "base/strings/string16.h"
 #include "ui/base/ime/chromeos/ime_keyboard.h"
@@ -27,6 +26,8 @@
 
 namespace ash {
 class LoginButton;
+enum class EasyUnlockIconId;
+struct LoginUserInfo;
 
 // Contains a textfield instance with a submit button. The user can type a
 // password into the textfield and hit enter to submit.
@@ -81,11 +82,11 @@
   void SetEnabledOnEmptyPassword(bool enabled);
 
   // Change the active icon for easy unlock.
-  void SetEasyUnlockIcon(mojom::EasyUnlockIconId id,
+  void SetEasyUnlockIcon(EasyUnlockIconId id,
                          const base::string16& accessibility_label);
 
   // Updates accessibility information for |user|.
-  void UpdateForUser(const mojom::LoginUserInfoPtr& user);
+  void UpdateForUser(const LoginUserInfo& user);
 
   // Enable or disable focus on the child elements (ie, password field and
   // submit button).
diff --git a/ash/login/ui/login_password_view_test.cc b/ash/login/ui/login_password_view_test.cc
index 9013928..4fefc4eb 100644
--- a/ash/login/ui/login_password_view_test.cc
+++ b/ash/login/ui/login_password_view_test.cc
@@ -5,6 +5,7 @@
 #include "ash/login/ui/login_password_view.h"
 
 #include "ash/login/ui/login_test_base.h"
+#include "ash/public/cpp/login_types.h"
 #include "ash/shell.h"
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
@@ -161,7 +162,7 @@
   ui::test::EventGenerator* generator = GetEventGenerator();
 
   // Enable icon.
-  view_->SetEasyUnlockIcon(mojom::EasyUnlockIconId::SPINNER,
+  view_->SetEasyUnlockIcon(EasyUnlockIconId::SPINNER,
                            base::string16() /*accessibility_label*/);
   ASSERT_TRUE(test_api.easy_unlock_icon()->GetVisible());
 
@@ -190,7 +191,7 @@
   ui::test::EventGenerator* generator = GetEventGenerator();
 
   // Enable icon, enable immediate hovering.
-  view_->SetEasyUnlockIcon(mojom::EasyUnlockIconId::SPINNER,
+  view_->SetEasyUnlockIcon(EasyUnlockIconId::SPINNER,
                            base::string16() /*accessibility_label*/);
   test_api.set_immediately_hover_easy_unlock_icon();
   ASSERT_TRUE(test_api.easy_unlock_icon()->GetVisible());
diff --git a/ash/login/ui/login_public_account_user_view.cc b/ash/login/ui/login_public_account_user_view.cc
index 40d1077b..5f0a826 100644
--- a/ash/login/ui/login_public_account_user_view.cc
+++ b/ash/login/ui/login_public_account_user_view.cc
@@ -59,13 +59,12 @@
 LoginPublicAccountUserView::Callbacks::~Callbacks() = default;
 
 LoginPublicAccountUserView::LoginPublicAccountUserView(
-    const mojom::LoginUserInfoPtr& user,
+    const LoginUserInfo& user,
     const Callbacks& callbacks)
     : NonAccessibleView(kLoginPublicAccountUserViewClassName),
       on_tap_(callbacks.on_tap),
       on_public_account_tap_(callbacks.on_public_account_tapped) {
-  DCHECK_EQ(user->basic_user_info->type,
-            user_manager::USER_TYPE_PUBLIC_ACCOUNT);
+  DCHECK_EQ(user.basic_user_info.type, user_manager::USER_TYPE_PUBLIC_ACCOUNT);
   DCHECK(callbacks.on_tap);
   DCHECK(callbacks.on_public_account_tapped);
 
@@ -127,13 +126,11 @@
   PreferredSizeChanged();
 }
 
-void LoginPublicAccountUserView::UpdateForUser(
-    const mojom::LoginUserInfoPtr& user) {
+void LoginPublicAccountUserView::UpdateForUser(const LoginUserInfo& user) {
   user_view_->UpdateForUser(user, true /*animate*/);
 }
 
-const mojom::LoginUserInfoPtr& LoginPublicAccountUserView::current_user()
-    const {
+const LoginUserInfo& LoginPublicAccountUserView::current_user() const {
   return user_view_->current_user();
 }
 
diff --git a/ash/login/ui/login_public_account_user_view.h b/ash/login/ui/login_public_account_user_view.h
index 5bd46a4..eac237e 100644
--- a/ash/login/ui/login_public_account_user_view.h
+++ b/ash/login/ui/login_public_account_user_view.h
@@ -8,7 +8,6 @@
 #include "ash/ash_export.h"
 #include "ash/login/ui/login_user_view.h"
 #include "ash/login/ui/non_accessible_view.h"
-#include "ash/public/interfaces/login_user_info.mojom.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/view.h"
 
@@ -47,13 +46,13 @@
     OnPublicAccountTapped on_public_account_tapped;
   };
 
-  LoginPublicAccountUserView(const mojom::LoginUserInfoPtr& user,
+  LoginPublicAccountUserView(const LoginUserInfo& user,
                              const Callbacks& callbacks);
   ~LoginPublicAccountUserView() override;
 
   void SetAuthEnabled(bool enabled, bool animate);
-  void UpdateForUser(const mojom::LoginUserInfoPtr& user);
-  const mojom::LoginUserInfoPtr& current_user() const;
+  void UpdateForUser(const LoginUserInfo& user);
+  const LoginUserInfo& current_user() const;
 
   // views::View:
   gfx::Size CalculatePreferredSize() const override;
diff --git a/ash/login/ui/login_public_account_user_view_unittest.cc b/ash/login/ui/login_public_account_user_view_unittest.cc
index 569e3b28..c1bceac 100644
--- a/ash/login/ui/login_public_account_user_view_unittest.cc
+++ b/ash/login/ui/login_public_account_user_view_unittest.cc
@@ -53,7 +53,7 @@
     SetWidget(CreateWidgetWithContent(container));
   }
 
-  mojom::LoginUserInfoPtr user_;
+  LoginUserInfo user_;
 
   LoginPublicAccountUserView* public_account_view_ = nullptr;
   views::View* focusable_view_ = nullptr;
diff --git a/ash/login/ui/login_test_base.cc b/ash/login/ui/login_test_base.cc
index d0c6da6..9db6a2d 100644
--- a/ash/login/ui/login_test_base.cc
+++ b/ash/login/ui/login_test_base.cc
@@ -109,7 +109,7 @@
 
   users_.erase(users_.begin() + count, users_.end());
   // Notify any listeners that the user count has changed.
-  DataDispatcher()->NotifyUsers(users_);
+  DataDispatcher()->SetUserList(users_);
 }
 
 void LoginTestBase::AddUsers(size_t num_users) {
@@ -120,12 +120,12 @@
   }
 
   // Notify any listeners that the user count has changed.
-  DataDispatcher()->NotifyUsers(users_);
+  DataDispatcher()->SetUserList(users_);
 }
 
 void LoginTestBase::AddUserByEmail(const std::string& email) {
   users_.push_back(CreateUser(email));
-  DataDispatcher()->NotifyUsers(users_);
+  DataDispatcher()->SetUserList(users_);
 }
 
 void LoginTestBase::AddPublicAccountUsers(size_t num_public_accounts) {
@@ -136,7 +136,7 @@
   }
 
   // Notify any listeners that the user count has changed.
-  DataDispatcher()->NotifyUsers(users_);
+  DataDispatcher()->SetUserList(users_);
 }
 
 void LoginTestBase::AddChildUsers(size_t num_users) {
@@ -147,7 +147,7 @@
   }
 
   // Notify any listeners that the user count has changed.
-  DataDispatcher()->NotifyUsers(users_);
+  DataDispatcher()->SetUserList(users_);
 }
 
 LoginDataDispatcher* LoginTestBase::DataDispatcher() {
diff --git a/ash/login/ui/login_test_base.h b/ash/login/ui/login_test_base.h
index fb4a811..d634a2a 100644
--- a/ash/login/ui/login_test_base.h
+++ b/ash/login/ui/login_test_base.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "ash/login/ui/login_data_dispatcher.h"
-#include "ash/public/interfaces/login_user_info.mojom.h"
 #include "ash/test/ash_test_base.h"
 #include "base/macros.h"
 
@@ -64,9 +63,9 @@
   // Changes the active number of users. Fires an event on |DataDispatcher()|.
   void AddChildUsers(size_t num_users);
 
-  std::vector<mojom::LoginUserInfoPtr>& users() { return users_; }
+  std::vector<LoginUserInfo>& users() { return users_; }
 
-  const std::vector<mojom::LoginUserInfoPtr>& users() const { return users_; }
+  const std::vector<LoginUserInfo>& users() const { return users_; }
 
   // If the LockScreen is instantiated, returns its data dispatcher. Otherwise,
   // returns a standalone instance.
@@ -81,7 +80,7 @@
   // The widget created using |ShowWidgetWithContent|.
   std::unique_ptr<views::Widget> widget_;
 
-  std::vector<mojom::LoginUserInfoPtr> users_;
+  std::vector<LoginUserInfo> users_;
 
   LoginDataDispatcher data_dispatcher_;
 
diff --git a/ash/login/ui/login_test_utils.cc b/ash/login/ui/login_test_utils.cc
index b31892d..eff688d0 100644
--- a/ash/login/ui/login_test_utils.cc
+++ b/ash/login/ui/login_test_utils.cc
@@ -14,16 +14,14 @@
 constexpr char kPrimaryName[] = "primary";
 constexpr char kSecondaryName[] = "secondary";
 
-mojom::LoginUserInfoPtr CreateUserWithType(const std::string& email,
-                                           user_manager::UserType user_type) {
-  auto user = mojom::LoginUserInfo::New();
-  user->basic_user_info = mojom::UserInfo::New();
-  user->basic_user_info->type = user_type;
-  user->basic_user_info->avatar = mojom::UserAvatar::New();
-  user->basic_user_info->account_id = AccountId::FromUserEmail(email);
-  user->basic_user_info->display_name = base::SplitString(
+LoginUserInfo CreateUserWithType(const std::string& email,
+                                 user_manager::UserType user_type) {
+  LoginUserInfo user;
+  user.basic_user_info.type = user_type;
+  user.basic_user_info.account_id = AccountId::FromUserEmail(email);
+  user.basic_user_info.display_name = base::SplitString(
       email, "@", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)[0];
-  user->basic_user_info->display_email = email;
+  user.basic_user_info.display_email = email;
   return user;
 }
 
@@ -65,27 +63,25 @@
       MakeLoginAuthTestApi(view, target).password_view());
 }
 
-mojom::LoginUserInfoPtr CreateUser(const std::string& email) {
+LoginUserInfo CreateUser(const std::string& email) {
   return CreateUserWithType(email, user_manager::UserType::USER_TYPE_REGULAR);
 }
 
-mojom::LoginUserInfoPtr CreateChildUser(const std::string& email) {
+LoginUserInfo CreateChildUser(const std::string& email) {
   return CreateUserWithType(email, user_manager::UserType::USER_TYPE_CHILD);
 }
 
-mojom::LoginUserInfoPtr CreatePublicAccountUser(const std::string& email) {
-  auto user = mojom::LoginUserInfo::New();
-  user->basic_user_info = mojom::UserInfo::New();
+LoginUserInfo CreatePublicAccountUser(const std::string& email) {
+  LoginUserInfo user;
   std::vector<std::string> email_parts = base::SplitString(
       email, "@", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-  user->basic_user_info->avatar = mojom::UserAvatar::New();
-  user->basic_user_info->account_id = AccountId::FromUserEmail(email);
-  user->basic_user_info->display_name = email_parts[0];
-  user->basic_user_info->display_email = email;
-  user->basic_user_info->type = user_manager::USER_TYPE_PUBLIC_ACCOUNT;
-  user->public_account_info = ash::mojom::PublicAccountInfo::New();
-  user->public_account_info->enterprise_domain = email_parts[1];
-  user->public_account_info->show_expanded_view = true;
+  user.basic_user_info.account_id = AccountId::FromUserEmail(email);
+  user.basic_user_info.display_name = email_parts[0];
+  user.basic_user_info.display_email = email;
+  user.basic_user_info.type = user_manager::USER_TYPE_PUBLIC_ACCOUNT;
+  user.public_account_info.emplace();
+  user.public_account_info->enterprise_domain = email_parts[1];
+  user.public_account_info->show_expanded_view = true;
   return user;
 }
 
diff --git a/ash/login/ui/login_test_utils.h b/ash/login/ui/login_test_utils.h
index f38f7262..1abbfe1 100644
--- a/ash/login/ui/login_test_utils.h
+++ b/ash/login/ui/login_test_utils.h
@@ -8,7 +8,6 @@
 #include "ash/login/ui/lock_contents_view.h"
 #include "ash/login/ui/login_auth_user_view.h"
 #include "ash/login/ui/login_password_view.h"
-#include "ash/public/interfaces/login_user_info.mojom.h"
 
 namespace ui {
 namespace test {
@@ -30,17 +29,17 @@
 LoginPasswordView::TestApi MakeLoginPasswordTestApi(LockContentsView* view,
                                                     AuthTarget auth);
 
-// Utility method to create a new |mojom::LoginUserInfoPtr| instance
+// Utility method to create a new |LoginUserInfo| instance
 // for regular user.
-mojom::LoginUserInfoPtr CreateUser(const std::string& email);
+LoginUserInfo CreateUser(const std::string& email);
 
-// Utility method to create a new |mojom::LoginUserInfoPtr| instance for child
+// Utility method to create a new |LoginUserInfo| instance for child
 // user.
-mojom::LoginUserInfoPtr CreateChildUser(const std::string& email);
+LoginUserInfo CreateChildUser(const std::string& email);
 
-// Utility method to create a new |mojom::LoginUserInfoPtr| instance for
+// Utility method to create a new |LoginUserInfo| instance for
 // public account user.
-mojom::LoginUserInfoPtr CreatePublicAccountUser(const std::string& email);
+LoginUserInfo CreatePublicAccountUser(const std::string& email);
 
 // Returns true if |view| or any child of it has focus.
 bool HasFocusInAnyChildView(const views::View* view);
diff --git a/ash/login/ui/login_user_view.cc b/ash/login/ui/login_user_view.cc
index d55bf8a..e789803 100644
--- a/ash/login/ui/login_user_view.cc
+++ b/ash/login/ui/login_user_view.cc
@@ -15,7 +15,7 @@
 #include "ash/login/ui/views_utils.h"
 #include "ash/public/cpp/ash_constants.h"
 #include "ash/public/cpp/login_constants.h"
-#include "ash/public/interfaces/user_info.mojom.h"
+#include "ash/public/cpp/session/user_info.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/user/rounded_image_view.h"
@@ -121,17 +121,17 @@
   }
   ~UserImage() override = default;
 
-  void UpdateForUser(const mojom::LoginUserInfoPtr& user) {
+  void UpdateForUser(const LoginUserInfo& user) {
     // Set the initial image from |avatar| since we already have it available.
     // Then, decode the bytes via blink's PNG decoder and play any animated
     // frames if they are available.
-    if (!user->basic_user_info->avatar->image.isNull())
-      image_->SetImage(user->basic_user_info->avatar->image);
+    if (!user.basic_user_info.avatar.image.isNull())
+      image_->SetImage(user.basic_user_info.avatar.image);
 
     // Decode the avatar using blink, as blink's PNG decoder supports APNG,
     // which is the format used for the animated avators.
-    if (!user->basic_user_info->avatar->bytes.empty()) {
-      DecodeAnimation(user->basic_user_info->avatar->bytes,
+    if (!user.basic_user_info.avatar.bytes.empty()) {
+      DecodeAnimation(user.basic_user_info.avatar.bytes,
                       base::Bind(&LoginUserView::UserImage::OnImageDecoded,
                                  weak_factory_.GetWeakPtr()));
     }
@@ -204,11 +204,11 @@
   }
   ~UserLabel() override = default;
 
-  void UpdateForUser(const mojom::LoginUserInfoPtr& user) {
-    std::string display_name = user->basic_user_info->display_name;
+  void UpdateForUser(const LoginUserInfo& user) {
+    std::string display_name = user.basic_user_info.display_name;
     // display_name can be empty in debug builds with stub users.
     if (display_name.empty())
-      display_name = user->basic_user_info->display_email;
+      display_name = user.basic_user_info.display_email;
 
     user_name_->SetText(gfx::ElideText(base::UTF8ToUTF16(display_name),
                                        user_name_->font_list(), label_width_,
@@ -424,9 +424,8 @@
 
 LoginUserView::~LoginUserView() = default;
 
-void LoginUserView::UpdateForUser(const mojom::LoginUserInfoPtr& user,
-                                  bool animate) {
-  current_user_ = user->Clone();
+void LoginUserView::UpdateForUser(const LoginUserInfo& user, bool animate) {
+  current_user_ = user;
 
   if (menu_ && menu_->parent()) {
     menu_->parent()->RemoveChildView(menu_);
@@ -434,11 +433,11 @@
   }
 
   menu_ = new LoginUserMenuView(
-      base::UTF8ToUTF16(current_user_->basic_user_info->display_name),
-      base::UTF8ToUTF16(current_user_->basic_user_info->display_email),
-      current_user_->basic_user_info->type, current_user_->is_device_owner,
+      base::UTF8ToUTF16(current_user_.basic_user_info.display_name),
+      base::UTF8ToUTF16(current_user_.basic_user_info.display_email),
+      current_user_.basic_user_info.type, current_user_.is_device_owner,
       dropdown_ /*anchor_view*/, dropdown_ /*bubble_opener*/,
-      current_user_->can_remove /*show_remove_user*/, on_remove_warning_shown_,
+      current_user_.can_remove /*show_remove_user*/, on_remove_warning_shown_,
       on_remove_);
   menu_->SetVisible(false);
 
@@ -574,7 +573,7 @@
 }
 
 void LoginUserView::UpdateCurrentUserState() {
-  auto email = base::UTF8ToUTF16(current_user_->basic_user_info->display_email);
+  auto email = base::UTF8ToUTF16(current_user_.basic_user_info.display_email);
   tap_button_->SetAccessibleName(email);
   if (dropdown_) {
     dropdown_->SetAccessibleName(l10n_util::GetStringFUTF16(
@@ -582,9 +581,9 @@
   }
 
   if (user_domain_) {
-    DCHECK(current_user_->public_account_info);
+    DCHECK(current_user_.public_account_info);
     const base::Optional<std::string>& enterprise_domain =
-        current_user_->public_account_info->enterprise_domain;
+        current_user_.public_account_info->enterprise_domain;
     if (enterprise_domain) {
       user_domain_->SetText(l10n_util::GetStringFUTF16(
           IDS_ASH_LOGIN_PUBLIC_ACCOUNT_INFO_FORMAT,
diff --git a/ash/login/ui/login_user_view.h b/ash/login/ui/login_user_view.h
index 34d04b4..9b90d7fc 100644
--- a/ash/login/ui/login_user_view.h
+++ b/ash/login/ui/login_user_view.h
@@ -9,7 +9,7 @@
 #include "ash/login/ui/login_base_bubble_view.h"
 #include "ash/login/ui/login_display_style.h"
 #include "ash/login/ui/login_user_menu_view.h"
-#include "ash/public/interfaces/login_user_info.mojom.h"
+#include "ash/public/cpp/login_types.h"
 #include "base/macros.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/view.h"
@@ -64,7 +64,7 @@
   ~LoginUserView() override;
 
   // Update the user view to display the given user information.
-  void UpdateForUser(const mojom::LoginUserInfoPtr& user, bool animate);
+  void UpdateForUser(const LoginUserInfo& user, bool animate);
 
   // Set if the view must be opaque.
   void SetForceOpaque(bool force_opaque);
@@ -72,7 +72,7 @@
   // Enables or disables tapping the view.
   void SetTapEnabled(bool enabled);
 
-  const mojom::LoginUserInfoPtr& current_user() const { return current_user_; }
+  const LoginUserInfo& current_user() const { return current_user_; }
 
   // views::View:
   const char* GetClassName() const override;
@@ -109,7 +109,7 @@
 
   // The user that is currently being displayed (or will be displayed when an
   // animation completes).
-  mojom::LoginUserInfoPtr current_user_;
+  LoginUserInfo current_user_;
 
   // Used to dispatch opacity update events.
   std::unique_ptr<HoverNotifier> hover_notifier_;
diff --git a/ash/login/ui/login_user_view_unittest.cc b/ash/login/ui/login_user_view_unittest.cc
index c7effa8..424be3c 100644
--- a/ash/login/ui/login_user_view_unittest.cc
+++ b/ash/login/ui/login_user_view_unittest.cc
@@ -42,7 +42,7 @@
                           on_remove_warning_shown, on_remove);
 
     std::string email = "foo@foo.com";
-    mojom::LoginUserInfoPtr user =
+    LoginUserInfo user =
         public_account ? CreatePublicAccountUser(email) : CreateUser(email);
     view->UpdateForUser(user, false /*animate*/);
     container_->AddChildView(view);
@@ -101,7 +101,7 @@
   EXPECT_GT(extra_small_width, 0);
 
   for (int i = 0; i < 25; ++i) {
-    mojom::LoginUserInfoPtr user = CreateUser("user@domain.com");
+    LoginUserInfo user = CreateUser("user@domain.com");
     large->UpdateForUser(user, false /*animate*/);
     small->UpdateForUser(user, false /*animate*/);
     extra_small->UpdateForUser(user, false /*animate*/);
@@ -281,8 +281,7 @@
                   false /*public_account*/);
   LoginUserView::TestApi view_test(view);
 
-  mojom::LoginUserInfoPtr user =
-      CreateUser("verylongusernamethatfillsthebox@domain.com");
+  LoginUserInfo user = CreateUser("verylongusernamethatfillsthebox@domain.com");
   view->UpdateForUser(user, false /*animate*/);
   container_->Layout();
 
diff --git a/ash/login/ui/scrollable_users_list_view.cc b/ash/login/ui/scrollable_users_list_view.cc
index f6d284b19..76b2a02 100644
--- a/ash/login/ui/scrollable_users_list_view.cc
+++ b/ash/login/ui/scrollable_users_list_view.cc
@@ -12,7 +12,6 @@
 #include "ash/login/ui/non_accessible_view.h"
 #include "ash/login/ui/views_utils.h"
 #include "ash/public/cpp/login_constants.h"
-#include "ash/public/interfaces/login_user_info.mojom.h"
 #include "ash/shell.h"
 #include "ash/wallpaper/wallpaper_controller.h"
 #include "base/bind.h"
@@ -286,7 +285,7 @@
 }
 
 ScrollableUsersListView::ScrollableUsersListView(
-    const std::vector<mojom::LoginUserInfoPtr>& users,
+    const std::vector<LoginUserInfo>& users,
     const ActionWithUser& on_tap_user,
     LoginDisplayStyle display_style)
     : display_style_(display_style) {
@@ -346,7 +345,7 @@
 LoginUserView* ScrollableUsersListView::GetUserView(
     const AccountId& account_id) {
   for (auto* view : user_views_) {
-    if (view->current_user()->basic_user_info->account_id == account_id)
+    if (view->current_user().basic_user_info.account_id == account_id)
       return view;
   }
   return nullptr;
diff --git a/ash/login/ui/scrollable_users_list_view.h b/ash/login/ui/scrollable_users_list_view.h
index 68b59e1..5e0e9e0 100644
--- a/ash/login/ui/scrollable_users_list_view.h
+++ b/ash/login/ui/scrollable_users_list_view.h
@@ -10,7 +10,6 @@
 #include "ash/ash_export.h"
 #include "ash/login/ui/login_display_style.h"
 #include "ash/login/ui/login_user_view.h"
-#include "ash/public/interfaces/login_user_info.mojom.h"
 #include "ash/wallpaper/wallpaper_controller_observer.h"
 #include "base/scoped_observer.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -49,7 +48,7 @@
   // Initializes users list with rows for all |users|. The |display_style| is
   // used to determine layout and sizings. |on_user_view_tap| callback is
   // invoked whenever user row is tapped.
-  ScrollableUsersListView(const std::vector<mojom::LoginUserInfoPtr>& users,
+  ScrollableUsersListView(const std::vector<LoginUserInfo>& users,
                           const ActionWithUser& on_tap_user,
                           LoginDisplayStyle display_style);
   ~ScrollableUsersListView() override;
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index 00840b9..e12ddb5 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -89,6 +89,12 @@
     "lock_screen_widget_factory.cc",
     "lock_screen_widget_factory.h",
     "login_constants.h",
+    "login_screen.cc",
+    "login_screen.h",
+    "login_screen_model.cc",
+    "login_screen_model.h",
+    "login_types.cc",
+    "login_types.h",
     "network_icon_image_source.cc",
     "network_icon_image_source.h",
     "new_window_delegate.cc",
diff --git a/ash/public/cpp/login_screen.cc b/ash/public/cpp/login_screen.cc
new file mode 100644
index 0000000..9ff259c
--- /dev/null
+++ b/ash/public/cpp/login_screen.cc
@@ -0,0 +1,30 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/public/cpp/login_screen.h"
+
+#include "base/logging.h"
+
+namespace ash {
+
+namespace {
+LoginScreen* g_instance = nullptr;
+}
+
+// static
+LoginScreen* LoginScreen::Get() {
+  return g_instance;
+}
+
+LoginScreen::LoginScreen() {
+  DCHECK_EQ(nullptr, g_instance);
+  g_instance = this;
+}
+
+LoginScreen::~LoginScreen() {
+  DCHECK_EQ(this, g_instance);
+  g_instance = nullptr;
+}
+
+}  // namespace ash
diff --git a/ash/public/cpp/login_screen.h b/ash/public/cpp/login_screen.h
new file mode 100644
index 0000000..660c869d
--- /dev/null
+++ b/ash/public/cpp/login_screen.h
@@ -0,0 +1,33 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_PUBLIC_CPP_LOGIN_SCREEN_H_
+#define ASH_PUBLIC_CPP_LOGIN_SCREEN_H_
+
+#include <string>
+
+#include "ash/public/cpp/ash_public_export.h"
+
+namespace ash {
+
+class LoginScreenModel;
+
+// Allows clients (e.g. the browser process) to send messages to the ash
+// login/lock/user-add screens.
+// TODO(estade): move more of mojom::LoginScreen here.
+class ASH_PUBLIC_EXPORT LoginScreen {
+ public:
+  // Returns the singleton instance.
+  static LoginScreen* Get();
+
+  virtual LoginScreenModel* GetModel() = 0;
+
+ protected:
+  LoginScreen();
+  virtual ~LoginScreen();
+};
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_LOGIN_SCREEN_H_
diff --git a/ash/public/cpp/login_screen_model.cc b/ash/public/cpp/login_screen_model.cc
new file mode 100644
index 0000000..c0074701
--- /dev/null
+++ b/ash/public/cpp/login_screen_model.cc
@@ -0,0 +1,11 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/public/cpp/login_screen_model.h"
+
+namespace ash {
+
+LoginScreenModel::~LoginScreenModel() = default;
+
+}
diff --git a/ash/public/cpp/login_screen_model.h b/ash/public/cpp/login_screen_model.h
new file mode 100644
index 0000000..441c490
--- /dev/null
+++ b/ash/public/cpp/login_screen_model.h
@@ -0,0 +1,68 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_PUBLIC_CPP_LOGIN_SCREEN_MODEL_H_
+#define ASH_PUBLIC_CPP_LOGIN_SCREEN_MODEL_H_
+
+#include <string>
+
+#include "ash/public/cpp/ash_public_export.h"
+
+class AccountId;
+
+namespace ash {
+
+enum class FingerprintState;
+struct EasyUnlockIconOptions;
+struct InputMethodItem;
+struct LocaleItem;
+struct LoginUserInfo;
+struct UserAvatar;
+
+// Provides Chrome access to Ash's login UI. See additional docs for
+// ash::LoginDataDispatcher.
+class ASH_PUBLIC_EXPORT LoginScreenModel {
+ public:
+  // Requests to show the custom icon in the user pod.
+  // |account_id|:  The account id of the user in the user pod.
+  // |icon|:        Information regarding the icon.
+  virtual void ShowEasyUnlockIcon(const AccountId& account_id,
+                                  const EasyUnlockIconOptions& icon) = 0;
+
+  // Set the users who are displayed on the login UI. |users| is filtered
+  // and does not correspond to every user on the device.
+  virtual void SetUserList(const std::vector<LoginUserInfo>& users) = 0;
+
+  // Update the status of fingerprint for |account_id|.
+  virtual void SetFingerprintState(const AccountId& account_id,
+                                   FingerprintState state) = 0;
+
+  // Called when |avatar| for |account_id| has changed.
+  virtual void SetAvatarForUser(const AccountId& account_id,
+                                const UserAvatar& avatar) = 0;
+
+  // Set the public session locales for user with |account_id|.
+  // |locales|:            Available locales for this user.
+  // |default_locale|:     Default locale for this user.
+  // |show_advanced_view|: True if we should show the advanced expanded user
+  //                       view for the public session.
+  virtual void SetPublicSessionLocales(const AccountId& account_id,
+                                       const std::vector<LocaleItem>& locales,
+                                       const std::string& default_locale,
+                                       bool show_advanced_view) = 0;
+
+  // Set the public session keyboard layouts for user with |account_id|.
+  // |locale|: The locale that |keyboard_layouts| can be used for.
+  virtual void SetPublicSessionKeyboardLayouts(
+      const AccountId& account_id,
+      const std::string& locale,
+      const std::vector<InputMethodItem>& keyboard_layouts) = 0;
+
+ protected:
+  virtual ~LoginScreenModel();
+};
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_LOGIN_SCREEN_MODEL_H_
diff --git a/ash/public/cpp/login_types.cc b/ash/public/cpp/login_types.cc
new file mode 100644
index 0000000..47857fb
--- /dev/null
+++ b/ash/public/cpp/login_types.cc
@@ -0,0 +1,56 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/public/cpp/login_types.h"
+
+namespace ash {
+
+EasyUnlockIconOptions::EasyUnlockIconOptions() = default;
+EasyUnlockIconOptions::EasyUnlockIconOptions(
+    const EasyUnlockIconOptions& other) = default;
+EasyUnlockIconOptions::EasyUnlockIconOptions(EasyUnlockIconOptions&& other) =
+    default;
+EasyUnlockIconOptions::~EasyUnlockIconOptions() = default;
+
+EasyUnlockIconOptions& EasyUnlockIconOptions::operator=(
+    const EasyUnlockIconOptions& other) = default;
+EasyUnlockIconOptions& EasyUnlockIconOptions::operator=(
+    EasyUnlockIconOptions&& other) = default;
+
+InputMethodItem::InputMethodItem() = default;
+InputMethodItem::InputMethodItem(const InputMethodItem& other) = default;
+InputMethodItem::InputMethodItem(InputMethodItem&& other) = default;
+InputMethodItem::~InputMethodItem() = default;
+
+InputMethodItem& InputMethodItem::operator=(const InputMethodItem& other) =
+    default;
+InputMethodItem& InputMethodItem::operator=(InputMethodItem&& other) = default;
+
+LocaleItem::LocaleItem() = default;
+LocaleItem::LocaleItem(const LocaleItem& other) = default;
+LocaleItem::LocaleItem(LocaleItem&& other) = default;
+LocaleItem::~LocaleItem() = default;
+
+LocaleItem& LocaleItem::operator=(const LocaleItem& other) = default;
+LocaleItem& LocaleItem::operator=(LocaleItem&& other) = default;
+
+PublicAccountInfo::PublicAccountInfo() = default;
+PublicAccountInfo::PublicAccountInfo(const PublicAccountInfo& other) = default;
+PublicAccountInfo::PublicAccountInfo(PublicAccountInfo&& other) = default;
+PublicAccountInfo::~PublicAccountInfo() = default;
+
+PublicAccountInfo& PublicAccountInfo::operator=(
+    const PublicAccountInfo& other) = default;
+PublicAccountInfo& PublicAccountInfo::operator=(PublicAccountInfo&& other) =
+    default;
+
+LoginUserInfo::LoginUserInfo() = default;
+LoginUserInfo::LoginUserInfo(const LoginUserInfo& other) = default;
+LoginUserInfo::LoginUserInfo(LoginUserInfo&& other) = default;
+LoginUserInfo::~LoginUserInfo() = default;
+
+LoginUserInfo& LoginUserInfo::operator=(const LoginUserInfo& other) = default;
+LoginUserInfo& LoginUserInfo::operator=(LoginUserInfo&& other) = default;
+
+}  // namespace ash
diff --git a/ash/public/cpp/login_types.h b/ash/public/cpp/login_types.h
new file mode 100644
index 0000000..ee2e5ee
--- /dev/null
+++ b/ash/public/cpp/login_types.h
@@ -0,0 +1,211 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_PUBLIC_CPP_LOGIN_TYPES_H_
+#define ASH_PUBLIC_CPP_LOGIN_TYPES_H_
+
+#include "ash/public/cpp/ash_public_export.h"
+#include "ash/public/cpp/session/user_info.h"
+#include "base/token.h"
+#include "chromeos/components/proximity_auth/public/interfaces/auth_type.mojom.h"
+
+namespace ash {
+
+// Supported multi-profile user behavior values.
+// Keep in sync with the enum in chromeos_user_pod_row.js and user_pod_row.js
+// TODO(estade): change all the enums to use kCamelCase.
+enum class MultiProfileUserBehavior {
+  UNRESTRICTED = 0,
+  PRIMARY_ONLY = 1,
+  NOT_ALLOWED = 2,
+  OWNER_PRIMARY_ONLY = 3,
+};
+
+// Easy unlock icon choices.
+enum class EasyUnlockIconId {
+  // No icon shown.
+  NONE,
+  // The user has clicked the easy unlock icon and disabled easy unlock for this
+  // login/lock session.
+  HARDLOCKED,
+  // Phone could not be found.
+  LOCKED,
+  // Phone found, but it is not unlocked.
+  LOCKED_TO_BE_ACTIVATED,
+  // Phone found, but it is too far away.
+  LOCKED_WITH_PROXIMITY_HINT,
+  // Phone found and unlocked. The user can click to dismiss the login/lock
+  // screen.
+  UNLOCKED,
+  // Scanning for phone.
+  SPINNER,
+};
+
+// The status of fingerprint availability.
+enum class FingerprintState {
+  // The user cannot use fingerprint. This may be because:
+  //  - they are not the primary user
+  //  - they never registered fingerprint
+  //  - the device does not have a fingerprint sensor
+  UNAVAILABLE,
+  // Fingerprint can be used to unlock the device.
+  AVAILABLE,
+  // There have been too many attempts, so now fingerprint is disabled.
+  DISABLED_FROM_ATTEMPTS,
+  // It has been too long since the device was last used.
+  DISABLED_FROM_TIMEOUT,
+  kMaxValue = DISABLED_FROM_TIMEOUT,
+};
+
+// Information about the custom icon in the user pod.
+struct ASH_PUBLIC_EXPORT EasyUnlockIconOptions {
+  EasyUnlockIconOptions();
+  EasyUnlockIconOptions(const EasyUnlockIconOptions& other);
+  EasyUnlockIconOptions(EasyUnlockIconOptions&& other);
+  ~EasyUnlockIconOptions();
+
+  EasyUnlockIconOptions& operator=(const EasyUnlockIconOptions& other);
+  EasyUnlockIconOptions& operator=(EasyUnlockIconOptions&& other);
+
+  // Icon that should be displayed.
+  EasyUnlockIconId icon = EasyUnlockIconId::NONE;
+  // Tooltip that is associated with the icon. This is shown automatically if
+  // |autoshow_tooltip| is true. The user can always see the tooltip if they
+  // hover over the icon. The tooltip should be used for the accessibility label
+  // if it is present.
+  base::string16 tooltip;
+  // If true, the tooltip should be displayed (even if the user is not currently
+  // hovering over the icon, ie, this makes |tooltip| act like a little like a
+  // notification).
+  bool autoshow_tooltip = false;
+  // Accessibility label. Only used if |tooltip| is empty.
+  // TODO(jdufault): Always populate and use |aria_label|, even if |tooltip| is
+  // non-empty.
+  base::string16 aria_label;
+  // If true, clicking the easy unlock icon should fire a hardlock event which
+  // will disable easy unlock. The hardlock event will request a new icon
+  // display via a separate EasyUnlockIconsOption update. See
+  // login_screen.mojom::HardlockPod.
+  bool hardlock_on_click = false;
+};
+
+// Information of each input method. This is used to populate keyboard layouts
+// for public account user.
+struct ASH_PUBLIC_EXPORT InputMethodItem {
+  InputMethodItem();
+  InputMethodItem(const InputMethodItem& other);
+  InputMethodItem(InputMethodItem&& other);
+  ~InputMethodItem();
+
+  InputMethodItem& operator=(const InputMethodItem& other);
+  InputMethodItem& operator=(InputMethodItem&& other);
+
+  // An id that identifies an input method engine (e.g., "t:latn-post",
+  // "pinyin", "hangul").
+  std::string ime_id;
+
+  // Title of the input method.
+  std::string title;
+
+  // Whether this input method is been selected.
+  bool selected = false;
+};
+
+// Information of each available locale. This is used to populate language
+// locales for public account user.
+struct ASH_PUBLIC_EXPORT LocaleItem {
+  LocaleItem();
+  LocaleItem(const LocaleItem& other);
+  LocaleItem(LocaleItem&& other);
+  ~LocaleItem();
+
+  LocaleItem& operator=(const LocaleItem& other);
+  LocaleItem& operator=(LocaleItem&& other);
+
+  // Language code of the locale.
+  std::string language_code;
+
+  // Title of the locale.
+  std::string title;
+
+  // Group name of the locale.
+  base::Optional<std::string> group_name;
+};
+
+// Information about a public account user.
+struct ASH_PUBLIC_EXPORT PublicAccountInfo {
+  PublicAccountInfo();
+  PublicAccountInfo(const PublicAccountInfo& other);
+  PublicAccountInfo(PublicAccountInfo&& other);
+  ~PublicAccountInfo();
+
+  PublicAccountInfo& operator=(const PublicAccountInfo& other);
+  PublicAccountInfo& operator=(PublicAccountInfo&& other);
+
+  // The domain name displayed in the login screen UI.
+  base::Optional<std::string> enterprise_domain;
+
+  // A list of available user locales.
+  std::vector<LocaleItem> available_locales;
+
+  // Default locale for this user.
+  std::string default_locale;
+
+  // Show expanded user view that contains session information/warnings and
+  // locale selection.
+  bool show_expanded_view = false;
+
+  // Show the advanced expanded user view if there are at least two recommended
+  // locales. This will be the case in multilingual environments where users
+  // are likely to want to choose among locales.
+  bool show_advanced_view = false;
+
+  // A list of available keyboard layouts.
+  std::vector<InputMethodItem> keyboard_layouts;
+};
+
+// Info about a user in login/lock screen.
+struct ASH_PUBLIC_EXPORT LoginUserInfo {
+  LoginUserInfo();
+  LoginUserInfo(const LoginUserInfo& other);
+  LoginUserInfo(LoginUserInfo&& other);
+  ~LoginUserInfo();
+
+  LoginUserInfo& operator=(const LoginUserInfo& other);
+  LoginUserInfo& operator=(LoginUserInfo&& other);
+
+  // User's basic information including account id, email, avatar etc.
+  UserInfo basic_user_info;
+
+  // What method the user can use to sign in.
+  proximity_auth::mojom::AuthType auth_type =
+      proximity_auth::mojom::AuthType::OFFLINE_PASSWORD;
+
+  // True if this user has already signed in.
+  bool is_signed_in = false;
+
+  // True if this user is the device owner.
+  bool is_device_owner = false;
+
+  // The initial fingerprint state. There are other mojom methods (ie,
+  // login_screen.mojom::SetFingerprintState) which update the current state.
+  FingerprintState fingerprint_state = FingerprintState::UNAVAILABLE;
+
+  // True if multi-profiles sign in is allowed for this user.
+  bool is_multiprofile_allowed = false;
+
+  // Enforced policy for multi-profiles sign in.
+  MultiProfileUserBehavior multiprofile_policy =
+      MultiProfileUserBehavior::UNRESTRICTED;
+
+  // True if this user can be removed.
+  bool can_remove = false;
+
+  // Contains the public account information if user type is PUBLIC_ACCOUNT.
+  base::Optional<PublicAccountInfo> public_account_info;
+};
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_LOGIN_TYPES_H_
diff --git a/ash/public/cpp/session/user_info.cc b/ash/public/cpp/session/user_info.cc
index fd00b92..8374ce7 100644
--- a/ash/public/cpp/session/user_info.cc
+++ b/ash/public/cpp/session/user_info.cc
@@ -18,26 +18,6 @@
 UserInfo::UserInfo(const UserInfo& other) = default;
 UserInfo::~UserInfo() = default;
 
-mojom::UserInfoPtr UserInfo::ToMojom() const {
-  mojom::UserInfoPtr user_info = mojom::UserInfo::New();
-  user_info->type = type;
-  user_info->account_id = account_id;
-  user_info->service_instance_group = service_instance_group;
-  user_info->display_name = display_name;
-  user_info->display_email = display_email;
-
-  user_info->avatar = mojom::UserAvatar::New();
-  user_info->avatar->image = avatar.image;
-  user_info->avatar->bytes = avatar.bytes;
-
-  user_info->is_new_profile = is_new_profile;
-  user_info->is_ephemeral = is_ephemeral;
-  user_info->is_device_owner = is_device_owner;
-  user_info->has_gaia_account = has_gaia_account;
-  user_info->should_display_managed_ui = should_display_managed_ui;
-  return user_info;
-}
-
 ASH_PUBLIC_EXPORT bool operator==(const UserInfo& a, const UserInfo& b) {
   return a.type == b.type && a.account_id == b.account_id &&
          a.service_instance_group == b.service_instance_group &&
diff --git a/ash/public/cpp/session/user_info.h b/ash/public/cpp/session/user_info.h
index 7ce1d234..6656db1 100644
--- a/ash/public/cpp/session/user_info.h
+++ b/ash/public/cpp/session/user_info.h
@@ -11,7 +11,7 @@
 #include <vector>
 
 #include "ash/public/cpp/ash_public_export.h"
-#include "ash/public/interfaces/user_info.mojom.h"
+#include "ash/public/cpp/session/user_info.h"
 #include "base/optional.h"
 #include "base/token.h"
 #include "components/account_id/account_id.h"
@@ -39,10 +39,6 @@
   UserInfo(const UserInfo& other);
   ~UserInfo();
 
-  // TODO(crbug.com/958206): Remove after login mojom migrates to use this and
-  // fix DetachableBaseHandler.
-  mojom::UserInfoPtr ToMojom() const;
-
   user_manager::UserType type = user_manager::USER_TYPE_REGULAR;
   AccountId account_id;
   base::Optional<base::Token> service_instance_group;
diff --git a/ash/public/interfaces/BUILD.gn b/ash/public/interfaces/BUILD.gn
index 4aba5ef2..780ff57 100644
--- a/ash/public/interfaces/BUILD.gn
+++ b/ash/public/interfaces/BUILD.gn
@@ -37,7 +37,6 @@
     "kiosk_next_shell.mojom",
     "locale.mojom",
     "login_screen.mojom",
-    "login_user_info.mojom",
     "media.mojom",
     "night_light_controller.mojom",
     "note_taking_controller.mojom",
@@ -47,7 +46,6 @@
     "tablet_mode.mojom",
     "tray_action.mojom",
     "update.mojom",
-    "user_info.mojom",
     "voice_interaction_controller.mojom",
     "vpn_list.mojom",
     "wallpaper.mojom",
diff --git a/ash/public/interfaces/login_screen.mojom b/ash/public/interfaces/login_screen.mojom
index 6a3367c0..7f942a2 100644
--- a/ash/public/interfaces/login_screen.mojom
+++ b/ash/public/interfaces/login_screen.mojom
@@ -4,8 +4,6 @@
 
 module ash.mojom;
 
-import "ash/public/interfaces/user_info.mojom";
-import "ash/public/interfaces/login_user_info.mojom";
 import "chromeos/components/proximity_auth/public/interfaces/auth_type.mojom";
 import "components/account_id/interfaces/account_id.mojom";
 import "mojo/public/mojom/base/string16.mojom";
@@ -78,6 +76,8 @@
 
 // Allows clients (e.g. the browser process) to send messages to the ash
 // login/lock/user-add screens.
+// TODO(estade): this is in the process of being migrated off Mojo. Methods will
+// move to ash::LoginScreen or ash::LoginScreenModel.
 interface LoginScreen {
   // Sets the client interface.
   SetClient(LoginScreenClient client);
@@ -117,16 +117,6 @@
   // Requests to close any displayed error messages in ash lock screen.
   ClearErrors();
 
-  // Requests to show the custom icon in the user pod.
-  // |account_id|:  The account id of the user in the user pod.
-  // |icon|:        Information regarding the icon.
-  ShowUserPodCustomIcon(signin.mojom.AccountId account_id,
-                        EasyUnlockIconOptions icon);
-
-  // Requests to hide the custom icon in the user pod.
-  // |account_id|:  The account id of the user in the user pod.
-  HideUserPodCustomIcon(signin.mojom.AccountId account_id);
-
   // Requests to set the authentication type.
   // |account_id|:    The account id of the user in the user pod.
   // |auth_type|:     Authentication type.
@@ -135,19 +125,11 @@
               proximity_auth.mojom.AuthType auth_type,
               mojo_base.mojom.String16 initial_value);
 
-  // Set the users who are displayed on the login UI. |users| is filtered
-  // and does not correspond to every user on the device.
-  SetUserList(array<LoginUserInfo> users);
-
   // Notification if pin is enabled or disabled for the given user.
   // |account_id|:   The account id of the user in the user pod.
   // |is_enabled|:   True if pin unlock is enabled.
   SetPinEnabledForUser(signin.mojom.AccountId account_id, bool is_enabled);
 
-  // Update the status of fingerprint for |account_id|.
-  SetFingerprintState(signin.mojom.AccountId account_id,
-                      FingerprintState state);
-
   // Called after a fingerprint authentication attempt has been made. If
   // |successful| is true, then the fingerprint authentication attempt was
   // successful and the device should be unlocked. If false, an error message
@@ -155,10 +137,6 @@
   NotifyFingerprintAuthResult(signin.mojom.AccountId account_id,
                               bool successful);
 
-  // Change the user's avatar. Some avatars may take a long time to load and the
-  // login screen may already be visible.
-  SetAvatarForUser(signin.mojom.AccountId account_id, UserAvatar avatar);
-
   // Called when auth should be enabled for the given user. When auth is
   // disabled, the user cannot unlock the device. Auth is enabled by default.
   // |account_id|:            The account id of the user in the user pod.
@@ -196,22 +174,6 @@
   SetPublicSessionDisplayName(signin.mojom.AccountId account_id,
                               string display_name);
 
-  // Set the public session locales for user with |account_id|.
-  // |locales|:            Available locales for this user.
-  // |default_locale|:     Default locale for this user.
-  // |show_advanced_view|: True if we should show the advanced expanded user
-  //                       view for the public session.
-  SetPublicSessionLocales(signin.mojom.AccountId account_id,
-                          array<LocaleItem> locales,
-                          string default_locale,
-                          bool show_advanced_view);
-
-  // Set the public session keyboard layouts for user with |account_id|.
-  // |locale|: The locale that |keyboard_layouts| can be used for.
-  SetPublicSessionKeyboardLayouts(signin.mojom.AccountId account_id,
-                                  string locale,
-                                  array<InputMethodItem> keyboard_layouts);
-
   // Sets whether full management disclosure is needed for the public/managed
   // session login screen.
   SetPublicSessionShowFullManagementDisclosure(
diff --git a/ash/public/interfaces/login_user_info.mojom b/ash/public/interfaces/login_user_info.mojom
deleted file mode 100644
index 16f8b69b..0000000
--- a/ash/public/interfaces/login_user_info.mojom
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2017 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 ash.mojom;
-
-import "ash/public/interfaces/user_info.mojom";
-import "chromeos/components/proximity_auth/public/interfaces/auth_type.mojom";
-import "mojo/public/mojom/base/string16.mojom";
-import "mojo/public/mojom/base/values.mojom";
-
-// Supported multi-profile user behavior values.
-// Keep in sync with the enum in chromeos_user_pod_row.js and user_pod_row.js
-enum MultiProfileUserBehavior {
-  UNRESTRICTED = 0,
-  PRIMARY_ONLY = 1,
-  NOT_ALLOWED = 2,
-  OWNER_PRIMARY_ONLY = 3,
-};
-
-// Easy unlock icon choices.
-enum EasyUnlockIconId {
-  // No icon shown.
-  NONE,
-  // The user has clicked the easy unlock icon and disabled easy unlock for this
-  // login/lock session.
-  HARDLOCKED,
-  // Phone could not be found.
-  LOCKED,
-  // Phone found, but it is not unlocked.
-  LOCKED_TO_BE_ACTIVATED,
-  // Phone found, but it is too far away.
-  LOCKED_WITH_PROXIMITY_HINT,
-  // Phone found and unlocked. The user can click to dismiss the login/lock
-  // screen.
-  UNLOCKED,
-  // Scanning for phone.
-  SPINNER,
-};
-
-// The status of fingerprint availability.
-enum FingerprintState {
-  // The user cannot use fingerprint. This may be because:
-  //  - they are not the primary user
-  //  - they never registered fingerprint
-  //  - the device does not have a fingerprint sensor
-  UNAVAILABLE,
-  // Fingerprint can be used to unlock the device.
-  AVAILABLE,
-  // There have been too many attempts, so now fingerprint is disabled.
-  DISABLED_FROM_ATTEMPTS,
-  // It has been too long since the device was last used.
-  DISABLED_FROM_TIMEOUT,
-};
-
-// Information about the custom icon in the user pod.
-struct EasyUnlockIconOptions {
-  // Icon that should be displayed.
-  EasyUnlockIconId icon;
-  // Tooltip that is associated with the icon. This is shown automatically if
-  // |autoshow_tooltip| is true. The user can always see the tooltip if they
-  // hover over the icon. The tooltip should be used for the accessibility label
-  // if it is present.
-  mojo_base.mojom.String16 tooltip;
-  // If true, the tooltip should be displayed (even if the user is not currently
-  // hovering over the icon, ie, this makes |tooltip| act like a little like a
-  // notification).
-  bool autoshow_tooltip;
-  // Accessibility label. Only used if |tooltip| is empty.
-  // TODO(jdufault): Always populate and use |aria_label|, even if |tooltip| is
-  // non-empty.
-  mojo_base.mojom.String16 aria_label;
-  // If true, clicking the easy unlock icon should fire a hardlock event which
-  // will disable easy unlock. The hardlock event will request a new icon
-  // display via a separate EasyUnlockIconsOption update. See
-  // login_screen.mojom::HardlockPod.
-  bool hardlock_on_click;
-};
-
-// Infomation of each input method. This is used to populate keyboard layouts
-// for public account user.
-struct InputMethodItem {
-  // An id that identifies an input method engine (e.g., "t:latn-post",
-  // "pinyin", "hangul").
-  string ime_id;
-
-  // Title of the imput method.
-  string title;
-
-  // Whether this input method is been selected.
-  bool selected;
-};
-
-// Information of each available locale. This is used to populate language
-// locales for public account user.
-struct LocaleItem {
-  // Language code of the locale.
-  string language_code;
-
-  // Title of the locale.
-  string title;
-
-  // Optional, group name of the locale.
-  string? group_name;
-};
-
-// Infomation about a public account user.
-struct PublicAccountInfo {
-  // Optional, the domain name displayed in the login screen UI.
-  string? enterprise_domain;
-
-  // A list of available user locales.
-  array<LocaleItem> available_locales;
-
-  // Default locale for this user.
-  string default_locale;
-
-  // Show expanded user view that contains session information/warnings and
-  // locale selection.
-  bool show_expanded_view;
-
-  // Show the advanced expanded user view if there are at least two recommended
-  // locales. This will be the case in multilingual environments where users
-  // are likely to want to choose among locales.
-  bool show_advanced_view;
-
-  // A list of available keyboard layouts.
-  array<InputMethodItem> keyboard_layouts;
-};
-
-// Info about a user in login/lock screen.
-struct LoginUserInfo {
-  // User's basic information including account id, email, avatar etc.
-  UserInfo basic_user_info;
-
-  // What method the user can use to sign in.
-  proximity_auth.mojom.AuthType auth_type;
-
-  // True if this user has already signed in.
-  bool is_signed_in;
-
-  // True if this user is the device owner.
-  bool is_device_owner;
-
-  // The initial fingerprint state. There are other mojom methods (ie,
-  // login_screen.mojom::SetFingerprintState) which update the current state.
-  FingerprintState fingerprint_state;
-
-  // True if multi-profiles sign in is allowed for this user.
-  bool is_multiprofile_allowed;
-
-  // Enforced policy for multi-profiles sign in.
-  MultiProfileUserBehavior multiprofile_policy;
-
-  // True if this user can be removed.
-  bool can_remove;
-
-  // Optional, contains the public account information if user type is
-  // PUBLIC_ACCOUNT.
-  PublicAccountInfo? public_account_info;
-};
diff --git a/ash/public/interfaces/typemaps.gni b/ash/public/interfaces/typemaps.gni
index a21e3662..7305cb5 100644
--- a/ash/public/interfaces/typemaps.gni
+++ b/ash/public/interfaces/typemaps.gni
@@ -4,6 +4,5 @@
 
 typemaps = [
   "//ash/public/interfaces/shelf_integration_test_api.typemap",
-  "//ash/public/interfaces/user_info.typemap",
   "//ash/public/interfaces/wallpaper.typemap",
 ]
diff --git a/ash/public/interfaces/user_info.mojom b/ash/public/interfaces/user_info.mojom
deleted file mode 100644
index 3e159f90..0000000
--- a/ash/public/interfaces/user_info.mojom
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2017 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 ash.mojom;
-
-import "components/account_id/interfaces/account_id.mojom";
-import "mojo/public/mojom/base/token.mojom";
-import "ui/gfx/image/mojo/image.mojom";
-
-// Matches user_manager::UserType.
-enum UserType {
-  // Regular user, has a user name and password.
-  REGULAR,
-
-  // Guest user, logs in without authentication.
-  GUEST,
-
-  // Public account user, logs in without authentication. Available only if
-  // enabled through policy.
-  PUBLIC_ACCOUNT,
-
-  // Supervised user, logs in only with local authentication.
-  SUPERVISED,
-
-  // Kiosk app robot, logs in without authentication.
-  KIOSK,
-
-  // Child user, with supervised options.
-  CHILD,
-
-  // Android app in kiosk mode, logs in without authentication.
-  ARC_KIOSK,
-
-  // Active Directory user. Authenticates against Active Directory server.
-  ACTIVE_DIRECTORY,
-};
-
-// Data for a user's avatar.
-struct UserAvatar {
-  gfx.mojom.ImageSkia image;
-  // The raw bytes for the avatar. Useful if the avatar is animated.
-  // TODO(crbug.com/770373): Use a shared buffer (mojo.Blob), as this may be
-  // large enough to congest IPC.
-  array<uint8> bytes;
-};
-
-// Info about a user. May be sent repeatedly for a single user because
-// individual fields may change (e.g. the avatar image or custodians).
-struct UserInfo {
-  UserType type;
-  signin.mojom.AccountId account_id;
-  mojo_base.mojom.Token? service_instance_group;
-  string display_name;
-  string display_email;
-  UserAvatar avatar;
-  // True if this user has a newly created profile (first time login on the
-  // device)
-  bool is_new_profile;
-  // True if the user's non-cryptohome data (wallpaper, avatar etc.) is
-  // ephemeral. See |UserManager::IsUserNonCryptohomeDataEphemeral| for details.
-  bool is_ephemeral;
-  // True if the user is also the device owner.
-  bool is_device_owner;
-  // True if the user has a gaia account.
-  bool has_gaia_account;
-  // True if should display managed ui.
-  bool should_display_managed_ui;
-};
diff --git a/ash/public/interfaces/user_info.typemap b/ash/public/interfaces/user_info.typemap
deleted file mode 100644
index 5a0e9376..0000000
--- a/ash/public/interfaces/user_info.typemap
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2017 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.
-
-mojom = "//ash/public/interfaces/user_info.mojom"
-public_headers = [ "//components/user_manager/user_type.h" ]
-traits_headers = [ "//ash/public/interfaces/user_info_traits.h" ]
-public_deps = [
-  "//components/user_manager",
-]
-type_mappings = [ "ash.mojom.UserType=user_manager::UserType" ]
diff --git a/ash/public/interfaces/user_info_traits.h b/ash/public/interfaces/user_info_traits.h
index 77bf2a0..fc24fd2 100644
--- a/ash/public/interfaces/user_info_traits.h
+++ b/ash/public/interfaces/user_info_traits.h
@@ -5,7 +5,7 @@
 #ifndef ASH_PUBLIC_INTERFACES_USER_INFO_TRAITS_H_
 #define ASH_PUBLIC_INTERFACES_USER_INFO_TRAITS_H_
 
-#include "ash/public/interfaces/user_info.mojom.h"
+#include "ash/public/cpp/session/user_info.h"
 #include "components/user_manager/user_type.h"
 
 namespace mojo {
diff --git a/ash/public/interfaces/wallpaper.mojom b/ash/public/interfaces/wallpaper.mojom
index e04f2d2..3e0d540 100644
--- a/ash/public/interfaces/wallpaper.mojom
+++ b/ash/public/interfaces/wallpaper.mojom
@@ -4,7 +4,6 @@
 
 module ash.mojom;
 
-import "ash/public/interfaces/user_info.mojom";
 import "components/account_id/interfaces/account_id.mojom";
 import "mojo/public/mojom/base/file_path.mojom";
 import "mojo/public/mojom/base/time.mojom";
@@ -19,6 +18,34 @@
   TILE,
 };
 
+// Matches user_manager::UserType.
+enum UserType {
+  // Regular user, has a user name and password.
+  REGULAR,
+
+  // Guest user, logs in without authentication.
+  GUEST,
+
+  // Public account user, logs in without authentication. Available only if
+  // enabled through policy.
+  PUBLIC_ACCOUNT,
+
+  // Supervised user, logs in only with local authentication.
+  SUPERVISED,
+
+  // Kiosk app robot, logs in without authentication.
+  KIOSK,
+
+  // Child user, with supervised options.
+  CHILD,
+
+  // Android app in kiosk mode, logs in without authentication.
+  ARC_KIOSK,
+
+  // Active Directory user. Authenticates against Active Directory server.
+  ACTIVE_DIRECTORY,
+};
+
 // User info needed to set wallpapers. Clients must specify the user because
 // it's not always the same with the active user, e.g., when showing wallpapers
 // for different user pods at login screen, or setting wallpapers selectively
@@ -27,7 +54,7 @@
   // The user's account id.
   signin.mojom.AccountId account_id;
 
-  // The user type. Matches user_manager::UserType.
+  // The user type.
   UserType type;
 
   // True if the user's non-cryptohome data (wallpaper, avatar etc.) is
diff --git a/ash/public/interfaces/wallpaper.typemap b/ash/public/interfaces/wallpaper.typemap
index 16b5792f..01525b3 100644
--- a/ash/public/interfaces/wallpaper.typemap
+++ b/ash/public/interfaces/wallpaper.typemap
@@ -3,6 +3,18 @@
 # found in the LICENSE file.
 
 mojom = "//ash/public/interfaces/wallpaper.mojom"
-public_headers = [ "//ash/public/cpp/wallpaper_types.h" ]
-traits_headers = [ "//ash/public/cpp/wallpaper_struct_traits.h" ]
-type_mappings = [ "ash.mojom.WallpaperLayout=ash::WallpaperLayout" ]
+public_headers = [
+  "//ash/public/cpp/wallpaper_types.h",
+  "//components/user_manager/user_type.h",
+]
+traits_headers = [
+  "//ash/public/cpp/wallpaper_struct_traits.h",
+  "//ash/public/interfaces/user_info_traits.h",
+]
+public_deps = [
+  "//components/user_manager",
+]
+type_mappings = [
+  "ash.mojom.WallpaperLayout=ash::WallpaperLayout",
+  "ash.mojom.UserType=user_manager::UserType",
+]
diff --git a/ash/session/session_controller_impl.cc b/ash/session/session_controller_impl.cc
index 39a81b0..56b6be01 100644
--- a/ash/session/session_controller_impl.cc
+++ b/ash/session/session_controller_impl.cc
@@ -12,7 +12,7 @@
 #include "ash/metrics/user_metrics_recorder.h"
 #include "ash/public/cpp/session/session_activation_observer.h"
 #include "ash/public/cpp/session/session_controller_client.h"
-#include "ash/public/interfaces/user_info.mojom.h"
+#include "ash/public/cpp/session/user_info.h"
 #include "ash/session/multiprofiles_intro_dialog.h"
 #include "ash/session/session_aborted_dialog.h"
 #include "ash/session/session_observer.h"
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc
index 7b14ad19..9239cf1 100644
--- a/ash/shelf/login_shelf_view.cc
+++ b/ash/shelf/login_shelf_view.cc
@@ -589,8 +589,7 @@
   SetLoginDialogState(state);
 }
 
-void LoginShelfView::OnUsersChanged(
-    const std::vector<mojom::LoginUserInfoPtr>& users) {
+void LoginShelfView::OnUsersChanged(const std::vector<LoginUserInfo>& users) {
   login_screen_has_users_ = !users.empty();
   UpdateUi();
 }
diff --git a/ash/shelf/login_shelf_view.h b/ash/shelf/login_shelf_view.h
index 6cffcda..bb992d5 100644
--- a/ash/shelf/login_shelf_view.h
+++ b/ash/shelf/login_shelf_view.h
@@ -41,9 +41,9 @@
 
 // LoginShelfView contains the shelf buttons visible outside of an active user
 // session. ShelfView and LoginShelfView should never be shown together.
-// This view is attached as a LoginDataDispatcher::Observer when the LockScreen
-// is instantiated in kLogin mode. It cannot attach itself because it does not
-// know when the Login is instantiated.
+// This view is attached as a LoginDataDispatcher::Observer when the
+// LockScreen is instantiated in kLogin mode. It cannot attach itself because it
+// does not know when the Login is instantiated.
 class ASH_EXPORT LoginShelfView : public views::View,
                                   public views::ButtonListener,
                                   public TrayActionObserver,
@@ -147,8 +147,7 @@
   void OnOobeDialogStateChanged(mojom::OobeDialogState state) override;
 
   // LoginDataDispatcher::Observer:
-  void OnUsersChanged(
-      const std::vector<mojom::LoginUserInfoPtr>& users) override;
+  void OnUsersChanged(const std::vector<LoginUserInfo>& users) override;
 
   // LocaleChangeObserver:
   void OnLocaleChanged() override;
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc
index 9211aef..b756921a 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -8,6 +8,9 @@
 #include <vector>
 
 #include "ash/public/cpp/ash_switches.h"
+#include "ash/public/cpp/login_screen.h"
+#include "ash/public/cpp/login_screen_model.h"
+#include "ash/public/cpp/login_types.h"
 #include "ash/public/interfaces/constants.mojom.h"
 #include "base/bind.h"
 #include "base/command_line.h"
@@ -762,9 +765,8 @@
     if (quick_unlock_storage->fingerprint_storage()->ExceededUnlockAttempts()) {
       VLOG(1) << "Fingerprint unlock is disabled because it reached maximum"
               << " unlock attempt.";
-      delegate_->SetFingerprintState(
-          user.GetAccountId(),
-          ash::mojom::FingerprintState::DISABLED_FROM_ATTEMPTS);
+      ash::LoginScreen::Get()->GetModel()->SetFingerprintState(
+          user.GetAccountId(), ash::FingerprintState::DISABLED_FROM_ATTEMPTS);
       delegate_->ShowErrorMessage(IDS_LOGIN_ERROR_FINGERPRINT_MAX_ATTEMPT,
                                   HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
     }
@@ -810,8 +812,8 @@
       if (quick_unlock_storage->fingerprint_storage()
               ->IsFingerprintAvailable()) {
         VLOG(1) << "Require strong auth to make fingerprint unlock available.";
-        delegate_->SetFingerprintState(
-            account_id, ash::mojom::FingerprintState::DISABLED_FROM_TIMEOUT);
+        ash::LoginScreen::Get()->GetModel()->SetFingerprintState(
+            account_id, ash::FingerprintState::DISABLED_FROM_TIMEOUT);
       }
     }
   }
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.h b/chrome/browser/chromeos/login/lock/screen_locker.h
index 38a5874..4ea1628 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.h
+++ b/chrome/browser/chromeos/login/lock/screen_locker.h
@@ -10,7 +10,6 @@
 #include <string>
 
 #include "ash/public/interfaces/login_screen.mojom.h"
-#include "ash/public/interfaces/login_user_info.mojom.h"
 #include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
@@ -58,10 +57,6 @@
     // Called by ScreenLocker to notify that ash lock animation finishes.
     virtual void OnAshLockAnimationFinished() = 0;
 
-    // Called when fingerprint state has changed.
-    virtual void SetFingerprintState(const AccountId& account_id,
-                                     ash::mojom::FingerprintState state) = 0;
-
     // Called after a fingerprint authentication attempt.
     virtual void NotifyFingerprintAuthResult(const AccountId& account_id,
                                              bool success) = 0;
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_unittest.cc b/chrome/browser/chromeos/login/lock/screen_locker_unittest.cc
index ca7211c..8dd0533 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker_unittest.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
 
+#include "ash/public/cpp/login_screen_model.h"
+#include "ash/public/cpp/login_types.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
diff --git a/chrome/browser/chromeos/login/lock/views_screen_locker.cc b/chrome/browser/chromeos/login/lock/views_screen_locker.cc
index 0126b51..c5199b6 100644
--- a/chrome/browser/chromeos/login/lock/views_screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/views_screen_locker.cc
@@ -9,6 +9,8 @@
 #include <utility>
 
 #include "ash/public/cpp/ash_features.h"
+#include "ash/public/cpp/login_screen.h"
+#include "ash/public/cpp/login_screen_model.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/i18n/time_formatting.h"
@@ -102,10 +104,6 @@
 void ViewsScreenLocker::Init() {
   lock_time_ = base::TimeTicks::Now();
   user_selection_screen_->Init(screen_locker_->users());
-  LoginScreenClient::Get()->login_screen()->SetUserList(
-      user_selection_screen_->UpdateAndReturnUserListForMojo());
-  LoginScreenClient::Get()->login_screen()->SetAllowLoginAsGuest(
-      false /*show_guest*/);
   if (!ime_state_.get())
     ime_state_ = input_method::InputMethodManager::Get()->GetActiveIMEState();
 
@@ -126,6 +124,12 @@
 
 void ViewsScreenLocker::OnLockScreenReady() {
   lock_screen_ready_ = true;
+
+  ash::LoginScreen::Get()->GetModel()->SetUserList(
+      user_selection_screen_->UpdateAndReturnUserListForAsh());
+  LoginScreenClient::Get()->login_screen()->SetAllowLoginAsGuest(
+      false /*show_guest*/);
+
   user_selection_screen_->InitEasyUnlock();
   UMA_HISTOGRAM_TIMES("LockScreen.LockReady",
                       base::TimeTicks::Now() - lock_time_);
@@ -151,13 +155,6 @@
   SessionControllerClientImpl::Get()->NotifyChromeLockAnimationsComplete();
 }
 
-void ViewsScreenLocker::SetFingerprintState(
-    const AccountId& account_id,
-    ash::mojom::FingerprintState state) {
-  LoginScreenClient::Get()->login_screen()->SetFingerprintState(account_id,
-                                                                state);
-}
-
 void ViewsScreenLocker::NotifyFingerprintAuthResult(const AccountId& account_id,
                                                     bool success) {
   LoginScreenClient::Get()->login_screen()->NotifyFingerprintAuthResult(
diff --git a/chrome/browser/chromeos/login/lock/views_screen_locker.h b/chrome/browser/chromeos/login/lock/views_screen_locker.h
index 4e00bdf..655f8ad 100644
--- a/chrome/browser/chromeos/login/lock/views_screen_locker.h
+++ b/chrome/browser/chromeos/login/lock/views_screen_locker.h
@@ -43,8 +43,6 @@
                         HelpAppLauncher::HelpTopic help_topic_id) override;
   void ClearErrors() override;
   void OnAshLockAnimationFinished() override;
-  void SetFingerprintState(const AccountId& account_id,
-                           ash::mojom::FingerprintState state) override;
   void NotifyFingerprintAuthResult(const AccountId& account_id,
                                    bool success) override;
 
diff --git a/chrome/browser/chromeos/login/lock_screen_utils.cc b/chrome/browser/chromeos/login/lock_screen_utils.cc
index ad19865..eb1a1db 100644
--- a/chrome/browser/chromeos/login/lock_screen_utils.cc
+++ b/chrome/browser/chromeos/login/lock_screen_utils.cc
@@ -159,27 +159,21 @@
       rate);
 }
 
-std::vector<ash::mojom::LocaleItemPtr> FromListValueToLocaleItem(
+std::vector<ash::LocaleItem> FromListValueToLocaleItem(
     std::unique_ptr<base::ListValue> locales) {
-  std::vector<ash::mojom::LocaleItemPtr> result;
+  std::vector<ash::LocaleItem> result;
   for (const auto& locale : *locales) {
     const base::DictionaryValue* dictionary;
     if (!locale.GetAsDictionary(&dictionary))
       continue;
 
-    ash::mojom::LocaleItemPtr locale_item = ash::mojom::LocaleItem::New();
-    std::string language_code;
-    dictionary->GetString("value", &language_code);
-    locale_item->language_code = language_code;
-
-    std::string title;
-    dictionary->GetString("title", &title);
-    locale_item->title = title;
-
+    ash::LocaleItem locale_item;
+    dictionary->GetString("value", &locale_item.language_code);
+    dictionary->GetString("title", &locale_item.title);
     std::string group_name;
     dictionary->GetString("optionGroupName", &group_name);
     if (!group_name.empty())
-      locale_item->group_name = group_name;
+      locale_item.group_name = group_name;
     result.push_back(std::move(locale_item));
   }
   return result;
diff --git a/chrome/browser/chromeos/login/lock_screen_utils.h b/chrome/browser/chromeos/login/lock_screen_utils.h
index 66f80906..88e4e01f 100644
--- a/chrome/browser/chromeos/login/lock_screen_utils.h
+++ b/chrome/browser/chromeos/login/lock_screen_utils.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_LOCK_SCREEN_UTILS_H_
 #define CHROME_BROWSER_CHROMEOS_LOGIN_LOCK_SCREEN_UTILS_H_
 
-#include "ash/public/interfaces/login_user_info.mojom.h"
+#include "ash/public/cpp/login_types.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
 
 class AccountId;
@@ -36,8 +36,8 @@
 // Update the keyboard settings for |account_id|.
 void SetKeyboardSettings(const AccountId& account_id);
 
-// Covert a ListValue of locale info to a list of mojo struct LocaleItem.
-std::vector<ash::mojom::LocaleItemPtr> FromListValueToLocaleItem(
+// Covert a ListValue of locale info to a list of ash struct LocaleItem.
+std::vector<ash::LocaleItem> FromListValueToLocaleItem(
     std::unique_ptr<base::ListValue> locales);
 
 }  // namespace lock_screen_utils
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.cc b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
index 2c12df7..6d8088a 100644
--- a/chrome/browser/chromeos/login/screens/user_selection_screen.cc
+++ b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
@@ -9,6 +9,7 @@
 #include <memory>
 #include <utility>
 
+#include "ash/public/cpp/login_types.h"
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/command_line.h"
@@ -159,21 +160,21 @@
 }
 
 // Determines the initial fingerprint state for the given user.
-ash::mojom::FingerprintState GetInitialFingerprintState(
+ash::FingerprintState GetInitialFingerprintState(
     const user_manager::User* user) {
   // User must be logged in.
   if (!user->is_logged_in())
-    return ash::mojom::FingerprintState::UNAVAILABLE;
+    return ash::FingerprintState::UNAVAILABLE;
 
   // Quick unlock storage must be available.
   quick_unlock::QuickUnlockStorage* quick_unlock_storage =
       quick_unlock::QuickUnlockFactory::GetForUser(user);
   if (!quick_unlock_storage)
-    return ash::mojom::FingerprintState::UNAVAILABLE;
+    return ash::FingerprintState::UNAVAILABLE;
 
   // Fingerprint is not registered for this account.
   if (!quick_unlock_storage->fingerprint_storage()->HasRecord())
-    return ash::mojom::FingerprintState::UNAVAILABLE;
+    return ash::FingerprintState::UNAVAILABLE;
 
   // Fingerprint unlock attempts should not be exceeded, as the lock screen has
   // not been displayed yet.
@@ -182,14 +183,14 @@
 
   // It has been too long since the last authentication.
   if (!quick_unlock_storage->HasStrongAuth())
-    return ash::mojom::FingerprintState::DISABLED_FROM_TIMEOUT;
+    return ash::FingerprintState::DISABLED_FROM_TIMEOUT;
 
   // Auth is available.
   if (quick_unlock_storage->IsFingerprintAuthenticationAvailable())
-    return ash::mojom::FingerprintState::AVAILABLE;
+    return ash::FingerprintState::AVAILABLE;
 
   // Default to unavailabe.
-  return ash::mojom::FingerprintState::UNAVAILABLE;
+  return ash::FingerprintState::UNAVAILABLE;
 }
 
 // Returns true if dircrypto migration check should be performed.
@@ -248,7 +249,7 @@
 
 void GetMultiProfilePolicy(const user_manager::User* user,
                            bool* out_is_allowed,
-                           ash::mojom::MultiProfileUserBehavior* out_policy) {
+                           ash::MultiProfileUserBehavior* out_policy) {
   const std::string& user_id = user->GetAccountId().GetUserEmail();
   MultiProfileUserController* multi_profile_user_controller =
       ChromeUserManager::Get()->GetMultiProfileUserController();
@@ -405,9 +406,9 @@
   user_dict->SetBoolean(kKeySignedIn, user->is_logged_in());
   user_dict->SetBoolean(kKeyIsOwner, is_owner);
   user_dict->SetBoolean(kKeyIsActiveDirectory, user->IsActiveDirectoryUser());
-  user_dict->SetBoolean(kKeyAllowFingerprint,
-                        GetInitialFingerprintState(user) ==
-                            ash::mojom::FingerprintState::AVAILABLE);
+  user_dict->SetBoolean(
+      kKeyAllowFingerprint,
+      GetInitialFingerprintState(user) == ash::FingerprintState::AVAILABLE);
 
   FillMultiProfileUserPrefs(user, user_dict, is_signin_to_add);
 
@@ -428,7 +429,7 @@
   }
 
   bool is_user_allowed;
-  ash::mojom::MultiProfileUserBehavior policy;
+  ash::MultiProfileUserBehavior policy;
   GetMultiProfilePolicy(user, &is_user_allowed, &policy);
   user_dict->SetBoolean(kKeyMultiProfilesAllowed, is_user_allowed);
   user_dict->SetInteger(kKeyMultiProfilesPolicy, static_cast<int>(policy));
@@ -474,33 +475,32 @@
 }
 
 // static
-ash::mojom::UserAvatarPtr UserSelectionScreen::BuildMojoUserAvatarForUser(
-    const user_manager::User* user) {
-  auto avatar = ash::mojom::UserAvatar::New();
-  if (!user->GetImage().isNull()) {
-    avatar->image = user->GetImage();
-  } else {
-    avatar->image = *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+ash::UserAvatar UserSelectionScreen::BuildAshUserAvatarForUser(
+    const user_manager::User& user) {
+  ash::UserAvatar avatar;
+  avatar.image = user.GetImage();
+  if (avatar.image.isNull()) {
+    avatar.image = *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
         IDR_LOGIN_DEFAULT_USER);
   }
 
   // TODO(jdufault): Unify image handling between this code and
   // user_image_source::GetUserImageInternal.
-  auto load_image_from_resource = [&](int resource_id) {
+  auto load_image_from_resource = [&avatar](int resource_id) {
     auto& rb = ui::ResourceBundle::GetSharedInstance();
     base::StringPiece avatar_data =
         rb.GetRawDataResourceForScale(resource_id, rb.GetMaxScaleFactor());
-    avatar->bytes.assign(avatar_data.begin(), avatar_data.end());
+    avatar.bytes.assign(avatar_data.begin(), avatar_data.end());
   };
-  if (user->has_image_bytes()) {
-    avatar->bytes.assign(
-        user->image_bytes()->front(),
-        user->image_bytes()->front() + user->image_bytes()->size());
-  } else if (user->HasDefaultImage()) {
+  if (user.has_image_bytes()) {
+    avatar.bytes.assign(
+        user.image_bytes()->front(),
+        user.image_bytes()->front() + user.image_bytes()->size());
+  } else if (user.HasDefaultImage()) {
     int resource_id = chromeos::default_user_image::kDefaultImageResourceIDs
-        [user->image_index()];
+        [user.image_index()];
     load_image_from_resource(resource_id);
-  } else if (user->image_is_stub()) {
+  } else if (user.image_is_stub()) {
     load_image_from_resource(IDR_LOGIN_DEFAULT_USER);
   }
 
@@ -796,9 +796,9 @@
   return users_list;
 }
 
-std::vector<ash::mojom::LoginUserInfoPtr>
-UserSelectionScreen::UpdateAndReturnUserListForMojo() {
-  std::vector<ash::mojom::LoginUserInfoPtr> user_info_list;
+std::vector<ash::LoginUserInfo>
+UserSelectionScreen::UpdateAndReturnUserListForAsh() {
+  std::vector<ash::LoginUserInfo> user_info_list;
 
   const AccountId owner = GetOwnerAccountId();
   const bool is_signin_to_add = IsSigninToAdd();
@@ -819,34 +819,33 @@
                    : proximity_auth::mojom::AuthType::OFFLINE_PASSWORD);
     user_auth_type_map_[account_id] = initial_auth_type;
 
-    ash::mojom::LoginUserInfoPtr user_info = ash::mojom::LoginUserInfo::New();
-    user_info->basic_user_info = ash::mojom::UserInfo::New();
-    user_info->basic_user_info->type = user->GetType();
-    user_info->basic_user_info->account_id = user->GetAccountId();
-    user_info->basic_user_info->display_name =
+    ash::LoginUserInfo user_info;
+    user_info.basic_user_info.type = user->GetType();
+    user_info.basic_user_info.account_id = user->GetAccountId();
+    user_info.basic_user_info.display_name =
         base::UTF16ToUTF8(user->GetDisplayName());
-    user_info->basic_user_info->display_email = user->display_email();
-    user_info->basic_user_info->avatar = BuildMojoUserAvatarForUser(user);
-    user_info->auth_type = initial_auth_type;
-    user_info->is_signed_in = user->is_logged_in();
-    user_info->is_device_owner = is_owner;
-    user_info->can_remove = CanRemoveUser(user);
-    user_info->fingerprint_state = GetInitialFingerprintState(user);
+    user_info.basic_user_info.display_email = user->display_email();
+    user_info.basic_user_info.avatar = BuildAshUserAvatarForUser(*user);
+    user_info.auth_type = initial_auth_type;
+    user_info.is_signed_in = user->is_logged_in();
+    user_info.is_device_owner = is_owner;
+    user_info.can_remove = CanRemoveUser(user);
+    user_info.fingerprint_state = GetInitialFingerprintState(user);
 
     // Fill multi-profile data.
     if (!is_signin_to_add) {
-      user_info->is_multiprofile_allowed = true;
+      user_info.is_multiprofile_allowed = true;
     } else {
-      GetMultiProfilePolicy(user, &user_info->is_multiprofile_allowed,
-                            &user_info->multiprofile_policy);
+      GetMultiProfilePolicy(user, &user_info.is_multiprofile_allowed,
+                            &user_info.multiprofile_policy);
     }
 
     // Fill public session data.
     if (user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
-      user_info->public_account_info = ash::mojom::PublicAccountInfo::New();
       std::string domain;
+      user_info.public_account_info.emplace();
       if (GetEnterpriseDomain(&domain))
-        user_info->public_account_info->enterprise_domain = domain;
+        user_info.public_account_info->enterprise_domain = domain;
 
       const std::vector<std::string>* public_session_recommended_locales =
           public_session_recommended_locales_.find(account_id) ==
@@ -859,22 +858,22 @@
           GetPublicSessionLocales(public_session_recommended_locales,
                                   &selected_locale, &has_multiple_locales);
       DCHECK(available_locales);
-      user_info->public_account_info->available_locales =
+      user_info.public_account_info->available_locales =
           lock_screen_utils::FromListValueToLocaleItem(
               std::move(available_locales));
-      user_info->public_account_info->default_locale = selected_locale;
-      user_info->public_account_info->show_advanced_view = has_multiple_locales;
+      user_info.public_account_info->default_locale = selected_locale;
+      user_info.public_account_info->show_advanced_view = has_multiple_locales;
       // Do not show expanded view when in demo mode.
-      user_info->public_account_info->show_expanded_view =
+      user_info.public_account_info->show_expanded_view =
           !DemoSession::IsDeviceInDemoMode();
     }
 
-    user_info->can_remove = CanRemoveUser(user);
+    user_info.can_remove = CanRemoveUser(user);
 
     // Send a request to get keyboard layouts for default locale.
     if (is_public_account && LoginScreenClient::HasInstance()) {
       LoginScreenClient::Get()->RequestPublicSessionKeyboardLayouts(
-          account_id, user_info->public_account_info->default_locale);
+          account_id, user_info.public_account_info->default_locale);
     }
 
     user_info_list.push_back(std::move(user_info));
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.h b/chrome/browser/chromeos/login/screens/user_selection_screen.h
index 83cd070..be173f3 100644
--- a/chrome/browser/chromeos/login/screens/user_selection_screen.h
+++ b/chrome/browser/chromeos/login/screens/user_selection_screen.h
@@ -9,6 +9,8 @@
 #include <string>
 #include <vector>
 
+#include "ash/public/cpp/login_types.h"
+#include "ash/public/cpp/session/user_info.h"
 #include "ash/public/interfaces/login_screen.mojom.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
@@ -112,13 +114,12 @@
   // Determines if user auth status requires online sign in.
   static bool ShouldForceOnlineSignIn(const user_manager::User* user);
 
-  // Builds a |UserAvatarPtr| instance which contains the current image for
-  // |user|.
-  static ash::mojom::UserAvatarPtr BuildMojoUserAvatarForUser(
-      const user_manager::User* user);
+  // Builds a |UserAvatar| instance which contains the current image for |user|.
+  static ash::UserAvatar BuildAshUserAvatarForUser(
+      const user_manager::User& user);
 
   std::unique_ptr<base::ListValue> UpdateAndReturnUserListForWebUI();
-  std::vector<ash::mojom::LoginUserInfoPtr> UpdateAndReturnUserListForMojo();
+  std::vector<ash::LoginUserInfo> UpdateAndReturnUserListForAsh();
   void SetUsersLoaded(bool loaded);
 
  protected:
diff --git a/chrome/browser/chromeos/login/ui/login_display_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_mojo.cc
index c0c60e2..67d67e89 100644
--- a/chrome/browser/chromeos/login/ui/login_display_mojo.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_mojo.cc
@@ -4,7 +4,9 @@
 
 #include "chrome/browser/chromeos/login/ui/login_display_mojo.h"
 
-#include "ash/public/interfaces/login_user_info.mojom.h"
+#include "ash/public/cpp/login_screen.h"
+#include "ash/public/cpp/login_screen_model.h"
+#include "ash/public/cpp/login_types.h"
 #include "base/bind.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -58,7 +60,6 @@
   // login screen multiple times. Views-login only supports initialization once.
   if (!initialized_) {
     client->SetDelegate(host_);
-
     client->login_screen()->ShowLoginScreen(
         base::BindOnce(&LoginDisplayMojo::OnLoginScreenShown,
                        weak_factory_.GetWeakPtr(), filtered_users.empty()));
@@ -66,8 +67,12 @@
 
   UserSelectionScreen* user_selection_screen = host_->user_selection_screen();
   user_selection_screen->Init(filtered_users);
-  client->login_screen()->SetUserList(
-      user_selection_screen->UpdateAndReturnUserListForMojo());
+  // The login screen will not be ready for the user list until
+  // ShowLoginScreen() is finished.
+  if (ash::LoginScreen::Get()->GetModel()) {
+    ash::LoginScreen::Get()->GetModel()->SetUserList(
+        user_selection_screen->UpdateAndReturnUserListForAsh());
+  }
   client->login_screen()->SetAllowLoginAsGuest(show_guest);
   user_selection_screen->SetUsersLoaded(true /*loaded*/);
 
@@ -258,14 +263,17 @@
 }
 
 void LoginDisplayMojo::OnUserImageChanged(const user_manager::User& user) {
-  LoginScreenClient::Get()->login_screen()->SetAvatarForUser(
+  ash::LoginScreen::Get()->GetModel()->SetAvatarForUser(
       user.GetAccountId(),
-      UserSelectionScreen::BuildMojoUserAvatarForUser(&user));
+      UserSelectionScreen::BuildAshUserAvatarForUser(user));
 }
 
 void LoginDisplayMojo::OnLoginScreenShown(bool users_empty, bool did_show) {
   CHECK(did_show);
 
+  ash::LoginScreen::Get()->GetModel()->SetUserList(
+      host_->user_selection_screen()->UpdateAndReturnUserListForAsh());
+
   // login-prompt-visible is recorded and tracked to verify boot performance
   // does not regress. Autotests may also depend on it (ie,
   // login_SameSessionTwice).
diff --git a/chrome/browser/chromeos/login/ui/login_display_mojo.h b/chrome/browser/chromeos/login/ui/login_display_mojo.h
index b21fa05..52b7b25 100644
--- a/chrome/browser/chromeos/login/ui/login_display_mojo.h
+++ b/chrome/browser/chromeos/login/ui/login_display_mojo.h
@@ -19,6 +19,7 @@
 
 // Interface used by UI-agnostic code to send messages to views-based login
 // screen.
+// TODO(estade): rename to LoginDisplayAsh.
 class LoginDisplayMojo : public LoginDisplay,
                          public SigninScreenHandlerDelegate,
                          public user_manager::UserManager::Observer {
diff --git a/chrome/browser/chromeos/login/user_board_view_mojo.cc b/chrome/browser/chromeos/login/user_board_view_mojo.cc
index 4bd827b..e206b19 100644
--- a/chrome/browser/chromeos/login/user_board_view_mojo.cc
+++ b/chrome/browser/chromeos/login/user_board_view_mojo.cc
@@ -6,6 +6,9 @@
 
 #include <utility>
 
+#include "ash/public/cpp/login_screen.h"
+#include "ash/public/cpp/login_screen_model.h"
+#include "ash/public/cpp/login_types.h"
 #include "chrome/browser/chromeos/login/lock_screen_utils.h"
 #include "chrome/browser/ui/ash/login_screen_client.h"
 
@@ -13,48 +16,47 @@
 
 namespace {
 
-ash::mojom::EasyUnlockIconId GetEasyUnlockIconIdFromUserPodCustomIconId(
+ash::EasyUnlockIconId GetEasyUnlockIconIdFromUserPodCustomIconId(
     proximity_auth::ScreenlockBridge::UserPodCustomIcon icon) {
   switch (icon) {
     case proximity_auth::ScreenlockBridge::USER_POD_CUSTOM_ICON_NONE:
-      return ash::mojom::EasyUnlockIconId::NONE;
+      return ash::EasyUnlockIconId::NONE;
     case proximity_auth::ScreenlockBridge::USER_POD_CUSTOM_ICON_HARDLOCKED:
-      return ash::mojom::EasyUnlockIconId::HARDLOCKED;
+      return ash::EasyUnlockIconId::HARDLOCKED;
     case proximity_auth::ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED:
-      return ash::mojom::EasyUnlockIconId::LOCKED;
+      return ash::EasyUnlockIconId::LOCKED;
     case proximity_auth::ScreenlockBridge::
         USER_POD_CUSTOM_ICON_LOCKED_TO_BE_ACTIVATED:
-      return ash::mojom::EasyUnlockIconId::LOCKED_TO_BE_ACTIVATED;
+      return ash::EasyUnlockIconId::LOCKED_TO_BE_ACTIVATED;
     case proximity_auth::ScreenlockBridge::
         USER_POD_CUSTOM_ICON_LOCKED_WITH_PROXIMITY_HINT:
-      return ash::mojom::EasyUnlockIconId::LOCKED_WITH_PROXIMITY_HINT;
+      return ash::EasyUnlockIconId::LOCKED_WITH_PROXIMITY_HINT;
     case proximity_auth::ScreenlockBridge::USER_POD_CUSTOM_ICON_UNLOCKED:
-      return ash::mojom::EasyUnlockIconId::UNLOCKED;
+      return ash::EasyUnlockIconId::UNLOCKED;
     case proximity_auth::ScreenlockBridge::USER_POD_CUSTOM_ICON_SPINNER:
-      return ash::mojom::EasyUnlockIconId::SPINNER;
+      return ash::EasyUnlockIconId::SPINNER;
   }
 }
 
 // Converts parameters to a mojo struct that can be sent to the
 // screenlock view-based UI.
-ash::mojom::EasyUnlockIconOptionsPtr ToEasyUnlockIconOptionsPtr(
+ash::EasyUnlockIconOptions ToEasyUnlockIconOptions(
     const proximity_auth::ScreenlockBridge::UserPodCustomIconOptions&
         icon_options) {
-  ash::mojom::EasyUnlockIconOptionsPtr options =
-      ash::mojom::EasyUnlockIconOptions::New();
-  options->icon =
+  ash::EasyUnlockIconOptions options;
+  options.icon =
       GetEasyUnlockIconIdFromUserPodCustomIconId(icon_options.icon());
 
   if (!icon_options.tooltip().empty()) {
-    options->tooltip = icon_options.tooltip();
-    options->autoshow_tooltip = icon_options.autoshow_tooltip();
+    options.tooltip = icon_options.tooltip();
+    options.autoshow_tooltip = icon_options.autoshow_tooltip();
   }
 
   if (!icon_options.aria_label().empty())
-    options->aria_label = icon_options.aria_label();
+    options.aria_label = icon_options.aria_label();
 
   if (icon_options.hardlock_on_click())
-    options->hardlock_on_click = true;
+    options.hardlock_on_click = true;
 
   return options;
 }
@@ -78,7 +80,7 @@
     const std::string& default_locale,
     bool multiple_recommended_locales) {
   DCHECK(locales);
-  LoginScreenClient::Get()->login_screen()->SetPublicSessionLocales(
+  ash::LoginScreen::Get()->GetModel()->SetPublicSessionLocales(
       account_id,
       lock_screen_utils::FromListValueToLocaleItem(std::move(locales)),
       default_locale, multiple_recommended_locales);
@@ -113,16 +115,12 @@
     const AccountId& account_id,
     const proximity_auth::ScreenlockBridge::UserPodCustomIconOptions&
         icon_options) {
-  ash::mojom::EasyUnlockIconOptionsPtr icon =
-      ToEasyUnlockIconOptionsPtr(icon_options);
-  if (!icon)
-    return;
-  LoginScreenClient::Get()->login_screen()->ShowUserPodCustomIcon(
-      account_id, std::move(icon));
+  ash::LoginScreen::Get()->GetModel()->ShowEasyUnlockIcon(
+      account_id, ToEasyUnlockIconOptions(icon_options));
 }
 
 void UserBoardViewMojo::HideUserPodCustomIcon(const AccountId& account_id) {
-  LoginScreenClient::Get()->login_screen()->HideUserPodCustomIcon(account_id);
+  ash::LoginScreen::Get()->GetModel()->ShowEasyUnlockIcon(account_id, {});
 }
 
 void UserBoardViewMojo::SetAuthType(const AccountId& account_id,
diff --git a/chrome/browser/chromeos/login/users/multi_profile_user_controller.cc b/chrome/browser/chromeos/login/users/multi_profile_user_controller.cc
index 0694306..5347d0cf 100644
--- a/chrome/browser/chromeos/login/users/multi_profile_user_controller.cc
+++ b/chrome/browser/chromeos/login/users/multi_profile_user_controller.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "ash/public/cpp/login_types.h"
 #include "base/bind.h"
 #include "chrome/browser/chromeos/login/users/multi_profile_user_controller_delegate.h"
 #include "chrome/browser/chromeos/policy/policy_cert_service.h"
@@ -122,17 +123,17 @@
 }
 
 // static
-ash::mojom::MultiProfileUserBehavior
+ash::MultiProfileUserBehavior
 MultiProfileUserController::UserBehaviorStringToEnum(
     const std::string& behavior) {
   if (behavior == kBehaviorPrimaryOnly)
-    return ash::mojom::MultiProfileUserBehavior::PRIMARY_ONLY;
+    return ash::MultiProfileUserBehavior::PRIMARY_ONLY;
   if (behavior == kBehaviorNotAllowed)
-    return ash::mojom::MultiProfileUserBehavior::NOT_ALLOWED;
+    return ash::MultiProfileUserBehavior::NOT_ALLOWED;
   if (behavior == kBehaviorOwnerPrimaryOnly)
-    return ash::mojom::MultiProfileUserBehavior::OWNER_PRIMARY_ONLY;
+    return ash::MultiProfileUserBehavior::OWNER_PRIMARY_ONLY;
 
-  return ash::mojom::MultiProfileUserBehavior::UNRESTRICTED;
+  return ash::MultiProfileUserBehavior::UNRESTRICTED;
 }
 
 bool MultiProfileUserController::IsUserAllowedInSession(
diff --git a/chrome/browser/chromeos/login/users/multi_profile_user_controller.h b/chrome/browser/chromeos/login/users/multi_profile_user_controller.h
index b071b621..3a874ce 100644
--- a/chrome/browser/chromeos/login/users/multi_profile_user_controller.h
+++ b/chrome/browser/chromeos/login/users/multi_profile_user_controller.h
@@ -9,7 +9,6 @@
 #include <string>
 #include <vector>
 
-#include "ash/public/interfaces/login_user_info.mojom.h"
 #include "base/macros.h"
 
 class PrefChangeRegistrar;
@@ -17,6 +16,10 @@
 class PrefService;
 class Profile;
 
+namespace ash {
+enum class MultiProfileUserBehavior;
+}
+
 namespace user_prefs {
 class PrefRegistrySyncable;
 }
@@ -72,7 +75,7 @@
   static UserAllowedInSessionReason GetPrimaryUserPolicy();
 
   // Returns the user behavior in MultiProfileUserBehavior enum.
-  static ash::mojom::MultiProfileUserBehavior UserBehaviorStringToEnum(
+  static ash::MultiProfileUserBehavior UserBehaviorStringToEnum(
       const std::string& behavior);
 
   // Returns true if user allowed to be in the current session. If |reason| not
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 799bf654..d9cb417 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3864,6 +3864,8 @@
       "ash/fake_tablet_mode_controller.h",
       "ash/test_login_screen.cc",
       "ash/test_login_screen.h",
+      "ash/test_login_screen_model.cc",
+      "ash/test_login_screen_model.h",
       "ash/test_session_controller.cc",
       "ash/test_session_controller.h",
       "ash/test_wallpaper_controller.cc",
diff --git a/chrome/browser/ui/ash/login_screen_client.cc b/chrome/browser/ui/ash/login_screen_client.cc
index a6828a7..36b2572 100644
--- a/chrome/browser/ui/ash/login_screen_client.cc
+++ b/chrome/browser/ui/ash/login_screen_client.cc
@@ -6,6 +6,9 @@
 
 #include <utility>
 
+#include "ash/public/cpp/login_screen.h"
+#include "ash/public/cpp/login_screen_model.h"
+#include "ash/public/cpp/login_types.h"
 #include "ash/public/interfaces/constants.mojom.h"
 #include "base/bind.h"
 #include "chrome/browser/chromeos/child_accounts/parent_access_code/parent_access_service.h"
@@ -266,30 +269,29 @@
     const AccountId& account_id,
     const std::string& locale,
     std::unique_ptr<base::ListValue> keyboard_layouts) {
-  std::vector<ash::mojom::InputMethodItemPtr> result;
+  std::vector<ash::InputMethodItem> result;
 
   for (const auto& i : *keyboard_layouts) {
     const base::DictionaryValue* dictionary;
     if (!i.GetAsDictionary(&dictionary))
       continue;
 
-    ash::mojom::InputMethodItemPtr input_method_item =
-        ash::mojom::InputMethodItem::New();
+    ash::InputMethodItem input_method_item;
     std::string ime_id;
     dictionary->GetString("value", &ime_id);
-    input_method_item->ime_id = ime_id;
+    input_method_item.ime_id = ime_id;
 
     std::string title;
     dictionary->GetString("title", &title);
-    input_method_item->title = title;
+    input_method_item.title = title;
 
     bool selected;
     dictionary->GetBoolean("selected", &selected);
-    input_method_item->selected = selected;
+    input_method_item.selected = selected;
     result.push_back(std::move(input_method_item));
   }
-  login_screen_->SetPublicSessionKeyboardLayouts(account_id, locale,
-                                                 std::move(result));
+  ash::LoginScreen::Get()->GetModel()->SetPublicSessionKeyboardLayouts(
+      account_id, locale, result);
 }
 
 void LoginScreenClient::OnUserActivity() {
diff --git a/chrome/browser/ui/ash/test_login_screen.cc b/chrome/browser/ui/ash/test_login_screen.cc
index f1cba50f..e5d2289 100644
--- a/chrome/browser/ui/ash/test_login_screen.cc
+++ b/chrome/browser/ui/ash/test_login_screen.cc
@@ -52,32 +52,16 @@
 
 void TestLoginScreen::ClearErrors() {}
 
-void TestLoginScreen::ShowUserPodCustomIcon(
-    const AccountId& account_id,
-    ::ash::mojom::EasyUnlockIconOptionsPtr icon) {}
-
-void TestLoginScreen::HideUserPodCustomIcon(const AccountId& account_id) {}
-
 void TestLoginScreen::SetAuthType(const AccountId& account_id,
                                   ::proximity_auth::mojom::AuthType auth_type,
                                   const base::string16& initial_value) {}
 
-void TestLoginScreen::SetUserList(
-    std::vector<::ash::mojom::LoginUserInfoPtr> users) {}
-
 void TestLoginScreen::SetPinEnabledForUser(const AccountId& account_id,
                                            bool is_enabled) {}
 
-void TestLoginScreen::SetFingerprintState(
-    const AccountId& account_id,
-    ::ash::mojom::FingerprintState state) {}
-
 void TestLoginScreen::NotifyFingerprintAuthResult(const AccountId& account_id,
                                                   bool successful) {}
 
-void TestLoginScreen::SetAvatarForUser(const AccountId& account_id,
-                                       ::ash::mojom::UserAvatarPtr avatar) {}
-
 void TestLoginScreen::EnableAuthForUser(const AccountId& account_id) {}
 
 void TestLoginScreen::DisableAuthForUser(
@@ -99,17 +83,6 @@
     const AccountId& account_id,
     const std::string& display_name) {}
 
-void TestLoginScreen::SetPublicSessionLocales(
-    const AccountId& account_id,
-    std::vector<::ash::mojom::LocaleItemPtr> locales,
-    const std::string& default_locale,
-    bool show_advanced_view) {}
-
-void TestLoginScreen::SetPublicSessionKeyboardLayouts(
-    const AccountId& account_id,
-    const std::string& locale,
-    std::vector<::ash::mojom::InputMethodItemPtr> keyboard_layouts) {}
-
 void TestLoginScreen::SetPublicSessionShowFullManagementDisclosure(
     bool show_full_management_disclosure) {}
 
@@ -132,6 +105,10 @@
 
 void TestLoginScreen::FocusLoginShelf(bool reverse) {}
 
+ash::LoginScreenModel* TestLoginScreen::GetModel() {
+  return &test_screen_model_;
+}
+
 void TestLoginScreen::Bind(mojo::ScopedMessagePipeHandle handle) {
   binding_.Bind(ash::mojom::LoginScreenRequest(std::move(handle)));
 }
diff --git a/chrome/browser/ui/ash/test_login_screen.h b/chrome/browser/ui/ash/test_login_screen.h
index 00c0dd0..6eebba8 100644
--- a/chrome/browser/ui/ash/test_login_screen.h
+++ b/chrome/browser/ui/ash/test_login_screen.h
@@ -8,8 +8,10 @@
 #include <string>
 #include <vector>
 
+#include "ash/public/cpp/login_screen.h"
 #include "ash/public/interfaces/login_screen.mojom.h"
 #include "base/macros.h"
+#include "chrome/browser/ui/ash/test_login_screen_model.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 // Test implementation of ash's mojo LoginScreen interface.
@@ -19,7 +21,8 @@
 //
 // Note: A ServiceManagerConnection must be initialized before constructing this
 // object. Consider using content::TestServiceManagerContext on your tests.
-class TestLoginScreen : public ash::mojom::LoginScreen {
+class TestLoginScreen : public ash::mojom::LoginScreen,
+                        public ash::LoginScreen {
  public:
   TestLoginScreen();
   ~TestLoginScreen() override;
@@ -35,23 +38,14 @@
   void ShowWarningBanner(const base::string16& message) override;
   void HideWarningBanner() override;
   void ClearErrors() override;
-  void ShowUserPodCustomIcon(
-      const AccountId& account_id,
-      ::ash::mojom::EasyUnlockIconOptionsPtr icon) override;
-  void HideUserPodCustomIcon(const AccountId& account_id) override;
   void SetAuthType(const AccountId& account_id,
                    ::proximity_auth::mojom::AuthType auth_type,
                    const base::string16& initial_value) override;
-  void SetUserList(std::vector<::ash::mojom::LoginUserInfoPtr> users) override;
 
   void SetPinEnabledForUser(const AccountId& account_id,
                             bool is_enabled) override;
-  void SetFingerprintState(const AccountId& account_id,
-                           ::ash::mojom::FingerprintState state) override;
   void NotifyFingerprintAuthResult(const AccountId& account_id,
                                    bool successful) override;
-  void SetAvatarForUser(const AccountId& account_id,
-                        ::ash::mojom::UserAvatarPtr avatar) override;
   void EnableAuthForUser(const AccountId& account_id) override;
   void DisableAuthForUser(
       const AccountId& account_id,
@@ -64,14 +58,6 @@
   void IsReadyForPassword(IsReadyForPasswordCallback callback) override;
   void SetPublicSessionDisplayName(const AccountId& account_id,
                                    const std::string& display_name) override;
-  void SetPublicSessionLocales(const AccountId& account_id,
-                               std::vector<::ash::mojom::LocaleItemPtr> locales,
-                               const std::string& default_locale,
-                               bool show_advanced_view) override;
-  void SetPublicSessionKeyboardLayouts(
-      const AccountId& account_id,
-      const std::string& locale,
-      std::vector<::ash::mojom::InputMethodItemPtr> keyboard_layouts) override;
   void SetPublicSessionShowFullManagementDisclosure(
       bool show_full_management_disclosure) override;
   void ShowKioskAppError(const std::string& message) override;
@@ -84,10 +70,15 @@
   void SetShowParentAccessDialog(bool show) override;
   void FocusLoginShelf(bool reverse) override;
 
+  // ash::LoginScreen:
+  ash::LoginScreenModel* GetModel() override;
+
  private:
   void Bind(mojo::ScopedMessagePipeHandle handle);
   mojo::Binding<ash::mojom::LoginScreen> binding_{this};
 
+  TestLoginScreenModel test_screen_model_;
+
   DISALLOW_COPY_AND_ASSIGN(TestLoginScreen);
 };
 
diff --git a/chrome/browser/ui/ash/test_login_screen_model.cc b/chrome/browser/ui/ash/test_login_screen_model.cc
new file mode 100644
index 0000000..3a5f6e7
--- /dev/null
+++ b/chrome/browser/ui/ash/test_login_screen_model.cc
@@ -0,0 +1,27 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/ash/test_login_screen_model.h"
+
+TestLoginScreenModel::TestLoginScreenModel() = default;
+TestLoginScreenModel::~TestLoginScreenModel() = default;
+
+void TestLoginScreenModel::SetUserList(
+    const std::vector<ash::LoginUserInfo>& users) {}
+void TestLoginScreenModel::SetAvatarForUser(const AccountId& account_id,
+                                            const ash::UserAvatar& avatar) {}
+void TestLoginScreenModel::ShowEasyUnlockIcon(
+    const AccountId& account_id,
+    const ash::EasyUnlockIconOptions& icon) {}
+void TestLoginScreenModel::SetFingerprintState(const AccountId& account_id,
+                                               ash::FingerprintState state) {}
+void TestLoginScreenModel::SetPublicSessionLocales(
+    const AccountId& account_id,
+    const std::vector<ash::LocaleItem>& locales,
+    const std::string& default_locale,
+    bool show_advanced_view) {}
+void TestLoginScreenModel::SetPublicSessionKeyboardLayouts(
+    const AccountId& account_id,
+    const std::string& locale,
+    const std::vector<ash::InputMethodItem>& keyboard_layouts) {}
diff --git a/chrome/browser/ui/ash/test_login_screen_model.h b/chrome/browser/ui/ash/test_login_screen_model.h
new file mode 100644
index 0000000..1a6a5d2
--- /dev/null
+++ b/chrome/browser/ui/ash/test_login_screen_model.h
@@ -0,0 +1,37 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_ASH_TEST_LOGIN_SCREEN_MODEL_H_
+#define CHROME_BROWSER_UI_ASH_TEST_LOGIN_SCREEN_MODEL_H_
+
+#include "ash/public/cpp/login_screen_model.h"
+#include "base/macros.h"
+
+class TestLoginScreenModel : public ash::LoginScreenModel {
+ public:
+  TestLoginScreenModel();
+  ~TestLoginScreenModel() override;
+
+  // ash::LoginScreenModel:
+  void SetUserList(const std::vector<ash::LoginUserInfo>& users) override;
+  void SetAvatarForUser(const AccountId& account_id,
+                        const ash::UserAvatar& avatar) override;
+  void SetFingerprintState(const AccountId& account_id,
+                           ash::FingerprintState state) override;
+  void ShowEasyUnlockIcon(const AccountId& user,
+                          const ash::EasyUnlockIconOptions& icon) override;
+  void SetPublicSessionLocales(const AccountId& account_id,
+                               const std::vector<ash::LocaleItem>& locales,
+                               const std::string& default_locale,
+                               bool show_advanced_view) override;
+  void SetPublicSessionKeyboardLayouts(
+      const AccountId& account_id,
+      const std::string& locale,
+      const std::vector<ash::InputMethodItem>& keyboard_layouts) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestLoginScreenModel);
+};
+
+#endif  // CHROME_BROWSER_UI_ASH_TEST_LOGIN_SCREEN_MODEL_H_