[basemgr] Auto-login to the first authenticated user on disc if the
session shell settings specifies it.

This also gets rid of jank on boot-up where we briefly see the base
shell.

MF-11 #comment
TESTED: paved, manual testing, ran unit/integration tests

Change-Id: I6908a354cd4ed6f7dcfb3983dcda93952b20d36d
diff --git a/bin/basemgr/basemgr_impl.cc b/bin/basemgr/basemgr_impl.cc
index 28b761e..a564274 100644
--- a/bin/basemgr/basemgr_impl.cc
+++ b/bin/basemgr/basemgr_impl.cc
@@ -237,10 +237,6 @@
         << std::endl;
   }
 
-  // Start the base shell. This is done first so that we can show some UI
-  // until other things come up.
-  StartBaseShell();
-
   // Wait for persistent data to come up.
   if (!settings_.no_minfs) {
     WaitForMinfs();
@@ -277,6 +273,25 @@
       authentication_context_provider_binding_.NewBinding().Bind(),
       settings_.enable_garnet_token_manager, this));
 
+  // If the session shell settings specifies it, auto-login as the first
+  // authenticated user.
+  if (active_session_shell_settings_index_ < session_shell_settings_.size() &&
+      session_shell_settings_[active_session_shell_settings_index_]
+          .auto_login) {
+    user_provider_impl_->PreviousUsers(
+        [this](fidl::VectorPtr<fuchsia::modular::auth::Account> accounts) {
+          if (accounts->empty()) {
+            StartBaseShell();
+          } else {
+            fuchsia::modular::UserLoginParams params;
+            params.account_id = accounts->at(0).id;
+            user_provider_impl_->Login(std::move(params));
+          }
+        });
+  } else {
+    StartBaseShell();
+  }
+
   ReportEvent(ModularEvent::BOOTED_TO_BASEMGR);
 }
 
diff --git a/bin/basemgr/user_provider_impl.h b/bin/basemgr/user_provider_impl.h
index 3c13c5a..316095d 100644
--- a/bin/basemgr/user_provider_impl.h
+++ b/bin/basemgr/user_provider_impl.h
@@ -76,13 +76,13 @@
   FuturePtr<> SwapSessionShell(
       fuchsia::modular::AppConfig session_shell_config);
 
- private:
-  // |fuchsia::modular::UserProvider|
+  // |fuchsia::modular::UserProvider|, also called by |basemgr_impl|.
   void Login(fuchsia::modular::UserLoginParams params) override;
 
-  // |fuchsia::modular::UserProvider|
+  // |fuchsia::modular::UserProvider|, also called by |basemgr_impl|.
   void PreviousUsers(PreviousUsersCallback callback) override;
 
+ private:
   // |fuchsia::modular::UserProvider|
   void AddUser(fuchsia::modular::auth::IdentityProvider identity_provider,
                AddUserCallback callback) override;
diff --git a/lib/session_shell_settings/session_shell_settings.cc b/lib/session_shell_settings/session_shell_settings.cc
index bba6b21..44ad687 100644
--- a/lib/session_shell_settings/session_shell_settings.cc
+++ b/lib/session_shell_settings/session_shell_settings.cc
@@ -100,10 +100,6 @@
 // Given a |json| string, parses it into list of session shell settings.
 std::vector<SessionShellSettings> ParseSessionShellSettings(
     const std::string& json) {
-  // TODO(MI4-1166): topaz/lib/base_shell/lib/session_shell_chooser.dart is a
-  // similar implementation of this in Dart. One of the two implementations
-  // could probably be removed now.
-
   std::vector<SessionShellSettings> settings;
 
   rapidjson::Document document;
@@ -141,6 +137,8 @@
         .screen_height = GetObjectValue<float>(session_shell, "screen_height"),
         .display_usage = GetObjectValue<fuchsia::ui::policy::DisplayUsage>(
             session_shell, "display_usage"),
+        .auto_login =
+            GetObjectValue<std::string>(session_shell, "auto_login") == "true",
     });
   }
 
@@ -173,9 +171,6 @@
 
 bool operator==(const SessionShellSettings& lhs,
                 const SessionShellSettings& rhs) {
-  if (lhs.name != rhs.name)
-    return false;
-
   auto float_eq = [](float f, float g) {
     // OK to do direct float comparison here, since we want bitwise value
     // equality.
@@ -188,16 +183,10 @@
     return false;
   };
 
-  if (!float_eq(lhs.screen_width, rhs.screen_width))
-    return false;
-
-  if (!float_eq(lhs.screen_height, rhs.screen_height))
-    return false;
-
-  if (lhs.display_usage != rhs.display_usage)
-    return false;
-
-  return true;
+  return lhs.name == rhs.name && lhs.auto_login == rhs.auto_login &&
+         float_eq(lhs.screen_width, rhs.screen_width) &&
+         float_eq(lhs.screen_height, rhs.screen_height) &&
+         lhs.display_usage == rhs.display_usage;
 }
 
 }  // namespace modular
diff --git a/lib/session_shell_settings/session_shell_settings.h b/lib/session_shell_settings/session_shell_settings.h
index 2b7fce4..a4206b1 100644
--- a/lib/session_shell_settings/session_shell_settings.h
+++ b/lib/session_shell_settings/session_shell_settings.h
@@ -23,6 +23,10 @@
   // The name of the session shell, e.g. "ermine".
   const std::string name;
 
+  // Whether the session shell should auto-login to the first authenticated
+  // user.
+  const bool auto_login;
+
   // The screen width & height in millimeters for the session shell's display.
   // Defaults to a signaling NaN so that any attempts to use it without checking
   // for NaN will trap.